Dans le cadre des exigences du noyau de module introduites dans Android 8.0, tous les noyaux de système sur puce (SoC) doivent prendre en charge les modules de noyau chargeables.
Options de configuration du noyau
Pour prendre en charge les modules de noyau chargeables, android-base.config dans tous les noyaux courants inclut les options de configuration de noyau suivantes (ou leur équivalent de version de noyau) :
CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y
Tous les noyaux de périphériques doivent activer ces options. Les modules du noyau doivent également prendre en charge le déchargement et le rechargement autant que possible.
Signature des modules
La signature de module n'est pas prise en charge pour les modules du fournisseur GKI. Sur les appareils requis pour prendre en charge le démarrage vérifié, Android exige que les modules du noyau se trouvent dans les partitions sur lesquelles dm-verity est activé. Cela supprime le besoin de signer des modules individuels pour leur authenticité. Android 13 a introduit le concept de modules GKI. Les modules GKI utilisent l'infrastructure de signature au moment de la construction du noyau pour différencier GKI des autres modules au moment de l'exécution. Les modules non signés sont autorisés à se charger à condition qu'ils utilisent uniquement les symboles apparaissant sur la liste verte ou fournis par d'autres modules non signés. Pour faciliter la signature des modules GKI pendant la construction de GKI à l'aide de la paire de clés de construction du noyau, la configuration du noyau GKI a activé CONFIG_MODULE_SIG_ALL=y
. Pour éviter de signer des modules non GKI lors de la construction du noyau de périphérique, vous devez ajouter # CONFIG_MODULE_SIG_ALL is not set
dans le cadre des fragments de configuration de votre noyau.
Emplacements des fichiers
Bien qu'Android 7.x et versions antérieures n'imposent pas les modules du noyau (et incluent la prise en charge de insmod
et rmmod
), Android 8.x et versions ultérieures recommandent l'utilisation de modules de noyau dans l'écosystème. Le tableau suivant montre la prise en charge potentielle des périphériques spécifiques à la carte requise dans trois modes de démarrage Android.
Mode d'amorçage | Stockage | Afficher | Clavier | Batterie | PMIC | Écran tactile | NFC, Wi-Fi, Bluetooth | Capteurs | Caméra |
---|---|---|---|---|---|---|---|---|---|
Récupération | |||||||||
Chargeur | |||||||||
Android |
En plus de la disponibilité dans les modes de démarrage Android, les modules du noyau peuvent également être classés selon leur propriétaire (le fournisseur SoC ou l'ODM). Si des modules du noyau sont utilisés, les exigences relatives à leur placement dans le système de fichiers sont les suivantes :
- Tous les noyaux doivent avoir une prise en charge intégrée pour le démarrage et le montage des partitions.
- Les modules du noyau doivent être chargés à partir d'une partition en lecture seule.
- Pour les périphériques devant avoir un démarrage vérifié, les modules du noyau doivent être chargés à partir des partitions vérifiées.
- Les modules du noyau ne doivent pas être situés dans
/system
. - Les modules GKI requis pour le périphérique doivent être chargés à partir de
/system/lib/modules
qui est un lien symbolique vers/system_dlkm/lib/modules
. - Les modules de noyau du fournisseur SoC requis pour les modes Android ou Charger complets doivent être situés dans
/vendor/lib/modules
. - Si une partition ODM existe, les modules du noyau de l'ODM requis pour les modes Android ou Charger complets doivent être situés dans
/odm/lib/modules
. Sinon, ces modules doivent être situés dans/vendor/lib/modules
. - Les modules de noyau du fournisseur SoC et d'ODM requis pour le mode de récupération doivent être situés dans les
ramfs
de récupération à l'/lib/modules
. - Les modules de noyau requis pour le mode de récupération et les modes Android ou Charger complets doivent exister à la fois dans les
rootfs
de récupération et dans les partitions/vendor
ou/odm
(comme décrit ci-dessus). - Les modules du noyau utilisés en mode de récupération ne doivent pas dépendre des modules situés uniquement dans
/vendor
ou/odm
, car ces partitions ne sont pas montées en mode de récupération. - Les modules du noyau du fournisseur SoC ne devraient pas dépendre des modules du noyau ODM.
Sous Android 7.x et versions antérieures, les partitions /vendor
et /odm
ne sont pas montées prématurément. Dans Android 8.x et versions ultérieures, pour rendre possible le chargement de modules à partir de ces partitions, des dispositions ont été prises pour monter les partitions plus tôt pour les appareils non-A/B et A/B . Cela garantit également que les partitions sont montées en modes Android et Charger.
Prise en charge du système de construction Android
Dans BoardConfig.mk
, la version Android définit une variable BOARD_VENDOR_KERNEL_MODULES
qui fournit une liste complète des modules du noyau destinés à l'image du fournisseur. Les modules répertoriés dans cette variable sont copiés dans l'image du fournisseur dans /lib/modules/
et, après avoir été montés sous Android, apparaissent dans /vendor/lib/modules
(conformément aux exigences ci-dessus). Exemple de configuration des modules du noyau du fournisseur :
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
Dans cet exemple, un référentiel prédéfini de module de noyau de fournisseur est mappé dans la version Android à l'emplacement indiqué ci-dessus.
L'image de récupération peut contenir un sous-ensemble des modules du fournisseur. La version Android définit la variable BOARD_RECOVERY_KERNEL_MODULES
pour ces modules. Exemple:
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 version Android se charge d'exécuter depmod
pour générer les fichiers modules.dep
requis dans /vendor/lib/modules
et /lib/modules
( recovery ramfs
).
Chargement et versionnage des modules
Chargez tous les modules du noyau en un seul passage depuis init.rc*
en appelant modprobe -a
. Cela évite la surcharge liée à l'initialisation répétée de l'environnement d'exécution C pour le binaire modprobe
. L'événement early-init
peut être modifié pour invoquer modprobe
:
on early-init exec u:r:vendor_modprobe:s0 -- /vendor/bin/modprobe -a -d \ /vendor/lib/modules module_a module_b module_c ...
Généralement, un module du noyau doit être compilé avec le noyau avec lequel le module doit être utilisé (sinon le noyau refuse de charger le module). CONFIG_MODVERSIONS
fournit une solution de contournement en détectant les ruptures dans l'interface binaire de l'application (ABI). Cette fonctionnalité calcule une valeur de contrôle de redondance cyclique (CRC) pour le prototype de chaque symbole exporté dans le noyau et stocke les valeurs dans le cadre du noyau ; pour les symboles utilisés par un module noyau, les valeurs sont également stockées dans le module noyau. Lorsque le module est chargé, les valeurs des symboles utilisés par le module sont comparées à celles du noyau. Si les valeurs correspondent, le module est chargé ; sinon, la charge échoue.
Pour activer la mise à jour de l'image du noyau séparément de l'image du fournisseur, activez CONFIG_MODVERSIONS
. Cela permet d'effectuer de petites mises à jour du noyau (telles que des corrections de bogues de LTS) tout en maintenant la compatibilité avec les modules de noyau existants dans l'image du fournisseur. Cependant, CONFIG_MODVERSIONS
ne résout pas à lui seul une panne ABI. Si le prototype d'un symbole exporté dans le noyau change, soit en raison d'une modification de la source, soit parce que la configuration du noyau a changé, cela rompt la compatibilité avec les modules du noyau qui utilisent ce symbole. Dans de tels cas, le module noyau doit être recompilé.
Par exemple, la structure task_struct
dans le noyau (définie dans include/linux/sched.h
) contient de nombreux champs inclus conditionnellement en fonction de la configuration du noyau. Le champ sched_info
est présent uniquement si CONFIG_SCHED_INFO
est activé (ce qui se produit lorsque CONFIG_SCHEDSTATS
ou CONFIG_TASK_DELAY_ACCT
sont activés). Si ces options de configuration changent d'état, la disposition de la structure task_struct
change et toutes les interfaces exportées du noyau qui utilisent task_struct
sont modifiées (par exemple, set_cpus_allowed_ptr
dans kernel/sched/core.c
). La compatibilité avec les modules de noyau précédemment compilés qui utilisent ces interfaces est interrompue, nécessitant la reconstruction de ces modules avec la nouvelle configuration du noyau.
Pour plus de détails sur CONFIG_MODVERSIONS
, reportez-vous à la documentation dans l'arborescence du noyau à Documentation/kbuild/modules.rst
.