Modul kernel yang dapat dimuat

Sebagai bagian dari persyaratan kernel modul yang diperkenalkan di Android 8.0, semua kernel system-on-chip (SoC) harus mendukung modul kernel yang dapat dimuat.

Opsi konfigurasi kernel

Untuk mendukung modul kernel yang dapat dimuat, android-base.config di semua kernel umum menyertakan opsi konfigurasi kernel berikut (atau yang setara dengan versi kernelnya):

CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y

Semua kernel perangkat harus mengaktifkan opsi ini. Modul kernel juga harus mendukung penghapusan muatan dan pemuatan ulang jika memungkinkan.

Penandatanganan modul

Penandatanganan modul tidak didukung untuk modul vendor GKI. Pada perangkat yang diperlukan untuk mendukung booting terverifikasi, Android mewajibkan modul kernel berada di partisi yang mengaktifkan dm-verity. Dengan demikian, Anda tidak perlu menandatangani setiap modul untuk keasliannya. Android 13 memperkenalkan konsep modul GKI. Modul GKI menggunakan infrastruktur penandatanganan waktu build kernel untuk membedakan antara GKI dan modul lainnya pada waktu proses. Modul yang tidak ditandatangani diizinkan untuk dimuat selama hanya menggunakan simbol yang muncul di daftar yang diizinkan atau disediakan oleh modul lain yang tidak ditandatangani. Untuk memfasilitasi penandatanganan modul GKI selama build GKI menggunakan pasangan kunci waktu build kernel, konfigurasi kernel GKI telah mengaktifkan CONFIG_MODULE_SIG_ALL=y. Untuk menghindari penandatanganan modul non-GKI selama build kernel perangkat, Anda harus menambahkan # CONFIG_MODULE_SIG_ALL is not set sebagai bagian dari fragmen konfigurasi kernel.

Lokasi file

Meskipun Android 7.x dan yang lebih rendah tidak mewajibkan modul kernel (dan menyertakan dukungan untuk insmod dan rmmod), Android 8.x dan yang lebih tinggi merekomendasikan penggunaan modul kernel dalam ekosistem. Tabel berikut menunjukkan potensi dukungan periferal khusus board yang diperlukan di tiga mode booting Android.

Mode booting Penyimpanan Tampilan Keypad Baterai PMIC Layar sentuh NFC, Wi-Fi,
Bluetooth
Sensor Kamera
Pemulihan
Pengisi daya
Android

Selain ketersediaan dalam mode booting Android, modul kernel juga dapat dikategorikan berdasarkan pemiliknya (vendor SoC atau ODM). Jika modul kernel sedang digunakan, persyaratan untuk penempatannya dalam sistem file adalah sebagai berikut:

  • Semua kernel harus memiliki dukungan bawaan untuk mem-booting dan memasang partisi.
  • Modul kernel harus dimuat dari partisi hanya baca.
  • Untuk perangkat yang diwajibkan untuk memiliki booting terverifikasi, modul kernel harus dimuat dari partisi terverifikasi.
  • Modul kernel tidak boleh berada di /system.
  • Modul GKI yang diperlukan untuk perangkat harus dimuat dari /system/lib/modules yang merupakan link simbolis ke /system_dlkm/lib/modules.
  • Modul kernel dari vendor SoC yang diperlukan untuk mode Android penuh atau Pengisi daya harus berada di /vendor/lib/modules.
  • Jika partisi ODM ada, modul kernel dari ODM yang diperlukan untuk mode Android atau Pengisi Daya penuh harus berada di /odm/lib/modules. Jika tidak, modul ini harus berada di /vendor/lib/modules.
  • Modul kernel dari vendor SoC dan ODM yang diperlukan untuk mode Pemulihan harus berada di ramfs pemulihan di /lib/modules.
  • Modul kernel yang diperlukan untuk mode Pemulihan dan mode Android atau Pengisi Daya penuh harus ada di rootfs pemulihan dan partisi /vendor atau /odm (seperti yang dijelaskan di atas).
  • Modul kernel yang digunakan dalam mode Pemulihan tidak boleh bergantung pada modul yang hanya berada di /vendor atau /odm, karena partisi tersebut tidak dipasang dalam mode Pemulihan.
  • Modul kernel vendor SoC tidak boleh bergantung pada modul kernel ODM.

