Sunday 20 January 2013

Linksys WRT54GL bricked

For years I've used the Linksys WRT54 range of wifi routers, I like these units as they have a decent form-factor, generally just keep on running for years without any attention and two wifi antennas that have screw-terminals on them so can easily add or change the aerial. I've always flashed these routers with different firmware, generally I use DDWRT as this has a new GUI, easy setup and quite a few advanced functions to switch WIFI on and off at certain times, captive portals, firewall rules, etc.

Recently I was going to upgrade my firmware, so did the usual, downloaded from DDWRT and uploaded it, then waited for the reboot, wifi didn't come back. Let it do its longer reboot, still nothing and it just wouldn't come back. I checked on the unit and the power light was constantly flashing, this is a bad sign, this generally means the FLASH/firmware isn't working correctly and its stuck in a boot loop. The recovery options on the Linksys/Broadcom hardware are to try their failsafe IP, this is 192.168.1.1 and initialise during their CFE bootloader. The trick here is to see if you can get a ping from 192.168.1.1 during power on. Unfortunately, this also didn't work for me, so it looked increasingly likely that I'd lost the unit completely, so it would be down to using a JTAG re-flash of the system to recover. This isn't easy! So popped the cover off and located the JTAG port. JTAG is a 12-pin (6x6 pins) port that you can access the Broadcom chipset directly to re-flash and debug it. In my case I was trying to use my FTDI cable FT232RL. I now realise this was STUPID of me! This is simply a low-voltage (3v) TTL to serial/usb converter cable, not a JTAG. So I started to give up hope. Until I realised, on the Linksys board was a SERIAL pin header. I soldered up some pins and connected up at 115200-8-N-1 and powered on. Sure enough I saw the bootloader!

This was a relief, it showed me that the bootloader wasn't damaged, but it just hun as it tried to load the O/S (As expected). It also confirmed that it should have been listening on 192.168.1.1 but the time it waited was tiny, almost 1-2 seconds! But it gave me hope as I reckon I could try to recover it from this point. Here is the screen output I had:

 

CFE version 1.0.37 for BCM947XX (32bit,SP,LE)
Build Date: Tue Jun 20 16:22:41 CST 2006 (root@localhost.localdomain)
Copyright (C) 2000,2001,2002,2003 Broadcom Corporation.
 
Initializing Arena
Initializing Devices.
 
No DPN
et0: Broadcom BCM47xx 10/100 Mbps Ethernet Controller 3.90.37.0
CPU type 0x29008: 200MHz
Total memory: 16384 KBytes
 
Total memory used by CFE:  0x80300000 - 0x803A39C0 (670144)
Initialized Data:          0x803398D0 - 0x8033BFE0 (10000)
BSS Area:                  0x8033BFE0 - 0x8033D9C0 (6624)
Local Heap:                0x8033D9C0 - 0x803A19C0 (409600)
Stack Area:                0x803A19C0 - 0x803A39C0 (8192)
Text (code) segment:       0x80300000 - 0x803398D0 (235728)
Boot area (physical):      0x003A4000 - 0x003E4000
Relocation Factor:         I:00000000 - D:00000000
 
Boot version: v3.7
The boot is CFE
 
mac_init(): Find mac [00:1C:10:36:41:9E] in location 0
Nothing...
 
eou_key_init(): Find key pair in location 0
The eou device id is same
The eou public key is same
The eou private key is same
Device eth0:  hwaddr 00-1C-10-36-41-9E, ipaddr 192.168.1.1, mask 255.255.255.0
        gateway not set, nameserver not set
Loader:raw Filesys:raw Dev:flash0.os File: Options:(null)
Loading: .. 3916 bytes read
Entry at 0x80001000
Closing network.
Starting program at 0x80001000
 
You can see it was giving me its IP and trying to boot. So now to try and interrupt it and get a ping reply. It also occurred to me at this point, previously trying to connect/talk to it I had plugged the cable directly from the router into my laptop. This was problematic as linux was trying to auto-negotiate and DHCP to the interface, which seemed to also introduce a delay, the delays were small but when I'd see the bootloader via serial I realised how time-sensitive the whole approach was. So using a mini-hub I connected the two together and started the ping again. Again I rebooted and found it didn't reply to pings.
The CFE bootloader can be interrupted by a CTRL-C to go interactive (like grub, lilo, etc) so the next trick was to try and interrupt it. Again this was time-sensitive and I found I had to keep hammering away at CTRL-C whilst plugging power into the router. A very tricky thing to do, but keep trying. Probably 10-20 attempts. Finally I got in and it responded:
 
mac_init(): Find mac [00:1C:10:36:41:9E] in location 0
Nothing...

eou_key_init(): Find key pair in location 0
The eou device id is same
The eou public key is same
The eou private key is same
Device eth0:  hwaddr 00-1C-10-36-41-9E, ipaddr 192.168.1.1, mask 255.255.255.0
        gateway not set, nameserver not set
Automatic startup canceled via Ctrl-C
CFE> ^C
CFE> ^C
CFE> help
Available commands:

rndis               Broadcom USB RNDIS utility.
et                  Broadcom Ethernet utility.
modify              Modify flash data.
nvram               NVRAM utility.
reboot              Reboot.
flash               Update a flash memory device
memtest             Test memory.
f                   Fill contents of memory.
e                   Modify contents of memory.
d                   Dump memory.
u                   Disassemble instructions.
autoboot            Automatic system bootstrap.
batch               Load a batch file into memory and execute it
go                  Verify and boot OS image.
boot                Load an executable file into memory and execute it
load                Load an executable file into memory without executing it
save                Save a region of memory to a remote file via TFTP
ping                Ping a remote IP host.
arp                 Display or modify the ARP Table
ifconfig            Configure the Ethernet interface
show devices        Display information about the installed devices.
unsetenv            Delete an environment variable.
printenv            Display the environment variables
setenv              Set an environment variable.
 
As you can see, we can now get to the bootloader commands, whilst this appeared my pings to 192.168.1.1 worked, so I now had a chance to get into it! I immediately tried sending a new firmware via TFTP to the Linksys. Trying to send the firmware over tftp was failing, so I was a little confused, until I read about CFE and how it works, and realised, by interrupting its boot process, it stopped its ability to receive firmware. So I now started to read about the commands, as I wanted to do it all in one go now, no more reboots as who knows if I'd get back into this mode again! Checking the commands I saw the erase and flash options. Checking again at DDWRT it showed that I could erase the existing/faulty flash 'nvram erase' which confirmed back with a 0 (for ok). I then found parameters to the flash command, and this accepted flashing from a TFTP source, so by doing:
flash -ctheader : flash1.trx
I could start the flash, at the same time sending the file via tftp it started to upload:
 
CFE> nvram erase
*** command status = 0
CFE> flash -ctheader : flash1.trx
Reading :: CODE Pattern is CORRECT!
upgrade_ver[v4.20.6] upgrade_ver[42006] 4712_ver[15000]
Done. 3032064 bytes read
fname=flash1.trx 
CODE Pattern is correct! (W54G)
Programming...done. 3032032 bytes written
*** command status = 0
 
At that point I typed 'go' which told it to boot, and sure enough after a few seconds DDWRT kernel boot messages appeared and eventually got the DDWRT root prompt, so I'm back in.
 
Hopefully the above will be handy to anyone in the same situation and thinking their router is toast. Persistance and keep on reading for solutions, good luck!