2018-04-18Google_實現 A/B 更新-3

實現 A/B 更新

想要實現 A/B 系統更新的原始設備制造商 (OEM) 和 SoC 供應商必須確保其引導加載程序實現 boot_control HAL,并將正確的參數傳遞到內核。

實現啟動控件 HAL

支持 A/B 更新的引導加載程序必須在 boot_control 中實現 [hardware/libhardware/include/hardware/boot_control.h](https://android.googlesource.com/platform/hardware/libhardware/+/master/include/hardware/boot_control.h) HAL。您可以使用 [system/extras/bootctl](https://android.googlesource.com/platform/system/extras/+/master/bootctl/) 實用工具和 [system/extras/tests/bootloader/](https://android.googlesource.com/platform/system/extras/+/refs/heads/master/tests/bootloader/) 來測試實現。

您還必須實現狀態機,如下所示:

引導加載程序狀態機.png

設置內核

要實現 A/B 系統更新,請執行以下操作:

  1. 擇優挑選下列內核補丁程序系列(如果需要):
  2. 確保內核命令行參數包含中以下額外參數:
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> 值是用于驗證 verity 表簽名的公鑰 ID(有關詳情,請參閱 dm-verity)。

  1. 將包含公鑰的 .X509 證書添加到系統密鑰環:
    1. 將設置為 .der 格式的 .X509 證書復制到 kernel 的根目錄。如果 .X509 證書的格式為 .pem 文件,請使用以下 openssl 命令將證書格式從 .pem 轉換為 .der
openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
 2.  構建 `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)。
3. 將空格替換為 #,并將其作為 <public-key-id> 在內核命令行中傳遞。例如,傳遞 Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f 而非 <public-key-id>

設置編譯變量

支持 A/B 更新的引導加載程序必須滿足以下編譯變量條件:


原文格式.png

要查看示例,請參閱 [/device/google/marlin/+/android-7.<wbr style="box-sizing: inherit;">1.<wbr style="box-sizing: inherit;">0_r1/device-common.<wbr style="box-sizing: inherit;">mk](https://android.googlesource.com/device/google/marlin/+/android-7.1.0_r1/device-common.mk)。 您可以選擇執行編譯中所述的安裝后(但在重新啟動前)dex2oat 步驟。

設置分區(插槽)

A/B 設備不需要恢復分區或緩存分區,因為 Android 已不再使用這些分區。數據分區現在用于存儲下載的 OTA 軟件包,而恢復映像代碼位于啟動分區。 A/B 化的所有分區都應按以下方法命名(插槽始終被命名為 ab等):boot_aboot_bsystem_asystem_bvendor_avendor_b。

緩存

對于非 A/B 更新,緩存分區用于存儲下載的 OTA 軟件包,并在應用更新時暫時隱藏塊。調整緩存分區大小從來沒有好辦法:所需的大小取決于您想要應用的更新。最糟糕的情況是緩存分區與系統映像一樣大。如果使用 A/B 更新,則無需隱藏塊(因為您始終在向當前未使用的分區寫入數據);如果流式傳輸 A/B 更新,則無需在應用之前下載整個 OTA 軟件包。

恢復

恢復 RAM 磁盤現已包含在 boot.img 文件中。進入恢復模式時,引導加載程序無法在內核命令行中添加 skip_initramfs 選項。

對于非 A/B 更新,恢復分區包含用于應用更新的代碼。A/B 更新由在正常啟動的系統映像中運行的 update_engine 應用。同時,仍有一種用于實現恢復出廠設置和旁加載更新軟件包的恢復模式(“恢復”就由此而來)。恢復模式的代碼和數據存儲在 ramdisk 的常規啟動分區中;為啟動進入系統映像,引導加載程序會指示內核跳過 ramdisk(否則,設備會啟動進入恢復模式)?;謴湍J胶苄。ㄆ渲写蟛糠忠言趩臃謪^上),所以啟動分區的大小不會增加。

Fstab

slotselect 參數必須位于進行 A/B 更新的分區對應的行中。例如:

<path-to-block-device>/vendor  /vendor  ext4  ro
wait,verify=<path-to-block-device>/metadata,slotselect

不得將任何分區命名為 vendor,而應選擇 vendor_avendor_b 分區并將其裝載到 /vendor 裝載點上。

內核插槽參數

應通過特定的設備樹 (DT) 節點 (/firmware/android/slot_suffix) 或 androidboot.slot_suffix 命令行參數傳遞當前插槽后綴。

默認情況下,fastboot 只會閃存 A/B 設備上的插槽 a,并將當前插槽設置為 a。如果更新軟件包還包含插槽 b 的映像,則 fastboot 也會閃存這些映像??捎眠x項包括:

  • --slot。提示 fastboot 使用插槽 b,而非插槽 a
  • --set-active。將插槽設置為活動插槽。
  • 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 更新的設備相同。target_files.zip 文件必須通過為 A/B 更新目標定義編譯變量生成。OTA 軟件包工具會自動識別并生成格式適用于 A/B 更新程序的軟件包。

例如:

  • 生成完整 OTA:
./build/tools/releasetools/ota_from_target_files \
  dist_output/tardis-target_files.zip ota_update.zip
  • 生成增量 OTA:
./build/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 分區。一對分區共用一個前綴(例如 systemboot),每個插槽設置一個后綴(例如 _a)。有效負載生成器為其定義更新的分區列表由 AB_OTA_PARTITIONS make 變量配置。

例如,如果磁盤中有一對分區 bootloader_abooloader_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

編譯

出于安全考慮,system_server 無法使用即時 (JIT) 編譯。 這意味著,您必須至少為 system_server 及其依賴項提前編譯 odex 文件;其他內容則可以先不編譯。

要在后臺編譯應用,您必須將以下內容添加到產品的設備配置(位于產品的 device.mk 中):

  1. 向版本中添加原生組件,以確保編譯腳本和二進制文件能夠編譯并添加到系統映像中。
  # A/B OTA dexopt package
  PRODUCT_PACKAGES += otapreopt_script
  1. 將編譯腳本與 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 文件的首次啟動安裝。

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License, and code samples are licensed under the Apache 2.0 License. For details, see our Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

上次更新日期:四月 17, 2018

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容