实现 GKI 模块分区

GKI 和 GKI 模块可以独立于分区的其余部分进行更新,因为 GKI 模块位于超级镜像中名为 system_dlkm 的单独动态分区上。GKI 模块由 Google 使用内核构建时密钥对进行签名,并且仅与构建它们的 GKI 兼容。GKI 和 GKI 模块之间没有 ABI 稳定性;为了使模块在运行时正确加载,GKI 和 GKI 模块必须一起构建和更新。

实现 system_dlkm 分区支持

system_dlkm 分区位于超级分区中,作为另一个动态分区。此分区可以包含

  • Google 构建时签名的内核模块
  • depmod 工件

构建 system_dlkm

构建 system_dlkm 与构建其他动态分区类似。执行以下步骤以将 system_dlkm 添加到您的构建

  1. BoardConfig.mk 中,添加以下条目

    BOARD_USES_SYSTEM_DLKMIMAGE := true
    BOARD_SYSTEM_DLKMIMAGE_FILE_SYSTEM_TYPE := $(TARGET_RO_FILE_SYSTEM_TYPE)
    TARGET_COPY_OUT_SYSTEM_DLKM := system_dlkm
    
  2. 在分区列表中,添加 system_dlkmBOARD_GOOGLE_SYSTEM_DYNAMIC_PARTITIONS_PARTITION_LIST := system_dlkm

  3. (可选)对于 A/B 和 Virtual A/B 设备,在设备的 device.mk 文件中添加以下行

    AB_OTA_PARTITIONS += system_dlkm
    

确定要复制到 system_dlkm 中的内核模块

为了使模块在运行时成功加载,GKI 和 GKI 模块必须一起构建。因此,您必须在 GKI 构建中为目标架构确定内核模块,并在平台构建期间将其作为 system_dlkm 分区的源提供。

对于 Android 13

BOARD_SYSTEM_DLKM_SRC 指向一个文件夹,该文件夹包含设备所需的 GKI 模块内核目标文件,作为构建系统的输入,以生成 system_dlkm 分区。例如

在文件夹中提供 GKI 模块源,并将 BOARD_SYSTEM_DLKM_SRC 指向该文件夹。例如

  BOARD_SYSTEM_DLKM_SRC := kernel/prebuilts/5.10/arm64/system_dlkm_staging

在构建时,BOARD_SYSTEM_DLKM_SRC 中列出的模块会安装在 $ANDROID_PRODUCT_OUT/system_dlkm 中。

对于 Android 14

我们使用宏 (BOARD_*_KERNEL_MODULES) 精简了实现,这些宏也用于其他 *_dlkm 分区。设备所需的 GKI 模块列表应由 BOARD_SYSTEM_KERNEL_MODULES 宏引用。在构建时,这些模块会安装在 $ANDROID_PRODUCT_OUT/system_dlkm 中。vendor_dlkm 分区中任何依赖于 system_dlkm 分区中模块的模块都会在 vendor_dlkm 分区的 modules.dep 文件中生成正确的引用。由于 modules.dep 表示的跨分区依赖关系,当加载供应商模块时,任何所需的 GKI 模块都会自动加载。

例如,要从预构建版本在 system_dlkm 分区上为 GKI arm64 内核 5.15 安装所有 GKI 模块

 BOARD_SYSTEM_KERNEL_MODULES := $(wildcard kernel/prebuilts/5.15/arm64/*.ko)

在运行时挂载 system_dlkm

根据用作只读文件系统的文件系统,在您的 fstab 中添加以下内容,以在运行时挂载 system_dlkm 分区

作为只读文件系统的 ext4

  system_dlkm /system_dlkm ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb

作为只读文件系统的 erofs

  system_dlkm /system_dlkm erofs ro wait,logical,first_stage_mount,slotselect,avb

分区挂载和模块加载

first_stage_init 期间,system_dlkm 分区作为只读文件系统挂载在 /system_dlkm 中。成功挂载后,指向 /system_dlkm/lib/modules/system/lib/modules 处的符号链接可用。

然后,供应商进程(例如 .rc 脚本)可以根据 modules.load 中指定的顺序加载内核模块。供应商进程必须使用符号链接 /system/lib/modules 来加载模块。如果需要,供应商进程也可以稍后加载模块。

SELinux

system_dlkm 分区中的每个文件都标有 system_dlkm_file 的文件上下文。为了加载 system_dlkm 分区中的 GKI 模块文件,负责加载模块的供应商进程需要供应商域中的 sepolicy

例如,Cuttlefish 使用的 dlkm_loader 加载 GKI 模块在 shared/sepolicy/vendor/dlkm_loader.te 的策略文件中具有以下权限

allow dlkm_loader self:capability sys_module;
allow dlkm_loader system_dlkm_file:dir r_dir_perms;
allow dlkm_loader system_dlkm_file:file r_file_perms;
allow dlkm_loader system_dlkm_file:system module_load;

验证 system-dlkm 分区

Google 提供了一个 GKI VTS 测试用例来验证 system_dlkm 分区。要手动调用测试,请使用以下 atest 命令

  atest -c vts_dlkm_partition_test