ベンダーブート パーティション

Android 11 では、汎用カーネル イメージ(GKI)という概念が導入されています。GKI を使用して任意のデバイスを簡単に起動できるように、Android 11 ではブートイメージ ヘッダー バージョン 3 を使用できます。バージョン 3 では、ベンダー固有の情報はすべて boot パーティションから移動され、新しい vendor_boot パーティションに再配置されています。5.4 Linux カーネルに Android 11 を搭載した ARM64 デバイスは、vendor_boot パーティションと更新された boot パーティション形式をサポートして、GKI を使用したテストに合格する必要があります。

Android 12 では、ブートイメージ ヘッダー バージョン 4 を使用できます。このバージョンでは vendor_boot パーティションに複数のベンダー RAM ディスクを格納できます。複数のベンダー RAM ディスク フラグメントは、ベンダー RAM ディスク セクションで連続して連結されます。ベンダー RAM ディスク テーブルは、ベンダー RAM ディスク セクションのレイアウトと、各ベンダー RAM ディスク フラグメントのメタデータを記述するために使用されます。

パーティションの構造

ベンダー ブート パーティションは、仮想 A/B で A/B が作成され、Android の確認付きブートによって保護されます。

バージョン 3

このパーティションは、ヘッダー、ベンダー RAM ディスク、デバイスツリー blob(DTB)で構成されます。

セクション ページ数
ベンダーの起動ヘッダー(n ページ) n = (2112 + page_size - 1) / page_size
ベンダー用 RAM ディスク(o ページ) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB(p ページ) p = (dtb_size + page_size - 1) / page_size

バージョン 4

このパーティションは、ヘッダー、ベンダー RAM ディスク セクション(連結されたすべてのベンダー RAM ディスク フラグメントで構成)、デバイスツリー blob(DTB)、ベンダー RAM ディスク テーブルで構成されます。

セクション ページ数
ベンダーの起動ヘッダー(n ページ) n = (2128 + page_size - 1) / page_size
ベンダー用 RAM ディスク フラグメント(o ページ) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB(p ページ) p = (dtb_size + page_size - 1) / page_size
ベンダー用 RAM ディスク テーブル(q ページ) q = (vendor_ramdisk_table_size + page_size - 1) / page_size
bootconfig(r ページ) r = (bootconfig_size + page_size - 1) / page_size

ベンダー ブートヘッダー

ベンダー ブート パーティション ヘッダーの内容は、主にブートイメージ ヘッダーから再配置されたデータで構成されます。また、ベンダーの RAM ディスクに関する情報も含まれています。

バージョン 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 は、すべてのベンダー RAM ディスク フラグメントの合計サイズです。
  • ramdisk_type は RAM ディスクのタイプを示します。有効な値は次のとおりです。
    • VENDOR_RAMDISK_TYPE_NONE は、値が指定されていないことを示します。
    • VENDOR_RAMDISK_TYPE_PLATFORM RAM ディスクには、プラットフォーム固有のビットが含まれています。 ブートローダーは、これらを常にメモリに読み込む必要があります。
    • VENDOR_RAMDISK_TYPE_RECOVERY RAM ディスクにはリカバリ リソースが含まれています。ブートローダーは、リカバリでの起動時にこれらをメモリに読み込む必要があります。
    • VENDOR_RAMDISK_TYPE_DLKM RAM ディスクには、動的に読み込み可能なカーネル モジュールが含まれています。
  • ramdisk_name は RAM ディスクの固有名です。
  • board_id は、ベンダーが定義したハードウェア識別子のベクトルです。

ブートローダーのサポート

ベンダー ブート パーティションには、ブート パーティションに以前存在していた情報(Flash ページサイズ、カーネル、RAM ディスク アドレス、DTB 自体など)が含まれているため、ブートローダーはブート パーティションとベンダーブート パーティションの両方にアクセスして起動を完了するうえで十分なデータを取得する必要があります。

ブートローダーは、ベンダー RAM ディスクの直後に汎用の RAM ディスクをメモリに読み込む必要があります(CPIO、Gzip、lz4 形式はこのタイプの連結をサポートしています)。汎用の RAM ディスク イメージをページに合わせて配置する、またはベンダー用 RAM ディスクとの間にその他のスペースをメモリ内に配置することはしないでください。カーネルが解凍されると、連結されたファイルが initramfs に抽出されます。これにより、ベンダー用 RAM ディスクのファイル構造にオーバーレイされる汎用 RAM ディスクのファイル構造が生成されます。

