Fastboot in den Userspace verschieben

Fastboot ist der Name eines Bootloader-Moduls und -Modus. Android 10 und höher unterstützt die Größenanpassung von Partitionen, indem die Fastboot-Implementierung vom Bootloader in den Nutzerbereich verlagert wird. Durch diese Verlagerung kann der Flash-Code an einen wartungsfreundlichen und testbaren gemeinsamen Ort verschoben werden. Nur die anbieterspezifischen Teile von Fastboot werden von einer Hardware-Abstraktionsschicht (Hardware Abstraction Layer, HAL) implementiert. Außerdem unterstützt Android 12 und höher das Flashen von Ramdisks über einen zusätzlichen Fastboot-Befehl.

Fastboot und Recovery zusammenführen

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

Fastbootd ist der Name eines Userspace-Daemons und -Modus. Zur Unterstützung von fastbootd muss der Bootloader einen neuen BCB-Befehl (Boot Control Block) von 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 Feld recovery des BCB unverändert, damit unterbrochene Wiederherstellungsaufgaben neu gestartet werden können. Die Felder status, stage und reserved bleiben ebenfalls unverändert. Der Bootloader lädt das Recovery-Image und startet es, wenn er boot-fastboot im BCB-Befehlsfeld sieht. Die Wiederherstellung analysiert dann die BCB-Nachricht und wechselt in den Modus fastbootd.

ADB-Befehle

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

Befehl Beschreibung
reboot fastboot
  • Neustart erfolgt in fastbootd (System).
  • Ruft fastbootd direkt ohne Neustart (Wiederherstellung) auf.

Fastboot-Befehle

In diesem Abschnitt werden die Fastboot-Befehle für die Integration von 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 erfolgt in den Wiederherstellungsmodus (Bootloader).
  • Das Gerät wechselt direkt in den Wiederherstellungsmodus, ohne neu zu starten (fastbootd).
reboot fastboot Neustart erfolgt in fastbootd.
getvar is-userspace
  • Gibt yes (fastbootd) zurück.
  • 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 die Superpartition eine A/B-Partition ist (was in der Regel 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 existieren.
delete-logical-partition <partition> Löscht die angegebene logische Partition (die Partition wird also gelöscht).
resize-logical-partition <partition> <size> Ändert die Größe der logischen Partition in die neue Größe, ohne ihren Inhalt zu ändern. Schlägt fehl, wenn nicht genügend Speicherplatz für die Durchführung der Größenänderung verfügbar ist.
flash <partition><filename> ] Schreibt eine Datei in eine Flash-Partition. Das Gerät muss entsperrt sein.
erase <partition> Löscht eine Partition (muss nicht sicher gelöscht werden). Das Gerät muss entsperrt sein.
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 fest. Beim nächsten Startversuch wird das System über den angegebenen Slot gestartet.

Für die A/B-Unterstützung werden Slots als doppelte Partitionssätze verwendet, von denen unabhängig gebootet werden kann. Die Slots heißen a, b usw. und werden durch Hinzufügen der Suffixe _a, _b usw. zum Partitionsnamen unterschieden.

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

Wird in Android 12 und höher verwendet, um das Flashen von Vendor-Ramdisks zu unterstützen.

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

Weitere Informationen finden Sie unter fastboot fetch vendor_boot <out.img>.

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

Wird in Android 12 und höher verwendet, um das Flashen von Vendor-Ramdisks zu unterstützen.

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

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

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

Ruft das vendor_boot-Bild ab. Gibt einen Fehler zurück, wenn der Vendor-Boot-Header Version 3 ist. Bei Version 4 wird das richtige Vendor-Ramdisk-Fragment (falls verfügbar) gefunden. Es wird durch das angegebene Bild ersetzt, Größen und Offsets werden neu berechnet und das neue vendor_boot image wird eingeblendet.

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

Fastboot und Bootloader

Der Bootloader flasht die Partitionen bootloader, radio und boot/recovery. Danach wird das Gerät in Fastboot (Nutzerbereich) gebootet und alle anderen Partitionen werden geflasht. Der Bootloader sollte die folgenden Befehle unterstützen.

Befehl Beschreibung
download Lädt das Image zum Flashen herunter.
flash recovery <image>/ flash boot <image>/ flash bootloader <image>/ Flasht die recovery/boot-Partition und den Bootloader.
reboot Startet das Gerät neu.
reboot fastboot Neustart erfolgt im Fastboot-Modus.
reboot recovery Das Gerät wird im Wiederherstellungsmodus neu gestartet.
getvar Ruft eine Bootloader-Variable ab, die zum Flashen des Recovery- oder 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. Bei Geräten mit nachgerüsteten dynamischen Partitionen unterstützt das Fastboot-Tool (und der Bootloader) einen Force-Modus, mit dem eine dynamische Partition direkt im Bootloader-Modus geflasht werden kann. Wenn system beispielsweise eine dynamische Partition auf dem nachgerüsteten Gerät ist, kann der Bootloader (anstatt von fastbootd) die Partition mit dem Befehl fastboot --force flash system flashen.

Laden im Aus-Modus

Wenn ein Gerät das Laden im Aus-Modus unterstützt oder anderweitig automatisch in einen speziellen Modus wechselt, wenn es mit Strom versorgt wird, 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 Nutzer den Ein/Aus-Schalter gedrückt.

Fastboot-OEM-HAL

