В Android 11 появилась концепция образа ядра Generic Kernel Image (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-разделом и проверенной загрузкой Android.
Версия 3
Раздел состоит из заголовка, электронного диска поставщика и двоичного двоичного объекта дерева устройств (DTB).
Раздел | Количество страниц |
---|---|
Заголовок загрузки поставщика (n страниц) | n = (2112 + page_size - 1) / page_size |
ramdisk поставщика (o страниц) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
DTB (стр. страниц) | p = (dtb_size + page_size - 1) / page_size |
Версия 4
Раздел состоит из заголовка, раздела RAM-диска поставщика (состоящего из всех объединенных фрагментов RAM-диска поставщика), двоичного двоичного объекта устройства (DTB) и таблицы RAM-диска поставщика.
Раздел | Количество страниц |
---|---|
Заголовок загрузки поставщика (n страниц) | n = (2128 + page_size - 1) / page_size |
Фрагменты ramdisk поставщика (o страниц) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
DTB (стр. страниц) | 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 |
Загрузочный заголовок поставщика
Содержимое заголовка загрузочного раздела поставщика состоит в основном из данных, перенесённых туда из заголовка загрузочного образа . Он также содержит информацию о 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
— общий размер всех фрагментов ramdisk поставщика. -
ramdisk_type
обозначает тип ramdisk, возможные значения:-
VENDOR_RAMDISK_TYPE_NONE
указывает, что значение не указано. -
VENDOR_RAMDISK_TYPE_PLATFORM
— виртуальные диски содержат платформенно-специфичные биты. Загрузчик всегда должен загружать их в память. - RAM-диски
VENDOR_RAMDISK_TYPE_RECOVERY
содержат ресурсы восстановления. Загрузчик должен загрузить их в память при загрузке в режим восстановления. - RAM-диски
VENDOR_RAMDISK_TYPE_DLKM
содержат динамически загружаемые модули ядра.
-
-
ramdisk_name
— уникальное имя ramdisk. -
board_id
— вектор идентификаторов оборудования, определенных поставщиком.
Поддержка загрузчика
Поскольку загрузочный раздел поставщика содержит информацию (такую как размер страницы флэш-памяти, ядро, адреса загрузки RAM-диска, сам DTB), которая ранее существовала в загрузочном разделе, загрузчик должен получить доступ как к загрузочному разделу, так и к загрузочному разделу поставщика, чтобы получить достаточно данных для завершения загрузки.
Загрузчик должен загрузить универсальный RAM-диск в память сразу после RAM-диска поставщика (форматы CPIO, Gzip и lz4 поддерживают этот тип конкатенации). Не выравнивайте образ универсального RAM-диска по страницам и не добавляйте никаких других пробелов между ним и концом RAM-диска поставщика в памяти. После распаковки ядро извлекает объединенный файл в initramfs
, что приводит к созданию файловой структуры, представляющей собой универсальный RAM-диск, наложенный на файловую структуру RAM-диска поставщика.
Поскольку универсальный RAM-диск и RAM-диск поставщика объединяются, они должны иметь одинаковый формат. Загрузочный образ GKI использует универсальный RAM-диск, сжатый с помощью LZ4, поэтому устройство, совместимое с GKI, должно использовать RAM-диск поставщика, сжатый с помощью LZ4. Конфигурация для этого показана ниже.
Требования к загрузчику для поддержки bootconfig описаны в разделе Реализация Bootconfig .
RAM-диски нескольких поставщиков (версия 4)
С заголовком загрузочного образа версии 4 загрузчик может выбрать либо подмножество, либо все RAM-диски поставщиков для загрузки в качестве 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
загружаются в память при загрузке в режиме восстановления.
В качестве альтернативы загрузчик может игнорировать таблицу RAM-диска вендора и загрузить весь раздел RAM-диска вендора. Это имеет тот же эффект, что и загрузка всех фрагментов RAM-диска вендора в разделе vendor_boot
.
Поддержка сборки
Чтобы реализовать поддержку загрузки поставщика для устройства:
Установите
BOARD_BOOT_HEADER_VERSION
на значение3
или больше.Установите
BOARD_RAMDISK_USE_LZ4
вtrue
, если ваше устройство совместимо с GKI или если оно использует универсальный RAM-диск, сжатый с помощью lz4.Установите
BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE
на соответствующий размер для вашего устройства, учитывая модули ядра, которые должны находиться на ramdisk поставщика.Обновите
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
в список имен логических фрагментов ramdisk поставщика, которые необходимо включить вvendor_boot
.Чтобы добавить готовый ramdisk поставщика, задайте
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT
для готового пути.Чтобы добавить ramdisk поставщика 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
для фрагмента RAM-диска поставщика. Для RAM-диска поставщика 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
. - Это добавляет фрагмент RAM-диска поставщика с
ramdisk_name
recovery
иramdisk_type
VENDOR_RAMDISK_TYPE_RECOVERY
. RAM-диск содержит все файлы восстановления, которые устанавливаются в$(TARGET_RECOVERY_ROOT_OUT)
.
аргументы mkbootimg
Аргумент | Описание |
---|---|
--ramdisk_type | Тип ramdisk может быть 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
будет содержать два фрагмента RAM-диска вендора. Первый — это RAM-диск «по умолчанию», содержащий каталог DLKM baz
и остальные файлы в $(TARGET_VENDOR_RAMDISK_OUT)
. Второй — это RAM-диск dlkm_foobar
, содержащий каталоги DLKM foo
и bar
, а параметр --ramdisk_type
по умолчанию устанавливает DLKM
.