O Android 11 introduziu o conceito de kernel genérico
de imagem (GKI). Para inicializar um dispositivo arbitrário com a GKI, o Android
11 podem usar a versão 3 do cabeçalho da imagem de inicialização. Em
na versão 3, todas as informações específicas do fornecedor serão consideradas do boot
e realocados para uma nova partição vendor_boot
. Um dispositivo ARM64.
lançados com o Android 11 no kernel do Linux 5.4 precisam
oferecem suporte à partição vendor_boot
e ao formato de partição boot
atualizado para
passar no teste com a GKI.
Dispositivos Android 12 podem usar a versão 4 do cabeçalho da imagem de inicialização,
que oferece suporte à inclusão de vários ramdisks de fornecedores no vendor_boot
partição. Vários fragmentos do ramdisk do fornecedor são concatenados um após o outro
na seção do ramdisk do fornecedor. Uma tabela do ramdisk do fornecedor é usada para descrever
layout da seção do ramdisk do fornecedor e os metadados de cada ramdisk
de dados.
Estrutura de partição
A partição de inicialização do fornecedor é A/B com A/B virtual e protegida pelo Android Inicialização verificada.
Versão 3
A partição consiste em um cabeçalho, o ramdisk do fornecedor e o blob da árvore de dispositivos (DTB).
Seção | Número de páginas |
---|---|
Cabeçalho de inicialização do fornecedor (n páginas) | n = (2112 + page_size - 1) / page_size |
ramdisk do fornecedor (o páginas) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
DTB (p páginas) | p = (dtb_size + page_size - 1) / page_size |
Versão 4
A partição consiste em um cabeçalho, a seção ramdisk do fornecedor (que consiste todos os fragmentos do ramdisk do fornecedor, concatenados), o blob da árvore de dispositivos (DTB, na sigla em inglês) e o tabela do ramdisk do fornecedor.
Seção | Número de páginas |
---|---|
Cabeçalho de inicialização do fornecedor (n páginas) | n = (2128 + page_size - 1) / page_size |
Fragmentos do ramdisk do fornecedor (páginas) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
DTB (p páginas) | p = (dtb_size + page_size - 1) / page_size |
Tabela do ramdisk do fornecedor (páginas q) | q = (vendor_ramdisk_table_size + page_size - 1) / page_size |
Bootconfig (páginas R) | r = (bootconfig_size + page_size - 1) / page_size |
Cabeçalho de inicialização do fornecedor
O conteúdo do cabeçalho da partição de inicialização do fornecedor consiste principalmente em dados que foi transferido para lá cabeçalho da imagem de inicialização. Ela também contém informações sobre o ramdisk do fornecedor.
Versão 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 */
};
Versão 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
é o tamanho total de todos os fragmentos do ramdisk do fornecedor.ramdisk_type
indica o tipo de ramdisk. Os valores possíveis são:VENDOR_RAMDISK_TYPE_NONE
indica que o valor não foi especificado.- Os ramdisks
VENDOR_RAMDISK_TYPE_PLATFORM
contêm bits específicos da plataforma. O carregador de inicialização precisa sempre carregá-los na memória. VENDOR_RAMDISK_TYPE_RECOVERY
ramdisks contêm recursos de recuperação. A o carregador de inicialização precisa carregá-los na memória ao inicializar na recuperação.- Os ramdisks
VENDOR_RAMDISK_TYPE_DLKM
contêm kernel dinâmico carregável módulos.
ramdisk_name
é um nome exclusivo do ramdisk.board_id
é um vetor de identificadores de hardware definidos pelo fornecedor.
Suporte ao carregador de inicialização
Como a partição de inicialização do fornecedor contém informações (como tamanho da página flash, kernel, endereços de carregamento do ramdisk, o próprio DTB) que já existiam na de inicialização, o carregador de inicialização deve acessar os dados de inicialização e de inicialização para que as partições tenham dados suficientes para concluir a inicialização.
O carregador de inicialização precisa carregar o ramdisk genérico na memória imediatamente após
o ramdisk do fornecedor (os formatos CPIO, Gzip e lz4 são compatíveis com esse tipo de
concatenação). Não alinhe a imagem genérica do ramdisk nem inclua
outro espaço entre ele e o fim do ramdisk do fornecedor na memória. Após o
o kernel descompacta, ele extrai o arquivo concatenado em um initramfs
,
Isso resulta em uma estrutura de arquivos que é um ramdisk genérico sobreposto
do fornecedor.
Como o ramdisk genérico e o ramdisk do fornecedor são concatenados, eles precisam estar no mesmo formato. A imagem de inicialização GKI usa um ramdisk genérico compactado com lz4. Portanto, dispositivo compatível com GKI precisa usar um ramdisk de fornecedor com compactação lz4. A para isso é mostrada abaixo.
Os requisitos do carregador de inicialização para suporte ao bootconfig são explicados em Implementação Bootconfig.
Vários ramdisks de fornecedores (versão 4)
Com a versão 4 do cabeçalho da imagem de inicialização, o carregador pode selecionar um subconjunto ou
todos os ramdisks do fornecedor sejam carregados como initramfs
durante a inicialização. A
tabela do ramdisk do fornecedor contém os metadados de cada ramdisk e pode ajudar
para decidir quais ramdisks carregar. O carregador de inicialização pode decidir
para carregar os ramdisks do fornecedor selecionado, desde que o ramdisk genérico seja
carregado por último.
Por exemplo, o carregador de inicialização pode omitir o carregamento de ramdisks do fornecedor do tipo
VENDOR_RAMDISK_TYPE_RECOVERY
durante a inicialização normal para economizar recursos, portanto,
os ramdisks do fornecedor do tipo VENDOR_RAMDISK_TYPE_PLATFORM
e
VENDOR_RAMDISK_TYPE_DLKM
são carregados na memória. Por outro lado, o fornecedor
ramdisks do tipo VENDOR_RAMDISK_TYPE_PLATFORM
, VENDOR_RAMDISK_TYPE_RECOVERY
e VENDOR_RAMDISK_TYPE_DLKM
são carregados na memória durante a inicialização na recuperação
modo
Como alternativa, o carregador de inicialização pode ignorar a tabela do ramdisk do fornecedor e carregar
em toda a seção do ramdisk do fornecedor. Isso tem o mesmo efeito que carregar todos
os fragmentos do ramdisk do fornecedor na partição vendor_boot
.
Suporte de build
Para implementar o suporte de inicialização do fornecedor para um dispositivo:
Defina
BOARD_BOOT_HEADER_VERSION
como3
ou mais.Defina
BOARD_RAMDISK_USE_LZ4
comotrue
se o dispositivo for compatível com GKI ou se mas usa um ramdisk genérico compactado com lz4.Defina
BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE
com um tamanho adequado para dispositivo, considerando os módulos do kernel que precisam ser colocados no ramdisk do fornecedor.Atualize o
AB_OTA_PARTITIONS
para incluirvendor_boot
e outras opções específicas de fornecedor. listas de partições OTA no dispositivo.Copie o dispositivo
fstab
para o/first_stage_ramdisk
novendor_boot
em vez da partiçãoboot
. Por exemplo:$(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM)
.
Para incluir vários ramdisks de fornecedores em vendor_boot
:
- Defina
BOARD_BOOT_HEADER_VERSION
como4
. Definir
BOARD_VENDOR_RAMDISK_FRAGMENTS
como uma lista de ramdisk do fornecedor lógico a serem incluídos emvendor_boot
.Para adicionar um ramdisk de fornecedor pré-criado, defina
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT
ao modelo pré-criado caminho.Para adicionar um ramdisk do fornecedor de DLKM, defina
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS
para o lista de diretórios de módulo do kernel a serem incluídos.Definir
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS
comomkbootimg
. Estes são os--board_id[0-15]
e--ramdisk_type
argumentos para o fragmento do ramdisk do fornecedor. Para o ramdisk do fornecedor do DLKM, a o--ramdisk_type
padrão seráDLKM
se não for especificado de outra forma.
Para criar recursos de recuperação como um ramdisk independente recovery
em vendor_boot
:
- Defina
BOARD_BOOT_HEADER_VERSION
como4
. - Defina
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT
comotrue
. - Defina
BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT
comotrue
. - Isso adiciona um fragmento do ramdisk do fornecedor com
ramdisk_name
comorecovery
eramdisk_type
éVENDOR_RAMDISK_TYPE_RECOVERY
. O ramdisk contém todos os arquivos de recuperação, que são arquivos instalados em$(TARGET_RECOVERY_ROOT_OUT)
:
Argumentos mkbootimg
Argumento | Descrição |
---|---|
--ramdisk_type |
O tipo do ramdisk pode ser NONE .
PLATFORM , RECOVERY ou DLKM .
|
--board_id[0-15] |
Especifique o vetor board_id . O padrão é 0 . |
Confira abaixo um exemplo de configuração:
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
O vendor_boot
resultante conteria dois fragmentos do ramdisk do fornecedor. A
a primeira é a "padrão", ramdisk, que contém o diretório DLKM baz
e
o restante dos arquivos em $(TARGET_VENDOR_RAMDISK_OUT)
. A segunda é
O ramdisk dlkm_foobar
, que contém os diretórios DLKM foo
e bar
, e
--ramdisk_type
é definido como DLKM
por padrão.