Giter Club home page Giter Club logo

snagboot's Introduction

Snagboot

Snagboot intends to be an open-source and generic replacement to the vendor-specific, sometimes proprietary, tools used to recover and/or reflash embedded platforms. Examples of such tools include STM32CubeProgrammer, SAM-BA ISP, UUU, and sunxi-fel. Snagboot is made of two separate parts:

  • snagrecover uses vendor-specific ROM code mechanisms to initialize external RAM and run U-Boot, without modifying any non-volatile memories.
  • snagflash communicates with U-Boot to flash system images to non-volatile memories, using either DFU, UMS or Fastboot.

animated

The currently supported SoC families are ST STM32MP1, Microchip SAMA5, NXP i.MX6/7/8/93, TI AM335x, Allwinner SUNXI and TI AM62x. Please check supported_socs.yaml or run snagrecover --list-socs for a more precise list of supported SoCs.

Installation

System requirements:

  • libusb 1.x, libusb 0.1.x or OpenUSB
  • The ensurepip Python package. On Debian, you can install the python[your python version]-venv package
  • Swig is required to build pylibfdt. You can simply install the swig package on most distros.

Snagboot is available on pip: python3 -m pip install --user snagboot.

This package provides two CLI tools:

$ snagrecover -h
$ snagflash -h

You also need to install udev rules so that snagrecover has read and write access to the USB devices exposed by the SoCs.

$ snagrecover --udev > 50-snagboot.rules
$ sudo cp 50-snagboot.rules /etc/udev/rules.d/
$ sudo udevadm control --reload-rules
$ sudo udevadm trigger

These rules work by adding the "uaccess" tag to the relevant USB devices. Systemd will then add an ACL to give access to currently logged in users. More info here.

Warning: If your distro does not use systemd, the "uaccess" method could possibly not work. In this case, make sure to customize the provided udev rules for your specific system.

Alternatively, Snagboot can be installed as a local Python wheel. An installation script is provided to automatically build and install the package.

$ cd snagboot
$ ./install.sh

There is also an AUR package available.

Usage guide

Note: Running snagboot as root is not recommended and will typically not work, since it is probably installed for the current user only

To recover and reflash a board using snagboot:

  1. Check that your SoC is supported in snagrecover by running: snagrecover --list-socs
  2. Setup your board for recovery
  3. Build or download the firmware binaries necessary for recovering and reflashing the board.
  4. Run snagrecover and check that the recovery was a success i.e. that U-Boot is running properly.
  5. Run snagflash to reflash the board

If you encounter issues, please take a look at the troubleshooting section.

You can play the snagrecover tutorial in your terminal!

sudo apt install asciinema
asciinema play -s=2 docs/tutorial_snagrecover.cast

Contributing

Contributions are welcome! Since Snagboot includes many different recovery techniques and protocols, we try to keep the code base as structured as possible. Please consult the contribution guidelines.

License

Snagboot is released under the GNU General Public License version 2

snagboot's People

Contributors

adriandc avatar aleeraser avatar dnltz avatar hundeboll avatar jameshilliard avatar kv-swetha avatar lucaceresoli avatar makohoek avatar miquelraynal avatar mstaack avatar nicgrimpe avatar rgantois avatar sebszymanski avatar tpetazzoni avatar tprrt avatar tq-niebelm avatar tropicao avatar wallaceit avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

snagboot's Issues

snagrecover: AM335x / UART

Depending on the configuration of the SPL part there is more or less console output befor the SPL goes into the YMODEM receive loop. As soon as the magic letter C is found in the output the tool starts to send u-boot.img and may falsely interpret the console output of SPL as unexpected answers to the data sent.

Two possibilities comes to my mind, but both not a perfect solution:

  • document this as requirement, that an SPL for AM335x supporting UART0 recovery should not output any status / banner that contains the magic letter 'C'.
  • implement a check that at least n modem protocoll ping characters (aka 'C') are received without any other character in between before starting download.

Selecting one of multiple identical USB devices

In our labs, we often have the case that multiple boards with the same SoC are connected to the same host.
If more than one of those is waiting in the ROM code, we have multiple USB devices with the same VID/PID.
snagboot uses usb.core.find(idVendor=usb_vid, idProduct=usb_pid), which just picks any matching device.

