Fastboot in den Userspace verschieben

Android 10 und höher unterstützt die Größenänderung von Partitionen durch die Verlagerung der Fastboot-Implementierung vom Bootloader in den Userspace. Diese Verlagerung ermöglicht das Verschieben des Flash-Codes an einen wartbaren und testbaren gemeinsamen Speicherort, wobei nur die herstellerspezifischen Teile von Fastboot durch eine Hardware-Abstraktionsschicht (HAL) implementiert werden. Darüber hinaus unterstützt Android 12 und höher das Flashen von Ramdisks durch einen zusätzlichen Fastboot-Befehl.

Fastboot und Wiederherstellung vereinen

Da Fastboot und Recovery im Userspace ähnlich sind, können Sie sie in einer Partition oder Binärdatei zusammenführen. Dies bietet Vorteile wie weniger Platzbedarf, insgesamt weniger Partitionen und die gemeinsame Nutzung von Kernel und Bibliotheken durch Fastboot und Recovery.

Um fastbootd zu unterstützen, muss der Bootloader einen neuen Boot Control Block (BCB)-Befehl boot-fastboot implementieren. Um in den fastbootd Modus zu wechseln, schreibt der Bootloader boot-fastboot in das Befehlsfeld der BCB-Nachricht und lässt das recovery von BCB unverändert (um den Neustart unterbrochener Wiederherstellungsaufgaben zu ermöglichen). Die Felder status , stage “ und reserved bleiben ebenfalls unverändert. Der Bootloader lädt und bootet das Wiederherstellungsimage, wenn im BCB-Befehlsfeld boot-fastboot angezeigt wird. Anschließend analysiert die Wiederherstellung die BCB-Nachricht und wechselt in den fastbootd Modus.

ADB-Befehle

In diesem Abschnitt wird der Befehl adb zum Integrieren fastbootd beschrieben. Der Befehl hat unterschiedliche Ergebnisse, je nachdem, ob er vom System oder von der Wiederherstellung ausgeführt wird.

Befehl Beschreibung
reboot fastboot
  • Startet in fastbootd (System) neu.
  • Ruft fastbootd direkt auf, ohne einen Neustart (Wiederherstellung).

Fastboot-Befehle

In diesem Abschnitt werden die Fastboot-Befehle zur Integration fastbootd beschrieben, einschließlich neuer Befehle zum Flashen und Verwalten logischer Partitionen. Einige Befehle haben unterschiedliche Ergebnisse, je nachdem, ob sie vom Bootloader oder von fastbootd ausgeführt wurden.

Befehl Beschreibung
reboot recovery
  • Neustart in die Wiederherstellung (Bootloader).
  • Startet die Wiederherstellung direkt ohne Neustart ( fastbootd ).
reboot fastboot Startet in fastbootd neu.
getvar is-userspace
  • Gibt yes zurück ( fastbootd ).
  • Gibt no (Bootloader) zurück.
getvar is-logical: <partition> Gibt yes zurück, wenn die angegebene Partition eine logische Partition ist, andernfalls no . Logische Partitionen unterstützen alle unten aufgeführten Befehle.
getvar super-partition-name Gibt den Namen der Superpartition zurück. Der Name enthält das aktuelle Slot-Suffix, wenn es sich bei der Superpartition um eine A/B-Partition handelt (was normalerweise nicht der Fall ist).
create-logical-partition <partition> <size> Erstellt eine logische Partition mit dem angegebenen Namen und der angegebenen Größe. Der Name darf nicht bereits als logische Partition vorhanden sein.
delete-logical-partition <partition> Löscht die angegebene logische Partition (löscht effektiv die Partition).
resize-logical-partition <partition> <size> Ändert die Größe der logischen Partition auf die neue Größe, ohne ihren Inhalt zu ändern. Schlägt fehl, wenn nicht genügend Speicherplatz für die Größenänderung verfügbar ist.
update-super <partition> Führt Änderungen an den Metadaten der Superpartition zusammen. Wenn eine Zusammenführung nicht möglich ist (z. B. weil das Format auf dem Gerät eine nicht unterstützte Version ist), schlägt dieser Befehl fehl. Ein optionaler wipe überschreibt die Metadaten des Geräts, anstatt eine Zusammenführung durchzuführen.
flash <partition> [ <filename> ] Schreibt eine Datei in eine Flash-Partition. Das Gerät muss sich im entsperrten Zustand befinden.
erase <partition> Löscht eine Partition (keine sichere Löschfunktion erforderlich). Das Gerät muss sich im entsperrten Zustand befinden.
getvar <variable> | all Zeigt eine Bootloader-Variable oder alle Variablen an. Wenn die Variable nicht vorhanden ist, wird ein Fehler zurückgegeben.
set_active <slot>

