Particiones de arranque del proveedor

Android 11 introdujo el concepto de imagen de kernel genérica (GKI). Para permitir el arranque fácil de un dispositivo arbitrario con GKI, los dispositivos con Android 11 pueden usar el encabezado de la imagen de arranque versión 3. En la versión 3, toda la información específica del proveedor se elimina de la partición boot y se reubica en una nueva partición vendor_boot . Un dispositivo ARM64 que se inicia con Android 11 en el kernel de Linux 5.4 debe admitir la partición vendor_boot y el formato de partición boot actualizado para pasar las pruebas con GKI.

Los dispositivos Android 12 pueden usar el encabezado de imagen de arranque versión 4, que admite la inclusión de varios discos RAM de proveedores en la partición vendor_boot . Varios fragmentos de disco ram del proveedor se concatenan uno tras otro en la sección del disco ram del proveedor. Se utiliza una tabla de disco ram del proveedor para describir el diseño de la sección del disco ram del proveedor y los metadatos de cada fragmento del disco ram del proveedor.

Estructura de partición

La partición de inicio del proveedor es A/B con A/B virtual y está protegida por el inicio verificado de Android.

Versión 3

La partición consta de un encabezado, el disco ram del proveedor y el blob de árbol de dispositivos (DTB).

Sección Número de páginas
Encabezado de inicio del proveedor (n páginas) n = (2112 + page_size - 1) / page_size
Disco RAM del proveedor (o páginas) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (p páginas) p = (dtb_size + page_size - 1) / page_size

Versión 4

La partición consta de un encabezado, la sección del disco ram del proveedor (que consta de todos los fragmentos del disco ram del proveedor, concatenados), el blob del árbol de dispositivos (DTB) y la tabla del disco ram del proveedor.

Sección Número de páginas
Encabezado de inicio del proveedor (n páginas) n = (2128 + page_size - 1) / page_size
Fragmentos de disco ram del proveedor (o páginas) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (p páginas) p = (dtb_size + page_size - 1) / page_size
Tabla de discos RAM del proveedor (q páginas) q = (vendor_ramdisk_table_size + page_size - 1) / page_size
Bootconfig (r páginas) r = (bootconfig_size + page_size - 1) / page_size

Encabezado de inicio del proveedor

El contenido del encabezado de la partición de inicio del proveedor consiste principalmente en datos que se reubicaron allí desde el encabezado de la imagen de inicio . También contiene información sobre el disco RAM del proveedor.

Versión 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 */

};

Versión 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 es el tamaño total de todos los fragmentos del disco ram del proveedor.
  • ramdisk_type indica el tipo de disco ram, los valores posibles son:
    • VENDOR_RAMDISK_TYPE_NONE indica que el valor no está especificado.
    • Los discos VENDOR_RAMDISK_TYPE_PLATFORM contienen bits específicos de la plataforma. El gestor de arranque siempre debe cargarlos en la memoria.
    • Los discos VENDOR_RAMDISK_TYPE_RECOVERY contienen recursos de recuperación. El gestor de arranque debe cargarlos en la memoria al iniciar en recuperación.
    • Los discos ram VENDOR_RAMDISK_TYPE_DLKM contienen módulos de kernel cargables dinámicos.
  • ramdisk_name es un nombre único del disco ram.
  • board_id es un vector de identificadores de hardware definidos por el proveedor.

Soporte de cargador de arranque

Debido a que la partición de inicio del proveedor contiene información (como el tamaño de la página flash, el kernel, las direcciones de carga del disco ram, el propio DTB) que existía previamente en la partición de inicio, el gestor de arranque debe acceder tanto a la partición de inicio como a la del proveedor para tener suficientes datos para completar el inicio. .

El gestor de arranque debe cargar el disco ram genérico en la memoria inmediatamente después del disco ram del proveedor (los formatos CPIO, Gzip y lz4 admiten este tipo de concatenación). No alinee la página de la imagen del disco ram genérico ni introduzca ningún otro espacio entre ella y el final del disco ram del proveedor en la memoria. Después de descomprimir el kernel, extrae el archivo concatenado en un initramfs , lo que da como resultado una estructura de archivos que es un disco ram genérico superpuesto a la estructura de archivos del disco ram del proveedor.

Debido a que el disco RAM genérico y el disco RAM del proveedor se concatenan, deben tener el mismo formato. La imagen de arranque de GKI utiliza un disco ram genérico comprimido con lz4, por lo que un dispositivo compatible con GKI debe utilizar un disco ram de proveedor comprimido con lz4. La configuración para esto se muestra a continuación.

