將 Fastboot 移至使用者空間

Android 10 及更高版本透過將 fastboot 實作從開機載入程式重新定位到使用者空間來支援可調整大小的分割區。透過這種重定位,可以將快閃記憶體程式碼移至可維護和可測試的公共位置,其中僅包含由硬體抽象層 (HAL) 實現的 fastboot 的特定於供應商的部分。此外,Android 12 及更高版本透過新增的 fastboot 指令支援刷新 ramdisk。

統一快速啟動與恢復

由於使用者空間 fastboot 和 recovery 很相似,因此您可以將它們合併到一個分割區或二進位檔案中。這提供了一些優點,例如使用更少的空間、總體上具有更少的分區以及讓快速啟動和恢復共享其核心和庫。

為了支援fastbootd ,引導程式必須實作新的引導控制區塊(BCB)指令boot-fastboot 。若要進入fastbootd模式,引導程式將boot-fastboot寫入 BCB 訊息的命令欄位中,並保持 BCB 的recovery欄位不變(以啟用重新啟動任何中斷的恢復任務)。 statusstagereserved字段也保持不變。引導程式在 BCB 命令欄位中看到boot-fastboot後載入並引導到恢復映像。然後 Recovery 解析 BCB 訊息並切換到fastbootd模式。

亞行命令

本節介紹用於整合fastbootd adb指令。該命令有不同的結果,取決於它是由系統執行還是由恢復執行。

命令描述
reboot fastboot
  • 重新啟動進入fastbootd (系統)。
  • 直接進入fastbootd ,無需重新啟動(恢復)。

快速啟動命令

本節介紹用於整合fastbootd fastboot 命令,包括用於刷新和管理邏輯分割區的新命令。某些指令有不同的結果,取決於它們是由 bootloader 還是由fastbootd執行。

命令描述
reboot recovery
  • 重新啟動進入恢復(引導程式)。
  • 直接進入恢復,無需重新啟動( fastbootd )。
reboot fastboot重新啟動進入fastbootd
getvar is-userspace
  • 返回yes ( fastbootd )。
  • 返回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 及更高版本中使用以支援刷新供應商 ramdisk。

取得整個分割區大小和區塊大小。取得每個區塊的數據,然後將資料拼接到<out.img>

有關詳細信息,請參閱fastboot fetch vendor_boot <out.img>

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

Android 12及更高版本中使用以支援刷新供應商 ramdisk。

這是 flash 指令的特殊變體。它執行fetch vendor_boot映像函數,就像呼叫fastboot fetch一樣。它刷新的新的vendor_boot映像取決於引導頭版本是版本3還是版本4。

有關詳細信息,請參閱fastboot flash vendor_boot:default <vendor-ramdisk.img>

fastboot flash vendor_boot: <foo> <vendor-ramdisk.img>Android 12及更高版本中使用以支援刷新供應商 ramdisk。

取得vendor_boot鏡像。如果供應商引導頭是版本 3,則傳回錯誤。如果是版本 4,它將找到正確的供應商 ramdisk 片段(如果可用)。它用給定的映像替換它,重新計算大小和偏移量,並刷新新的vendor_boot image

詳細資訊請參考fastboot flash vendor_boot: <foo> <vendor-ramdisk.img>

快速啟動和引導程式

引導程式會刷新bootloaderradioboot/recovery分割區,之後裝置啟動到 fastboot (使用者空間)並刷新所有其他分割區。引導程式應支援以下命令。

命令描述
download將圖像下載到閃存。
flash recovery <image> / flash boot <image> / flash bootloader <image> /刷新recovery/boot分割區和引導程式。
reboot重新啟動設備。
reboot 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

  1. fastbootd加入device.mk中的PRODUCT_PACKAGESPRODUCT_PACKAGES += fastbootd

  2. 確保將 fastboot HAL、啟動控制 HAL 和 health HAL 打包為恢復映像的一部分。

  3. 新增fastbootd所需的任何特定於裝置的 SEPolicy 權限。例如, fastbootd需要對裝置特定分割區進行寫入存取才能刷新該分割區。此外,fastboot HAL 實作可能還需要裝置特定的權限。

