Déplacement de fastboot vers l'espace utilisateur

Android 10 et versions ultérieures sont compatibles avec les partitions redimensionnables en déplaçant l'implémentation de fastboot du bootloader vers l'espace utilisateur. Ce déplacement permet de déplacer le code clignotant vers un emplacement commun gérable et testable, où seules les parties spécifiques au fournisseur de fastboot sont implémentées par une couche d'abstraction matérielle (HAL). De plus, Android 12 ou version ultérieure prend en charge le flash de ramdisks via une commande fastboot ajoutée.

Unifier Fastboot et la récupération

Comme le démarrage rapide et la récupération de l'espace utilisateur sont similaires, vous pouvez les fusionner en une seule partition ou un seul binaire. Cela offre des avantages tels que l'utilisation de moins d'espace, le fait d'avoir moins de partitions dans l'ensemble, et le partage de noyau et de bibliothèques avec fastboot et récupération.

Pour prendre en charge fastbootd, le bootloader doit implémenter une nouvelle commande de bloc de contrôle de démarrage (BCB) de boot-fastboot. Pour passer en mode fastbootd, le bootloader écrit boot-fastboot dans le champ de commande du message BCB et ne modifie pas le champ recovery du BCB (pour permettre le redémarrage des tâches de récupération interrompues). Les champs status, stage et reserved restent également inchangés. Le bootloader se charge et démarre dans l'image de récupération lorsque boot-fastboot s'affiche dans le champ de commande BCB. La récupération analyse ensuite le message BCB et passe en mode fastbootd.

Commandes ADB

Cette section décrit la commande adb pour intégrer fastbootd. La commande produit des résultats différents, selon qu'elle est exécutée par le système ou par une récupération.

Commande Description
reboot fastboot
  • Redémarrage dans fastbootd (système).
  • Saisit fastbootd directement, sans redémarrage (récupération).

Commandes Fastboot

Cette section décrit les commandes fastboot permettant d'intégrer fastbootd, y compris les nouvelles commandes permettant de flasher et de gérer des partitions logiques. Certaines commandes ont des résultats différents, selon qu'elles ont été exécutées par le bootloader ou par fastbootd.

Commande Description
reboot recovery
  • Redémarre en mode récupération (bootloader).
  • Démarre le processus de récupération directement, sans redémarrer l'application (fastbootd).
reboot fastboot Redémarrage dans fastbootd.
getvar is-userspace
  • Renvoie yes (fastbootd).
  • Renvoie no (bootloader).
getvar is-logical:<partition> Renvoie yes si la partition donnée est une partition logique, et no dans les autres cas. Les partitions logiques sont compatibles avec toutes les commandes listées ci-dessous.
getvar super-partition-name Renvoie le nom de la super-partition. Le nom inclut le suffixe d'emplacement actuel si la super-partition est une partition A/B (ce qui n'est généralement pas le cas).
create-logical-partition <partition> <size> Crée une partition logique avec le nom et la taille donnés. Le nom ne doit pas déjà exister en tant que partition logique.
delete-logical-partition <partition> Supprime la partition logique donnée (efface la partition).
resize-logical-partition <partition> <size> Redimensionne la partition logique à la nouvelle taille sans modifier son contenu. L'opération échoue si l'espace disponible est insuffisant pour effectuer le redimensionnement.
update-super <partition> Fusionne les modifications apportées aux métadonnées de la super-partition. Si une fusion n'est pas possible (par exemple, le format sur l'appareil est une version non compatible), cette commande échoue. Un paramètre wipe facultatif écrase les métadonnées de l'appareil au lieu d'effectuer une fusion.
flash <partition><filename> ] Écrit un fichier sur une partition Flash. L'appareil doit être déverrouillé.
erase <partition> Efface une partition (non nécessaire pour une effacement sécurisé). L'appareil doit être déverrouillé.
getvar <variable> | all Affiche une variable du bootloader ou toutes les variables. Si la variable n'existe pas, renvoie une erreur.
set_active <slot>

Définit l'emplacement de démarrage A/B donné sur active. Lors de la prochaine tentative de démarrage, le système démarre à partir de l'emplacement spécifié.

