Partitions de démarrage du fournisseur

Restez organisé à l'aide des collections Enregistrez et classez les contenus selon vos préférences.

Android 11 a introduit le concept de l'image générique du noyau (GKI). Pour permettre de démarrer facilement un appareil arbitraire avec le GKI, les appareils Android 11 peuvent utiliser l'en-tête d'image de démarrage version 3. Dans la version 3, toutes les informations spécifiques au fournisseur sont exclues de la partition de boot et déplacées dans une nouvelle partition vendor_boot . Un appareil ARM64 lancé avec Android 11 sur le noyau Linux 5.4 doit prendre en charge la partition vendor_boot et le format de partition de boot mis à jour pour réussir les tests avec le GKI.

Les appareils Android 12 peuvent utiliser la version 4 de l'en-tête d'image de démarrage, qui prend en charge l'inclusion de plusieurs disques RAM de fournisseur dans la partition vendor_boot . Plusieurs fragments de disque virtuel fournisseur sont concaténés les uns après les autres dans la section disque virtuel fournisseur. Une table de disque virtuel fournisseur est utilisée pour décrire la disposition de la section du disque virtuel fournisseur et les métadonnées de chaque fragment de disque virtuel fournisseur.

Structure des partitions

La partition de démarrage du fournisseur est A/B avec A/B virtuel et protégée par Android Verified Boot.

Variante 3

La partition se compose d'un en-tête, du disque virtuel du fournisseur et du blob de l'arborescence des périphériques (DTB).

Section Nombre de pages
En-tête de démarrage du fournisseur (n pages) n = (2112 + page_size - 1) / page_size
Disque virtuel du fournisseur (o pages) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (p pages) p = (dtb_size + page_size - 1) / page_size

Variante 4

La partition se compose d'un en-tête, de la section du disque virtuel du fournisseur (constituée de tous les fragments de disque virtuel du fournisseur, concaténés), du blob de l'arborescence des périphériques (DTB) et de la table du disque virtuel du fournisseur.

Section Nombre de pages
En-tête de démarrage du fournisseur (n pages) n = (2128 + page_size - 1) / page_size
Fragments de disque virtuel du fournisseur (o pages) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (p pages) p = (dtb_size + page_size - 1) / page_size
Table des disques virtuels du fournisseur (q pages) q = (vendor_ramdisk_table_size + page_size - 1) / page_size
Bootconfig (r pages) r = (bootconfig_size + page_size - 1) / page_size

En-tête de démarrage du fournisseur

Le contenu de l'en-tête de la partition de démarrage du fournisseur se compose principalement de données qui y ont été déplacées à partir de l' en-tête de l'image de démarrage . Il contient également des informations sur le disque virtuel du fournisseur.

Variante 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 */

};

Variante 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 est la taille totale de tous les fragments de disque virtuel du fournisseur.
  • ramdisk_type indique le type du disque virtuel, les valeurs possibles sont :
    • VENDOR_RAMDISK_TYPE_NONE indique que la valeur n'est pas spécifiée.
    • Les disques VENDOR_RAMDISK_TYPE_PLATFORM contiennent des bits spécifiques à la plate-forme. Le chargeur de démarrage doit toujours les charger en mémoire.
    • Les disques VENDOR_RAMDISK_TYPE_RECOVERY contiennent des ressources de récupération. Le chargeur de démarrage doit les charger en mémoire lors du démarrage en récupération.
    • Les disques VENDOR_RAMDISK_TYPE_DLKM contiennent des modules de noyau chargeables dynamiquement.
  • ramdisk_name est un nom unique du disque virtuel.
  • board_id est un vecteur d'identificateurs de matériel définis par le fournisseur.

Prise en charge du chargeur de démarrage

Étant donné que la partition de démarrage du fournisseur contient des informations (telles que la taille de la page flash, le noyau, les adresses de chargement du disque RAM, le DTB lui-même) qui existaient auparavant dans la partition de démarrage, le chargeur de démarrage doit accéder à la fois aux partitions de démarrage et de démarrage du fournisseur pour avoir suffisamment de données pour terminer le démarrage. .

Le chargeur de démarrage doit charger le disque virtuel générique en mémoire immédiatement après le disque virtuel du fournisseur (les formats CPIO, Gzip et lz4 prennent en charge ce type de concaténation). N'alignez pas la page de l'image du disque virtuel générique et n'introduisez aucun autre espace entre celle-ci et la fin du disque virtuel du fournisseur en mémoire. Une fois le noyau décompressé, il extrait le fichier concaténé dans un initramfs , ce qui donne une structure de fichiers qui est un disque virtuel générique superposé à la structure de fichiers du disque virtuel du fournisseur.

Étant donné que le disque virtuel générique et le disque virtuel du fournisseur sont concaténés, ils doivent être au même format. L'image de démarrage GKI utilise un disque virtuel générique compressé en lz4. Par conséquent, un périphérique compatible GKI doit utiliser un disque virtuel fournisseur compressé en lz4. La configuration pour cela est illustrée ci-dessous.

