供應商引導分區

Android 11 引入了通用內核映像 (GKI) 的概念。為了能夠容易地與GKI引導的任意設備,機器人11設備可以使用引導映像頭版本3.在版本3中,所有的供應商特定的信息被提取出來的的boot分區並重新定位到一個新的vendor_boot分區。在5.4 Linux內核的Android 11的ARM64設備啟動必須支持vendor_boot分區和更新的boot分區格式通過與GKI測試。

機器人12設備可以使用引導映像頭版本4,該支撐件包括在多供應商的ramdisk vendor_boot分區。多個供應商 ramdisk 片段在供應商 ramdisk 部分中一個接一個地連接在一起。供應商 ramdisk 表用於描述供應商 ramdisk 部分的佈局和每個供應商 ramdisk 片段的元數據。

分區結構

供應商啟動分區使用虛擬 A/B 進行 A/B 處理,並受 Android 驗證啟動保護。

版本 3

該分區由標頭、供應商 ramdisk 和設備樹 blob (DTB) 組成。

部分頁數
供應商引導頭(n 頁) n = (2112 + page_size - 1) / page_size
供應商 ramdisk (o 頁) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB(p 頁) p = (dtb_size + page_size - 1) / page_size

版本 4

該分區由一個標頭、供應商 ramdisk 部分(由所有供應商 ramdisk 片段組成,串聯)、設備樹 blob (DTB) 和供應商 ramdisk 表組成。

部分頁數
供應商引導頭(n 頁) n = (2128 + page_size - 1) / page_size
供應商 ramdisk 片段(o 頁) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB(p 頁) p = (dtb_size + page_size - 1) / page_size
供應商 ramdisk 表(q 頁) q = (vendor_ramdisk_table_size + page_size - 1) / page_size
Bootconfig(r 頁) r = (bootconfig_size + page_size - 1) / page_size

供應商引導頭

供應商的引導分區頭的內容主要包括一個已經從搬遷有數據引導映像頭。它還包含有關供應商 ramdisk 的信息。

版本 3

struct vendor_boot_img_hdr_v3
{
#define VENDOR_BOOT_MAGIC_SIZE 8
    uint8_t magic[VENDOR_BOOT_MAGIC_SIZE];
    uint32_t header_version;
    uint32_t page_size;           /* flash page size we assume */

    uint32_t kernel_addr;         /* physical load addr */
    uint32_t ramdisk_addr;        /* physical load addr */

    uint32_t vendor_ramdisk_size; /* size in bytes */

#define VENDOR_BOOT_ARGS_SIZE 2048
    uint8_t cmdline[VENDOR_BOOT_ARGS_SIZE];

    uint32_t tags_addr;           /* physical addr for kernel tags */

#define VENDOR_BOOT_NAME_SIZE 16
    uint8_t name[VENDOR_BOOT_NAME_SIZE]; /* asciiz product name */
    uint32_t header_size;         /* size of vendor boot image header in
                                   * bytes */
    uint32_t dtb_size;            /* size of dtb image */
    uint64_t dtb_addr;            /* physical load address */

};

版本 4

struct vendor_boot_img_hdr_v4
{
#define VENDOR_BOOT_MAGIC_SIZE 8
    uint8_t magic[VENDOR_BOOT_MAGIC_SIZE];
    uint32_t header_version;
    uint32_t page_size;           /* flash page size we assume */

    uint32_t kernel_addr;         /* physical load addr */
    uint32_t ramdisk_addr;        /* physical load addr */

    uint32_t vendor_ramdisk_size; /* size in bytes */

#define VENDOR_BOOT_ARGS_SIZE 2048
    uint8_t cmdline[VENDOR_BOOT_ARGS_SIZE];