So this basically a REF to add support for selecting a specific device instance.

Some possible ways this could be done:

  • the pyusb find() method also supports bus=busnum, address=devnum, which points to a single device only (as new addresses/devnums are allocated for each new device detected per bus). busnum/devnum can be either passed on the commandline (i.e. by labgrid) or found using udev from other meta-data. For example, sigrog's CLI support pass busnum/devnum via arguments.
  • use the path-based identifiers (like 1-3.1:1.1). The can be resolve via sysfs (/sys/bus/usb/devices) or udev. Perhaps pyusb also supports them directly. The C fastboot and dfu-util tools also support this form.
  • use more generic udev property matches (i.e. on ID_PATH)

Keep in mind that if the device re-enumerates, it will get a new devnum. So for devices with do that, some approach 2 or 3 seem better (or a stable identifier like the path would need to be resolved from busnum/devnum).

snagrecover: undefined symbol old LTS ubuntu

Distro: Ubuntu 20.04.5
Small error snagrecover.
Should we support old Ubuntu LTS releases? Yes, I know I need to update my distro!!

$ snagrecover -h
Traceback (most recent call last):
  File "/home/kmaincent/.local/bin/snagrecover", line 5, in <module>
    from snagrecover.cli import cli
  File "/home/kmaincent/.local/lib/python3.8/site-packages/snagrecover/cli.py", line 24, in <module>
    from snagrecover.recoveries.imx import main as imx_recovery
  File "/home/kmaincent/.local/lib/python3.8/site-packages/snagrecover/recoveries/imx.py", line 50, in <module>
    import hid
  File "/home/kmaincent/.local/lib/python3.8/site-packages/hid/__init__.py", line 83, in <module>
    hidapi.hid_get_input_report.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t]
  File "/usr/lib/python3.8/ctypes/__init__.py", line 386, in __getattr__
    func = self.__getitem__(name)
  File "/usr/lib/python3.8/ctypes/__init__.py", line 391, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: /usr/lib/x86_64-linux-gnu/libhidapi-hidraw.so: undefined symbol: hid_get_input_report

Incorrect SUDOERS in am335x_usb_setup.sh

The new calculation for SUDOERS introduced in commit 112bb48 does not work in my case. It results in root rather than my actual user name.

I call the script like this: sudo ~/repo/snagboot/src/snagrecover/am335x_usb_setup.sh -s 0525:a4a5

Undefined Symbol: hid_get_input_report

As a new user of this tool, I followed the readme installing everything. However, I got this error when running snagrecover for my board.

Traceback (most recent call last):
File "/usr/local/bin/snagrecover", line 8, in
sys.exit(cli())
File "/usr/local/lib/python3.8/dist-packages/snagrecover/cli.py", line 146, in cli
from snagrecover.recoveries.am62x import main as am62x_recovery
File "/usr/local/lib/python3.8/dist-packages/snagrecover/recoveries/am62x.py", line 4, in
from snagrecover.firmware.firmware import run_firmware
File "/usr/local/lib/python3.8/dist-packages/snagrecover/firmware/firmware.py", line 23, in
from snagrecover.firmware.imx_fw import imx_run
File "/usr/local/lib/python3.8/dist-packages/snagrecover/firmware/imx_fw.py", line 52, in
from snagrecover.protocols import imx_sdp
File "/usr/local/lib/python3.8/dist-packages/snagrecover/protocols/imx_sdp.py", line 60, in
import hid
File "/usr/local/lib/python3.8/dist-packages/hid/init.py", line 83, in
hidapi.hid_get_input_report.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t]
File "/usr/lib/python3.8/ctypes/init.py", line 386, in getattr
func = self.getitem(name)
File "/usr/lib/python3.8/ctypes/init.py", line 391, in getitem
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: /lib/x86_64-linux-gnu/libhidapi-hidraw.so.0: undefined symbol: hid_get_input_report

The solution for me was to install hid 1.0.4. It seems hid 1.0.5 is now automatically dependent:
$ sudo python3 -m pip install hid==1.0.4

