Cabeçalho da imagem de inicialização

O Android 9 introduziu um campo de versão no cabeçalho da imagem de inicialização, permitindo atualizações no cabeçalho, mantendo a compatibilidade com versões anteriores. O bootloader deve verificar o campo de versão do cabeçalho e analisar o cabeçalho de acordo. Dispositivos iniciados com:

  • O Android 12 pode usar a versão 3 ou 4 do cabeçalho de inicialização. Para dispositivos compatíveis com a arquitetura Generic Kernel Image (GKI) , a versão 4 é a imagem de inicialização principal.
  • O Android 11 pode usar a versão 3 do cabeçalho de inicialização. Para dispositivos que suportam a arquitetura Generic Kernel Image (GKI) , esta versão deve ser usada para a imagem de inicialização primária.
  • O Android 10 deve usar o cabeçalho de inicialização versão 2.
  • O Android 9 deve usar a versão 1 do cabeçalho de inicialização.
  • O Android 8 e inferior são considerados como usando um cabeçalho de imagem de inicialização versão 0.

Para todos os dispositivos com Android 9 ou superior, o Vendor Test Suite (VTS) verifica o formato da imagem de boot/recovery para garantir que o cabeçalho da imagem de inicialização use a versão correta. Para visualizar os detalhes do AOSP em todos os cabeçalhos de imagem de inicialização do fornecedor e de inicialização suportados atualmente, consulte system/tools/mkbootimg/include/bootimg/bootimg.h .

Implementando o controle de versão do cabeçalho da imagem de inicialização

A ferramenta mkbootimg aceita os seguintes argumentos.

Argumento Descrição
header_version Define a versão do cabeçalho da imagem de inicialização. Uma imagem de inicialização com uma versão de cabeçalho:
  • 1 ou 2 suporta uma imagem DTBO de recuperação ou uma imagem ACPIO de recuperação.
  • 3 não oferece suporte a imagens de recuperação.
recovery_dtbo Usado para arquiteturas que usam DTB. Especifica o caminho para a imagem DTBO de recuperação. Opcional para dispositivos A/B, que não precisam de uma imagem de recuperação. Dispositivos não A/B usando header_version :
  • 1 ou 2 podem especificar esse caminho ou usar a seção recovery_acpio para especificar um caminho para uma imagem ACPIO de recuperação.
  • 3 não pode especificar uma imagem DTBO de recuperação.
recovery_acpio Usado para arquiteturas que usam ACPI em vez de DTB. Especifica o caminho para a imagem ACPIO de recuperação. Opcional para dispositivos A/B, que não precisam de uma imagem de recuperação. Dispositivos não A/B usando header_version :
  • 1 ou 2 podem especificar esse caminho ou usar a seção recovery_dtbo para especificar um caminho para uma imagem DTBO de recuperação.
  • 3 não pode especificar uma imagem ACPIO de recuperação.
dtb Caminho para a imagem DTB incluída nas imagens de inicialização/recuperação.
dtb_offset Quando adicionado ao argumento base , fornece o endereço de carregamento físico para a árvore de dispositivos final. Por exemplo, se o argumento base for 0x10000000 e o argumento dtb_offset for 0x01000000 , o dtb_addr_field no cabeçalho da imagem de inicialização será preenchido como 0x11000000 .

O dispositivo BoardConfig.mk usa a configuração BOARD_MKBOOTIMG_ARGS para adicionar a header version aos outros argumentos específicos da placa de mkbootimg . Por exemplo:

BOARD_MKBOOTIMG_ARGS := --ramdisk_offset $(BOARD_RAMDISK_OFFSET) --tags_offset $(BOARD_KERNEL_TAGS_OFFSET) --header_version $(BOARD_BOOTIMG_HEADER_VERSION)

O sistema de compilação do Android usa a variável BoardConfig BOARD_PREBUILT_DTBOIMAGE para definir o argumento recovery_dtbo da ferramenta mkbootimg durante a criação da imagem de recuperação. Para obter detalhes sobre as alterações do Android Open Source Project (AOSP), revise as listas de alterações associadas para o controle de versão do cabeçalho da imagem de inicialização .

Cabeçalho da imagem de inicialização, versão 4

O Android 12 fornece um boot_signature no cabeçalho da imagem de inicialização versão 4, que pode ser usado para verificar a integridade do kernel e do ramdisk. A verificação é feita no VtsSecurityAvbTest e é necessária para dispositivos que usam a arquitetura GKI. No entanto, o boot_signature não está envolvido no processo de inicialização verificado específico do dispositivo e é usado apenas no VTS. Consulte a configuração da placa GKI boot.img e as configurações de inicialização verificadas pelo GKI para obter detalhes.

