O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Partições de inicialização do fornecedor

O Android 11 introduziu o conceito de imagem genérica do kernel (GKI). Para ativar facilmente arrancar um dispositivo arbitrária com o GKI, Android 11 dispositivos podem usar bota cabeçalho de imagem versão 3. Na versão 3, todas as informações específicas do fornecedor está consignado fora do boot partição e se mudou para um novo vendor_boot partição. Um ARM64 lançamento dispositivo com Android 11 no kernel 5.4 do Linux deve suportar o vendor_boot partição e o atualizou boot formato de partição para passar o teste com o GKI.

Android 12 dispositivos podem usar bota cabeçalho de imagem versão 4, que suporta incluindo várias ramdisks fornecedor no vendor_boot partição. Fragmentos de ramdisk de vários fornecedores são concatenados um após o outro na seção de ramdisk do fornecedor. Uma tabela de ramdisk do fornecedor é usada para descrever o layout da seção do ramdisk do fornecedor e os metadados de cada fragmento do ramdisk do fornecedor.

Estrutura de partição

A partição de inicialização do fornecedor é A / B com A / B virtual e protegida pela inicialização verificada do Android.

Versão 3

A partição consiste em um cabeçalho, o ramdisk do fornecedor e o blob da árvore do dispositivo (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 (páginas o) 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 do ramdisk do fornecedor (consistindo em todos os fragmentos do ramdisk do fornecedor, concatenados), o blob da árvore do dispositivo (DTB) e a 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 de ramdisk do fornecedor (páginas o) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (p páginas) p = (dtb_size + page_size - 1) / page_size
Tabela de ramdisk do fornecedor (páginas q) q = (vendor_ramdisk_table_size + page_size - 1) / page_size
Bootconfig (r páginas) r = (bootconfig_size + page_size - 1) / page_size

Cabeçalho de inicialização do fornecedor

O conteúdo do cabeçalho partição fornecedor de inicialização consistem principalmente em dados que foram realocados lá desde o cabeçalho de imagem de inicialização . Ele 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 fornecedor disco em memória.
  • ramdisk_type denota o tipo do disco em memória, os valores possíveis são:
    • VENDOR_RAMDISK_TYPE_NONE indica que o valor não é especificado.
    • VENDOR_RAMDISK_TYPE_PLATFORM ramdisks contêm pedaços plataforma específicos. O bootloader deve sempre carregá-los na memória.
    • VENDOR_RAMDISK_TYPE_RECOVERY ramdisks contêm recursos de recuperação. O bootloader deve carregá-los na memória ao inicializar na recuperação.
    • VENDOR_RAMDISK_TYPE_DLKM ramdisks contém os módulos do kernel carregáveis dinâmicas.
  • ramdisk_name é um nome exclusivo do disco RAM.
  • board_id é um vetor de fornecedor definido identificadores de hardware.

Suporte a bootloader

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 existiam anteriormente na partição de inicialização, o carregador de inicialização deve acessar as partições de inicialização e do fornecedor para ter dados suficientes para concluir a inicialização .

O bootloader deve carregar o ramdisk genérica na memória imediatamente após o ramdisk fornecedor (o CPIO, Gzip e formatos lz4 apoiar este tipo de concatenação). Não alinhe a página da imagem do ramdisk genérico ou introduza qualquer outro espaço entre ela e o fim do ramdisk do fornecedor na memória. Após os descomprime do kernel, ele extrai o arquivo concatenado em uma initramfs , que resulta em uma estrutura de arquivo que é um sobreposto ramdisk genérico sobre a estrutura do arquivo ramdisk fornecedor.

Como o ramdisk genérico e o ramdisk do fornecedor são concatenados, eles devem estar no mesmo formato. A imagem de inicialização GKI usa um ramdisk genérico compactado com lz4, portanto, um dispositivo compatível com GKI deve usar um ramdisk de fornecedor compactado com lz4. A configuração para isso é mostrada abaixo.

Os requisitos bootloader para apoiar bootconfig são explicados na Implementação Bootconfig página.

Ramdisks de vários fornecedores (versão 4)

Com inicialização cabeçalho de imagem versão 4, o bootloader pode selecionar um subconjunto ou todas as ramdisks fornecedor para carga como os initramfs durante o tempo de boot. A tabela do ramdisk do fornecedor contém os metadados de cada ramdisk e pode ajudar o carregador de inicialização a decidir quais ramdisks carregar. O bootloader pode decidir a ordem para carregar os ramdisks do fornecedor selecionado, desde que o ramdisk genérico seja carregado por último.

Por exemplo, o gestor de arranque pode omitir ramdisks carregamento fornecedor do tipo VENDOR_RAMDISK_TYPE_RECOVERY durante a inicialização normal para recursos de conserva, de modo único fornecedor ramdisks de tipo VENDOR_RAMDISK_TYPE_PLATFORM e VENDOR_RAMDISK_TYPE_DLKM são carregados para a memória. Por outro lado, ramdisks fornecedores do tipo VENDOR_RAMDISK_TYPE_PLATFORM , VENDOR_RAMDISK_TYPE_RECOVERY e VENDOR_RAMDISK_TYPE_DLKM são carregados na memória quando arrancar em modo de recuperação.

Alternativamente, o bootloader pode ignorar a tabela de disco ram do fornecedor e carregar toda a seção do disco ram do fornecedor. Isto tem o mesmo efeito que faz o carregamento de todos os fragmentos fornecedor disco em memória no vendor_boot partição.

Construir suporte

Para implementar o suporte de inicialização do fornecedor para um dispositivo:

  • Conjunto BOARD_BOOT_HEADER_VERSION a 3 ou maior.

  • Set BOARD_RAMDISK_USE_LZ4 a true se o seu aparelho é GKI-compliant, ou se de outra forma utiliza um disco em memória genérica comprimido-lz4.

  • Set BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE para um tamanho adequado para o seu dispositivo, considerando os módulos do kernel que deve ir na ramdisk fornecedor.

  • Atualização AB_OTA_PARTITIONS para incluir vendor_boot e quaisquer listas específicas de fornecedor de partições OTA no dispositivo.

  • Copie o seu dispositivo fstab para /first_stage_ramdisk na vendor_boot partição, não a boot partição. Por exemplo, $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM) .

