Mise en page des partitions

Dans Android 10, le système de fichiers racine n'est plus inclus dans ramdisk.img et est fusionné dans system.img (c'est-à-dire que system.img est toujours créé comme si BOARD_BUILD_SYSTEM_ROOT_IMAGE était défini). Appareils avec Android 10 préinstallé:

  • Utilisez une mise en page de partition système en tant que racine (appliquée automatiquement par la compilation, sans option permettant de modifier le comportement).
  • Vous devez utiliser un ramdisk, qui est obligatoire pour dm-linear.
  • Vous devez définir BOARD_BUILD_SYSTEM_ROOT_IMAGE sur false. Ce paramètre ne sert qu'à différencier les appareils qui utilisent un ramdisk et ceux qui n'en utilisent pas (et qui installent directement system.img).

La signification d'une configuration système en tant que racine diffère entre Android 9 et Android 10. Dans une configuration système en tant que racine Android 9, BOARD_BUILD_SYSTEM_ROOT_IMAGE est défini sur true, ce qui force la compilation à fusionner le système de fichiers racine dans system.img, puis à installer system.img en tant que système de fichiers racine (rootfs). Cette configuration est obligatoire pour les appareils lancés avec Android 9, mais facultative pour les appareils qui passent à Android 9 et pour ceux qui exécutent des versions antérieures d'Android. Dans une configuration système en tant que racine Android 10, le build fusionne toujours $TARGET_SYSTEM_OUT et $TARGET_ROOT_OUT dans system.img. Cette configuration correspond au comportement par défaut de tous les appareils exécutant Android 10.

Android 10 apporte d'autres modifications pour prendre en charge les partitions dynamiques, un système de partitionnement de l'espace utilisateur qui permet aux mises à jour OTA de créer, redimensionner ou détruire des partitions. Dans le cadre de ce changement, le kernel Linux ne peut plus monter la partition système logique sur les appareils exécutant Android 10. Cette opération est donc gérée par l'initialisation de la première étape.

Les sections suivantes décrivent les exigences du système en tant que racine pour les mises à jour OTA du système uniquement, et fournissent des conseils pour mettre à jour les appareils afin d'utiliser le système en tant que racine (y compris les modifications de la mise en page des partitions et les exigences du noyau dm-verity). Pour en savoir plus sur les modifications apportées au ramdisk, consultez la section Partitions de ramdisk.

À propos des mises à jour OTA système uniquement

Les OTA système uniquement, qui permettent aux versions Android de mettre à jour system.img et product.img sans modifier d'autres partitions, nécessitent une mise en page de partition système en tant que racine. Tous les appareils équipés d'Android 10 doivent utiliser une mise en page de partition système en tant que racine pour activer les mises à jour OTA système uniquement.

  • Les appareils A/B, qui montent la partition system en tant que rootfs, utilisent déjà le système en tant que root et ne nécessitent aucune modification pour prendre en charge les OTA du système.
  • Les appareils autres qu'A/B, qui installent la partition system à /system, doivent être mis à jour pour utiliser une mise en page de partition système en tant que racine afin de prendre en charge les mises à jour OTA du système.

Pour en savoir plus sur les appareils A/B et non A/B, consultez Mises à jour système A/B (fluides).

Utiliser la superposition du fournisseur (<=AOSP 14)

La superposition du fournisseur vous permet de superposer des modifications à la partition vendor au démarrage de l'appareil. Une superposition de fournisseur est un ensemble de modules de fournisseur dans la partition product qui sont superposés à la partition vendor au démarrage de l'appareil, en remplaçant et en ajoutant aux modules existants.

Lorsque l'appareil démarre, le processus init termine le montage de la première étape et lit les propriétés par défaut. Il recherche ensuite /product/vendor_overlay/<target_vendor_version> et monte chaque sous-répertoire sur son répertoire de partition vendor correspondant, si les conditions suivantes sont remplies:

  • /vendor/<overlay_dir> existe.
  • /product/vendor_overlay/<target_vendor_version>/<overlay_dir> possède le même contexte de fichier que /vendor/<overlay_dir>.
  • init est autorisé à se monter sur le contexte de fichier de /vendor/<overlay_dir>.

Implémenter la superposition du fournisseur

Installez les fichiers de superposition du fournisseur dans /product/vendor_overlay/<target_vendor_version>. Ces fichiers se superposent à la partition vendor au démarrage de l'appareil, remplaçant les fichiers du même nom et ajoutant de nouveaux fichiers. La superposition du fournisseur ne peut pas supprimer de fichiers de la partition vendor.