Di Android 7.x dan yang lebih lama, partisi /vendor dan /odm tidak dipasang lebih awal. Di Android 8.x dan yang lebih tinggi, untuk memungkinkan pemuatan modul dari partisi ini, ketentuan telah dibuat untuk memasang partisi lebih awal untuk perangkat non-A/B dan A/B. Tindakan ini juga memastikan partisi dipasang dalam mode Android dan Pengisi Daya.

Dukungan sistem build Android

Di BoardConfig.mk, build Android menentukan variabel BOARD_VENDOR_KERNEL_MODULES yang memberikan daftar lengkap modul kernel yang ditujukan untuk image vendor. Modul yang tercantum dalam variabel ini disalin ke dalam image vendor di /lib/modules/, dan, setelah dipasang di Android, muncul di /vendor/lib/modules (sesuai dengan persyaratan di atas). Contoh konfigurasi modul kernel vendor:

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

Dalam contoh ini, repositori bawaan modul kernel vendor dipetakan ke build Android di lokasi yang tercantum di atas.

Image pemulihan dapat berisi subset modul vendor. Build Android menentukan variabel BOARD_RECOVERY_KERNEL_MODULES untuk modul ini. Contoh:

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

Build Android akan menjalankan depmod untuk membuat file modules.dep yang diperlukan di /vendor/lib/modules dan /lib/modules (recovery ramfs).

Pemuatan dan pembuatan versi modul

Muat semua modul kernel dalam satu kali operasi dari init.rc* dengan memanggil modprobe -a. Hal ini menghindari overhead inisialisasi berulang lingkungan runtime C untuk biner modprobe. Peristiwa early-init dapat diubah untuk memanggil modprobe:

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

Biasanya, modul kernel harus dikompilasi dengan kernel yang akan digunakan modul tersebut (jika tidak, kernel akan menolak memuat modul). CONFIG_MODVERSIONS memberikan solusi dengan mendeteksi kerusakan di antarmuka biner aplikasi (ABI). Fitur ini menghitung nilai cyclic redundancy check (CRC) untuk prototipe setiap simbol yang diekspor di kernel dan menyimpan nilai sebagai bagian dari kernel; untuk simbol yang digunakan oleh modul kernel, nilai juga disimpan dalam modul kernel. Saat modul dimuat, nilai untuk simbol yang digunakan oleh modul akan dibandingkan dengan nilai di kernel. Jika nilainya cocok, modul akan dimuat; jika tidak, pemuatan akan gagal.

Untuk mengaktifkan update image kernel secara terpisah dari image vendor, aktifkan CONFIG_MODVERSIONS. Tindakan ini memungkinkan update kecil pada kernel (seperti perbaikan bug dari LTS) dilakukan sekaligus mempertahankan kompatibilitas dengan modul kernel yang ada dalam image vendor. Namun, CONFIG_MODVERSIONS tidak memperbaiki kerusakan ABI dengan sendirinya. Jika prototipe simbol yang diekspor di kernel berubah, baik karena modifikasi sumber atau karena konfigurasi kernel berubah, hal ini akan merusak kompatibilitas dengan modul kernel yang menggunakan simbol tersebut. Dalam kasus tersebut, modul kernel harus dikompilasi ulang.

Misalnya, struktur task_struct di kernel (ditentukan dalam include/linux/sched.h) berisi banyak kolom yang disertakan secara kondisional bergantung pada konfigurasi kernel. Kolom sched_info hanya ada jika CONFIG_SCHED_INFO diaktifkan (yang terjadi saat CONFIG_SCHEDSTATS atau CONFIG_TASK_DELAY_ACCT diaktifkan). Jika opsi konfigurasi ini mengubah status, tata letak struktur task_struct akan berubah dan antarmuka apa pun yang diekspor dari kernel yang menggunakan task_struct akan diubah (misalnya, set_cpus_allowed_ptr di kernel/sched/core.c). Kompatibilitas dengan modul kernel yang dikompilasi sebelumnya yang menggunakan antarmuka ini akan rusak, sehingga modul tersebut harus dibuat ulang dengan konfigurasi kernel baru.

Untuk mengetahui detail selengkapnya tentang CONFIG_MODVERSIONS, lihat dokumentasi di hierarki kernel di Documentation/kbuild/modules.rst.