В Android 11 представлена концепция универсального образа ядра (GKI). Чтобы упростить загрузку произвольного устройства с помощью GKI, устройства Android 11 могут использовать заголовок загрузочного образа версии 3. В версии 3 вся информация, относящаяся к поставщику, исключается из boot раздела и перемещается в новый раздел vendor_boot . Устройство ARM64, запускаемое с Android 11 на ядре Linux 5.4, должно поддерживать раздел vendor_boot и обновленный формат boot раздела, чтобы пройти тестирование с помощью GKI.
 Устройства Android 12 могут использовать заголовок загрузочного образа версии 4, который поддерживает включение виртуальных дисков нескольких поставщиков в раздел vendor_boot . Несколько фрагментов виртуального диска поставщика объединяются один за другим в разделе виртуального диска поставщика. Таблица виртуального диска поставщика используется для описания структуры раздела виртуального диска поставщика и метаданных каждого фрагмента виртуального диска поставщика.
Структура разделов
Загрузочный раздел поставщика помечен как A/B с виртуальным A/B и защищен проверенной загрузкой Android.
Версия 3
Раздел состоит из заголовка, виртуального диска поставщика и большого двоичного объекта дерева устройств (DTB).
| Раздел | Число страниц | 
|---|---|
| Загрузочный заголовок поставщика (n страниц) | n = (2112 + page_size - 1) / page_size | 
| Виртуальный диск производителя (o страниц) | o = (vendor_ramdisk_size + page_size - 1) / page_size | 
| ДТБ (стр.) | p = (dtb_size + page_size - 1) / page_size | 
Версия 4
Раздел состоит из заголовка, раздела виртуального диска поставщика (состоящего из всех объединенных фрагментов виртуального диска поставщика), большого двоичного объекта дерева устройств (DTB) и таблицы виртуального диска поставщика.
| Раздел | Число страниц | 
|---|---|
| Загрузочный заголовок поставщика (n страниц) | n = (2128 + page_size - 1) / page_size | 
| Фрагменты виртуального диска поставщика (o страниц) | o = (vendor_ramdisk_size + page_size - 1) / page_size | 
| ДТБ (стр.) | p = (dtb_size + page_size - 1) / page_size | 
| Таблица виртуального диска поставщика (q страниц) | q = (vendor_ramdisk_table_size + page_size - 1) / page_size | 
| Bootconfig (r страниц) | r = (bootconfig_size + page_size - 1) / page_size | 
Загрузочный заголовок поставщика
Содержимое заголовка загрузочного раздела поставщика состоит в основном из данных, перемещенных туда из заголовка загрузочного образа . Он также содержит информацию о виртуальном диске поставщика.
Версия 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указывает, что значение не указано.
-  RAM- VENDOR_RAMDISK_TYPE_PLATFORMсодержат специфичные для платформы биты. Загрузчик всегда должен загружать их в память.
-  VENDOR_RAMDISK_TYPE_RECOVERYсодержат ресурсы для восстановления. Загрузчик должен загрузить их в память при загрузке в рекавери.
-  VENDOR_RAMDISK_TYPE_DLKMсодержат динамически загружаемые модули ядра.
 
-  
-  ramdisk_name— уникальное имя RAM-диска.
-  board_id— это вектор определяемых поставщиком идентификаторов оборудования.
Поддержка загрузчика
Поскольку загрузочный раздел поставщика содержит информацию (такую как размер флэш-страницы, ядро, загрузочные адреса виртуального диска, сам DTB), которая ранее существовала в загрузочном разделе, загрузчик должен получить доступ как к загрузочному разделу, так и к загрузочному разделу поставщика, чтобы иметь достаточно данных для завершения загрузки. .
 Загрузчик должен загрузить общий виртуальный диск в память сразу после виртуального диска поставщика (форматы CPIO, Gzip и lz4 поддерживают этот тип конкатенации). Не выравнивайте общий образ виртуального диска по страницам и не добавляйте в память никакого другого пробела между ним и концом виртуального диска поставщика. После распаковки ядра оно извлекает объединенный файл в initramfs , в результате чего файловая структура представляет собой общий виртуальный диск, наложенный на файловую структуру виртуального диска поставщика.