Les fichiers de superposition du fournisseur doivent avoir le même contexte de fichier que les fichiers cibles qu'ils remplacent dans la partition vendor. Par défaut, les fichiers du répertoire /product/vendor_overlay/<target_vendor_version> ont le contexte vendor_file. Si des différences de contexte de fichier existent entre les fichiers de superposition du fournisseur et les fichiers qu'ils remplacent, spécifiez-les dans la règle de sécurité spécifique à l'appareil. Le contexte de fichier est défini au niveau du répertoire. Si le contexte de fichier d'un répertoire de superposition du fournisseur ne correspond pas au répertoire cible et que le contexte de fichier approprié n'est pas spécifié dans la stratégie de sécurité spécifique à l'appareil, ce répertoire de superposition du fournisseur n'est pas superposé au répertoire cible.

Pour utiliser la superposition du fournisseur, le noyau doit activer OverlayFS en définissant CONFIG_OVERLAY_FS=y. En outre, le noyau doit être fusionné à partir du noyau commun 4.4 ou version ultérieure, ou corrigé avec "overlayfs: override_creds=off option bypass creator_cred".

Exemple d'implémentation d'une superposition de fournisseur

Cette procédure montre comment implémenter une superposition de fournisseur qui recouvre les répertoires /vendor/lib/*, /vendor/etc/* et /vendor/app/*.

  1. Ajoutez des fichiers de fournisseurs prédéfinis dans device/<vendor>/<target>/vendor_overlay/<target_vendor_version>/:

    device/google/device/vendor_overlay/28/lib/libfoo.so
    device/google/device/vendor_overlay/28/lib/libbar.so
    device/google/device/vendor_overlay/28/etc/baz.xml
    device/google/device/vendor_overlay/28/app/qux.apk
  2. Installez les fichiers de fournisseurs prédéfinis dans product/vendor_overlay dans device/google/device/device.mk:

    PRODUCT_COPY_FILES += \
        $(call find-copy-subdir-files,*,device/google/device/vendor_overlay,$(TARGET_COPY_OUT_PRODUCT)/vendor_overlay)
  3. Définissez des contextes de fichier si les fichiers de partition vendor cibles ont des contextes autres que vendor_file. Comme /vendor/lib/* utilise le contexte vendor_file, cet exemple n'inclut pas ce répertoire.

    Ajoutez les éléments suivants à device/google/device-sepolicy/private/file_contexts:

    /(product|system/product)/vendor_overlay/[0-9]+/etc(/.*)?   u:object_r:vendor_configs_file:s0
    /(product|system/product)/vendor_overlay/[0-9]+/app(/.*)?   u:object_r:vendor_app_file:s0
  4. Autorisez le processus init à installer la superposition du fournisseur sur des contextes de fichiers autres que vendor_file. Étant donné que le processus init est déjà autorisé à se monter sur le contexte vendor_file, cet exemple ne définit pas la stratégie pour vendor_file.

    Ajoutez les éléments suivants à device/google/device-sepolicy/public/init.te:

    allow init vendor_configs_file:dir mounton;
    allow init vendor_app_file:dir mounton;

Valider la superposition du fournisseur

Pour valider la configuration de superposition du fournisseur, ajoutez des fichiers dans /product/vendor_overlay/<target_vendor_version>/<overlay_dir> et vérifiez s'ils sont superposés aux fichiers de /vendor/<overlay_dir>.

Pour les builds userdebug, un module de test est disponible pour Atest:

$ atest -v fs_mgr_vendor_overlay_test

Mise à jour vers system-as-root

Pour mettre à jour les appareils autres qu'A/B afin qu'ils utilisent le système en tant que racine, vous devez mettre à jour le schéma de partitionnement pour boot.img et system.img, configurer dm-verity et supprimer toutes les dépendances de démarrage sur les dossiers racine spécifiques à l'appareil.

Mettre à jour les partitions

Contrairement aux appareils A/B qui réutilisent /boot comme partition de restauration, les appareils non A/B doivent maintenir la partition /recovery distincte, car ils ne disposent pas de la partition de l'emplacement de remplacement (par exemple, de boot_a à boot_b). Si /recovery est supprimé sur un appareil non A/B et rendu semblable au schéma A/B, le mode de récupération risque de se briser en cas d'échec de la mise à jour de la partition /boot. Pour cette raison, la partition /recovery doit être une partition distincte de /boot pour les appareils autres que A/B, ce qui implique que l'image de récupération continue d'être mise à jour de manière différée (c'est-à-dire comme sur les appareils équipés d'Android 8.1.0 ou version antérieure).

Le tableau suivant présente les différences de partitionnement d'image pour les appareils autres qu'A/B avant et après Android 9.

Image Ramdisk (avant la version 9) System-as-root (après la version 9)
boot.img Contient un noyau et un ramdisk.img:
ramdisk.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/ (mount point)
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
Ne contient qu'un noyau de démarrage normal.
recovery.img Contient un noyau de récupération et un ramdisk.img de récupération.
system.img Elle contient les éléments suivants:
system.img
  -/
    - bin/
    - etc
    - vendor -> /vendor
    - ...
Contient le contenu fusionné des system.img et ramdisk.img d'origine:
system.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/
      - bin/
      - etc/
      - vendor -> /vendor
      - ...
    - vendor/ (mount point)
    - odm/ (mount point)
    ...

Les partitions elles-mêmes ne changent pas. Le ramdisk et le système en tant que racine utilisent le schéma de partitionnement suivant:

  • /boot
  • /system
  • /system
  • /recovery
  • /vendor, etc.

Configurer dm-verity

Dans le système en tant que racine, le noyau doit installer system.img sous / (point d'installation) avec dm-verity. AOSP est compatible avec les implémentations dm-verity suivantes pour system.img.

vboot 1.0

Pour vboot 1.0, le noyau doit analyser les métadonnées spécifiques à Android sur /system, puis les convertir en paramètres dm-verity pour configurer dm-verity (nécessite ces correctifs du noyau). L'exemple suivant montre les paramètres liés à dm-verity pour system-as-root dans la ligne de commande du kernel:

ro root=/dev/dm-0 rootwait skip_initramfs init=/init
dm="system none ro,0 1 android-verity /dev/sda34"
veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f

vboot 2.0

Pour vboot 2.0 (AVB), le bootloader doit intégrer external/avb/libavb, qui analyse ensuite le descripteur de hachage pour /system, le convertit en paramètres dm-verity, puis transmet les paramètres au noyau via la ligne de commande du noyau. (Les descripteurs de l'arborescence de hachage de /system peuvent se trouver sur /vbmeta ou sur /system lui-même.)

vboot 2.0 nécessite les correctifs de kernel suivants:

L'exemple suivant montre les paramètres liés à dm-verity pour system-as-root dans la ligne de commande du kernel:

ro root=/dev/dm-0 rootwait  skip_initramfs init=/init

dm="1 vroot none ro 1,0 5159992 verity 1
PARTUUID=00000016-0000-0000-0000-000000000000
PARTUUID=00000016-0000-0000-0000-000000000000 4096 4096 644999 644999
sha1 d80b4a8be3b58a8ab86fad1b498640892d4843a2
8d08feed2f55c418fb63447fec0d32b1b107e42c 10 restart_on_corruption
ignore_zero_blocks use_fec_from_device
PARTUUID=00000016-0000-0000-0000-000000000000 fec_roots 2 fec_blocks
650080 fec_start 650080"

Utiliser des dossiers racine spécifiques à l'appareil

Avec le système en tant que racine, une fois la image système générique (GSI) flashée sur l'appareil (et avant d'exécuter les tests de la suite de tests du fournisseur), tous les dossiers racine spécifiques à l'appareil ajoutés avec BOARD_ROOT_EXTRA_FOLDERS sont supprimés, car l'intégralité du contenu du répertoire racine a été remplacée par la GSI système en tant que racine. La suppression de ces dossiers peut empêcher le démarrage de l'appareil si une dépendance existe sur les dossiers racine spécifiques à l'appareil (par exemple, s'ils sont utilisés comme points d'installation).

Pour éviter ce problème, n'utilisez pas BOARD_ROOT_EXTRA_FOLDERS pour ajouter des dossiers racine spécifiques à l'appareil. Si vous devez spécifier des points d'installation spécifiques à l'appareil, utilisez /mnt/vendor/<mount point> (ajouté dans ces listes de modifications). Ces points d'installation spécifiques au fournisseur peuvent être spécifiés directement dans l'arborescence d'appareils fstab (pour l'installation de premier niveau) et dans le fichier /vendor/etc/fstab.{ro.hardware} sans configuration supplémentaire (car fs_mgr les crée automatiquement sous /mnt/vendor/*).