儘早掛載分區

啟用 Treble 的裝置必須啟用第一階段掛載,以確保init可以載入分佈在systemvendor分割區中的安全增強型 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條目指定,則可以省略此標誌的參數。

以下範例顯示了將systemvendorproduct分區設定為邏輯(動態)分區的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 提前掛載分割區的要求包括:

  1. 裝置節點路徑必須在fstab和 devicetree 條目中使用其by-name連結。例如,不要使用/dev/block/mmcblk0pX指定分區,而是確保分區已命名且設備節點為/dev/block/…./by-name/{system,vendor,odm}
  2. 產品的裝置配置中(即device/ oem / project /device.mk )中為PRODUCT_{SYSTEM,VENDOR}_VERITY_PARTITIONCUSTOM_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
    
  3. 透過設備樹覆蓋提供的條目不得在fstab檔案片段中重複。例如,在裝置樹中指定要掛載/vendor條目時, fstab檔案不得重複該條目。
  4. 不得提前安裝需要verifyatboot的分割區(不支援這樣做)。
  5. 必須使用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必須是 Android fs_mgr flags標誌清單(如fstab檔案所示)
  • A/B 分割區必須具有slotselect fs_mgr選項。
  • 啟用 dm-verity 的分割區必須具有verify fs_mgr選項。

範例: N6P 上的 /system 和 /vendor

以下範例顯示了 Nexus 6P 上systemvendor分區的 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 提前掛載分割區的要求是:

  1. 裝置節點路徑必須在fstab和 devicetree 條目中使用其by-name連結。例如,不要使用/dev/block/mmcblk0pX指定分區,而是確保分區已命名且設備節點為/dev/block/…./by-name/{system,vendor,odm}
  2. VBoot 2.0 不需要 VBoot 1.0 的建置系統變數(例如PRODUCT_{SYSTEM,VENDOR}_VERITY_PARTITIONCUSTOM_IMAGE_VERITY_BLOCK_DEVICE )。相反,應該定義 VBoot 2.0 中引入的建置變數(包括BOARD_AVB_ENABLE := true );有關完整配置,請參閱AVB 的建置系統整合
  3. 透過設備樹覆蓋提供的條目不得在fstab檔案片段中重複。例如,如果您指定要在裝置樹中掛載/vendor條目,則fstab檔案不得重複該條目。
  4. VBoot 2.0 不支援verifyatboot ,無論是否啟用早期安裝。
  5. 必須使用androidboot.veritymode選項(現有要求)在kernel_cmdline中指定已驗證分區的驗證模式/狀態。確保包含以下針對 AVB 的修復:

儘早掛載 devicetree,VBoot 2.0

VBoot 2.0 的 devicetree 中的配置與VBoot 1.0中的配置相同,但有以下例外:

  • fsmgr_flagverify切換到avb
  • 所有具有 AVB 元資料的分割區都必須位於裝置樹的 VBMeta 條目中,即使該分割區沒有事先安裝(例如/boot )。

範例: N5X 上的 /system 和 /vendor

以下範例顯示了 Nexus 5X 上systemvendor分割區的 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";
            };
          };
        };
      };
    };