Skip to content

Commit

Permalink
snagrecover: am335x: drop UART recovery
Browse files Browse the repository at this point in the history
An overwhelming majority of ARM SoC recovery flows rely on USB. Among the
recovery flows currently supported by snagboot, the only exception is AM335x
UART recovery, which is drastically slower than AM335x USB recovery.

In the interest of improving the coherency and efficiency of Snagboot as a USB
recovery and flashing tool, drop AM335x UART recovery.

Signed-off-by: Romain Gantois <romain.gantois@bootlin.com>
  • Loading branch information
rgantois committed May 4, 2024
1 parent b19d92f commit ddb593b
Show file tree
Hide file tree
Showing 8 changed files with 22 additions and 126 deletions.
30 changes: 6 additions & 24 deletions docs/board_setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ boot fuses, removing some external boot media and/or other board-specific
actions. Referring to your board's user guide can help you find out
what you need to do here.

The board should be connected to your host PC via USB (except for the special
case of AM335x UART recovery). The specific USB port to use is board-dependent,
it is usually the OTG port. We also strongly recommend that you open a UART
connection to the board so that you can monitor the recovery process as it
unfolds. On STM32MP1 discovery kits, the default UART is often wired to the
ST-LINK port.
The board should be connected to your host PC via USB The specific USB port to
use is board-dependent, it is usually the OTG port. We also strongly recommend
that you open a UART connection to the board so that you can monitor the
recovery process as it unfolds. On STM32MP1 discovery kits, the default UART is
often wired to the ST-LINK port.

Once your board is in recovery mode, a new USB device should appear on your host
system. This is the device that snagrecover will communicate with. Below are
Expand Down Expand Up @@ -62,24 +61,7 @@ During initialization, the ROM code will set up a boot device list and for each
device, will try to perform either a memory boot or a peripheral boot.
Peripheral booting is what interests us for recovering a board. It can be done
over USB, UART or Ethernet. Out of the 3 possible peripheral boot modes,
snagrecover supports UART mode, and USB mode. UART is much simpler to setup but
is very slow and for this reason is only supported by snagrecover, not
snagflash.

### TI AM335x UART recovery

Connect a UART to the board, open a serial port and make sure that the ROM code
boots in UART mode. If that’s the case, it should regularly ping the serial
console which will result in the character “C” being displayed.

As an example, here is the procedure for the Beaglebone black wireless board :

1. remove all connectors and make sure that the sd card slot is empty
2. set up the UART cable on the serial header (GND:J1 RX: J4 TX: J5).
3. hold the S2 button and plug the power cable in. This will change the boot
sequence so that the board doesn’t try to boot from eMMC.
4. open a serial port and press the reset button. You should get pings in your
console
snagrecover only supports USB mode.

### TI AM335x USB recovery

Expand Down
7 changes: 3 additions & 4 deletions docs/fw_binaries.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,9 @@ configuration:

[example](../src/snagrecover/templates/am335x-beaglebone-black.yaml)

**spl:** First stage bootloader. Build the spl/u-boot-spl.bin target for your
board in U-Boot mainline. If recovering via UART, SPL should be built with
CONFIG\_SPL\_YMODEM_SUPPORT enabled. If recovering via USB, the USB Ethernet
gadget should be enabled, which implies the following options:
**spl:** First stage bootloader. Build the spl/u-boot-spl.bin target for your board in U-Boot
mainline. If recovering via USB, the USB Ethernet gadget should be enabled, which implies the
following options:

