Google is committed to advancing racial equity for Black communities. See how.

Boot Image Header

Android 9 introduced a version field in the boot image header, enabling updates to the header while maintaining backward compatibility. The bootloader must check the header version field and parse the header accordingly. Devices launching with:

  • Android 11 can use boot header version 3. For devices supporting Generic Kernel Image (GKI) architecture, this version must be used for the primary boot image.
  • Android 10 must use boot header version 2.
  • Android 9 must use boot header version 1.
  • Android 8 and lower are considered as using a boot image header version 0.

For all devices running with Android 9 or higher, the Vendor Test Suite (VTS) checks the format of the boot/recovery image to ensure that the boot image header uses the correct version. To view AOSP details on all currently supported boot and vendor boot image headers, refer to system/tools/mkbootimg/include/bootimg/bootimg.h.

Implementing boot image header versioning

The mkbootimg tool accepts the following arguments.

Argument Description
header_version Sets the boot image header version. A boot image with a header version:
  • 1 or 2 supports a recovery DTBO image or a recovery ACPIO image.
  • 3 doesn't support recovery images.
recovery_dtbo Used for architectures that use DTB. Specifies the path to the recovery DTBO image. Optional for A/B devices, which don't need a recovery image. Non-A/B devices using header_version:
  • 1 or 2 can specify this path or use the recovery_acpio section to specify a path to a recovery ACPIO image.
  • 3 can't specify a recovery DTBO image.
recovery_acpio Used for architectures that use ACPI instead of DTB. Specifies the path to the recovery ACPIO image. Optional for A/B devices, which don't need a recovery image. Non-A/B devices using header_version:
  • 1 or 2 can specify this path or use the recovery_dtbo section to specify a path to a recovery DTBO image.
  • 3 can't specify a recovery ACPIO image.
dtb Path to the DTB image that's 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 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.

Boot image header, version 3

Android 11 updates the boot image header to version 3, which removes the following data:

  • Second-stage bootloader. The second_size and second_addr fields no longer appear in the boot image header. Devices with a second-stage bootloader must store that bootloader in its own partition.

  • Recovery image. The requirement for specifying a recovery image has been deprecated, and the recovery_dtbo_size, recovery_dtbo_offset, recovery_acpio_size, and recovery_acpio_offset fields no longer appear in the boot image header.

    • A/B devices use an update and recovery scheme that makes it unnecessary to specify a DTBO or ACPIO image for recovery.

    • Non-A/B devices that want to specify a recovery image (either DTBO or ACPIO) should use boot image header version 1 or 2.

  • Device tree blob (DTB). The DTB is stored in the vendor boot partition, so the dtb_size and dtb_addr fields no longer appear in the boot image header (but are present in the vendor boot image header).

Devices can use boot image header version 3 to comply with Generic Kernel Image (GKI) architecture, which unifies the core kernel and moves vendor modules that are required for boot to the vendor_boot partition (meaning the boot image contains only GKI components). Devices that:

  • Use GKI (requires the android-4.19 or android-5.4 kernel) but don't use A/B updates can specify a recovery image by using boot image version 3 for the boot image and boot image version 2 for the recovery image.

  • Don't use GKI and don't use A/B updates can specify a recovery image by using boot image version 1 or 2 for both boot and recovery images.

Version 3 of the boot image header version uses the following format.

struct boot_img_hdr
{
#define BOOT_MAGIC_SIZE 8
    uint8_t magic[BOOT_MAGIC_SIZE];

    uint32_t kernel_size;    /* size in bytes */
    uint32_t ramdisk_size;   /* size in bytes */

    uint32_t os_version;

    uint32_t header_size;    /* size of boot image header in bytes */
    uint32_t reserved[4];
    uint32_t header_version; /* offset remains constant for version check */

#define BOOT_ARGS_SIZE 512
#define BOOT_EXTRA_ARGS_SIZE 1024
    uint8_t cmdline[BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE];
};

Boot image header, version 2

Android 10 updates the boot image header to version 2, which adds a section for recovery DTB image information (image size and physical load address).

Version 2 of the boot image header version uses the following format.

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|acpio]_size;    /* size of recovery image */
    uint64_t recovery_[dtbo|acpio]_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 */
};

Boot image header, version 1

Android 9 converts the unused field of the boot image header to a header version field. Devices launching with Android 9 must use the boot image header with the header version set to 1 or higher (this is verified by VTS).

Version 1 of the boot image header version uses the following format.

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|acpio]_size;    /* size of recovery image */
    uint64_t recovery_[dtbo|acpio]_offset;  /* offset in boot image */
    uint32_t header_size;               /* size of boot image header in bytes */
};

Non-A/B devices can specify a DTB/ACPI overlay image for recovery to help mitigate over-the-air (OTA) update failures. (A/B devices don't have this problem and don't need to specify an overlay image.) You can specify either a DTBO image or an ACPIO image, but not both (because they're used by different architectures). To configure the boot image header correctly, when using:

  • A DTBO image for recovery, include the recovery_dtbo_size and recovery_dtbo_offset fields (and don't include the recovery_acpio_size and recovery_acpio_offset fields).

  • An ACPIO image for recovery, include the recovery_acpio_size and recovery_acpio_offset fields (and don't include the recovery_dtbo_size and recovery_dtbo_offset fields).

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|acpio] section of the boot image in addition to the kernel, ramdisk, and second sections. For details on the recovery_[dtbo|acpio]_size and recovery_[dtbo|acpio]_offset fields, see Recovery Images.

Legacy boot image header, version 0

Devices launched before Android 9 using the legacy boot image header are considered as using a boot image header version 0.

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];
};