内核模块支持

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

模块位置

ramdisk 是第一阶段 init 以及 A/B 和虚拟 A/B 设备上 recovery/fastbootd 映像的文件系统。它是一个 initramfs,由两个 cpio 归档文件组成,这两个文件由引导加载程序连接而成。第一个 cpio 归档文件作为供应商 ramdisk 存储在 vendor-boot 分区中,包含以下组件

  • 第一阶段 init 供应商内核模块,位于 /lib/modules/ 中。
  • modprobe 配置文件,位于 /lib/modules/ 中:modules.depmodules.softdepmodules.aliasmodules.options
  • modules.load 文件,指示在第一阶段 init 期间要加载哪些模块以及加载顺序,位于 /lib/modules/ 中。
  • 供应商 recovery-kernel 模块,适用于 A/B 和虚拟 A/B 设备,位于 /lib/modules/
  • modules.load.recovery,指示要加载的模块以及加载顺序,适用于 A/B 和虚拟 A/B 设备,位于 /lib/modules 中。

第二个 cpio 归档文件与 GKI 一起作为 boot.img 的 ramdisk 提供,并在第一个 cpio 归档文件之上应用,其中包含 first_stage_init 及其依赖的库。

第一阶段 init 中的模块加载

第一阶段 init 首先从 ramdisk 上的 /lib/modules/ 读取 modprobe 配置文件。接下来,它读取 /lib/modules/modules.load(如果是 recovery,则为 /lib/modules/modules.load.recovery)中指定的模块列表,并尝试按照顺序加载每个模块,并遵循先前加载的文件中指定的配置。为了满足硬依赖或软依赖关系,请求的顺序可能会有所偏差。

构建支持,第一阶段 init

要指定要复制到供应商 ramdisk cpio 中的内核模块,请在 BOARD_VENDOR_RAMDISK_KERNEL_MODULES 中列出它们。构建过程会对这些模块运行 depmod,并将生成的 modprobe 配置文件放入供应商 ramdisk cpio 中。

构建过程还会创建一个 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

构建支持,完整 Android

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

通配符和集成内核构建

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

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

内核模块 zip 归档文件应具有 make 规则,以确保平台构建可以在需要时生成该归档文件。

恢复

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

要了解有关创建供应商启动分区(其中包含本页提及的供应商 ramdisk)的信息,请参阅启动分区