通用启动分区

在 Android 12 中,通用 boot 镜像(称为通用内核镜像 (GKI))包含通用 ramdisk 和 GKI 内核。

对于搭载 Android 13 发布的设备,通用 ramdisk 将从 boot 镜像中移除,并放置在单独的 init_boot 镜像中。此更改使 boot 镜像仅包含 GKI 内核。

对于继续使用 Android 12 或更旧内核版本的升级设备,通用 ramdisk 仍保留在原来的位置,无需新的 init_boot 镜像。

要构建通用 ramdisk,请将供应商特定的资源移出 ramdisk,以便通用 ramdisk 仅包含第一阶段 init 和包含时间戳信息的属性文件。

在以下设备上:

  • 不使用专用 recovery 分区,所有恢复位都从通用 ramdisk 移至 vendor_boot ramdisk。

  • 使用专用 recovery 分区,则无需更改 recovery ramdisk,因为 recovery ramdisk 是自包含的。

架构

以下图表说明了运行 Android 12 及更高版本的设备的架构。搭载 Android 13 推出的设备具有新的 init_boot 镜像,其中包含通用 ramdisk。从 Android 12 升级到 Android 13 的设备使用的架构与 Android 12 相同。

搭载 Android 13 推出,无专用恢复

Launch/upgrade device, GKI, no dedicated recovery

图 1. 搭载或升级到 Android 13 的设备,使用 GKI,无专用恢复。

搭载 Android 13 推出,专用和 A/B 恢复(专用 ramdisk)

Launch/upgrade device, GKI, dedicated and A/B recovery

图 2. 搭载或升级到 Android 13 的设备,使用 GKI,专用和 A/B 恢复。

如果设备具有 recovery_arecovery_b 分区,请参考此图。

搭载 Android 13 推出,专用和非 A/B 恢复(专用 ramdisk)

Launch/upgrade device, GKI, dedicated and non-A/B recovery

图 3. 搭载或升级到 Android 13 的设备,使用 GKI,专用和非 A/B 恢复。

如果设备具有名为 recovery 且没有槽后缀的分区,请参考此图。

搭载或升级到 Android 12,无专用恢复

Launch/upgrade device, GKI, no dedicated recovery

图 4. 搭载或升级到 Android 12 的设备,使用 GKI,无专用恢复。

搭载或升级到 Android 12,专用和 A/B 恢复(专用 ramdisk)

Launch/upgrade device, GKI, dedicated and A/B recovery

图 5. 搭载或升级到 Android 12 的设备,使用 GKI,专用和 A/B 恢复。

如果设备具有 recovery_arecovery_b 分区,请参考此图。

搭载或升级到 Android 12,专用和非 A/B 恢复(专用 ramdisk)

Launch/upgrade device, GKI, dedicated and non-A/B recovery

图 6. 搭载或升级到 Android 12 的设备,使用 GKI,专用和非 A/B 恢复。

如果设备具有名为 recovery 且没有槽后缀的分区,请参考此图。

升级到 Android 12,recovery-as-boot(recovery-as-ramdisk)

Launch/upgrade device, no GKI, recovery-as-boot

图 7. 升级到 Android 12 的设备,无 GKI,recovery-as-boot。

升级到 Android 12,专用恢复(专用 ramdisk)

Launch/upgrade device, no GKI, dedicated recovery

图 8. 升级到 Android 12 的设备,无 GKI,专用恢复。

启动镜像内容

