Anbieter-Boot-Partitionen

Mit Sammlungen den Überblick behalten Sie können Inhalte basierend auf Ihren Einstellungen speichern und kategorisieren.

Android 11 führte das Konzept des Generic Kernel Image (GKI) ein. Um ein einfaches Booten eines beliebigen Geräts mit der GKI zu ermöglichen, können Android 11-Geräte den Boot-Image-Header Version 3 verwenden. In Version 3 werden alle herstellerspezifischen Informationen aus der boot Partition herausgerechnet und in eine neue vendor_boot -Partition verschoben. Ein ARM64-Gerät, das mit Android 11 auf dem 5.4-Linux-Kernel gestartet wird, muss die vendor_boot Partition und das aktualisierte boot Partitionsformat unterstützen, um die Tests mit der GKI zu bestehen.

Android 12-Geräte können die Boot-Image-Header-Version 4 verwenden, die das Einschließen mehrerer Anbieter-Ramdisks in die vendor_boot Partition unterstützt. Mehrere Vendor-Ramdisk-Fragmente werden im Vendor-Ramdisk-Abschnitt nacheinander verkettet. Eine Vendor-Ramdisk-Tabelle wird verwendet, um das Layout des Vendor-Ramdisk-Abschnitts und die Metadaten jedes Vendor-Ramdisk-Fragments zu beschreiben.

Partitionsstruktur

Die Bootpartition des Anbieters ist A/B-geladen mit virtuellem A/B und durch Android Verified Boot geschützt.

Fassung 3

Die Partition besteht aus einem Header, der Ramdisk des Anbieters und dem Device Tree Blob (DTB).

Abschnitt Seitenzahl
Boot-Header des Anbieters (n Seiten) n = (2112 + page_size - 1) / page_size
Anbieter Ramdisk (o Seiten) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (p Seiten) p = (dtb_size + page_size - 1) / page_size

Fassung 4

Die Partition besteht aus einem Header, dem Vendor-Ramdisk-Abschnitt (bestehend aus allen Vendor-Ramdisk-Fragmenten, verkettet), dem Device Tree Blob (DTB) und der Vendor-Ramdisk-Tabelle.

Abschnitt Seitenzahl
Boot-Header des Anbieters (n Seiten) n = (2128 + page_size - 1) / page_size
Hersteller-Ramdisk-Fragmente (o Seiten) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (p Seiten) p = (dtb_size + page_size - 1) / page_size
Hersteller-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

Boot-Header des Anbieters

Der Inhalt des Hersteller-Startpartitions-Headers besteht hauptsächlich aus Daten, die aus dem Start-Image-Header dorthin verschoben wurden. Es enthält auch Informationen über die Ramdisk des Herstellers.

Fassung 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 */

};

Fassung 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 Ramdisk-Fragmente des Anbieters.
  • ramdisk_type bezeichnet den Typ der Ramdisk, mögliche Werte sind:
    • VENDOR_RAMDISK_TYPE_NONE gibt an, dass der Wert nicht angegeben ist.
    • VENDOR_RAMDISK_TYPE_PLATFORM Ramdisks enthalten plattformspezifische Bits. Der Bootloader muss diese immer in den Speicher laden.
    • VENDOR_RAMDISK_TYPE_RECOVERY Ramdisks enthalten Wiederherstellungsressourcen. Der Bootloader muss diese beim Booten in die Wiederherstellung in den Arbeitsspeicher laden.
    • VENDOR_RAMDISK_TYPE_DLKM Ramdisks enthalten dynamisch ladbare Kernelmodule.
  • ramdisk_name ist ein eindeutiger Name der Ramdisk.
  • board_id ist ein Vektor von anbieterdefinierten Hardwarekennungen.

Bootloader-Unterstützung

Da die Boot-Partition des Anbieters Informationen enthält (z. B. Flash-Seitengröße, Kernel, Ladeadressen der Ramdisk, den DTB selbst), die zuvor in der Boot-Partition vorhanden waren, muss der Bootloader sowohl auf die Boot- als auch auf die Boot-Partition des Anbieters zugreifen, um genügend Daten zum Abschließen des Bootens zu haben .

Der Bootloader muss die generische Ramdisk unmittelbar nach der Anbieter-Ramdisk in den Speicher laden (die Formate CPIO, Gzip und lz4 unterstützen diese Art der Verkettung). Richten Sie das generische Ramdisk-Image nicht an den Seiten aus und fügen Sie keine anderen Leerzeichen zwischen ihm und dem Ende der Anbieter-Ramdisk im Speicher ein. Nachdem der Kernel dekomprimiert hat, extrahiert er die verkettete Datei in ein initramfs , was zu einer Dateistruktur führt, bei der es sich um eine generische Ramdisk handelt, die der Dateistruktur der Ramdisk des Anbieters überlagert ist.

Da die generische Ramdisk und die Anbieter-Ramdisk verkettet werden, müssen sie dasselbe Format haben. Das GKI-Boot-Image verwendet eine lz4-komprimierte generische Ramdisk, sodass ein Gerät, das GKI-konform ist, eine lz4-komprimierte Ramdisk eines Anbieters verwenden muss. Die Konfiguration dafür ist unten dargestellt.

