支援 Treble 的裝置必須啟用第一階段裝載,以確定 init 可以加載分布在 system 和 vendor 分區的安全增強型 (SELinux) 政策 Fragment。此通路權限還可實作在核心啟動後盡快加載核心子產品。
如需執行提前裝載,Android 必須有權通路子產品所在的檔案系統。Android 8.0 及更高版本支援在 init 的第一階段(即初始化 SElinux 之前)裝載 /system、/vendor 或 /odm。
1、Fstab 條目
在 Android 9 及更低版本中,裝置可以使用裝置樹疊加層 (DTO) 為提前裝載的分區指定 fstab 條目。
在 Android 10 及更高版本中,裝置必須使用第一階段 ramdisk 中的 fstab 檔案為提前裝載的分區指定 fstab 條目。Android 10 引入了以下可在 fstab 檔案中使用的 fs_mgr 标記:
- first_stage_mount 表明将由第一階段 init 裝載分區。
- logical 表明這是一個動态分區。
- avb=vbmeta-partition-name 可指定 vbmeta 分區。第一階段 init 可初始化該分區,然後再裝載其他分區。如果該條目的 vbmeta 分區已由上一行中的其他 fstab 條目指定,可以省略此标記的參數。
以下示例展示了将 system、vendor 和 product 分區設定為邏輯(動态)分區的 fstab 條目。
#<dev> <mnt_point> <type> <mnt_flags options> <fs_mgr_flags>
system /system ext4 ro,barrier=1 wait,slotselect,avb=vbmeta_system,logical,first_stage_mount
vendor /vendor ext4 ro,barrier=1 wait,slotselect,avb=vbmeta,logical,first_stage_mount
product /product ext4 ro,barrier=1 wait,slotselect,avb,logical,first_stage_mount
在上述示例中,供應商使用 fs_mgr 标記 avb=vbmeta 指定了 vbmeta 分區,但 product 省略了 vbmeta 參數,因為供應商已将 vbmeta 添加到了分區清單。
搭載 Android 10 及更高版本的裝置必須将 fstab 檔案放在 ramdisk 和 vendor 分區中。
2、Ramdisk
fstab 檔案在 ramdisk 中的位置取決于裝置如何使用 ramdisk。
具有啟動 ramdisk 的裝置必須将 fstab 檔案放在啟動 ramdisk 根目錄中。如果裝置同時具有啟動 ramdisk 和恢複 ramdisk,就無需對恢複 ramdisk 進行任何更改。示例:
PRODUCT_COPY_FILES += device/google/<product-name>/fstab.hardware:$(TARGET_COPY_OUT_RAMDISK)/fstab.$(PRODUCT_PLATFORM)
将恢複用作 ramdisk 的裝置必須使用核心指令行參數 androidboot.force_normal_boot=1 來決定是啟動到 Android 還是繼續啟動到恢複模式。
釋出時搭載 Android 12 或更高版本且核心版本為 5.10 或更高版本的裝置必須使用 bootconfig 傳遞 androidboot.force_normal_boot=1 參數。
在這些裝置中,第一階段 init 在裝載提前裝載分區之前将根操作切換到了 /first_stage_ramdisk,是以裝置必須将 fstab 檔案放在 $(TARGET_COPY_OUT_RECOVERY)/root/first_stage_ramdisk 中。示例:
PRODUCT_COPY_FILES += device/google/<product-name>/fstab.hardware:$(TARGET_COPY_OUT_RECOVERY)/root/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM)
3、Vendor
所有裝置都必須将 fstab 檔案的副本放到 /vendor/etc 中。這是因為第一階段 init 在完成分區提前裝載之後釋放了 ramdisk,并執行了切換根操作,以将位于 /system 的裝載移動到了 /。是以,後續任何需要通路 fstab 檔案的操作都必須使用 /vendor/etc 中的副本。示例:
PRODUCT_COPY_FILES += device/google/<product-name>/fstab.hardware:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.$(PRODUCT_PLATFORM)
4、提前裝載分區,VBoot 1.0
使用 VBoot 1.0 提前裝載分區的要求包括:
- 1、裝置節點路徑必須在 fstab 和裝置樹條目中使用其 by-name 符号連結。例如,確定對分區進行命名且裝置節點為 /dev/block/…./by-name/{system,vendor,odm},而不是使用 /dev/block/mmcblk0pX 指定分區。
- 2、在産品的裝置配置中(即 device/oem/project/device.mk 中)為 PRODUCT_{SYSTEM,VENDOR}_VERITY_PARTITION 和 CUSTOM_IMAGE_VERITY_BLOCK_DEVICE 指定的路徑必須與 fstab/裝置樹條目中相應塊裝置節點指定的 by-name 相比對。示例:
PRODUCT_SYSTEM_VERITY_PARTITION := /dev/block/…./by-name/system
PRODUCT_VENDOR_VERITY_PARTITION := /dev/block/…./by-name/vendor
CUSTOM_IMAGE_VERITY_BLOCK_DEVICE := /dev/block/…./by-name/odm
- 3、通過裝置樹疊加層提供的條目不得在 fstab 檔案 fragment 中出現重複。例如,指定某個條目以在裝置樹中裝載 /vendor 時,fstab 檔案不得重複該條目。
- 4、不得提前裝載需要 verifyatboot 的分區(此操作不受支援)。
- 5、必須在 kernel_cmdline 中使用 androidboot.veritymode 選項指定驗證分區的真實模式/狀态(現有要求)。
5、提前裝載裝置樹,VBoot 1.0
在 Android 8.x 及更高版本中,init 會解析裝置樹并建立 fstab 條目,以在其第一階段提前裝載分區。fstab 條目采用以下形式:
src mnt_point type mnt_flags fs_mgr_flags
定義裝置樹屬性以模拟該格式:
- fstab 條目必須在裝置樹中的 /firmware/android/fstab 下,且必須将相容字元串設定為 android,fstab。
-
/firmware/android/fstab 下的每個節點都被視為單個提前裝載 fstab 條目。節點必須定義以下屬性:
dev 必須指向表示 by-name 分區的裝置節點
- type 必須是檔案系統類型(如在 fstab 檔案中一樣)
- mnt_flags 必須是裝載标記的逗号分隔清單(如在 fstab 檔案中一樣)
- fsmgr_flags 必須是 Android fs_mgr flags 清單(如在 fstab 檔案中一樣)
- A/B 分區必須具有 slotselect fs_mgr 選項。
- 已啟用 dm-verity 的分區必須具有 verify fs_mgr 選項。
示例:N6P 上的 /system 和 /vendor
下面的示例顯示的是在 Nexus 6P 上為 system 和 vendor 分區提前裝載裝置樹:
/ {
firmware {
android {
compatible = "android,firmware";
fstab {
compatible = "android,fstab";
system {
compatible = "android,system";
dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/system";
type = "ext4";
mnt_flags = "ro,barrier=1,inode_readahead_blks=8";
fsmgr_flags = "wait,verify";
};
vendor {
compatible = "android,vendor";
dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor";
type = "ext4";
mnt_flags = "ro,barrier=1,inode_readahead_blks=8";
fsmgr_flags = "wait";
};
};
};
};
};
示例:Pixel 上的 /vendor
下面的示例顯示的是在 Pixel 上為 /vendor 提前裝載裝置樹(請務必為 A/B 分區添加 slotselect):
/ {
firmware {
android {
compatible = "android,firmware";
fstab {
compatible = "android,fstab";
vendor {
compatible = "android,vendor";
dev = "/dev/block/platform/soc/624000.ufshc/by-name/vendor";
type = "ext4";
mnt_flags = "ro,barrier=1,discard";
fsmgr_flags = "wait,slotselect,verify";
};
};
};
};
};
6、提前裝載分區,VBoot 2.0
VBoot 2.0 是 Android 啟動時驗證 (AVB)。使用 VBoot 2.0 提前裝載分區的要求如下:
- 1、裝置節點路徑必須在 fstab 和裝置樹條目中使用其 by-name 符号連結。例如,確定對分區進行命名且裝置節點為 /dev/block/…./by-name/{system,vendor,odm},而不是使用 /dev/block/mmcblk0pX 指定分區。
- 2、VBoot 1.0 所用的建構系統變量(如 PRODUCT_{SYSTEM,VENDOR}_VERITY_PARTITION 和 CUSTOM_IMAGE_VERITY_BLOCK_DEVICE)對 VBoot 2.0 而言并不是必需的。您應定義 VBoot 2.0 中引入的 build 變量(包括 BOARD_AVB_ENABLE := true)。
- 3、通過裝置樹疊加層提供的條目不得在 fstab 檔案 fragment 中出現重複。例如,如果您指定某個條目以在裝置樹中裝載 /vendor,fstab 檔案不得重複該條目。
- 4、VBoot 2.0 不支援 verifyatboot,無論是否啟用了提前裝載。
- 5、必須在 kernel_cmdline 中使用 androidboot.veritymode 選項指定驗證分區的真實模式/狀态(現有要求)。確定包含以下 AVB 修複程式:
- https://android-review.googlesource.com/#/q/topic:libavb-api-rev-for-verity-modes+(status:open+OR+status:merged)
- https://android-review.googlesource.com/#/c/394215/
7、提前裝載裝置樹,VBoot 2.0
VBoot 2.0 裝置樹中的配置與 VBoot 1.0 中的大緻相同,但還有以下幾項不同之處:
- 1、fsmgr_flag 由 verify 變為 avb。
- 2、包含 AVB 中繼資料的所有分區都必須位于裝置樹的 VBMeta 條目中,即使相應的分區并非提前裝載的分區(如 /boot)也是如此。
示例:N5X 上的 /system 和 /vendor
下面的示例顯示的是在 Nexus 5X 上為 system 和 vendor 分區提前裝載裝置樹。注意:
- /system 使用 AVB 進行裝載,且 /vendor 的裝載不需要進行完整性驗證。
- 由于 Nexus 5X 沒有 /vbmeta 分區,是以頂層 vbmeta 位于 /boot 分區的末端(如需了解詳情,請參閱 AOSP 變更清單)。
/ {
firmware {
android {
compatible = "android,firmware";
vbmeta {
compatible = "android,vbmeta";
parts = "boot,system,vendor";
};
fstab {
compatible = "android,fstab";
system {
compatible = "android,system";
dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/system";
type = "ext4";
mnt_flags = "ro,barrier=1,inode_readahead_blks=8";
fsmgr_flags = "wait,avb";
};
vendor {
compatible = "android,vendor";
dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor";
type = "ext4";
mnt_flags = "ro,barrier=1,inode_readahead_blks=8";
fsmgr_flags = "wait";
};
};
};
};
};
示例:Pixel 上的 /vendor
下面的示例顯示的是在 Pixel 上提前裝載 /vendor。注意:
- 很多分區都是在 vbmeta 條目中指定的,因為這些分區受 AVB 保護。
- 請務必包含所有 AVB 分區,即使僅提前裝載了 /vendor 也是如此。
- 請務必為 A/B 分區添加 slotselect。
/ {
vbmeta {
compatible = "android,vbmeta";
parts = "vbmeta,boot,system,vendor,dtbo";
};
firmware {
android {
compatible = "android,firmware";
fstab {
compatible = "android,fstab";
vendor {
compatible = "android,vendor";
dev = "/dev/block/platform/soc/624000.ufshc/by-name/vendor";
type = "ext4";
mnt_flags = "ro,barrier=1,discard";
fsmgr_flags = "wait,slotselect,avb";
};
};
};
};
};