Implémenter bootconfig dans Android 12

Dans Android 12, la fonctionnalité bootconfig remplace les options de ligne de commande du kernel androidboot.* utilisées avec Android 11 ou version antérieure. La fonctionnalité bootconfig est un mécanisme permettant de transmettre les détails de configuration de la compilation et du bootloader à Android 12.

Cette fonctionnalité permet de séparer les paramètres de configuration de l'espace utilisateur Android de ceux du noyau. Le déplacement des longs paramètres du kernel androidboot.* vers le fichier bootconfig crée de l'espace sur la ligne de commande du kernel et le rend disponible pour une future extension.

Le noyau et l'espace utilisateur Android doivent tous deux prendre en charge bootconfig.

  • Première version compatible: Android 12
  • Première version de kernel compatible: kernel 12-5.4.xx

Implémentation de la fonctionnalité bootconfig pour les nouveaux appareils lancés avec une version de kernel 12-5.10.xx. Vous n'avez pas besoin de l'implémenter si vous mettez à niveau des appareils.

Exemples et source

En consultant les exemples et le code source de cette section, notez que le format du code bootconfig n'est que légèrement différent de celui de la ligne de commande du noyau utilisée dans Android 11 et versions antérieures. Cependant, la différence suivante est importante pour votre utilisation:

  • Les paramètres doivent être séparés par la séquence d'échappement de saut de ligne \n, et non par des espaces.

Exemple de bootloader

Pour obtenir un exemple de bootloader, consultez l'implémentation du bootloader de référence U-boot de Cuttlefish. Deux commits de la référence sont listés ci-dessous. La première permet de mettre à jour la compatibilité de l'en-tête de démarrage vers la dernière version. Dans l'exemple, le premier commit met à jour (ou met à niveau) la compatibilité de la version avec la suivante, la version 4. La seconde a deux avantages : elle ajoute la gestion de bootconfig et illustre l'ajout de paramètres au moment de l'exécution :

Créer un exemple

Pour obtenir un exemple de compilation montrant les modifications apportées à mkbootimg pour compiler le vendor_boot.img avec l'en-tête de démarrage fournisseur v4, consultez mkbootimg changes for bootconfig. Consultez les modifications apportées à Cuttlefish pour effectuer les opérations suivantes:

Implémentation

Les partenaires doivent ajouter la prise en charge à leurs bootloaders et déplacer leurs paramètres androidboot.* au moment de la compilation de la ligne de commande du kernel vers le fichier bootconfig. Le meilleur moyen de mettre en œuvre cette modification est de le faire de manière incrémentielle. Consultez la section Implémentation incrémentielle et validation pour en savoir plus sur le suivi d'un processus incrémentiel.

Si des modifications recherchent des paramètres androidboot.* dans le fichier /proc/cmdline, pointez-les plutôt vers le fichier /proc/bootconfig. Les propriétés ro.boot.* sont définies avec les nouvelles valeurs bootconfig. Vous n'avez donc pas besoin d'apporter de modifications au code qui utilise ces propriétés.

Modifications de la compilation

Commencez par mettre à niveau la version de l'en-tête de démarrage vers la version 4:

- BOARD_BOOT_HEADER_VERSION := 3

+ BOARD_BOOT_HEADER_VERSION := 4

Ajoutez le paramètre cmdline du noyau bootconfig. Le noyau recherche alors la section "bootconfig" :

BOARD_KERNEL_CMDLINE += bootconfig

Les paramètres de bootconfig sont créés à partir des paramètres de la variable BOARD_BOOTCONFIG, tout comme la cmdline du kernel est créée à partir de BOARD\_KERNEL\_CMDLINE.

Tous les paramètres androidboot.* peuvent être déplacés tels quels, comme suit:

- BOARD_KERNEL_CMDLINE += androidboot..selinux=enforcing

+ BOARD_BOOTCONFIG += androidboot..selinux=enforcing

Modifications apportées au bootloader

Le bootloader configure le initramfs avant de passer au kernel. La configuration de démarrage du kernel recherche la section "bootconfig" et vérifie qu'elle se trouve tout à la fin de initramfs, avec la remorque attendue.

