Ladbare Kernelmodule

Als Teil der in Android 8.0 eingeführten Modul-Kernel-Anforderungen müssen alle System-on-Chip (SoC)-Kernel ladbare Kernel-Module unterstützen.

Kernel-Konfigurationsoptionen

Um ladbare Kernel-Module zu unterstützen, enthält android-base.config in allen gängigen Kerneln die folgenden Kernel-Config-Optionen (oder deren Kernel-Versionsäquivalent):

CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y

Alle Gerätekerne müssen diese Optionen aktivieren. Kernelmodule sollten nach Möglichkeit auch das Entladen und Neuladen unterstützen.

Signieren des Moduls

Die Modulsignierung wird für GKI-Anbietermodule nicht unterstützt. Auf Geräten, die verifiziertes Booten unterstützen müssen, erfordert Android, dass sich Kernelmodule in den Partitionen befinden, auf denen dm-verity aktiviert ist. Dadurch entfällt die Notwendigkeit, einzelne Module auf ihre Authentizität zu signieren. Mit Android 13 wurde das Konzept der GKI-Module eingeführt. GKI-Module nutzen die Build-Time-Signatur-Infrastruktur des Kernels, um zur Laufzeit zwischen GKI und anderen Modulen zu unterscheiden. Nicht signierte Module dürfen geladen werden, solange sie nur Symbole verwenden, die auf der Zulassungsliste stehen oder von anderen nicht signierten Modulen bereitgestellt werden. Um das Signieren von GKI-Modulen während der GKI-Erstellung mithilfe des Schlüsselpaars zur Erstellungszeit des Kernels zu erleichtern, wurde in der GKI-Kernelkonfiguration CONFIG_MODULE_SIG_ALL=y aktiviert. Um das Signieren von Nicht-GKI-Modulen während der Kernel-Builds des Geräts zu vermeiden, müssen Sie # CONFIG_MODULE_SIG_ALL is not set als Teil Ihrer Kernel-Konfigurationsfragmente hinzufügen.

Dateispeicherorte

Während Android 7.x und niedriger keine Kernel-Module vorschreiben (und Unterstützung für insmod und rmmod bieten), empfehlen Android 8.x und höher die Verwendung von Kernel-Modulen im Ökosystem. Die folgende Tabelle zeigt die potenzielle platinenspezifische Peripherieunterstützung, die in drei Android-Startmodi erforderlich ist.

Boot modus Lagerung Anzeige Tastenfeld Batterie PMIC Touch-Screen NFC, WLAN,
Bluetooth
Sensoren Kamera
Erholung
Ladegerät
Android

Zusätzlich zur Verfügbarkeit in Android-Startmodi können Kernelmodule auch danach kategorisiert werden, wem sie gehören (dem SoC-Anbieter oder dem ODM). Wenn Kernel-Module verwendet werden, gelten folgende Anforderungen für deren Platzierung im Dateisystem:

  • Alle Kernel sollten über eine integrierte Unterstützung für das Booten und Mounten von Partitionen verfügen.
  • Kernelmodule müssen von einer schreibgeschützten Partition geladen werden.
  • Für Geräte, für die ein verifizierter Start erforderlich ist, sollten Kernelmodule von verifizierten Partitionen geladen werden.
  • Kernelmodule sollten sich nicht in /system befinden.
  • Für das Gerät erforderliche GKI-Module sollten von /system/lib/modules geladen werden, was einen symbolischen Link zu /system_dlkm/lib/modules darstellt.
  • Kernelmodule des SoC-Anbieters, die für den vollständigen Android- oder Charger-Modus erforderlich sind, sollten sich in /vendor/lib/modules befinden.
  • Wenn eine ODM-Partition vorhanden ist, sollten sich Kernelmodule aus dem ODM, die für den vollständigen Android- oder Charger-Modus erforderlich sind, in /odm/lib/modules befinden. Andernfalls sollten sich diese Module in /vendor/lib/modules befinden.
  • Kernel-Module des SoC-Anbieters und ODM, die für den Wiederherstellungsmodus erforderlich sind, sollten sich in den Wiederherstellungs- ramfs unter /lib/modules befinden.
  • Kernelmodule, die sowohl für den Wiederherstellungsmodus als auch für den vollständigen Android- oder Charger-Modus erforderlich sind, sollten sowohl im Wiederherstellungs- rootfs als auch in den Partitionen /vendor oder /odm (wie oben beschrieben) vorhanden sein.
  • Im Wiederherstellungsmodus verwendete Kernelmodule sollten nicht von Modulen abhängen, die sich nur in /vendor oder /odm befinden, da diese Partitionen nicht im Wiederherstellungsmodus bereitgestellt werden.
  • Kernelmodule von SoC-Anbietern sollten nicht von ODM-Kernelmodulen abhängen.