Android 启动镜像包含以下内容。

  • init_boot 镜像为搭载 Android 13 推出的设备添加

    • 标头版本 V4
    • 通用 ramdisk 镜像
  • 通用 boot 镜像

    • 标头版本 V3V4
      • 用于 GKI boot.img 认证的 boot_signature(仅限 v4)。经过认证的 GKI boot.img 未针对已验证启动进行签名。OEM 仍必须使用设备特定的 AVB 密钥对预构建的 boot.img 进行签名。
      • 通用 cmdline (GENERIC_KERNEL_CMDLINE)
      • GKI 内核
    • 通用 ramdisk 镜像
      • 仅包含在 Android 12 及更早版本的 boot 镜像中
  • vendor_boot 镜像(有关详情,请参阅 供应商启动分区

    • vendor_boot 标头
      • 设备特定的 cmdline (BOARD_KERNEL_CMDLINE)
    • vendor_boot ramdisk 镜像
      • lib/modules
      • 恢复资源(如果没有专用恢复)
    • dtb 镜像
  • recovery 镜像

    • 标头版本 V2
      • 设备特定的恢复 cmdline(如果需要)
      • 对于非 A/B 恢复分区,标头的内容必须是独立的;请参阅 恢复镜像。例如
      • cmdline 未连接到 bootvendor_boot cmdline
      • 标头指定恢复 DTBO(如果需要)。
      • 对于 A/B 恢复分区,内容可以连接或从 bootvendor_boot 推断。例如
      • cmdline 连接到 bootvendor_boot cmdline
      • DTBO 可以从 vendor_boot 标头推断。
    • recovery ramdisk 镜像
      • 恢复资源
      • 对于非 A/B 恢复分区,ramdisk 的内容必须是独立的;请参阅 恢复镜像。例如
      • lib/modules 必须包含启动恢复模式所需的所有内核模块
      • 恢复 ramdisk 必须包含 init
      • 对于 A/B 恢复分区,恢复 ramdisk 会预先添加到通用和 vendor_boot ramdisk,因此无需独立。例如
      • lib/modules 可能仅包含启动恢复模式所需的其他内核模块,以及 vendor_boot ramdisk 中的内核模块。
      • 位于 /init 的符号链接可能存在,但会被启动镜像中第一阶段的 /init 二进制文件所取代。

通用 ramdisk 镜像内容

通用 ramdisk 包含以下组件。

  • init
  • system/etc/ramdisk/build.prop
  • ro.PRODUCT.bootimg.* build 属性
  • 挂载点的空目录:debug_ramdisk/mnt/dev/sys/proc/metadata/
  • first_stage_ramdisk/
    • 挂载点的重复空目录:debug_ramdisk/mnt/dev/sys/proc/metadata/

启动镜像集成

构建标志控制如何构建 init_bootbootrecoveryvendor_boot 镜像。布尔值板变量的值必须是字符串 true 或为空(默认值)。

  • TARGET_NO_KERNEL。此变量指示构建是否使用预构建的启动镜像。如果此变量设置为 true,则将 BOARD_PREBUILT_BOOTIMAGE 设置为预构建启动镜像的位置 (BOARD_PREBUILT_BOOTIMAGE:= device/${company}/${board}/boot.img)

  • BOARD_USES_RECOVERY_AS_BOOT。此变量指示设备是否使用 recovery 镜像作为 boot 镜像。使用 GKI 时,此变量为空,恢复资源应移至 vendor_boot

  • BOARD_USES_GENERIC_KERNEL_IMAGE。此变量指示板是否使用 GKI。此变量不影响系统属性或 PRODUCT_PACKAGES

    这是板级 GKI 开关;以下所有变量都受此变量限制。

  • BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT。此变量控制是否将 ramdisk 恢复资源构建到 vendor_boot

    • 设置为 true 时,恢复资源仅构建到 vendor-ramdisk/,而不构建到 recovery/root/

    • 为空时,恢复资源仅构建到 recovery/root/,而不构建到 vendor-ramdisk/

  • BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT。此变量控制是否将 GSI AVB 密钥构建到 vendor_boot

    • 设置为 true 时,如果 BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT

      • 已设置,GSI AVB 密钥将构建到 $ANDROID_PRODUCT_OUT/vendor-ramdisk/first_stage_ramdisk/avb

      • 未设置,GSI AVB 密钥将构建到 $ANDROID_PRODUCT_OUT/vendor-ramdisk/avb

    • 为空时,如果 BOARD_RECOVERY_AS_ROOT

      • 已设置,GSI AVB 密钥将构建到 $ANDROID_PRODUCT_OUT/recovery/root/first_stage_ramdisk/avb

      • 未设置,GSI AVB 密钥将构建到 $ANDROID_PRODUCT_OUT/ramdisk/avb

  • BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE。此变量控制 recovery 镜像是否包含内核。搭载 Android 12 并使用 A/B recovery 分区推出的设备必须将此变量设置为 true。搭载 Android 12 并使用非 A/B 推出的设备必须将此变量设置为 false,以保持恢复镜像的自包含性。

  • BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES。此变量控制是否将 $OUT/boot*.img 复制到目标文件下的 IMAGES/

    • aosp_arm64 必须将此变量设置为 true

    • 其他设备必须将此变量留空。

  • BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE。此变量控制是否生成 init_boot.img 并设置大小。设置后,通用 ramdisk 会添加到 init_boot.img 而不是 boot.img,并且需要设置 BOARD_AVB_INIT_BOOT* 变量以用于 链接的 vbmeta

允许的组合

组件或变量 升级不带恢复分区的设备 升级带恢复分区的设备 搭载不带恢复分区的设备推出 搭载带 A/B 恢复分区的设备推出 搭载带非 A/B 恢复分区的设备推出 aosp_arm64
包含 boot
包含 init_boot (Android 13)
包含 vendor_boot 可选 可选
包含 recovery
BOARD_USES_RECOVERY_AS_BOOT true
BOARD_USES_GENERIC_KERNEL_IMAGE true true true true
PRODUCT_BUILD_RECOVERY_IMAGE true 或空 true 或空 true 或空
BOARD_RECOVERYIMAGE_PARTITION_SIZE > 0 > 0 > 0
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT true
BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT true true true
BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE true
BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES true

具有专用 recovery 分区的设备可以将 PRODUCT_BUILD_RECOVERY_IMAGE 设置为 true 或空。对于这些设备,如果设置了 BOARD_RECOVERYIMAGE_PARTITION_SIZE,则会构建 recovery 镜像。

为启动启用链接的 vbmeta

必须为 bootinit_boot 镜像启用链接的 vbmeta。指定以下内容

BOARD_AVB_BOOT_KEY_PATH := external/avb/test/data/testkey_rsa4096.pem
BOARD_AVB_BOOT_ALGORITHM := SHA256_RSA4096
BOARD_AVB_BOOT_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_BOOT_ROLLBACK_INDEX_LOCATION := 2

BOARD_AVB_INIT_BOOT_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_INIT_BOOT_ALGORITHM := SHA256_RSA2048
BOARD_AVB_INIT_BOOT_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_INIT_BOOT_ROLLBACK_INDEX_LOCATION := 3

有关示例,请参阅此更改

System-as-root

使用 GKI 的设备不支持 System-as-root。在此类设备上,BOARD_BUILD_SYSTEM_ROOT_IMAGE 必须为空。使用动态分区的设备也不支持 System-as-root。

产品配置

使用通用 ramdisk 的设备必须安装允许安装到 ramdisk 的文件列表。为此,请在 device.mk 中指定以下内容

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)