Le bootloader obtient les informations de mise en page vendor_boot.img à partir de l'en-tête de l'image de démarrage du fournisseur.

Schéma de la mise en page de l'allocation de mémoire avec bootconfig

Figure 1 : Allocation de mémoire du fichier de configuration de démarrage Android 12

Le bootloader crée la section "bootconfig" en mémoire. La section "bootconfig" contient des allocations de mémoire pour les éléments suivants:

  • Paramètres
  • 4 B parameters size
  • Taille 4 B parameters checksum
  • Chaîne magique de bootconfig de 12 Mo (#BOOTCONFIG\n)

Les paramètres proviennent de deux sources: les paramètres connus au moment de la compilation et les paramètres inconnus au moment de la compilation. Vous devez ajouter les paramètres inconnus.

Les paramètres connus au moment de la compilation sont empaquetés à la fin de l'image vendor_boot dans la section bootconfig. La taille de la section est stockée (en octets) dans le champ vendor_bootconfig_size de l'en-tête de démarrage du fournisseur.

Les paramètres qui ne sont pas connus au moment de la compilation ne le sont qu'au moment de l'exécution dans le bootloader. Ils doivent être ajoutés à la fin de la section des paramètres de bootconfig avant que la remorque de bootconfig ne soit appliquée.

Si vous devez ajouter des paramètres après l'application de la bande-annonce bootconfig, remplacez-la, puis appliquez-la à nouveau.

Implémentation et validation incrémentielles

Implémentez la fonctionnalité de bootconfig de manière incrémentielle en suivant la procédure décrite dans cette section. Ne modifiez pas les paramètres de ligne de commande du noyau pendant l'ajout des paramètres bootconfig.

Voici les étapes d'une implémentation incrémentielle, avec validation:

  1. Apportez les modifications au bootloader et à la compilation, puis procédez comme suit :
    1. Utilisez la variable BOARD_BOOTCONFIG pour ajouter un paramètre de démarrage.
    2. Laissez les paramètres cmdline du noyau tels quels pour que l'appareil puisse continuer à démarrer correctement. Cela facilite grandement le débogage et la validation.
  2. Vérifiez votre travail en consultant le contenu de /proc/bootconfig. Vérifiez que le paramètre que vous venez d'ajouter s'affiche après le démarrage de l'appareil.
  3. Déplacez les paramètres androidboot.* de la ligne de commande du kernel vers le fichier de configuration de démarrage, à l'aide de la variable BOARD_BOOTCONFIG et du bootloader.
  4. Vérifiez que chacun des paramètres existe dans /proc/bootconfig ET qu'ils ne sont pas dans /proc/cmdline. Si vous pouvez le vérifier, votre implémentation a réussi.

Remarques concernant les mises à niveau et les rétrogradations OTA

Lorsque vous gérez les mises à niveau et les rétrogradations OTA entre différentes versions d'Android ou différentes versions du kernel, vous devez faire preuve de prudence.

Android 12 est la première version compatible avec bootconfig. Si vous effectuez une rétrogradation vers une version antérieure, vous devez utiliser les paramètres de ligne de commande du kernel au lieu de bootconfig.

Les versions de kernel 12-5.4 et ultérieures sont compatibles avec bootconfig. Si vous effectuez une rétrogradation vers une version antérieure(y compris 11-5.4), vous devez utiliser les paramètres de ligne de commande du kernel.

Les mises à niveau d'Android 11 ou version antérieure vers Android 12 ou version ultérieure peuvent continuer à utiliser les paramètres de ligne de commande du noyau. Il en va de même pour la mise à niveau des versions de noyau.

Dépannage

Lorsque vous effectuez l'étape de vérification, si vous ne voyez pas les paramètres attendus dans /proc/bootconfig, vérifiez les journaux du kernel dans logcat. Une entrée de journal est toujours présente pour bootconfig si le noyau le prend en charge.

Exemple de sortie de journal

$ adb logcat | grep bootconfig
02-24 17:00:07.610     0     0 I Load bootconfig: 128 bytes 9 nodes

Si un journal d'erreur est renvoyé, un problème s'est produit lors du chargement du fichier de démarrage. Pour afficher les différents types d'erreurs, consultez init/main.c.