A versão 4 do cabeçalho da imagem de inicialização do fornecedor oferece suporte a fragmentos de disco ram de vários fornecedores.

A versão 4 da versão do cabeçalho da imagem de inicialização usa o seguinte formato.

struct boot_img_hdr
{
#define BOOT_MAGIC_SIZE 8
    uint8_t magic[BOOT_MAGIC_SIZE];

    uint32_t kernel_size;    /* size in bytes */
    uint32_t ramdisk_size;   /* size in bytes */

    uint32_t os_version;

    uint32_t header_size;    /* size of boot image header in bytes */
    uint32_t reserved[4];
    uint32_t header_version; /* offset remains constant for version check */

#define BOOT_ARGS_SIZE 512
#define BOOT_EXTRA_ARGS_SIZE 1024
    uint8_t cmdline[BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE];

    uint32_t signature_size; /* size in bytes */
};

Cabeçalho da imagem de inicialização, versão 3

O Android 11 atualiza o cabeçalho da imagem de inicialização para a versão 3, que remove os seguintes dados:

  • Bootloader de segundo estágio. Os campos second_size e second_addr não aparecem mais no cabeçalho da imagem de inicialização. Dispositivos com um carregador de inicialização de segundo estágio devem armazenar esse carregador de inicialização em sua própria partição.

  • Imagem de recuperação. O requisito para especificar uma imagem de recuperação foi preterido e os campos recovery_dtbo_size , recovery_dtbo_offset , recovery_acpio_size e recovery_acpio_offset não aparecem mais no cabeçalho da imagem de inicialização.

    • Os dispositivos A/B usam um esquema de atualização e recuperação que torna desnecessária a especificação de uma imagem DTBO ou ACPIO para recuperação.

    • Dispositivos não A/B que desejam especificar uma imagem de recuperação (DTBO ou ACPIO) devem usar o cabeçalho da imagem de inicialização versão 1 ou 2.

  • Blob de árvore de dispositivos (DTB). O DTB é armazenado na partição de inicialização do fornecedor , portanto, os campos dtb_size e dtb_addr não aparecem mais no cabeçalho da imagem de inicialização (mas estão presentes no cabeçalho da imagem de inicialização do fornecedor).

Os dispositivos podem usar o cabeçalho da imagem de inicialização versão 3 para cumprir com a arquitetura Generic Kernel Image (GKI) , que unifica o núcleo do kernel e move os módulos do fornecedor necessários para a inicialização para a partição vendor_boot (ou seja, a imagem de inicialização contém apenas componentes GKI). Dispositivos que:

  • Use GKI (requer o kernel android-4.19 ou android-5.4), mas não use atualizações A/B pode especificar uma imagem de recuperação usando a imagem de inicialização versão 3 para a imagem de inicialização e a imagem de inicialização versão 2 para a imagem de recuperação.

  • Não use GKI e não use atualizações A/B pode especificar uma imagem de recuperação usando a imagem de inicialização versão 1 ou 2 para imagens de inicialização e recuperação.

A versão 3 da versão do cabeçalho da imagem de inicialização usa o seguinte formato.

struct boot_img_hdr
{
#define BOOT_MAGIC_SIZE 8
    uint8_t magic[BOOT_MAGIC_SIZE];

    uint32_t kernel_size;    /* size in bytes */
    uint32_t ramdisk_size;   /* size in bytes */

    uint32_t os_version;

    uint32_t header_size;    /* size of boot image header in bytes */
    uint32_t reserved[4];
    uint32_t header_version; /* offset remains constant for version check */

#define BOOT_ARGS_SIZE 512
#define BOOT_EXTRA_ARGS_SIZE 1024
    uint8_t cmdline[BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE];
};

Cabeçalho da imagem de inicialização, versão 2

O Android 10 atualiza o cabeçalho da imagem de inicialização para a versão 2, que adiciona uma seção para informações de imagem DTB de recuperação (tamanho da imagem e endereço de carregamento físico).

A versão 2 da versão do cabeçalho da imagem de inicialização usa o seguinte formato.

struct boot_img_hdr
{
    uint8_t magic[BOOT_MAGIC_SIZE];
    uint32_t kernel_size;               /* size in bytes */
    uint32_t kernel_addr;               /* physical load addr */

    uint32_t ramdisk_size;              /* size in bytes */
    uint32_t ramdisk_addr;              /* physical load addr */

    uint32_t second_size;               /* size in bytes */
    uint32_t second_addr;               /* physical load addr */

