啟用 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 並執行 switch root 操作以將/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
分區不得提前掛載(不支持這樣做)。 - 驗證分區的驗證模式/狀態必須在
kernel_cmdline
中使用androidboot.veritymode
選項(現有要求)指定。
儘早掛載設備樹,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
分區的設備樹早期掛載:
/ { 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"; }; }; }; }; };
示例:像素上的 /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
,無論是否啟用了早期掛載。 - 驗證分區的驗證模式/狀態必須在
kernel_cmdline
中使用androidboot.veritymode
選項(現有要求)指定。確保包含以下 AVB 修復:
儘早掛載設備樹,VBoot 2.0
VBoot 2.0 的 devicetree 中的配置與VBoot 1.0中的配置相同,但有以下例外:
-
fsmgr_flag
從verify
切換到avb
。 - 所有具有 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"; }; }; }; }; };
示例:像素上的 /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"; }; }; }; }; };