abootimg - manipulate Android Boot Images. ------------------------------------------ (c) 2010 Gilles Grandou <gilles@grandou.net> * Android Boot Images --------------------- It a special partition format defined by the Android Open Source Porject. See bootimg.h in the source tree for more information about the structure. It's used by Android Bootloaders to boot the OS. Boot images mainly convey: - a kernel image - a ramdisk image - optionaly, a 2nd stage bootloader - the cmdline passed to the kernel when booting. The official tool used to create boot images is part of the Android Project, available here: http://android.git.kernel.org/?p=platform/system/core.git;a=tree;f=mkbootimg abootimg can work directly on block devices, or, the safest way, on a file image. File images can be read/written with dd: $ dd if=/dev/mmcblk0p2 of=boot.img $ dd if=boot.img of=/dev/mmcblk0p2 You obviously need to have right access to the block device (using su, sudo, ...). Android Boot Image contains an 32 bytes Id. The specification does not actually mandates any specific implementation of this Id (it can be a timestamp, a CRC checksum, a SHA hash, ...). Bootloader appears to do nothing of this Id, it's solely here for tracking purpose. Currently abootimg does nothing with it, it's never touched/modified. * Building abootimg ------------------- On a linux system, it's simply as: $ make blkid library is needed to perform some sanity checks when writing boot image directly on a block device (to avoid writing a valid existing filesystem). * Looking at an Android Boot Image ---------------------------------- Basic Information can be extracted from a boot image, using: $ abootimg -i <bootimg> Here is an example: $ ./abootimg -i boot.img Android Boot Image Info: * file name = boot.img * image size = 8388608 bytes (8.00 MB) page size = 2048 bytes * Boot Name = "" * kernel size = 3002744 bytes (2.86 MB) ramdisk size = 1639626 bytes (1.56 MB) * load addresses: kernel: 0x10008000 ramdisk: 0x11000000 tags: 0x10000100 * cmdline = mem=448M@0M nvmem=64M@448M vmalloc=320M video=tegrafb console=tty0 usbcore.old_scheme_first=1 quiet splash elevator=noop tegraboot=sdmmc cmdpart=1:7168:10240,2:17408:16384,3:35840:614400,4:4004864:27096064 * id = 0x07571070 0x13950a6a 0x185c996f 0x9ab7b64d 0xcccd09bd 0x00000000 0x00000000 0x00000000 * Extracting elements from an Android Boot Image ------------------------------------------------ All parts of boot image can be extracted with: $ abootimg -x <bootimg> [<bootimg.cfg> [<kernel> [<ramdisk> [<secondstage>]]]] Parts name are optional. Default ones are used if none are given: * bootimg.cfg for the configuration file * zImage for the Kernel image * initrd.img for the Ramdisk * stage2.img for the Second Stage image Here is an example: $ abootimg -x boot.img writing boot image config in bootimg.cfg extracting kernel in zImage extracting ramdisk in initrd.img * Boot Configuration file ------------------------- It's an editable ascii file which is basically a dump of the header content, to be able to rebuild a compatible image later. Each entry takes one line and is in the form of: <entry> = <value> You can put any number of spaces/tab before/after the = <value> is evalued starting from the fisrt non space character following the = until the end of line Numerical values can be given in decimal (12345) or hexadecimal (0x1234abcd). Known configuration entries are: * bootsize Indicate the size of the boot image to produce * pagesize All sizes have to be a multiple of the page size. Standard page size is 2048 bytes. I don't know if other page size are supported by Android bootloader * kerneladdr, ramdiskaddr, secondaddr, tagsaddr Address in RAM used to load the kernel, ramdisk, 2nd stage bootloader, and tags table. * name name given to the boot image. not really used by bootloader, but it's can be usefull to keep track of what the image actually contains * cmdline contains the command line passed to the kernel when booting * Updating an existing Android Boot Image ----------------------------------------- An existing valid Boot Image can be updated with: $ abootimg -u <bootimg> [-c "param=value"] [-f <bootimg.cfg>] [-k <kernel>] [-r <ramdisk>] [-s <secondstage>] Any part of the image can be individully updated. As an example: $ abootimg -u boot.img -k zImage.new will update the kernel $ abootimg -u boot.img -r initrd.new.img will update the image $ abootimg -u boot.img -k zImage.new -r initrd.new.img will update both Image configuration can be updated either by giving a configuration file (-f option) or by giving individual config entries on the command line (-c). Severial config entries (-c) can be given on comamd line. As an example: $ abootimg -u boot.img -f bootimg.new.cfg will update the configuration without touching the kernel nor the ramdisk $ abootimg -u boot.img -c "cmdline = mem=448M@0M nvmem=64M@448M vmalloc=320M \ video=tegrafb console=tty0 usbcore.old_scheme_first=1 quiet splash elevator=noop \ tegraboot=sdmmc tegrapart=recovery:700:a00:800,boot:1100:1000:800,mbr:2100:200:800,\ system:2300:25800:800,cache:27b00:32000:800,misc:59b00:400:800,userdata:5a000:9a600:800" update the boot conmand line $ abootimg -u boot.img -c "bootsize=0x500000" update the boot image size to 5MB. It's usefull if you want to shrink an existing image to make it fit in another smaller boot partition. (On Toshiba AC100, it allows you to take a part06.img and transform it to fit inside part05) The original boot image has to be valid, otherwise abootimg will refuse to update it. * Creating a new Android Boot Image from scratch ------------------------------------------------ A new boot image can be create with: $ abootimg --create <bootimg> [-c "param=value"] [-f <bootimg.cfg>] -k <kernel> -r <ramdisk> [-s <secondstage>] Parameters are the same than above for update. The only difference is that kernel and ramdisk are mandatory. * Working directly of Block Devices ----------------------------------- Instead of manipulating Boot Image regular file, you can work directly on boot block device. Note that, on AC100, the current kernel needs to be patched in order to have direct access to boot partitions (partitions 5 and 6). Some examples: $ sudo abootimg -i /dev/mmcblk0p2 read the current boot partition $ sudo abootimg -u /dev/mmcblk0p2 -k arch/arm/boot/zImage update the boot partition with the kernel you have just built $ sudo abootimg -u /dev/mmcblk0p2 -c "cmdline=..." update the boot partition with a new boot cmdline $ sudo abootimg --create /dev/mmcblk0p2 -f boot.cfg -k zImage -r initrd.img overwrite the boot partition (which can be damaged) with a brand new image If abootimg has to write to a block device (-u and --create), some sanity check are performed: * you oviously need read/write access to the block device (so use su, sudo, ...) * the actual partition must not be identified as containing a valid filesystem as recognised by blkid library. Specifically, it cannot contains a ext2/3 filesystem (this avoids you to ovewrite your root filesystem by mistake) * the updated/created boot image has to be same size than the block device you try to write on. * in case of update, the current boot partition has to contain a valid Android Boot Image. Failing any of these tests will abort the operation on block device. It's by definition more risky to manipulate block device, as a bad manipulation can as bad manipulation can make your system unbootable if you don't fix it before the next reboot. On the other hand, manipulating the block device allows abootimg to prevent most of the stupid mistakes which can be made when writing boot image with dd (overwriting another filesystem, writing a boot image bigger than the partition, writing the wrong file or an invalid partition, ...)