    uint32_t tags_addr;                 /* physical addr for kernel tags */
    uint32_t page_size;                 /* flash page size we assume */
    uint32_t header_version;
    uint32_t os_version;
    uint8_t name[BOOT_NAME_SIZE];       /* asciiz product name */
    uint8_t cmdline[BOOT_ARGS_SIZE];
    uint32_t id[8];                     /* timestamp / checksum / sha1 / etc */
    uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
    uint32_t recovery_[dtbo|acpio]_size;    /* size of recovery image */
    uint64_t recovery_[dtbo|acpio]_offset;  /* offset in boot image */
    uint32_t header_size;               /* size of boot image header in bytes */
    uint32_t dtb_size;                  /* size of dtb image */
    uint64_t dtb_addr;                  /* physical load address */
};

Cabeçalho da imagem de inicialização, versão 1

O Android 9 converte o campo unused do cabeçalho da imagem de inicialização em um campo de versão do cabeçalho. Os dispositivos iniciados com o Android 9 devem usar o cabeçalho da imagem de inicialização com a versão do cabeçalho definida como 1 ou superior (isso é verificado pelo VTS).

A versão 1 da versão do cabeçalho da imagem de inicialização usa o formato a seguir.

struct boot_img_hdr
{
    uint8_t magic[BOOT_MAGIC_SIZE];
    uint32_t kernel_size;               /* size in bytes */
    uint32_t kernel_addr;               /* physical load addr */
    uint32_t ramdisk_size;              /* size in bytes */
    uint32_t ramdisk_addr;              /* physical load addr */

    uint32_t second_size;               /* size in bytes */
    uint32_t second_addr;               /* physical load addr */

    uint32_t tags_addr;                 /* physical addr for kernel tags */
    uint32_t page_size;                 /* flash page size we assume */
    uint32_t header_version;
    uint32_t os_version;
    uint8_t name[BOOT_NAME_SIZE];       /* asciiz product name */
    uint8_t cmdline[BOOT_ARGS_SIZE];
    uint32_t id[8];                     /* timestamp / checksum / sha1 / etc */
    uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
    uint32_t recovery_[dtbo|acpio]_size;    /* size of recovery image */
    uint64_t recovery_[dtbo|acpio]_offset;  /* offset in boot image */
    uint32_t header_size;               /* size of boot image header in bytes */
};

Dispositivos não A/B podem especificar uma imagem de sobreposição DTB/ACPI para recuperação para ajudar a mitigar falhas de atualização over-the-air (OTA). (Os dispositivos A/B não têm esse problema e não precisam especificar uma imagem de sobreposição.) Você pode especificar uma imagem DTBO ou uma imagem ACPIO, mas não ambas (porque elas são usadas por diferentes arquiteturas). Para configurar o cabeçalho da imagem de inicialização corretamente, ao usar:

  • Uma imagem DTBO para recuperação, inclua os campos recovery_dtbo_size e recovery_dtbo_offset (e não inclua os campos recovery_acpio_size e recovery_acpio_offset ).

  • Uma imagem ACPIO para recuperação, inclua os campos recovery_acpio_size e recovery_acpio_offset (e não inclua os campos recovery_dtbo_size e recovery_dtbo_offset ).

O campo header_size contém o tamanho do cabeçalho da imagem de inicialização. Se a versão do cabeçalho da imagem de inicialização for definida como 1, o campo id conterá o resumo SHA-1 para a seção recovery_[dtbo|acpio] da imagem de inicialização, além das seções kernel , ramdisk e second sections . Para obter detalhes sobre os recovery_[dtbo|acpio]_size e recovery_[dtbo|acpio]_offset , consulte Imagens de recuperação .

Cabeçalho de imagem de inicialização herdado, versão 0

Dispositivos lançados antes do Android 9 usando o cabeçalho de imagem de inicialização herdado são considerados como usando um cabeçalho de imagem de inicialização versão 0.

struct boot_img_hdr
{
    uint8_t magic[BOOT_MAGIC_SIZE];
    uint32_t kernel_size;                /* size in bytes */
    uint32_t kernel_addr;                /* physical load addr */

    uint32_t ramdisk_size;               /* size in bytes */
    uint32_t ramdisk_addr;               /* physical load addr */

    uint32_t second_size;                /* size in bytes */
    uint32_t second_addr;                /* physical load addr */

    uint32_t tags_addr;                  /* physical addr for kernel tags */
    uint32_t page_size;                  /* flash page size we assume */
    uint32_t unused;
    uint32_t os_version;
    uint8_t name[BOOT_NAME_SIZE];        /* asciiz product name */
    uint8_t cmdline[BOOT_ARGS_SIZE];
    uint32_t id[8];                      /* timestamp / checksum / sha1 / etc */
    uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
};