Les OEM et les fournisseurs de SoC qui souhaitent implémenter les mises à jour du système A/B doivent s'assurer que leur chargeur de démarrage implémente le boot_control HAL et transmet les paramètres corrects au noyau.
Implémentation du contrôle de démarrage HAL
Les chargeurs de démarrage compatibles A/B doivent implémenter le boot_control
HAL dans hardware/libhardware/include/hardware/boot_control.h
. Vous pouvez tester les implémentations à l'aide de l'utilitaire system/extras/bootctl
et system/extras/tests/bootloader/
.
Vous devez également implémenter la machine d'état illustrée ci-dessous :

Configuration du noyau
Pour implémenter les mises à jour du système A/B :
- Cherrypick la série de correctifs de noyau suivante (si nécessaire):
- Si vous démarrez sans disque virtuel et utilisez "boot as recovery", sélectionnez android-review.googlesource.com/#/c/158491/ .
- Pour configurer dm-verity sans disque virtuel, sélectionnez android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18 .
- Assurez-vous que les arguments de la ligne de commande du noyau contiennent les arguments supplémentaires suivants :
skip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
<public-key-id>
est l'ID de la clé publique utilisée pour vérifier la signature de la table de vérification (pour plus de détails, voir dm-verity ) . - Ajoutez le certificat .X509 contenant la clé publique au trousseau de clés système :
- Copiez le certificat .X509 formaté au format
.der
à la racine du répertoire dukernel
. Si le certificat .X509 est formaté en tant que fichier.pem
, utilisez la commandeopenssl
suivante pour convertir du format.pem
au format.der
:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
- Créez le
zImage
pour inclure le certificat dans le trousseau de clés du système. Pour vérifier, vérifiez l'entréeprocfs
(nécessite l'activation deKEYS_CONFIG_DEBUG_PROC_KEYS
) :angler:/# cat /proc/keys 1c8a217e I------ 1 perm 1f010000 0 0 asymmetri Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f [] 2d454e3e I------ 1 perm 1f030000 0 0 keyring .system_keyring: 1/4
L'inclusion réussie du certificat .X509 indique la présence de la clé publique dans le trousseau de clés du système (la surbrillance indique l'ID de la clé publique). - Remplacez l'espace par
#
et transmettez-le en tant que<public-key-id>
dans la ligne de commande du noyau. Par exemple, passezAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40f
à la place de<public-key-id>
.
- Copiez le certificat .X509 formaté au format
Définition des variables de construction
Les chargeurs de démarrage compatibles A/B doivent répondre aux critères de variable de construction suivants :
Doit être défini pour la cible A/B |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk . Vous pouvez éventuellement effectuer l'étape dex2oat post-installation (mais avant redémarrage) décrite dans Compilation . |
---|---|
Fortement recommandé pour la cible A/B |
|
Impossible de définir pour la cible A/B |
|
Facultatif pour les versions de débogage | PRODUCT_PACKAGES_DEBUG += update_engine_client |
Paramétrage des partitions (slots)
Les appareils A/B n'ont pas besoin d'une partition de récupération ou d'une partition de cache car Android n'utilise plus ces partitions. La partition de données est maintenant utilisée pour le package OTA téléchargé et le code de l'image de récupération se trouve sur la partition de démarrage. Toutes les partitions A/B-ed doivent être nommées comme suit (les emplacements sont toujours nommés a
, b
, etc.) : boot_a
, boot_b
, system_a
, system_b
, vendor_a
, vendor_b
.
Cache
Pour les mises à jour non A/B, la partition de cache a été utilisée pour stocker les packages OTA téléchargés et pour stocker temporairement les blocs lors de l'application des mises à jour. Il n'y a jamais eu de bonne façon de dimensionner la partition de cache : sa taille dépendait des mises à jour que vous vouliez appliquer. Le pire des cas serait une partition de cache aussi grande que l'image système. Avec les mises à jour A/B, il n'est pas nécessaire de stocker des blocs (car vous écrivez toujours sur une partition qui n'est pas utilisée actuellement) et avec le streaming A/B, il n'est pas nécessaire de télécharger l'ensemble du package OTA avant de l'appliquer.
Récupération
Le disque RAM de récupération est maintenant contenu dans le fichier boot.img
. Lors de la récupération, le chargeur de démarrage ne peut pas mettre l'option skip_initramfs
sur la ligne de commande du noyau.
Pour les mises à jour non A/B, la partition de récupération contient le code utilisé pour appliquer les mises à jour. Les mises à jour A/B sont appliquées par update_engine
s'exécutant dans l'image système démarrée normale. Il existe toujours un mode de récupération utilisé pour implémenter la réinitialisation des données d'usine et le chargement latéral des packages de mise à jour (d'où vient le nom "récupération"). Le code et les données du mode de récupération sont stockés dans la partition de démarrage normale d'un disque virtuel ; pour démarrer dans l'image système, le chargeur de démarrage indique au noyau d'ignorer le disque virtuel (sinon le périphérique démarre en mode de récupération. Le mode de récupération est petit (et une grande partie était déjà sur la partition de démarrage), donc la partition de démarrage n'augmente pas en taille.
Fstab
L'argument slotselect
doit être sur la ligne pour les partitions A/B-ed. Par exemple:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
Aucune partition ne doit être nommée vendor
. Au lieu de cela, la partition vendor_a
ou vendor_b
sera sélectionnée et montée sur le point de montage /vendor
.
Arguments d'emplacement du noyau
Le suffixe d'emplacement actuel doit être transmis via un nœud d'arborescence de périphériques (DT) spécifique ( /firmware/android/slot_suffix
) ou via la ligne de commande du noyau androidboot.slot_suffix
ou l'argument bootconfig.
Par défaut, fastboot fait clignoter l'emplacement actuel sur un périphérique A/B. Si le package de mise à jour contient également des images pour l'autre emplacement non actuel, fastboot fait également clignoter ces images. Les options disponibles incluent :
-
--slot SLOT
. Remplacez le comportement par défaut et invitez fastboot à flasher l'emplacement transmis en tant qu'argument. -
--set-active [ SLOT ]
. Définissez l'emplacement comme actif. Si aucun argument facultatif n'est spécifié, l'emplacement actuel est défini comme actif. -
fastboot --help
. Obtenez des détails sur les commandes.
Si le chargeur de démarrage implémente le démarrage rapide, il doit prendre en charge la commande set_active <slot>
qui définit l'emplacement actif actuel sur l'emplacement donné (cela doit également effacer l'indicateur non amorçable pour cet emplacement et réinitialiser le nombre de tentatives aux valeurs par défaut). Le chargeur de démarrage doit également prendre en charge les variables suivantes :
-
has-slot:<partition-base-name-without-suffix>
. Renvoie « oui » si la partition donnée prend en charge les emplacements, « non » dans le cas contraire. -
current-slot
. Renvoie le suffixe d'emplacement qui sera démarré à partir du suivant. -
slot-count
. Renvoie un entier représentant le nombre d'emplacements disponibles. Actuellement, deux emplacements sont pris en charge, cette valeur est donc2
. -
slot-successful:<slot-suffix>
. Renvoie "oui" si le slot donné a été marqué comme ayant démarré avec succès, "non" sinon. -
slot-unbootable:<slot-suffix>
. Renvoie "oui" si l'emplacement donné est marqué comme non amorçable, "non" sinon. -
slot-retry-count
. Nombre de tentatives restantes pour tenter de démarrer l'emplacement donné.
Pour afficher toutes les variables, exécutez fastboot getvar all
.
Génération de packages OTA
Les outils du package OTA suivent les mêmes commandes que les commandes pour les périphériques non-A/B. Le fichier target_files.zip
doit être généré en définissant les variables de construction pour la cible A/B. Les outils de package OTA identifient et génèrent automatiquement des packages au format du programme de mise à jour A/B.
Exemples:
- Pour générer un OTA complet :
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip
- Pour générer un OTA incrémentiel :
./build/make/tools/releasetools/ota_from_target_files \ -i PREVIOUS-tardis-target_files.zip \ dist_output/tardis-target_files.zip \ incremental_ota_update.zip
Configuration des partitions
Le update_engine
de mise à jour peut mettre à jour n'importe quelle paire de partitions A/B définies sur le même disque. Une paire de partitions a un préfixe commun (tel que system
ou boot
) et un suffixe par emplacement (tel que _a
). La liste des partitions pour lesquelles le générateur de payload définit une mise à jour est configurée par la variable make AB_OTA_PARTITIONS
.
Par exemple, si une paire de partitions bootloader_a
et booloader_b
sont incluses ( _a
et _b
sont les suffixes d'emplacement), vous pouvez mettre à jour ces partitions en spécifiant ce qui suit sur la configuration du produit ou de la carte :
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
Toutes les partitions mises à jour par update_engine
ne doivent pas être modifiées par le reste du système. Pendant les mises à jour incrémentielles ou delta , les données binaires de l'emplacement actuel sont utilisées pour générer les données dans le nouvel emplacement. Toute modification peut entraîner l'échec de la vérification des nouvelles données d'emplacement pendant le processus de mise à jour, et donc l'échec de la mise à jour.
Configuration de la post-installation
Vous pouvez configurer l'étape de post-installation différemment pour chaque partition mise à jour à l'aide d'un ensemble de paires clé-valeur. Pour exécuter un programme situé dans /system/usr/bin/postinst
dans une nouvelle image, spécifiez le chemin relatif à la racine du système de fichiers dans la partition système.
Par exemple, usr/bin/postinst
est system/usr/bin/postinst
(si vous n'utilisez pas de disque RAM). De plus, spécifiez le type de système de fichiers à transmettre à l'appel système mount(2)
. Ajoutez les éléments suivants aux fichiers .mk
du produit ou de l'appareil (le cas échéant) :
AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=usr/bin/postinst \ FILESYSTEM_TYPE_system=ext4
Compilation
Pour des raisons de sécurité, system_server
ne peut pas utiliser la compilation juste-à-temps (JIT) . Cela signifie que vous devez compiler à l'avance les fichiers odex pour system_server
et ses dépendances au minimum ; tout le reste est facultatif.
Pour compiler des applications en arrière-plan, vous devez ajouter les éléments suivants à la configuration de l'appareil du produit (dans le fichier device.mk du produit) :
- Incluez les composants natifs dans la construction pour vous assurer que le script de compilation et les fichiers binaires sont compilés et inclus dans l'image système.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
- Connectez le script de compilation à
update_engine
de sorte qu'il s'exécute en tant qu'étape de post-installation.# A/B OTA dexopt update_engine hookup AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=system/bin/otapreopt_script \ FILESYSTEM_TYPE_system=ext4 \ POSTINSTALL_OPTIONAL_system=true
Pour obtenir de l'aide sur l'installation des fichiers préoptés dans la seconde partition système inutilisée, reportez-vous à la section Première installation au démarrage des fichiers DEX_PREOPT .