Pour la compatibilité avec les tests A/B, les emplacements sont des ensembles de partitions dupliqués qui peuvent être démarrés indépendamment. Les emplacements sont nommés a, b, etc., et se différencient par l'ajout des suffixes _a, _b, etc. au nom de la partition.

reboot Redémarre normalement l'appareil.
reboot-bootloader (ou reboot bootloader) Redémarre l'appareil dans le bootloader.
fastboot fetch vendor_boot <out.img>

À utiliser dans Android 12 ou version ultérieure pour permettre de flasher les ramdisks des fournisseurs.

Récupère la taille totale de la partition et la taille des fragments. Elle obtient les données de chaque fragment, puis les assemble dans <out.img>.

Pour en savoir plus, consultez fastboot fetch vendor_boot <out.img>.

fastboot flash vendor_boot:default <vendor-ramdisk.img>

À utiliser sur Android 12 ou version ultérieure pour permettre la mise en flash des ramdisks des fournisseurs.

Il s'agit d'une variante spéciale de la commande flash. Elle exécute une fonction d'image fetch vendor_boot, comme si fastboot fetch était appelé. La nouvelle image vendor_boot qu'elle clignote varie selon que la version de l'en-tête de démarrage est la version 3 ou la version 4.

Pour en savoir plus, consultez fastboot flash vendor_boot:default <vendor-ramdisk.img>.

fastboot flash vendor_boot:<foo> <vendor-ramdisk.img> Utilisez cette version sur Android 12 ou version ultérieure pour permettre la flashation des ramdisks des fournisseurs.

Récupère l'image vendor_boot. Renvoie une erreur si l'en-tête de démarrage du fournisseur est de version 3. Avec la version 4, il trouve le fragment ramdisk du fournisseur approprié (le cas échéant). Elle la remplace par l'image donnée, recalcule les tailles et les décalages, et clignote le nouveau vendor_boot image.

Pour en savoir plus, consultez fastboot flash vendor_boot:<foo> <vendor-ramdisk.img>

Fastboot et bootloader

Le bootloader flashe les partitions bootloader, radio et boot/recovery, après quoi l'appareil démarre en fastboot (espace utilisateur) et toutes les autres partitions sont flashées. Le bootloader doit être compatible avec les commandes suivantes.

Commande Description
download Télécharge l'image à flasher.
flash recovery <image>/ flash boot <image>/ flash bootloader <image>/ Flashe la partition recovery/boot et le bootloader.
reboot Redémarre l'appareil.
reboot fastboot Redémarre en mode Fastboot.
reboot recovery Redémarre avant la récupération.
getvar Récupère une variable de bootloader requise pour flasher l'image de récupération/de démarrage (par exemple, current-slot et max-download-size).
oem <command> Commande définie par l'OEM.

Partitions dynamiques

Le bootloader ne doit pas permettre le flash ou l'effacement des partitions dynamiques, et doit renvoyer une erreur en cas de tentative de ces opérations. Pour les appareils de partition dynamique réajustés, l'outil fastboot (et le bootloader) prend en charge un mode forcé pour flasher directement une partition dynamique en mode bootloader. Par exemple, si system est une partition dynamique sur l'appareil réaménagé, l'utilisation de la commande fastboot --force flash system permet au bootloader (au lieu de fastbootd) de flasher la partition.

Recharge hors mode

Si un appareil prend en charge la recharge hors mode ou démarre automatiquement dans un mode spécial lorsqu'il est alimenté, une implémentation de la commande fastboot oem off-mode-charge 0 doit contourner ces modes spéciaux, afin que l'appareil démarre comme si l'utilisateur avait appuyé sur le bouton Marche/Arrêt.

HAL OEM Fastboot

Pour remplacer complètement le bootloader Fastboot, il doit gérer toutes les commandes Fastboot existantes. Un grand nombre de ces commandes proviennent d'OEM et sont documentées, mais nécessitent une implémentation personnalisée. De nombreuses commandes spécifiques aux OEM ne sont pas documentées. Pour gérer de telles commandes, le HAL fastboot spécifie les commandes OEM requises. Les OEM peuvent également implémenter leurs propres commandes.