Legt den angegebenen A/B-Boot-Slot als active . Beim nächsten Startversuch startet das System vom angegebenen Steckplatz.

Für die A/B-Unterstützung sind Slots duplizierte Partitionssätze, die unabhängig voneinander gebootet werden können. Slots werden a , b usw. bezeichnet und durch das Hinzufügen der Suffixe _a , _b usw. zum Partitionsnamen unterschieden.

reboot Startet das Gerät normal neu.
reboot-bootloader (oder reboot bootloader ) Startet das Gerät im Bootloader neu.
fastboot fetch vendor_boot <out.img>

Verwendung in Android 12 und höher , um das Flashen von Hersteller-Ramdisks zu unterstützen.

Ruft die gesamte Partitionsgröße und die Blockgröße ab. Ruft Daten für jeden Block ab und fügt die Daten dann zu <out.img> zusammen

Einzelheiten finden Sie unter fastboot fetch vendor_boot <out.img> .

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

Verwendung in Android 12 und höher, um das Flashen von Hersteller-Ramdisks zu unterstützen.

Dies ist eine spezielle Variante des Flash-Befehls. Es führt eine Funktion fetch vendor_boot Images aus, als ob fastboot fetch aufgerufen würde. Das neue vendor_boot -Image, das geflasht wird, hängt davon ab, ob die Boot-Header-Version Version 3 oder Version 4 ist.

Einzelheiten finden Sie unter fastboot flash vendor_boot:default <vendor-ramdisk.img> .

fastboot flash vendor_boot: <foo> <vendor-ramdisk.img> Verwendung in Android 12 und höher, um das Flashen von Hersteller-Ramdisks zu unterstützen.

Ruft das vendor_boot -Image ab. Gibt einen Fehler zurück, wenn der Boot-Header des Anbieters Version 3 ist. Wenn es sich um Version 4 handelt, wird das richtige Ramdisk-Fragment des Anbieters gefunden (sofern verfügbar). Es ersetzt dieses durch das angegebene Image, berechnet Größen und Offsets neu und flasht das neue vendor_boot image .

Einzelheiten finden Sie unter fastboot flash vendor_boot: <foo> <vendor-ramdisk.img>

Fastboot und Bootloader

Der Bootloader flasht die bootloader , radio und boot/recovery Partitionen, woraufhin das Gerät in Fastboot (Userspace) bootet und alle anderen Partitionen flasht. Der Bootloader sollte die folgenden Befehle unterstützen.

Befehl Beschreibung
download Lädt das Bild zum Flashen herunter.
flash recovery <image> / flash boot <image> / flash bootloader <image> / Flasht recovery/boot Partition und den Bootloader.
reboot Startet das Gerät neu.
reboot fastboot Neustart zum Fastboot.
reboot recovery Neustart zur Wiederherstellung.
getvar Ruft eine Bootloader-Variable ab, die zum Flashen des Wiederherstellungs-/Boot-Images erforderlich ist (z. B. current-slot und max-download-size ).
oem <command> Vom OEM definierter Befehl.

Dynamische Partitionen

Der Bootloader darf das Flashen oder Löschen dynamischer Partitionen nicht zulassen und muss einen Fehler zurückgeben, wenn diese Vorgänge versucht werden. Für nachgerüstete dynamische Partitionsgeräte unterstützt das Fastboot-Tool (und der Bootloader) einen Force-Modus, um eine dynamische Partition im Bootloader-Modus direkt zu flashen. Wenn es sich bei system beispielsweise um eine dynamische Partition auf dem nachgerüsteten Gerät handelt, ermöglicht die Verwendung des Systembefehls fastboot --force flash system dem Bootloader (anstelle von fastbootd ), die Partition zu flashen.

