儘早掛載分區

啟用 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 並執行 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 提前掛載分區的要求包括:

  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. 驗證分區的驗證模式/狀態必須在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必須是 Android fs_mgr flags的列表(如在fstab文件中)
  • A/B 分區必須有一個slotselect fs_mgr選項。
  • 啟用 dm-verity 的分區必須有一個verify fs_mgr選項。

示例: N6P 上的 /system 和 /vendor

以下示例顯示了 Nexus 6P 上systemvendor分區的設備樹早期掛載:

/ {
  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 提前掛載分區的要求是:

  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. 驗證分區的驗證模式/狀態必須在kernel_cmdline中使用androidboot.veritymode選項(現有要求)指定。確保包含以下 AVB 修復:

儘早掛載設備樹,VBoot 2.0

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

  • fsmgr_flagverify切換到avb
  • 所有具有 AVB 元數據的分區都必須位於設備樹的 VBMeta 條目中,即使該分區沒有提前掛載(例如/boot )。

示例: N5X 上的 /system 和 /vendor

以下示例顯示了 Nexus 5X 上systemvendor分區的設備樹早期掛載。注意:

  • /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";
            };
          };
        };
      };
    };