A while ago one of the people that use my OpenWRT builds managed to brick his TP-Link TL-WR1043ND. So of course I wanted to know what happened, what went wrong? It seems he did a “sysupgrade” but was short on time, so he did it a bit quick. For those familiar with Murphy’s law, that one always manages to ruin your day when you want something technical done quickly…
My guess is either his download corrupted and he skipped checking the MD5 checksum or something went wrong with the flash. Whatever, went wrong… it doesn’t really matter anymore, his router would not boot any longer. When he plugged it in, all it did was flash it’s PWR LED on and that was it. It did not respond on it’s network interfaces nor was he able to use the OpenWRT fail-safe boot.
I had a hunch the rootfs of his router was corrupted in some way, and the boot-loader would still work. Because a sysupgrade procedure only touches the rootfs as far as I know. While doing some research on debricking I learned that it would be possible to reflash the rootfs from the boot-loader over TFTP. Next step: how to get in touch with the U-Boot boot-loader?
Like lots of other routers, there is a Serial TTL interface on the board connected to the SoC. What needs to be done is solder some headers to the holes in the PCB, so you can hook up a serial console to it. Once that’s done it’s possible to talk to the U-Boot boot-loader.
On the PCs side you need something that can speak 3.3V TTL. Regular serial ports, the ones you used to find on PCs, use a higher voltage, so you cannot use those. And most PCs do not even offer a serial port anymore, perhaps some headers on the motherboard but that’s about it. To solve this I bought a USB-TTL converter from DealExtreme for about 7 Euros. It comes with a cable to connect it to the router as well.
For most people the CP2102 USB-TTL converter seems to work out-of-the-box or after instructing Windows to look for drivers on Windows Update. Linux should also support it out of the box. In case you run Windows, and need drivers to get it to recognize, here’s a link to the SiLabs CP201x USB to UART Bridge drivers.
On the software side you can use GNU Screen on Linux, or PuTTY on Windows, and there are plenty of alternatives if you need one.
Modifying the router
Inside the TL-WR1043ND are 4 holes for the TTL interface. You find these holes in a single row on the front right of the PCB, while looking at the router from the front, close to the openings for a JTAG port.
First act is to open the case. This is fairly straight-forward, but some instruction how to do it for the first time comes in handy. Have a look at OpenWRT Wiki - TL-WR1043ND - Opening/Closing the case
The pin-out can be found at OpenWRT Wiki - TL-WR1043ND - Serial and here’s the picture for reference.
Soldering the header to it requires a good soldering iron with a small tip. The RX and TX headers are quite easy to solder, but the GND pin can dissipate the heat over a large area of the board. I had trouble with it, but eventually got it done with an extra pairs of hands and an extra soldering iron for some more heat. You don’t need VCC by the way.
Talking to the bootloader
So let’s hook up the USB-TTL converter to the router: Connect GND to the GND pin, RX to TX and TX to RX pin. And connect to the PC by plugging it in the USB port. Start your serial console of choice and configure it for a baud rate of 115200 (8 data bits, No parity, 1 stop bit, no flow control, all are often defaults). I have used PuTTY in this case because I happened to be on my Windows box at the time. Set it to Serial mode and told it to use COM3 as the communication device. You should check under what device name your USB-TTL converter presents itself to your OS.
Once your serial console it running, power up your router and watch the console for output. On my first attempt I got no output. I needed to reverse my RX and TX connectors, once I did that and re-powered the router it worked immediately. As soon as you see the message
Autobooting in 1 seconds type “tpl” quickly. It will interrupt the boot process and give you a minimal shell in the U-Boot boot-loader to send it commands. I had this on my console:
U-Boot 1.1.4 (Mar 31 2012 - 10:40:21)
AP83 (ar9100) U-boot 0.0.11
id read 0x100000ff
flash size 8MB, sector count = 128
Flash: 8 MB
Using default environment
No valid address in Flash. Using fixed address
: cfg1 0xf cfg2 0x7114
Autobooting in 1 secondsar7100>
If you get something similar, its time for the next step.
I used a Linux box I had laying around for this. You can use the machine you are working on if you like.
Download the factory image of my OpenWRT Regular build for the TL-WR1043ND and save it as
code.bin to an appropriate directory:
# mkdir /srv/tftpd
# wget -O /srv/tftpd/code.bin http://openwrt.sjoosten.nl/files/attitude_adjustment/12.09/r36655/ultrawrt-regular/ar71xx/openwrt-ar71xx-generic-tl-wr1043nd-v1-squashfs-factory.bin
# md5sum /run/shm/tftpd/code.bin
And of course check it’s MD5 hash to make sure it’s proper.
Just in case, you should check the IP address of the machine you are using as TFTP server, so we can later instruct U-Boot where to look. Use
ip addr or
ifconfig for this. The IP of my TFTP server is
tftpd-hpa to serve the file over TFTP. I used
# apt-get install dnsmasq
# /etc/init.d/dnsmasq stop # Debian automatically starts it as a daemon, so I stop it
# dnsmasq --enable-tftp --tftp-root=/srv/tftp/
Flashing the router
If you still have your serial console open from testing if it worked or not, you can continue where we left off. If not, open it again, power up the router and interrupt to boot process by typing ‘tpl’ quickly after the
Autobooting in 1 seconds message.
First off I configured the IP address of the router (default:
192.168.0.2) and the IP of the TFTP (default:
192.168.0.5) it will look for. I’ve set the IP address to a range my DHCP server does not issue, and the TFTP server IP to the one of the spare Linux box running DNSMasq as TFTP server. Adjust these for your situation:
ar7100> setenv ipaddr 192.168.3.8
ar7100> setenv serverip 192.168.3.34
Confirm the settings have been accepted correctly by entering
bootargs=console=ttyS0,115200 root=31:02 rootfstype=jffs2 init=/sbin/init mtdparts=ar9100-nor0:128k(u-boot),1024k(kernel),4096k(rootfs),64k(art)
Erase the corrupt firmware
Now it’s time to erase the corrupted firmware so it’s all nice and clean before flashing:
ar7100> erase 0xbf020000 +7c0000
First 0x2 last 0x7d sector size 0x10000 125
Erased 124 sectors
Load new firmware over TFTP to memory
ar7100> tftpboot 0x81000000 code.bin
Using eth0 device
TFTP from server 192.168.3.34; our IP address is 192.168.3.8
Load address: 0x81000000
[..I've cut some lines here..]
Bytes transferred = 8126464 (7c0000 hex)
Flash the new firmware
ar7100> cp.b 0x81000000 0xbf020000 0x7c0000
Copy to Flash... write addr: bf020000
Boot the new firmware
ar7100> bootm 0xbf020000
## Booting image at bf020000 ...
Uncompressing Kernel Image ... OK
Starting kernel ...
OpenWrt kernel loader for AR7XXX/AR9XXX
Copyright (C) 2011 Gabor Juhos <email@example.com>
Looking for OpenWrt image... found at 0xbf022000
Decompressing kernel... done!
Starting kernel at 80060000...
[ 0.000000] Linux version 3.3.8 (stefan@bacchus) (gcc version 4.6.3 20120201 (prerelease) (Linaro GCC 4.6-2012.02) ) #1 Fri May 17 19:36:54 CEST 2013
Yay! It’s working again. Enjoy!
Some resources I came across and benefited from: