ユーザー空間への fastboot の移行

Android 10 以降では、fastboot の実装をブートローダーからユーザー空間に再配置することで、サイズ変更可能なパーティションがサポートされています。この再配置により、Hardware Abstraction Layer(HAL)によって実装された fastboot のベンダー固有の部分のみを使用して、保守可能でテスト可能な共通の場所にフラッシュ コードを移動できます。また、Android 12 以降では、追加された fastboot コマンドによる RAM ディスクのフラッシュがサポートされています。

fastboot とリカバリの統合

ユーザー空間 fastboot とリカバリは似ているため、1 つのパーティションまたはバイナリに統合できます。統合は、スペースの節約、合計パーティション数の削減、fastboot とリカバリによるカーネルとライブラリの共有などのメリットがあります。

fastbootd をサポートするには、ブートローダーが boot-fastboot の新しいブート コントロール ブロック(BCB)コマンドを実装する必要があります。fastbootd モードを実行するには、ブートローダーで boot-fastboot を BCB メッセージのコマンド フィールドに書き込み、BCB の recovery フィールドはそのままにしておく必要があります(それにより、中断されたリカバリタスクを再開できます)。statusstagereserved の各フィールドもそのまま残ります。ブートローダーは、BCB コマンド フィールドに boot-fastboot が出現すると、リカバリ イメージを読み込んで起動します。その後、リカバリで BCB メッセージが解析され、fastbootd モードに切り替わります。

ADB コマンド

このセクションでは、fastbootd を統合するための adb コマンドについて説明します。このコマンドの実行結果は、システムによって実行されるか、リカバリによって実行されるかによって異なります。

コマンド 説明
reboot fastboot
  • fastbootd(システム)に再起動します。
  • 再起動(リカバリ)なしで直接 fastbootd に入ります。

fastboot コマンド

このセクションでは、fastbootd を統合するための fastboot コマンドについて説明します。論理パーティションのフラッシュや管理に使用する新しいコマンドについてもここで説明します。一部のコマンドについては、ブートローダーによる実行か fastbootd による実行かによって、結果が異なります。

コマンド 説明
reboot recovery
  • 再起動してリカバリ(ブートローダー)に入ります。
  • 再起動(fastbootd)なしで直接リカバリに入ります。
reboot fastboot 再起動して fastbootd に入ります。
getvar is-userspace
  • yesfastbootd)を返します。
  • no(ブートローダー)を返します。
getvar is-logical:<partition> 指定されたパーティションが論理パーティションである場合は yes を返し、それ以外の場合は no を返します。 論理パーティションは、以下のすべてのコマンドをサポートします。
getvar super-partition-name スーパー パーティションの名前を返します。スーパー パーティションが A/B パーティションの場合は(通常はそのようにならない)、現在のスロット サフィックスがこの名前に含まれます。
create-logical-partition <partition> <size> 指定した名前とサイズで論理パーティションを作成します。この名前は論理パーティションとしてすでに存在しているものであってはなりません。
delete-logical-partition <partition> 指定した論理パーティションを削除(実際にはパーティションをワイプ)します。
resize-logical-partition <partition> <size> 論理パーティションの内容を変更せずに、新しいサイズに変更します。 サイズ変更の実行に十分な空き領域がない場合は失敗します。
update-super <partition> スーパー パーティション メタデータに変更をマージします。マージができない場合(たとえば、デバイスの形式がサポートされていない場合など)、このコマンドは失敗します。オプションの wipe パラメータを使用した場合、マージを実行する代わりに、デバイスのメタデータを上書きします。
flash <partition><filename> ] フラッシュ パーティションにファイルを書き込みます。デバイスはロック解除状態でなければなりません。
erase <partition> パーティションを消去します(セキュアな消去である必要はありません)。デバイスはロック解除状態でなければなりません。
getvar <variable> | all ブートローダー変数、またはすべての変数を表示します。変数が存在しない場合はエラーを返します。
set_active <slot>

指定した A/B ブートスロットを active に設定します。システムは次のブート時に、指定したスロットから起動します。

A/B サポートの場合、スロットは独立した起動が可能なパーティションの重複セットです。スロットには ab などの名前が付けられます。これらはパーティション名に接尾辞 _a_b などを付けることで区別されます。

