Starting in Android 9, the boot image header contains a field to indicate the header version. The bootloader must check this header version field and parse the header accordingly. Versioning the boot image header allows future modifications to the header while maintaining backward compatibility.
All devices launching with Android 9 must use boot header version 1.
Boot image header changes
In the legacy boot image header (shown below), the unused
field is converted to a header version field for devices launching with
Android 9.
struct boot_img_hdr { uint8_t magic[BOOT_MAGIC_SIZE]; uint32_t kernel_size; /* size in bytes */ uint32_t kernel_addr; /* physical load addr */ uint32_t ramdisk_size; /* size in bytes */ uint32_t ramdisk_addr; /* physical load addr */ uint32_t second_size; /* size in bytes */ uint32_t second_addr; /* physical load addr */ uint32_t tags_addr; /* physical addr for kernel tags */ uint32_t page_size; /* flash page size we assume */ uint32_t unused; uint32_t os_version; uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */ uint8_t cmdline[BOOT_ARGS_SIZE]; uint32_t id[8]; /* timestamp / checksum / sha1 / etc */ uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE]; };
Devices launched before Android 9 using the legacy boot image header are considered as using a boot image header version 0. All devices launching with Android 9 must use the following structure for the boot image header with the header version set to 1.
struct boot_img_hdr { uint8_t magic[BOOT_MAGIC_SIZE]; uint32_t kernel_size; /* size in bytes */ uint32_t kernel_addr; /* physical load addr */ uint32_t ramdisk_size; /* size in bytes */ uint32_t ramdisk_addr; /* physical load addr */ uint32_t second_size; /* size in bytes */ uint32_t second_addr; /* physical load addr */ uint32_t tags_addr; /* physical addr for kernel tags */ uint32_t page_size; /* flash page size we assume */ uint32_t header_version; uint32_t os_version; uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */ uint8_t cmdline[BOOT_ARGS_SIZE]; uint32_t id[8]; /* timestamp / checksum / sha1 / etc */ uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE]; uint32_t recovery_dtbo_size; /* size of recovery dtbo image */ uint64_t recovery_dtbo_offset; /* offset in boot image */ uint32_t header_size; /* size of boot image header in bytes */ };
The header_size
field contains the size of the boot image
header. If the boot image header version is set to 1, the id
field contains
the SHA-1 digest for the recovery_dtbo
section of the boot image
in addition to the kernel
, ramdisk
,
and second sections
. For details on the
recovery_dtbo_size
and recovery_dtbo_offset
fields,
refer to Including
DTBO in Recovery for Non-A/B Devices.
Implementation
The mkbootimg
tool that creates boot images adds the
following arguments to support the new boot image header.
Argument | Description |
---|---|
header_version
|
Sets the boot image header version. |
recovery_dtbo
|
Path to the recovery DTBO image to be included in the recovery image. |
The device BoardConfig.mk
uses the config
BOARD_MKBOOTIMG_ARGS
to add header version
to the
other board-specific arguments of mkbootimg
. For example:
BOARD_MKBOOTIMG_ARGS := --ramdisk_offset $(BOARD_RAMDISK_OFFSET) --tags_offset $(BOARD_KERNEL_TAGS_OFFSET) --header_version $(BOARD_BOOTIMG_HEADER_VERSION)
The Android build system uses the BoardConfig
variable
BOARD_PREBUILT_DTBOIMAGE
to set the argument
recovery_dtbo
of the mkbootimg
tool during the creation
of the recovery image.
For details on the Android Open Source Project (AOSP) changes, review the associated changelists for boot image header versioning.
Validation
For all devices launching with Android 9, the Vendor Test Suite (VTS) checks the format of the boot/recovery image to ensure that the boot image header uses version 1.
Including DTB in the boot image
Android 10 updates the boot image header to version 2, which includes a section to store the device tree blob (DTB) image. Android 10 VTS tests verify that all devices launching with Android 10 use boot image header version 2 and include a valid DTB image as part of the boot/recovery images.
About DTB
In Android 9 and earlier releases, the DTB image was
either placed in its own partition or appended to the kernel image.gz
to
create the kernel + DTB image (which is then passed to mkbootimg
to
create boot.img
). In Android 10,
the boot image format is further updated with a section for DTB images.
This change means that Android doesn't need to support scripts that append the DTB image
to image.gz
in the kernel and enables the use of VTS tests to verify
(and standardize) DTB placement.
In addition, for non-A/B devices, it's safer to have the DTB as part of the recovery image rather than in a separate partition to prevent issues caused by interrupted OTAs. During an OTA, if a problem occurs after the DTB partition is updated (but prior to completing the full update), the device tries to boot into recovery mode to complete the OTA. However, because the DTB partition has already been updated, a mismatch could occur with the recovery image (which has not yet been updated). Having the DTB image as part of the boot image format prevents such issues by making the recovery image self sufficient (that is, it doesn't depend on another partition).
Boot image header version 2
Boot image header version 2 is defined as shown below with fields representing the size of the DTB image and its physical load address.
struct boot_img_hdr { uint8_t magic[BOOT_MAGIC_SIZE]; uint32_t kernel_size; /* size in bytes */ uint32_t kernel_addr; /* physical load addr */ uint32_t ramdisk_size; /* size in bytes */ uint32_t ramdisk_addr; /* physical load addr */ uint32_t second_size; /* size in bytes */ uint32_t second_addr; /* physical load addr */ uint32_t tags_addr; /* physical addr for kernel tags */ uint32_t page_size; /* flash page size we assume */ uint32_t header_version; uint32_t os_version; uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */ uint8_t cmdline[BOOT_ARGS_SIZE]; uint32_t id[8]; /* timestamp / checksum / sha1 / etc */ uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE]; uint32_t recovery_dtbo_size; /* size of recovery dtbo image */ uint64_t recovery_dtbo_offset; /* offset in boot image */ uint32_t header_size; /* size of boot image header in bytes */ uint32_t dtb_size; /* size of dtb image */ uint64_t dtb_addr; /* physical load address */ };
To allow the inclusion of the DTB image, update the boot image format as follows.
Boot image format | Number of pages |
---|---|
Boot header (1 page) | 1 |
Kernel (l pages) | l = (kernel_size + page_size - 1) / page_size
|
Ramdisk (m pages) | m = (ramdisk_size + page_size - 1) / page_size
|
Second stage bootloader (n pages) | n = (second_size + page_size - 1) / page_size
|
Recovery DTBO (o pages) | o = (recovery_dtbo_size + page_size - 1) / page_size
|
DTB (p pages) | p = (dtb_size + page_size - 1) / page_size
|
The DTB image must use one of the following formats:
- DT blobs concatenated one after the other. Bootloader
uses the
totalsize
field in each FDT header to read and parse the corresponding blob. - DTB/DTBO
partitions structure. Bootloader has an efficient way to select the correct DT blob by
examining the
dt_table_entry
struct (containsid
,rev
, andcustom
fields) that can hold hardware identifying information for the entry.
Android 10 modifies mkbootimg.py
to support the
following arguments.
Argument | Description |
---|---|
dtb | Path to the DTB image to be included in the boot/recovery images. |
dtb_offset | When added to the base argument, provides the physical load address for
the final device tree. For example, if the base argument is
0x10000000 and the dtb_offset argument is 0x01000000 ,
the dtb_addr_field in the boot image header is populated as 0x11000000 .
|
The board config variable BOARD_PREBUILT_DTBIMAGE_DIR
must be used to specify
the path to the DTB image. If more than one file with extension *.dtb
is
present in the directory BOARD_PREBUILT_DTBIMAGE_DIR
, the Android build
system concatenates the files to create the final DTB image used in the boot image creation.
The board config variable BOARD_INCLUDE_DTB_IN_BOOTIMG
must be set to true.
BOARD_INCLUDE_DTB_IN_BOOTIMG := true
This causes the argument dtb
to be passed to mkbootimg.py
with the DTB image
from the directory specified by BOARD_PREBUILT_DTBIMAGE_DIR
.
The dtb_offset
argument can be appended to the board config variable
BOARD_MKBOOTIMG_ARGS
along with the other offsets and header version.
BOARD_MKBOOTIMG_ARGS := --ramdisk_offset $(BOARD_RAMDISK_OFFSET) --dtb_offset $(BOARD_DTB_OFFSET) --tags_offset $(BOARD_KERNEL_TAGS_OFFSET) --header_version $(BOARD_BOOTIMG_HEADER_VERSION)
Bootloader must support the updated boot image and must add a new kernel command line
parameter androidboot.dtb_idx
to indicate the index of
the selected DT to facilitate VTS verification. You can only specify one (1) index.
For example, the parameter androidboot.dtb_idx=N
reports N
as the zero-based index of the device tree selected by
the bootloader from the set of DT blobs present in the boot image.