    uint32_t tags_addr;           /* physical addr for kernel tags */

#define VENDOR_BOOT_NAME_SIZE 16
    uint8_t name[VENDOR_BOOT_NAME_SIZE]; /* asciiz product name */
    uint32_t header_size;         /* size of vendor boot image header in
                                   * bytes */
    uint32_t dtb_size;            /* size of dtb image */
    uint64_t dtb_addr;            /* physical load address */

    uint32_t vendor_ramdisk_table_size; /* size in bytes for the vendor ramdisk table */
    uint32_t vendor_ramdisk_table_entry_num; /* number of entries in the vendor ramdisk table */
    uint32_t vendor_ramdisk_table_entry_size; /* size in bytes for a vendor ramdisk table entry */
    uint32_t bootconfig_size; /* size in bytes for the bootconfig section */
};

#define VENDOR_RAMDISK_TYPE_NONE 0
#define VENDOR_RAMDISK_TYPE_PLATFORM 1
#define VENDOR_RAMDISK_TYPE_RECOVERY 2
#define VENDOR_RAMDISK_TYPE_DLKM 3

struct vendor_ramdisk_table_entry_v4
{
    uint32_t ramdisk_size; /* size in bytes for the ramdisk image */
    uint32_t ramdisk_offset; /* offset to the ramdisk image in vendor ramdisk section */
    uint32_t ramdisk_type; /* type of the ramdisk */
#define VENDOR_RAMDISK_NAME_SIZE 32
    uint8_t ramdisk_name[VENDOR_RAMDISK_NAME_SIZE]; /* asciiz ramdisk name */

#define VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE 16
    // Hardware identifiers describing the board, soc or platform which this
    // ramdisk is intended to be loaded on.
    uint32_t board_id[VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE];
};
  • vendor_ramdisk_size是所有供應商虛擬盤片段的總大小。
  • ramdisk_type表示虛擬盤的類型,可能的值為:
    • VENDOR_RAMDISK_TYPE_NONE指示值是不確定的。
    • VENDOR_RAMDISK_TYPE_PLATFORM的ramdisk包含平台特定位。引導加載程序必須始終將這些加載到內存中。
    • VENDOR_RAMDISK_TYPE_RECOVERY的ramdisk包含回收資源。引導加載程序在啟動恢復時必須將這些加載到內存中。
    • VENDOR_RAMDISK_TYPE_DLKM的ramdisk包含動態加載的內核模塊。
  • ramdisk_name是ramdisk上的唯一名字。
  • board_id是供應商定義的硬件標識符的矢量。

引導加載程序支持

由於供應商引導分區包含先前存在於引導分區中的信息(例如閃存頁面大小、內核、ramdisk 加載地址、DTB 本身),因此引導加載程序必須同時訪問引導分區和供應商引導分區以獲得足夠的數據來完成引導.

引導加載程序必須在通用虛擬盤加載到內存立即供應商虛擬盤以下(在CPIO,gzip和LZ4格式支持這種類型的級聯的)。不要頁面對齊通用 ramdisk 映像或在它和內存中供應商 ramdisk 的末尾之間引入任何其他空間。內核解壓縮後,提取連結文件到initramfs ,它生成的文件結構,這對供應商的ramdisk文件結構的通用RAMDISK覆蓋。

因為通用 ramdisk 和供應商 ramdisk 連接在一起,所以它們必須採用相同的格式。 GKI 啟動映像使用 lz4 壓縮的通用 ramdisk,因此符合 GKI 的設備必須使用 lz4 壓縮的供應商 ramdisk。其配置如下所示。

支持BOOTCONFIG引導程序要求上解釋實施BOOTCONFIG頁。

多個供應商 ramdisk(版本 4)

與引導映像頭版本4,引導加載程序可以選擇一個子集或全部供應商的ramdisk到負載作為的initramfs期間啟動時間。供應商 ramdisk 表包含每個 ramdisk 的元數據,可以幫助引導加載程序決定加載哪些 ramdisk。引導加載程序可以決定加載所選供應商 ramdisk 的順序,只要最後加載通用 ramdisk。