I hope this helps.

snagflash: improvement for UMS raw device mode

Since the UMS gadget should use a known VID:PID pair, it would be cool to get the device file from this information. udevadm should provide all the information but I'm not 100% sure if this is the right way to go.

Or is writing an udev-Rule for a disk device matching ID_VENDOR_ID/ID_MODEL_ID better? This way it would be possible to have a reproducible path and give user R/W access to the block device.

80-snagboot.rules does not catch i.MX6ULL

After installing the udev rules and connecting an i.MX6ULL in recovery mode, the device is visible in lsusb but the udev rule does not match.

$ lsusb  | grep -i recovery
Bus 003 Device 117: ID 15a2:0080 Freescale Semiconductor, Inc. i.MX 6ULL SystemOnChip in RecoveryMode
$ ll /dev/bus/usb/003/117
crw-rw-r--  1 root root 189, 372 May 11 17:18 /dev/bus/usb/003/117
$

Fixed locally with the following change, inspired by 70-uuu.rules and the live output of udevadm monitor --env:

-SUBSYSTEM=="hidraw", SUBSYSTEMS=="usb", ATTRS{idVendor}=="15a2", ATTRS{idProduct}=="0080", MODE="0660", GROUP="users"
+SUBSYSTEM=="usb", ATTRS{idVendor}=="15a2", ATTRS{idProduct}=="0080", MODE="0660", GROUP="users"

The status now is:

$ lsusb  | grep -i recovery
Bus 003 Device 118: ID 15a2:0080 Freescale Semiconductor, Inc. i.MX 6ULL SystemOnChip in RecoveryMode
$ ls -l /dev/bus/usb/003/118
crw-rw---- 1 root users 189, 373 May 11 17:32 /dev/bus/usb/003/118
$

snagflash: fastboot: Access denied

I'm using Ubuntu 22.04 and IIRC I need escalated rights in order to use fastboot. But I guess snagflash is only installed for the current user, so I cannot just use sudo here:

$ snagflash -P fastboot -p 0451:d022 -f download:u-boot.img -f flash:0:1 -f boot
Traceback (most recent call last):
  File "/home/mraynal/.local/bin/snagflash", line 8, in <module>
    sys.exit(cli())
  File "/home/mraynal/.local/lib/python3.10/site-packages/snagflash/cli.py", line 93, in cli
    fastboot(args)
  File "/home/mraynal/.local/lib/python3.10/site-packages/snagflash/fastboot.py", line 35, in fastboot
    fast = fb.Fastboot(dev)
  File "/home/mraynal/.local/lib/python3.10/site-packages/snagrecover/protocols/fastboot.py", line 34, in __init__
    cfg = dev.get_active_configuration()
  File "/home/mraynal/.local/lib/python3.10/site-packages/usb/core.py", line 921, in get_active_configuration
    return self._ctx.get_active_configuration(self)
  File "/home/mraynal/.local/lib/python3.10/site-packages/usb/core.py", line 113, in wrapper
    return f(self, *args, **kwargs)
  File "/home/mraynal/.local/lib/python3.10/site-packages/usb/core.py", line 249, in get_active_configuration
    self.managed_open()
  File "/home/mraynal/.local/lib/python3.10/site-packages/usb/core.py", line 113, in wrapper
    return f(self, *args, **kwargs)
  File "/home/mraynal/.local/lib/python3.10/site-packages/usb/core.py", line 131, in managed_open
    self.handle = self.backend.open_device(self.dev)
  File "/home/mraynal/.local/lib/python3.10/site-packages/usb/backend/libusb1.py", line 804, in open_device
    return _DeviceHandle(dev)
  File "/home/mraynal/.local/lib/python3.10/site-packages/usb/backend/libusb1.py", line 652, in __init__
    _check(_lib.libusb_open(self.devid, byref(self.handle)))
  File "/home/mraynal/.local/lib/python3.10/site-packages/usb/backend/libusb1.py", line 604, in _check
    raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 13] Access denied (insufficient permissions)

Add swig as a requirement

