開機映像檔標頭

Android 9 在啟動映像檔標頭中導入了版本欄位,可在維持回溯相容性的同時更新標頭。引導程式必須檢查標頭版本欄位,並相應地剖析標頭。啟動裝置:

  • Android 13 可使用啟動標頭版本 3 或 4。如果裝置支援 通用核心映像檔 (GKI) 架構,版本 4 就是主要的啟動映像檔,且啟動標頭中的 os_version 欄位必須為零。裝置系統啟動載入程式應改為從 Android 驗證開機程序 (AVB) 屬性取得版本資訊。
  • Android 12 可使用啟動標頭版本 3 或 4。對於支援通用核心映像檔 (GKI) 架構的裝置,第 4 版是主要的啟動映像檔。
  • Android 11 可使用啟動標頭版本 3。如果裝置支援 通用核心映像檔 (GKI) 架構,則必須使用這個版本做為主要開機映像檔。
  • Android 10 必須使用啟動標頭第 2 版。
  • Android 9 必須使用啟動標頭 1 版。
  • Android 8 以下版本會被視為使用啟動映像檔標頭版本 0。

對於搭載 Android 9 以上版本的所有裝置,供應商測試套件 (VTS) 會檢查 boot/recovery 映像檔的格式,確保引導映像檔標頭使用正確的版本。如要查看所有支援的開機和供應商開機映像檔標頭的 Android 開放原始碼計畫詳細資料,請參閱 system/tools/mkbootimg/include/bootimg/bootimg.h

實作開機映像檔標頭版本管理

mkbootimg 工具接受下列引數。

引數 說明
header_version 設定開機映像檔標頭版本。含有標頭版本的開機映像檔:
  • 1 或 2 支援復原 DTBO 映像檔或復原 ACPIO 映像檔。
  • 3 不支援復原映像檔。
recovery_dtbo 適用於使用 DTB 的架構。指定復原 DTBO 映像檔的路徑。可選,適用於不需要復原映像檔的 A/B 裝置。使用 header_version 的非 A/B 裝置:
  • 1 或 2 可以指定這個路徑,或使用 recovery_acpio 部分指定復原 ACPIO 映像檔的路徑。
  • 3 無法指定復原 DTBO 映像檔。
recovery_acpio 適用於使用 ACPI 而非 DTB 的架構。指定復原 ACPIO 映像檔的路徑。如果是 A/B 裝置,不需要復原映像檔,則為選用項目。使用 header_version 的非 A/B 裝置:
  • 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 設定 mkbootimg 工具的引數 recovery_dtbo。如要進一步瞭解 Android 開放原始碼計畫 (AOSP) 的異動,請參閱與啟動映像檔標頭版本控制相關的變更清單

開機映像檔標頭,版本 4

Android 12 在啟動映像檔標頭第 4 版中提供 boot_signature,可用於檢查核心和 RAM 磁碟的完整性。檢查作業會在 VtsSecurityAvbTest 中執行,且適用於使用 GKI 架構的裝置。不過,boot_signature 不會參與裝置專屬的驗證開機程序,只會用於 VTS。詳情請參閱 GKI boot.img 主機板設定GKI 驗證開機設定

供應商開機映像檔標頭第 4 版支援多個供應商 ramdisk 片段。

第 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 版)

Android 11 會將啟動映像檔標頭更新至第 3 版,並移除下列資料:

  • 第二階段的系統啟動載入程式。開機映像檔標頭中不再顯示 second_sizesecond_addr 欄位。搭載第二階段系統啟動載入程式的裝置必須將該系統啟動載入程式儲存在自己的分區中。

  • 復原映像檔。指定復原映像檔的需求已淘汰,recovery_dtbo_sizerecovery_dtbo_offsetrecovery_acpio_sizerecovery_acpio_offset 欄位也不再顯示在啟動映像檔標頭中。

    • A/B 裝置採用更新與復原配置,因此沒有必要指定要復原的 DTBO 或 ACPIO 映像檔。

    • 非 A/B 裝置如要指定復原映像檔 (DTBO 或 ACPIO),應使用啟動映像檔標頭第 1 或第 2 版。

  • 裝置樹狀結構 blob (DTB)。DTB 會儲存在供應商的開機分割區中,因此 dtb_sizedtb_addr 欄位不會再顯示在開機映像檔標頭中 (但會顯示在供應商的開機映像檔標頭中)。

裝置可使用啟動映像檔標頭第 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];
};

開機映像檔標頭 (第 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 */
};

開機映像檔標頭,版本 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_sizerecovery_dtbo_offset 欄位)。

header_size 欄位包含開機映像檔標頭的大小。如果啟動映像檔標頭版本設為 1,則 id 欄位除了 kernelramdisksecond sections 以外,還會包含啟動映像檔 recovery_[dtbo|acpio] 區段的 SHA-1 摘要。如要進一步瞭解 recovery_[dtbo|acpio]_sizerecovery_[dtbo|acpio]_offset 欄位,請參閱復原映像檔

舊版開機映像檔標頭,版本 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];
};