generic_ramdisk.mk 文件还可防止其他 makefile 意外地将其他文件安装到 ramdisk(请将此类文件移至 vendor_ramdisk)。

设置设备

搭载 Android 13 推出的设备、升级到 Android 12 的设备和搭载 Android 12 推出的设备之间的设置说明有所不同。Android 13 的设置方式与 Android 12 类似

  • 升级到 Android 12 的设备

    • 可以保留 BOARD_USES_RECOVERY_AS_BOOT 的值。如果这样做,他们将使用旧版配置,并且新的构建变量必须为空。如果此类设备

      • BOARD_USES_RECOVERY_AS_BOOT 设置为 true,则架构如图 3所示。

      • BOARD_USES_RECOVERY_AS_BOOT 设置为空,则架构如图 4所示。

    • 可以将 BOARD_USES_RECOVERY_AS_BOOT 设置为空。如果这样做,他们将使用新的配置。如果此类设备

  • 搭载 Android 12 推出的设备必须将 BOARD_USES_RECOVERY_AS_BOOT 设置为空并使用新的配置。如果此类设备

由于 aosp_arm64 仅构建 GKI(而非 vendor_boot 或恢复),因此它不是完整的目标。对于 aosp_arm64 构建配置,请参阅 generic_arm64

选项 1:无专用恢复分区

没有 recovery 分区的设备在 boot 分区中包含通用 boot 镜像。vendor_boot ramdisk 包含所有恢复资源,包括 lib/modules(带有供应商内核模块)。在此类设备上,产品配置继承generic_ramdisk.mk

设置 BOARD 值

设置以下值

BOARD_USES_RECOVERY_AS_BOOT :=
BOARD_USES_GENERIC_KERNEL_IMAGE := true
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true
BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE :=
BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT := true