Installing via the install scrip install.sh fails when swig is not installed on the system and the wheel for pylibfdt needs to be built.

Building wheels for collected packages: hid, pylibfdt, tftpy
  Building wheel for hid (pyproject.toml) ... done
  Created wheel for hid: filename=hid-1.0.5-py3-none-any.whl size=3727 sha256=2f94d4730513bfa1825305989f973bd4cc3ef686d0b252e3b6c42140604c5c21
  Stored in directory: /home/nic/.cache/pip/wheels/29/47/ad/ec06975af624accf9e20e57ebf9aa10805379a41371bee4e91
  Building wheel for pylibfdt (pyproject.toml) ... error
  error: subprocess-exited-with-error
  
  × Building wheel for pylibfdt (pyproject.toml) did not run successfully.
  │ exit code: 1
  ╰─> [8 lines of output]
      running bdist_wheel
      running build
      running build_py
      running build_ext
      building '_libfdt' extension
      swigging libfdt/libfdt.i to libfdt/libfdt_wrap.c
      swig -python -Ilibfdt -o libfdt/libfdt_wrap.c libfdt/libfdt.i
      error: command 'swig' failed: No such file or directory
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
  ERROR: Failed building wheel for pylibfdt
  Building wheel for tftpy (pyproject.toml) ... done
  Created wheel for tftpy: filename=tftpy-0.8.2-py3-none-any.whl size=29494 sha256=f7a51a7986ba39188315a5cbc2f964236e302674844c4d8d1b13b42966c21c45
  Stored in directory: /home/nic/.cache/pip/wheels/c1/5a/d7/016ea5fd8815488a61f07972dd68868083d3819305b700c244
Successfully built hid tftpy
Failed to build pylibfdt
ERROR: Could not build wheels for pylibfdt, which is required to install pyproject.toml-based projects

I let you guys decide if you want to add it to the requirements.

snagrecover: NXP IMX6ULL `HIDexception: Success`

I'm trying to use snagboot to flash a Variscite iMX6ULL Dart SOM.

When executing the snagrecover tool I encountered the following error:

