Unpack boot.img
Get android_bootimg_tools
and extract to ~/.local/bin
:
wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/android-serialport-api/android_bootimg_tools.tar.gz /tmp/tools.tar.gz
tar xzvf /tmp/tools.tar.gz -C ~/.local/bin/
Make sure ~/.local/bin
is in your PATH
.
You will now have the mkbootimg
and unpackbootimg
programs available.
Copy the boot.img you want to disect into your local folder and run
mkdir boot/ && unpackbootimg -i boot.img -o boot/
You will now have the following files inside the boot/
folder:
boot.img-base
boot.img-cmdline
boot.img-pagesize
boot.img-ramdisk.gz
boot.img-zImage
The boot.img-zImage
file is the kernel.
Source: stackoverflow.
Unpack ramdisk
This is only necessary if you want to change files inside your boot.img. If you only want to use a different kernel, you can skip this step.
cd
into boot/
and unpack the ramdisk:
gunzip --to-stdout --uncompress boot.img-ramdisk.gz | cpio --extract \
--make-directories --no-absolute-filenames
To re-pack the cpio archive, move the rootfs files into a subdirectory and run the following from there:
find . | cpio -o -H newc > ../boot.img-ramdisk
The -H newc
option creates the SV4 archive type.
Then go up one directory and gzip
-compress the archive:
gzip boot.img-ramdisk
The ramdisk has a special format named cpio
. More information on
Wikipedia and the manpage.
The exact format of the cpio
archive is “SV4 with no CRC”. You can verify the
archive type for future Android versions by doing:
$ gunzip --uncompress boot.img-ramdisk.gz
$ file boot.img-ramdisk
# boot.img-ramdisk: ASCII cpio archive (SVR4 with no CRC)
Re-pack boot.img
If you unpacked your ramdisk, first re-create a cpio archive and gzip-compress it again, see the previous step.
Use mkbootimg
with the appropriate flags. To find out the values for
cmdline
, base
and pagesize
, take a look at the generated boot.img-*
files, e.g. boot.img-base
should contain a number like 80000000
.
mkbootimg \
--cmdline "$(cat boot.img-cmdline)" \
--base "$(cat boot.img-base)" \
--pagesize "$(cat boot.img-pagesize)" \
--ramdisk "boot.img-ramdisk.gz" \
--kernel "boot.img-zImage" \
-o boot-repacked.img
For newer devices, the bootloader expects you to set an OS version and a security patch level in the bootimage. These values should match the system or vendor image values. The patch level corresponds to the AOSP Security bulletins, e.g. 2020-06-05.
export OS_VERSION=10
export OS_PATCH_LEVEL='2020-06-05'
mkbootimg \
--cmdline
--id \
[...] \
--os_version $OS_VERSION \
--os_patch_level $OS_PATCH_LEVEL
-o boot-repacked.img
If you are constructing a boot image from scratch, you also need to set kernel
tags offset and ramdisk offset, which can be taken from the device
BoardConfig.mk
or PlatformConfig.mk
.
export BOARD_KERNEL_TAGS_OFFSET=0x01E00000
export BOARD_RAMDISK_OFFSET=0x02000000
mkbootimg \
[...] \
--ramdisk_offset $BOARD_RAMDISK_OFFSET \
--tags_offset $BOARD_KERNEL_TAGS_OFFSET \
-o boot-repacked.img
Here are some example values:
CMDLINE="androidboot.bootdevice=7464900.sdhci msm_rtb.filter=0x3F \
ehci-hcd.park=3 coherent_pool=8M sched_enable_power_aware=1 \
user_debug=31 cgroup.memory=nokmem printk.devkmsg=on \
androidboot.hardware=kagura buildvariant=userdebug \
androidboot.selinux=permissive"
BASE="80000000"
PAGESIZE="4096"
The newly packged boot image will be named boot-repacked.img
(or whatever name
you chose for -o
).
Gotchas
In case you compiled your own kernel, don’t forget to think about .dtb
files!
Many older devices (e.g. the Xperia XZ) need the
Device Tree Binaries (dtb
) appended to the kernel zImage
.