Partizioni di avvio del fornitore

In Android 11 è stato introdotto il concetto di kernel generico Immagine (GKI). Per abilitare l'avvio di un dispositivo arbitrario con GKI, Android 11 dispositivi possono utilizzare la versione 3 dell'intestazione dell'immagine di avvio. Nel versione 3, tutte le informazioni specifiche del fornitore vengono escluse dalla boot e spostata in una nuova partizione vendor_boot. Un dispositivo ARM64 il lancio con Android 11 sul kernel Linux 5.4 deve supportare la partizione vendor_boot e il formato di partizione boot aggiornato per superare il test con la GKI.

I dispositivi Android 12 possono utilizzare la versione 4 dell'intestazione dell'immagine di avvio che supporta l'inclusione di ramdisk di più fornitori in vendor_boot della partizione di testo. Più frammenti ramdisk del fornitore vengono concatenati uno dopo l'altro nella sezione ramdisk del fornitore. Viene utilizzata una tabella ramdisk del fornitore per descrivere Layout della sezione ramdisk del fornitore e metadati di ciascun ramdisk del fornitore .

Struttura della partizione

La partizione di avvio del fornitore è A/B-ed con A/B virtuale e protetta da Android Avvio verificato.

Versione 3

La partizione è costituita da un'intestazione, dal ramdisk del fornitore e dal blob dell'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 ramdisk del fornitore (costituita da tutti i frammenti ramdisk del fornitore, concatenati), il blob ad albero dei dispositivi (DTB) e la tabella ramdisk del fornitore.

Sezione Numero di pagine
Intestazione di avvio del fornitore (n pagine) n = (2128 + page_size - 1) / page_size
Frammenti 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 del fornitore (q pagine) q = (vendor_ramdisk_table_size + page_size - 1) / page_size
Bootconfig (pagine) r = (bootconfig_size + page_size - 1) / page_size

Intestazione avvio fornitore

I contenuti dell'intestazione della partizione di avvio del fornitore sono costituiti principalmente da dati che è stato trasferito lì intestazione immagine di avvio. it 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 ramdisk del fornitore.
  • ramdisk_type indica il tipo di ramdisk. I valori possibili sono:
    • VENDOR_RAMDISK_TYPE_NONE indica che il valore non è specificato.
    • I ramdisk VENDOR_RAMDISK_TYPE_PLATFORM contengono bit specifici della piattaforma. il bootloader deve sempre caricarli in memoria.
    • VENDOR_RAMDISK_TYPE_RECOVERY ramdisk contengono risorse di ripristino. La il bootloader deve caricarli in memoria all'avvio del ripristino.
    • VENDOR_RAMDISK_TYPE_DLKM ramdisk contengono un kernel caricabile dinamico moduli.
  • ramdisk_name è un nome univoco del ramdisk.
  • board_id è un vettore di identificatori hardware definiti dal fornitore.

Supporto del bootloader

