Skip to content

Unbrick a Device (currently only SM2)

A device whose bootloader is damaged can still be recovered, because the AM335x BootROM tries the Micro-USB setup port before it tries NAND. Whatever is written in the flash, a board with a host on that port boots what the host offers it. That is what makes the rest of this page safe to get wrong.

Boot the device over USB RNDIS and rewrite the bootloader partitions from the U-Boot prompt, over the same USB link that brought U-Boot in. Nothing else is needed on the device: the recovery U-Boot reads and writes NAND by itself, so the recovery Linux root filesystem never has to come up.

Warning: This only applies to SM2 devices and out of these it is only confirmed for spotty_sm2. For SCM devices there currently is no easy way to unbrick them. If you bricked your SCM device, what you have to do is force it to boot from UART (either by changing boot order or by forcing reads from NAND to fail), then boot MLO and U-Boot via UART. From there you then have to write MLO/U-Boot to flash, after possibly transferring another "clean" copy via UART (XMODEM/YMODEM). This is not only difficult to set up but also very time-consuming.

1. Boot the recovery U-Boot

Set the host up and boot the device as described in USB RNDIS network boot. Only the DHCP and TFTP services from that page are needed here; the NFS root is not used.

Press a key when the device offers to stop autoboot, to get a prompt:

Hit any key to stop autoboot:  0
=>

Check that the recovery U-Boot can see the flash before going any further:

=> nand info

Device 0: nand0, sector size 128 KiB
  Page size         2048 b
  OOB size            64 b
  Erase size      131072 b

If this prints nothing, stop. Without a working NAND there is nothing to recover onto, and the writes below would not do what this page says.

2. Put the replacement images where the device can fetch them

Copy the MLO and u-boot.img you intend to restore into the TFTP directory the device already booted from. These are normally the ones from the stock firmware for your device; obtaining them is outside the scope of this guide. The MLO and u-boot.img built from this project work too, and are what a development device runs.

Warning: The steps below erase and rewrite the bootloader partitions. Make sure the two files are the ones you mean to write.

3. Load and check the images

Give the device an address, then fetch both files into RAM:

=> setenv autoload no
=> dhcp
=> tftpboot 0x82000000 MLO
=> tftpboot 0x84000000 u-boot.img

Two things here bite people:

  • The command is tftpboot. There is no tftp; it fails with Unknown command, and if you do not read the output you will go on to write whatever happened to be in RAM already.
  • Load to 0x82000000 and 0x84000000. Higher addresses run into memory U-Boot has reserved for itself, and the transfer stops with TFTP error: trying to overwrite reserved memory.

Check every transfer before writing anything. A successful one ends with a byte count:

Bytes transferred = 65200 (feb0 hex)

If that line is missing, the load failed. Do not continue.

4. Write the bootloader partitions

The bootloader lives at the bottom of the flash:

Offset Size Partition
0x000000 0x20000 NAND.SPL — the copy the BootROM tries first
0x020000 0x20000 NAND.SPL.backup1
0x040000 0x20000 NAND.SPL.backup2
0x060000 0x20000 NAND.SPL.backup3
0x080000 0x1e0000 NAND.U-Boot
0x260000 0x20000 NAND.U-Boot-Env

Write MLO to the first slot and u-boot.img to the U-Boot partition. The write lengths are rounded up to whole flash pages, which is why they are larger than the files:

=> nand erase 0x0 0x20000
=> nand write 0x82000000 0x0 0x10000
=> nand erase 0x80000 0x1e0000
=> nand write 0x84000000 0x80000 0xb0000

Writing only the first slot leaves the three backups as they were, so the BootROM still has something to fall back on if that copy ever becomes unreadable. To replace them as well, repeat the two MLO commands at 0x20000, 0x40000 and 0x60000.

5. Verify what landed in the flash

Read each region back and compare it against the file. crc32 over the length of the original file must match what the same file gives on the host:

=> nand read 0x82000000 0x0 0x10000
=> crc32 0x82000000 0xfeb0
CRC32 for 82000000 ... 8200feaf ==> 10149634

On the host:

python3 -c 'import zlib,sys; print("%08x" % zlib.crc32(open(sys.argv[1],"rb").read()))' MLO

Use the exact byte length of the file, not the rounded-up write length. If the two do not match, write it again; do not power the device off believing it is fixed.

6. Clear the U-Boot environment (optional)

An environment stored by the previous installation survives a bootloader rewrite and can send the new U-Boot somewhere unexpected. To discard it:

=> nand erase 0x260000 0x20000

Erase nothing else for this step.

7. Boot from the flash

Remove the USB host — unplug the Micro-USB cable, or power its port down — and power cycle the device. With no host on that port the BootROM falls through to NAND and runs what you just wrote.

If it does not come up, reconnect USB and start again from step 1. The recovery path does not depend on anything in the flash, so it is still there.