パーティションの早期マウント

Treble 対応のデバイスでは、第 1 ステージのマウントを有効にして、system パーティションと vendor パーティションに散在している Security-Enhanced Linux(SELinux)のポリシー フラグメントを init が読み込めるようにする必要があります。また、このアクセス権により、カーネルブート後すぐにカーネル モジュールの読み込みができるようになります。

早期マウントを行うには、モジュールが存在するファイルシステムに Android がアクセスできる必要があります。Android 8.0 以上では、init の第 1 ステージの時点から(つまり SElinux の初期化前に)/system/vendor/odm をマウントできます。

fstab エントリ

Android 9 以下のデバイスでは、デバイスツリー オーバーレイ(DTO)を使用して早期マウント パーティションの fstab エントリを指定できます。Android 10 以上のデバイスでは、第 1 ステージの RAM ディスクにある fstab ファイルを使用して、早期マウントするパーティションの fstab エントリを指定する必要があります。Android 10 では、fstab ファイルで使用する以下の fs_mgr フラグが導入されています。

  • first_stage_mount: パーティションを第 1 ステージの init でマウントするように指定します。
  • logical: 動的パーティションを指定します。
  • avb=vbmeta-partition-name: vbmeta パーティションを指定します。第 1 ステージの init は、他のパーティションをマウントする前に、このパーティションを初期化します。このフラグの引数は、このエントリの vbmeta パーティションが、前の行の fstab エントリですでに指定されている場合、省略できます。

次に示す fstab エントリの例では、system パーティション、vendor パーティション、product パーティションを論理(動的)パーティションに設定します。

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

この例では、vendor は fs_mgr フラグの avb=vbmeta を使用して vbmeta パーティションを指定していますが、product では、すでに vendor でパーティションのリストに vbmeta が追加されているため vbmeta を省略しています。

Android 10 以上を搭載するデバイスでは、fstab ファイルを RAM ディスクと vendor パーティションに置く必要があります。

RAM ディスク

RAM ディスク内での fstab ファイルの場所は、デバイスが RAM ディスクを使用する方法によって異なります。

ブート用 RAM ディスクがあるデバイスでは、fstab ファイルをブート用 RAM ディスクのルートに置きます。デバイスにブート用 RAM ディスクとリカバリ用 RAM ディスクの両方がある場合は、リカバリ用 RAM ディスクに対する変更は必要ありません。例を次に示します:

PRODUCT_COPY_FILES +=  device/google/<product-name>/fstab.hardware:$(TARGET_COPY_OUT_RAMDISK)/fstab.$(PRODUCT_PLATFORM)

リカバリを RAM ディスクとして使用するデバイスでは、カーネル コマンドライン パラメータ androidboot.force_normal_boot=1 を使用して、Android をブートするか、リカバリを始めるかを指定する必要があります。Android 12 以降を搭載し、カーネル バージョン 5.10 以降を使用するデバイスでは、bootconfig を使用して androidboot.force_normal_boot=1 パラメータを渡す必要があります。これらのデバイスでは、第 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)

vendor

すべてのデバイスで、fstab ファイルを /vendor/etc にコピーしておく必要があります。これは、第 1 ステージの 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 用のデバイス設定にある(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 ファイル フラグメントでは指定しないでください。たとえば、devicetree で /vendor をマウントするエントリを指定した場合、fstab ファイルでそのエントリを指定しないでください。
  4. verifyatboot の必要なパーティションは、早期マウントしないでください(サポートされていません)。
  5. 検証されたパーティションの verity モードと verity ステータスは、androidboot.veritymode オプションを使用して kernel_cmdline で指定してください(既存の要件)。

devicetree の早期マウント、VBoot 1.0

Android 8.x 以上では、init が devicetree を解析し、fstab エントリを作成して第 1 ステージでパーティションを早期マウントします。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 オプションを指定する必要があります。

例: 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 Verified Boot(AVB)のことです。VBoot 2.0 でパーティションを早期マウントするための要件は次のとおりです。

  1. デバイスノードのパスでは、その by-name シンボリック リンクを fstab エントリと devicetree エントリで使用する必要があります。たとえば、/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 ファイル フラグメントでは指定しないでください。たとえば、devicetree で /vendor をマウントするエントリを指定した場合、fstab ファイルでそのエントリを指定しないでください。
  4. verifyatboot は、早期マウントが有効か無効かにかかわらず、VBoot 2.0 ではサポートされていません。
  5. 検証されたパーティションの verity モードと verity ステータスは、androidboot.veritymode オプションを使用して kernel_cmdline で指定してください(既存の要件)。必ず、AVB に対する次の修正を行ってください。

devicetree の早期マウント、VBoot 2.0

VBoot 2.0 用の devicetree の設定は VBoot 1.0 の設定とほぼ同じですが、以下の例外があります。

  • fsmgr_flag は、verify から avb に変更されました。
  • パーティションが早期マウントされていない場合でも、AVB メタデータを持つすべてのパーティションは devicetree の 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 によって保護されているためです。
  • /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";
            };
          };
        };
      };
    };