Scripts for working with uImage files

I’ve created a set of python scripts for working with U-Boot image files when phone-hacking.  The first script is similar to the U-Boot mkimage tool, only it adds the ability to extract data from existing images.

The next two scripts are particularly for WebOS and meta doctor.  These scripts are similar to diff and patch, but they are intended to distribute change instructions for ramdisk image files.  More than just a binary patch, these utilities introduce what I call a copy-patch.  A copy-patch contains instructions for merging one binary file into another without actually containing the contents of either file.  This allows the patch to be distributed without violating the IP rights of the owners of the binary files.

Downloads

ramdiskpatch.py

ramdiskdiff.py

uImage.py

ramdisk.copyPatch

Usage examples

Words often don’t explain as well as examples, so I’ll show an example of updating the TP and A6 firmware in a WebOS 2.1.2 image.  Note that the patch file does not contain the firmware, so I will have to supply the patch tool with the location of the files I intend to graft into the root file system ramdisk image.

 

uImage.py usage and listing image information:

# python uImage.py -h
Usage:
        uImage.py -l image
        uImage.py -c [options] image
        uImage.py -x image
        uImage.py -h

Options:
  -h, --help         show this help message and exit
  -l                 list image contents
  -c                 create new image
  -x                 extract image contents

  Creation Options:
    -c -A arch -O os -T type -C comp -a addr -e ep -n name -d
    data_file[:data_file...] image

    -A ARCHITECTURE  set architecture to 'arch'
    -O OSTYPE        set operating system to 'os'
    -T IMAGETYPE     set image type to 'type'
    -C COMPRESSION   set compression to 'comp'
    -a LOADADDR      iset load address to 'addr'
    -e ENTRYADDR     iset entry point to 'ep'
    -n IMAGENAME     set image name to 'name'
    -d FILESPEC      image data from 'datafile'
#
# python uImage.py -l nova-installer-image-broadway.uImage
Image name:     nova-installer-image-broadway-43
Created:        Wed Dec 31 16:00:00 1969
Image type:     ARM Linux Multi-File (uncompressed)
Data size:      12566392 Bytes
Load Address:   0x000000
Entry Point:    0x000000
Header CRC:     0xcf936b92 ... OK
Data CRC:       0x2defc1cd
Contents:
   Image 0: 2610004 bytes
   Image 1: 9956376 bytes

Multi-File Image 0: Header
--------------------------
Image name:     Linux-2.6.29-palm-shank
Created:        Wed Dec 31 16:00:00 1969
Image type:     ARM Linux Kernel (uncompressed)
Data size:      2609940 Bytes
Load Address:   0x208000
Entry Point:    0x208000
Header CRC:     0xfd901980 ... OK
Data CRC:       0xffbe63e6

Multi-File Image 1: Header
--------------------------
Image name:     ramdisk
Created:        Wed Dec 31 16:00:00 1969
Image type:     ARM Linux RAMDisk (uncompressed)
Data size:      9956312 Bytes
Load Address:   0x000000
Entry Point:    0x000000
Header CRC:     0xccd15a95 ... OK
Data CRC:       0xa6d2f9e9

 

Extracting images:

# python uImage.py -x nova-installer-image-broadway.uImage
Linux-2.6.29-palm-shank.uImage
Linux-2.6.29-palm-shank
ramdisk.uImage
ramdisk

Notice that there were 4 files extracted.  Let me explain:  The main uImage file is a multi-file type that contains two files:  A kernel uImage and a ramdisk uImage.  Each of these two files is also a uImage, so uImage.py extracted their contents as well.  We are left with 4 files:  the ones with .uImage extensions have uImage headers.  The other two are the raw data contents.

Now let’s verify that the ramdisk file is a gzipped EXT2 image and then apply the copy-patch:

# file ramdisk
ramdisk: gzip compressed data, was "nova-installer-image-broadway-4", from Unix, last modified: Fri Apr 15 12:01:11 2011, max compression

# zcat ramdisk > nova-installer-image-broadway-4

# file nova-installer-image-broadway-4
nova-installer-image-broadway-4: Linux rev 0.0 ext2 filesystem data