Поскольку общий виртуальный диск и виртуальный диск поставщика объединяются, они должны быть в одном и том же формате. Загрузочный образ GKI использует универсальный виртуальный диск со сжатием lz4, поэтому устройство, совместимое с GKI, должно использовать виртуальный диск производителя со сжатием lz4. Конфигурация для этого показана ниже.
Требования к загрузчику для поддержки bootconfig объясняются на странице Реализация Bootconfig .
Виртуальные диски нескольких поставщиков (версия 4)
 С версией заголовка загрузочного образа 4 загрузчик может выбрать либо подмножество, либо все виртуальные диски поставщика для загрузки в качестве initramfs во время загрузки. Таблица RAM-дисков поставщика содержит метаданные каждого RAM-диска и может помочь загрузчику решить, какие RAM-диски загружать. Загрузчик может определить порядок загрузки RAM-дисков выбранного поставщика, если общий RAM-диск загружается последним.
 Например, загрузчик может не загружать виртуальные диски поставщика типа VENDOR_RAMDISK_TYPE_RECOVERY во время обычной загрузки для экономии ресурсов, поэтому в память загружаются только виртуальные диски поставщика типа VENDOR_RAMDISK_TYPE_PLATFORM и VENDOR_RAMDISK_TYPE_DLKM . С другой стороны, виртуальные диски поставщиков типа VENDOR_RAMDISK_TYPE_PLATFORM , VENDOR_RAMDISK_TYPE_RECOVERY и VENDOR_RAMDISK_TYPE_DLKM загружаются в память при загрузке в режиме восстановления.
 Кроме того, загрузчик может игнорировать таблицу виртуального диска поставщика и загружать весь раздел виртуального диска поставщика. Это имеет тот же эффект, что и загрузка всех фрагментов виртуального диска поставщика в разделе vendor_boot .
Создайте поддержку
Чтобы реализовать поддержку загрузки поставщика для устройства:
- Установите для - BOARD_BOOT_HEADER_VERSIONзначение- 3или выше.
- Установите для - BOARD_RAMDISK_USE_LZ4значение- true, если ваше устройство совместимо с GKI, или если оно каким-либо иным образом использует общий виртуальный диск со сжатием lz4.
- Задайте для - BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZEразмер, подходящий для вашего устройства, с учетом модулей ядра, которые должны находиться на виртуальном диске поставщика.
- Обновите - AB_OTA_PARTITIONS, включив в- vendor_bootи любые зависящие от поставщика списки разделов OTA на устройстве.
- Скопируйте - fstabвашего устройства в- /first_stage_ramdiskв разделе- vendor_boot, а не в- bootразделе. Например,- $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM).
 Чтобы включить несколько виртуальных дисков поставщиков в vendor_boot :
-  Установите для BOARD_BOOT_HEADER_VERSIONзначение4.
- Установите - BOARD_VENDOR_RAMDISK_FRAGMENTSв список имен логических фрагментов виртуального диска поставщика, которые будут включены в- vendor_boot.
- Чтобы добавить готовый виртуальный диск поставщика, задайте - BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILTк готовому файлу.
- Чтобы добавить виртуальный диск поставщика DLKM, установите - BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRSв список каталогов модулей ядра, которые необходимо включить.
- Установите - BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGSв аргументы- mkbootimg. Это- --board_id[0-15]и- --ramdisk_typeдля фрагмента виртуального диска поставщика. Для виртуального диска поставщика DLKM значением по умолчанию- --ramdisk_typeбудет- DLKM, если не указано иное.
 Чтобы создать ресурсы восстановления в виде отдельного виртуального диска recovery в vendor_boot :
-  Установите для 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. Затем виртуальный диск содержит все файлы восстановления, которые являются файлами, установленными в$(TARGET_RECOVERY_ROOT_OUT).
 mkbootimg аргументы
| Аргумент | Описание | 
|---|---|
| --ramdisk_type | Тип виртуального диска может быть одним из 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 будет содержать два фрагмента виртуального диска поставщика. Первый — это виртуальный диск «по умолчанию», который содержит каталог DLKM baz и остальные файлы в $(TARGET_VENDOR_RAMDISK_OUT) . Второй — это виртуальный диск dlkm_foobar , который содержит каталоги DLKM foo и bar , а параметр --ramdisk_type по умолчанию имеет значение DLKM .