Para incluir vários ramdisks fornecedores em vendor_boot :

  • Definir BOARD_BOOT_HEADER_VERSION a 4 .
  • Definir BOARD_VENDOR_RAMDISK_FRAGMENTS para uma lista de fornecedores lógico nome dos fragmentos ramdisk para ser incluído no vendor_boot .

  • Para adicionar um ramdisk fornecedor pré-construídos, conjunto BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT para o caminho do arquivo pré-construídos.

  • Para adicionar um ramdisk fornecedor DLKM, conjunto BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS à lista de diretórios de módulos do kernel para ser incluído.

  • Set BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS para mkbootimg argumentos. Estes são os --board_id[0-15] e --ramdisk_type argumentos para o fragmento fornecedor ramdisk. Para ramdisk fornecedor DLKM, o padrão --ramdisk_type seria DLKM se não for especificado em contrário.

Para construir os recursos de recuperação como um autônomo recovery ramdisk em vendor_boot :

  • Definir BOARD_BOOT_HEADER_VERSION a 4 .
  • Definir BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT a true .
  • Definir BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT a true .
  • Isso adiciona um fragmento fornecedor ramdisk cuja ramdisk_name é recovery e ramdisk_type é VENDOR_RAMDISK_TYPE_RECOVERY . O ramdisk, em seguida, contém todos os arquivos de recuperação, que são arquivos instalados sob $(TARGET_RECOVERY_ROOT_OUT) .

mkbootimg argumentos

Argumento Descrição
--ramdisk_type O tipo de disco em memória, pode ser um de NONE , PLATFORM , RECOVERY ou DLKM .
--board_id[0-15] Especifique o board_id vector, o padrão é 0 .

A seguir está 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 resultante vendor_boot iria conter dois fragmentos fornecedor disco em memória. O primeiro é o ramdisk "default", que contém o diretório DLKM baz e o resto dos arquivos em $(TARGET_VENDOR_RAMDISK_OUT) . A segunda é o dlkm_foobar disco em memória, que contém o directórios DLKM foo e bar , e as --ramdisk_type padrão para DLKM .