Background:

u-boot uImage files have a 64-byte header defined in image.h as follows:

#define IH_MAGIC    0x27051956    /* Image Magic Number     */#define IH_NMLEN    32            /* Image Name Length      */typedef struct image_header {    uint32_t    ih_magic;         /* Image Header Magic Number */    uint32_t    ih_hcrc;          /* Image Header CRC Checksum */    uint32_t    ih_time;          /* Image Creation Timestamp  */    uint32_t    ih_size;          /* Image Data Size           */    uint32_t    ih_load;          /* Data     Load  Address    */    uint32_t    ih_ep;            /* Entry Point Address       */    uint32_t    ih_dcrc;          /* Image Data CRC Checksum   */    uint8_t     ih_os;            /* Operating System          */    uint8_t     ih_arch;          /* CPU architecture          */    uint8_t     ih_type;          /* Image Type                */    uint8_t     ih_comp;          /* Compression Type          */    uint8_t     ih_name[IH_NMLEN];    /* Image Name            */} image_header_t;

According to the u-boot README in the section “More About U-Boot Image Types”:

“Multi-File Images” start with a list of image sizes, each
image size (in bytes) specified by an “uint32_t” in network
byte order. This list is terminated by an “(uint32_t)0″.
Immediately after the terminating 0 follow the images, one by
one, all aligned on “uint32_t” boundaries (size rounded up to
a multiple of 4 bytes).

 

Install uboot-mkimage from ports:

$ cd /usr/ports/devel/u-boot$ make install clean

List image header:

$ mkimage -l nova-installer-image-broadway.uImageImage Name:   nova-installer-image-broadway-43Created:      Wed Dec 31 16:00:00 1969Image Type:   ARM Linux Multi-File Image (uncompressed)Data Size:    12566392 Bytes = 12271.87 kB = 11.98 MBLoad Address: 0x00000000Entry Point:  0x00000000Contents:   Image 0:  2610004 Bytes = 2548 kB = 2 MB   Image 1:  9956376 Bytes = 9723 kB = 9 MB

This image contains two files, so it is a multi-file image.  To extract the two child image files, we must first chop off or skip over the 64-byte header + 4-byte image 0 size + 4 byte image 1 size + 4 byte null terminator = first 76 bytes.  Next we’ll extract Image 0  (2610004 bytes long in this example) and image 1 (9956376 bytes long in this example). Note that these two files are also uImage files!

Skip first 76 bytes and extract length of first image:

$ dd if=nova-installer-image-broadway.uImage of=kernel.uImage bs=1 skip=76 count=26100042610004+0 records in2610004+0 records out2610004 bytes transferred in 46.503855 secs (56124 bytes/sec)

Now I’ll skip 76 bytes + the size of the first image to get the second image:

$ dd if=nova-installer-image-broadway.uImage of=ramdisk.uImage bs=1 skip=26100809956376+0 records in9956376+0 records out9956376 bytes transferred in 168.836628 secs (58970 bytes/sec)

Let’s look at the kernel image header:

$ mkimage -l kernel.uImageImage Name:   Linux-2.6.29-palm-shankCreated:      Wed Dec 31 16:00:00 1969Image Type:   ARM Linux Kernel Image (uncompressed)Data Size:    2609940 Bytes = 2548.77 kB = 2.49 MBLoad Address: 0x00208000Entry Point:  0x00208000

And the ramdisk image header:

$ mkimage -l ramdisk.uImageImage Name:   ramdiskCreated:      Wed Dec 31 16:00:00 1969Image Type:   ARM Linux RAMDisk Image (uncompressed)Data Size:    9956312 Bytes = 9722.96 kB = 9.50 MBLoad Address: 0x00000000Entry Point:  0x00000000

Now let’s pluck off the 64-byte header from the ramdisk:

$ dd if=ramdisk.uImage of=ramdisk bs=64 skip=1155567+1 records in155567+1 records out9956312 bytes transferred in 2.952196 secs (3372511 bytes/sec)

And examine it:

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

Now extract it:

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

And examine it again:

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

So it’s an ext2 filesystem.  Let’s mount it under FreeBSD:

$ kldload ext2fs$ mdconfig -a -t vnode -f nova-installer-image-broadway-4md0$ mount -t ext2fs /dev/md0 /mnt

Let’s add a file full of random garbage just for fun:

$ dd if=/dev/random of=/mnt/garbage bs=1M count=11+0 records in1+0 records out1048576 bytes transferred in 0.237938 secs (4406931 bytes/sec)$ ls /mntbin        dev        garbage    lib        media      opt        sbin       tmp        varboot       etc        home       md5sums.gz mnt        proc       sys        usr

Now it’s time to unmount the file and package everything back together:

$ umount /mnt$ mdconfig -d -u 0

Don’t forget to gzip the ramdisk image…

$ gzip nova-installer-image-broadway-4

First create the ramdisk uImage:

$ mkimage -A arm -T ramdisk -C none -n ramdisk -d nova-installer-image-broadway-4.gz ramdisk.uImageImage Name:   ramdiskCreated:      Wed Jun 20 23:34:59 2012Image Type:   ARM Linux RAMDisk Image (uncompressed)Data Size:    11036471 Bytes = 10777.80 kB = 10.53 MBLoad Address: 0x00000000Entry Point:  0x00000000

Now combine the kernel image and ramdisk image into the final one:

$ mkimage -A arm -T multi -C none -n Linux-2.6.29-palm-shank -d kernel.uImage:ramdisk.uImage nova-installer-image-broadway.uImageImage Name:   Linux-2.6.29-palm-shankCreated:      Wed Jun 20 23:40:05 2012Image Type:   ARM Linux Multi-File Image (uncompressed)Data Size:    13646551 Bytes = 13326.71 kB = 13.01 MBLoad Address: 0x00000000Entry Point:  0x00000000Contents:   Image 0:  2610004 Bytes = 2548 kB = 2 MB   Image 1: 11036535 Bytes = 10777 kB = 10 MB

Note how the overall image size and image 1 size are 1MB larger than the original from the beginning.

 

Now let’s test it with novacom.  Restart the phone and hold the volume-up key to enter bootie the bootloader.  now:

novacom boot mem:// < nova-installer-image-broadway.uImage

 

Wait a few seconds, then launch novaterm and verify that we booted to the new ramdisk with the 1M garbage file: