啟用 Treble 的裝置必須啟用第一階段掛載,以確保init
可以載入分佈在system
和vendor
分割區中的安全增強型 Linux (SELinux)策略片段。此存取還可以在核心啟動後儘快載入核心模組。
若要執行早期安裝,Android 必須有權存取模組所在的檔案系統。 Android 8.0 及更高版本支援早在init
的第一階段(即初始化 SElinux 之前)掛載/system
、 /vendor
或/odm
。
Fstab 條目
在 Android 9 及更低版本中,裝置可以使用裝置樹覆蓋 (DTO)為早期安裝的分割區指定fstab
條目。在 Android 10 及更高版本中,裝置必須使用第一階段ramdisk中的fstab
檔案為早期安裝的分割區指定fstab
條目。 Android 10 引入了以下fs_mgr
標誌以在fstab
檔案中使用:
-
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
分區。
記憶體磁碟
ramdisk 中的fstab
檔案位置取決於裝置使用 ramdisk 的方式。
具有啟動 ramdisk 的裝置必須將fstab
檔案放置在啟動 ramdisk 根目錄中。如果裝置同時具有啟動 ramdisk 和復原 ramdisk,則無需對復原 ramdisk 進行任何變更。例子:
PRODUCT_COPY_FILES += device/google/<product-name>/fstab.hardware:$(TARGET_COPY_OUT_RAMDISK)/fstab.$(PRODUCT_PLATFORM)
使用 recovery 作為 ramdisk 的裝置必須使用核心命令列參數androidboot.force_normal_boot=1
來決定是啟動到 Android 還是繼續啟動到 recovery。使用 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)
小販
所有裝置都必須將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)
儘早掛載分割區,VBoot 1.0
使用 VBoot 1.0 提前掛載分割區的要求包括:
- 裝置節點路徑必須在
fstab
和 devicetree 條目中使用其by-name
連結。例如,不要使用/dev/block/mmcblk0pX
指定分區,而是確保分區已命名且設備節點為/dev/block/…./by-name/{system,vendor,odm}
。 - 產品的裝置配置中(即
device/ oem / project /device.mk
)中為PRODUCT_{SYSTEM,VENDOR}_VERITY_PARTITION
和CUSTOM_IMAGE_VERITY_BLOCK_DEVICE
指定的路徑必須與fstab
/devicetree 中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
- 透過設備樹覆蓋提供的條目不得在
fstab
檔案片段中重複。例如,在裝置樹中指定要掛載/vendor
條目時,fstab
檔案不得重複該條目。 - 不得提前安裝需要
verifyatboot
的分割區(不支援這樣做)。 - 必須使用
androidboot.veritymode
選項(現有要求)在kernel_cmdline
中指定已驗證分區的驗證模式/狀態。
儘早掛載 devicetree,VBoot 1.0
在 Android 8.x 及更高版本中, init
會解析裝置樹並建立fstab
條目,以便在第一階段儘早掛載分割區。 fstab
條目採用以下形式:
src mnt_point type mnt_flags fs_mgr_flags
Devicetree 屬性被定義為模仿該格式:
-
fstab
條目必須位於裝置樹中的/firmware/android/fstab
下,且必須將相容字串設為android,fstab
。 -
/firmware/android/fstab
下的每個節點被視為單一早期安裝fstab
條目。節點必須定義下列屬性:-
dev
必須指向代表分割區by-name
裝置節點 type
必須是檔案系統類型(如fstab
檔案中所示)-
mnt_flags
必須是以逗號分隔的掛載標誌清單(如fstab
檔案所示) -
fsmgr_flags
必須是 Androidfs_mgr flags
標誌清單(如fstab
檔案所示)
-
- A/B 分割區必須具有
slotselect fs_mgr
選項。 - 啟用 dm-verity 的分割區必須具有
verify fs_mgr
選項。
範例: N6P 上的 /system 和 /vendor
以下範例顯示了 Nexus 6P 上system
和vendor
分區的 devicetree 早期掛載:
/ { 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
的 devicetree 早期掛載(請記得為受 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"; }; }; }; }; };
儘早掛載分割區,VBoot 2.0
VBoot 2.0 是Android 驗證啟動 (AVB) 。使用 VBoot 2.0 提前掛載分割區的要求是:
- 裝置節點路徑必須在
fstab
和 devicetree 條目中使用其by-name
連結。例如,不要使用/dev/block/mmcblk0pX
指定分區,而是確保分區已命名且設備節點為/dev/block/…./by-name/{system,vendor,odm}
。 - VBoot 2.0 不需要 VBoot 1.0 的建置系統變數(例如
PRODUCT_{SYSTEM,VENDOR}_VERITY_PARTITION
和CUSTOM_IMAGE_VERITY_BLOCK_DEVICE
)。相反,應該定義 VBoot 2.0 中引入的建置變數(包括BOARD_AVB_ENABLE := true
);有關完整配置,請參閱AVB 的建置系統整合。 - 透過設備樹覆蓋提供的條目不得在
fstab
檔案片段中重複。例如,如果您指定要在裝置樹中掛載/vendor
條目,則fstab
檔案不得重複該條目。 - VBoot 2.0 不支援
verifyatboot
,無論是否啟用早期安裝。 - 必須使用
androidboot.veritymode
選項(現有要求)在kernel_cmdline
中指定已驗證分區的驗證模式/狀態。確保包含以下針對 AVB 的修復:
儘早掛載 devicetree,VBoot 2.0
VBoot 2.0 的 devicetree 中的配置與VBoot 1.0中的配置相同,但有以下例外:
-
fsmgr_flag
從verify
切換到avb
。 - 所有具有 AVB 元資料的分割區都必須位於裝置樹的 VBMeta 條目中,即使該分割區沒有事先安裝(例如
/boot
)。
範例: N5X 上的 /system 和 /vendor
以下範例顯示了 Nexus 5X 上system
和vendor
分割區的 devicetree 早期安裝。注意:
-
/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"; }; }; }; }; };