Re-enabling JTAG and Debugging the WRT120N

After de-obfuscating the WRT120N’s firmware, I started taking a closer look at the code, which runs the now-defunct SuperTask! RTOS.

Thanks in no small part to copious debug strings littered throughout the code and some leaked Atheros datasheets, I made good progress in statically disassembling the code. The next step was to start debugging the system while exercising some of the router’s services.

The WRT120N does have a JTAG port (labeled J8), which appears to conform to the MIPS EJTAG standard header:

After some probing, I found that this is due to the hardware design of the WRT120N: the reset button has been connected to the JTAG TDI pin on the AR7240 SoC. It is common for systems to allow JTAG pins to be re-configured as GPIO pins, so this is not un-heard of. However, this means that JTAG is likely being disabled in software.

Additionally, when depressed, the reset button asserts this pin low; the TDI line driven from my JTAG adapter also idles low. This means that whenever the JTAG adapter was connected to the JTAG header, the system thought that the reset button had been pressed.

I obviously didn’t want JTAG to be disabled, nor did I want the system continually resetting during a debug session. But, since I couldn’t magically redefine hardware pins, these were issues that had to be addressed in software.

Patching the Bootloader

The first firmware patch I needed to make was to the bootloader.

As seen previously, the bootloader checks the reset pin, and if asserted, it boots into a recovery image instead of booting the main image:

if(check_reset_button() != 0) goto load_main_image;

Since the JTAG adapter pulls the TDI line low, the bootloader wouldn’t even boot the main OS with the JTAG adapter connected; it thought the reset button had been pushed and loaded the recovery image instead!

There were two solutions to this problem. First, I could simply set a breakpoint on this conditional branch and change the register contents so that the recovery image is never loaded.

Besides being a PITA, this approach turned out to be impractical due to the following piece of earlier code:

Setting the RESET_SWITCH bit in the CPU_CLOCK_CONTROL register

This code is executed very early in the boot process and is in part responsible for configuring the system’s PLL clock. Specifically, the code snippet above sets bit 0 (the RESET_SWITCH bit) in the CPU_CLOCK_CONTROL register; according to the datasheet, this generates a CPU reset, causing the debugger to lose control of execution:

This register [CPU_CLOCK_CONTROL] controls the clock and reset to the CPU. These bits are controlled by driver software…RESET_SWITCH reset[s] during clock switch trigger.

What this means is that I would have to enter JTAG debug mode after the PLL was configured, but before the reset button was checked; a race condition that was difficult to reliably to win.

Instead, I opted to simply patch the bootloader on the flash chip. The check_reset_button function masks out bit 6 of the GPIO_IN register (aka, the TDI pin) by performing a logical AND with 0x40; if that pin is low, the function returns 0 (reset button depressed), else it returns non-zero:

The check_reset_button function

I changed this from a logical AND to a logical OR, ensuring that check_reset_button always returns non-zero regardless of the actual state of the pin. This is just a one bit change to the instruction opcode:

The modified check_reset_button function

Desoldering the flash chip and overwriting the bootloader with this patch got me past the bootloader and into the main OS:

I threw together a little script to automate this; it’s super hacky, but works so long as I don’t change the size of the decompressed OS image.

After buggering it up the first time, I recovered the system and flashed the modified firmware image through the router’s web interface. After a reboot, lo and behold, JTAG was up and running without issues:

I’ve placed a copy of the modified firmware image up on github, along with the script used to build it. Note that this will not patch the bootloader, although upgrading the bootloader via a firmware update does appear to be supported; I’ll leave that as an exercise to the reader. 😉

15 Responses to Re-enabling JTAG and Debugging the WRT120N

Hi Craig, what you are doing is awesome, indeed.
I especially appreciate that you develop highly innovative open source software such as for example the reaver.
Is there any way to make a donation to support your research? Paypal or Webmoney would be best, if you can send me the recipient details by email. Or I can buy any of your products, if you sell something. Thank you!

Hi,
I’m trying to recreate what you did (I’m new to hardware hacking), and I’m curious as to what exactly you did when you said “Desoldering the flash chip and overwriting the bootloader with this patch got me past the bootloader and into the main OS”. Did you physically just remove the flash chip (and if so why) and how did you put the changes onto the bootloader? Also I’m assuming you reattached the flash chip?In the mean time I’ll be googling for more info but I figured it was worth a shot to ask.

I used a hot air rework station to do the desoldering (highly recommend getting one of these if you’re doing a lot of desoldering; you can get them for $100 or less now).

In some cases you don’t have to physically remove the chip, and can just attach to it in circuit with a test clip. In this case my programmer wasn’t playing nicely with the chip in circuit, which is why I physically removed it.

The flash chip uses the Serial Peripheral Interface (SPI), so you can interface with it using variety of tools (microcontrollers, BusPirate, etc). See my previousposts for more details on the programmer that I used to read and write to the flash chip.

And yes, I re-soldered the chip afterwards. The typical packages these types of flash chips come in (SOP-8 / SOIC-8) are very easy to solder, as their pins are not terribly close together.

Hi Craig, thx for a cool write-up! I am trying to solve very similar problem, i have soho-router with MIPS micro controller and 14-pin JTAG port. As i’m experiencing kinda similar troubles your post was like a fresh air to me, but still I feel i don’t grasp it completely.
1. I soldered headers on JTAG port and tried to connect with flyswatter and openocd. it didn’t work out of the box.
2. I traversed paths from pins to micro controller. All pins are directly connected to the chip. Verified with multimeter.
3. Hooked with logic analyser and noticed that there are signals on some pins of header and some of them correlate very well with LEDs blinking. So i think I have similar issue as you described. JTAG pins are used is GPIO.

So i thought i gonna try what you mentioned: set a breakpoint and than trace boot loader to see where it turned off JTAG to use it as GPIO. what i don’t understand is how you managed to halt a processor on the very first instruction?target halted in MIPS32 mode due to debug-request, pc: 0xbfc00000

i thought may be you powered up your board from flyswatter2 and it would have more precise control over when chip starts to execute. so i located a number of pins on the board signed as 3v3 and tried to connect flyswatter’s Vsupply and/or VREF to it. Neither of this seemed to work.

is there a way to power the board from flyswatter2 at all?
if not how have you managed to halt CPU at the very first instruction??

I hope my writing got not very confusing and i would really very much appreciate your help! if it’s not very clear fell free to ask or email me.

Hi, James Shaw,
Sure it can.With the dump file and a simple s24/25 programmer,it can be running dd-wrt or Openwrt with 8MB and 16MB chip, and UBNT airos too.
The only thing is we can only dump the ART from similar devices with AR9285 from TP-LINK,Netgear etc.
No idea to copy the dump of The individually calibrated ART parttion.That’s why I posted in another thread…Need help from Craig.

Another problem is after flashing 3rd party firmware, no idea how to make the use of the RF ap msc5511, maybe it’s GPIO activated.

Also many models with AR7240+AR9285 is one stream only, one antenna.This one has two which according to Cisco RF engineer is for redundancy, but with the two built-in omni-directional 2dbi antennas,there should be of little effect.