Voici la définition du HAL fastboot:

import IFastbootLogger;

/**
 * IFastboot interface implements vendor specific fastboot commands.
 */
interface IFastboot {
    /**
     * Returns a bool indicating whether the bootloader is enforcing verified
     * boot.
     *
     * @return verifiedBootState True if the bootloader is enforcing verified
     * boot and False otherwise.
     */
    isVerifiedBootEnabled() generates (bool verifiedBootState);

    /**
     * Returns a bool indicating the off-mode-charge setting. If off-mode
     * charging is enabled, the device autoboots into a special mode when
     * power is applied.
     *
     * @return offModeChargeState True if the setting is enabled and False if
     * not.
     */
    isOffModeChargeEnabled() generates (bool offModeChargeState);

    /**
     * Returns the minimum battery voltage required for flashing in mV.
     *
     * @return batteryVoltage Minimum battery voltage (in mV) required for
     * flashing to be successful.
     */
    getBatteryVoltageFlashingThreshold() generates (int32_t batteryVoltage);

    /**
     * Returns the file system type of the partition. This is only required for
     * physical partitions that need to be wiped and reformatted.
     *
     * @return type Can be ext4, f2fs or raw.
     * @return result SUCCESS if the operation is successful,
     * FAILURE_UNKNOWN if the partition is invalid or does not require
     * reformatting.
     */
    getPartitionType(string partitionName) generates (FileSystemType type, Result result);

    /**
     * Executes a fastboot OEM command.
     *
     * @param oemCmd The oem command that is passed to the fastboot HAL.
     * @response result Returns the status SUCCESS if the operation is
     * successful,
     * INVALID_ARGUMENT for bad arguments,
     * FAILURE_UNKNOWN for an invalid/unsupported command.
     */
    doOemCommand(string oemCmd) generates (Result result);

};

Activer fastbootd

Pour activer fastbootd sur un appareil:

  1. Ajoutez fastbootd à PRODUCT_PACKAGES dans device.mk: PRODUCT_PACKAGES += fastbootd.

  2. Assurez-vous que le HAL de démarrage rapide, le HAL de contrôle de démarrage et le HAL d'état sont empaquetés dans l'image de récupération.

  3. Ajoutez toutes les autorisations SEPolicy spécifiques à l'appareil requises par fastbootd. Par exemple, fastbootd nécessite un accès en écriture à une partition spécifique à l'appareil pour flasher cette partition. En outre, l'implémentation de la couche HAL fastboot peut également nécessiter des autorisations spécifiques à l'appareil.

Pour valider le démarrage rapide de l'espace utilisateur, exécutez la suite de test fournisseur (VTS).

Disques RAM du fournisseur Flash

Android 12 et les versions ultérieures permettent de flasher des ramdisks grâce à une commande fastboot supplémentaire qui extrait l'image vendor_boot complète d'un appareil. La commande invite l'outil Fastboot côté hôte à lire l'en-tête de démarrage du fournisseur, à réimager et à flasher la nouvelle image.

Pour extraire l'image vendor_boot complète, la commande fetch:vendor_boot a été ajoutée à la fois au protocole fastboot et à son implémentation fastbootd dans Android 12. Notez que fastbootd met en œuvre cela, mais que ce n'est peut-être pas le cas du bootloader lui-même. Les OEM peuvent ajouter la commande fetch:vendor_boot à la mise en œuvre du protocole du bootloader dans leur bootloader. Toutefois, si la commande n'est pas reconnue en mode bootloader, l'option flasher les ramdisks de fournisseurs individuels en mode bootloader n'est pas proposée par le fournisseur.

Modifications apportées au bootloader

Les commandes getvar:max-fetch-size et fetch:name sont implémentées dans fastbootd. Pour permettre le flashage des ramdisks des fournisseurs dans le bootloader, vous devez implémenter ces deux commandes.

Modifications en fastboot

getvar:max-fetch-size est semblable à max-download-size. Il spécifie la taille maximale que l'appareil peut envoyer dans une réponse DATA. Le pilote ne doit pas extraire une taille supérieure à cette valeur.