Laden im Off-Modus

Wenn ein Gerät das Laden im Aus-Modus unterstützt oder auf andere Weise beim Anlegen der Stromversorgung automatisch in einen speziellen Modus startet, muss eine Implementierung des Befehls fastboot oem off-mode-charge 0 diese speziellen Modi umgehen, sodass das Gerät so startet, als hätte der Benutzer gedrückt den Netzschalter.

Fastboot OEM HAL

Um den Bootloader Fastboot vollständig zu ersetzen, muss Fastboot alle vorhandenen Fastboot-Befehle verarbeiten. Viele dieser Befehle stammen von OEMs und sind dokumentiert, erfordern jedoch eine benutzerdefinierte Implementierung. Viele OEM-spezifische Befehle sind nicht dokumentiert. Um solche Befehle zu verarbeiten, gibt die Fastboot-HAL die erforderlichen OEM-Befehle an. OEMs können auch eigene Befehle implementieren.

Die Definition von Fastboot HAL lautet wie folgt:

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);

};

Fastbootd aktivieren

So aktivieren Sie fastbootd auf einem Gerät:

  1. Fügen Sie fastbootd zu PRODUCT_PACKAGES in device.mk hinzu: PRODUCT_PACKAGES += fastbootd .

  2. Stellen Sie sicher, dass die Fastboot-HAL, die Boot-Control-HAL und die Health-HAL als Teil des Wiederherstellungsimages gepackt sind.

  3. Fügen Sie alle gerätespezifischen SEPolicy-Berechtigungen hinzu, die für fastbootd erforderlich sind. fastbootd erfordert beispielsweise Schreibzugriff auf eine gerätespezifische Partition, um diese Partition zu flashen. Darüber hinaus sind für die Fastboot-HAL-Implementierung möglicherweise auch gerätespezifische Berechtigungen erforderlich.

Um den Userspace-Fastboot zu validieren, führen Sie die Vendor Test Suite (VTS) aus.

Flashende Hersteller-Ramdisks

Android 12 und höher bietet Unterstützung für das Flashen von Ramdisks mit einem zusätzlichen Fastboot-Befehl, der das vollständige vendor_boot Image von einem Gerät abruft. Der Befehl fordert das hostseitige Fastboot-Tool auf, den Boot-Header des Anbieters zu lesen, ein neues Image zu erstellen und das neue Image zu flashen.

Um das vollständige vendor_boot Image abzurufen, wurde der Befehl fetch:vendor_boot sowohl zum Fastboot-Protokoll als auch zur Fastbootd-Implementierung des Protokolls in Android 12 hinzugefügt. Beachten Sie, dass Fastbootd dies zwar implementiert , der Bootloader selbst jedoch möglicherweise nicht. OEMs können den Befehl fetch:vendor_boot zu ihrer Bootloader-Implementierung des Protokolls hinzufügen. Wenn der Befehl jedoch im Bootloader-Modus nicht erkannt wird, ist das Flashen einzelner Hersteller-Ramdisks im Bootloader-Modus keine vom Hersteller unterstützte Option.

Bootloader-Änderungen

Die Befehle getvar:max-fetch-size und fetch:name sind in fastbootd implementiert. Um das Flashen von Hersteller-Ramdisks im Bootloader zu unterstützen, müssen Sie diese beiden Befehle implementieren.

Fastbootd-Änderungen

getvar:max-fetch-size ähnelt max-download-size . Es gibt die maximale Größe an, die das Gerät in einer DATA-Antwort senden kann. Der Treiber darf keine größere Größe als diesen Wert abrufen.

fetch:name[:offset[:size]] führt eine Reihe von Überprüfungen auf dem Gerät durch. Wenn alle folgenden Aussagen zutreffen, gibt der Befehl fetch:name[:offset[:size]] Daten zurück:

  • Auf dem Gerät wird ein debuggbarer Build ausgeführt.
  • Das Gerät ist entsperrt (Bootstatus orange).
  • Der abgerufene Partitionsname ist vendor_boot .
  • Der size liegt im Bereich 0 < size <= max-fetch-size .