例如,引導加載程序可以省略類型的負載供應商的ramdisk VENDOR_RAMDISK_TYPE_RECOVERY正常引導,以節約資源期間,因此,只有供應商類型的的ramdisk VENDOR_RAMDISK_TYPE_PLATFORMVENDOR_RAMDISK_TYPE_DLKM被加載到存儲器。在另一方面,類型的供應商的ramdisk VENDOR_RAMDISK_TYPE_PLATFORMVENDOR_RAMDISK_TYPE_RECOVERYVENDOR_RAMDISK_TYPE_DLKM被引導進入恢復模式在被加載到存儲器中。

或者,引導加載程序可以忽略供應商 ramdisk 表並加載整個供應商 ramdisk 部分。此具有相同的效果一樣加載所有供應商虛擬盤片段在vendor_boot分區。

建立支持

要為設備實現供應商啟動支持:

  • 設置BOARD_BOOT_HEADER_VERSION3或者更大。

  • 設置BOARD_RAMDISK_USE_LZ4true ,如果你的設備是否符合GKI-,或者如果它以其他方式使用LZ4壓縮一般性RAMDISK。

  • 設置BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE為您的設備合適的大小,考慮到內核模塊必須在供應商的ramdisk。

  • 更新AB_OTA_PARTITIONS包括vendor_boot和設備上的OTA分區的任何供應商的具體名單。

  • 手機複製fstab/first_stage_ramdiskvendor_boot分區,而不是boot分區。例如, $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM)

要在多供應商的ramdisk vendor_boot

  • 設置BOARD_BOOT_HEADER_VERSION4
  • 設置BOARD_VENDOR_RAMDISK_FRAGMENTS被列入到邏輯供應商RAMDISK片段名稱的列表vendor_boot

  • 要添加一個預置的供應商RAMDISK,集BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT到預置的文件路徑。

  • 要添加DLKM廠商RAMDISK,集BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS到內核模塊的目錄列表包括在內。

  • 設置BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGSmkbootimg參數。這些是--board_id[0-15]--ramdisk_type參數為供應商虛擬盤片段。對於DLKM廠商RAMDISK,默認--ramdisk_typeDLKM ,如果它不另有規定。

要建立回收資源作為一個獨立的recovery中的ramdisk vendor_boot

  • 設置BOARD_BOOT_HEADER_VERSION4
  • 設置BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOTtrue
  • 設置BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOTtrue
  • 這增加了其供應商RAMDISK片段ramdisk_namerecoveryramdisk_typeVENDOR_RAMDISK_TYPE_RECOVERY 。 ramdisk上則包含所有恢復文件,這些文件在安裝文件$(TARGET_RECOVERY_ROOT_OUT)

mkbootimg參數

爭論描述
--ramdisk_type類型的虛擬盤的,可以是一個NONEPLATFORMRECOVERYDLKM
--board_id[0-15]指定board_id矢量,默認為0

下面是一個示例配置:

BOARD_KERNEL_MODULE_DIRS := foo bar baz
BOARD_BOOT_HEADER_VERSION := 4
BOARD_VENDOR_RAMDISK_FRAGMENTS := dlkm_foobar
BOARD_VENDOR_RAMDISK_FRAGMENT.dlkm_foobar.KERNEL_MODULE_DIRS := foo bar
BOARD_VENDOR_RAMDISK_FRAGMENT.dlkm_foobar.MKBOOTIMG_ARGS := --board_id0 0xF00BA5 --board_id1 0xC0FFEE

將所得vendor_boot將包括兩個供應商虛擬盤片段。第一個是“默認”的ramdisk,其中包含DLKM目錄baz和文件中其餘$(TARGET_VENDOR_RAMDISK_OUT)第二個是dlkm_foobar虛擬盤,其中包含了目錄DLKM foobar ,以及--ramdisk_type默認為DLKM