Starting recovery of imx6ull board
Installing firmware SPL
Downloading file...
Done
Skipping DCD header...
Done
Jumping to SPL...
Traceback (most recent call last):
  File "/usr/local/bin/snagrecover", line 8, in <module>
    sys.exit(cli())
  File "/usr/local/lib/python3.10/site-packages/snagrecover/cli.py", line 139, in cli
    imx_recovery()
  File "/usr/local/lib/python3.10/site-packages/snagrecover/recoveries/imx.py", line 100, in main
    run_firmware(dev, "SPL")
  File "/usr/local/lib/python3.10/site-packages/snagrecover/firmware/firmware.py", line 105, in run_firmware
    imx_run(port, fw_name, fw_blob, subfw_name)
  File "/usr/local/lib/python3.10/site-packages/snagrecover/firmware/imx_fw.py", line 184, in imx_run
    memops.jump(ivtable.addr)
  File "/usr/local/lib/python3.10/site-packages/snagrecover/protocols/memory_ops.py", line 51, in jump
    ret = self.backend.jump(addr)
  File "/usr/local/lib/python3.10/site-packages/snagrecover/protocols/imx_sdp.py", line 183, in jump
    status = self.dev.read(65, timeout = 100)[1:]
  File "/usr/local/lib/python3.10/site-packages/hid/__init__.py", line 165, in read
    size = self.__hidcall(
  File "/usr/local/lib/python3.10/site-packages/hid/__init__.py", line 148, in __hidcall
    raise HIDException(err)
hid.HIDException: Success

Which is strange on its own, because the exception message is "Success"...

So I changed the following lines:

try:
dev = hid.Device(vid, pid)
except hid.HIDException:
access_error("USB HID", f"{vid:04x}:{pid:04x}")
if soc_model in sdps_socs:
run_firmware(dev, "flash-bin", "spl-sdps")
# On some SoCs (e.g.: i.MX8QM) we can have a second stage based on SPDV
if soc_model != "imx8qm":
return None
elif "u-boot-with-dcd" in recovery_config["firmware"]:
run_firmware(dev, "u-boot-with-dcd")
return None
elif "SPL" in recovery_config["firmware"]:
run_firmware(dev, "SPL")
else:
run_firmware(dev, "flash-bin", "spl")
logger.info("SDP command sequence done, closing hid device...")
dev.close()

To this, in order to ignore all the exceptions:

        try:
            	dev = hid.Device(vid, pid)
                if soc_model in sdps_socs:
                        run_firmware(dev, "flash-bin", "spl-sdps")
                        # On some SoCs (e.g.: i.MX8QM) we can have a second stage based on SPDV
                        if soc_model != "imx8qm":
                                return None
                elif "u-boot-with-dcd" in recovery_config["firmware"]:
                        run_firmware(dev, "u-boot-with-dcd")
                        return None
                elif "SPL" in recovery_config["firmware"]:
                        run_firmware(dev, "SPL")
                else:
                        run_firmware(dev, "flash-bin", "spl")
                logger.info("SDP command sequence done, closing hid device...")

                dev.close()
        except hid.HIDException:
                pass #access_error("USB HID", f"{vid:04x}:{pid:04x}")

And now I was able to boot my u-boot correctly.

Config is:

SPL:
  path: SPL-mfgtool
u-boot:
  path: u-boot.imx

different dfu alt info on stm32mp13

I'm not sure if I'm doing something wrong, or this is to be expected or not.

When I use snagrecover to attempt a recovery of the stm32mp13 board I'm working with, the resulting accessible dfu alt info are different than if I was to interrupt u-boot and use the dfu 0 command myself.

hardware

I work on the stm32mp135d-based board from Seeed Studio, stm32mp135d-odyssey. Schematics are available here in case it is important to this issue (I don't believe it is).

software versions

  • snagboot 1.2
  • dfu-util 0.11
  • ATF v2.8-stm32mp-r1 (st)
  • optee_os 3.19.0-stm32mp-r1 (st)
  • u-boot 2022.10-stm32mp-r1 (st)

output of dfu-util -l when boot sequence is not interrupted

Found DFU: [0483:df11] ver=0200, devnum=78, cfg=1, intf=0, path="3-3", alt=2, name="@OTP/0xf2/1*776Be", serial="0021001A3232510937393835"
Found DFU: [0483:df11] ver=0200, devnum=78, cfg=1, intf=0, path="3-3", alt=1, name="@virtual/0xf1/1*512Be", serial="0021001A3232510937393835"
Found DFU: [0483:df11] ver=0200, devnum=78, cfg=1, intf=0, path="3-3", alt=0, name="@FlashLayout/0x00/1*256Ke", serial="0021001A3232510937393835"

output of dfu-util -l when boot sequence is interrupted and dfu 0 is ran

Found DFU: [0483:df11] ver=0200, devnum=81, cfg=1, intf=0, path="3-3", alt=4, name="mmc1_boot2", serial="0021001A3232510937393835"
Found DFU: [0483:df11] ver=0200, devnum=81, cfg=1, intf=0, path="3-3", alt=3, name="mmc1_boot1", serial="0021001A3232510937393835"
Found DFU: [0483:df11] ver=0200, devnum=81, cfg=1, intf=0, path="3-3", alt=2, name="uramdisk.image.gz", serial="0021001A3232510937393835"
Found DFU: [0483:df11] ver=0200, devnum=81, cfg=1, intf=0, path="3-3", alt=1, name="devicetree.dtb", serial="0021001A3232510937393835"
Found DFU: [0483:df11] ver=0200, devnum=81, cfg=1, intf=0, path="3-3", alt=0, name="uImage", serial="0021001A3232510937393835"

output of u-boot during uninterrupted boot sequence

In:    serial
Out:   serial
Err:   serial
invalid MAC address 0 in OTP 00:00:00:00:00:00
Net:   eth0: eth1@5800a000, eth1: eth2@5800e000
Hit any key to stop autoboot:  0
Boot over usb0!
DFU alt info setting: done

I suspect this has something to do with the boot over usb0 message, but I am not sure. How do I get access to the devices shown by dfu 0 when using snagrecover? Is this possible, or did I misunderstand the tool?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.