In Android 11 è stato introdotto il concetto di immagine
del kernel generica (GKI). Per consentire l'avvio di un dispositivo arbitrario con il GKI, i dispositivi Android 11 possono utilizzare la versione 3 dell'intestazione dell'immagine di avvio. Nella
versione 3, tutte le informazioni specifiche del fornitore vengono escluse dalla partizione boot
e spostate in una nuova partizione vendor_boot
. Un dispositivo ARM64 avviato con Android 11 sul kernel Linux 5.4 deve supportare la partizione vendor_boot
e il formato della partizione boot
aggiornato per superare i test con il GKI.
I dispositivi Android 12 possono utilizzare la versione 4 dell'intestazione dell'immagine di avvio,
che supporta l'inclusione di più ramdisk del fornitore nella partizione vendor_boot
. Più frammenti del ramdisk del fornitore vengono concatenati uno dopo l'altro
nella sezione del 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 ogni frammento del ramdisk del fornitore.
Struttura della partizione
La partizione di avvio del fornitore è A/B con A/B virtuale e protetta dall'avvio verificato di Android.
Versione 3
La partizione è composta da un'intestazione, dal ramdisk del fornitore e dal BLOB della struttura ad albero dei dispositivi (DTB).
Sezione | Numero di pagine |
---|---|
Intestazione del boot del fornitore (n pagine) | n = (2112 + page_size - 1) / page_size |
Ramdisk del fornitore (pagine o) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
DTB (pagine) | p = (dtb_size + page_size - 1) / page_size |
Versione 4
La partizione è costituita da un'intestazione, dalla sezione ramdisk del fornitore (costituita da tutti i frammenti ramdisk del fornitore, concatenati), dal blob ad albero dei dispositivi (DTB) e dalla tabella ramdisk del fornitore.
Sezione | Numero di pagine |
---|---|
Intestazione del boot del fornitore (n pagine) | n = (2128 + page_size - 1) / page_size |
Frammenti (o pagine) del ramdisk del fornitore | o = (vendor_ramdisk_size + page_size - 1) / page_size |
DTB (pagine) | p = (dtb_size + page_size - 1) / page_size |
Tabella del ramdisk del fornitore (pagine q) | q = (vendor_ramdisk_table_size + page_size - 1) / page_size |
Bootconfig (pagine r) | r = (bootconfig_size + page_size - 1) / page_size |
Intestazione di avvio del fornitore
I contenuti dell'intestazione della partizione di avvio del fornitore consistono principalmente in dati trasferiti dall'intestazione dell'immagine di avvio. Contiene inoltre 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 del 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. Il bootloader deve caricarli in memoria durante l'avvio in modalità di ripristino.- I ramdisk
VENDOR_RAMDISK_TYPE_DLKM
contengono moduli del kernel caricabili dinamicamente.
ramdisk_name
è un nome univoco della ramdisk.board_id
è un vettore di identificatori hardware definiti dal fornitore.
Supporto del bootloader
Poiché la partizione di avvio del fornitore contiene informazioni (ad esempio la dimensione della pagina flash, il kernel, gli indirizzi di caricamento del ramdisk e il DTB stesso) che esistevano in precedenza nella partizione di avvio, il bootloader deve accedere sia alla partizione di avvio sia alla partizione di avvio del fornitore per avere dati sufficienti per completare l'avvio.
Il bootloader deve caricare il ramdisk generico nella memoria immediatamente seguendo il ramdisk del fornitore (i formati CPIO, Gzip e lz4 supportano questo tipo di concatenazione). Non allineare la pagina all'immagine del ramdisk generico o inserire un altro spazio tra questa e la fine del ramdisk del fornitore in memoria. Dopo la decompressione del kernel, il file concatenato viene estratto in un initramfs
,
ovvero in una struttura di file che è un ramdisk generico sovrapposto alla struttura di file del ramdisk del 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, pertanto un dispositivo conforme a GKI deve utilizzare un ramdisk del fornitore compresso con lz4. La configurazione per questa operazione è mostrata di seguito.
I requisiti del bootloader per supportare bootconfig sono spiegati in Implementa Bootconfig.
Più ramdisk di fornitori (versione 4)
Con la versione 4 dell'intestazione dell'immagine di avvio, il bootloader può selezionare un sottoinsieme o tutti i ramdisk del fornitore da caricare come initramfs
durante l'avvio. La tabella del ramdisk del fornitore contiene i metadati di ogni ramdisk e può aiutare il bootloader a decidere quali ramdisk caricare. Il bootloader può decidere l'ordine di caricamento dei ramdisk del fornitore selezionati, a condizione che il ramdisk generico venga caricato per ultimo.
Ad esempio, il bootloader può omettere il caricamento delle ramdisk del fornitore di tipoVENDOR_RAMDISK_TYPE_RECOVERY
durante il normale avvio per risparmiare risorse, quindi solo le ramdisk del fornitore di tipoVENDOR_RAMDISK_TYPE_PLATFORM
eVENDOR_RAMDISK_TYPE_DLKM
vengono caricate in memoria. D'altra parte, i ramdisk del fornitore 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 recupero.
In alternativa, il bootloader può ignorare la tabella del ramdisk del fornitore e caricare l'intera sezione del ramdisk del fornitore. L'effetto è lo stesso del caricamento di tutti i frammenti del ramdisk del fornitore nella partizione vendor_boot
.
Creare assistenza
Per implementare il supporto per l'avvio del fornitore per un dispositivo:
Imposta
BOARD_BOOT_HEADER_VERSION
su3
o un valore superiore.Imposta
BOARD_RAMDISK_USE_LZ4
sutrue
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 essere inseriti sul ramdisk del fornitore.Aggiorna
AB_OTA_PARTITIONS
in modo da includerevendor_boot
e eventuali elenchi di partizioni OTA specifici del fornitore sul dispositivo.Copia
fstab
del dispositivo in/first_stage_ramdisk
nella partizionevendor_boot
, non nella partizioneboot
. Ad esempio,$(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM)
.
Per includere più ramdisk del fornitore in vendor_boot
:
- Imposta
BOARD_BOOT_HEADER_VERSION
su4
. Imposta
BOARD_VENDOR_RAMDISK_FRAGMENTS
su un elenco di nomi di frammenti ramdisk del fornitore logico da includere invendor_boot
.Per aggiungere un ramdisk del fornitore precompilato, imposta
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT
sul percorso precompilato.Per aggiungere un ramdisk del fornitore DLKM, imposta
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS
sull'elenco di directory dei moduli kernel da includere.Imposta
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS
sumkbootimg
argomenti. Si tratta degli argomenti--board_id[0-15]
e--ramdisk_type
per il frammento del ramdisk del fornitore. Per il ramdisk del fornitore DLKM, il valore predefinito di--ramdisk_type
èDLKM
se non viene specificato diversamente.
Per creare risorse di ripristino come ramdisk recovery
autonomo in vendor_boot
:
- Imposta
BOARD_BOOT_HEADER_VERSION
su4
. - Imposta
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT
sutrue
. - Imposta
BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT
sutrue
. - Viene aggiunto un frammento del ramdisk del fornitore il cui
ramdisk_name
èrecovery
eramdisk_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 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. Il primo è il ramdisk "default", che contiene la directory DLKM baz
e il resto dei file in $(TARGET_VENDOR_RAMDISK_OUT)
. Il secondo è il
dlkm_foobar
ramdisk, che contiene le directory DLKM foo
e bar
, e
il valore predefinito di --ramdisk_type
è DLKM
.