 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, ...)