Los requisitos del gestor de arranque para admitir bootconfig se explican en la página Implementación de Bootconfig .

Discos ram de múltiples proveedores (versión 4)

Con la versión 4 del encabezado de la imagen de arranque, el gestor de arranque puede seleccionar un subconjunto o todos los discos RAM del proveedor para cargarlos como initramfs durante el tiempo de arranque. La tabla de discos ram del proveedor contiene los metadatos de cada disco ram y puede ayudar al gestor de arranque a decidir qué discos ram cargar. El gestor de arranque puede decidir el orden en que se cargarán los discos ram del proveedor seleccionado, siempre que el disco ram genérico se cargue en último lugar.

Por ejemplo, el gestor de arranque puede omitir la carga de discos RAM del proveedor de tipo VENDOR_RAMDISK_TYPE_RECOVERY durante el arranque normal para conservar recursos, por lo que solo se cargan en la memoria los discos RAM del proveedor de tipo VENDOR_RAMDISK_TYPE_PLATFORM y VENDOR_RAMDISK_TYPE_DLKM . Por otro lado, los discos RAM del proveedor de tipo VENDOR_RAMDISK_TYPE_PLATFORM , VENDOR_RAMDISK_TYPE_RECOVERY y VENDOR_RAMDISK_TYPE_DLKM se cargan en la memoria cuando se inicia en modo de recuperación.

Alternativamente, el gestor de arranque puede ignorar la tabla del disco ram del proveedor y cargar toda la sección del disco ram del proveedor. Esto tiene el mismo efecto que cargar todos los fragmentos del disco ram del proveedor en la partición vendor_boot .

Construir soporte

Para implementar soporte de arranque de proveedor para un dispositivo:

  • Establezca BOARD_BOOT_HEADER_VERSION en 3 o más.

  • Establezca BOARD_RAMDISK_USE_LZ4 en true si su dispositivo es compatible con GKI o si utiliza un disco ram genérico comprimido con lz4.

  • Configure BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE en un tamaño apropiado para su dispositivo, considerando los módulos del kernel que deben ir en el disco RAM del proveedor.

  • Actualice AB_OTA_PARTITIONS para incluir vendor_boot y cualquier lista específica del proveedor de particiones OTA en el dispositivo.

  • Copie fstab de su dispositivo en /first_stage_ramdisk en la partición vendor_boot , no en la partición boot . Por ejemplo, $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM) .

Para incluir varios discos ram de proveedores en vendor_boot :

  • Establezca BOARD_BOOT_HEADER_VERSION en 4 .
  • Establezca BOARD_VENDOR_RAMDISK_FRAGMENTS en una lista de nombres de fragmentos de disco ram de proveedores lógicos que se incluirán en vendor_boot .

  • Para agregar un disco RAM de proveedor precompilado, configure BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT en la ruta del archivo precompilado.

  • Para agregar un disco ram de proveedor DLKM, configure BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS en la lista de directorios de módulos del kernel que se incluirán.

  • Establezca BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS en los argumentos mkbootimg . Estos son los argumentos --board_id[0-15] y --ramdisk_type para el fragmento de disco RAM del proveedor. Para el disco ram del proveedor de DLKM, el --ramdisk_type predeterminado sería DLKM si no se especifica lo contrario.

Para crear recursos de recuperación como un disco ram recovery independiente en vendor_boot :

  • Establezca BOARD_BOOT_HEADER_VERSION en 4 .
  • Establezca BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT en true .
  • Establezca BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT en true .
  • Esto agrega un fragmento de disco ram del proveedor cuyo ramdisk_name es recovery y ramdisk_type es VENDOR_RAMDISK_TYPE_RECOVERY . Luego, el disco RAM contiene todos los archivos de recuperación, que son archivos instalados en $(TARGET_RECOVERY_ROOT_OUT) .

argumentos mkbootimg

Argumento Descripción
--ramdisk_type El tipo de disco RAM puede ser NONE , PLATFORM , RECOVERY o DLKM .
--board_id[0-15] Especifique el vector board_id , el valor predeterminado es 0 .

A continuación se muestra una configuración de ejemplo:

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

El vendor_boot resultante contendría dos fragmentos de disco RAM del proveedor. El primero es el disco RAM "predeterminado", que contiene el directorio DLKM baz y el resto de los archivos en $(TARGET_VENDOR_RAMDISK_OUT) . El segundo es el disco ram dlkm_foobar , que contiene los directorios DLKM foo y bar , y --ramdisk_type por defecto es DLKM .