想要實作 A/B 系統更新的 OEM 和 SoC 供應商必須確保其引導程式實作 boot_control HAL 並將正確的參數傳遞給核心。
實現啟動控制HAL
支援 A/B 的開機載入程式必須在hardware/libhardware/include/hardware/boot_control.h
實作boot_control
HAL。您可以使用system/extras/bootctl
實用程式和system/extras/tests/bootloader/
測試實作。
您還必須實作如下所示的狀態機:
設定內核
要實施 A/B 系統更新:
- 精選以下內核補丁系列(如果需要):
- 如果在沒有 ramdisk 的情況下啟動並使用“啟動作為恢復”,請cherrypick android-review.googlesource.com/#/c/158491/ 。
- 若要在沒有 ramdisk 的情況下設定 dm-verity,請cherrypick android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18 。
- 確保內核命令列參數包含以下額外參數:
skip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
<public-key-id>
值是用於驗證驗證表簽名的公鑰的 ID(有關詳細信息,請參閱dm-verity ) 。 - 將包含公鑰的 .X509 憑證新增至系統金鑰環:
- 將
.der
格式的.X509憑證複製到kernel
目錄的根目錄下。如果 .X509 憑證格式為.pem
文件,請使用下列openssl
指令將.pem
轉換為.der
格式:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
- 建置
zImage
以將憑證包含在系統金鑰環中。若要進行驗證,請檢查procfs
條目(需要啟用KEYS_CONFIG_DEBUG_PROC_KEYS
):angler:/# cat /proc/keys 1c8a217e I------ 1 perm 1f010000 0 0 asymmetri Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f [] 2d454e3e I------ 1 perm 1f030000 0 0 keyring .system_keyring: 1/4
成功包含 .X509 憑證表示系統金鑰環中存在公鑰(反白表示公鑰 ID)。 - 將空格替換為
#
並將其作為<public-key-id>
在核心命令列中傳遞。例如,傳遞Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f
代替<public-key-id>
。
- 將
設定建構變數
支援 A/B 的引導程式必須符合以下建置變數標準:
必須定義 A/B 目標 |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk 。您可以選擇執行編譯中所述的安裝後(但重新啟動前)dex2oat 步驟。 |
---|---|
強烈建議用於 A/B 目標 |
|
無法定義 A/B 目標 |
|
偵錯版本可選 | PRODUCT_PACKAGES_DEBUG += update_engine_client |
設定分區(槽)
A/B 裝置不需要恢復分區或快取分區,因為 Android 不再使用這些分區。資料分割區現在用於下載的 OTA 包,恢復映像碼位於啟動分割區。所有 A/B 分區應如下命名(插槽永遠命名為a
、 b
等): boot_a
、 boot_b
、 system_a
、 system_b
、 vendor_a
、 vendor_b
。
快取
對於非 A/B 更新,快取分區用於儲存下載的 OTA 套件並在應用程式更新時暫時儲存區塊。從來沒有一個好的方法來確定快取分區的大小:它需要多大取決於您想要應用的更新。最糟的情況是快取分區與系統映像一樣大。使用 A/B 更新,無需儲存區塊(因為您總是寫入目前未使用的分割區),並且使用串流 A/B 更新,無需在應用程式之前下載整個 OTA 套件。
恢復
恢復 RAM 磁碟現在包含在boot.img
檔案中。進入復原狀態時,引導程式無法將skip_initramfs
選項放在核心命令列上。
對於非 A/B 更新,復原分割區包含用於套用更新的程式碼。 A/B 更新由在常規啟動的系統映像中執行的update_engine
套用。還有一種恢復模式用於實現恢復出廠資料和側載更新包(這就是“恢復”名稱的由來)。恢復模式的程式碼和資料儲存在 ramdisk 的常規啟動分區中;為了引導到系統映像,引導程式告訴核心跳過 ramdisk(否則裝置將引導至復原模式。復原模式很小(並且其中大部分已經在引導分割區上),因此引導分割區不會增加在尺寸方面。
穩定表
slotselect
參數必須位於 A/B 分區的行上。例如:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
任何分區都不應該被命名為vendor
。相反,將選擇分區vendor_a
或vendor_b
並將其安裝在/vendor
安裝點上。
核心槽參數
當前插槽後綴應透過特定裝置樹 (DT) 節點 ( /firmware/android/slot_suffix
) 或透過androidboot.slot_suffix
核心命令列或 bootconfig 參數傳遞。
預設情況下,fastboot 會刷新 A/B 裝置上的目前插槽。如果更新套件還包含其他非目前插槽的映像,則 fastboot 也會刷新這些映像。可用選項包括:
-
--slot SLOT
。覆寫預設行為並提示 fastboot 刷新作為參數傳入的插槽。 -
--set-active [ SLOT ]
。將插槽設定為活動狀態。如果未指定選用參數,則目前插槽設定為活動插槽。 -
fastboot --help
。取得有關命令的詳細資訊。
如果引導程式實現 fastboot,則它應該支援命令set_active <slot>
,該命令將當前活動插槽設為給定插槽(這也必須清除該插槽的不可引導標誌並將重試計數重設為預設值).引導程式也應該支援以下變數:
-
has-slot:<partition-base-name-without-suffix>
。如果給定分區支援插槽,則傳回“yes”,否則傳回“no”。 -
current-slot
。傳回將從下一個啟動的插槽後綴。 -
slot-count
。傳回一個表示可用槽數的整數。目前,支援兩個插槽,因此該值為2
。 -
slot-successful:<slot-suffix>
。如果給定插槽已標記為成功啟動,則傳回“yes”,否則傳回“no”。 -
slot-unbootable:<slot-suffix>
。如果給定插槽被標記為無法啟動,則傳回“yes”,否則傳回“no”。 -
slot-retry-count
。嘗試引導給定插槽的剩餘重試次數。
若要查看所有變量,請執行fastboot getvar all
。
生成OTA包
OTA 打包工具遵循與非 A/B 裝置相同的指令。必須透過定義 A/B 目標的建置變數來產生target_files.zip
檔。 OTA 套件工具會自動識別並產生 A/B 更新程式格式的套件。
例子:
- 產生完整的 OTA:
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip
- 產生增量 OTA:
./build/make/tools/releasetools/ota_from_target_files \ -i PREVIOUS-tardis-target_files.zip \ dist_output/tardis-target_files.zip \ incremental_ota_update.zip
配置分區
update_engine
可以更新在同一磁碟中定義的任一對 A/B 分割區。一對分區具有共同的前綴(例如system
或boot
)和每個插槽的後綴(例如_a
)。有效負載產生器定義更新的分區清單由AB_OTA_PARTITIONS
make 變數配置。
例如,如果包含一對分割區bootloader_a
和booloader_b
( _a
和_b
是插槽後綴),您可以透過在產品或主機板配置上指定以下內容來更新這些分割區:
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
由update_engine
更新的所有分區不得被系統的其餘部分修改。在增量或增量更新期間,目前槽中的二進位資料用於產生新槽中的資料。任何修改都可能導致更新過程中新槽位資料驗證失敗,從而導致更新失敗。
配置安裝後
您可以使用一組鍵值對為每個更新的分割區配置不同的安裝後步驟。若要在新映像中執行位於/system/usr/bin/postinst
的程序,請指定相對於系統分割區中檔案系統根目錄的路徑。
例如, usr/bin/postinst
是system/usr/bin/postinst
(如果不使用 RAM 磁碟)。此外,指定要傳遞給mount(2)
系統呼叫的檔案系統類型。將以下內容新增至產品或裝置.mk
檔案(如果適用):
AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=usr/bin/postinst \ FILESYSTEM_TYPE_system=ext4
編譯應用程式
應用程式可以在使用新系統映像重新啟動之前在背景編譯。若要在背景編譯應用程序,請將以下內容新增至產品的裝置配置中(在產品的 device.mk 中):
- 在建置中包含本機元件,以確保編譯腳本和二進位檔案已編譯並包含在系統映像中。
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
- 將編譯腳本連接到
update_engine
,以便作為安裝後步驟執行。# A/B OTA dexopt update_engine hookup AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=system/bin/otapreopt_script \ FILESYSTEM_TYPE_system=ext4 \ POSTINSTALL_OPTIONAL_system=true
有關在未使用的第二個系統分割區中安裝預選檔案的協助,請參閱DEX_PREOPT 檔案的首次開機安裝。