vendor_boot ramdisk 可以包含 /init/system/bin/init 的符号链接,以及位于 /system/bin/initinit_second_stage.recovery。但是,由于通用 ramdisk 连接在 vendor_boot ramdisk 之后,因此 /init 符号链接将被覆盖。当设备启动进入恢复模式时,需要 /system/bin/init 二进制文件来支持第二阶段 init。vendor_boot + 通用 ramdisk 的内容如下

  • /init(来自通用 ramdisk,从 init_first_stage 构建)
  • /system/bin/init(来自 vendor_ramdisk,从 init_second_stage.recovery 构建)

移动 fstab 文件

将安装到通用 ramdisk 的任何 fstab 文件移动到 vendor_ramdisk。有关示例,请参阅此更改

安装模块

您可以将设备特定的模块安装到 vendor_ramdisk(如果您没有任何设备特定的模块要安装,请跳过此步骤)。

  • 当模块安装到 /first_stage_ramdisk 时,请使用模块的 vendor_ramdisk 变体。此模块应在 init 将根切换到 /first_stage_ramdisk 之后但在 init 将根切换到 /system 之前可用。有关示例,请参阅元数据校验和Virtual A/B 压缩

  • 当模块安装到 / 时,请使用模块的 recovery 变体。此模块应在 init 将根切换到 /first_stage_ramdisk 之前可用。有关将模块安装到 / 的详细信息,请参阅第一阶段控制台

第一阶段控制台

由于第一阶段控制台在 init 将根切换到 /first_stage_ramdisk 之前启动,因此您需要安装模块的 recovery 变体。默认情况下,这两个模块变体都安装到 build/make/target/product/base_vendor.mk,因此如果设备 makefile 从该文件继承,则无需显式安装 recovery 变体。

要显式安装恢复模块,请使用以下代码。

PRODUCT_PACKAGES += \
    linker.recovery \
    shell_and_utilities_recovery \

这可确保 linkershtoybox 安装到 $ANDROID_PRODUCT_OUT/recovery/root/system/bin,然后安装到 vendor_ramdisk 下的 /system/bin

要添加第一阶段控制台所需的模块(例如,adbd),请使用以下代码。

PRODUCT_PACKAGES += adbd.recovery

这可确保指定的模块安装到 $ANDROID_PRODUCT_OUT/recovery/root/system/bin,然后安装到 vendor_ramdisk 下的 /system/bin

元数据校验和

为了在第一阶段挂载期间支持 元数据校验和,不支持 GKI 的设备会安装以下模块的 ramdisk 变体。要添加对 GKI 的支持,请将模块移动到 $ANDROID_PRODUCT_OUT/vendor-ramdisk/first_stage_ramdisk/system/bin

PRODUCT_PACKAGES += \
    linker.vendor_ramdisk \
    resize2fs.vendor_ramdisk \
    tune2fs.vendor_ramdisk \

有关示例,请参阅此变更列表

Virtual A/B 压缩

为了支持 Virtual A/B 压缩,必须将 snapuserd 安装到 vendor_ramdisk。设备应从 virtual_ab_ota/compression.mk 继承,该文件会安装 snapuserdvendor_ramdisk 变体。

启动过程的更改

启动进入恢复模式或 Android 的过程不会更改,但以下情况除外

  • Ramdisk build.prop 移至 /second_stage_resources,以便第二阶段 init 可以读取启动的构建时间戳。

由于资源从通用 ramdisk 移至 vendor_boot ramdisk,因此将通用 ramdisk 连接到 vendor_boot ramdisk 的结果不会更改。

使 e2fsck 可用

设备 makefile 可以从以下文件继承

  • virtual_ab_ota/launch_with_vendor_ramdisk.mk(如果设备支持 Virtual A/B 但不支持压缩)。

  • virtual_ab_ota/compression.mk(如果设备支持 Virtual A/B 压缩)。

产品 makefile 安装 $ANDROID_PRODUCT_OUT/vendor-ramdisk/first_stage_ramdisk/system/bin/e2fsck。在运行时,第一阶段 init 将根切换到 /first_stage_ramdisk,然后执行 /system/bin/e2fsck

选项 2a:专用和 A/B 恢复分区

