Módulos de kernel cargables

Como parte de los requisitos del módulo de kernel presentados en Android 8.0, todos Los kernels de sistema en chip (SoC) deben ser compatibles con módulos de kernel cargables.

Opciones de configuración del kernel

Para admitir módulos de kernel cargables, android-base.config en todos los kernels comunes incluye el Las siguientes opciones de configuración de kernel (o su equivalente a la versión de kernel):

CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y

Todos los kernels de dispositivos deben habilitar estas opciones. Los módulos de kernel también deben admitir la descarga y la recarga siempre que sea posible.

Firma de módulos

La firma de módulos no es compatible con los módulos de proveedores de GKI. En los dispositivos necesarios para admite el inicio verificado, Android requiere que los módulos de kernel estén en las particiones que tengan dm-verity habilitado. Esto quita la necesidad de firmar una persona módulos para comprobar su autenticidad. Android 13 introdujo el concepto de módulos de GKI. Los módulos de GKI usan el tiempo de compilación del kernel infraestructura de firma para diferenciar entre GKI y otros módulos en el tiempo de ejecución. Se pueden cargar los módulos sin firma, siempre y cuando solo usen símbolos que aparecen en la lista de entidades permitidas o proporcionados por otros módulos sin firmar. Para facilitar la firma de los módulos de GKI durante la compilación de GKI con el par de claves de tiempo de compilación del kernel, La configuración del kernel de GKI habilitó CONFIG_MODULE_SIG_ALL=y. Para evitar firmar módulos que no sean de GKI durante las compilaciones del kernel del dispositivo, debes agregar # CONFIG_MODULE_SIG_ALL is not set como parte de la configuración de tu kernel o fragmentos.

Ubicaciones de los archivos

Aunque Android 7.x y las versiones anteriores no admiten módulos de kernel (e incluyen compatibilidad con insmod y rmmod), Android 8.x y el uso de módulos de kernel en el ecosistema. Lo siguiente muestra la posible compatibilidad con periféricos específicos de la placa en tres Modos de inicio de Android

Modo de inicio Almacenamiento Pantalla Teclado Batería PMIC Pantalla táctil NFC, Wi-Fi,
Bluetooth
Sensores Cámara
Recuperación
Cargador
Android

Además de la disponibilidad en los modos de inicio de Android, los módulos de kernel también pueden categorizados según su propietario (el proveedor del SoC o el ODM). Si los módulos de kernel se usan, los requisitos para su ubicación en el sistema de archivos son los siguientes: sigue:

  • Todos los kernels deben tener compatibilidad integrada para el inicio y la activación y particiones.
  • Los módulos de kernel deben cargarse desde una partición de solo lectura.
  • En el caso de los dispositivos que deben tener un inicio verificado, los módulos de kernel deben se cargan desde particiones verificadas.
  • Los módulos de kernel no deben estar ubicados en /system.
  • Los módulos de GKI necesarios para el dispositivo deben cargarse desde /system/lib/modules, que es un vínculo simbólico a /system_dlkm/lib/modules
  • Los módulos de kernel del proveedor de SoC que se requieren para Android o Los modos del cargador deben encontrarse en /vendor/lib/modules.
  • Si existe una partición de ODM, los módulos de kernel del ODM que se requieren para los modos completos de Android o Charger deben ubicarse en /odm/lib/modules De lo contrario, estos módulos deberían estar ubicados en /vendor/lib/modules
  • Módulos de kernel del proveedor del SoC y del ODM que se requieren para la recuperación este modo debe ubicarse en el ramfs de recuperación en /lib/modules
  • Los módulos de kernel necesarios para el modo de recuperación y la versión completa de Android Los modos del cargador deben existir en el rootfs de recuperación y las particiones /vendor o /odm (como se describe arriba).
  • Los módulos de kernel que se usan en Modo de recuperación no deben depender de los módulos ubicados solo en /vendor o /odm, ya que esas particiones no están se activan en modo de recuperación.
  • Los módulos de kernel del proveedor de SoC no deberían depender de los módulos de kernel de ODM.

En Android 7.x y versiones anteriores, /vendor y /odm las particiones no se activan antes. En Android 8.x y versiones posteriores, para que la carga de módulos desde estas particiones sea posible, se implementaron aprovisionamiento para activar las particiones con anticipación dispositivos que no son A/B y A/B. Esto también garantiza que las particiones se activen en los modos Android y Charger.

