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_PLATFORMRAM ディスクには、プラットフォーム固有のビットが含まれています。 ブートローダーは、これらを常にメモリに読み込む必要があります。VENDOR_RAMDISK_TYPE_RECOVERYRAM ディスクにはリカバリ リソースが含まれています。ブートローダーは、リカバリでの起動時にこれらをメモリに読み込む必要があります。VENDOR_RAMDISK_TYPE_DLKMRAM ディスクには、動的に読み込み可能なカーネル モジュールが含まれています。
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_PLATFORM、VENDOR_RAMDISK_TYPE_RECOVERY、VENDOR_RAMDISK_TYPE_DLKM タイプのベンダー RAM ディスクは、リカバリモードで起動したときにメモリに読み込まれます。
また、ブートローダーは、ベンダー RAM ディスク テーブルを無視して、ベンダー RAM ディスク セクション全体を読み込むこともできます。このときの動作は、vendor_boot パーティション内のすべてのベンダー RAM ディスク フラグメントを読み込む場合と同じ効果を持ちます。
ビルドサポート
デバイスにベンダーブートのサポートを実装するには、次の操作を行います。
BOARD_BOOT_HEADER_VERSIONを3以上に設定します。デバイスが GKI に準拠している場合、またはそれ以外の場合で lz4 で圧縮された汎用 RAM ディスクを使用している場合は
BOARD_RAMDISK_USE_LZ4をtrueに設定します。ベンダーの 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_VERSIONを4に設定します。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_ARGSをmkbootimg引数に設定します。これらは、ベンダーの RAM ディスク フラグメントの--board_id[0-15]引数と--ramdisk_type引数です。DLKM ベンダー RAM ディスクの場合、特に指定されていない限り、デフォルトの--ramdisk_typeはDLKMになります。
vendor_boot でリカバリ リソースをスタンドアロンの recovery RAM ディスクとしてビルドするには:
BOARD_BOOT_HEADER_VERSIONを4に設定します。BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOTをtrueに設定します。BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOTをtrueに設定します。- これにより、
ramdisk_nameがrecoveryで、ramdisk_typeがVENDOR_RAMDISK_TYPE_RECOVERYのベンダー RAM ディスク フラグメントが追加されます。その場合、RAM ディスクにはすべてのリカバリ ファイルが含まれます。これらのファイルは$(TARGET_RECOVERY_ROOT_OUT)にインストールされています。
mkbootimg の引数
| 引数 | 説明 |
|---|---|
--ramdisk_type |
RAM ディスクの種類。NONE、PLATFORM、RECOVERY、DLKM のいずれかを指定できます。
|
--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 になります。