reboot デバイスは通常どおりに再起動します。
reboot-bootloader(または reboot bootloader デバイスを再起動してブートローダーに入ります。
fastboot fetch vendor_boot <out.img>

Android 12 以降ベンダー RAM ディスクのフラッシュをサポートするために使用します。

全体のパーティション サイズとチャンクサイズを取得します。各チャンクのデータを取得し、そのデータを組み合わせて <out.img> を作成します。

詳しくは、fastboot fetch vendor_boot <out.img> をご覧ください。

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

Android 12 以降でベンダー RAM ディスクのフラッシュをサポートするために使用します。

これは Flash コマンドの特殊なバリアントです。fastboot fetch が呼び出された場合と同様に、fetch vendor_boot イメージ関数を実行します。フラッシュする新しい vendor_boot イメージは、ブートヘッダー バージョンが 3 か 4 かによって異なります。

詳しくは、fastboot flash vendor_boot:default <vendor-ramdisk.img> をご覧ください。

fastboot flash vendor_boot:<foo> <vendor-ramdisk.img> Android 12 以降でベンダー RAM ディスクのフラッシュをサポートするために使用します。

vendor_boot イメージを取得します。ベンダー ブートヘッダーがバージョン 3 の場合、エラーを返します。バージョン 4 の場合、正しいベンダー RAM ディスク フラグメントを検索します(存在する場合)。そしてそれを指定したイメージで置き換え、サイズとオフセットを再計算し、新しい vendor_boot image をフラッシュします。

詳しくは、fastboot flash vendor_boot:<foo> <vendor-ramdisk.img> をご覧ください。

fastboot とブートローダー

ブートローダーは、bootloaderradioboot/recovery のパーティションをフラッシュします。その後、デバイスが fastboot(ユーザー空間)で起動し、他のすべてのパーティションをフラッシュします。ブートローダーは、次のコマンドをサポートしている必要があります。

コマンド 説明
download フラッシュするイメージをダウンロードします。
flash recovery <image>/ flash boot <image>/ flash bootloader <image>/ recovery/boot パーティションとブートローダーをフラッシュします。
reboot デバイスを再起動します。
reboot fastboot 再起動して fastboot に入ります。
reboot recovery 再起動してリカバリに入ります。
getvar リカバリ / ブートイメージ(current-slotmax-download-size など)のフラッシュに必要なブートローダー変数を取得します。
oem <command> OEM によって定義されたコマンド。

動的パーティション

ブートローダーで動的パーティションのフラッシュまたは消去を許可してはなりません。また、これらの操作が試みられた場合にはエラーを返す必要があります。レトロフィットされた動的パーティション デバイスの場合、fastboot ツール(およびブートローダー)は、ブートローダー モードで動的パーティションを直接フラッシュするための強制モードをサポートします。たとえば、system がレトロフィットされたデバイスの動的パーティションである場合、fastboot --force flash system コマンドを使用すると、(fastbootd の代わりに)ブートローダーはパーティションをフラッシュできるようになります。

オフモード充電

デバイスがオフモード充電に対応している場合、またはそれ以外で電源投入時に特殊モードで自動起動する場合、fastboot oem off-mode-charge 0 コマンドの実装時にこれらの特殊モードは無視され、デバイスがユーザーが電源ボタンを押した場合と同じように起動します。

fastboot OEM HAL

ブートローダーの fastboot を完全に置き換えるには、fastboot が既存のすべての fastboot コマンドを処理する必要があります。これらのコマンドの多くは OEM から提供され、ドキュメント化されていますが、カスタム実装が必要です。OEM 固有のコマンドの多くはドキュメントに記載されていません。このようなコマンドを処理するため、fastboot HAL は必要な OEM コマンドを指定します。OEM は独自のコマンドを実装することもできます。

fastboot HAL の定義は次のとおりです。

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 の有効化

デバイスで fastbootd を有効にする手順は、以下のとおりです。

  1. fastbootddevice.mkPRODUCT_PACKAGES に追加します(PRODUCT_PACKAGES += fastbootd)。

  2. fastboot HAL、ブート コントロール HAL、Health HAL がリカバリ イメージの一部としてパッケージ化されていることを確認します。

  3. fastbootd で必要となるデバイス独自の SEPolicy アクセス許可を追加します。たとえば、fastbootd はデバイス独自のパーティションをフラッシュするため、そのパーティションへの書き込みアクセスが必要となります。さらに、fastboot HAL の実装にはデバイス独自のアクセス許可も必要になる場合があります。

ユーザー空間 fastboot を検証するには、ベンダー テストスイート(VTS)を実行します。

ベンダー RAM ディスクのフラッシュ

Android 12 以降では、デバイスから完全な vendor_boot イメージを取得する追加の fastboot コマンドを使用して、RAM ディスクをフラッシュできます。このコマンドは、ホスト側の fastboot ツールに対し、ベンダー ブートヘッダーを読み取り、イメージを再作成して新しいイメージをフラッシュするように要求します。

完全な vendor_boot イメージを取得するために、Android 12 では fastboot プロトコルと fastboot プロトコルの fastbootd 実装の両方にコマンド fetch:vendor_boot が追加されました。fastbootd はこれを実装しますが、ブートローダー自体はこれを実装していない場合があります。OEM は、プロトコルのブートローダー実装に fetch:vendor_boot コマンドを追加できます。ただし、コマンドがブートローダー モードで認識されなかった場合、ブートローダー モードでの個別のベンダー RAM ディスクのフラッシュは、ベンダーがサポートするオプションではなくなります。

ブートローダーの変更

コマンド getvar:max-fetch-sizefetch:namefastbootd に実装されています。 ブートローダーでのベンダー RAM ディスクのフラッシュをサポートするには、次の 2 つのコマンドを実装する必要があります。

fastbootd の変更

getvar:max-fetch-sizemax-download-size と同様です。1 つの DATA レスポンスでデバイスが送信できる最大サイズを指定します。ドライバがこの値より大きいサイズを取得することはできません。

fetch:name[:offset[:size]] はデバイスで一連のチェックを実行します。以下のすべてが当てはまる場合、fetch:name[:offset[:size]] コマンドはデータを返します。

  • デバイスがデバッグ可能なビルドを実行している。
  • デバイスのロックが解除されている(ブート状態がオレンジ)。
  • 取得されたパーティション名が vendor_boot である。
  • size の値が 0 < size <= max-fetch-size の範囲にある。

これらが検証されると、fetch:name[:offset[:size]] はパーティションのサイズとオフセットを返します。 次の点に注意してください。

  • fetch:namefetch:name:0 と等価です。これはすなわち fetch:name:0:partition_size と等価です。
  • fetch:name:offsetfetch:name:offset:(partition_size - offset) と等価です。

そのため fetch:name[:offset[:size]] = fetch:name:offset:(partition_size - offset) となります。

offset または partition_size(または両方)が指定されていない場合、デフォルト値が使用されます。デフォルト値は offset では 0、size では partition_size - offset の計算値です。

  • オフセットが指定され、サイズが指定されてない場合: size = partition_size - offset
  • どちらも指定されていない場合: 両方にデフォルト値が使用されます(size = partition_size - 0)。

たとえば、fetch:foo と指定すると、オフセット 0 で foo パーティション全体が取得されます。

ドライバの変更

ドライバの変更を実装するためのコマンドが fastboot ツールに追加されました。それぞれ、Fastboot コマンドの表の完全な定義にリンクしています。

  • fastboot fetch vendor_boot out.img

    • getvar max-fetch-size を呼び出してチャンクサイズを判別します。
    • getvar partition-size:vendor_boot[_a] を呼び出してパーティション全体のサイズを判別します。
    • チャンクごとに fastboot fetch vendor_boot[_a]:offset:size を呼び出します(チャンクサイズは vendor_boot サイズよりも大きいため、通常はチャンクは 1 つだけです)。
    • データを組み合わせて out.img を作成します。
  • fastboot flash vendor_boot:default vendor-ramdisk.img

    これは Flash コマンドの特殊なバリアントです。fastboot fetch が呼び出された場合と同様に、vendor_boot イメージを取得します。

    • ベンダー ブートヘッダーがバージョン 3 の場合、次の処理が行われます。
      • ベンダー RAM ディスクを指定されたイメージに置き換えます。
      • 新しい vendor_boot イメージをフラッシュします。
    • ベンダー ブートヘッダーがバージョン 4 の場合、次の処理が行われます。
      • ベンダー RAM ディスク全体を指定されたイメージに置き換えます。これにより、指定されたイメージが vendor_boot イメージ内の唯一のベンダー RAM ディスク フラグメントになります。
      • ベンダー RAM ディスク テーブルのサイズとオフセットを再計算します。
      • 新しい vendor_boot イメージをフラッシュします。
  • fastboot flash vendor_boot:foo vendor-ramdisk.img

    fastboot fetch が呼び出された場合と同様に vendor_boot image を取得します。

    • ベンダー ブートヘッダーがバージョン 3 の場合は、エラーを返します。
    • ベンダー ブートヘッダーがバージョン 4 の場合、次の処理が行われます。

      • foo という名前のベンダー RAM ディスク フラグメントを検索します。見つからない場合、または一致する結果が複数ある場合は、エラーが返されます。
      • ベンダー RAM ディスク フラグメントを指定されたイメージに置き換えます。
      • ベンダー RAM ディスク テーブルのそれぞれのサイズとオフセットを再計算します。
      • 新しい vendor_boot イメージをフラッシュします。

mkbootimg

Android 12 以降では、default という名前はベンダー RAM ディスク フラグメントに名前を付けるために予約されています。fastboot の flash vendor_boot:default セマンティクスは変わりませんが、RAM ディスク フラグメントに default という名前を付けることはできません

SELinux の変更

fastbootd.te で、ベンダー RAM ディスクのフラッシュをサポートするための変更が行われました。