# python ramdiskpatch.py nova-installer-image-broadway-4 2.2.4/usr/lib/ipkg/info/a6-firmware.control 2.2.4/usr/lib/ipkg/info/a6-firmware.md5sums 2.2.4/usr/lib/ipkg/info/pma6updater.control 2.2.4/usr/lib/ipkg/info/pma6updater.md5sums 2.2.4/usr/lib/ipkg/info/pmtpupdater.control 2.2.4/usr/lib/ipkg/info/pmtpupdater.md5sums 2.2.4/usr/lib/ipkg/info/pmtpupdater.list 2.2.4/lib/firmware/a6_firmware.txt 2.2.4/lib/firmware/cy8ctma300e.fw 2.2.4/lib/firmware/cy8ctma300e.ver 2.2.4/usr/bin/PmTpUpdater 2.2.4/usr/bin/PmTpWhich 2.2.4/usr/bin/PmA6Updater 2.2.4/usr/bin/catnip < ramdisk.copyPatch
Patching-in "2.2.4/usr/lib/ipkg/info/a6-firmware.control" .Done.
Patching-in "2.2.4/usr/lib/ipkg/info/a6-firmware.md5sums" .Done.
Patching-in "2.2.4/usr/lib/ipkg/info/pma6updater.control" .Done.
Patching-in "2.2.4/usr/lib/ipkg/info/pma6updater.md5sums" .Done.
Patching-in "2.2.4/usr/lib/ipkg/info/pmtpupdater.control" .Done.
Patching-in "2.2.4/usr/lib/ipkg/info/pmtpupdater.md5sums" .Done.
Patching-in "2.2.4/usr/lib/ipkg/info/pmtpupdater.list" .Done.
Patching-in "2.2.4/lib/firmware/a6_firmware.txt" ..............................................Done.
Patching-in "2.2.4/lib/firmware/cy8ctma300e.fw" ....................................................Done.
Patching-in "2.2.4/lib/firmware/cy8ctma300e.ver" .Done.
Patching-in "2.2.4/usr/bin/PmTpUpdater" ......Done.
Patching-in "2.2.4/usr/bin/PmA6Updater" .............Done.
Patching-in "2.2.4/usr/bin/PmTpWhich" .Done.
Patching-in "2.2.4/usr/bin/catnip" .........................................................................................Done.

Performing binary patches to file system structure ..............................................................................................................................................................................................................................................................................................................................................................................................................................................................
Patch successful!  md5: 1cdb4f76aeacc0ba1760cc6496137e61

 

Now we’ll re-compress the ramdisk, and make it into a uImage:

# gzip nova-installer-image-broadway-4

# python uImage.py -c -A arm -T ramdisk -C none -n ramdisk -d nova-installer-image-broadway-4.gz ramdisk.uImage
Image name:     ramdisk
Created:        Sun Jun 24 04:01:21 2012
Image type:     ARM Linux RAMDisk (uncompressed)
Data size:      10051920 Bytes
Load Address:   0x000000
Entry Point:    0x000000
Header CRC:     0x1cf594e7 ... OK
Data CRC:       0xcf80cb73

Now we re-combine the extracted kernel uImage and the ramdisk uImage:

# python uImage.py -c -A arm -T multi -C none -n Linux-2.6.29-palm-shank -d Linux-2.6.29-palm-shank.uImage:ramdisk.uImage my-install-image.uImage
Image name:     Linux-2.6.29-palm-shank
Created:        Sun Jun 24 04:04:59 2012
Image type:     ARM Linux Multi-File (uncompressed)
Data size:      12662000 Bytes
Load Address:   0x000000
Entry Point:    0x000000
Header CRC:     0x71281fb4 ... OK
Data CRC:       0x9f1b4262
Contents:
   Image 0: 2610004 bytes
   Image 1: 10051984 bytes

Multi-File Image 0: Header
--------------------------
Image name:     Linux-2.6.29-palm-shank
Created:        Wed Dec 31 16:00:00 1969
Image type:     ARM Linux Kernel (uncompressed)
Data size:      2609940 Bytes
Load Address:   0x208000
Entry Point:    0x208000
Header CRC:     0xfd901980 ... OK
Data CRC:       0xffbe63e6

Multi-File Image 1: Header
--------------------------
Image name:     ramdisk
Created:        Sun Jun 24 04:01:21 2012
Image type:     ARM Linux RAMDisk (uncompressed)
Data size:      10051920 Bytes
Load Address:   0x000000
Entry Point:    0x000000
Header CRC:     0x1cf594e7 ... OK
Data CRC:       0xcf80cb73

And that’s it!