Partizioni di avvio del fornitore

Android 11 ha introdotto il concetto di Generic Kernel Image (GKI). Per attivare facilmente l'avvio di un dispositivo arbitrario con GKI, Android 11 dispositivi possono utilizzare l'avvio intestazione dell'immagine versione 3. Nella versione 3, tutte le informazioni specifiche del fornitore viene scomposto fuori boot partizione e trasferito in una nuova vendor_boot partizione. Un ARM64 lancio dispositivo con Android 11 sul kernel 5.4 di Linux deve supportare il vendor_boot divisorio e la versione aggiornata boot formato di partizione per passare il test con la GKI.

12 dispositivi Android possono utilizzare avvio intestazione dell'immagine versione 4, che supporta tra cui molteplici ramdisk vendor nel vendor_boot partizione. Più frammenti di ramdisk del fornitore vengono concatenati uno dopo l'altro nella sezione ramdisk del fornitore. Una tabella del ramdisk del fornitore viene utilizzata per descrivere il layout della sezione del ramdisk del fornitore e i metadati di ciascun frammento del ramdisk del fornitore.

Struttura della partizione

La partizione di avvio del fornitore è A/B con A/B virtuale e protetta da Android Verified Boot.

Versione 3

La partizione è costituita da un'intestazione, dal ramdisk del fornitore e dal blob della struttura ad albero dei dispositivi (DTB).

Sezione Numero di pagine
Intestazione di avvio del fornitore (n pagine) n = (2112 + page_size - 1) / page_size
Ramdisk del fornitore (o pagine) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (p pagine) p = (dtb_size + page_size - 1) / page_size

Versione 4

La partizione è costituita da un'intestazione, la sezione del ramdisk del fornitore (costituita da tutti i frammenti del ramdisk del fornitore, concatenati), il blob della struttura ad albero dei dispositivi (DTB) e la tabella del ramdisk del fornitore.

Sezione Numero di pagine
Intestazione di avvio del fornitore (n pagine) n = (2128 + page_size - 1) / page_size
Frammenti del ramdisk del fornitore (o pagine) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (p pagine) p = (dtb_size + page_size - 1) / page_size
Tabella ramdisk fornitore (q pagine) q = (vendor_ramdisk_table_size + page_size - 1) / page_size
Bootconfig (r pagine) r = (bootconfig_size + page_size - 1) / page_size

Intestazione di avvio del fornitore

Il contenuto della partizione di avvio di intestazione vendor sono costituite principalmente da dati che sono stati lì riassegnati dalla intestazione immagine di avvio . Contiene anche informazioni sul ramdisk del fornitore.

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

};

Versione 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 è la dimensione totale di tutti i frammenti fornitore ramdisk.
  • ramdisk_type denota il tipo di ramdisk, valori possibili sono:
    • VENDOR_RAMDISK_TYPE_NONE indica il valore non è specificato.
    • VENDOR_RAMDISK_TYPE_PLATFORM ramdisks contengono bit piattaforma specifici. Il bootloader deve sempre caricarli in memoria.
    • VENDOR_RAMDISK_TYPE_RECOVERY ramdisk contengono risorse di recupero. Il bootloader deve caricarli in memoria durante l'avvio in recovery.
    • VENDOR_RAMDISK_TYPE_DLKM ramdisk contengono moduli del kernel caricabili dinamici.
  • ramdisk_name è un nome univoco del ramdisk.
  • board_id è un vettore di vendor definito identificatori hardware.

Supporto per il bootloader

Poiché la partizione di avvio del fornitore contiene informazioni (come la dimensione della pagina flash, il kernel, gli indirizzi di caricamento del ramdisk, il DTB stesso) che esistevano in precedenza nella partizione di avvio, il bootloader deve accedere sia alla partizione di avvio che alla partizione di avvio del fornitore per avere dati sufficienti per completare l'avvio .

Il bootloader deve caricare il ramdisk generico nella memoria immediatamente successivo alla ramdisk fornitore (la CPIO, Gzip, e formati LZ4 sostenere questo tipo di concatenazione). Non eseguire l'allineamento delle pagine dell'immagine ramdisk generica o introdurre qualsiasi altro spazio tra essa e la fine del ramdisk del fornitore in memoria. Dopo le decomprime kernel, estrae il file concatenati in un initramfs , che si traduce in una struttura di file che è un ramdisk sovrapposti generica sulla struttura del file ramdisk fornitore.

