By corrupting a bootloader on my router's motherboard I managed to soft-brick it. Bootloader is usually the first batch of software instructions, the motherboard executes when powered up. Soft-bricking means that the device won't boot up, but can be resurrected to life, or de-bricked.

De-bricking procedure depends on the steps that caused the corruption in the first place. Replacing the corrupted bootloader instruction with the correct ones can make the device bootable again, provided nothing else got damaged.

On the motherboards without too much focus on space constrains, a category of almost all consumer electronics with the exception of cell phones would fall, the bootloader program may be stored on the easily identifiable flash chip. Many such flash chips use the same physical package following the common pinout. This is convenient for the manufacturer, as hooking up the chip to a programmer requires just a specialized clips tool and it takes very little effort to burn the actual firmware into the device. A programmer in this context is another device that translates the file on a disk to a low level electronic impulses that the chip can understand - in this scenario, store the program in the non-volatile memory.

But this set up is not convenient only for the manufacturer. In fact, it is also convenient for any user determined to modify or upgrade the functionality of such a device. The motives for this are many. Fixing a bug, increasing a security of a device, decreasing privacy concerns of a device or to make device do something completely different.

Raspberry Pi as a programmer

Many people these days have a spare Raspberry Pi lying around. And of course it can be re-purposed as a programmer in many situations, as it boasts many peripherals, either high-level like Ethernet and Wi-fi to connect with a computer or low level, such as UART, I2C and SPI to connect the chip on the other hand.

Chip I was talking with was Winbond W25Q64.V, a 64Mb chip that talks over SPI, a common part on the market, apart from TP-link routers it can be also found on ThinkPad notebooks.

Either uncomment a line in /boot/config.txt:

device_tree_param=spi=on

Or use the raspi-config GUI available from AUR:

sudo raspi-config

Interfacing options > SPI > Yes

Reboot was required on my device:

sudo systemctl reboot

After reboot, make sure that there is an output^[https://www.raspberrypi-spy.co.uk/2014/08/enabling-the-spi-interface-on-the-raspberry-pi/]:

lsmod | grep spi_

The devices located at /dev/spidev* should be available:

ls /dev/spidev*

Raspberry Pi 3 offers two hardware SPI ports, SPI0 as spidev0.0 and SPI1 as spidev0.1.

crw------- 1 root root 153, 0 Mar 15 16:07 /dev/spidev0.0
crw------- 1 root root 153, 1 Mar 15 16:07 /dev/spidev0.1

Note that the ports are in a root group, they will require permissions to use.

Wiring

A wiring table for the flash chip used. For the SOIC-8 chip flash chip, this table can be reused as many such chips are pin compatible. Most guides including this one assume SPI0 is used.

Flash PinFlash MeaningPi SPI0Pi SPI1Pi Meaning
1CS2436CS0
2DO2135MISO
3WP17173V3
4GND2525GND
5DI1938MOSI
6CLK2340SCLK
7HOLD17173V3
8VCC17173V3

Flashrom installation

flashrom is a utility for identifying, reading, writing, verifying and erasing flash chips. It is designed to flash BIOS/EFI/coreboot/firmware/optionROM images on mainboards, network/graphics/storage controller cards, and various other programmer devices. ^[https://flashrom.org/Flashrom]

flashrom is available in the Arch community repositories:

sudo pacman -S flashrom

Verify the installation by running flashrom:

Please select a programmer with the --programmer parameter. Valid choices are:
dummy, ft2232_spi, serprog, buspirate_spi, dediprog, developerbox, pony_spi, linux_mtd, linux_spi, usbblaster_spi, pickit2_spi, ch341a_spi, digilent_spi, stlinkv3_spi.

What will work with Pi is the linux_spi programmer:

flashrom -p linux_spi

Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Using default 2000kHz clock. Use 'spispeed' parameter to override.
No SPI device given. Use flashrom -p linux_spi:dev=/dev/spidevX.Y
Error: Programmer initialization failed.

It is obvious that the tool offers helpful usage tips, the full programmer parameter looks like so:

flashrom -p linux_spi:dev=/dev/spidev0.0

Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Using default 2000kHz clock. Use 'spispeed' parameter to override.
linux_spi_init: failed to open /dev/spidev0.0: Permission denied
Error: Programmer initialization failed.

Note on permissions

On a Debian based Raspberry Pi distribution, adding a user to the spi group and re-logging in would suffice. On Archlinux ARM there is no such group by default and the /dev/spidev* are owned by root. To use the SPI ports, either use sudo flashrom or alarm udev rules.

Flashrom usage

Probe the chip, making sure the wiring and the setup is correct:

flashrom -p linux_spi:dev=/dev/spidev0.0

If the setup is right, the chip is recognized:

Found Winbond flash chip "W25Q64.V" (8192 kB, SPI) on linux_spi.

Sometimes multiple chip definitions are detected^[https://openwrt.org/toh/tp-link/archer_mr200#debricking]:

Found Macronix flash chip "MX25L6405" (8192 kB, SPI) on linux_spi.
Found Macronix flash chip "MX25L6405D" (8192 kB, SPI) on linux_spi.
Found Macronix flash chip "MX25L6406E/MX25L6408E" (8192 kB, SPI) on linux_spi.
Found Macronix flash chip "MX25L6436E/MX25L6445E/MX25L6465E/MX25L6473E/MX25L6473F" (8192 kB, SPI) on linux_spi.

Multiple flash chip definitions match the detected chip(s): "MX25L6405", "MX25L6405D", "MX25L6406E/MX25L6408E", "MX25L6436E/MX25L6445E/MX25L6465E/MX25L6473E/MX25L6473F"
Please specify which chip definition to use with the -c option.

If this is the case, help it with picking the right chip type, it might be written on it's physical package:

flashrom -p linux_spi:dev=/dev/spidev0.0 -c MX25L6405D

Found Macronix flash chip "MX25L6405D" (8192 kB, SPI) on linux_spi.:w

With the formalities sorted out, store the flash contents into file (provide -c parameter if needed):

flashrom -p linux_spi:dev=/dev/spidev0.0 -r original.bin

Found Winbond flash chip "W25Q64.V" (8192 kB, SPI) on linux_spi. Reading flash... done.

Warning: The following command rewrites contents of the flash chip under consideration, potentially bricking/damaging your device.

Write flash contents from the file into the flash:

flashrom -p linux_spi:dev=/dev/spidev0.0 -w new.bin

Found Winbond flash chip "W25Q64.V" (8192 kB, SPI) on linux_spi.
Reading old flash chip contents... done.
Erasing and writing flash chip... Erase/write done.
Verifying flash... VERIFIED.

Given the new file contents is a valid instruction set with a correct data, possibly a bootloader, the device should now boot, if this was the goal.

This is a 27th post of #100daystooffload.