Implémentation des mises à jour A/B

OEM et les fournisseurs SoC qui veulent mettre en œuvre les mises à jour du système A / B doivent assurer leur bootloader met en œuvre la boot_control HAL et transmet les paramètres corrects au niveau du noyau.

Implémentation du contrôle de démarrage HAL

A / B bootloader capable doit mettre en œuvre la boot_control HAL au hardware/libhardware/include/hardware/boot_control.h . Vous pouvez tester les implémentations utilisant le system/extras/bootctl utilitaire et system/extras/tests/bootloader/ .

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

Figure 1. Bootloader machine d'état

Configuration du noyau

Pour mettre en œuvre les mises à jour du système A/B :

  1. Choisissez la série de correctifs du noyau suivante (si nécessaire) :
  2. Assurez -vous des 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ù le <public-key-id> valeur est l'ID de la clé publique utilisée pour vérifier la signature de la table de Verity (pour plus de détails, voir dm-Verity ) .
  3. Ajoutez le certificat .X509 contenant la clé publique au trousseau de clés système :
    1. Copiez le certificat .X509 formaté dans le .der format à la racine du kernel répertoire. Si le certificat est .X509 formaté comme .pem fichier, utilisez ce qui suit openssl commande pour convertir de .pem à .der Format:
      openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
    2. Construire le zImage pour inclure le certificat dans le cadre du système de porte - clé. Pour vérifier, vérifier l' procfs entrée (nécessite KEYS_CONFIG_DEBUG_PROC_KEYS être activé):
      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
      inclusion réussie du certificat .X509 indique la présence de la clé publique dans le trousseau de clés du système (point culminant indique l'ID de clé publique).
    3. Remplacer l'espace avec # et le transmettre comme <public-key-id> dans la ligne de commande du noyau. Par exemple, passer Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f à la place de <public-key-id> .

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
  • AB_OTA_UPDATER := true
  • AB_OTA_PARTITIONS := \
    boot \
    system \
    vendor
    et d' autres partitions mises à jour par update_engine (radio, bootloader, etc.)
  • PRODUCT_PACKAGES += \
    update_engine \
    update_verifier
Pour un exemple, reportez - vous à /device/google/marlin/+/android-7.1.0_r1/device-common.mk . Vous pouvez éventuellement effectuer la post-installation (mais pré-redémarrage) dex2oat étape décrite dans Compiling .
Fortement recommandé pour la cible 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

Paramétrage des partitions (emplacements)

Les appareils A/B n'ont pas besoin de partition de récupération ou de 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 qui sont A / B-ed devraient être nommés comme suit (slots sont toujours nommés a , b , etc.): boot_a , boot_b , system_a , system_b , vendor_a , vendor_b .

Cacher

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 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 actuellement utilisée) 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 maintenant contenue dans le boot.img fichier. Lorsque vous allez dans la récupération, le bootloader ne peut pas mettre la skip_initramfs option 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 mises à jour / B sont appliquées par update_engine en cours d' exécution dans l'image régulière du système botté. 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 dit 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

Le slotselect argument doit être sur la ligne pour les partitions-ed B A /. Par exemple:

<path-to-block-device>/vendor  /vendor  ext4  ro
wait,verify=<path-to-block-device>/metadata,slotselect

Aucune partition doit être nommé vendor . Au lieu de cela, la partition vendor_a ou vendor_b seront sélectionnés et montés sur le /vendor point de montage.

Arguments d'emplacement de noyau

Le suffixe emplacement actuel doit être passé soit par un noeud (arbre de dispositif spécifique (DT) /firmware/android/slot_suffix ) ou par la androidboot.slot_suffix ligne de commande ou noyau 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 qui est transmis en tant qu'argument.
  • --set-active [ SLOT ] . Définissez l'emplacement comme actif. Si aucun argument facultatif n'est spécifié, le slot actuel est défini comme actif.
  • fastboot --help . Obtenez des détails sur les commandes.

Si le bootloader met en œuvre fastboot, il devrait soutenir la commande set_active <slot> qui définit la fente active en cours à la fente donnée (cela doit également effacer le drapeau pour cet emplacement amorçable et réinitialiser le nombre de nouvelles tentatives de 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 » sinon.
  • current-slot . Renvoie le suffixe d'emplacement qui sera démarré à partir du prochain.
  • slot-count . Renvoie un entier représentant le nombre d'emplacements disponibles. À l' heure actuelle, deux emplacements sont pris en charge si cette valeur est 2 .
  • slot-successful:<slot-suffix> . Renvoie « oui » si l'emplacement donné a été marqué comme un démarrage réussi, « non » dans le cas contraire.
  • 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 voir toutes les variables, exécutez fastboot getvar all .

Générer des packages OTA

Les outils de paquets OTA suivent les mêmes commandes que les commandes pour les dispositifs non-A / B. Le target_files.zip fichier 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 plein OTA:
    ./build/make/tools/releasetools/ota_from_target_files \
        dist_output/tardis-target_files.zip \
        ota_update.zip
    
  • Pour générer un différentiel OTA:
    ./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 peut mettre à jour une paire quelconque de partitions A / B définies dans le même disque. Une paire de partitions a un préfixe commun (tel que le system ou boot ) et le suffixe par emplacement (comme _a ). La liste des partitions pour lequel le générateur de charge utile définit une mise à jour est configuré par le AB_OTA_PARTITIONS faire variable.

Par exemple, si une paire de partitions bootloader_a et booloader_b sont inclus ( _a et _b sont les suffixes à sous), vous pouvez mettre à jour ces partitions en spécifiant ce qui suit sur la configuration du produit ou du conseil:

AB_OTA_PARTITIONS := \
  boot \
  system \
  bootloader

Toutes les partitions mises à jour par update_engine ne doivent pas être modifiés par le reste du système. Au cours de mises à jour incrémentielles ou delta, les données binaires de l'emplacement actuel est utilisé 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é à /system/usr/bin/postinst dans une nouvelle image, 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 (sinon l' aide d' un disque RAM). En outre, de spécifier le type de système de fichiers pour passer à la mount(2) appel système. Ajouter ce qui suit au produit ou dispositif .mk fichiers ( 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 juste à temps (JIT) compilation. Cela signifie que vous devez compiler en avance sur les fichiers de temps 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) :

  1. Incluez les composants natifs dans la construction pour vous assurer que le script de compilation et les binaires sont compilés et inclus dans l'image système.
      # A/B OTA dexopt package
      PRODUCT_PACKAGES += otapreopt_script
    
  2. Connectez le script de compilation à update_engine telle que fonctionne comme une é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 savoir comment installer les fichiers preopted dans la deuxième partition du système utilisé, reportez - vous à l' installation du premier démarrage de fichiers DEX_PREOPT .