Skip to content

Commit

Permalink
snagrecover: am335x_usb_setup.sh: Improve POSIX-compliance
Browse files Browse the repository at this point in the history
This is part of an effort to make this script work better with different
user shells, such as fish shell which previously couldn't run this script.

Remove bashisms and change method for creating recovery shell. Use sh
instead of bash for the recovery shell.

Signed-off-by: Romain Gantois <romain.gantois@bootlin.com>
  • Loading branch information
rgantois committed Jan 5, 2024
1 parent 1a440e5 commit de02fac
Showing 1 changed file with 57 additions and 56 deletions.
113 changes: 57 additions & 56 deletions src/snagrecover/am335x_usb_setup.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/sh
# This file is part of Snagboot
# Copyright (C) 2023 Bootlin
#
Expand All @@ -17,24 +17,23 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
: '
This script will do the following things to setup
an environment for recovering an AM335x soc via USB:
1. Create a new network namespace called $NETNS_NAME
2. Run a subprocess that will trigger every time
a new ROM code or SPL USB ethernet gadget with a
certain PID:VID pair is registered.
It will:
2.1. Move the network interface to $NETNS_NAME
2.2. Add a static IP address to the interface,
so that the board can reach the recovery tool
2.3. Route an arbitrary client ip to the interface,
so that the recovery tool can reach the board
3.4. Route 255.255.255.255 to the interface, so
that the recovery tool can reach the board
using a broadcast, when the board does not
know its own IP yet
'

# This script will do the following things to setup
# an environment for recovering an AM335x soc via USB:
# 1. Create a new network namespace called $NETNS_NAME
# 2. Run a subprocess that will trigger every time
# a new ROM code or SPL USB ethernet gadget with a
# certain PID:VID pair is registered.
# It will:
# 2.1. Move the network interface to $NETNS_NAME
# 2.2. Add a static IP address to the interface,
# so that the board can reach the recovery tool
# 2.3. Route an arbitrary client ip to the interface,
# so that the recovery tool can reach the board
# 3.4. Route 255.255.255.255 to the interface, so
# that the recovery tool can reach the board
# using a broadcast, when the board does not
# know its own IP yet

print_usage () {
echo "am335x_usb_setup.sh: Create network namespace and udev rules necessary for AM335x USB recovery"
Expand All @@ -54,25 +53,23 @@ print_usage () {
fail_on_error () {
echo "ERROR: $1" >> /dev/stderr
echo "Operation failed" >> /dev/stderr
exit -1
exit 1
}

DEFAULT_ROMUSB="0451:6141"
DEFAULT_SPLUSB="0451:d022"
SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
NETNS_NAME="snagbootnet"
SUDOER="$SUDO_USER"
SUDOER_BASHRC=$(eval echo "~$SUDOER")"/.bashrc"
CUSTOM_RCFILE=". $SUDOER_BASHRC; export PS1='(am335_recovery) \u@\h:\w \$ '"
poller_id=""

#delete the new network namespace and udev rules
cleanup () {
if [ ! "$poller_id" == "" ]; then
if [ ! "$poller_id" = "" ]; then
kill -KILL $poller_id
fi
echo "Deleting namespace $NETNS_NAME..."
ip netns delete $NETNS_NAME
ip netns delete "$NETNS_NAME"
}

config_interface () {
Expand All @@ -84,14 +81,14 @@ config_interface () {
IF_NAME=$1

#move interface to recovery network namespace
ip link set $IF_NAME down
ip link set $IF_NAME netns $NETNS_NAME
ip netns exec $NETNS_NAME ip link set $IF_NAME up
ip link set "$IF_NAME" down
ip link set "$IF_NAME" netns "$NETNS_NAME"
ip netns exec "$NETNS_NAME" ip link set "$IF_NAME" up

#assign static ip to interface, setup ip route
ip netns exec $NETNS_NAME ip addr add dev $IF_NAME $SERVER_IP
ip netns exec $NETNS_NAME ip route add "255.255.255.255" dev $IF_NAME
ip netns exec $NETNS_NAME ip route add $CLIENT_IP dev $IF_NAME
ip netns exec "$NETNS_NAME" ip addr add dev "$IF_NAME" "$SERVER_IP"
ip netns exec "$NETNS_NAME" ip route add "255.255.255.255" dev "$IF_NAME"
ip netns exec "$NETNS_NAME" ip route add "$CLIENT_IP" dev "$IF_NAME"
}


Expand All @@ -106,19 +103,19 @@ while getopts "r:s:n:ch:" opt; do
h) print_usage
exit 0
;;
*) echo "Invalid option: -$OPTARG" >&2
:) echo "Option -$OPTARG requires an argument." >&2
print_usage
exit -1
exit 1
;;
:) echo "Option -$OPTARG requires an argument." >&2
*) echo "Invalid option: -$OPTARG" >&2
print_usage
exit -1
exit 1
;;
esac
done

#check user
if [ ! "$(whoami)" == "root" ]; then
if [ ! "$(whoami)" = "root" ]; then
fail_on_error "This script should be run as root!"
fi

Expand All @@ -128,9 +125,11 @@ if [ -z "${SUDOER}" ]; then
fi

id "$SUDOER" >/dev/null 2>&1; code=$?
if [ $code -eq 1 ] || [ "$SUDOER" == "root" ]; then
if [ $code -eq 1 ] || [ "$SUDOER" = "root" ]; then
# SUDO_USER may not work on all systems ...
SUDOER="$(ps -o user= -p $(ps -o ppid= -p $(ps -o ppid= -p $$)))"
PARENT_ID=$(ps -o ppid= -p $$)
GRANDPARENT_ID=$(ps -o ppid= -p $PARENT_ID)
SUDOER=$(ps -o user= -p $GRANDPARENT_ID)
id "$SUDOER" >/dev/null 2>&1; code=$?
if [ $code -eq 1 ] || [ "$SUDOER" = "root" ]; then
fail_on_error "Failed to find the username of sudo caller: found $SUDOER"
Expand All @@ -142,28 +141,30 @@ if [ ! -f "$SUDOER_BASHRC" ]; then
fi