Damit der Bootloader-Fastboot vollständig ersetzt werden kann, muss Fastboot alle vorhandenen Fastboot-Befehle verarbeiten können. Viele dieser Befehle stammen von OEMs und sind dokumentiert, erfordern aber eine benutzerdefinierte Implementierung. Viele OEM-spezifische Befehle sind nicht dokumentiert. Zur Verarbeitung solcher Befehle werden im Fastboot-HAL die erforderlichen OEM-Befehle angegeben. OEMs können auch eigene Befehle implementieren.

Die Definition der Fastboot-HAL lautet so:

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üge fastbootd zu PRODUCT_PACKAGES in device.mk hinzu: PRODUCT_PACKAGES += fastbootd.

  2. Die Fastboot-HAL, die Boot-Control-HAL und die Health-HAL müssen im Recovery-Image enthalten sein.

  3. Fügen Sie alle gerätespezifischen SEPolicy-Berechtigungen hinzu, die von fastbootd benötigt werden. Für fastbootd ist beispielsweise Schreibzugriff auf eine gerätespezifische Partition erforderlich, um diese Partition zu flashen. Außerdem sind für die Implementierung des Fastboot-HAL möglicherweise auch gerätespezifische Berechtigungen erforderlich.

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

Vendor-Ramdisks flashen

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 Fastboot-Tool auf dem Host auf, den Vendor-Boot-Header zu lesen, das Image neu zu erstellen und das neue Image zu flashen.

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

Bootloader-Änderungen

Die Befehle getvar:max-fetch-size und fetch:name sind in fastbootd implementiert. Damit das Flashen von Vendor-Ramdisks im Bootloader unterstützt wird, müssen Sie diese beiden Befehle implementieren.

Änderungen an Fastbootd

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

fetch:name[:offset[:size]] führt eine Reihe von Prüfungen auf dem Gerät durch. Wenn alle folgenden Bedingungen erfüllt sind, gibt der Befehl fetch:name[:offset[:size]] Daten zurück:

  • Auf dem Gerät wird ein debugfähiger Build ausgeführt.
  • Das Gerät ist entsperrt (Boot-Status: Orange).
  • Der abgerufene Partitionsname ist vendor_boot.
  • Der size-Wert liegt im Bereich 0 < size <= max-fetch-size.

Wenn diese überprüft wurden, gibt fetch:name[:offset[:size]] die Partitionsgröße und den Offset zurück. Beachten Sie Folgendes:

  • fetch:name entspricht fetch:name:0, was wiederum fetch:name:0:partition_size entspricht.
  • fetch:name:offset entspricht fetch:name:offset:(partition_size - offset)

Daher ist fetch:name[:offset[:size]] = fetch:name:offset:(partition_size - offset).

Wenn offset oder partition_size (oder beide) nicht angegeben sind, werden die Standardwerte verwendet. Für offset ist das 0 und für size der berechnete Wert von partition_size - offset.

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

Mit fetch:foo wird beispielsweise die gesamte Partition foo mit dem Offset 0 abgerufen.

Fahrerwechsel

Dem Fastboot-Tool wurden Befehle hinzugefügt, um Treiberänderungen zu implementieren. 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 ermitteln.
    • Ruft fastboot fetch vendor_boot[_a]:offset:size für jeden Chunk auf. (Die Blockgröße ist größer als die Größe von vendor_boot, sodass es normalerweise nur einen Block gibt.)
    • Fügt die Daten zusammen, um out.img zu erhalten.
  • fastboot flash vendor_boot:default vendor-ramdisk.img

    Dies ist eine spezielle Variante des Flash-Befehls. Es wird das Bild vendor_boot abgerufen, als ob fastboot fetch aufgerufen worden wäre.

    • Wenn der Vendor-Boot-Header Version 3 hat, wird Folgendes ausgeführt:
      • Ersetzt die Vendor-Ramdisk durch das angegebene Image.
      • Das neue vendor_boot-Bild wird eingeblendet.
    • Wenn der Vendor-Boot-Header Version 4 ist, wird Folgendes ausgeführt:
      • Ersetzt die gesamte Vendor-Ramdisk durch das angegebene Image, sodass das angegebene Image das einzige Vendor-Ramdisk-Fragment im vendor_boot-Image wird.
      • Berechnet die Größe und den Offset in der Vendor-Ramdisk-Tabelle neu.
      • Das neue vendor_boot-Bild wird eingeblendet.
  • fastboot flash vendor_boot:foo vendor-ramdisk.img

    Ruft vendor_boot image ab, als ob fastboot fetch aufgerufen wurde.

    • Wenn der Vendor-Boot-Header Version 3 hat, wird ein Fehler zurückgegeben.
    • Wenn der Vendor-Boot-Header Version 4 ist, wird Folgendes ausgeführt:

      • Sucht das Vendor-Ramdisk-Fragment mit dem Namen ramdisk_<var>&lt;foo></var>. Wenn sie nicht gefunden wird oder mehrere Übereinstimmungen vorhanden sind, wird ein Fehler zurückgegeben.
      • Ersetzt das Vendor-Ramdisk-Fragment durch das angegebene Image.
      • Berechnet jede Größe und jeden Offset in der Vendor-Ramdisk-Tabelle neu.
      • Das neue vendor_boot-Bild wird eingeblendet.
    • Wenn <foo> nicht angegeben ist, wird versucht, ramdisk_ zu finden.

mkbootimg

Der Name default ist für die Benennung von Vendor-Ramdisk-Fragmenten in Android 12 und höher reserviert. Die Semantik von Fastboot flash vendor_boot:default bleibt zwar unverändert, Sie dürfen Ihre Ramdisk-Fragmente jedoch nicht als default benennen.

SELinux-Änderungen

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