[INFO] Debricking TPLink TL-WR1043ND v.1.11 using JTAG


I have gone through the process of de-bricking my router. Since I experienced some problems I decided to share the process and create this write-up

Model: TPLINK TL-WR1043ND v.1.11
Symptoms: only power LED is on, no serial console available
Brick cause: SPI flash overwritten with garbage because of wrong file specified during write of "fullflash"

JTAG hardware used: FTDI 232H (aka FT232H)
JTAG software: openocd
300 ohm resistor is required for EJTAG connection

Openwrt device page: https://openwrt.org/toh/tp-link/tl-wr1043nd
Openwrt de-bricking instructions: https://openwrt.org/docs/guide-user/hardware/debrick.ath79.using.jtag

  1. JTAG connection
AD0 - TCK 		
AD1 - TDI 	
nTRST - 300ohm - VREF

Use 300ohm resistor to short nTRST and VREF pins (pull-up)

  1. Verifying openocd connection
# openocd -f tcl/interface/ftdi/um232h.cfg -f ath79.cfg -c "adapter_khz 6000"
Open On-Chip Debugger 0.10.0+dev-00567-gcea4015 (2018-11-06-12:50)
Licensed under GNU GPL v2
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
jtag_ntrst_assert_width: 200
jtag_ntrst_delay: 1
trst_only separate trst_push_pull
adapter speed: 6000 kHz
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 6000 kHz
Info : JTAG tap: ath79.cpu tap/device found: 0x00000001 (mfg: 0x000 (<invalid>), part: 0x0000, ver: 0x0)
MIPS32 with MIPS16 support implemented
Info : Listening on port 3333 for gdb connections
Info : accepting 'telnet' connection on tcp/4444
    TargetName         Type       Endian TapName            State
--  ------------------ ---------- ------ ------------------ ------------
 0* ath79.cpu          mips_m4k   big    ath79.cpu          halted
Error: Unknown flash device (ID 0x0017301c)

If you see the same output – then everything is set up correctly.
If you see "Error: ath79.cpu: IR capture error; saw 0x1f not 0x01" – then your JTAG wiring is bad.

  1. Adding SPI support

Following Openwrt instruction add support to your SPI. In my case "Unknown flash device (ID 0x0017301c)" means that my SPI is not supported by openocd. I did this modification and recompiled openocd:

