So…A friend asked me to restore the original firmware on his Linksys WRT54g2 after having installed DD-WRT. Well, it isnt as straightforward as it is the other way around. In fact, it isnt doable just by software.
First, you need to open the router. Damn thing uses the only screwdriver i don’t have.
Looking around, you’ll find the 5 pins in the middle of the top face of the mainboard are a serial port. And the 6 boxes in the right (6 on top face, 6 on bottom face) are pins for jtag. You’ll have to scratch the green stuff out (carefully) using a screwdriver, nail, or something sharp. After leaving enough copper surface visible, you can proceed to solder cables or some kind of surface connector. (or, adapt a standard connector)
So far, so good.
You’ll need a jtag cable. You can get some online, from cheap ones, to really expensive ones. Plus, you need to know if it will support the chip the router uses.
Cheap solution : Use a home-made cable consisting in 4 resistors + 1 DB25 male connector (using the printer port. Note that it needs to be a REAL printer port. Not an USB “printer” port).
* Taken from OpenWRT Wiki
This easy to make cable (Unbuffered cable) has to be short. No more than 6 inches, or noise will be your enemy. I made one about 3 inches long.
Get tjtag to tinkle with the board. Runs on windows and linux. As none of my laptops have a printer port, i used a colleague’s computer (WinXP). Now this becomes nasty xD
Running test commands, the software recognized the board and memory chip. All good!
Cable was good, board was alive (duh! it was working), and software was compatible.
Then, (just in case) i made a wholeflash backup. This will save all the flash content bit by bit, allowing a future restore to DD-WRT (in this case).
(2MB backup, took 623 seconds to complete.)
Now, according to dd-wrt forums, once installed dd-wrt on this router, there is no way back. Well, this is partly true.
As i commented before, there is no “easy” way back. Better yet, if you do not make a wholeflash backup yourself, the “not easy” way back, becomes more “not easy”.
Well.. I received this router with dd-wrt preinstalled, and was asked to return it to firmware factory. All system hardware was “pristine”, so nobody mangled it, and… nobody made a flash backup. Fortunately , a guy in the forums was nice enough to post a wholeflash backup of his router. (different flash chip).
When decided to try it out, i renamed the file to wholeflash.bin and run
A couple of numbers showed up on screen….
….. (i let it run, and i went back to work)
If you consider the time between the numbers on screen, it would have taken about 120 hours to flash the whole flash. I know jtag is slow, but this is ridiculous.
So, Control-C, and try again using some parameters.
Now the board started to act weird. Some times it didnt detected the flash chip, some times it complained about not being able to set debug mode on processor, hanged while enabling memory writes, etc.
After some time trying and reading, i decided to use the /dma, /noreset and /noemw parameters. (force enable dma (speed), disable reset and memory writes). Some times i had to force the flash id (/fc:09). Now it was running fast. (read, about 2 minute per each percent).
Off to work again.
Checked about 60 minutes later, and the damned thing hanged at 27%.
After that, came a series of erase of the flash, followed by differents tries to flash. Each attempt failed in different places. (6%, 12%, the most i got, was 37%).
Checked the cable, any interference around, etc. Same result.
I went home, and let the stupid board flashing. Didnt care anymore
Next day i tried a couple of things.
One of them lead me to success (hours later!)
The important steps were this :
- Connected the pin 1 of the unbuffered cable , to a Vcc source (used serial’s port) with a 100ohm resistor. (In the pictures the pin is connected…. i took the pictures after all this)
- Left each cable a couple of millimeters away from each other.
- Put the router in its own case, to isolate it from external noise. (however, i used the original casing.. Some suggest using some tinfoil around).
This led me to flash to 15% almost every time. (it was still hanging).
Then, i got fed up. Decided to split the bin file into smaller pieces (256KB seemed about right) and started flashing it by parts (8 parts). For this, you need to calculate the beginning area of the flash memory, and the length to program. With all the information you get with tflash, this is fairly easy.
Some more failures. Still dont know why, but after flashing part2 (256 to 512KB) i got some hangs in specific address. Tired, decided to go backwards (literally). Erased the flash, and started flashing from part 8 to 1.
It went smooth! No errors, about 560 seconds each part (something about 75 minutes total).
To confirm the procedure, made a wholeflash backup and compared it to the file… Damn. Differences. First difference occurred about 750KB from beggining.
If you check the addresses where the BSP or CFE is stored, you will realize that 750KB from the beggining is just past that. Im not going too write much about this, but it is important to know, CFE is the boot system used to boot linux (dd-wrt in this case), and BSP is the system used by linksys firmware based on VxWorks.
Taking that into account, i just rebooted the router. Lights went all on, then off…. Success !
Power light was blinking. That means firmware loading problem. Not that bad. Configured the computer to use 192.168.1.20 , and connected via WEB to 192.168.1.1. A simple page titled “Management Mode – Firmware Upgrade” asking me to select a file, appeared.
I went to Linksys.com, browsed for the latest firmware for this router (1.04.00) and selected it. Run!
A couple of minutes passed by, and the page asked me to reboot the router.
Normal boot !
We are back to the original firmware.
Utilities and files :
- tjtag v0.3 [ from : here ]
- Whole flash backup [ from : here ]
- Original Linksys Firmware 1.0.04US [ from : here ]
- Splitted Flash : Each of the files to flash manually and by segments of 256KB.
* (including bat files with the command line)
All the files here, were taken from the sites specified.
If you think i am violating some copyright, please write me.
Lot of time has passed since i released a stable version of mod_bw.
Stable as it is, it isn’t free of problems.
Frederik Temmermans contacted me a couple of weeks ago, and sent some errors he got compiling current version of mod_bw (0.8 as of now).
He was running MacOSX 10.5.7 with standar Apache 2.2.11.
When compiling normally using apxs, the module will be built and installed. But after starting apache, an error will appear :
httpd: Syntax error on line 54 of /private/etc/apache2/httpd.conf: Cannot load /usr/libexec/apache2/mod_bw.so into server: dlopen(/usr/libexec/apache2/mod_bw.so, 10): no suitable image found. Did find: /usr/libexec/apache2/mod_bw.so: mach-o, but wrong architecture
So…. There is a binary.. but for the wrong architecture.
As Mac’s nowadays are Intel based, to me it looks like it is a 32/64bits issue.
As MacOSX is a hybrid system running 32 and 64bits apps (since some time), looks like apache is a 64bit application :
G1X:mod_bw root# httpd -V Server version: Apache/2.2.11 (Unix) Server built: Feb 3 2009 01:54:45 Server's Module Magic Number: 20051115:21 Server loaded: APR 1.2.7, APR-Util 1.2.7 Compiled using: APR 1.2.7, APR-Util 1.2.7 Architecture: 64-bit Server MPM: Prefork threaded: no forked: yes (variable process count) G1X:mod_bw root# uname -a Darwin G1X.local 9.7.0 Darwin Kernel Version 9.7.0: Tue Mar 31 22:52:17 PDT 2009; root:xnu-1228.12.14~1/RELEASE_I386 i386
And it also seems that apxs is compiling a 32bit binary.
(G1X is my Asus G1 laptop running OSX. Sorry Apple, I know i should not do this.. but it was a quick test to help. If anyone wants to donate a MacBookPro…. :X)
Well, after realizing whats the problem, it is just a matter of adjusting some compiling flags.. Run apxs like this :
apxs -c -i -Wc,'-arch x86_64' -Wl,'-arch x86_64' mod_bw.c
And that’s it. You’ll have a 64bit module.
Did i said that’s it ?
Well.. Life is not an easy ride. After fixing this, Frederik had another issue. (I find this weird… i had a system setup to be similar to his, and i didn’t have this problem.)
If loading the module you get an error like this one :
httpd: Syntax error on line 117 of /private/etc/apache2/httpd.conf: Cannot load /usr/libexec/apache2/mod_bw.so into server: dlopen(/usr/libexec/apache2/mod_bw.so, 10): Symbol not found: _apr_atomic_add\n Referenced from: /usr/libexec/apache2/mod_bw.so Expected in: dynamic lookup
It is because that symbol (used in the module) is not in your current APR Lib version. I have seen this occur in some linux distros (but never happened to me… damn). When i first received an email regarding this bug, we came up with an easy fix, and it seemed to solve it. (did last a while…)
Well, to fix it, you need to locate and erase this lines from mod_bw.c
#if (APR_MAJOR_VERSION < 1) #define apr_atomic_inc32 apr_atomic_inc #define apr_atomic_dec32 apr_atomic_dec #define apr_atomic_add32 apr_atomic_add #define apr_atomic_cas32 apr_atomic_cas #define apr_atomic_set32 apr_atomic_set #endif
Compile again, and that's it. (this time for real).
In the next release (hope to be soon), i'll try to have this fixed once and for all.