分区布局

在 Android 10 中,根文件系统已不再包含在 ramdisk.img 中,而是合并到了 system.img(即在创建 system.img 时始终将 BOARD_BUILD_SYSTEM_ROOT_IMAGE 视为已设置)。搭载 Android 10 的设备:

  • 使用 system-as-root 分区布局(由编译流程自动执行,且不可选择更改这种行为)。
  • 必须使用 ramdisk,这对于 dm-linear 而言是必需的。
  • 必须将 BOARD_BUILD_SYSTEM_ROOT_IMAGE 设为 false。此设置仅用于区分使用 ramdisk 的设备和没有使用 ramdisk 的设备(这类设备直接装载 system.img)。

system-as-root 配置的含义在 Android 9 和 Android 10 之间有所不同。在 Android 9 system-as-root 配置中,BOARD_BUILD_SYSTEM_ROOT_IMAGE 设为 true,这会强制编译将根文件系统合并到 system.img 中,然后将 system.img 作为根文件系统 (rootfs) 进行装载。此配置对于搭载 Android 9 的设备是强制性的,但对于升级到 Android 9 及搭载较低 Android 版本的设备是可选的。在 Android 10 system-as-root 配置中,编译始终将 $TARGET_SYSTEM_OUT$TARGET_ROOT_OUT 合并到 system.img 中;此配置是搭载 Android 10 的所有设备的默认行为。

Android 10 进行了进一步更改来支持动态分区,这是一种可以通过无线下载 (OTA) 更新来创建、销毁分区或调整分区大小的用户空间分区系统。作为此更改的一部分,Linux 内核无法再在搭载 Android 10 的设备上装载逻辑系统分区,因此该操作由第一阶段的 init 处理。

以下部分介绍了系统专用 OTA 的 system-as-root 要求,提供了有关将设备更新为使用 system-as-root 的指导(包括分区布局更改以及 dm-verity 内核要求),并详细介绍了 Android 10 中对 ramdisk 的更改

关于系统专用 OTA

系统专用 OTA 需要 system-as-root 分区布局,可以让 Android 版本在不更改其他分区的情况下更新 system.img。搭载 Android 10 的所有设备都必须使用 system-as-root 分区布局来启用系统专用 OTA。

  • A/B 设备(将 system 分区作为 rootfs 进行装载)已经使用 system-as-root,不需要进行更改即可支持系统 OTA。
  • 非 A/B 设备(在 /system 装载 system 分区)必须更新为使用 system-as-root 分区布局才可支持系统 OTA。

如需详细了解 A/B 设备和非 A/B 设备,请参阅 A/B(无缝)系统更新

更新为 system-as-root

要将非 A/B 设备更新为使用 system-as-root,您必须更新 boot.imgsystem.img 的分区架构、设置 dm-verity,并移除特定于设备的根文件夹中的任何启动依赖项。

更新分区

不同于将 /boot 改为 recovery 分区的 A/B 设备,非 A/B 设备必须保留单独的 /recovery 分区,因为它们没有后备插槽分区(例如从 boot_aboot_b)。如果在非 A/B 设备上移除 /recovery 并使其与 A/B 架构类似,那么在 /boot 分区更新失败时,恢复模式可能无法正常工作。因此,在非 A/B 设备上,必须/recovery 分区与 /boot 分区分开,这意味着将继续延迟更新恢复映像(即和搭载 Android 9 之前版本的设备一样)。

下表列出了非 A/B 设备在使用 Android 9 前后的映像分区差异。

映像 ramdisk(Android 9 之前) system-as-root(Android 9 之后)
boot.img 包含内核和 ramdisk.img

ramdisk.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/ (mount point)
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
仅包含正常启动内核。
recovery.img 包含恢复内核和恢复 ramdisk.img
system.img 包含以下内容:

system.img
  -/
    - bin/
    - etc
    - vendor -> /vendor
    - ...
包含原始 system.imgramdisk.img 的合并内容:

system.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/
      - bin/
      - etc/
      - vendor -> /vendor
      - ...
    - vendor/ (mount point)
    - odm/ (mount point)
    ...

分区本身不会更改;ramdisk 和 system-as-root 都使用以下分区架构:

  • /boot
  • /system
  • /recovery
  • /vendor 等

设置 dm-verity

在 system-as-root 中,内核必须使用 dm-verity/(装载点)下装载 system.img。AOSP 支持 system.img 的下列 dm-verity 实现。

vboot 1.0

对于 vboot 1.0,内核必须在 /system 上解析 Android 专用元数据,然后转换为 dm-verity 参数以设置 dm-verity(需要这些内核补丁程序)。下面的示例显示了内核命令行中 system-as-root 的 dm-verity 相关设置:

ro root=/dev/dm-0 rootwait skip_initramfs init=/init
dm="system none ro,0 1 android-verity /dev/sda34"
veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f

vboot 2.0

对于 vboot 2.0 (AVB),引导加载程序必须先整合 external/avb/libavb,然后 external/avb/libavb 会解析 /system哈希树描述符,再将解析结果转换为 dm-verity 参数,最后通过内核命令行将这些参数传递给内核。(/system 的哈希树描述符可能位于 /vbmeta/system 本身上)。

vboot 2.0 需要以下内核补丁程序:

下面的示例显示了内核命令行中 system-as-root 的 dm-verity 相关设置:

ro root=/dev/dm-0 rootwait  skip_initramfs init=/init

