Mit Android 11 wurde das Konzept des generischen Kernel-Images (GKI) eingeführt. Um das Starten eines beliebigen Geräts mit der GKI zu ermöglichen, können Android 11-Geräte die Boot-Image-Header-Version 3 verwenden. In Version 3 werden alle anbieterspezifischen Informationen aus der boot
-Partition entfernt und in eine neue vendor_boot
-Partition verschoben. Ein ARM64-Gerät, das mit Android 11 auf dem Linux-Kernel 5.4 gestartet wird, muss die vendor_boot
-Partition und das aktualisierte boot
-Partitionsformat unterstützen, um die GKI-Tests zu bestehen.
Android 12-Geräte können die Boot-Image-Header-Version 4 verwenden, die die Aufnahme von Ramdisks mehrerer Anbieter in die vendor_boot
-Partition unterstützt. Mehrere Anbieter-Ramdisk-Fragmente werden im Abschnitt „Anbieter-Ramdisk“ nacheinander zusammengefügt. Eine Anbieter-Ramdisk-Tabelle wird verwendet, um das Layout des Anbieter-RAMdisk-Abschnitts und die Metadaten jedes Anbieter-Rahmendisk-Fragments zu beschreiben.
Partitionsstruktur
Die Bootpartition des Anbieters ist A/B-gespiegelt mit virtuellem A/B und durch den verifizierten Bootmodus von Android geschützt.
Version 3
Die Partition besteht aus einem Header, der Anbieter-RAMdisk und dem Device Tree Blob (DTB).
Abschnitt | Seitenzahl |
---|---|
Anbieter-Boot-Header (n Seiten) | n = (2112 + page_size - 1) / page_size |
Anbieter-Ramdisk (o-Seiten) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
DTB (Seiten) | p = (dtb_size + page_size - 1) / page_size |
Version 4
Die Partition besteht aus einem Header, dem Anbieter-Ramdisk-Abschnitt (bestehend aus allen zusammenhängenden Anbieter-Ramdisk-Fragmenten), dem Device-Tree-Blob (DTB) und der Anbieter-Ramdisk-Tabelle.
Abschnitt | Seitenzahl |
---|---|
Anbieter-Boot-Header (n Seiten) | n = (2128 + page_size - 1) / page_size |
Anbieter-RAM-Disk-Fragmente (o-Seiten) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
DTB (p-Seiten) | p = (dtb_size + page_size - 1) / page_size |
Anbieter-Ramdisk-Tabelle (Q-Seiten) | q = (vendor_ramdisk_table_size + page_size - 1) / page_size |
Bootconfig (R-Seiten) | r = (bootconfig_size + page_size - 1) / page_size |
Anbieter-Boot-Header
Der Inhalt des Boot-Partitions-Headers des Anbieters besteht hauptsächlich aus Daten, die aus dem Boot-Image-Header dorthin verschoben wurden. Es enthält auch Informationen zum Anbieter ramdisk.
Version 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 */
};
Version 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
ist die Gesamtgröße aller RAM-Disk-Fragmente des Anbieters.ramdisk_type
gibt den Typ des RAM-Laufwerks an. Mögliche Werte sind:VENDOR_RAMDISK_TYPE_NONE
gibt an, dass der Wert nicht angegeben ist.VENDOR_RAMDISK_TYPE_PLATFORM
-RAMdisks enthalten plattformspezifische Bits. Sie müssen vom Bootloader immer in den Arbeitsspeicher geladen werden.VENDOR_RAMDISK_TYPE_RECOVERY
RAMdisks enthalten Wiederherstellungsressourcen. Der Bootloader muss diese beim Starten in den Wiederherstellungsmodus in den Arbeitsspeicher laden.VENDOR_RAMDISK_TYPE_DLKM
RAM-Disks enthalten dynamisch ladbare Kernelmodule.
ramdisk_name
ist ein eindeutiger Name für das RAM-Disk.board_id
ist ein Vektor von vom Anbieter definierten Hardware-IDs.
Bootloader-Unterstützung
Da die Bootpartition des Anbieters Informationen wie die Flash-Seitengröße, den Kernel, die Ramdisk-Ladeadressen und das DTB selbst enthält, die zuvor in der Bootpartition vorhanden waren, muss der Bootloader sowohl auf die Boot- als auch auf die Bootpartition des Anbieters zugreifen, um genügend Daten für den vollständigen Startvorgang zu haben.
Der Bootloader muss die allgemeine Ramdisk direkt nach der Ramdisk des Anbieters in den Arbeitsspeicher laden. Die Formate CPIO, Gzip und Lz4 unterstützen diese Art der Verkettung. Das generische RAM-Disk-Image darf nicht seitenausgerichtet werden und es darf auch keinen anderen Speicherplatz zwischen ihm und dem Ende des RAM-Disks des Anbieters geben. Nachdem der Kernel die Dekomprimierung abgeschlossen hat, wird die zusammengesetzte Datei in eine initramfs
extrahiert. Dies führt zu einer Dateistruktur, die ein generisches RAM-Disk ist, das über die RAM-Disk-Dateistruktur des Anbieters gelegt wird.
Da die generische Ramdisk und die Anbieter-Ramdisk verkettet werden, müssen sie dasselbe Format haben. Das GKI-Boot-Image verwendet ein LZ4-komprimiertes generisches RAM-Disk. Daher muss ein GKI-kompatibles Gerät ein LZ4-komprimiertes RAM-Disk des Anbieters verwenden. Die Konfiguration dafür ist unten dargestellt.
Die Bootloader-Anforderungen zur Unterstützung von Bootconfig werden unter Bootconfig implementieren erläutert.
RAM-Disks mehrerer Anbieter (Version 4)
Bei der Boot-Image-Header-Version 4 kann der Bootloader entweder einen Teil oder alle RAM-Disks des Anbieters auswählen, die während des Bootens als initramfs
geladen werden sollen. Die RAM-Disk-Tabelle des Anbieters enthält die Metadaten der einzelnen RAM-Disks und kann dem Bootloader bei der Entscheidung helfen, welche RAM-Disks geladen werden sollen. Der Bootloader kann die Reihenfolge zum Laden der Ramdisks des ausgewählten Anbieters festlegen, solange die allgemeine RAM-Disk zuletzt geladen wird.
Beispielsweise kann der Bootloader das Laden von RAM-Disks vom Typ VENDOR_RAMDISK_TYPE_RECOVERY
beim normalen Starten auslassen, um Ressourcen zu sparen. So werden nur RAM-Disks vom Typ VENDOR_RAMDISK_TYPE_PLATFORM
und VENDOR_RAMDISK_TYPE_DLKM
in den Arbeitsspeicher geladen. Anbieter-RAM-Disks vom Typ VENDOR_RAMDISK_TYPE_PLATFORM
, VENDOR_RAMDISK_TYPE_RECOVERY
und VENDOR_RAMDISK_TYPE_DLKM
werden dagegen in den Arbeitsspeicher geladen, wenn der Computer im Wiederherstellungsmodus gestartet wird.
Alternativ kann der Bootloader die Ramdisk-Tabelle des Anbieters ignorieren und den gesamten Abschnitt mit Ramdisk des Anbieters laden. Dies hat denselben Effekt wie das Laden aller Ramdisk-Fragmente des Anbieters in die Partition vendor_boot
.
Unterstützung aufbauen
So implementieren Sie die Unterstützung für den Anbieterstart für ein Gerät:
Legen Sie
BOARD_BOOT_HEADER_VERSION
auf3
oder höher fest.Legen Sie
BOARD_RAMDISK_USE_LZ4
auftrue
fest, wenn Ihr Gerät GKI-kompatibel ist oder andernfalls ein lz4-komprimiertes generisches RAM-Disk verwendet.Legen Sie für
BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE
eine geeignete Größe für Ihr Gerät fest. Berücksichtigen Sie dabei die Kernelmodule, die auf der Ramdisk des Anbieters gespeichert werden müssen.Aktualisieren Sie
AB_OTA_PARTITIONS
, umvendor_boot
und alle anbieterspezifischen Listen der OTA-Partitionen auf dem Gerät einzuschließen.Kopieren Sie
fstab
auf dem Gerät in/first_stage_ramdisk
in der Partitionvendor_boot
, nicht in der Partitionboot
. Beispiel:$(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM)
.
So fügen Sie mehrere Anbieter-Ramdisks in vendor_boot
ein:
- Legen Sie
BOARD_BOOT_HEADER_VERSION
auf4
fest. Legen Sie
BOARD_VENDOR_RAMDISK_FRAGMENTS
auf eine Liste logischer Namen von RAM-Disk-Fragmenten des Anbieters fest, die invendor_boot
aufgenommen werden sollen.Wenn Sie ein vorkonfiguriertes RAM-Disk des Anbieters hinzufügen möchten, setzen Sie
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT
auf den vorkonfigurierten Pfad.Wenn Sie ein DLKM-Anbieter-Ramdisk hinzufügen möchten, setzen Sie
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS
in die Liste der zu berücksichtigenden Kernelmodulverzeichnisse.Legen Sie für
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS
die Argumentemkbootimg
fest. Das sind die Argumente--board_id[0-15]
und--ramdisk_type
für das Anbieter-Ramdisk-Fragment. Für das DLKM-RAM-Disk des Anbieters istDLKM
der Standardwert für--ramdisk_type
, sofern nicht anders angegeben.
So erstellen Sie Wiederherstellungsressourcen als eigenständiges recovery
-Ramdisk in vendor_boot
:
- Legen Sie
BOARD_BOOT_HEADER_VERSION
auf4
fest. - Setzen Sie
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT
auftrue
. - Setzen Sie
BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT
auftrue
. - Dadurch wird ein Anbieter-Ramdisk-Fragment hinzugefügt, dessen
ramdisk_name
recovery
undramdisk_type
VENDOR_RAMDISK_TYPE_RECOVERY
ist. Das RAM-Disk enthält dann alle Wiederherstellungsdateien, die unter$(TARGET_RECOVERY_ROOT_OUT)
installiert sind.
mkbootimg-Argumente
Argument | Beschreibung |
---|---|
--ramdisk_type |
Der Typ des RAM-Disks kann NONE , PLATFORM , RECOVERY oder DLKM sein.
|
--board_id[0-15] |
Geben Sie den Vektor board_id an. Der Standardwert ist 0 . |
Es folgt eine Beispielkonfiguration:
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
Das resultierende vendor_boot
würde zwei Ramdisk-Fragmente des Anbieters enthalten. Die erste ist die Standard-RAMdisk, die das DLKM-Verzeichnis baz
und die restlichen Dateien in $(TARGET_VENDOR_RAMDISK_OUT)
enthält. Das zweite ist das dlkm_foobar
-Ramdisk, das die DLKM-Verzeichnisse foo
und bar
enthält. Der Standardwert für --ramdisk_type
ist DLKM
.