Les exigences du chargeur de démarrage pour la prise en charge de bootconfig sont expliquées sur la page Implémentation de Bootconfig .

Disques RAM multifournisseurs (version 4)

Avec la version 4 de l'en-tête d'image de démarrage, le chargeur de démarrage peut sélectionner un sous-ensemble ou tous les disques virtuels du fournisseur à charger en tant initramfs au démarrage. La table des disques virtuels du fournisseur contient les métadonnées de chaque disque virtuel et peut aider le chargeur de démarrage à décider quels disques virtuels charger. Le chargeur de démarrage peut décider de l'ordre de chargement des disques virtuels du fournisseur sélectionné, tant que le disque virtuel générique est chargé en dernier.

Par exemple, le chargeur de démarrage peut omettre de charger les ramdisks du fournisseur de type VENDOR_RAMDISK_TYPE_RECOVERY lors du démarrage normal pour économiser les ressources, de sorte que seuls les ramdisks du fournisseur de type VENDOR_RAMDISK_TYPE_PLATFORM et VENDOR_RAMDISK_TYPE_DLKM sont chargés en mémoire. D'un autre côté, les disques virtuels du fournisseur de type VENDOR_RAMDISK_TYPE_PLATFORM , VENDOR_RAMDISK_TYPE_RECOVERY et VENDOR_RAMDISK_TYPE_DLKM sont chargés en mémoire lors du démarrage en mode de récupération.

Alternativement, le chargeur de démarrage peut ignorer la table du disque virtuel du fournisseur et charger toute la section du disque virtuel du fournisseur. Cela a le même effet que le chargement de tous les fragments de disque virtuel du fournisseur dans la partition vendor_boot .

Construire un support

Pour implémenter la prise en charge du démarrage du fournisseur pour un appareil :

  • Définissez BOARD_BOOT_HEADER_VERSION sur 3 ou plus.

  • Définissez BOARD_RAMDISK_USE_LZ4 sur true si votre appareil est compatible GKI, ou s'il utilise autrement un ramdisk générique compressé lz4.

  • Définissez BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE sur une taille appropriée pour votre appareil, en tenant compte des modules du noyau qui doivent aller sur le disque virtuel du fournisseur.

  • Mettez à jour AB_OTA_PARTITIONS pour inclure vendor_boot et toutes les listes de partitions OTA spécifiques au fournisseur sur le périphérique.

  • Copiez le fstab de votre appareil dans /first_stage_ramdisk dans la partition vendor_boot , pas la partition de boot . Par exemple, $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM) .

Pour inclure plusieurs ramdisks de fournisseur dans vendor_boot :

  • Définissez BOARD_BOOT_HEADER_VERSION sur 4 .
  • Définissez BOARD_VENDOR_RAMDISK_FRAGMENTS sur une liste de noms de fragments de disque virtuel de fournisseur logique à inclure dans vendor_boot .

  • Pour ajouter un ramdisk fournisseur prédéfini, définissez BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT sur le chemin du fichier prédéfini.

  • Pour ajouter un disque virtuel de fournisseur DLKM, définissez BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS dans la liste des répertoires de modules du noyau à inclure.

  • Définissez BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS sur les arguments mkbootimg . Il s'agit des --board_id[0-15] et --ramdisk_type pour le fragment de disque virtuel du fournisseur. Pour le ramdisk du fournisseur DLKM, le --ramdisk_type par défaut serait DLKM s'il n'est pas spécifié autrement.

Pour créer des ressources de récupération en tant que ramdisk de recovery autonome dans vendor_boot :

  • Définissez BOARD_BOOT_HEADER_VERSION sur 4 .
  • Définissez BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT sur true .
  • Définissez BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT sur true .
  • Cela ajoute un fragment de ramdisk fournisseur dont ramdisk_name est recovery et ramdisk_type est VENDOR_RAMDISK_TYPE_RECOVERY . Le disque virtuel contient alors tous les fichiers de récupération, qui sont des fichiers installés sous $(TARGET_RECOVERY_ROOT_OUT) .

Arguments mkbootimg

Argument La description
--ramdisk_type Le type de disque virtuel peut être NONE , PLATFORM , DLKM RECOVERY
--board_id[0-15] Spécifiez le vecteur board_id , par défaut à 0 .

Voici un exemple de configuration :

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

Le vendor_boot résultant contiendrait deux fragments de disque virtuel du fournisseur. Le premier est le disque virtuel "par défaut", qui contient le répertoire DLKM baz et le reste des fichiers dans $(TARGET_VENDOR_RAMDISK_OUT) . Le second est le disque virtuel dlkm_foobar , qui contient les répertoires DLKM foo et bar , et le --ramdisk_type défaut est DLKM .