Ładowane moduły jądra

W ramach wymagań jądra modułów wprowadzonych w Androidzie 8.0 wszystkie Jądra systemu SOC muszą obsługiwać możliwe do załadowania moduły jądra.

Opcje konfiguracji jądra systemu

Aby zapewnić obsługę wczytywanych modułów jądra, Plik android-base.config we wszystkich popularnych jądrach zawiera komponent następujące opcje konfiguracji jądra (lub ich odpowiedniki w wersji jądra):

CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y

Wszystkie jądra urządzeń muszą mieć włączone te opcje. Moduły jądra powinny obsługują wyładowywanie i ponowne ładowanie.

Podpisywanie modułu

Podpisywanie modułów nie jest obsługiwane w przypadku modułów dostawcy GKI. Na urządzeniach wymaganych do obsługa weryfikacji podczas uruchamiania, Android wymaga, aby moduły jądra były umieszczone na partycjach. z włączoną usługą dm-verity. Eliminuje to potrzebę podpisywania indywidualnej osoby modułów za ich autentyczność. W Androidzie 13 wprowadzono koncepcję modułów GKI. Moduły GKI używają czasu kompilacji jądra infrastruktury podpisywania w celu odróżniania GKI od innych modułów w czasie działania. Moduły niepodpisane mogą się ładować, pod warunkiem że zawierają tylko symbole znajdujące się na liście dozwolonych lub dostarczane przez inne niepodpisane moduły. Aby ułatwić podpisywanie modułów GKI podczas kompilacji GKI za pomocą pary kluczy czasu kompilacji jądra, Konfiguracja jądra GKI włączyła funkcję CONFIG_MODULE_SIG_ALL=y. Aby uniknąć podpisywania modułów innych niż GKI podczas kompilacji jądra urządzenia, musisz dodać # CONFIG_MODULE_SIG_ALL is not set w ramach konfiguracji jądra fragmenty.

Lokalizacje plików

Android 7.x i starsze nie wymagają stosowania modułów jądra obsługa systemów insmod i rmmod), Androida 8.x i zalecają korzystanie w ekosystemie z modułów jądra. Poniżej Tabela przedstawia potencjalną obsługę konkretnej płyty peryferyjnej wymaganej przez trzy Tryby uruchamiania Androida.

Tryb uruchamiania Miejsce na dane Wyświetlacz Klawiatura Bateria PMIC, Ekran dotykowy NFC, Wi-Fi,
Bluetooth
Czujniki Aparat
Odzyskanie
Ładowarka
Android

Poza dostępnością w trybach rozruchu Androida moduły jądra mogą być również są podzielone na kategorie według tego, kto jest ich właścicielem (dostawcy układu SOC lub ODM). Jeśli moduły jądra systemu ich umiejscowienie w systemie plików następujące:

  • Wszystkie jądra powinny mieć wbudowaną obsługę uruchamiania i montowania partycji.
  • Moduły jądra muszą być ładowane z partycji tylko do odczytu.
  • Aby urządzenia wymagały weryfikacji podczas uruchamiania, moduły jądra systemu powinny być załadowano ze zweryfikowanych partycji.
  • Moduły jądra nie powinny znajdować się w regionie /system.
  • Moduły GKI wymagane przez urządzenie powinny być ładowane z /system/lib/modules, który jest łączem symbolicznym do: /system_dlkm/lib/modules
  • Moduły jądra systemu SOC, które są wymagane do działania pełnej wersji Androida lub Tryby ładowarki powinny znajdować się w trybie /vendor/lib/modules.
  • Jeśli istnieje partycja ODM, wymagane są moduły jądra ODM. w trybie pełnego Androida lub ładowania należy znajdować się w /odm/lib/modules W przeciwnym razie moduły te powinny znajdować się w /vendor/lib/modules
  • Moduły jądra systemu SoC i ODM wymagane do przywracania tryb powinien znajdować się w sekcji odzyskiwania (ramfs) na /lib/modules
  • Moduły jądra są wymagane zarówno w trybie odzyskiwania, jak i w wersji z pełną wersją Androida lub Tryby ładowarki powinny być dostępne zarówno w trybie rootfs odzyskiwania, jak i partycję /vendor lub /odm (zgodnie z opisem) powyżej).
  • Moduły jądra używane w trybie przywracania nie powinny zależeć od modułów znajdujących się tylko w /vendor lub /odm, ponieważ te partycje nie są podłączonych w trybie odzyskiwania.
  • Moduły jądra dostawcy SoC nie powinny opierać się na modułach jądra ODM.