diff --git a/src/flash/nor/spi.c b/src/flash/nor/spi.c
index 273e850..73994f7 100644
--- a/src/flash/nor/spi.c
+++ b/src/flash/nor/spi.c
@@ -80,5 +80,6 @@ const struct flash_device flash_devices[] = {
        FLASH_ID("gd gd25q16c",         0xd8, 0xc7, 0x001540c8, 0x100, 0x10000, 0x200000),
        FLASH_ID("gd gd25q32c",         0xd8, 0xc7, 0x001640c8, 0x100, 0x10000, 0x400000),
        FLASH_ID("gd gd25q128c",        0xd8, 0xc7, 0x001840c8, 0x100, 0x10000, 0x1000000),
+      FLASH_ID("EN25Q64-104HIP",      0xd8, 0xc7, 0x0017301c, 0x100, 0x10000, 0x800000),
        FLASH_ID(NULL,                  0,    0,    0,          0,     0,       0)
  1. ath79.conf issue

This is the most tricky part. For some reason latest openocd refuses to write the flash as it was in the instructions:

flash write_image unlock cfe.bin 0xbf000000
auto unlock enabled
Start address out of range: 0 bf000000 800000
error writing to flash at address 0xbf000000 at offset 0x00000000

I had to change flash bank address in the ath79.conf file: 0xbf000000 to 0x00000000. Last line should look like this:

flash bank $_FLASHNAME ath79 0x00000000 0x01000000 0 0 $_TARGETNAME

So now, if you want to read the flash you use:

dump_image cfe.bin 0x9f000000 0x20000

Offset specified was 0x9f000000. If you want to write the flash, you use 0x00000000:

flash write_image unlock cfe.bin 0x00000000

But both command will reference the same block in the SPI – first 128KB of bootloader aka CFE

  1. Find CFE

Now you need to find 128KB CFE file for your model and flash it. The best would be to dump CFE from a similar router. But you can use TPLINK OEM firmware and exctract CFE from it - just be sure to download the correct version. Download it and unzip. The bootloader starts at offset 0x200 so you have to skip the first 512 bytes and copy total 131072 bytes:

# dd if=wr1043nv1_en_3_13_15_up_boot\(140319\).bin skip=1 bs=512 count=256 of=cfe.bin
256+0 records in
256+0 records out
131072 bytes (131 kB, 128 KiB) copied, 0.0406206 s, 3.2 MB/s

Follow Openwrt de-bricking openocd instructions and flash the CFE file you just got

  1. If you got the correct CFE file, your JTAG connection was fine and openocd showed no errors, in about 1 hour (depends on your JTAG hardware speed) writing will complete. Reset the router. You should now see system LED also on. This means the bootloader is available

  2. Follow Openwrt instructions to connect serial console and perform TFTP recovery as usually



Thank you for the detailed write-up.

Kindly include a link where to buy such a FTDI 232H device?

Unfortunately, as a new user, I was not allowed to put more than 2 links in my post. You can search on ebay or aliexpress for "FT232H" and the top results should be what I used. I got mine for $8. Looks like this:



Thank you, i will try this product on DigiKey 768-1103-ND as Aliexpress shipping wlil take too long

Im looking if it would be possible to modify your method to work on the Cisco Meraki MR18

Question is would openocd support 128MB Nand Flash ?

I cannot guarantee that Cisco Meraki MR18 will work out of the box. Even if the chipset is the same, my router uses SPI, not NAND. So it could be that you will have to alter ath79 config file. Maybe someone more experienced with openocd can comment

1 Like

Understood, thank you for your feedback


The same procedure is valid for archer c7 ? What about VREF pin, use one on JTAG header or 3.3V ?

Note:Device is not bricked, I am just trying to verify if my JTAG cable will work.


nTRST - 300ohm - VREF

For the records:

this time i actually tried to use jTAG on Archer C7 v1, using chinese usb module known as baite, that was flashed with dirtyjtag firmware: Screenshot

There is very little info around on urjtag support for atheros socs and it is mostly for old ar2312 chips, best bet would be that the basic low level regs are still same on newer qca socs

trying to detect board works:

jtag> cable dirtyjtag
jtag> detect
IR length: 5
Chain length: 1
Device Id: 00000000000000000000000000000001 (0x00000001)
  Unknown manufacturer! (00000000000) (/usr/local/share/urjtag/MANUFACTURERS)

including config file returns some info too:

jtag>  include atheros/ar2312/ar2312    
ImpCode=00000000000000000000000000000001 00000001
EJTAG version: <= 2.0
EJTAG Implementation flags: R4k DMA MIPS64
Processor entered Debug Mode.

trying to detect flash failed:

jtag> detectflash 0x1f000000
ImpCode=10100000010000010100000000000000 A0414000
EJTAG version: unknown (5)
EJTAG Implementation flags: R4k ASID_8 MIPS16 NoDMA MIPS32
Processor entered Debug Mode.
dev ID=0000   man ID=0000
urj_flash_amd_detect: mid 0, did 0
error: flash: mid != 0x01

jtag status:

jtag> print
 No. Manufacturer              Part                 Stepping Instruction          Register                        
   0                                                         EJTAG_CONTROL        EJCONTROL                       

Active bus:
*0: EJTAG compatible bus driver via PrAcc (JTAG part No. 0)
	start: 0x00000000, length: 0x20000000, data width: 8 bit
	start: 0x20000000, length: 0x20000000, data width: 16 bit
	start: 0x40000000, length: 0x20000000, data width: 32 bit

discovery froze the cpu at some point (TDO stuck):

jtag> discovery
Detecting IR length ... 5
Detecting DR length for IR 11111 ... 1
Detecting DR length for IR 00000 ... 1
Detecting DR length for IR 00001 ... 32
Detecting DR length for IR 00010 ... 1
Detecting DR length for IR 00011 ... 32
Detecting DR length for IR 00100 ... 1
Detecting DR length for IR 00101 ... 1
Detecting DR length for IR 00110 ... 1
Detecting DR length for IR 00111 ... 1
Detecting DR length for IR 01000 ... 32
Detecting DR length for IR 01001 ... 32
Detecting DR length for IR 01010 ... 32
Detecting DR length for IR 01011 ... 96
Detecting DR length for IR 01100 ... 1
Detecting DR length for IR 01101 ... 1
Detecting DR length for IR 01110 ... 33
Detecting DR length for IR 01111 ... 1
Detecting DR length for IR 10000 ... 1
Detecting DR length for IR 10001 ... 1
Detecting DR length for IR 10010 ... 1
Detecting DR length for IR 10011 ... 32
Detecting DR length for IR 10100 ... 1
Detecting DR length for IR 10101 ... 1
Detecting DR length for IR 10110 ... 1
Detecting DR length for IR 10111 ... -1
Detecting DR length for IR 11000 ... warning: TDO seems to be stuck at 0
Detecting DR length for IR 11001 ... ^C

there is a poke command to init SPI but there's no documentation on what it does:

poke 0x58400000 0x100e3ce1

some have used it as:

poke 0xb8400000 0x000e3ce1

no such regs in datasheets, besides 0x18400000 that holds DMA registers (checksum)

as those are probably needed to be configure for things to work, it is necessary to find correct descriptors and exact address to write them to....

Hi a much simple method you could look at is to write the SPI flash chip directly with a Raspberry Pi with flashrom, skipping JTAG moethod altogether

as is done with the Aruba AP-105


managed to connect with openocd. uboot rewrite in progress...
update: it worked. will add detailed howto in wiki

1 Like

good to hear