Poiché il ramdisk generico e il ramdisk del fornitore vengono concatenati, devono essere nello stesso formato. L'immagine di avvio GKI utilizza un ramdisk generico compresso con lz4, quindi un dispositivo conforme a GKI deve utilizzare un ramdisk del fornitore compresso con lz4. La configurazione per questo è mostrata di seguito.

I requisiti bootloader per supportare bootconfig sono spiegati nella esecuzione Bootconfig pagina.

Ramdisk di più fornitori (versione 4)

Con avvio intestazione dell'immagine versione 4, il bootloader può selezionare un sottoinsieme o tutti i ramdisk venditrici alle carico degli initramfs durante l'avvio. La tabella dei ramdisk del fornitore contiene i metadati di ciascun ramdisk e può aiutare il bootloader a decidere quali ramdisk caricare. Il bootloader può decidere l'ordine di caricamento dei ramdisk del fornitore selezionato, purché il ramdisk generico venga caricato per ultimo.

Ad esempio, il bootloader può omettere ramdisks loading fornitore di tipo VENDOR_RAMDISK_TYPE_RECOVERY durante l'avvio normale risorse conservare, in modo unico fornitore ramdisks di tipo VENDOR_RAMDISK_TYPE_PLATFORM e VENDOR_RAMDISK_TYPE_DLKM vengono caricati in memoria. D'altra parte, ramdisks vendor di tipo VENDOR_RAMDISK_TYPE_PLATFORM , VENDOR_RAMDISK_TYPE_RECOVERY e VENDOR_RAMDISK_TYPE_DLKM vengono caricati in memoria durante l'avvio in modalità di ripristino.

In alternativa, il bootloader può ignorare la tabella del ramdisk del fornitore e caricare l'intera sezione del ramdisk del fornitore. Questo ha lo stesso effetto come fa caricare tutti i frammenti fornitore ramdisk nella vendor_boot partizione.

Crea supporto

Per implementare il supporto di avvio del fornitore per un dispositivo:

  • Set BOARD_BOOT_HEADER_VERSION a 3 o superiore.

  • Set BOARD_RAMDISK_USE_LZ4 al true se il dispositivo è GKI-compliant, o se altrimenti usa un ramdisk generico LZ4-compressa.

  • Set BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE ad una dimensione appropriata per il dispositivo, considerando i moduli del kernel che devono andare sul ramdisk fornitore.

  • Aggiornamento AB_OTA_PARTITIONS per includere vendor_boot e elenchi vendor specifici di partizioni OTA sul dispositivo.

  • Copiare il vostro dispositivo fstab in /first_stage_ramdisk nel vendor_boot partizione, non l' boot della partizione. Ad esempio, $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM) .

Per includere più ramdisk vendor in vendor_boot :

  • Impostare BOARD_BOOT_HEADER_VERSION a 4 .
  • Impostare BOARD_VENDOR_RAMDISK_FRAGMENTS a una lista di vendor logica nomi frammento ramdisk da includere nel vendor_boot .

  • Per aggiungere un fornitore ramdisk precompilati, insieme BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT al percorso del file precompilati.

  • Per aggiungere un fornitore ramdisk DLKM, insieme BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS alla lista delle directory dei moduli del kernel di essere inclusi.

  • Set BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS a mkbootimg argomenti. Queste sono le --board_id[0-15] e --ramdisk_type argomenti per il frammento fornitore ramdisk. Per DLKM vendor ramdisk, il default --ramdisk_type sarebbe DLKM , se non è diversamente specificato.

Per costruire le risorse di recupero come un autonomo recovery ramdisk in vendor_boot :

  • Impostare BOARD_BOOT_HEADER_VERSION a 4 .
  • Impostare BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT al true .
  • Impostare BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT al true .
  • Questo aggiunge un frammento fornitore ramdisk cui ramdisk_name è recovery e ramdisk_type è VENDOR_RAMDISK_TYPE_RECOVERY . Il ramdisk contiene quindi tutti i file di ripristino, che sono file installati sotto $(TARGET_RECOVERY_ROOT_OUT) .

mkbootimg argomenti

Discussione Descrizione
--ramdisk_type Il tipo di disco RAM, può essere uno dei NONE , PLATFORM , RECOVERY o DLKM .
--board_id[0-15] Specificare la board_id vettore, il default è 0 .

Di seguito è riportato un esempio di configurazione:

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

Il risultante vendor_boot conterrebbe due frammenti fornitore ramdisk. Il primo è il ramdisk "default", che contiene la directory DLKM baz e il resto dei file in $(TARGET_VENDOR_RAMDISK_OUT) . La seconda è la dlkm_foobar ramdisk, che contiene la directory DLKM foo e bar , e le --ramdisk_type default DLKM .