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.cfg 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 memerlukan modul kernel berada di partisi yang mengaktifkan dm-verity. Ini menghilangkan kebutuhan untuk menandatangani modul individual untuk keasliannya.

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 di ekosistem. Tabel berikut menunjukkan potensi dukungan periferal khusus papan 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 siapa pemiliknya (vendor SoC atau ODM). Jika modul kernel digunakan, persyaratan penempatannya di sistem file adalah sebagai berikut:

  • Semua kernel harus memiliki dukungan bawaan untuk mem-boot dan memasang 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 berada di /system .
  • Modul kernel dari vendor SoC yang diperlukan untuk mode Android atau Charger lengkap harus ditempatkan di /vendor/lib/modules .
  • Jika ada partisi ODM, modul kernel dari ODM yang diperlukan untuk mode Android atau Charger penuh harus ditempatkan di /odm/lib/modules . Jika tidak, 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 hanya terletak 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, untuk memungkinkan pemuatan modul dari partisi ini, ketentuan telah dibuat untuk memasang partisi lebih awal untuk perangkat non-A/B dan A/B . Ini juga memastikan bahwa partisi dipasang di mode Android dan Charger.

Dukungan sistem pembangunan Android

Di BoardConfig.mk , Android build mendefinisikan variabel BOARD_VENDOR_KERNEL_MODULES yang menyediakan daftar lengkap modul kernel yang ditujukan untuk citra 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 bawaan modul kernel vendor dipetakan ke dalam build Android di lokasi yang tercantum di atas.

Gambar pemulihan mungkin berisi subset dari modul vendor. Android build 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

Pembangunan Android menangani menjalankan depmod untuk menghasilkan file modules.dep yang diperlukan di /vendor/lib/modules dan /lib/modules ( recovery ramfs ).

Pemuatan modul dan pembuatan versi

Muat semua modul kernel dalam satu lintasan dari init.rc* dengan menjalankan modprobe -a . 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 modul tersebut (jika tidak, kernel menolak untuk memuat modul). CONFIG_MODVERSIONS menyediakan 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, 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 gagal.

Untuk mengaktifkan pembaruan citra kernel secara terpisah dari citra vendor, aktifkan CONFIG_MODVERSIONS . Melakukannya memungkinkan pembaruan kecil pada kernel (seperti perbaikan bug dari LTS) dilakukan sambil mempertahankan 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, ini merusak kompatibilitas dengan modul kernel yang menggunakan simbol itu. Dalam kasus seperti itu, modul kernel harus dikompilasi ulang.

Misalnya, struktur task_struct di kernel (didefinisikan dalam include/linux/sched.h ) berisi banyak bidang yang disertakan secara kondisional tergantung 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 mengubah status, tata letak struktur task_struct berubah dan antarmuka 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 terputus, membutuhkan modul tersebut untuk dibangun kembali dengan konfigurasi kernel baru.

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