#check usb args
usb_regex="^[[:xdigit:]]{4}:[[:xdigit:]]{4}$"
if [[ ! "$ROMUSB" =~ $usb_regex ]]; then
USB_REGEX="^[[:xdigit:]]{4}:[[:xdigit:]]{4}$"
if ! echo "$ROMUSB" | grep -qE "$USB_REGEX"; then
echo "Missing -r flag or invalid format for ROM USB gadget address vid:pid, using default value"
ROMUSB=$DEFAULT_ROMUSB
fi
if [[ ! "$SPLUSB" =~ $usb_regex ]]; then
if ! echo "$SPLUSB" | grep -qE "$USB_REGEX"; then
echo "Missing -s flag or invalid format for SPL USB gadget address vid:pid, using default value"
SPLUSB=$DEFAULT_SPLUSB
fi

#strip leading zeroes and replace colons with slashes
ROMUSB=$(echo -n "$ROMUSB/" | sed -e 's/^0*//' -e 's/:0*/:/' -e 's/:/\//')
SPLUSB=$(echo -n "$SPLUSB/" | sed -e 's/^0*//' -e 's/:0*/:/' -e 's/:/\//')
ROMUSB=$(printf "%s/" "$ROMUSB" | sed -e 's/^0*//' -e 's/:0*/:/' -e 's/:/\//')
SPLUSB=$(printf "%s/" "$SPLUSB" | sed -e 's/^0*//' -e 's/:0*/:/' -e 's/:/\//')

echo "Starting polling subprocess..."

poll_interface () {
ROMNETFILE=$(grep -s -l "PRODUCT=$ROMUSB" $(grep -s -l "DEVTYPE=usb_interface" /sys/class/net/*/device/uevent))
SPLNETFILE=$(grep -s -l "PRODUCT=$SPLUSB" $(grep -s -l "DEVTYPE=usb_interface" /sys/class/net/*/device/uevent))
if [ -e "$ROMNETFILE" ]; then
config_interface "$(echo $ROMNETFILE | cut -d '/' -f 5)" >/dev/null 2>&1
fi
if [ -e "$SPLNETFILE" ]; then
config_interface "$(echo $SPLNETFILE | cut -d '/' -f 5)" >/dev/null 2>&1
UEVENTS=$(grep -s -l "DEVTYPE=usb_interface" /sys/class/net/*/device/uevent)
ROMNETDEV=$(grep -s -l "PRODUCT=$ROMUSB" $UEVENTS | cut -d '/' -f 5)
SPLNETDEV=$(grep -s -l "PRODUCT=$SPLUSB" $UEVENTS | cut -d '/' -f 5)
if [ -n "$ROMNETDEV" ]; then
config_interface "$ROMNETDEV" >/dev/null 2>&1
elif [ -n "$SPLNETDEV" ]; then
config_interface "$SPLNETDEV" >/dev/null 2>&1
fi
}

Expand All @@ -179,20 +180,20 @@ if test -f "/run/netns/$NETNS_NAME"; then
fail_on_error "The network namespace $NETNS_NAME already exists! Cancelling operation..."
fi
echo "Creating network namespace $NETNS_NAME..."
ip netns add $NETNS_NAME || fail_on_error "Could not create namespace $NETNS_NAME"
ip netns add "$NETNS_NAME" || fail_on_error "Could not create namespace $NETNS_NAME"

#iptables rules
ip netns exec $NETNS_NAME iptables -t nat -A PREROUTING -p udp --dport 67 -j DNAT --to-destination :9067
ip netns exec $NETNS_NAME iptables -t nat -A PREROUTING -p udp --dport 69 -j DNAT --to-destination :9069
ip netns exec $NETNS_NAME iptables -t nat -A POSTROUTING -p udp --sport 9067 -j MASQUERADE --to-ports 67
ip netns exec $NETNS_NAME iptables -t nat -A POSTROUTING -p udp --sport 9069 -j MASQUERADE --to-ports 69
ip netns exec "$NETNS_NAME" iptables -t nat -A PREROUTING -p udp --dport 67 -j DNAT --to-destination :9067
ip netns exec "$NETNS_NAME" iptables -t nat -A PREROUTING -p udp --dport 69 -j DNAT --to-destination :9069
ip netns exec "$NETNS_NAME" iptables -t nat -A POSTROUTING -p udp --sport 9067 -j MASQUERADE --to-ports 67
ip netns exec "$NETNS_NAME" iptables -t nat -A POSTROUTING -p udp --sport 9069 -j MASQUERADE --to-ports 69

#start new shell
echo -e "Logging user $SUDOER into new shell\n"
printf "Logging user %s into new shell\n" "$SUDOER"
echo "===== $NETNS_NAME ====="
echo "You can now setup the board and run the recovery tool."
echo "Please type 'exit' to delete the namespace, stop the polling process and leave the shell when you are done."
ip netns exec $NETNS_NAME su $SUDOER --session-command "bash --rcfile <(echo \"$CUSTOM_RCFILE\")"
SUDO_PS1='(am335_recovery) \u@\h:\w \$' ip netns exec "$NETNS_NAME" sudo -i -u "$SUDOER" sh

#leave shell and cleanup
cleanup
Expand Down

0 comments on commit de02fac

Please sign in to comment.