对于具有 A/B recovery 分区的设备,请使用此选项;即,设备具有 recovery_arecovery_b 分区。此类设备包括恢复分区可更新的 A/B 和 Virtual A/B 设备,具有以下配置

AB_OTA_PARTITIONS += recovery

vendor_boot ramdisk 包含 ramdisk 的供应商位和供应商内核模块,包括以下内容

  • 设备特定的 fstab 文件

  • lib/modules(包括供应商内核模块)

recovery ramdisk 包含所有恢复资源。在此类设备上,产品配置继承generic_ramdisk.mk

设置 BOARD 值

为具有 A/B recovery 分区的设备设置以下值

BOARD_USES_RECOVERY_AS_BOOT :=
BOARD_USES_GENERIC_KERNEL_IMAGE := true
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT :=
BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE := true
BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT := true

recovery ramdisk 可以包含 /init -> /system/bin/init 符号链接,以及位于 /system/bin/initinit_second_stage.recovery。但是,由于启动 ramdisk 连接在 recovery ramdisk 之后,因此 /init 符号链接将被覆盖。当设备启动进入恢复模式时,需要 /system/bin/init 二进制文件来支持第二阶段 init。

当设备启动进入 recovery 时,recovery + vendor_boot + 通用 ramdisk 的内容如下

  • /init(来自 ramdisk,从 init_first_stage 构建)
  • /system/bin/init(来自 recovery ramdisk,从 init_second_stage.recovery 构建,并从 /init 执行)

当设备启动进入 Android 时,vendor_boot + 通用 ramdisk 的内容如下

  • /init(来自通用 ramdisk,从 init_first_stage 构建)

移动 fstab 文件

将安装到通用 ramdisk 的任何 fstab 文件移动到 vendor_ramdisk。有关示例,请参阅此更改

安装模块

(可选)您可以将设备特定的模块安装到 vendor_ramdisk(如果您没有任何设备特定的模块要安装,请跳过此步骤)。Init 不切换根。模块的 vendor_ramdisk 变体会安装到 vendor_ramdisk 的根目录。有关将模块安装到 vendor_ramdisk 的示例,请参阅第一阶段控制台元数据校验和Virtual A/B 压缩

第一阶段控制台

要安装模块的 vendor_ramdisk 变体,请使用以下代码

PRODUCT_PACKAGES += \
    linker.vendor_ramdisk \
    shell_and_utilities_vendor_ramdisk \

这可确保 linkershtoybox 安装到 $ANDROID_PRODUCT_OUT/vendor-ramdisk/system/bin,然后安装到 vendor_ramdisk 下的 /system/bin

要添加第一阶段控制台所需的模块(例如,adbd),请通过将相关补丁上传到 AOSP 来启用这些模块的 vendor_ramdisk 变体,然后使用以下代码,

PRODUCT_PACKAGES += adbd.vendor_ramdisk

这可确保指定的模块安装到 $ANDROID_PRODUCT_OUT/vendor-ramdisk/system/bin。如果在恢复模式下加载 vendor_boot ramdisk,则该模块在 recovery 中也可用。如果未在恢复模式下加载 vendor_boot ramdisk,则设备可以选择也安装 adbd.recovery

元数据校验和

为了在第一阶段挂载期间支持 元数据校验和,不支持 GKI 的设备会安装以下模块的 ramdisk 变体。要添加对 GKI 的支持,请将模块移动到 $ANDROID_PRODUCT_OUT/vendor-ramdisk/system/bin

PRODUCT_PACKAGES += \
    linker.vendor_ramdisk \
    resize2fs.vendor_ramdisk \
    tune2fs.vendor_ramdisk \

有关示例,请参阅此变更列表

Virtual A/B 压缩

为了支持 Virtual A/B 压缩,必须将 snapuserd 安装到 vendor_ramdisk。设备应从 virtual_ab_ota/compression.mk 继承,该文件会安装 snapuserdvendor_ramdisk 变体。

启动过程的更改

启动进入 Android 时,启动过程不会更改。vendor_boot + 通用 ramdisk 类似于现有的启动过程,只不过 fstabvendor_boot 加载。由于 system/bin/recovery 不存在,first_stage_init 会将其作为正常启动来处理。

