实现 GKI 模块分区

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

实现 system_dklm 分区支持

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

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

构建 system_dlkm

构建 system_dlkm 过程与构建其他动态分区类似。如需将 system_dlkm 添加到您的 build 中,请执行以下步骤:

  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 设备和虚拟 A/B 设备,请在设备的 device.mk 文件中添加以下代码行:

    AB_OTA_PARTITIONS += system_dlkm
    

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

为了让模块在运行时成功加载,必须同时构建 GKI 和 GKI 模块。因此,您必须为目标架构确定 GKI build 中的内核模块,并在平台构建期间将这些模块作为 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 分区中的模块的任何模块都会在 modules.dep 文件中为 vendor_dlkm 分区生成正确的引用。由于 modules.dep 表示的此跨分区依赖关系,因此在加载供应商模块时,系统会自动加载任何所需的 GKI 模块。

例如,如需为预构建的 GKI arm64 内核 5.15system_dlkm 分区中安装所有 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/lib/modules 中指向 /system_dlkm/lib/modules 的符号链接将可用。

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

SELinux

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

例如,Cuttlefish 用于加载 GKI 模块的 dlkm_loader 在位于 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