As I tried instructions to install Linux on Amlogic S905 Android TV boxes yesterday, I wanted to extract kernel.img file found in Android firmware, but Google did not help that much until I found mkboot part of mkbootimg_tools scripts.
But first let’s see how kernel.img is created… Google provide a Python script called mkbootimg that combine the kernel image (e,.g. zImage), a rootfs/ramdisk and the device tree (DTB) file with a command line that looks like:
1 |
./mkbootimg --base=0 --kernel_offset=0x01080000 --kernel ${KERNEL} --ramdisk_offset=0x01000000 --ramdisk ./${ROOTFS} --second ${DTBFILE} --output ./kernel.img |
However, AFAIK the company does not provide a “unmkbootimg” script, and mkbootimg can only be used to create kernel.img, not decompile it. But that’s what mkboot does, and it works for kernel.img and recovery.img. Let’s retrieve the necessary files first:
1 |
git clone https://github.com/xiaolu/mkbootimg_tools |
mkboot is a bash script so we can use it right away:
1 2 3 4 5 6 7 8 9 10 11 |
cd mkbootimg_tools ./mkboot <Unpack and repack boot.img tool> ---------------------------------------------------------------------- Not enough parameters or parameter error! unpack boot.img & decompress ramdisk: mkboot [img] [output dir] mkboot boot.img boot20130905 Use the unpacked directory repack boot.img(img_info): mkboot [unpacked dir] [newbootfile] mkboot boot20130905 newboot.img |
So it can be used both for unpacking and repacking kernel.img to/from the output directory. Let’s run the command with an actual kernel.img file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
./mkboot kernel.img k1plus Unpack & decompress ../kernel.img to k1plus kernel : kernel ramdisk : ramdisk page size : 2048 kernel size : 7236663 ramdisk size : 4282196 second_size : 31763 base : 0x01078000 kernel offset : 0x00008000 ramdisk offset : 0xfff88000 second_offset : 0xffe88000 tags offset : 0xfef88100 cmd line : ramdisk is gzip format. Unpack completed. |
The script has indeed decompiled kernel.img with the kernel itself, the ramdisk (compressed and decompressed), and second.img that’s the DTB file. img_info contains the information shown during extraction above.
1 2 3 4 5 6 7 8 |
ls -l k1plus/ total 11364 -rw-rw-r-- 1 jaufranc jaufranc 250 ธ.ค. 7 10:22 img_info -rw-rw-r-- 1 jaufranc jaufranc 7236663 ธ.ค. 7 10:22 kernel drwxrwxr-x 18 jaufranc jaufranc 4096 ธ.ค. 7 10:22 ramdisk -rw-rw-r-- 1 jaufranc jaufranc 4282196 ธ.ค. 7 10:22 ramdisk.packed -rw-rw-r-- 1 jaufranc jaufranc 31763 ธ.ค. 7 10:22 second.img -rw-rw-r-- 1 jaufranc jaufranc 32768 ธ.ค. 7 10:22 second.img.tmp |
second.img and second.img.tmp files differ in size, so I ran through dtc to get the readable device tree file,. and the resulting files are identical:
1 2 3 |
dtc -I dtb second.img -O dts -o k1plus.dtd dtc -I dtb second.img.tmp -O dts -o k1plus.dtd.tmp diff k1plus.dtd k1plus.dtd.tmp |
So the tmp files must have had some padding, that the script stripped to create second.img.
In theory, you can change the kernel files, randisk or device tree, and repack everything with:
1 |
./mkboot k1plus kernelimg_new.img |
but it did not quite work here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
mkbootimg from k1plus/img_info. board : k1plus kernel : kernel ramdisk : new_ramdisk page size : 2048 kernel size : 7236663 ramdisk size : 4282403 second_size : 31763 base : 0x01078000 kernel offset : 0x00008000 ramdisk offset : 0xfff88000 second_offset : tags offset : 0xfef88100 cmd line : ramdisk is gzip format. Traceback (most recent call last): File "/home/jaufranc/edev/mini_mx/mkbootimg_tools/mkbootimg", line 140, in <module> main() File "/home/jaufranc/edev/mini_mx/mkbootimg_tools/mkbootimg", line 133, in main img_id = write_header(args) File "/home/jaufranc/edev/mini_mx/mkbootimg_tools/mkbootimg", line 57, in write_header args.pagesize)) # flash page size we assume struct.error: 'I' format requires 0 <= number <= 4294967295 Make boot.img Error! pls check img_info file. ... |
If we look a the first ./mkbootimg command in this post we can see some different offset in the decompile image, so I changed img_info as per the first command line, with base=0, kernel_offset=0x01080000, and ramdisk_offset=0x01000000, and it all worked out OK:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
./mkboot k1plus kernelimg_new.img mkbootimg from k1plus/img_info. kernel : kernel ramdisk : new_ramdisk page size : 2048 kernel size : 7236663 ramdisk size : 4282403 second_size : 31763 base : 0 kernel offset : 0x01080000 ramdisk offset : 0x01000000 second_offset : tags offset : 0xfef88100 cmd line : ramdisk is gzip format. Kernel size: 7236663, new ramdisk size: 4282403, kernelimg_new.img: 11556864. kernelimg_new.img has been created. |
Jean-Luc started CNX Software in 2010 as a part-time endeavor, before quitting his job as a software engineering manager, and starting to write daily news, and reviews full time later in 2011.
Support CNX Software! Donate via cryptocurrencies, become a Patron on Patreon, or purchase goods on Amazon or Aliexpress
“So the tmp files must have had some padding, that the script stripped to create second.img.”
Amlogic ditched their dtd format and they are using dts standard kernel format on 3.14 kernel. There are couple of dts files included in final eg p200 board dts file. These included files contain default values which are not board specific. I assume (didn’t check) that .tmp or first file you have is that 1st part with included file(s).