In Android 7.x und niedriger werden /vendor und /odm Partitionen nicht frühzeitig gemountet. Um das Laden von Modulen aus diesen Partitionen zu ermöglichen, wurden in Android 8.x und höher Vorkehrungen getroffen, um Partitionen sowohl für Nicht-A/B- als auch für A/B-Geräte frühzeitig bereitzustellen. Dadurch wird auch sichergestellt, dass die Partitionen sowohl im Android- als auch im Charger-Modus gemountet werden.

Unterstützung für Android-Build-Systeme

In BoardConfig.mk definiert der Android-Build eine BOARD_VENDOR_KERNEL_MODULES -Variable, die eine vollständige Liste der Kernelmodule bereitstellt, die für das Anbieter-Image vorgesehen sind. Die in dieser Variablen aufgeführten Module werden in das Hersteller-Image unter /lib/modules/ kopiert und erscheinen nach dem Mounten in Android in /vendor/lib/modules (gemäß den oben genannten Anforderungen). Beispielkonfiguration der Kernelmodule des Herstellers:

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

In diesem Beispiel wird ein vorgefertigtes Repository für ein Kernelmodul eines Anbieters dem Android-Build am oben aufgeführten Speicherort zugeordnet.

Das Wiederherstellungsimage kann eine Teilmenge der Herstellermodule enthalten. Der Android-Build definiert die Variable BOARD_RECOVERY_KERNEL_MODULES für diese Module. Beispiel:

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

Der Android-Build kümmert sich darum, depmod auszuführen, um die erforderlichen modules.dep Dateien in /vendor/lib/modules und /lib/modules ( recovery ramfs ) zu generieren.

Laden und Versionieren von Modulen

Laden Sie alle Kernelmodule in einem Durchgang von init.rc* , indem Sie modprobe -a aufrufen. Dadurch wird der Aufwand vermieden, der mit der wiederholten Initialisierung der C-Laufzeitumgebung für die modprobe Binärdatei verbunden ist. Das early-init Ereignis kann geändert werden, um modprobe aufzurufen:

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

Normalerweise muss ein Kernelmodul mit dem Kernel kompiliert werden, mit dem das Modul verwendet werden soll (andernfalls weigert sich der Kernel, das Modul zu laden). CONFIG_MODVERSIONS bietet eine Problemumgehung, indem Fehler in der Anwendungsbinärschnittstelle (ABI) erkannt werden. Diese Funktion berechnet einen CRC-Wert (Cyclic Redundancy Check) für den Prototyp jedes exportierten Symbols im Kernel und speichert die Werte als Teil des Kernels. Für Symbole, die von einem Kernelmodul verwendet werden, werden die Werte auch im Kernelmodul gespeichert. Beim Laden des Moduls werden die Werte für die vom Modul verwendeten Symbole mit denen im Kernel verglichen. Stimmen die Werte überein, wird das Modul geladen; andernfalls schlägt der Ladevorgang fehl.

Um die Aktualisierung des Kernel-Images getrennt vom Hersteller-Image zu ermöglichen, aktivieren Sie CONFIG_MODVERSIONS . Auf diese Weise können kleine Aktualisierungen des Kernels (z. B. Fehlerbehebungen von LTS) vorgenommen werden, während gleichzeitig die Kompatibilität mit vorhandenen Kernelmodulen im Anbieter-Image gewahrt bleibt. Allerdings behebt CONFIG_MODVERSIONS allein keinen ABI-Fehler. Wenn sich der Prototyp eines exportierten Symbols im Kernel ändert, entweder aufgrund einer Änderung der Quelle oder weil sich die Kernelkonfiguration geändert hat, beeinträchtigt dies die Kompatibilität mit Kernelmodulen, die dieses Symbol verwenden. In solchen Fällen muss das Kernelmodul neu kompiliert werden.

Beispielsweise enthält die task_struct Struktur im Kernel (definiert in include/linux/sched.h ) viele Felder, die abhängig von der Kernelkonfiguration bedingt eingeschlossen sind. Das Feld sched_info ist nur vorhanden, wenn CONFIG_SCHED_INFO aktiviert ist (was der Fall ist, wenn CONFIG_SCHEDSTATS oder CONFIG_TASK_DELAY_ACCT aktiviert sind). Wenn diese Konfigurationsoptionen ihren Status ändern, ändert sich das Layout der task_struct Struktur und alle exportierten Schnittstellen aus dem Kernel, die task_struct verwenden, werden geändert (z. B. set_cpus_allowed_ptr in kernel/sched/core.c ). Die Kompatibilität mit zuvor kompilierten Kernelmodulen, die diese Schnittstellen verwenden, wird unterbrochen, sodass diese Module mit der neuen Kernelkonfiguration neu erstellt werden müssen.

Weitere Einzelheiten zu CONFIG_MODVERSIONS finden Sie in der Dokumentation im Kernel-Baum unter Documentation/kbuild/modules.rst .