汎用の RAM ディスクとベンダー RAM ディスクは連結されるため、同じ形式にする必要があります。GKI ブートイメージは lz4 圧縮の汎用 RAM ディスクを使用するため、GKI に準拠するデバイスは lz4 圧縮のベンダー RAM ディスクを使用する必要があります。その構成を以下に示します。

bootconfig をサポートするためのブートローダーの要件については、Bootconfig の実装ページをご覧ください。

複数のベンダー RAM ディスク(バージョン 4)

ブートイメージ ヘッダー バージョン 4 では、ブートローダーはベンダー RAM ディスクのサブセットまたはすべてを選択して、ブート時に initramfs として読み込むことができます。ベンダー RAM ディスク テーブルには各 RAM ディスクのメタデータが含まれており、ブートローダーが読み込む RAM ディスクを決定する際に役立ちます。ブートローダーは、選択したベンダー RAM ディスクを読み込む順序を決定できます。ただし、汎用の RAM ディスクは最後に読み込む必要があります。

たとえば、通常のブート時に、リソースを節約するために VENDOR_RAMDISK_TYPE_RECOVERY タイプのベンダー RAM ディスクの読み込みを省略できます。この場合、メモリに読み込まれるのは VENDOR_RAMDISK_TYPE_PLATFORM タイプと VENDOR_RAMDISK_TYPE_DLKM タイプのベンダー RAM ディスクのみです。一方、VENDOR_RAMDISK_TYPE_PLATFORMVENDOR_RAMDISK_TYPE_RECOVERYVENDOR_RAMDISK_TYPE_DLKM タイプのベンダー RAM ディスクは、リカバリモードで起動したときにメモリに読み込まれます。

また、ブートローダーは、ベンダー RAM ディスク テーブルを無視して、ベンダー RAM ディスク セクション全体を読み込むこともできます。このときの動作は、vendor_boot パーティション内のすべてのベンダー RAM ディスク フラグメントを読み込む場合と同じ効果を持ちます。

ビルドサポート

デバイスにベンダーブートのサポートを実装するには、次の操作を行います。

  • BOARD_BOOT_HEADER_VERSION3 以上に設定します。

  • デバイスが GKI に準拠している場合、またはそれ以外の場合で lz4 で圧縮された汎用 RAM ディスクを使用している場合は BOARD_RAMDISK_USE_LZ4true に設定します。

  • ベンダーの RAM ディスクに必要なカーネル モジュールを考慮して、BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE をデバイスの適切なサイズに設定します。

  • vendor_boot と、デバイス固有の OTA パーティションのベンダー固有のリストが含まれるように、AB_OTA_PARTITIONS を更新します。

  • boot パーティションではなく vendor_boot パーティションの /first_stage_ramdisk にデバイス fstab をコピーします。例: $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM)

vendor_boot に複数のベンダー RAM ディスクを含めるには:

  • BOARD_BOOT_HEADER_VERSION4 に設定します。
  • BOARD_VENDOR_RAMDISK_FRAGMENTS を、vendor_boot に含める論理ベンダー RAM ディスク フラグメント名のリストに設定します。

  • ビルド済みのベンダー RAM ディスクを追加するには、BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT をビルド済みのファイルパスに設定します。

  • DLKM ベンダー RAM ディスクを追加するには、BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS を、含めるカーネル モジュール ディレクトリのリストに設定します。

  • BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGSmkbootimg 引数に設定します。これらは、ベンダーの RAM ディスク フラグメントの --board_id[0-15] 引数と --ramdisk_type 引数です。DLKM ベンダー RAM ディスクの場合、特に指定されていない限り、デフォルトの --ramdisk_typeDLKM になります。

vendor_boot でリカバリ リソースをスタンドアロンの recovery RAM ディスクとしてビルドするには:

  • BOARD_BOOT_HEADER_VERSION4 に設定します。
  • BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOTtrue に設定します。
  • BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOTtrue に設定します。
  • これにより、ramdisk_namerecovery で、ramdisk_typeVENDOR_RAMDISK_TYPE_RECOVERY のベンダー RAM ディスク フラグメントが追加されます。その場合、RAM ディスクにはすべてのリカバリ ファイルが含まれます。これらのファイルは $(TARGET_RECOVERY_ROOT_OUT) にインストールされています。

mkbootimg 引数

引数 説明
--ramdisk_type RAM ディスクの種類。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 には、2 つのベンダー RAM ディスク フラグメントが含まれます。1 つ目は「デフォルト」の RAM ディスクで、DLKM ディレクトリ baz と、$(TARGET_VENDOR_RAMDISK_OUT) の残りの部分が含まれています。2 つ目は dlkm_foobar RAM ディスクで、DLKM ディレクトリ foo および bar が含まれます。--ramdisk_type のデフォルトは DLKM になります。