Na Androidzie 7.x i starszych: /vendor i /odm partycje nie są podłączone wcześnie. W Androidzie 8.x i nowszych aby możliwe było ładowanie modułów z tych partycji, zasoby reklamowe zostały udostępnione wczesne montowanie partycji w obu urządzeniami innych niż A/B i A/B. To także pozwala na zamontowanie partycji zarówno w trybie Androida, jak i w trybie ładowarki.

Obsługa systemu Android Build

W BoardConfig.mk kompilacja Androida definiuje Zmienna BOARD_VENDOR_KERNEL_MODULES, która przedstawia pełną listę modułów jądra przeznaczonych dla obrazu dostawcy. Moduły wymienione w ta zmienna jest kopiowana do obrazu dostawcy pod adresem /lib/modules/, Po podłączeniu do Androida /vendor/lib/modules (zgodnie z powyższymi wymaganiami). Przykładowa konfiguracja modułów jądra dostawcy:

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

W tym przykładzie gotowe repozytorium modułu jądra dostawcy jest mapowane kompilację Androida w podanej wyżej lokalizacji.

Obraz przywracania może zawierać podzbiór modułów dostawcy. Android kompilacja definiuje zmienną BOARD_RECOVERY_KERNEL_MODULES dla dla tych modułów. Przykład:

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

Kompilacja Androida obsługuje uruchamianie depmod, aby generować wymagane pliki: modules.dep w zasobniku /vendor/lib/modules i /lib/modules (recovery ramfs).

Wczytywanie modułu i obsługa wersji

Wczytaj wszystkie moduły jądra w jednej przepustce z init.rc* przez wywołanie modprobe -a Pozwala to uniknąć konieczności wielokrotnego inicjowania w środowisku wykonawczym C dla pliku binarnego modprobe. Zdarzenie early-init można zmodyfikować, aby wywoływać metodę modprobe:

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

Zazwyczaj moduł jądra systemu musi być skompilowany z jądrem, z którym ma być używany (w przeciwnym razie jądro zablokuje załadowanie modułu). CONFIG_MODVERSIONS udostępnia obejście polegające na wykrywaniu usterek w interfejsie binarnym aplikacji (ABI). Ta funkcja oblicza cykl kontroli nadmiarowości (CRC) dla prototypu każdego wyeksportowanego symbolu w ją jądra i przechowuje wartości w jego ramach; dla symboli używanych przez , wartości są również przechowywane w module jądra. Gdy jest wczytywany, wartości symboli używanych przez moduł są porównywane i te w jądrze. Jeśli wartości są zgodne, moduł jest wczytywany. w przeciwnym razie wczytywanie się nie uda.

Aby umożliwić aktualizowanie obrazu jądra niezależnie od obrazu dostawcy, włącz funkcję CONFIG_MODVERSIONS. Pozwoli to wprowadzić niewielkie aktualizacje jądro (np. poprawki błędów z LTS), które należy wprowadzić przy zachowaniu zgodności z istniejącymi modułami jądra w obrazie dostawcy. Pamiętaj jednak: CONFIG_MODVERSIONS samo w sobie nie naprawia błędu ABI. Jeśli prototyp wyeksportowanego symbolu w jądrze zmienia się z powodu ze względu na zmianę źródła lub konfigurację jądra, narusza zgodność z modułami jądra używającymi tego symbolu. W takich przypadkach moduł jądra systemu należy skompilować ponownie.

Na przykład struktura task_struct w jądrze (zdefiniowana w include/linux/sched.h) zawiera wiele pól warunkowo w zależności od konfiguracji jądra systemu operacyjnego. sched_info jest dostępne tylko wtedy, gdy włączona jest opcja CONFIG_SCHED_INFO (która występuje, gdy CONFIG_SCHEDSTATS lub CONFIG_TASK_DELAY_ACCT). Jeśli te konfiguracje opcje zmieniają stan, układ struktury task_struct i wszystkich wyeksportowanych interfejsów z jądra, które używają task_struct zostały zmienione (na przykład set_cpus_allowed_ptr w kernel/sched/core.c). Zgodność ze skompilowanymi wcześniej modułami jądra, które korzystają z tych interfejsów ulegają awarii, co wymaga odbudowy tych modułów za pomocą nowego jądra systemu konfiguracji.

Więcej informacji o CONFIG_MODVERSIONS znajdziesz tutaj: w drzewie jądra pod adresem Documentation/kbuild/modules.rst