若要驗證使用者空間快速啟動,請執行供應商測試套件 (VTS)

刷新供應商 ramdisk

Android 12 及更高版本提供對快閃 ramdisk 的支持,並添加了 fastboot 命令,可從裝置中提取完整的vendor_boot映像。此指令提示主機端 fastboot 工具讀取供應商引導標頭、重新映像並刷新新映像。

為了提取完整的vendor_boot鏡像,命令fetch:vendor_boot被添加到fastboot協定和Android 12中該協定的fastbootd實作中。請注意,fastbootd確實實現了這一點,但引導程式本身可能沒有。 OEM 可以將fetch:vendor_boot指令加入到協定的引導程式實作中。但是,如果在引導程式模式下無法識別該命令,則在引導程式模式下刷新各個供應商 ramdisk 不是供應商支援的選項。

引導程式更改

指令getvar:max-fetch-sizefetch:namefastbootd中實作。要在引導程式中支援刷新供應商 ramdisk,您必須實作這兩個命令。

Fastbootd 的變化

getvar:max-fetch-sizemax-download-size類似。它指定設備可以在一個資料回應中發送的最大大小。驅動程式不得取得大於此值的大小。

fetch:name[:offset[:size]]對裝置執行一系列檢查。如果以下所有條件均成立, fetch:name[:offset[:size]]指令傳回資料:

  • 該設備正在運行可調試版本。
  • 設備已解鎖(啟動狀態橙色)。
  • 取得的分區名稱是vendor_boot
  • size值在 0 < size <= max-fetch-size內。

驗證這些後, fetch:name[:offset[:size]]傳回分割區大小和偏移量。請注意以下事項:

  • fetch:name相當於fetch:name:0 ,後者相當於fetch:name:0:partition_size
  • fetch:name:offset相當於fetch:name:offset:(partition_size - offset)

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

offsetpartition_size (或兩者)未指定時,將使用預設值, offset為0, sizepartition_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大小,因此通常只有一個塊。)
    • 將資料拼接在一起,形成out.img
  • fastboot flash vendor_boot:default vendor-ramdisk.img

    這是 flash 指令的特殊變體。它取得vendor_boot鏡像,就像呼叫fastboot fetch

    • 如果供應商引導的標頭版本為 3 ,它將執行以下操作:
      • 使用給定的映像替換供應商 ramdisk。
      • 刷新新的vendor_boot映像。
    • 如果供應商引導標頭是版本 4 ,它將執行以下操作:
      • 將整個供應商 ramdisk 替換為給定映像,以便給定映像成為vendor_boot映像中唯一的供應商 ramdisk 片段。
      • 重新計算供應商 ramdisk 表中的大小和偏移量。
      • 刷新新的vendor_boot映像。
  • fastboot flash vendor_boot:foo vendor-ramdisk.img

    取得vendor_boot image ,就像呼叫fastboot fetch

    • 如果供應商引導標頭是版本 3,則會傳回錯誤。
    • 如果供應商引導標頭是版本 4,它將執行以下操作:

      • 尋找名為foo供應商 ramdisk 片段。如果未找到,或存在多個符合項,則傳回錯誤。
      • 用給定的映像取代供應商 ramdisk 片段。
      • 重新計算供應商 ramdisk 表中的每個大小和偏移。
      • 刷新新的vendor_boot映像。

MKBootimg

default名稱保留用於命名 Android 12 及更高版本中的供應商 ramdisk 片段。雖然 fastboot flash vendor_boot:default語意保持不變,但您不得將 ramdisk 片段命名為default

SELinux 的變化

fastbootd.te中進行了更改以支援刷新供應商 ramdisk。