When I first opened the file in vim and used the handy xxd command to see the hexdump (:%!xxd, which also works magically on Windows), it felt a little disorienting. However, there are certain things that I knew would be in the firmware update image. Since the Galileo board is booting from the device, there has to be some sort of bootloader in there (grub legacy, as seen before) as well as the bootloader configuration information (grub.conf). I also know that the Linux kernel image and the initramfs image must also be included. In the bootlog, as Linux kernel boots, it helpfully prints the following which gives me the kernel and initramfs sizes.
That's more than enough to start some spelunking. Since it's easiest to find strings, and I know grub.conf is a simple text file, I started by looking for the title of the boot targets like 'Clanton' and 'SVP' - Voila! At 0x06a3990, you see the contents of grub.conf that corresponds to the boot menu that we see in the bootlog.[Linux-EFI SPI, setup=0x107f, size=0x1e0da0] [Initrd SPI, addr=0xdb5f000, size=0x298a13]
|Claton SVP kernel!|
Linux kernel image also has some unique features - I know that it'll start with "MZ" as its magic number and will have some blurb about needing a bootloader. By looking for that string, I found what looks very much like the executable kernel image at 0x04be990.
|Start of the Linux Kernel|
As I was browsing around, I noticed a certain pattern appearing close to start of the two sections above. The entire update image itself starts with header string with the string "HSC_", and this header appears 9 times throughout the file aligned at 16 byte boundaries. More importantly, this appears exactly 1024 bytes before the two sections that I've found above. Using this big hint, I looked at the different sections and tried to figure out what they might be - initramfs was easy, as it's the only region big enough to fit the file size above. Grub EFI executable was also easy to determine, but the first sets of regions are a mystery for now.
Now that we have the regions, we can extract the kernel and initramfs filesystem with a simple dd commands0x0000000 (size 0x0021500) - ??? looks like some sort of table 0x0021500 (size 0x0062090) - ??? looks like an executable 0x0083590 (size 0x0040000) - ??? looks like an executable 0x00c3590 (size 0x0040000) - ??? looks like an executable 0x0103590 (size 0x0121000) - ??? looks like an executable 0x0224590 (size 0x029A000) - initramfs 0x04be590 (size 0x01E5000) - Kernel Image 0x06a3590 (size 0x0001000) - grub.conf 0x06a4590 (size 0x0051000) - grub.efi executable
Extracting the rootfs from initramfs is pretty straight forward from this point$ dd if=sysimage-galileo-1.0.2.cap of=initramfs.lzma bs=1 skip=2247056 count=2722323 $ dd if=sysimage-galileo-1.0.2.cap of=vmlinux bs=1 skip=4974992 count=1986560
And now you have the exact filesystem that you get within Galileo after Linux boots up. We can even see the firmware flashing code in opt/cln/galileo/start_spi_upgrade.sh! And just for fun, let's try booting the Kernel and initramfs on QEMU :-)$ mkdir rootfs $ cp initramfs.lzma rootfs/ $ cd rootfs $ unxz initramfs.lzma $ cpio -ivd < initramfs
After that, you need to switch QEMU to serial0 by pressing Ctrl + Alt + 3, but once done, you see the kernel booting on a completely different QEMU system!$ qemu-system-i386 -kernel vmlinux -initrd initramfs.lzma -append ="root=/dev/ram0 console=uart earlyprintk=serial apic=debug rw"
|It's booting up!|