Experimenting with embedded devices is fun but things not always work as expected. Sometimes you just flash the wrong firmware. So did I. After having done so I furthermore realized that the bootloader in my TL-WA801ND v2.1 was the current one and therefore contains a bug (or maybe it was deliberately crippled?). The impact of this bug was that you’re not able to load something via TFTP from the bootloader. How to unbrick this device? Is it possible at all? To anticipate the answer: It is. But at intermediate level…
Before I go into the details a hint about the commands I use to create files and stuff like that. I mainly work with a Windows machine but regularly use a *nix like environment on that machine. For this purpose I’ve installed Cygwin which provides me a lot of non-Windows tools I’m regularly using.
The very first step was to identify the flash chip itself. In the picture below I marked the flash on the PCB. It is located next to the UART header JP1 (unpopulated in this picture). It is a S25FL032A/P from Spansion.
Unfortunately it can’t be flashed while soldered. To flash it from outside of the device it needs to be desoldered. Attention: desoldering a SOP-8 chip requires good soldering skills. If you have a soldering tweezers it is a bit easier. In any case you might cause a severe damage on the device. Do it at your own risk.
Preparing the firmware
Before I flashed a new firmware into the desoldered flash had to prepare a file containing a good one. The flash is logically divided into five parts which are as follows:
00000000:0001ffff uboot 00020000:0011ffff kernel 00120000:003dffff rootfs 003e0000:003effff config 003f0000:003fffff art
The “uboot” contains the bootloader which loads the real firmware consisting of “kernel”, “rootfs” and “config”. The last block is the so-called Atheros Radio Test (ART) and contains vital data for the radio chip. As this is the only one I would like to have from the old flash I started by extracting this one. In order to get it I first extracted the complete flash content:
flashrom -p buspirate_spi:dev=COM7,spispeed=2M -r bricked.bin
dd if=bricked.bin of=art.bin bs=1 skip=4128768
dd if=/dev/mtd0 of=/tmp/u-boot.bin
hexdump -n 6 -s 130048 -e '"%06.6_ax " 5/1 "%02X:" 1/1 "%02X""\n"' u-boot.bin
newmac=12:34:56:78:9A:BC echo $newmac | gawk -b -F ':' '{ for (i=1; i <=NF; i++) { printf("%c", strtonum("0x"$i)); } }' | dd conv=notrunc bs=1 count=6 seek=130048 of=u-boot.bin
dd if=/dev/zero bs=1 count=65535 | tr "00" "\377" >ffed64.bin
The last part will be the firmware. I decided to use the stock one from TP-Link but not the latest one so I didn’t have to remove the bootloader from it. At the end I had the 4 files
- u-boot.bin
- wa801nv2_en_3_13_20_up(120524).bin
- ffed64.bin
- art.bin
Those were concatenated by
copy /b u-boot.bin+wa801nv2_en_3_13_20_up(120524).bin+ffed64.bin+art.bin recover.bin
Flashing
To flash the firmware with flashrom an appropriate layout file is required. The above layout is exactly in the format needed so I simply put it in a file called “rom.layout”. Finally
flashrom -p buspirate_spi:dev=COM7,spispeed=2M -n -w recover.bin -l rom.layout -i uboot -i kernel -i rootfs -i config -i art
Have a look at my modified version of U-Boot, which supports WA801ND v2:
https://github.com/pepe2k/u-boot_mod
It’s probably a stupid questions given your detailed description, but just to be clear. I cannot flash the TL-WA801ND v2.1 without removing the chip? -_-
Directly flashing the chip requires desoldering.
Hallo…
Flashing the device without desoldering of the FLASH is possible. All you need is a running bootloader with possible mm command and connecting the uart to device.
I wrote a little script below, to flash a new kernelimage to the device without TFTP Client. Only Uart Bootloader Console is needed and my python script.
I posted my code, but all tabs and spaces where deleted. So this code is quite buggy.
If you are interested in my code, send me an e-mail adress or a public storage to upload the script.
Good Luck
Regards Christian
Hi,
Can this procedure be used for unbricking the TL-WA801ND V1.1 ? If so, can the 2.1 bootloader you have uploaded to dropbox be used for TL-WA801ND V1.1 ?
thanks
Hello, i have a problem with my repeater.
i haven’t modified anything (it’s virgin xD ), but i have the problem of the power led everytime on, and the other 4 leds blinking together (it’s seems bricked).
I used it for a long time (like 7 moth without power off (just once every 2 weeks for a couple of minutes), then I haven’t used anymore because I moved.
Now without reason it’s bricked.
I Tryed to connect a serial port to USB made by prolific (NOT TTL) and putty doesn’t show anything….
what can i do? i don’t want to spend money for a programmer that cost like the repeater.
Thank You.
Hello together……
At first sorry for my bad english.
I have found and checked a way to unbrick a TP-Link Device with a cripped Bootloader (Bootloader without working TFTP Client) without desoldering and external flashing.
At first, the problem is how to get the new Firmware in RAM without TFTP transfert. After some time reingeneering the cripped u-boot i found a way to manipulate the RAM content very easy with only some possibilities of commands.
The way is to use the mm command (memory manipulating command of u-boot). Ok… thats fine, but how can i automate the input of all 4Byte blocks in the boot loader console?
The answers was writing a little programm with this functions …
1. Reading the *.bin file in an array
2. Ordering all bytes in blocks of 4Bytes (same order als mm command need)
3. Automating the Bootloader stop command with “tpl”
4. Automate the first command “mm 0x81000000”
5. Read the answer of device with Adress and Content like “0x81000000 : 0xffffffff ? ”
6 Bilding a loop to send all the 4 Byte blocks to Device with new Content Answers.
7. and so on for the hole *.bin file.
8. After that change the automating console to human console input
9. Sending erase 0x9f020000 +0x3c0000 (eeprom erase)
10. Sending copy command cp.b 0x81000000 0x9f020000 0x3c0000 (copy ram->flash)
11. after “done….” sending bootm 0x9f020000 (booting kernel from flash)
12 ….. ***Bang*** Thats the goal.
I´m felt glad to found a way unbricking the device without any money or desoldering.
If someone is interested in getting the source code…. no problem. I will post the code. But the code is not released or best praxis at the moment. It is a little python script, looks like a “Quick Hack”, and written in 20 minutes. So at is at it is.
In the next days or weeks i will spend some time to optimate the code.
Thank You ….
Regards Christian
Hello twice ….
Here is my code. For your information: Sending OpenWRT Image to device needs 02:12:00 houres…. Is long but better als desoldering…
#
# Some Inports
#
import sys
import string
import serial
#
# Init Vars
#
offset = 0x81000000; # Start Adress in RAM
#
# function for missing printf
#
def printf(format, *args):
sys.stdout.write(format % args)
#
# Reading bin file, converting to hex, ordering to 4 Byte Blocks
#
binarray=[0 for i in range(1016012)]; # Init Array
str = open(“openwrt.bin”,”rb”).read() # Define Filename in
hexStr=””
count = 0; # Init 4 Byte Block Counter
for x in range(0, len(str), 4): # Loop on str var with step 4
hexstr=””; # Init 4 Byte Block Content
hexStr=hex(ord(str[x]))[2:]; # converting bin to hex
if len(hexStr) < 2: # checking on 1 collum only
hexstr=hexstr + "0" + (hexStr).strip(); # insert pre 0 if needed + first byte of block
else:
hexstr=hexstr + (hexStr).strip(); # first byte of block
if x+4 <= len(str): # are there some bytes missing?
for y in range(1, 4): # yes, fill in the missing bytes of block
hexStr=hex(ord(str[x+y]))[2:]; # converting missing bytes to hex
if len(hexStr) 0: # are the some bytes missing after last block?
for z in range(0, Rest): # loop on missing bytes after last block
#
print x+z; # debug output
#
hexStr=hex(ord(str[x+z]))[2:]; # convert bin to hex
if len(hexStr) < 2: # checking on 1 collum only
hexstr=hexstr + "0" + (hexStr).strip(); # insert pre 0 if needed
else:
hexstr=hexstr + (hexStr).strip(); # insert one missing byte
for w in range(Rest, 4): # fill in all missing bytes of block without content
hexstr=hexstr + "00";
# print "Adress:", hex(offset+x), "Arraycount:", count, "Byteblock:", hex(x), "Block:", hexstr; # Debug
binarray[count]=hexstr; # copy converted content to Array
# print binarray[int(0xb5ac)/4]; # Offset-Debug output
#
# Serial Console emulation with little output parser
#
port = serial.Serial("/dev/ttyUSB0", 115200, timeout = None); # define Serial
port.flushOutput(); # clear output buffer
port.flushInput(); # clear input buffer
# Read line on serial up to CR is incommung
def serialrdln(pruefung): # funktion on parsing input
while True:
zeile = port.readline().strip(); # reading one line on serial up to CR
log(zeile, "in"); # Log output
if (pruefung) != "": # check if input is empty
if zeile == (pruefung): # check if input = parsing line
return zeile # return with arg
# Reading Serial byte by byte and checking on incomming word
def serialrd(word): # function on parsing word
wordlen = len(word); # lenght of parsing word
count = 0; # collum conter = 0
# log("Waiting for: " + word, "log"); # Debug Output
while count ” + data;
if typ == “out”:
print ” “);
log (“State1: Sende mm mit Offset”, “log”);
serialwriteecho(“mm ” + (hex(offset)) + “\r\n”);
line = serialrd_input(22);
print line;
state = 2;
if state == 2:
for t in range (0, count+1):
serialwriteecho(binarray[t] + “\r\n”);
line = serialrd_input(22);
print line;
port.close();
break
Hallo …..
With my post i will send a better source code of my python script for flashing a TP-Link AP with crippled or buggy bootloader 1.1.4.
Before using the script connect the uart with Converter to 3,3V to the device. Start the script and then switch on the AP.
Good Luck
Regards Christian
——————————————————————————————-
#!/usr/bin/python
#
# Some Inports
#
import sys # Import for sys.stdout.write
import string # Import for string handling
import serial # Import for Serial communication
#
# Init Vars
#
imagefile = “openwrt.bin”; # define new imagefile
debugmode = “true”; # set Debugmode to true or false if needed
stopboot = “tpl”; # word for stopping bootloader on TP-Link
offset = 0x81000000; # Start Adress in RAM
offsetflash = 0x9f020000; # start Adress of kernel image in flash
imagelenght = 0x3c0000; # lenth of openwrt image
#
# function for missing printf
#
def printf(format, *args):
sys.stdout.write(format % args)
#
# Reading bin file, converting to hex, ordering to 4 Byte Blocks
#
str = open(imagefile,”rb”).read(); # Define Filename in
binarray=[0 for i in range((len(str)/4)+1)]; # Calculating the width of Binarray
hexStr=””; # Init Var
count=0; # Init 4 Byte Block Counter
for x in range(0, len(str), 4): # Loop on str var with step 4
hexstr=””; # Init 4 Byte Block Content
hexStr=hex(ord(str[x]))[2:]; # converting bin to hex
if len(hexStr) < 2: # checking on 1 collum only
hexstr=hexstr + "0" + (hexStr).strip(); # insert pre 0 if needed + first byte of block
else:
hexstr=hexstr + (hexStr).strip(); # first byte of block
if x+4 <= len(str): # are there some bytes missing?
for y in range(1, 4): # yes, fill in the missing bytes of block
hexStr=hex(ord(str[x+y]))[2:]; # converting missing bytes to hex
if len(hexStr) 0: # are the some bytes missing after last block?
for z in range(0, missing): # loop on missing bytes after last block
if debugmode==”true”: print “Adress:”, hex(x+z); # debug output
hexStr=hex(ord(str[x+z]))[2:]; # convert bin to hex
if len(hexStr) < 2: # checking on 1 collum only
hexstr=hexstr + "0" + (hexStr).strip(); # insert pre 0 if needed
else:
hexstr=hexstr + (hexStr).strip(); # insert one missing byte
# After working on last missing Bytes, fill up the last empty Bytes of Block with FF
for w in range(missing, 4): # fill in all missing bytes of block without content
hexstr=hexstr + "FF"; # filling up with FF
if debugmode=="true": print "Fill up next empty Byte of Block with FF";
if debugmode=="true": print "Offset:", hex(offset+x), "Arraycount:", count, "Byteblock:", hex(x), "Block:", hexstr; # Debug
binarray[count]=hexstr; # copy converted content to Array
count +=1; # array block counter +1
#
# Serial Console emulation with little output parser
#
port = serial.Serial("/dev/ttyUSB0", 115200, timeout = None); # define Serial
port.flushOutput(); # clear output buffer
port.flushInput(); # clear input buffer
# Read line on serial up to CR is incommung
def serialrdln(pruefung): # funktion on parsing input
while True:
line = port.readline().strip(); # reading one line on serial up to CR
log(line, "in"); # Log output
if (pruefung) != "": # check if input is empty
if line == (pruefung): # check if input = parsing line
return line # return with arg
# Reading Serial byte by byte and find a defined word
def serialrd(word): # function on parsing word
wordlen = len(word); # lenght of parsing word
charcount = 0; # character conter = 0
while charcount “, data;
if typ == “out”:
print ” “); # parsing console prompt
log (“State1: Sending mm with offset”, “log”); # log sending mm command with right offset Adress in RAM
serialwriteecho(“mm ” + (hex(offset)) + “\r\n”); # sending mm command with right offset Adress in RAM and CR with echo
line = serialrd_input(22); # reading answer from device with offset adress and content
printf (line); # printing output from device to console
state = 2; # change to state 2
if state == 2: # automating the content input to device
for t in range (0, count): # loop for count of blocks
serialwriteecho(binarray[t] + “\r\n”); # sending content to port with CR
line = serialrd_input(22); # reading answer from device with offset adress and content
printf (line); # printing output from device to console
state = 3; # change to state 3
if state == 3: # image is send to ram, stopping mm console with quit
serialwriteecho(“quit\r\n”); # sending q with CR to port with echo return from device
data = serialrd(“wasp> “); # parsing console prompt
state = 4; # change to state 4
if state == 4: # console input, erasing FLASH
serialwriteecho(“erase ” + (hex(offsetflash)) + ” +” + (hex(imagelenght)) + “\r\n”); # send erase Flash
data = serialrd(“wasp> “); # parsing console prompt after earasing
state = 5; # change to state 5
if state == 5: # erasing FLASH is done, copy RAM to FLASH
serialwriteecho(“cp.b ” + (hex(offset)) + ” ” + (hex(offsetflash)) + ” ” + (hex(imagelenght)) + “\r\n”); # send copy to FLASH
data = serialrd(“wasp> “); # parsing console prompt after flashing
state = 6; # change to state 6
if state == 6: # flashing is done, boot from flash
serialwrite(“bootm ” + (hex(offsetflash)) + “\r\n”); # send boot from flash to device
port.close(); # close port to device
break
Hallo,
the Link to the code:
https://www.dropbox.com/s/ro31y443wmb6m8s/tplflash.py?dl=0
Regards
Christian
Sorry wrong link
This https://www.dropbox.com/s/ek9fn3q0mr1ck36/tpflash.py?dl=0 is right
CU
regards Christian
Please verify scripts when reading the file openwrt.bin is taking a more character “L” in the String part
Offset: 0x81000000L Arraycount: 0 Byteblock: 0x0 Block: 01000000
The size of the * .bin is 0x81000000
I think the right thing to be without the “L”
Offset: 0x81000000 Arraycount: 0 Byteblock: 0x0 Block: 01000000
when this ending run this command
erase 0x9f020000L + 0x3c0000
cp.b 0x81000000L 0x9f020000L 0x3c0000
bootm 0x9f020000L
right when I think should be without the “L”
erase 0x9f020000 + 0x3c0000
cp.b 0x81000000 0x9f020000 0x3c0000
bootm 0x9f020000
Hi, I unbrick my wa801dn v2 without soldering. Read this Link: http://www.dd-wrt.com/phpBB2/viewtopic.php?t=278489
After unbrick I use this firmware : https://www.dropbox.com/sh/4dd3x9jf6qc7gx6/W0XZ-0LrZ-
from here: https://tasksofohm.wordpress.com/hardware/bringing-openwrt-to-tl-wa801nd-part-2-building-openwrt/
Harris ( http://www.bonsaiforum.gr )
Hi Bonsai,
yes, that is the normal way but we are talking about a way to unbrick the device with deactivated tftp connection on bootloader. Congratulation, you have a bootloader with full function. So…. never update/reverse the device with the latest tp-link firmware. After that you have the same buggy bootloader in your device….
On that you can use my script from here: https://tasksofohm.wordpress.com/hardware/bringing-openwrt-to-tl-wa801nd-part-2-building-openwrt/
Regards Christian
Hi, you have right, but I used the first tp-link firmware (I wrote this to my instructions).
Thank you Christian.
Hello Christian,
i have a wa801nd and a problem i hope you might be kind enough to help me with.. if possible.
the problem in brief is that i’m unable to connect to the unit through LAN, once i plug the cable, the LAN led turns off, and when i unplug the cable, LAN turns back on again. if i’m not mistaken, this should be the other way around!!
when the original firmware by tp-link was still on the unit, i could connect to it wirelessly but not through LAN. so i figured, why not flash your openwrt rom and try it out. i was mistaken. now the AP boots up without wireless (standard openwrt first boot), and i’m unable to connect at all, not through wlreless, nor LAN.
from what i observed, the unit “is” working fine, all except for the “LAN” part. but i can’t connect unfortunately.
what do you suggest?
thank you
Hi mjay,
there is still a way to connect the device through UART (RS232). But think about the different Voltage Level between the device Port and the PC UART. Don´t connect the PC to the device without the right Level Shifter.
For standard PC Rs232 Port the following connection is needed.
The other way is to connect the device via usb to TTL like DKU-5 data cable.
Next step is to open a standard console on RS232 and connect/Login to the openwrt sytem. On this session you can configure your wifi as you want, or use
Could you please explain me more details with your problem on your LAN Port? I need more information……
regards
Christian
Hello Christian
Apologies for the late reply.
The problem with the lan port is weird. Let’s say I boot up the AP without plugging the cable. It boots just fine (from what I can see from the leds), then all of a sudden the lan port led turns on (without the cable). After that if I plug the cable, the lan led would turn off. On the other end the PC starts trying to connect, but eventually gives me a message saying the network cable is unplugged. At this point if I unplug the cable the lan led (which is off) turns back on.
In simple words it’s acting exactly the opposite to the way it should with regard to the lan led responding to plugging and unplugging the ethernet cable.
When plugged, if I try to ping/ssh/telnet the AP, I get a “host not found” error..
That’s about it I guess.
Now, if I go with the USB to TTL cable option, do I still need a voltage level shifter?
Thanks
Hello again,
i found this on Amazon..
it will take about 15-20 days to get to where i am from the day of purchase :(
with this i’ll probably be able to turn on WiFi, do you think i’ll be able to configure Openwrt through Wifi to do wireless bridging, did you ever try it? what are your thoughts?
too many questions i know..
thanks
Hi mjay,
there are never to many questions.
So let me first give you some answers…. You are right. Your adapter is the right way to connect to your device without any other level shifter (It is included for 3.3V and 5V).
But i think it is not the best way to configure the flashed firmware over uart because it seems verry buggy. So on my oppinion the best way is to flash a new firmway with all you working functions are included.
Could you please test flashing the firmware with tftp on bootloader…?
After that all your needed configurations are working as default.
Regards
Christian
Hi there,
I have an WR1043ND v2 router and after attempting to flash the original firmware (I was having some performance issues and thought OpenWRT was the cause) my device is in a boot loop. I should have flashed the tplink firmware without the bootloader probably. I’ve soldered pins for the serial connection and used my Aten USB serial converter to connect to the router(only Tx,Rx and GND). Putty and the Com port settings are ok (115200, 8N1, No flow ctrl) but strange characters are appearing in the console and it won’t accept any commands. Now I’m not sure why is this happenning. Can the above script be used for my router too? How can I run the php script?
Thanks,
Nico
Hi Nico,
your experimental things are the best way to kill your device.
Please disconnect your device from your PC as soonest as is can. Your USB to Uart converter is not the right thing because the output is not TTL or 3.3V. It is +/- 12 Volt so you can’t connect to your device, only kill the uart front end of your device.
Please use the right adapter and read all the post to this on this Page at first.
Regards
Christian
Like most TP-Link access-points/routers it will try to download a recovery image over tftp if bricked. Just start a tftp server at 192.168.0.66, and put an image (eg. the original firmware) in the root and name it wa801nv2_tp_recovery.bin (you can verify by using tcpdump or wireshark). Start the access point and press the reset button for a couple of seconds. No soldering required.
I think that doesn’t work. At least I’m not able to reproduce such a behavior.
Hey Guys,
I have a TL-WA801ND that is stuck in a boot loop, I can get to the “wasp>” prompt however tftp does not work – I assumed this has to do with the Ethernet port not being able via uboot….
My question is how do I use your phyton script to manually upload the openwrt software? Can this be done in windows?
It was bricked with dd-wrt firmware; I was trying to revert to stock firmware….
Hey Jigg,
yes it is possible to do this under windows, but the better way is to do this under windows. In the past we had some problems under different linux python versions.
All you need is to read this blog e.g. my posts to the same problem:
https://tasksofohm.wordpress.com/hardware/bringing-openwrt-to-tl-wa801nd-part-2-building-openwrt/
Have a nice day …. regards Christian
Thank you Christian,
I got through with the script…..one thing though, I had to time the auto-boot on the TL-WA801ND because it would get stuck after sometime; So I started the script and when it got close to the end of the firmware conversion, I powered up the TL-WA801ND.
where i typ all this commands?
i got win, and i cant get any ip address from my reapiter
he just turn on and off, my switch get connection and lost every 5 sec
what i can do?
someone can explain me what can i do to unbrick wa801 v2.1 whitout desoldering the chip?
i want upload original firmware……
thanks
i’ve tried to use python script changing ttyUSB0 to Com8 (using usb to ttl device) but when i run the script i recive this error :
File “tpf.py”, line 44
hexstr=hexstr + “0” + (hexStr).strip(); # insert pre 0 if needed
^
IndentationError: expected an indented block
i’ve debugged the script it’s all error relative at tabs spacement and parethesis during print command, now the script start but give this error:
File “C:\Users\admin4\Desktop\tpflash.py”, line 30, in
binarray=[0 for i in range((len(str)/4)+1)]; # Calculating the width of Binarray
TypeError: ‘float’ object cannot be interpreted as an integer
how can i fix it?
thanks.
Hey Marco,
Can I suggest you use a Linux OS (you can use a live cd) to run the script – its a bit easier and less buggy that way….
Using linux everythings Goes ok :)
I’ve Just debricked The device!
On Linux python workshop bettee than Windows :) At first script run And I’ve uploaded open wrt Image. ..
So i decide To Revere Back To originale firmware, with winspc And ssh commando :) thanks To all!
Glad you got thru….
You can get instructions for programming with SPI programmer?
I accidentally deleted all ( with usb to ttl adapter, with putty, command “ERASE ALL” )
Thanks
Don’t know if this is the right place to ask. But can I get the wa801nd-v2 to fetch firmware from tftp without bricking it first? Is there any combination of power on or reset that trigger a tftp boot fetch procedure?
hello, by mistake delete the data that contained the eeprom chip of my device, is there any way to recover my device and that it works again?
Managed to revive a WA801nd-v2 today that got bricked by forced flashing of the official firmware from OpenWrt’s sysupgrade routine.
It resulted in an endless loop of the LEDs doing on-off every few seconds.
Did use an USBasp programmer as used to program Atmel SoCs. Soldered the gnd wire to the UART ground and 4 signal wires to the Spanion flash chip without desoldering the flash.
Power on AP and USBasp in USB slot and the flash is recognized in the program ‚AsProgrammer‘ in a Windows environment as there is no Linux version.
AsProgrammer comes with drivers for the USBasp programmer. The programmer costs very little and happened to have a few from Arduino projects.
Made a recover.bin by concatenating a u-boot from this article with adapted MAC, a tplink firmware stripped from its header and u-boot, a config filler but one byte longer than described here, and the asp data as described here; this completely fills the 4MB flash. WA801nd v2 revival! Thanks a lot for the article!