启动进入恢复模式时,启动过程会更改。恢复 + vendor_boot + 通用 ramdisk 类似于现有的恢复过程,但内核从 boot 镜像而不是从 recovery 镜像加载。恢复模式的启动过程如下。

  1. 引导加载程序启动,然后执行以下操作

    1. 将恢复 + vendor_boot + 通用 ramdisk 推送到 /。(如果 OEM 通过将内核模块添加到 BOARD_RECOVERY_KERNEL_MODULES 在恢复 ramdisk 中复制内核模块),vendor_boot 是可选的。)
    2. 运行来自 boot 分区的内核。
  2. 内核将 ramdisk 挂载到 /,然后从通用 ramdisk 执行 /init

  3. 第一阶段 init 启动,然后执行以下操作

    1. 设置 IsRecoveryMode() == trueForceNormalBoot() == false
    2. /lib/modules 加载供应商内核模块。
    3. 调用 DoFirstStageMount(),但由于 IsRecoveryMode() == true 而跳过挂载。(设备不会释放 ramdisk(因为 / 仍然相同),但会调用 SetInitAvbVersionInRecovery()。)
    4. recovery ramdisk 中的 /system/bin/init 启动第二阶段 init。

使 e2fsck 可用

设备 makefile 可以从以下文件继承

  • virtual_ab_ota/launch_with_vendor_ramdisk.mk(如果设备支持 Virtual A/B 但不支持压缩)。

  • virtual_ab_ota/compression.mk(如果设备支持 Virtual A/B 压缩)。

产品 makefile 安装 $ANDROID_PRODUCT_OUT/vendor-ramdisk/system/bin/e2fsck。在运行时,第一阶段 init 执行 /system/bin/e2fsck

选项 2b:专用和非 A/B 恢复分区

对于具有非 A/B recovery 分区的设备,请使用此选项;即,设备具有名为 recovery 且没有槽后缀的分区。此类设备包括

  • 非 A/B 设备;
  • 恢复分区不可更新的 A/B 和 Virtual A/B 设备。(这种情况不常见。)

vendor_boot ramdisk 包含 ramdisk 的供应商位和供应商内核模块,包括以下内容

  • 设备特定的 fstab 文件
  • lib/modules(包括供应商内核模块)

recovery 镜像必须是自包含的。它必须包含启动恢复模式所需的所有资源,包括

  • 内核镜像
  • DTBO 镜像
  • lib/modules 中的内核模块
  • 第一阶段 init 作为符号链接 /init -> /system/bin/init
  • 第二阶段 init 二进制文件 /system/bin/init
  • 设备特定的 fstab 文件
  • 所有其他恢复资源,包括 recovery 二进制文件

在此类设备上,产品配置继承generic_ramdisk.mk

设置 BOARD 值

为非 A/B 设备设置以下值

BOARD_USES_RECOVERY_AS_BOOT :=
BOARD_USES_GENERIC_KERNEL_IMAGE := true
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT :=
BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE :=
BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT := true

recovery ramdisk 必须包含 /init -> /system/bin/init 符号链接,以及位于 /system/bin/initinit_second_stage.recovery。当设备启动进入恢复模式时,需要 /system/bin/init 二进制文件来支持第一阶段和第二阶段 init。

当设备启动进入 recovery 时,recovery ramdisk 的内容如下

  • /init -> /system/bin/init(来自 recovery ramdisk)
  • /system/bin/init(来自 recovery ramdisk,从 init_second_stage.recovery 构建,并从 /init 执行)

当设备启动进入 Android 时,vendor_boot + 通用 ramdisk 的内容如下

  • /init(来自 ramdisk,从 init_first_stage 构建)

移动 fstab 文件

将安装到通用 ramdisk 的任何 fstab 文件移动到 vendor_ramdiskrecovery ramdisk。有关示例,请参阅此更改

安装模块

您可以将设备特定的模块安装到 vendor_ramdiskrecovery ramdisk(如果您没有任何设备特定的模块要安装,请跳过此步骤)。init 不切换根。模块的 vendor_ramdisk 变体会安装到 vendor_ramdisk 的根目录。模块的 recovery 变体会安装到 recovery ramdisk 的根目录。有关将模块安装到 vendor_ramdiskrecovery ramdisk 的示例,请参阅第一阶段控制台元数据校验和

第一阶段控制台