Compatibilidad con el sistema de compilación de Android

En BoardConfig.mk, la compilación de Android define un elemento Variable BOARD_VENDOR_KERNEL_MODULES que proporciona una lista completa de los módulos de kernel diseñados para la imagen del proveedor. Los módulos que se enumeran en esta variable se copian en la imagen del proveedor en /lib/modules/ y, luego de activarse en Android, aparecer en /vendor/lib/modules (de acuerdo con los requisitos anteriores). Ejemplo de configuración de los módulos de kernel del proveedor:

vendor_lkm_dir := device/$(vendor)/lkm-4.x
BOARD_VENDOR_KERNEL_MODULES := \
  $(vendor_lkm_dir)/vendor_module_a.ko \
  $(vendor_lkm_dir)/vendor_module_b.ko \
  $(vendor_lkm_dir)/vendor_module_c.ko

En este ejemplo, se asigna un repositorio precompilado del módulo kernel del proveedor la compilación de Android en la ubicación indicada anteriormente.

La imagen de recuperación puede contener un subconjunto de los módulos del proveedor. Android build define la variable BOARD_RECOVERY_KERNEL_MODULES para estos módulos. Ejemplo:

vendor_lkm_dir := device/$(vendor)/lkm-4.x
BOARD_RECOVERY_KERNEL_MODULES := \
  $(vendor_lkm_dir)/vendor_module_a.ko \
  $(vendor_lkm_dir)/vendor_module_b.ko

La compilación de Android se encarga de ejecutar depmod para generar la se necesitaban modules.dep archivos en /vendor/lib/modules y /lib/modules (recovery ramfs).

Carga de módulos y control de versiones

Carga todos los módulos de kernel en una sola pasada desde init.rc* invocando modprobe -a Esto evita la sobrecarga de inicializar repetidamente el entorno de ejecución de C para el objeto binario modprobe El Se puede modificar el evento early-init para invocar modprobe:

on early-init
    exec u:r:vendor_modprobe:s0 -- /vendor/bin/modprobe -a -d \
        /vendor/lib/modules module_a module_b module_c ...

Normalmente, un módulo de kernel debe compilarse con el kernel al que está usar (de lo contrario, el kernel no cargará el módulo). CONFIG_MODVERSIONS proporciona una solución alternativa a través de la detección de fallas. de la interfaz binaria de la aplicación (ABI). Este atributo calcula un valor cíclico de comprobación de redundancia (CRC) del prototipo de cada símbolo exportado en el kernel y almacena los valores como parte de este; para los símbolos utilizados por un módulo de kernel, los valores también se almacenan en el módulo de kernel. Cuando módulo, se comparan los valores de los símbolos usados por el módulo con los del kernel. Si los valores coinciden, se carga el módulo. De lo contrario, la carga fallará.

Para habilitar la actualización de la imagen del kernel por separado de la imagen del proveedor, habilitar CONFIG_MODVERSIONS Esto permite pequeñas actualizaciones en la kernel (como correcciones de errores de LTS) que se realizará mientras se mantiene la compatibilidad con módulos de kernel existentes en la imagen del proveedor. Sin embargo, CONFIG_MODVERSIONS no repara una falla de la ABI por sí sola. Si el botón prototipo de un símbolo exportado en el kernel cambia, ya sea debido a de la fuente o debido a que cambió la configuración del kernel, esta interrumpe la compatibilidad con los módulos de kernel que usan ese símbolo. En esos casos, se debe volver a compilar el módulo del kernel.

Por ejemplo, la estructura task_struct en el kernel (definida en include/linux/sched.h) contiene muchos campos de forma condicional se incluye en función de la configuración del kernel. El sched_info solo está presente si se habilita CONFIG_SCHED_INFO (que ocurre cuando CONFIG_SCHEDSTATS o CONFIG_TASK_DELAY_ACCT). Si estos parámetros de configuración las opciones cambian el estado, el diseño de la estructura task_struct y cualquier interfaz exportada del kernel que use Se alteró task_struct (por ejemplo, set_cpus_allowed_ptr en kernel/sched/core.c). Se agregó compatibilidad con módulos de kernel compilados previamente que usan estos errores en la interfaz, lo que requiere que esos módulos se vuelvan a compilar con el nuevo kernel configuración.

Para obtener más información sobre CONFIG_MODVERSIONS, consulta la en el árbol del kernel en Documentation/kbuild/modules.rst