内核模块支持

通用内核映像 (GKI) 可能不包含使设备能够装载分区所需的驱动程序支持。为了使设备能够装载分区并继续启动,增强了第一阶段 init,用于加载 ramdisk 上的内核模块。ramdisk 被拆分为通用 ramdisk 和供应商 ramdisk。供应商内核模块存储在供应商 ramdisk 中。内核模块加载的顺序可以配置。

模块位置

ramdisk 是第一阶段 init, 的文件系统,也是 A/B 设备和虚拟 A/B 设备上的恢复/fastboot 映像的文件系统。这是一个 initramfs,包含两个由引导加载程序串联的 cpio 归档。第一个 cpio 归档(作为供应商 ramdisk 存储在供应商启动分区中)包含以下组件:

  • 第一阶段 init 供应商内核模块,位于 /lib/modules/
  • modprobe 配置文件,位于 /lib/modules/modules.depmodules.softdepmodules.aliasmodules.options
  • 一个 modules.load 文件,用于指示在第一阶段 init 期间加载的模块及相应的加载顺序,位于 /lib/modules/
  • 供应商恢复内核模块,用于 A/B 和虚拟 A/B 设备,位于 /lib/modules/
  • modules.load.recovery,用于指示要加载的模块及相应的加载顺序,用于 A/B 和虚拟 A/B 设备,位于 /lib/modules

第二个 cpio 归档(作为 boot.img 的 ramdisk 随 GKI 提供,应用在第一个 cpio 归档之上)包含 first_stage_init 及其依赖的库。

在第一阶段 init 期间加载模块

第一阶段 init 首先从 ramdisk 上的 /lib/modules/ 读取 modprobe 配置文件。接下来,读取 /lib/modules/modules.load(在恢复过程中,则为 /lib/modules/modules.load.recovery)中指定的模块列表,并尝试按照之前加载的文件中指定的配置,依次加载各个模块。为了满足硬依赖项或软依赖项的要求,实际执行顺序可以不同于请求的顺序。

build 支持,第一阶段 init

如需指定要复制到供应商 ramdisk cpio 的内核模块,请在 BOARD_VENDOR_RAMDISK_KERNEL_MODULES 中将其列出。build 会对这些模块运行 depmod,并将生成的 modprobe 配置文件放在供应商 ramdisk cpio 中。

build 还会创建一个 modules.load 文件,并将其存储在供应商 ramdisk cpio 中。默认情况下,该文件包含 BOARD_VENDOR_RAMDISK_KERNEL_MODULES 中列出的所有模块。如需替换该文件的内容,请使用 BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD,如以下示例所示:

BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD := \
    device/vendor/mydevice-kernel/first.ko \
    device/vendor/mydevice-kernel/second.ko \
    device/vendor/mydevice-kernel/third.ko

build 支持,所有 Android 版本

与在 Android 10 及更低版本中一样,BOARD_VENDOR_KERNEL_MODULES 中列出的内核模块会由 Android 平台 build 复制到 vendor 分区中的 /vendor/lib/modules。平台 build 会对这些模块运行 depmod,并将 depmod 输出文件复制到 vendor 分区中的相同位置。从 /vendor 加载内核模块的机制与以前的 Android 版本相同。您可以决定如何以及何时加载这些模块,尽管这通常是使用 init.rc 脚本来完成的。

通配符和集成的内核 build

如果供应商将设备内核 build 与 Android 平台 build 相结合,可能就会无法使用上述 BOARD 宏来指定要复制到设备的内核模块。如果供应商不希望在设备的平台 build 文件中列出内核模块,可以使用通配符 ($(wildcard device/vendor/mydevice/*.ko)。请注意,如果集成了内核 build,该通配符会不起作用,因为调用 make 并在 makefile 中展开宏时,内核模块尚未构建,因此宏为空。

为了解决此问题,供应商可以让其内核 build 创建一个 zip 归档文件,其中包含要复制到每个分区的内核模块。将该 zip 归档文件的路径设置到 BOARD_*_KERNEL_MODULES_ARCHIVE,其中 * 为分区的名称(例如 BOARD_VENDOR_KERNEL_MODULES_ARCHIVE)。Android 平台 build 会将此 zip 归档文件解压缩到适当的位置,并对模块运行 depmod

内核模块 zip 归档文件应包含一条 make 规则,用于确保平台 build 可以在需要时生成归档文件。

恢复

在之前的 Android 版本中,恢复所需的内核模块在 BOARD_RECOVERY_KERNEL_MODULES 中指定。在 Android 11 中,恢复所需的内核模块仍使用该宏指定。但是,恢复内核模块会被复制到供应商 ramdisk cpio,而不是通用的 ramdisk cpio。默认情况下,BOARD_RECOVERY_KERNEL_MODULES 中列出的所有内核模块都会在第一阶段 init 期间加载。如果您只想加载这些模块中的一部分,请在 BOARD_RECOVERY_KERNEL_MODULES_LOAD 中指定这一部分的内容。

如需了解如何创建供应商启动分区(其中包含本页中提及的供应商 ramdisk),请参阅启动分区