要安装模块的 vendor_ramdisk 变体,请使用以下代码

PRODUCT_PACKAGES += \
    linker.vendor_ramdisk \
    shell_and_utilities_vendor_ramdisk \

这可确保 linkershtoybox 安装到 $ANDROID_PRODUCT_OUT/vendor-ramdisk/system/bin,然后安装到 vendor_ramdisk 下的 /system/bin

要添加第一阶段控制台所需的模块(例如,adbd),请通过将相关补丁上传到 AOSP 来启用这些模块的 vendor_ramdisk 变体,然后使用以下代码,

PRODUCT_PACKAGES += adbd.vendor_ramdisk

这可确保指定的模块安装到 $ANDROID_PRODUCT_OUT/vendor-ramdisk/system/bin

要安装模块的 recovery 变体,请将 vendor_ramdisk 替换为 recovery

PRODUCT_PACKAGES += \
    linker.recovery \
    shell_and_utilities_recovery \
    adbd.recovery \

元数据校验和

为了在第一阶段挂载期间支持 元数据校验和,不支持 GKI 的设备会安装以下模块的 ramdisk 变体。要添加对 GKI 的支持,请将模块移动到 $ANDROID_PRODUCT_OUT/vendor-ramdisk/system/bin

PRODUCT_PACKAGES += \
    linker.vendor_ramdisk \
    resize2fs.vendor_ramdisk \
    tune2fs.vendor_ramdisk \

为了在恢复模式下的第一阶段挂载期间支持元数据校验和,请启用这些模块的恢复变体并同时安装它们。

启动过程的更改

启动进入 Android 时,启动过程不会更改。vendor_boot + 通用 ramdisk 类似于现有的启动过程,只不过 fstabvendor_boot 加载。由于 system/bin/recovery 不存在,first_stage_init 会将其作为正常启动来处理。

启动进入恢复模式时,启动过程不会更改。恢复 ramdisk 的加载方式与现有的恢复过程相同。内核从 recovery 镜像加载。恢复模式的启动过程如下。

  1. 引导加载程序启动,然后执行以下操作

    1. 将恢复 ramdisk 推送到 /
    2. 运行来自 recovery 分区的内核。
  2. 内核将 ramdisk 挂载到 /,然后执行 /init,这是来自 recovery ramdisk 的 /system/bin/init 的符号链接。

  3. 第一阶段 init 启动,然后执行以下操作

    1. 设置 IsRecoveryMode() == trueForceNormalBoot() == false
    2. /lib/modules 加载供应商内核模块。
    3. 调用 DoFirstStageMount(),但由于 IsRecoveryMode() == true 而跳过挂载。(设备不会释放 ramdisk(因为 / 仍然相同),但会调用 SetInitAvbVersionInRecovery()。)
    4. recovery ramdisk 中的 /system/bin/init 启动第二阶段 init。

启动镜像时间戳

以下代码是 boot 镜像时间戳文件的示例

####################################
# from generate-common-build-props
# These properties identify this partition image.
####################################
ro.product.bootimage.brand=Android
ro.product.bootimage.device=generic_arm64
ro.product.bootimage.manufacturer=unknown
ro.product.bootimage.model=AOSP on ARM64
ro.product.bootimage.name=aosp_arm64
ro.bootimage.build.date=Mon Nov 16 22:46:27 UTC 2020
ro.bootimage.build.date.utc=1605566787
ro.bootimage.build.fingerprint=Android/aosp_arm64/generic_arm64:S/MASTER/6976199:userdebug/test-keys
ro.bootimage.build.id=MASTER
ro.bootimage.build.tags=test-keys
ro.bootimage.build.type=userdebug
ro.bootimage.build.version.incremental=6976199
ro.bootimage.build.version.release=11
ro.bootimage.build.version.release_or_codename=S
ro.bootimage.build.version.sdk=30
# Auto-added by post_process_props.py
persist.sys.usb.config=none
# end of file
  • 在构建时,system/etc/ramdisk/build.prop 文件会添加到通用 ramdisk。此文件包含构建的时间戳信息。

  • 在运行时,第一阶段 init 复制 ramdisk 中的文件到 tmpfs,然后再释放 ramdisk,以便第二阶段 init 可以读取此文件以设置 boot 镜像时间戳属性。