Android Boot Image
Overview
Android Boot Image is used to boot Android OS. It usually contains kernel image
(like zImage file) and ramdisk. Sometimes it can contain additional
binaries. This image is built as a part of AOSP (called boot.img), and being
flashed into boot partition on eMMC. Bootloader then reads that image from
boot partition to RAM and boots the kernel from it. Kernel then starts
init process from the ramdisk. It should be mentioned that recovery image
(recovery.img) also has Android Boot Image format.
Android Boot Image format is described at [1]. At the moment it can have one of next image headers:
v0: it’s called legacy boot image header; used in devices launched before Android 9; contains kernel image, ramdisk and second stage bootloader (usually unused)
v1: used in devices launched with Android 9; adds
recovery_dtbofield, which should be used for non-A/B devices inrecovery.img(see [2] for details)v2: used in devices launched with Android 10; adds
dtbfield, which references payload containing DTB blobs (either concatenated one after the other, or in Android DTBO image format)v3: used in devices launched with Android 11; adds
vendor_bootpartition and removes the second-stage bootloader and recovery image support. The newvendor_bootpartition holds the device tree blob (DTB) and a vendor ramdisk. The generic ramdisk inbootpartition is loaded immediately following the vendor ramdisk.v4: used in devices launched with Android 12; provides a boot signature in boot image header, supports multiple vendor ramdisk fragments in
vendor_bootpartition. This version also adds a bootconfig section at the end of the vendor boot image, this section contains boot configuration parameters known at build time (see [9] for details).
v2, v1 and v0 formats are backward compatible.
The Android Boot Image format is represented by
struct andr_image_data in U-Boot, and can be seen in
include/android_image.h. U-Boot supports booting Android Boot Image and also
has associated command
Booting
U-Boot is able to boot the Android OS from Android Boot Image using bootm
command. In order to use Android Boot Image format support, next option should
be enabled:
CONFIG_ANDROID_BOOT_IMAGE=y
Then one can use next bootm command call to run Android:
=> bootm $loadaddr $loadaddr $fdtaddr
where $loadaddr - address in RAM where boot image was loaded; $fdtaddr -
address in RAM where DTB blob was loaded.
And parameters are, correspondingly:
Where kernel image is located in RAM
Where ramdisk is located in RAM (can be
"-"if not applicable)Where DTB blob is located in RAM
bootm command will figure out that image located in $loadaddr has
Android Boot Image format, will parse that and boot the kernel from it,
providing DTB blob to kernel (from 3rd parameter), passing info about ramdisk to
kernel via DTB.
DTB and DTBO blobs
bootm command can’t just use DTB blob from Android Boot Image (dtb
field), because:
there is no DTB area in Android Boot Image before v2
there may be several DTB blobs in DTB area (e.g. for different SoCs)
some DTBO blobs may have to be merged in DTB blobs before booting (e.g. for different boards)
So user has to prepare DTB blob manually and provide it in a 3rd parameter
of bootm command. Next commands can be used to do so:
abootimg: manipulates Anroid Boot Image, allows one to extract meta-information and payloads from itadtimg: manipulates Android DTB/DTBO image [3], allows one to extract DTB/DTBO blobs from it
In order to use those, please enable next config options:
CONFIG_CMD_ABOOTIMG=y
CONFIG_CMD_ADTIMG=y
For example, let’s assume we have next Android partitions on eMMC:
boot: contains Android Boot Image v2 (including DTB blobs)dtbo: contains DTBO blobs
Then next command sequence can be used to boot Android:
=> mmc dev 1
# Read boot image to RAM (into $loadaddr)
=> part start mmc 1 boot boot_start
=> part size mmc 1 boot boot_size
=> mmc read $loadaddr $boot_start $boot_size
# Read DTBO image to RAM (into $dtboaddr)
=> part start mmc 1 dtbo dtbo_start
=> part size mmc 1 dtbo dtbo_size
=> mmc read $dtboaddr $dtbo_start $dtbo_size
# Copy required DTB blob (into $fdtaddr)
=> abootimg get dtb --index=0 dtb0_start dtb0_size
=> cp.b $dtb0_start $fdtaddr $dtb0_size
# Merge required DTBO blobs into DTB blob
=> fdt addr $fdtaddr 0x100000
=> adtimg addr $dtboaddr
=> adtimg get dt --index=0 $dtbo0_addr
=> fdt apply $dtbo0_addr
# Boot Android
=> bootm $loadaddr $loadaddr $fdtaddr
This sequence should be used for Android 10 boot. Of course, the whole Android boot procedure includes much more actions, like:
obtaining reboot reason from BCB (see [4])
implementing recovery boot
implementing fastboot boot
implementing A/B slotting (see [5])
implementing AVB2.0 (see [6])
But Android Boot Image booting is the most crucial part in Android boot scheme.
All Android bootloader requirements documentation is available at [7]. Some overview on the whole Android 10 boot process can be found at [8].
C API for working with Android Boot Image format
-
int android_image_get_kernel(const void *hdr, const void *vendor_boot_img, int verify, ulong *os_data, ulong *os_len)
processes kernel part of Android boot images
Parameters
const void *hdrPointer to boot image header, which is at the start of the image.
const void *vendor_boot_imgPointer to vendor boot image header, which is at the start of the image.
int verifyChecksum verification flag. Currently unimplemented.
ulong *os_dataPointer to a ulong variable, will hold os data start address.
ulong *os_lenPointer to a ulong variable, will hold os data length.
Description
This function returns the os image’s start address and length. Also, it appends the kernel command line to the bootargs env variable.
Return
- Zero, os start address and length on success,
otherwise on failure.
-
long android_boot_append_bootconfig(const struct andr_image_data *img_data, char *params, long params_len, void *ramdisk_dest)
Append bootconfig parameters to ramdisk
Parameters
const struct andr_image_data *img_dataPointer to Android image data
char *paramsPointer to boot config parameters to append
long params_lenLength of boot config parameters
void *ramdisk_destDestination address for the merged ramdisk
Description
This function copies the vendor ramdisk, boot ramdisk, and bootconfig to the destination. It then appends the provided bootconfig parameters.
Return
Bytes added to the bootconfig on success, negative on error.
-
long android_image_set_bootconfig(const void *hdr, const void *vendor_boot_img, ulong ramdisk_addr)
Extract androidboot.* args and append to bootconfig
Parameters
const void *hdrPointer to boot image header
const void *vendor_boot_imgPointer to vendor boot image header
ulong ramdisk_addrDestination address for the merged ramdisk
Return
Size of the bootconfig section (including new params) on success, negative on error.
-
bool android_image_get_dtbo(ulong hdr_addr, ulong *addr, u32 *size)
Get address and size of recovery DTBO image.
Parameters
ulong hdr_addrBoot image header address
ulong *addrIf not NULL, will contain address of recovery DTBO image
u32 *sizeIf not NULL, will contain size of recovery DTBO image
Description
Get the address and size of DTBO image in “Recovery DTBO” area of Android Boot Image in RAM. The format of this image is Android DTBO (see corresponding “DTB/DTBO Partitions” AOSP documentation for details). Once the address is obtained from this function, one can use ‘adtimg’ U-Boot command or android_dt_*() functions to extract desired DTBO blob.
This DTBO (included in boot image) is only needed for non-A/B devices, and it only can be found in recovery image. On A/B devices we can always rely on “dtbo” partition. See “Including DTBO in Recovery for Non-A/B Devices” in AOSP documentation for details.
Return
true on success or false on error.
-
bool android_image_get_dtb_img_addr(ulong hdr_addr, ulong vhdr_addr, ulong *addr)
Get the address of DTB area in boot image.
Parameters
ulong hdr_addrBoot image header address
ulong vhdr_addrVendor Boot image header address
ulong *addrWill contain the address of DTB area in boot image
Return
true on success or false on fail.
-
bool android_image_get_dtb_by_index(ulong hdr_addr, ulong vendor_boot_img, u32 index, ulong *addr, u32 *size)
Get address and size of blob in DTB area.
Parameters
ulong hdr_addrBoot image header address
ulong vendor_boot_imgPointer to vendor boot image header, which is at the start of the image.
u32 indexIndex of desired DTB in DTB area (starting from 0)
ulong *addrIf not NULL, will contain address to specified DTB
u32 *sizeIf not NULL, will contain size of specified DTB
Description
Get the address and size of DTB blob by its index in DTB area of Android Boot Image in RAM.
Return
true on success or false on error.
-
void android_print_contents(const struct andr_boot_img_hdr_v0 *hdr)
prints out the contents of the Android format image
Parameters
const struct andr_boot_img_hdr_v0 *hdrpointer to the Android format image header
Description
android_print_contents() formats a multi line Android image contents description. The routine prints out Android image properties
Return
no returned results
-
bool android_image_print_dtb_info(const struct fdt_header *fdt, u32 index)
Print info for one DTB blob in DTB area.
Parameters
const struct fdt_header *fdtDTB header
u32 indexNumber of DTB blob in DTB area.
Return
true on success or false on error.
-
bool android_image_print_dtb_contents(ulong hdr_addr)
Print info for DTB blobs in DTB area.
Parameters
ulong hdr_addrBoot image header address
Description
- DTB payload in Android Boot Image v2+ can be in one of following formats:
Concatenated DTB blobs
Android DTBO format (see CONFIG_CMD_ADTIMG for details)
- This function does next:
Prints out the format used in DTB area
Iterates over all DTB blobs in DTB area and prints out the info for each blob.
Return
true on success or false on error.