Google s'est engagé à promouvoir l'équité raciale pour les communautés noires. Regarde comment.
Cette page a été traduite par l'API Cloud Translation.
Switch to English

Implémentation des mises à jour A / B

Les OEM et les fournisseurs de SoC qui souhaitent implémenter des mises à jour système A / B doivent s'assurer que leur chargeur de démarrage implémente la HAL boot_control 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 la HAL boot_control dans hardware/libhardware/include/hardware/boot_control.h . Vous pouvez tester les implémentations en utilisant l'utilitaire system/extras/bootctl et system/extras/tests/bootloader/ .

Vous devez également implémenter la machine d'état ci-dessous:

Figure 1. Machine d'état du chargeur de démarrage

Configurer le noyau

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

  1. Cherrypick la série de correctifs de noyau suivante (si nécessaire):
  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> est l'ID de la clé publique utilisée pour vérifier la signature de la table de vérité (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 .der format .der à la racine du répertoire du kernel . Si le certificat .X509 est formaté en tant que fichier .pem , utilisez la commande openssl suivante pour convertir du format .pem au format .der :
      openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
    2. Créez la zImage pour inclure le certificat dans le trousseau de clés système. Pour vérifier, vérifiez l'entrée procfs (nécessite l' KEYS_CONFIG_DEBUG_PROC_KEYS de KEYS_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 système (la surbrillance indique l'ID de clé publique).
    3. Remplacez l'espace par # et transmettez-le comme <public-key-id> dans la ligne de commande du noyau. Par exemple, passez 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 définir 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 un exemple, reportez-vous à /device/google/marlin/+/android-7.1.0_r1/device-common.mk . Vous pouvez éventuellement effectuer l'étape de post-installation (mais pré-redémarrage) dex2oat décrite dans Compilation .
Fortement recommandé pour la cible A / B
  • Définir TARGET_NO_RECOVERY := true
  • Définir BOARD_USES_RECOVERY_AS_BOOT := true
  • Ne définissez pas 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éfinition des partitions (slots)

Les périphériques 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 é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 avait jamais de bon moyen 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 cacher 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 le package OTA complet 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 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. 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 pour le mode de récupération sont stockés dans la partition de démarrage normale dans un disque RAM; 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

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 de l'emplacement du noyau

Le suffixe d'emplacement actuel doit être transmis soit via un nœud d'arborescence de périphériques (DT) spécifique ( /firmware/android/slot_suffix ) soit via l'argument de ligne de commande androidboot.slot_suffix .

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 demandez à fastboot de faire clignoter l'emplacement qui est passé 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 fastboot, 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 de non amorçage 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 «yes» si la partition donnée prend en charge les slots, «no» dans le cas contraire.
  • current-slot . Renvoie le suffixe du slot qui sera démarré à partir de la prochaine.
  • slot-count . Renvoie un entier représentant le nombre d'emplacements disponibles. Actuellement, deux emplacements sont pris en charge, cette valeur est donc 2 .
  • slot-successful:<slot-suffix> . Renvoie "yes" si le slot donné a été marqué comme démarrant avec succès, "no" dans le cas contraire.
  • slot-unbootable:<slot-suffix> . Renvoie «yes» si l'emplacement donné est marqué comme non amorçable, «no» dans le cas contraire.
  • slot-retry-count . Nombre de tentatives restantes pour tenter de démarrer le slot donné.

Pour afficher toutes les variables, exécutez fastboot getvar all .

Générer des 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 les 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
    

Configurer les partitions

update_engine peut mettre à jour n'importe quelle paire de partitions A / B définies dans 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 charge utile 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 les éléments suivants 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. Lors des 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 données du nouvel emplacement pendant le processus de mise à jour et, par conséquent, 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). En outre, 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 du périphérique (le cas échéant):

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

Compiler

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 system_server 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 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 pour qu'il s'exécute 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 obtenir de l'aide sur l'installation des fichiers préoptés dans la deuxième partition système inutilisée, reportez-vous à la section Première installation de démarrage des fichiers DEX_PREOPT .