dm="1 vroot none ro 1,0 5159992 verity 1
PARTUUID=00000016-0000-0000-0000-000000000000
PARTUUID=00000016-0000-0000-0000-000000000000 4096 4096 644999 644999
sha1 d80b4a8be3b58a8ab86fad1b498640892d4843a2
8d08feed2f55c418fb63447fec0d32b1b107e42c 10 restart_on_corruption
ignore_zero_blocks use_fec_from_device
PARTUUID=00000016-0000-0000-0000-000000000000 fec_roots 2 fec_blocks
650080 fec_start 650080"

使用特定于设备的根文件夹

使用 system-as-root 时,在设备上刷写常规系统映像 (GSI) 之后(以及在运行供应商测试套件测试之前),任何通过 BOARD_ROOT_EXTRA_FOLDERS 添加的特定于设备的根文件夹都会消失,因为整个根目录内容已被 system-as-root GSI 取代。如果对特定于设备的根文件夹有依赖性(例如将此类文件夹用作装载点),则移除这些文件夹可能会导致设备无法启动。

为避免此问题,请勿使用 BOARD_ROOT_EXTRA_FOLDERS 来添加特定于设备的根文件夹。如果需要指定特定于设备的装载点,请使用 /mnt/vendor/<mount point>(已添加到这些更改列表中)。这些特定于供应商的装载点可在 fstab 设备树(适用于第一阶段的装载)和 /vendor/etc/fstab.{ro.hardware} 文件中直接指定,而无需进行额外设置(因为 fs_mgr 将在 /mnt/vendor/* 下自动创建它们)。

Ramdisk

在 Android 10 中,第一阶段 ramdisk 包含第一阶段 init 二进制文件(按照 fstab 条目的指定执行早期装载)和供应商 fstab 文件。(与在 Android 9 中一样,system.img 包含 $TARGET_ROOT_OUT 的内容。)

  • 对于具有 boot-ramdisk 的设备(非 A/B),第一阶段 init 是位于 /init 的静态可执行文件。这些设备将 system.img 作为 /system 进行装载,然后执行切换根操作将装载从 /system 移动到 /。装载完成后,ramdisk 的内容将会释放。
  • 对于将恢复用作 ramdisk 的设备,第一阶段 init 位于恢复 ramdisk 中的 /init。这些设备首先将根切换到 /first_stage_ramdisk,以便从环境中移除恢复组件,然后执行与具有 boot-ramdisk 的设备一样的操作(即,将 system.img 作为 /system 进行装载,切换根以将该装载移动到 /,然后在装载完成后释放 ramdisk 内容)。如果内核命令行中存在 androidboot.force_normal_boot=1,则设备会正常启动(启动到 Android)而不是启动到恢复模式。

在第一阶段 init 完成后,它会使用 selinux_setup 参数执行 /system/bin/init,以便编译 SELinux 并将其加载到系统中。最后,init 会使用 second_stage 参数再次执行 /system/bin/init。此时,init 的主要阶段将会运行,并使用 init.rc 脚本继续执行启动过程。

分区布局(非 A/B 设备)

下面的部分详细介绍了非 A/B 设备在使用 Android 10 前后的分区布局差异。

boot.img

Ramdisk
(Android 8.x 及更低版本)
System as root
(Android 9)
Ramdisk
(Android 10)
包含内核和 ramdisk.img


ramdisk.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/ (mount point)
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
    
仅包含正常启动内核。 包含内核和 ramdisk.img


ramdisk.img
  -/
    - init
    - vendor fstab files
    - system/ (mount point)
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
    

recovery.img

Ramdisk
(Android 8.x 及更低版本)
System as root
(Android 9)
Ramdisk
(Android 10)
包含恢复内核和恢复 ramdisk.img

system.img

Ramdisk
(Android 8.x 及更低版本)
System as root
(Android 9)
Ramdisk
(Android 10)
包含 system.img



system.img
  -/
    - bin/
    - etc
    - vendor -> /vendor
    - ...
   
包含 $TARGET_SYSTEM_OUT$TARGET_ROOT_OUT 的合并内容。


system.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/
      - bin/
      - etc/
      - vendor -> /vendor
      - ...
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
    
包含 $TARGET_SYSTEM_OUT$TARGET_ROOT_OUT 的合并内容。


system.img
  -/
    - init.rc
    - init -> /system/bin/init
    - etc -> /system/etc
    - system/
      - bin/
      - etc/
      - vendor -> /vendor
      - ...
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
    

分区布局(A/B 设备)

下面的部分详细介绍了 A/B 设备在使用 Android 10 前后的分区布局差异。

boot.img

System as root
(Android 9)
Ramdisk
(Android 10)
包含正常启动内核和 recovery-ramdisk (BOARD_USES_RECOVERY_AS_BOOT := true)。

Recovery-ramdisk 仅用于启动到恢复模式。
包含正常启动内核和 recovery-ramdisk (BOARD_USES_RECOVERY_AS_BOOT := true)。

Recovery-ramdisk 用于启动到恢复模式和 Android。

ramdisk.img
  -/
    - init -> /system/bin/init
    - first_stage_ramdisk
       - vendor fstab files
    - etc -> /system/etc
    - system/ (mount point)
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
    

system.img

System as root
(Android 9)
Ramdisk
(Android 10)
包含 $TARGET_SYSTEM_OUT$TARGET_ROOT_OUT 的合并内容。


system.img
  -/
    - init.rc
    - init -> /system/bin/init
    - etc -> /system/etc
    - system/
      - bin/
      - etc/
      - vendor -> /vendor
      - ...
    - vendor/ (mount point)
    - odm/ (mount point)
    ...