```bash
CONFIG\_SPL\_NET\_SUPPORT=y
Expand Down
4 changes: 0 additions & 4 deletions docs/snagrecover.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ USB device can be found in sysfs :

`/sys/bus/usb/devices/...`.

When recovering an AM335x SOC via UART using the snagrecover, you have to pass
the --uart flag to the CLI. You can also pass the --baudrate flag in case the
default 115200 baud rate does not fit your device.

The rest of the command line arguments are optional.

Examples:
Expand Down
12 changes: 0 additions & 12 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,3 @@ binaries](fw_binaries.md) section of the docs.
On some boards, you have to enable `CONFIG_USB_ETHER` in U-Boot for USB gadgets
to work correctly.

## AM335x UART recovery fails after running SPL

In some cases SPL's standard console output can be confused with xmodem 'C'
pings. You can set the following U-Boot configuration options to try and silence
SPL:

```
CONFIG_SPL_SILENT_CONSOLE=y
CONFIG_SPL_BANNER_PRINT=n
CONFIG_SPL_DISPLAY_PRINT=n
```

1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ dependencies = [
"pyyaml >= 6.0",
"pyusb >= 1.2.1",
"pyserial >= 3.5",
"xmodem >= 0.4.6",
"tftpy >= 0.8.2",
"crccheck >= 1.3.0",
"pylibfdt >= 1.7.0.post1",
Expand Down
2 changes: 0 additions & 2 deletions src/snagrecover/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ def cli():
mandatory.add_argument("-f", "--firmware-file", help="firmware configurations, passed as a yaml file", metavar="\"templates/colibri-imx7d.yaml\"", action="append")
mandatory.add_argument("-F", "--firmware", help="firmware configurations, formatted as a python3 dict", metavar="\"{'fw1': {'path': '/path/to', 'address': 0x00}}\"", action="append", type=ast.literal_eval)
optional = parser.add_argument_group("Optional")
optional.add_argument("--uart", help="use UART for AM335x recovery", metavar="/dev/ttyx")
optional.add_argument("--baudrate", help="UART baudrate", default=115200)
optional.add_argument("--netns", help="network namespace for AM335x USB recovery, defaults to 'snagbootnet'", default="snagbootnet")
optional.add_argument("--loglevel", help="set loglevel", choices=["silent","info","debug"], default="silent")
optional.add_argument("--logfile", help="set logfile", default="board_recovery.log")
Expand Down
61 changes: 1 addition & 60 deletions src/snagrecover/firmware/am335x_fw.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,9 @@
import time
import logging
logger = logging.getLogger("snagrecover")
from xmodem import XMODEM
# setting this logger to the same format as the main
# logger since it sometimes prints out messages that seem
# like fatal errors but are apparently benign
xmodem_logger = logging.getLogger("xmodem.XMODEM")
xmodem_logger.parent = logger
import tftpy
import threading
import os.path
import collections
import errno

server_config = {
Expand Down Expand Up @@ -87,7 +80,7 @@ def handle(self):
else:
raise err

def am335x_usb(port, fw_name: str):
def am335x_run(port, fw_name: str):
tftp_start_timeout = server_config["tftp_start_timeout"]
tftp_complete_timeout = server_config["tftp_complete_timeout"]
# TFTP server thread
Expand Down Expand Up @@ -134,55 +127,3 @@ def am335x_usb(port, fw_name: str):
print("Waiting for TFTP shutdown...")
tftp_thread.join()

xmodem_total_size = 0
def xmodem_callback(total_packets: int, success_count: int, error_count: int):
"""
This is called during the xmodem transfer,
it prints a progress bar
"""
global xmodem_total_size
progress = int(100 * total_packets * 1.0 / xmodem_total_size)
print(f"\rprogress: {progress}%", end="")


def am335x_uart(port, fw_name: str):
TRANSFER_WAIT_TIMEOUT = 30
global xmodem_total_size
if fw_name == "u-boot":
print("Transfering U-Boot over a UART connection, this could take a while...")
port.write_timeout = 5
port.timeout = 5

def getc(size, timeout=1):
return port.read(size) or None

def putc(data, timeout=1):
return port.write(data)

modem = XMODEM(getc, putc)
"""
snagrecover sometimes confuses standard SPL console output
with xmodem pings (see issue #14), we wait for three pings
to reduce the likelihood of this happening
"""
print("Waiting for three pings before xmodem transfer...")
ping_buf = collections.deque(maxlen=3)
t0 = time.time()
while list(ping_buf) != [b"C", b"C", b"C"]:
ping_buf.append(port.read(1))
if time.time() - t0 > TRANSFER_WAIT_TIMEOUT:
raise Exception("Timeout waiting for UART pings")
fw_path = recovery_config["firmware"][fw_name]["path"]
xmodem_total_size = int(os.path.getsize(fw_path) / 128)
with open(fw_path, "rb") as file:
logger.info(f"Transfering {fw_path} using xmodem...")
modem.send(file, callback=xmodem_callback)
print("")
logger.info("xmodem transfer done")

def am335x_run(port, fw_name: str):
if recovery_config["args"]["uart"]:
am335x_uart(port, fw_name)
else:
am335x_usb(port, fw_name)

31 changes: 12 additions & 19 deletions src/snagrecover/recoveries/am335x.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,24 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

import serial
from snagrecover.config import recovery_config
from snagrecover.firmware.firmware import run_firmware
import subprocess
import os
import sys

def main():
if recovery_config["args"]["uart"]:
port = serial.Serial(recovery_config["args"]["uart"], baudrate=recovery_config["args"]["baudrate"])
run_firmware(port, "spl")
run_firmware(port, "u-boot")
port.close()
else:
# Check that we are running in the expected network namespace
netns_name = recovery_config["args"]["netns"]
bash_cmd = "ip netns identify " + str(os.getpid())
process = subprocess.Popen(bash_cmd.split(), stdout=subprocess.PIPE)
output, error = process.communicate()
if output.decode("ascii") != f"{netns_name}\n":
print(f"This recovery needs to be run in the {netns_name} namespace!\nDid you run sudo am335x_usb_setup.sh?", file=sys.stderr)
sys.exit(-1)
# Check that we are running in the expected network namespace
netns_name = recovery_config["args"]["netns"]
bash_cmd = "ip netns identify " + str(os.getpid())
process = subprocess.Popen(bash_cmd.split(), stdout=subprocess.PIPE)
output, error = process.communicate()
if output.decode("ascii") != f"{netns_name}\n":
print(f"This recovery needs to be run in the {netns_name} namespace!\nDid you run sudo am335x_usb_setup.sh?", file=sys.stderr)
sys.exit(-1)

# Install and run SPL
run_firmware(None, "spl")
# Install and run U-Boot
run_firmware(None, "u-boot")
# Install and run SPL
run_firmware(None, "spl")
# Install and run U-Boot
run_firmware(None, "u-boot")

0 comments on commit ddb593b

Please sign in to comment.