Die Bootloader-Anforderungen zur Unterstützung von bootconfig werden auf der Seite Implementing Bootconfig erläutert.

Ramdisks mehrerer Anbieter (Version 4)

Mit der Boot-Image-Header-Version 4 kann der Bootloader entweder eine Teilmenge oder alle Ramdisks des Herstellers auswählen, die während des Bootens als initramfs geladen werden sollen. Die Hersteller-Ramdisk-Tabelle enthält die Metadaten jeder Ramdisk und kann dem Bootloader bei der Entscheidung helfen, welche Ramdisk geladen werden soll. Der Bootloader kann entscheiden, in welcher Reihenfolge die ausgewählten Hersteller-Ramdisks geladen werden, solange die generische Ramdisk zuletzt geladen wird.

Beispielsweise kann der Bootloader das Laden von Anbieter-Ramdisks des Typs VENDOR_RAMDISK_TYPE_RECOVERY während des normalen Bootens auslassen, um Ressourcen zu sparen, sodass nur Anbieter-Ramdisks des Typs VENDOR_RAMDISK_TYPE_PLATFORM und VENDOR_RAMDISK_TYPE_DLKM in den Arbeitsspeicher geladen werden. Andererseits werden Hersteller-Ramdisks vom Typ VENDOR_RAMDISK_TYPE_PLATFORM , VENDOR_RAMDISK_TYPE_RECOVERY und VENDOR_RAMDISK_TYPE_DLKM beim Booten im Wiederherstellungsmodus in den Arbeitsspeicher geladen.

Alternativ kann der Bootloader die Vendor-Ramdisk-Tabelle ignorieren und den gesamten Vendor-Ramdisk-Abschnitt laden. Dies hat den gleichen Effekt wie das Laden aller Ramdisk-Fragmente des Herstellers in der vendor_boot Partition.

Unterstützung aufbauen

So implementieren Sie Anbieter-Boot-Unterstützung für ein Gerät:

  • Setzen BOARD_BOOT_HEADER_VERSION auf 3 oder höher.

  • Setzen BOARD_RAMDISK_USE_LZ4 auf „ true “, wenn Ihr Gerät GKI-kompatibel ist oder anderweitig eine lz4-komprimierte generische Ramdisk verwendet.

  • Stellen Sie BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE auf eine angemessene Größe für Ihr Gerät ein, unter Berücksichtigung der Kernel-Module, die auf der Ramdisk des Anbieters installiert werden müssen.

  • Aktualisieren AB_OTA_PARTITIONS , um vendor_boot und alle herstellerspezifischen Listen von OTA-Partitionen auf dem Gerät einzuschließen.

  • Kopieren Sie Ihre Geräte- fstab in /first_stage_ramdisk in der vendor_boot Partition, nicht in der boot Partition. Beispiel: $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM) .

So schließen Sie mehrere Hersteller-Ramdisks in vendor_boot :

  • Legen Sie BOARD_BOOT_HEADER_VERSION auf 4 fest.
  • Legen Sie BOARD_VENDOR_RAMDISK_FRAGMENTS auf eine Liste mit logischen Ramdisk-Fragmentnamen von Anbietern fest, die in vendor_boot eingeschlossen werden sollen.

  • Um eine vorgefertigte Ramdisk eines Anbieters hinzuzufügen, legen BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT auf den vorgefertigten Dateipfad fest.

  • Um eine Ramdisk eines DLKM-Anbieters hinzuzufügen, setzen BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS auf die Liste der einzuschließenden Kernel-Modulverzeichnisse.

  • Setzen BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS auf mkbootimg Argumente. Dies sind die Argumente --board_id[0-15] und --ramdisk_type für das Ramdisk-Fragment des Anbieters. Für Ramdisk des DLKM-Anbieters wäre der Standardwert für --ramdisk_type DLKM , wenn nicht anders angegeben.

So erstellen Sie Wiederherstellungsressourcen als eigenständige recovery -Ramdisk in vendor_boot :

  • Legen Sie BOARD_BOOT_HEADER_VERSION auf 4 fest.
  • Setzen BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT auf true .
  • Setzen BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT auf true .
  • Dadurch wird ein Anbieter-Ramdisk-Fragment hinzugefügt, dessen ramdisk_name recovery und ramdisk_type VENDOR_RAMDISK_TYPE_RECOVERY . Die Ramdisk enthält dann alle Wiederherstellungsdateien, die unter $(TARGET_RECOVERY_ROOT_OUT) installiert sind.

mkbootimg Argumente

Streit Beschreibung
--ramdisk_type Der Typ der Ramdisk kann entweder NONE , PLATFORM , RECOVERY oder DLKM .
--board_id[0-15] Geben Sie den board_id Vektor an, standardmäßig 0 .

Nachfolgend 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

Der sich daraus ergebende „ vendor_boot würde zwei Anbieter-Ramdisk-Fragmente enthalten. Die erste ist die "Standard"-Ramdisk, die das DLKM-Verzeichnis baz und den Rest der Dateien in $(TARGET_VENDOR_RAMDISK_OUT) . Die zweite ist die Ramdisk dlkm_foobar , die die DLKM-Verzeichnisse foo und bar enthält, und --ramdisk_type standardmäßig DLKM .