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 versi kernel yang setara):

CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y

Semua kernel perangkat harus mengaktifkan opsi ini. Modul kernel juga harus mendukung pembongkaran dan pemuatan ulang bila memungkinkan.

Penandatanganan modul

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

Lokasi berkas

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 boot Android.

Mode boot Penyimpanan Menampilkan Papan tombol Baterai PMIC Layar sentuh NFC, WiFi,
Bluetooth
Sensor Kamera
Pemulihan
Pengisi daya
Android

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

  • Semua kernel harus memiliki dukungan bawaan untuk booting dan pemasangan partisi.
  • Modul kernel harus dimuat dari partisi read-only.
  • Untuk perangkat yang memerlukan boot terverifikasi, modul kernel harus dimuat dari partisi terverifikasi.
  • Modul kernel tidak boleh ditempatkan di /system .
  • Modul GKI yang diperlukan untuk perangkat harus dimuat dari /system/lib/modules yang merupakan tautan simbolik ke /system_dlkm/lib/modules .
  • Modul kernel dari vendor SoC yang diperlukan untuk mode Android atau Charger penuh harus ditempatkan di /vendor/lib/modules .
  • Jika ada partisi ODM, modul kernel dari ODM yang diperlukan untuk mode Android atau Charger lengkap harus ditempatkan di /odm/lib/modules . Jika tidak, modul-modul ini harus ditempatkan di /vendor/lib/modules .
  • Modul kernel dari vendor SoC dan ODM yang diperlukan untuk mode Pemulihan harus ditempatkan di ramfs pemulihan di /lib/modules .
  • Modul kernel yang diperlukan untuk mode Pemulihan dan mode Android atau Pengisi Daya lengkap harus ada di rootfs pemulihan dan partisi /vendor atau /odm (seperti dijelaskan di atas).
  • Modul kernel yang digunakan dalam mode Pemulihan tidak boleh bergantung pada modul yang terletak hanya 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 rendah, partisi /vendor dan /odm tidak dipasang lebih awal. Di Android 8.x dan yang lebih tinggi, agar pemuatan modul dari partisi ini dapat dilakukan, ketentuan telah dibuat untuk memasang partisi lebih awal untuk perangkat non-A/B dan A/B . Ini juga memastikan bahwa partisi dipasang dalam mode Android dan Charger.

Dukungan sistem build Android

Di BoardConfig.mk , build Android mendefinisikan variabel BOARD_VENDOR_KERNEL_MODULES yang menyediakan daftar lengkap modul kernel yang ditujukan untuk image vendor. Modul yang tercantum dalam variabel ini disalin ke gambar 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 modul kernel vendor yang telah dibuat sebelumnya dipetakan ke dalam build Android di lokasi yang tercantum di atas.

Gambar pemulihan mungkin berisi subset modul vendor. Versi Android mendefinisikan 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 menangani menjalankan depmod untuk menghasilkan 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 pass dari init.rc* dengan menjalankan modprobe -a . Hal ini menghindari overhead berulang kali menginisialisasi lingkungan runtime C untuk biner modprobe . Acara early-init dapat dimodifikasi 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 dengan modul tersebut (jika tidak, kernel akan menolak memuat modul). CONFIG_MODVERSIONS memberikan solusi dengan mendeteksi kerusakan pada antarmuka biner aplikasi (ABI). Fitur ini menghitung nilai cyclic redundancy check (CRC) untuk prototipe setiap simbol yang diekspor di kernel dan menyimpan nilai tersebut sebagai bagian dari kernel; untuk simbol yang digunakan oleh modul kernel, nilainya juga disimpan dalam modul kernel. Ketika modul dimuat, nilai simbol yang digunakan oleh modul dibandingkan dengan yang ada di kernel. Jika nilainya cocok, modul dimuat; jika tidak, beban akan gagal.

Untuk mengaktifkan pembaruan image kernel secara terpisah dari image vendor, aktifkan CONFIG_MODVERSIONS . Hal ini memungkinkan pembaruan kecil pada kernel (seperti perbaikan bug dari LTS) dilakukan dengan tetap menjaga kompatibilitas dengan modul kernel yang ada di 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 seperti ini, modul kernel harus dikompilasi ulang.

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

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