Dumping flash from a WAG45G

Back to homepage

It was lying in storage for quite a long time. I got it primarily because it's the same series as the WRT54GL, my favourite router. It was quite cheap. ADSL gateway was no use to me, as I dont have any ADSL drop, but I felt I could play with it.

The internals

It uses a Samsung S3C2510, which is arm940t based CPU. Wireless is done by a PCMCIA adapter (not in the picture). There's a standard 2x10 ARM JTAG header (CN2) and a UART (CN9). There is a 2M flash connected to the CPU over CFI, and that's what we're after. However, it's very tricky to get the flash contents...

OpenOCD doesn't support the arm940t family but it seems that treating it as arm920t works well enough for my application.

UART, JTAG connections and OpenOCD config

I used a BusPirate as a JTAG adapter, for which it's pretty darn good. My OpenOCD config was split between two .cfg files: one for setting up the BusPirate and one for the CPU.

BusPirate config is as follows:

source [find interface/buspirate.cfg]

buspirate_vreg 0
buspirate_mode open-drain
buspirate_pullup 1
buspirate_port /dev/ttyUSB0
#buspirate_speed normal
buspirate_speed fast
buspirate_mode open-drain
reset_config srst_only

And the CPU config file, as found online with a little modification is as shown:

if { [info exists CHIPNAME] } {
} else {
     set _CHIPNAME s3c2510a
if { [info exists ENDIAN] } {
     set _ENDIAN $ENDIAN
} else {
     set _ENDIAN little
if { [info exists CPUTAPID] } {
} else {
    set _CPUTAPID 0x1094009d
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x01 -irmask 0x03 -expected-id $_CPUTAPID


#  target create $_TARGETNAME arm9tdmi -endian $_ENDIAN -chain-position $_TARGETNAME -variant arm940t
target create $_TARGETNAME arm920t -endian $_ENDIAN -chain-position $_TARGETNAME
$_TARGETNAME configure -work-area-phys 0x40000000 -work-area-size 0x4000 -work-area-backup 0
flash bank $_CHIPNAME.extnorflash cfi	0x00000000 0x00200000 2 2 $_TARGETNAME

s3c2510a.cpu arm7_9 dcc_downloads enable

I had to set proper flash size (after being warned by flash probe 0). I also enabled DCC downloads - thats the first important thing! (not related to IRC DCC)

Both CN2 and CN8 were unpopulated. I had to solder the pins myself

As for the UART connection, there's a console port at 115200 8n1 baud. Pinout below, (pin 1 marked on silkscreen with the arrow):

|1 |3v3
|2 |TxD
|3 |RxD
|4 |???
|5 |GND
|6 |GND

The JTAG connections are as follows:

MOSI -> TDI   [  5]
MISO -> TDO   [ 13]
CLK  -> TCLK  [  9]
CS   -> TMS   [  7]
AUX  -> RESET [ 15]
VPU  -> VCC   [  2]
GND  -> GND   [any]

The console plays a crucial part in the flash dumping operation - we need it to disable the watchdog timer. Why? Because of the way it works, and the way OpenOCD dumps flash.

A WDT, short for watchdog timer, is a peripheral of modern CPUs that is designed to prevent lockups. It's implemented as a timer that runs in the background. In a typical situation the main application periodically notifies the WDT, either by clearing a bit in a register, or some other way, that it's running. If it fails to do so in a predefined amount of time, the WDT kicks in and resets the CPU.

In order to extract the flash image, OpenOCD uploads and executes a small flash transfer program to the target. Now if you leave the WDT (watchdog) runing, it will keep resetting the CPU - as the transfer program isn't periodically notifying the WDT that, it's in fact, not frozen.

Luckily the console allows us to disable the WDT

Dumping procedure

  1. Turn on the router
  2. Wait for the CON> prompt at the boot console - you might have to hit enter for it to appear. Enter wdt to disable the watchdog:
    Watch Dog off 
  3. Start OpenOCD:
    openocd -f buspirate.cfg -f samsung.cfg
    and telnet 4444 in another terminal. For some reason the router fails to boot up if OpenOCD is running. Make sure DCC transfers are enabled.
    $ telnet localhost 4444
    Connected to localhost.
    Escape character is '^]'.
    Open On-Chip Debugger
    > halt
    target halted in ARM state due to debug-request, current mode: User
    cpsr: 0x80000010 pc: 0x0000cd68
    MMU: disabled, D-Cache: enabled, I-Cache: disabled
    > targets
        TargetName         Type       Endian TapName            State       
    --  ------------------ ---------- ------ ------------------ ------------
     0* s3c2510a.cpu       arm920t    little s3c2510a.cpu       halted
  4. Now you can dump the flash with:
    > dump_image linksys.bin 0x00000000 0x00200000

Enjoy. You might want to run strings against the binary to verify it's correct. Besides that, the CPU is pretty much useless. It's an old ARM (ARMv4), no MMU (just some rudimentary 8 segment protection circuitry). Analyzing the binary with binwalk didnt even yield any filesystems embedded inside. There is no operating system running on the router. The image has bits of HTML scattered throughout. The copytight string dates the software to 2001.

Other notes

| || | |'-'|            |       |   |   |
|    '-'   |            |       |   |   |
|          |____________|       '---'   |
|          _____________         ___    |
|      _  |_____________|       |   |   |
|     / \   ___                 '---'   |
|     \_/  |   |                || ||   |
|| :::     '---'                |'_'|   |
||     _____                            |
|  #: |     |        ______ o      *    |
|  #: |     | _     |      |          []|
|  #: |_____|| |    |      |       *   *|
|  #:        | |    |      |     ___    |
|  #:        '-'    '______'    |   |   |
|#   _  _  _                o   '---'   |
|#  / \/ \/ \                        <> |
|#  \_/\_/\_/                           |

I made an asciiart of the board. Isn't it cool?

Serial bootlog (until the CON> prompt)

------- START AP --- IMG = 41AL HW = V1.1----
ADSL:download init code                      
 write jump command with address=0x8000000
got ACT:Init code OK                      
ADSL:download init code OK
ADSL:download runtime code
 write jump command with address=0x0
got ACT:Modem code OK               
ADSL:download showtime code OK
utopia para(Level:1,AddrFast:1,AddrInterl:1)-- ok
function code(0xa1)-- ok                         
vendorID([0][49][54][43]) ok
SW Feature Code(0x12)-- ok  
write Tx Gain Offset(0x0)--ok
Target Noise Margin Offset(0xff)--ok
Max Bits/Tone Limit(0xe)--ok        
Rx Gain Offset(0x0)--ok     
write open command(0x3)--ok
open command ok            
------- START watchdog timer----
ST version is 02(HEX)
NV offset at 44891

I also found an unpopulated USB socket. Maybe it's used in another model?

I am not bound by any subscriber agreement regarding this ADSL gateway

Back to homepage