Implémenter les mises à jour A/B

Les OEM et les fournisseurs de SoC qui souhaitent mettre en œuvre des mises à jour de système A/B doivent s'assurer que leur bootloader implémente le HAL boot_control et transmet les paramètres corrects au noyau.

Implémenter la commande HAL de contrôle de démarrage

Les bootloaders compatibles A/B doivent implémenter le HAL boot_control à hardware/libhardware/include/hardware/boot_control.h Vous pouvez tester les implémentations à l'aide du system/extras/bootctl utilitaire et system/extras/tests/bootloader/

Vous devez également implémenter la machine à états ci-dessous:

Figure 1 : Machine à états du bootloader

Configurer le noyau

Pour implémenter les mises à jour du système A/B:

  1. Choisissez la série de correctifs de noyau suivante (si nécessaire): <ph type="x-smartling-placeholder">
  2. Assurez-vous que les arguments de 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>"
    ... où la valeur <public-key-id> correspond à l'ID de la clé publique utilisée pour la signature de la table de vérification (pour en savoir plus, consultez dm-verity).
  3. Ajoutez le certificat .X509 contenant la clé publique au trousseau de clés du système: <ph type="x-smartling-placeholder">
      </ph>
    1. Copiez le certificat .X509 au format .der à la racine de kernel. Si le certificat .X509 est au format .pem, utilisez la commande openssl suivante pour effectuer la conversion Format .pem à .der:
      openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
    2. Créez le zImage pour inclure le certificat dans le trousseau système. Pour effectuer la validation,cochez l'entrée procfs (nécessite KEYS_CONFIG_DEBUG_PROC_KEYS à activer):
      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 du certificat .X509 indique la présence de la clé publique dans le trousseau de clés système (le texte mis en surbrillance indique l'ID de clé publique).
    3. Remplacez l'espace par # et transmettez-le en tant que <public-key-id> dans la ligne de commande du noyau. Par exemple, transmettez Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f à la place de <public-key-id>

Définir des variables de compilation

Les bootloaders compatibles A/B doivent répondre aux critères de variable de compilation suivants:

Doit être défini pour la cible A/B
  • AB_OTA_UPDATER := true

  • AB_OTA_PARTITIONS := \   boot \
      system \
      vendor
    et autres partitions mises à jour via update_engine (radio, bootloader, etc.)
  • PRODUCT_PACKAGES += \
      update_engine \
      update_verifier
Pour obtenir un exemple, consultez /device/google/marlin/+/android-7.1.0_r1/device-common.mk Vous pouvez éventuellement effectuer l'étape dex2oat post-installation (mais avant le redémarrage) décrite dans Compilation :
Fortement recommandé pour l'objectif A/B
  • Définir TARGET_NO_RECOVERY := true
  • Définir BOARD_USES_RECOVERY_AS_BOOT := true
  • Ne pas définir BOARD_RECOVERYIMAGE_PARTITION_SIZE
Impossible de définir pour la cible A/B
  • BOARD_CACHEIMAGE_PARTITION_SIZE
  • BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
Facultatif pour les versions de débogage PRODUCT_PACKAGES_DEBUG += update_engine_client

Définir des partitions (emplacements)

Les appareils A/B n'ont pas besoin d'une partition de récupération ni 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 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 était utilisée pour stocker les packages OTA téléchargés et pour cache temporairement des blocages pendant l'application des mises à jour. Il n'existait aucun moyen efficace de dimensionner le cache. partition: la taille requise pour les mises à jour que vous vouliez appliquer. Le pire serait une partition de cache aussi grande que l'image système. Avec les mises à jour A/B, il n'est pas nécessaire pour 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'intégralité du package OTA avant de l'appliquer.

Récupération

Le disque RAM de récupération est désormais contenu dans le fichier boot.img. Lorsque vous entrez dans la récupération, le bootloader ne peut pas placer 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. A/B les mises à jour sont appliquées par update_engine s'exécutant dans l'image système standard démarrée. Il existe toujours un mode de récupération utilisé pour effectuer le rétablissement de la configuration d'usine et le téléchargement indépendant de la mise à jour. packages (d’où vient le nom « recovery »). Code et données du mode Recovery est stocké dans la partition de démarrage ordinaire dans un ramdisk. pour démarrer l'image système, le bootloader indique au noyau d’ignorer ramdisk (sinon, l’appareil démarre . Le mode de récupération est petit (et une grande partie était déjà sur la partition de démarrage), donc le démarrage partition n'augmente pas en taille.

fstab

L'argument slotselect doit se trouver sur la ligne de l'instruction A/B-ed. des partitions. 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. Partitionnez plutôt vendor_a ou vendor_b sera sélectionné et installé sur le point d'installation /vendor.

Arguments d'emplacement du kernel

Le suffixe d'emplacement actuel doit être transmis via un nœud d'arborescence d'appareils spécifique (/firmware/android/slot_suffix) ou via la Ligne de commande du noyau androidboot.slot_suffix ou argument bootconfig.

Par défaut, fastboot flashe l'emplacement actuel sur un appareil A/B. Si le package de mise à jour contient les images de l'autre emplacement non actuel, fastboot les flashe également. Les options disponibles incluent:

  • --slot SLOT. Ignorez le comportement par défaut et invite fastboot à flasher l'emplacement transmis en tant que un argument.
  • --set-active [SLOT]. Définissez l'emplacement comme actif. Si aucun argument facultatif est spécifiée, l'emplacement actuel est défini comme actif.
  • fastboot --help En savoir plus sur les commandes

Si le bootloader implémente fastboot, il devrait être compatible avec la commande set_active <slot> qui définit l'emplacement actif actuel sur l'emplacement donné (ce doit également effacer l'indicateur d'impossibilité de démarrer l'emplacement et rétablir le nombre de nouvelles tentatives par défaut. ). Le bootloader doit également être compatible avec les variables suivantes:

  • has-slot:<partition-base-name-without-suffix>. Affiche "yes" si la valeur prend en charge les emplacements, "no" dans le cas contraire.
  • current-slot Renvoie le suffixe d'emplacement qui démarrera à partir du prochain démarrage.
  • slot-count. Renvoie un nombre entier représentant le nombre d'emplacements disponibles. Actuellement, deux emplacements sont acceptés. Cette valeur est donc 2.
  • slot-successful:<slot-suffix>. Affiche "yes" (oui) si l'espace publicitaire marqué comme étant en cours de démarrage, « non » sinon.
  • slot-unbootable:<slot-suffix>. Affiche "yes" si l'espace publicitaire donné est marqué comme non amorçable, "no" sinon.
  • slot-retry-count:<slot-suffix>. Nombre de tentatives restantes démarrer l'emplacement donné.

Pour afficher toutes les variables, exécutez la commande suivante : fastboot getvar all

Générer des packages OTA

Les outils de package OTA suivent les mêmes commandes que pour les appareils non-A/B. Le fichier target_files.zip doit être généré par en définissant les variables de compilation pour la cible A/B. Les outils de package OTA identifient automatiquement et générer des packages au format pour le programme de mise à jour A/B.

Exemples :

  • Pour générer une OTA complète:
    ./build/make/tools/releasetools/ota_from_target_files \
        dist_output/tardis-target_files.zip \
        ota_update.zip
    
  • Pour générer une OTA incrémentielle:
    ./build/make/tools/releasetools/ota_from_target_files \
        -i PREVIOUS-tardis-target_files.zip \
        dist_output/tardis-target_files.zip \
        incremental_ota_update.zip
    

Configurer des partitions

update_engine peut mettre à jour n'importe quelle paire de partitions A/B définies sur le même disque. Une paire de partitions possède un préfixe commun (par exemple, system ou boot) et un suffixe par emplacement (tel que _a). La liste des partitions pour lesquelles la charge utile Le générateur définit qu'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 inclus (_a et _b sont l'emplacement ), vous pouvez mettre à jour ces partitions en spécifiant ce qui suit sur le produit ou le tableau de bord configuration:

AB_OTA_PARTITIONS := \
  boot \
  system \
  bootloader

Toutes les partitions mises à jour par update_engine ne doivent pas être modifiées par le reste du du système d'exploitation. Lors des mises à jour incrémentielles ou delta, les données binaires de l'emplacement actuel sont pour générer les données du nouvel emplacement. Toute modification peut entraîner la échouent lors du processus de mise à jour et, par conséquent, échouent à la mise à jour.

Configurer la postinstallation

Vous pouvez configurer l'étape post-installation différemment pour chaque partition mise à jour à l'aide d'un ensemble de de paires clé-valeur. Pour exécuter un programme situé dans /system/usr/bin/postinst dans une nouvelle , spécifiez le chemin d'accès par rapport à la racine du système de fichiers dans la partition système.

Par exemple, usr/bin/postinst est system/usr/bin/postinst (si ce n'est à l'aide d'un disque RAM). De plus, spécifiez le type de système de fichiers à transmettre au Appel système mount(2). Ajoutez les éléments suivants au produit ou à l'appareil .mk fichiers (le cas échéant):

AB_OTA_POSTINSTALL_CONFIG += \
  RUN_POSTINSTALL_system=true \
  POSTINSTALL_PATH_system=usr/bin/postinst \
  FILESYSTEM_TYPE_system=ext4

Compiler des applications

Les applications peuvent être compilées en arrière-plan avant le redémarrage avec la nouvelle image système. Pour compiler en arrière-plan, ajoutez ce qui suit à la configuration de l'appareil du produit (dans les device.mk du produit):

  1. Incluez les composants natifs dans la compilation pour vous assurer que le script de compilation et les binaires compilé et inclus dans l'image système.
      # A/B OTA dexopt package
      PRODUCT_PACKAGES += otapreopt_script
    
  2. Connectez le script de compilation à update_engine de sorte qu'il s'exécute en tant que l'étape 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 concernant l'installation des fichiers prédéfinis dans la deuxième partition système inutilisée, consultez Première installation des fichiers DEX_PREOPT.