Wenn diese überprüft werden, gibt fetch:name[:offset[:size]] die Partitionsgröße und den Offset zurück. Beachte das Folgende:

  • fetch:name entspricht fetch:name:0 , was fetch:name:0:partition_size entspricht.
  • fetch:name:offset ist äquivalent zu fetch:name:offset:(partition_size - offset)

Deshalb fetch:name[:offset[:size]] = fetch:name:offset:(partition_size - offset)

Wenn offset oder partition_size (oder beide) nicht angegeben sind, werden die Standardwerte verwendet, die für offset 0 und für size den berechneten Wert von partition_size - offset betragen.

  • Offset angegeben, Größe nicht angegeben: size = partition_size - offset
  • Keines angegeben: Standardwerte werden für beide verwendet, size = partition_size – 0.

Beispielsweise ruft fetch:foo die gesamte foo Partition mit Offset 0 ab.

Fahrerwechsel

Dem Fastboot-Tool wurden Befehle hinzugefügt, um Treiberänderungen umzusetzen. Jeder ist mit seiner vollständigen Definition in der Tabelle der Fastboot-Befehle verknüpft.

  • fastboot fetch vendor_boot out.img

    • Ruft getvar max-fetch-size auf, um die Blockgröße zu bestimmen.
    • Ruft getvar partition-size:vendor_boot[_a] auf, um die Größe der gesamten Partition zu bestimmen.
    • Ruft fastboot fetch vendor_boot[_a]:offset:size für jeden Chunk auf. (Die Blockgröße ist größer als die vendor_boot Größe, daher gibt es normalerweise nur einen Block.)
    • Fügt die Daten zu out.img zusammen.
  • fastboot flash vendor_boot:default vendor-ramdisk.img

    Dies ist eine spezielle Variante des Flash-Befehls. Es ruft das vendor_boot Image ab, als ob fastboot fetch aufgerufen würde.

    • Wenn es sich bei dem Hersteller-Boot um Header- Version 3 handelt, geschieht Folgendes:
      • Ersetzt die Ramdisk des Anbieters durch das angegebene Image.
      • Flasht das neue vendor_boot -Image.
    • Wenn der Boot-Header des Herstellers Version 4 ist, geschieht Folgendes:
      • Ersetzt die gesamte Ramdisk des Anbieters durch das angegebene Image, sodass das angegebene Image das einzige Ramdisk-Fragment des Anbieters im vendor_boot Image wird.
      • Berechnet die Größe und den Offset in der Ramdisk-Tabelle des Anbieters neu.
      • Flasht das neue vendor_boot -Image.
  • fastboot flash vendor_boot:foo vendor-ramdisk.img

    Ruft vendor_boot image ab, als ob fastboot fetch aufgerufen würde.

    • Wenn der Boot-Header des Herstellers Version 3 ist, wird ein Fehler zurückgegeben.
    • Wenn der Boot-Header des Herstellers Version 4 ist, geschieht Folgendes:

      • Findet das Hersteller-Ramdisk-Fragment mit dem Namen foo . Wenn es nicht gefunden wird oder mehrere Übereinstimmungen vorliegen, wird ein Fehler zurückgegeben.
      • Ersetzt das Ramdisk-Fragment des Anbieters durch das angegebene Image.
      • Berechnet jede Größe und jeden Offset in der Ramdisk-Tabelle des Anbieters neu.
      • Flasht das neue vendor_boot -Image.

mkbootimg

Der default ist für die Benennung von Hersteller-Ramdisk-Fragmenten in Android 12 und höher reserviert. Während die Fastboot- flash vendor_boot:default -Semantik gleich bleibt, dürfen Sie Ihre Ramdisk-Fragmente nicht als default bezeichnen.

SELinux-Änderungen

In fastbootd.te wurde eine Änderung vorgenommen, um das Flashen von Hersteller-Ramdisks zu unterstützen.