fetch:name[:offset[:size]] effectue une série de vérifications sur l'appareil. Si toutes les conditions suivantes sont remplies, la commande fetch:name[:offset[:size]] renvoie des données:

  • L'appareil exécute une version débogable.
  • L'appareil est déverrouillé (état de démarrage orange).
  • Le nom de la partition récupérée est vendor_boot.
  • La valeur size est comprise entre 0 < size <= max-fetch-size.

Lorsque ces éléments sont vérifiés, fetch:name[:offset[:size]] renvoie la taille de la partition et le décalage. Remarques :

  • fetch:name équivaut à fetch:name:0, ce qui équivaut à fetch:name:0:partition_size.
  • fetch:name:offset équivaut à fetch:name:offset:(partition_size - offset).

On obtient donc fetch:name[:offset[:size]] = fetch:name:offset:(partition_size - offset).

Lorsque offset ou partition_size (ou les deux) ne sont pas spécifiés, les valeurs par défaut sont utilisées. Ainsi, pour offset est 0, et size est la valeur calculée de partition_size - offset.

  • Décalage spécifié, taille non spécifiée: size = partition_size - offset
  • Aucune valeur spécifiée: valeurs par défaut utilisées dans les deux cas (size = partition_size - 0).

Par exemple, fetch:foo récupère la totalité de la partition foo avec un décalage de 0.

Modifications des pilotes

Des commandes ont été ajoutées à l'outil fastboot pour implémenter les modifications apportées au pilote. Chacune est liée à sa définition complète dans le tableau des commandes Fastboot.

  • fastboot fetch vendor_boot out.img

    • Elle appelle getvar max-fetch-size pour déterminer la taille des fragments.
    • Elle appelle getvar partition-size:vendor_boot[_a] pour déterminer la taille de la partition entière.
    • Elle appelle fastboot fetch vendor_boot[_a]:offset:size pour chaque fragment. (La taille des fragments est supérieure à vendor_boot, il n'y a donc normalement qu'un seul fragment.)
    • Associe les données à out.img.
  • fastboot flash vendor_boot:default vendor-ramdisk.img

    Il s'agit d'une variante spéciale de la commande flash. Elle récupère l'image vendor_boot, comme si fastboot fetch était appelé.

    • Si le démarrage du fournisseur est l'en-tête version 3, il effectue les opérations suivantes :
      • Remplace le ramdisk du fournisseur par l'image donnée.
      • Flashe la nouvelle image vendor_boot.
    • Si l'en-tête de démarrage du fournisseur est la version 4, il effectue les opérations suivantes :
      • Remplace l'ensemble du disque ramdisk du fournisseur par l'image donnée, de sorte que cette image devienne le seul fragment ramdisk du fournisseur dans l'image vendor_boot.
      • Il recalcule la taille et le décalage dans la table ramdisk du fournisseur.
      • Flashe la nouvelle image vendor_boot.
  • fastboot flash vendor_boot:foo vendor-ramdisk.img

    Récupère vendor_boot image, comme si fastboot fetch était appelé.

    • Si l'en-tête de démarrage du fournisseur correspond à la version 3, une erreur est renvoyée.
    • Si l'en-tête de démarrage du fournisseur correspond à la version 4, il effectue les opérations suivantes:

      • Recherche le fragment ramdisk du fournisseur nommé foo. S'il est introuvable ou s'il existe plusieurs correspondances, renvoie une erreur.
      • Remplace le fragment ramdisk du fournisseur par l'image donnée.
      • Il recalcule chaque taille et chaque décalage dans la table ramdisk du fournisseur.
      • Flashe la nouvelle image vendor_boot.

MKbootimg

Le nom default est réservé à l'attribution de noms aux fragments ramdisk du fournisseur dans Android 12 ou version ultérieure. Bien que la sémantique flash vendor_boot:default de fastboot reste la même, vous ne devez pas nommer vos fragments ramdisk default.

Modifications apportées à SELinux

Une modification a été apportée dans fastbootd.te pour permettre le flashage des ramdisks du fournisseur.