Poiché la partizione di avvio del fornitore contiene informazioni (come le dimensioni della pagina Flash, (gli indirizzi di caricamento ramdisk, il DTB stesso) che esistevano in precedenza la partizione di avvio, il bootloader deve accedere sia all'avvio del fornitore che all'avvio in modo da avere dati sufficienti per completare l'avvio.

Il bootloader deve caricare il ramdisk generico nella memoria immediatamente dopo aver eseguito il ramdisk del fornitore (i formati CPIO, Gzip e lz4 supportano concatenazione). Non allineare nella pagina l'immagine ramdisk generica e non introdurre alcuna spazio tra quest'ultimo e la fine del ramdisk del fornitore in memoria. Dopo il si decomprime, estrae il file concatenato in un initramfs Il risultato è una struttura di file costituita da un ramdisk generico sovrapposto al la struttura del file ramdisk del fornitore.

Poiché il ramdisk generico e il ramdisk del fornitore vengono concatenati, devono essere lo stesso formato. L'immagine di avvio GKI utilizza un ramdisk generico compresso con lz4, quindi un conforme a GKI deve utilizzare un ramdisk del fornitore compresso con lz4. La la configurazione del deployment.

I requisiti del bootloader per il supporto di bootconfig sono descritti in Implementa Bootconfig.

Ramdisk di più fornitori (versione 4)

Con l'intestazione dell'immagine di avvio versione 4, il bootloader può selezionare un sottoinsieme o tutti i ramdisk del fornitore da caricare come initramfs durante il tempo di avvio. La la tabella ramdisk del fornitore contiene i metadati di ogni ramdisk e può aiutare bootloader per decidere quali ramdisk caricare. Il bootloader può decidere per caricare i ramdisk del fornitore selezionati, purché venga utilizzato il ramdisk generico caricati per ultimi.

Ad esempio, il bootloader può omettere il caricamento dei ramdisk del fornitore di tipo VENDOR_RAMDISK_TYPE_RECOVERY durante il normale avvio per risparmiare risorse, quindi solo ramdisk del fornitore di tipo VENDOR_RAMDISK_TYPE_PLATFORM e VENDOR_RAMDISK_TYPE_DLKM sono stati caricati in memoria. Al contrario, il fornitore ramdisk di tipo VENDOR_RAMDISK_TYPE_PLATFORM, VENDOR_RAMDISK_TYPE_RECOVERY e VENDOR_RAMDISK_TYPE_DLKM vengono caricati nella memoria durante l'avvio del ripristino .

In alternativa, il bootloader può ignorare la tabella ramdisk del fornitore e caricare dell'intera sezione ramdisk del fornitore. Ciò ha lo stesso effetto del caricamento di tutti i frammenti ramdisk del fornitore nella partizione vendor_boot.

Assistenza allo sviluppo

Per implementare il supporto per l'avvio del fornitore per un dispositivo:

  • Imposta BOARD_BOOT_HEADER_VERSION su 3 o un valore superiore.

  • Imposta BOARD_RAMDISK_USE_LZ4 su true se il tuo dispositivo è conforme a GKI o se altrimenti utilizza un ramdisk generico compresso con lz4.

  • Imposta BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE su una dimensione appropriata per il tuo dispositivo, considerando i moduli kernel che devono trovarsi sul ramdisk del fornitore.

  • Aggiorna AB_OTA_PARTITIONS in modo da includere vendor_boot ed eventuali altri fornitori specifici di partizioni OTA sul dispositivo.

  • Copia il tuo dispositivo fstab in /first_stage_ramdisk in vendor_boot non la partizione boot. Ad esempio: $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM).

Per includere ramdisk di più fornitori in vendor_boot:

  • Imposta BOARD_BOOT_HEADER_VERSION su 4.
  • Imposta BOARD_VENDOR_RAMDISK_FRAGMENTS su un elenco di ramdisk del fornitore logico dei nomi dei frammenti da includere in vendor_boot.

  • Per aggiungere un ramdisk del fornitore predefinito, imposta BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT alla configurazione predefinita del tuo percorso di apprendimento.

  • Per aggiungere un ramdisk del fornitore DLKM, imposta BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS alla l'elenco delle directory dei moduli kernel da includere.

  • Imposta BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS su mkbootimg argomenti. Questi sono i --board_id[0-15] e le --ramdisk_type argomenti per il frammento ramdisk del fornitore. Per ramdisk del fornitore DLKM, la Il valore predefinito di --ramdisk_type è DLKM se non diversamente specificato.

Per creare risorse di recupero come ramdisk recovery autonomo in vendor_boot:

  • Imposta BOARD_BOOT_HEADER_VERSION su 4.
  • Imposta BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT su true.
  • Imposta BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT su true.
  • Viene aggiunto un frammento ramdisk del fornitore il cui ramdisk_name è recovery e ramdisk_type è VENDOR_RAMDISK_TYPE_RECOVERY. Il ramdisk contiene quindi tutti i file di ripristino, ovvero i file installati in $(TARGET_RECOVERY_ROOT_OUT).

Argomenti mkbootimg

Argomento Descrizione
--ramdisk_type Il tipo di ramdisk può essere uno dei seguenti: NONE, PLATFORM, RECOVERY o DLKM.
--board_id[0-15] Specifica il vettore board_id. Il valore predefinito è 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 risultato vendor_boot conterrà due frammenti ramdisk del fornitore. La la prima è quella "predefinita" ramdisk, che contiene la directory DLKM baz e il resto dei file in $(TARGET_VENDOR_RAMDISK_OUT). Il secondo è il ramdisk dlkm_foobar, che contiene le directory DLKM foo e bar, e Per impostazione predefinita, --ramdisk_type è DLKM.