Unpacking and repacking U-Boot uImage files
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.uImage Image Name: nova-installer-image-broadway-43 Created: Wed Dec 31 16:00:00 1969 Image Type: ARM Linux Multi-File Image (uncompressed) Data Size: 12566392 Bytes = 12271.87 kB = 11.98 MB Load Address: 0x00000000 Entry Point: 0x00000000 Contents: 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=2610004 2610004+0 records in 2610004+0 records out 2610004 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=2610080 9956376+0 records in 9956376+0 records out 9956376 bytes transferred in 168.836628 secs (58970 bytes/sec)
Let’s look at the kernel image header:
$ mkimage -l kernel.uImage Image Name: Linux-2.6.29-palm-shank Created: Wed Dec 31 16:00:00 1969 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 2609940 Bytes = 2548.77 kB = 2.49 MB Load Address: 0x00208000 Entry Point: 0x00208000
And the ramdisk image header:
$ mkimage -l ramdisk.uImage Image Name: ramdisk Created: Wed Dec 31 16:00:00 1969 Image Type: ARM Linux RAMDisk Image (uncompressed) Data Size: 9956312 Bytes = 9722.96 kB = 9.50 MB Load Address: 0x00000000 Entry Point: 0x00000000
Now let’s pluck off the 64-byte header from the ramdisk:
$ dd if=ramdisk.uImage of=ramdisk bs=64 skip=1 155567+1 records in 155567+1 records out 9956312 bytes transferred in 2.952196 secs (3372511 bytes/sec)
And examine it:
$ 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
Now extract it:
zcat ramdisk > nova-installer-image-broadway-4
And examine it again:
$ file nova-installer-image-broadway-4 nova-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-4 md0 $ 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=1 1+0 records in 1+0 records out 1048576 bytes transferred in 0.237938 secs (4406931 bytes/sec) $ ls /mnt bin dev garbage lib media opt sbin tmp var boot 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.uImage Image Name: ramdisk Created: Wed Jun 20 23:34:59 2012 Image Type: ARM Linux RAMDisk Image (uncompressed) Data Size: 11036471 Bytes = 10777.80 kB = 10.53 MB Load Address: 0x00000000 Entry 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.uImage Image Name: Linux-2.6.29-palm-shank Created: Wed Jun 20 23:40:05 2012 Image Type: ARM Linux Multi-File Image (uncompressed) Data Size: 13646551 Bytes = 13326.71 kB = 13.01 MB Load Address: 0x00000000 Entry Point: 0x00000000 Contents: 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:
[…] This should let us build a WebOS Doctor that does the complete upgrade to 2.2.4 in one step Unpacking and repacking U-Boot uImage files […]
[…] Mais informações sobre o header do uImage, leia este post: http://www.isysop.com/unpacking-and-repacking-u-boot-uimage-files/ […]
[…] Source: Unpacking and repacking U-Boot uImage files […]
[…] 3.) Use dd, remove the U-Boot header, and copy contents of U-Boot image to new boot and root images. (http://www.isysop.com/unpacking-and-repacking-u-boot-uimage-files/) […]
Thanks! Saved me hours of grief trying to load an image to the wrong memory location via JTAG.