Backup Linux embedded system firmware (Heden, Foscam, WRT..)

This post talk about a cheap Heden clone outdoor camera but should work on most Linux embedded systems.

Here the little story : A friend ask me to repair his bricked Heden cam copy (no-name). So let’s open it, find a serial port and look what’s going on. I used the bus-pirate of course. I discovered that only the bootloader is working, the whole flash seems empty.I searched a long time, and tried severals stuffs, but I was unable to find the right firmware (in the right format) for his no-name camera.

NetOS opened camera

So my friend sent the camera back (warranty), and receive a new one. Now, he ask me to backup the flash memory, to fix the problem if this occurs in a few months again.

The main issue is : The camera has no backup web interface, no MTD dump shell binary (nor ftp, scp..), and it’s not really easy to compile the mtd tools because the system has no library installed (only a few static binary files). I’m unable to backup the firmware throught the OS. Let’s try see the bootloader.

The bootloader has no backup firmware features, but it can dump the memory content (flash included), and it has a builtin “ls” like command that display base memory segments. With the simple “d 0xAAAA”, you can dump the memory at 0xAAAA address. Fine, I decided to write a little script that walk the memory, dump the content and rebuild the binary file.

#!/usr/bin/env python2
import serial,sys,string

log_file = None

def ser_open():
    ser = serial.Serial("/dev/ttyUSB0", 115200, timeout = 0.1)
    return ser

def log(line):
    l=string.split(line,' ')
    data='%s%s%s%s' % (l[1],l[2],l[4],l[5])
    for i in range(0,32,2):
        octet = int(data[i:i+2],16)
        log_file.write('%s' % chr(octet))

def dump(ser,addr):
    s = "d -s 0x%x\n" % addr
    ser.write(s)

    l=[]
    i = 0
    while 1:
        data = ser.read()
        if not data:break
        l.append(data)
        if (data=='\r'):
            s = string.join(l,'')
            if (s[0] == '['):
                log(s)
            l=[]

d = ser_open()
log_file = open('log.raw','a')

img_start = 0x7F0E0000
img_size = 0xC3C00

for i in range(img_start,img_start+img_size+0x100,0x100):
    dump(d,i)
    print "0x%x"% i

As you can see, this code isn’t really clean and well written, but it give me a nice binary file for a given offset and size. Simply dump the memory through serial port, do a little parsing, and store the result in binary file named log.raw.

I used this to backup the camera linux.bin file, and the romfs.img. Of course you can use this to dump the whole memory too. To check if the files are Ok, you can try to g-unzip the Linux Kernel, and mount the romfs.

To check the romfs, I simply mount it with : mount -t roomfs -o loop log.raw ./log

So now, I have a backup for this no-name camera, and next time the whole memory will drop, I will try to restore it ;).

This method seems really crude (and dirty), but it work without too much trouble, and can be tweaked for a lot of systems. It should work on every Linux embedded system with an dump memory feature in the bootloader (quite every one).

Enjoy memory ;)



Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>