Bootpartitionen des Anbieters

Mit Android 11 wurde das Konzept des generischen Kernels eingeführt Bild (GKI). 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 die mit Android 11 auf dem Linux-Kernel 5.4 gestartet werden, die Partition vendor_boot und das aktualisierte Partitionsformat boot, um die Tests mit der Google-KI bestehen.

Android 12-Geräte können die Boot-Image-Header-Version 4 verwenden, die das Einfügen mehrerer RAM-Disks von Anbietern in die vendor_boot-Partition unterstützt. Mehrere Anbieter-Ramdisk-Fragmente werden im Abschnitt „Anbieter-Ramdisk“ nacheinander zusammengefügt. Eine Ramdisk-Tabelle des Anbieters wird verwendet, um Layout des Abschnitts „Vendor ramdisk“ (Anbieter-ramdisk) und die Metadaten der einzelnen anbieter-ramdisk Fragment.

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, dem 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 (p-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
Boot-Header des Anbieters (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 Header der Bootpartition des Anbieters besteht hauptsächlich aus Daten, die dort aus dem Boot-Image-Header verschoben wurden. Außerdem enthält es Informationen zum RAM-Disk des Anbieters.

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 Ramdisk-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. Der Bootloader muss diese immer in den Arbeitsspeicher laden.
    • VENDOR_RAMDISK_TYPE_RECOVERY RAMdisks enthalten Wiederherstellungsressourcen. Die Bootloader muss diese beim Starten zur Wiederherstellung in den Arbeitsspeicher laden.
    • VENDOR_RAMDISK_TYPE_DLKM RAMdisks enthalten einen dynamischen ladbaren Kernel Module.
  • ramdisk_name ist ein eindeutiger Name für das RAM-Disk.
  • board_id ist ein Vektor von anbieterdefinierten Hardware-IDs.

Bootloader-Unterstützung

Da die Bootpartition des Anbieters Informationen wie die Flash-Seitengröße, Kernel, Ramdisk-Ladeadressen, DTB selbst). muss der Bootloader sowohl auf Boot- als auch auf Anbieter-Boot zugreifen können. um genügend Daten für den Startvorgang zu haben.

Der Bootloader muss die generische Ramdisk sofort nach vom Anbieter ramdisk (die Formate CPIO, Gzip und Lz4 unterstützen diese Art von 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. Nach dem Beim Dekomprimieren des Kernels wird die verkettete Datei in ein initramfs-, Das Ergebnis ist eine allgemeine Ramdisk-Datei, anbieter-ramdisk-dateistruktur.

Da die generische ramdisk und die anbieter-ramdisk verkettet werden, müssen sie sich im im selben Format. 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 Implementieren Bootconfig

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 Die Ramdisk-Tabelle des Anbieters enthält die Metadaten jeder Ramdisk und kann dem bei der Entscheidung, welche Ramdisks geladen werden sollen. Der Bootloader kann die Reihenfolge zum Laden der ausgewählten Anbieter-Ramdisks festlegen, solange das generische Ramdisk als letztes geladen wird.

Beispielsweise kann der Bootloader das Laden von Anbieter-RAMdisks des Typs VENDOR_RAMDISK_TYPE_RECOVERY beim normalen Starten, um Ressourcen zu sparen. Anbieter-RAMdisks vom Typ VENDOR_RAMDISK_TYPE_PLATFORM und VENDOR_RAMDISK_TYPE_DLKM werden 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 Vendor-Ramdisk-Tabelle ignorieren und den gesamten Vendor-Ramdisk-Bereich laden. Dies hat denselben Effekt wie das Laden Die Ramdisk-Fragmente des Anbieters in der Partition vendor_boot.

Unterstützung aufbauen

So implementieren Sie die Bootunterstützung des Anbieters für ein Gerät:

  • Legen Sie BOARD_BOOT_HEADER_VERSION auf 3 oder höher fest.

  • Legen Sie BOARD_RAMDISK_USE_LZ4 auf true 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 für Ihr Gerät geeignete Größe fest. Berücksichtigen Sie dabei die Kernelmodule, die auf dem RAM-Disk des Anbieters abgelegt werden müssen.

  • Aktualisieren Sie AB_OTA_PARTITIONS, um vendor_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 Partition vendor_boot, nicht in der Partition boot. 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 auf 4 fest.
  • Setzen Sie BOARD_VENDOR_RAMDISK_FRAGMENTS auf eine Liste mit Ramdisk des logischen Anbieters. in vendor_boot einzuschließende Fragmentnamen.

  • Um eine vordefinierte Ramdisk des Anbieters hinzuzufügen, BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT zu den vordefinierten 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.

  • BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS festlegen auf mkbootimg Argumente. 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 ist DLKM 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 auf 4 fest.
  • Setzen Sie BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT auf true.
  • Setzen Sie 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 ist. Die Ramdisk enthält dann Alle Wiederherstellungsdateien, d. h. Dateien, die unter $(TARGET_RECOVERY_ROOT_OUT)

mkbootimg-Argumente

Argumentation Beschreibung
--ramdisk_type Der Typ der Ramdisk ist NONE, PLATFORM, RECOVERY oder DLKM.
--board_id[0-15] Geben Sie den board_id-Vektor an. Standardmäßig ist 0 festgelegt.

Hier sehen Sie 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 Das erste ist die „Standard“- ramdisk mit dem DLKM-Verzeichnis baz und der restlichen Dateien in $(TARGET_VENDOR_RAMDISK_OUT). Das zweite ist der dlkm_foobar für ramdisk, das die DLKM-Verzeichnisse foo und bar enthält ist der Standardwert für --ramdisk_type DLKM.