Splitting and Packing Android Boot images
I have tested these programs using factory images for Nexus 4, 5 and 7, but do not warrant their use. Use of these programs will invalidate any warranty for your device and may possibly brick your device.
USE AT YOUR OWN RISK !
spbootimg.c (split boot image) and pkbootimg.c (pack boot image) are derived from the Android 4.4 version of the program ~/android/source/system/core/mkbootimg/mkbootimg.c.
I learned about unpacking/repacking ramdisks from HOWTO: Unpack, Edit, and Re-Pack Boot Images
These two programs are intended to be used together when modifying an existing boot image. I have used these programs to root Nexus factory images by modifying default.prop in the ramdisk to set ro.secure=0 and ro.adb.secure=0.
usage: spbootimg -i|--input
spbootimg splits an Android boot image file into separate files:
- <bootimg-filename>-kernel - kernel
- <bootimg-filename>-first-ramdisk - ramdisk
- <bootimg-filename>-second-ramdisk - only created if it existed in the input boot image file.
- <bootimg-filename-header> - text file containing constants discovered in the boot image
usage: pkbootimg --kernel --kernel-addr --ramdisk --ramdisk-addr [ --second <2ndbootloader-filename>] [ --cmdline ] [ --board ] [ --pagesize ] --second-addr --tags-addr -o|--output
pkbootimg takes the output of spbootimg: a kernel file, a ramdisk file, an optional ramdisk file; and using the command line, board, page size and address information discovered in the original boot image, packs them into a new boot image which can be flashed onto a device using fastboot.
pkbootimg is used instead of the 'official' Android mkbootimg since mkbootimg requires knowledge of the base address used as well as the fact that, for Nexus devices at least, some boot image files do not follow the base+offset convention for all addresses. pkbootimg instead uses the raw addresses detected by spbootimg and is therefore independent of any choice of base address or inconsistency between the boot image's addresses and the base + offset address convention.
Note that all of the address parameters including --second-addr are required even if there was no second ramdisk.
NOTE|WARNING You should check if spbootimg and pkbootimg work for your boot image, by re-packing the output of spbootimg and checking if the new boot image file is identical to the original boot image. If the two boot image files are different, then there is a problem and you should not use spbootimg and pkbootimg for your boot image file.
For example, for a boot image with a single ramdisk such as a Nexus 4 Mako build
spbootimg -i boot.img
will for create:
- boot.img-kernel
- boot.img-first-ramdisk
- boot.img-header
where boot.img-header contains:
Assumptions kernel_offset = 0x8000 ramdisk_offset = 0x1000000 second_offset = 0xF00000 tags_offset = 0x100 Detected values kernel_size = 5677280 kernel_addr = 0x80208000 ramdisk_size = 357798 ramdisk_addr = 0x81800000 second_size = 0 second_addr = 0x81100000 tags_addr = 0x80200100 page_size = 2048 name/board = cmdline = console=ttyHSL0,115200,n8 androidboot.hardware=mako lpj=67677 Computed values kernel_base = 0x80200000 ramdisk_base = 0x80800000, kernel_base - ramdisk_offset=0xFFA00000 second_base = 0x80200000, kernel_base - second_offset=0x0 tags_base = 0x80200000, kernel_base - tags_offset = 0x0 WARNING! base addresses do not match!
To check if spbootimg and pkbootimg work, re-pack the output of spbootimg and check if the new boot image file is identical to the original boot image. If it is not, then there is a problem and you should not use spbootimg and pkbootimg for your boot image file.
pkbootimg --kernel boot.img-kernel \ --kernel-addr 0x80208000 \ --ramdisk boot.img-first-ramdisk \ --ramdisk-addr 0x81800000 \ --cmdline 'console=ttyHSL0,115200,n8 androidboot.hardware=mako lpj=67677' \ --second-addr 0x81100000 \ --tags-addr 0x80200100 \ --output new-boot.img
If you wish to modify the ramdisk for example in order to root the device, you will need to unpack the ramdisk for modifcation:
mkdir ramdisk cd ramdisk gzip -dc ../boot.img-first-ramdisk | cpio -i # edit default.prop... # On Linux you can find . | cpio -o -H newc | gzip > ../ramdisk-new.gz # On OSX you can use the mkbootfs program in ~/android/source/out/host/ cd .. mkbootfs ./ramdisk | gzip > ramdisk-new.gz pkbootimg --kernel boot.img-kernel \ --kernel-addr 0x80208000 \ --ramdisk ramdisk-new.gz \ --ramdisk-addr 0x81800000 \ --cmdline 'console=ttyHSL0,115200,n8 androidboot.hardware=mako lpj=67677' \ --second-addr 0x81100000 \ --tags-addr 0x80200100 \ --output new-boot.img
fastboot allows you to boot from a temporary boot image from a kernel and ramdisk using
fastboot boot boot.img-kernel ramdisk.img
however this may not work if the default values used for the addresses, command line, board etc do not work for your device.
WARNING - you will invalidate your warranty and potentially brick your device.
USE AT YOUR OWN RISK !
To permanently flash your new boot image to the device:
fastboot flash boot new-boot.img fastboot reboot
Set up your build environment according to Android's Downloading and Building instructions.
pkbootimg requires the library libmincrypt.a. The easiest (though slowest) means of obtaining libmincrypt.a is to build Android prior to attempting to compile spbootimg.c or pkbootimg.c. It may be possible to only build the system/core directory though I haven't tested it.
You will need to find the location of your libmincrypt.a directory. On Linux, mine
was located in ~/android/source//out/host/linux-x86/obj/STATIC_LIBRARIES/libmincrypt_intermediates/
.
Either copy or symlink spbootimg.c and pkbootimg.c into the mkbootimg directory in your Android source, e.g. ~/android/source/system/core/mkbootimg/.
Compile and place the binaries in your ~/bin/ directory:
gcc -m32 -o ~/bin/pkbootimg -I ../include/ pkbootimg.c ~/android/source/out/host/linux-x86/obj/STATIC_LIBRARIES/libmincrypt_intermediates/libmincrypt.a
gcc -m32 -o ~/bin/spbootimg spbootimg.c