Android Boot Image Header

作者 by adtxl / 2022-03-16 / 暂无评论 / 561 个足迹

翻译&整理自https://source.android.com/devices/bootloader/boot-image-header

1. 概述

Android9中,在boot image header中添加了一个version字段,可以在更新头文件的时候保持向后兼容。bootloader必须检查header中的这个version字段,并据此进行解析。对设备有以下要求:

  • Android12可以使用header version 3或4.对于设用GKI的设备,优先在boot image中使用version 4.
  • Android11可以使用boot header version 3,使用GKI的设备必须优先使用version 3.
  • Android 10, 必须使用boot header version 2.
  • Android 9, 必须使用boot header version 1.
  • Android 8及以下版本使用boot header version 0.

在Android9以及更高的版本中,vts会测试boot/revovery image中是否使用了正确的版本。。如需查看有关当前支持的所有启动映像头文件和供应商启动映像头文件的 AOSP 详细信息,请参阅 system/tools/mkbootimg/include/bootimg/bootimg.h

2. 实现boot image header version

mkbootimg工具接受如下的参数:

  • header_version

设置启动映像头文件版本。如果head version版本为:

1 或 2,启动映像支持recovery DTBO image或 recovery ACPIO 恢复映像。
3,启动映像不支持recovery images。
  • recovery_dtbo

适用于使用 DTB 的架构。指定 DTBO 恢复映像的路径。对于无需恢复映像的 A/B 设备,此参数为可选参数。如果非 A/B 设备使用的 header_version 为:

1 或 2,则设备可以指定此路径,也可以使用 recovery_acpio 部分指定 ACPIO 恢复映像的路径。
3,则设备无法指定 DTBO 恢复映像。
  • recovery_acpio

适用于使用 ACPI(而非 DTB)的架构。指定 ACPIO 恢复映像的路径。对于不需要恢复映像的 A/B 设备,此参数为可选参数。如果非 A/B 设备使用的 header_version 为:

1 或 2,则设备可以指定此路径,也可以使用 recovery_dtbo 部分指定 DTBO 恢复映像的路径。
3,则设备无法指定 ACPIO 恢复映像。
  • dtb
启动/恢复映像中 DTB 映像的路径。
  • dtb_offset
在添加到 base 参数时,系统会提供最终设备树的实际加载地址。例如,如果 base 参数为 0x10000000 且 dtb_offset 参数为 0x01000000,则启动映像头文件中的 dtb_addr_field 将填充为 0x11000000。

在BoardConfig.mk 中使用 BOARD_MKBOOTIMG_ARGS 将 header version 添加到 mkbootimg 的参数中。例如:

BOARD_MKBOOTIMG_ARGS := --ramdisk_offset $(BOARD_RAMDISK_OFFSET) --tags_offset $(BOARD_KERNEL_TAGS_OFFSET) --header_version $(BOARD_BOOTIMG_HEADER_VERSION)

Android 构建系统使用 BoardConfig 中的变量 BOARD_PREBUILT_DTBOIMAGE指定recovery_dtbo的位置,然后会在mkbootimg工具生成recovery.img时使用。如需详细了解 Android 开源项目 (AOSP) 的变化,请查看与启动映像头文件版本编号相关的更改列表

2. Boot image header version 4

Android 12 在启动映像头文件版本 4 中提供了一个 boot_signature,可用于检查内核和 ramdisk 的完整性。该检查在 VtsSecurityAvbTest 中完成,对于使用 GKI 2.0 架构的设备来说是必须执行的。不过,特定于设备的启动时验证流程中不涉及 boot_signature,它仅用于 VTS 中。如需了解详情,请参阅 GKI 2.0 boot.img 集成。

供应商启动映像头文件版本 4 支持多个供应商 ramdisk fragment。

启动映像头文件版本 4 采用以下格式。

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

    uint32_t signature_size; /* size in bytes */
};

3. Boot image header, version 3

Android 11 将启动映像头文件更新为版本 3,该版本移除了以下数据:

  • Second-stage bootloader. 启动映像头文件中不再显示 second_size 和 second_addr 字段。具有第二阶段引导加载程序的设备必须将相应引导加载程序存储在自己的分区中。

  • Recovery image。指定恢复映像时需满足的要求已被弃用,且启动映像头文件中不再显示 recovery_dtbo_size、recovery_dtbo_offset、recovery_acpio_size 和 recovery_acpio_offset 字段。

    • A/B 设备使用了更新和恢复方案,因此无需指定 DTBO 或 ACPIO 恢复映像。
    • 如果非 A/B 设备需要指定恢复映像(DTBO 或 ACPIO),则应使用启动映像头文件版本 1 或 2。
  • 设备树 blob (DTB)。DTB 存储在vendor boot partition中,因此启动映像头文件中不再显示 dtb_size 和 dtb_addr 字段(但vendor boot image header文件中会显示)。

设备可以通过启动映像头文件版本 3 来满足通用内核映像 (GKI) 架构的要求,该架构统一了核心内核,并将启动所需的供应商模块移至 vendor_boot 分区(这意味着启动映像仅包含 GKI 组件)。如果设备:

使用 GKI(需要 android-4.19 或 android-5.4 内核)但不使用 A/B 更新机制,则可以使用启动映像版本 3(适用于启动映像)和启动映像版本 2(适用于恢复映像)指定恢复映像。

既不使用 GKI 也不使用 A/B 更新机制,则可以使用启动映像版本 1 指定恢复映像或将启动映像版本 2 同时用于启动映像和恢复映像。

启动映像头文件版本 3 采用以下格式。

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

4. Boot image header, version 2

Android 10 已将启动映像头文件更新为版本 2,且添加了 DTB 恢复映像的信息部分(映像大小和实际加载地址)。

启动映像头文件版本 2 采用以下格式。

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 */
};

5. Boot image header, version 1

Android 9 会将启动映像头文件的 unused 字段转换为头文件版本字段。搭载 Android 9 的设备必须使用头文件版本为 1 或更高(由 VTS 进行验证)的启动映像头文件。

启动映像头文件版本 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|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 */

};

非 A/B 设备可以指定 DTB/ACPI 叠加层恢复映像,以减少无线下载 (OTA) 更新失败的次数。(A/B 设备不会出现这种问题,且无需指定叠加层映像)。您可以指定 DTBO 映像或 ACPIO 映像,但不能同时指定二者(因为它们所适用的架构有所不同)。要正确配置启动映像头文件:

使用 DTBO 恢复映像时,请添加 recovery_dtbo_sizerecovery_dtbo_offset 字段(不要添加 recovery_acpio_sizerecovery_acpio_offset 字段)。

使用 ACPIO 恢复映像时,请添加 recovery_acpio_sizerecovery_acpio_offset 字段(不要添加 recovery_dtbo_size 和 recovery_dtbo_offset 字段)。

header_size 字段包含启动映像头文件大小。如果启动映像头文件版本为 1,则除了 kernel、ramdisk 和 second sections 之外,id 字段还包含启动映像 recovery_[dtbo|acpio] 部分的 SHA-1 摘要。如需详细了解 recovery_[dtbo|acpio]_sizerecovery_[dtbo|acpio]_offset 字段,请参阅恢复映像。

6. Legacy boot image header, version 0

如果设备搭载 Android 9 之前的版本且使用旧版启动映像头文件,则将其视为使用启动映像头文件版本 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];

};

独特见解