提早掛接分區

支援 Treble 的裝置必須啟用第一個階段掛架,才能確保 init 可以載入 Security-Enhanced Linux (SELinux) 政策片段分散在 systemvendor 個分區。此存取權也會允許載入核心 模組。

如要執行早期掛接,Android 必須能夠存取 模組所在的位置Android 8.0 以上版本支援掛接功能 提前 /system/vendor/odm init 的第一個階段 (也就是 SElinux 初始化之前)。

Fstab 項目

在 Android 9 以下版本中,裝置可以指定 fstab 項目: 早期掛接的分區 (使用裝置樹狀結構) 疊加層 (DTO):在 Android 10 以上版本中 裝置必須為早期掛接的分區指定 fstab 個項目 在第一個階段使用 fstab 檔案 ramdisk。Android 版 10 推出了下列 fs_mgr 標記 以便用於 fstab 檔案:

  • first_stage_mount 表示已掛接分區 第一個階段 init
  • logical 表示這是 動態分區
  • avb=vbmeta-partition-name 會指定 vbmeta 個分區。第一個階段 init 會初始化這個分區 再掛接其他分區如果發生下列情況,可以省略這個旗標的引數: 項目的 vbmeta 分區已由 上一行中另一個 fstab 項目

以下範例顯示fstab要設定 systemvendorproduct 分區 邏輯 (動態) 分區

#<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

在此範例中,廠商使用 vbmeta 指定分區 fs_mgr 旗標 avb=vbmeta,但 product 會省略 vbmeta 引數,因為供應商已新增 vbmeta 新增至分區清單。

如果裝置搭載 Android 10 以上版本,就必須將 ramdisk 和 vendor 中的 fstab 檔案

Ramdisk

ramdisk 中的 fstab 檔案位置取決於裝置 使用了 ramdisk。

搭載開機磁碟的裝置必須放置 fstab 寫入 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)

供應商

所有裝置都必須將 fstab 檔案副本複製到 /vendor/etc。這是因為第一階段 init 會釋放 完成分區的早期掛接作業後,RAM 會 切換根作業,將掛接位置 (/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. 裝置節點路徑必須在by-name fstab 和 devicetree 項目。舉例來說 使用 /dev/block/mmcblk0pX 建立多個分區,請確保這些分區 並使用裝置節點 /dev/block/…./by-name/{system,vendor,odm}
  2. 提供給 PRODUCT_{SYSTEM,VENDOR}_VERITY_PARTITION 和 以下項目的裝置設定中有 CUSTOM_IMAGE_VERITY_BLOCK_DEVICEdevice/oem/project/device.mk) 必須與 設定相應的區塊裝置節點by-name fstab/devicetree 項目。範例:
    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 檔案片段。舉例來說,指定項目至 在 devicetree (fstab 檔案) 中掛接 /vendor 請勿重複輸入相同的項目
  4. 不得使用 verifyatboot 的分區 提早掛接 (因為不支援此類型)。
  5. 已驗證分區的驗證模式/狀態必須在 使用「androidboot.veritymode」選項的kernel_cmdline (現有規定)。

盡早掛接 devicetree,VBoot 1.0

在 Android 8.x 以上版本中,init 會剖析 devicetree 並 建立 fstab 項目以提早掛接分區 第一階段fstab 項目採用以下格式:

src mnt_point type mnt_flags fs_mgr_flags

Devicetree 屬性的定義是模仿下列格式:

  • fstab 個項目不得超過 devicetree 中的 /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 如果有需要 SQL 指令的分析工作負載 則 BigQuery 可能是最佳選擇

例如:/system 和 N6P 上的 /vendor

以下範例顯示 system 的 devicetree 早期掛架 Nexus 6P 上的 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 on Pixel

以下範例顯示 /vendor 的 devicetree 早期掛架 (請記得新增 slotselect 做為分區, A/B):

/ {
  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. 裝置節點路徑必須在by-name fstab 和 devicetree 項目。舉例來說 使用 /dev/block/mmcblk0pX 建立多個分區,請確保這些分區 檔案名稱,且裝置節點為 /dev/block/…./by-name/{system,vendor,odm}
  2. 建構系統變數 (例如 「PRODUCT_{SYSTEM,VENDOR}_VERITY_PARTITION」和 CUSTOM_IMAGE_VERITY_BLOCK_DEVICE),並非用於 VBoot 1.0 VBoot 2.0 的必要性請改為在 VBoot 2.0 中導入的建構變數 (包括 BOARD_AVB_ENABLE := true) 必須定義。的 完整設定,請參閱 建構 AVB 系統整合
  3. 透過裝置樹狀結構疊加層提供的項目,不得在 fstab 檔案片段。舉例來說,如果您指定項目 在 devicetree (fstab 檔案) 中掛接 /vendor 請勿重複輸入相同的項目
  4. 無論是早期掛接,VBoot 2.0 都不支援 verifyatboot 已啟用與否
  5. 已驗證分區的驗證模式/狀態必須在 使用androidboot.veritymodekernel_cmdline 選項 (現有規定)。請務必為 AVB:

盡早掛接 devicetree,VBoot 2.0

VBoot 2.0 的 devicetree 設定與 VBoot 1.0,搭配 例外狀況:

  • fsmgr_flag已從 verify 切換為 avb
  • 所有具有 AVB 中繼資料的分區,都必須位於 裝置樹狀結構,即使分區未提早安裝 (例如 /boot)。

例如:/system 和 /vendor 上的 /vendor

以下範例顯示 Nexus 5X 上的 systemvendor 分區。請注意:

  • /system 已與 AVB 掛接,/vendor 為 ,未進行完整性驗證。
  • 由於 Nexus 5X 沒有 /vbmeta 分區,因此頂層 vbmeta 位於 /boot 分區的結尾 (詳情請參閱 請參閱 Android 開放原始碼計畫變更清單)。
    / {
      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 on Pixel

以下範例顯示如何在 Pixel 上提早安裝 /vendor。 請注意:

  • vbmeta 項目中指定了更多分區,因為這些分區 是 受到 AVB 保護
  • 即使只有 /vendor 是,也必須納入所有 AVB 分區 及早安裝
  • 請記得為受限於 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";
            };
          };
        };
      };
    };