Theo yêu cầu về hạt nhân mô-đun được giới thiệu trong Android 8.0, tất cả hạt nhân hệ thống trên chip (SoC) đều phải hỗ trợ các mô-đun hạt nhân có thể tải.
Các tuỳ chọn cấu hình hạt nhân
Để hỗ trợ các mô-đun hạt nhân có thể tải, android-base.config trong tất cả các hạt nhân phổ biến bao gồm các tuỳ chọn cấu hình hạt nhân sau (hoặc tương đương với phiên bản hạt nhân):
CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y
Tất cả nhân thiết bị đều phải bật các tuỳ chọn này. Các mô-đun hạt nhân cũng phải hỗ trợ việc tải xuống và tải lại bất cứ khi nào có thể.
Ký mô-đun
Tính năng ký mô-đun không được hỗ trợ cho các mô-đun nhà cung cấp GKI. Trên các thiết bị bắt buộc phải hỗ trợ tính năng khởi động đã xác minh, Android yêu cầu các mô-đun hạt nhân phải nằm trong các phân vùng đã bật dm-verity. Nhờ đó, bạn không cần phải ký từng mô-đun để xác thực tính xác thực của các mô-đun đó.
Android 13 đã giới thiệu khái niệm về các mô-đun GKI. Các mô-đun GKI sử dụng cơ sở hạ tầng ký thời gian xây dựng của hạt nhân để phân biệt giữa GKI và các mô-đun khác trong thời gian chạy.
Các mô-đun chưa ký được phép tải miễn là chỉ sử dụng các ký hiệu xuất hiện trong danh sách cho phép hoặc do các mô-đun chưa ký khác cung cấp.
Để tạo điều kiện ký các mô-đun GKI trong bản dựng GKI bằng cách sử dụng cặp khoá thời gian xây dựng của hạt nhân, cấu hình hạt nhân GKI đã bật CONFIG_MODULE_SIG_ALL=y
.
Để tránh ký các mô-đun không phải GKI trong các bản dựng hạt nhân thiết bị, bạn phải thêm # CONFIG_MODULE_SIG_ALL is not set
vào các mảnh cấu hình hạt nhân.
Vị trí tệp
Mặc dù Android 7.x trở xuống không bắt buộc phải sử dụng mô-đun hạt nhân (và bao gồm cả tính năng hỗ trợ cho insmod
và rmmod
), nhưng Android 8.x trở lên nên sử dụng mô-đun hạt nhân trong hệ sinh thái. Bảng sau đây cho thấy khả năng hỗ trợ thiết bị ngoại vi dành riêng cho bo mạch cần thiết trong 3 chế độ khởi động Android.
Chế độ khởi động | Dung lượng lưu trữ | Màn hình | Bàn phím | Pin | PMIC | Màn hình cảm ứng | NFC, Wi-Fi, Bluetooth |
Cảm biến | Camera |
---|---|---|---|---|---|---|---|---|---|
Khôi phục | |||||||||
Bộ sạc | |||||||||
Android |
Ngoài việc có sẵn trong các chế độ khởi động Android, các mô-đun hạt nhân cũng có thể được phân loại theo chủ sở hữu (nhà cung cấp SoC hoặc ODM). Nếu bạn đang sử dụng các mô-đun hạt nhân, thì các yêu cầu về vị trí của các mô-đun này trong hệ thống tệp như sau:
- Tất cả nhân đều phải có tính năng hỗ trợ tích hợp để khởi động và gắn các phân vùng.
- Các mô-đun hạt nhân phải được tải từ một phân vùng chỉ có thể đọc.
- Đối với các thiết bị bắt buộc phải có quy trình khởi động đã xác minh, các mô-đun hạt nhân phải được tải từ các phân vùng đã xác minh.
- Mô-đun hạt nhân không được nằm trong
/system
. - Các mô-đun GKI cần thiết cho thiết bị phải được tải từ
/system/lib/modules
, đây là một đường liên kết tượng trưng đến/system_dlkm/lib/modules
. - Các mô-đun hạt nhân của nhà cung cấp SoC cần thiết cho chế độ Android đầy đủ hoặc sạc phải nằm trong
/vendor/lib/modules
. - Nếu có phân vùng ODM, thì các mô-đun hạt nhân từ ODM cần thiết cho chế độ Android đầy đủ hoặc chế độ sạc phải nằm trong
/odm/lib/modules
. Nếu không, các mô-đun này phải nằm trong/vendor/lib/modules
. - Các mô-đun hạt nhân của nhà cung cấp SoC và ODM cần thiết cho chế độ Recovery (Khôi phục) phải nằm trong
ramfs
khôi phục tại/lib/modules
. - Các mô-đun hạt nhân cần thiết cho cả Chế độ khôi phục và chế độ sạc Android hoặc sạc đầy phải tồn tại cả trong
rootfs
khôi phục và phân vùng/vendor
hoặc/odm
(như mô tả ở trên). - Các mô-đun hạt nhân dùng trong chế độ Khôi phục không được phụ thuộc vào các mô-đun chỉ nằm trong
/vendor
hoặc/odm
, vì các phân vùng đó không được gắn trong chế độ Khôi phục. - Mô-đun hạt nhân của nhà cung cấp SoC không được phụ thuộc vào mô-đun hạt nhân ODM.
Trong Android 7.x trở xuống, các phân vùng /vendor
và /odm
không được gắn sớm. Trong Android 8.x trở lên, để có thể tải mô-đun từ các phân vùng này, chúng tôi đã cung cấp các biện pháp để gắn sớm các phân vùng cho cả thiết bị không phải A/B và A/B. Điều này cũng đảm bảo rằng các phân vùng được gắn ở cả chế độ Android và chế độ sạc.
Hỗ trợ hệ thống xây dựng Android
Trong BoardConfig.mk
, bản dựng Android xác định một biến BOARD_VENDOR_KERNEL_MODULES
cung cấp danh sách đầy đủ các mô-đun hạt nhân dành cho hình ảnh của nhà cung cấp. Các mô-đun được liệt kê trong biến này sẽ được sao chép vào hình ảnh nhà cung cấp tại /lib/modules/
và sau khi được gắn trong Android, sẽ xuất hiện trong /vendor/lib/modules
(theo các yêu cầu ở trên).
Ví dụ về cấu hình của các mô-đun hạt nhân của nhà cung cấp:
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
Trong ví dụ này, kho lưu trữ tạo sẵn của mô-đun hạt nhân của nhà cung cấp được liên kết vào bản dựng Android tại vị trí nêu trên.
Hình ảnh khôi phục có thể chứa một tập hợp con của các mô-đun nhà cung cấp. Bản dựng Android xác định biến BOARD_RECOVERY_KERNEL_MODULES
cho các mô-đun này. Ví dụ:
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
Bản dựng Android sẽ chạy depmod
để tạo các tệp modules.dep
bắt buộc trong /vendor/lib/modules
và /lib/modules
(recovery ramfs
).
Tải và tạo phiên bản mô-đun
Tải tất cả mô-đun hạt nhân trong một lượt từ init.rc*
bằng cách gọi modprobe -a
. Điều này giúp tránh hao tổn khi khởi chạy môi trường thời gian chạy C nhiều lần cho tệp nhị phân modprobe
. Bạn có thể sửa đổi sự kiện early-init
để gọi modprobe
:
on early-init exec u:r:vendor_modprobe:s0 -- /vendor/bin/modprobe -a -d \ /vendor/lib/modules module_a module_b module_c ...
Thông thường, mô-đun hạt nhân phải được biên dịch bằng hạt nhân mà mô-đun sẽ sử dụng (nếu không, hạt nhân sẽ từ chối tải mô-đun).
CONFIG_MODVERSIONS
cung cấp giải pháp tạm thời bằng cách phát hiện các lỗi trong giao diện nhị phân của ứng dụng (ABI). Tính năng này tính toán giá trị kiểm tra dự phòng tuần hoàn (CRC) cho nguyên mẫu của mỗi biểu tượng được xuất trong hạt nhân và lưu trữ các giá trị đó trong hạt nhân; đối với các biểu tượng do mô-đun hạt nhân sử dụng, các giá trị này cũng được lưu trữ trong mô-đun hạt nhân. Khi mô-đun được tải, các giá trị cho các ký hiệu mà mô-đun sử dụng sẽ được so sánh với các giá trị trong hạt nhân. Nếu các giá trị khớp nhau, mô-đun sẽ được tải; nếu không, quá trình tải sẽ không thành công.
Để bật tính năng cập nhật hình ảnh hạt nhân riêng biệt với hình ảnh của nhà cung cấp, hãy bật CONFIG_MODVERSIONS
. Việc này cho phép thực hiện các bản cập nhật nhỏ cho hạt nhân (chẳng hạn như bản sửa lỗi từ LTS) trong khi vẫn duy trì khả năng tương thích với các mô-đun hạt nhân hiện có trong hình ảnh của nhà cung cấp. Tuy nhiên, CONFIG_MODVERSIONS
không tự khắc phục được sự cố ABI. Nếu nguyên mẫu của một biểu tượng đã xuất trong hạt nhân thay đổi, do sửa đổi nguồn hoặc do cấu hình hạt nhân thay đổi, thì điều này sẽ làm mất khả năng tương thích với các mô-đun hạt nhân sử dụng biểu tượng đó. Trong những trường hợp như vậy, bạn phải biên dịch lại mô-đun hạt nhân.
Ví dụ: cấu trúc task_struct
trong hạt nhân (được xác định trong include/linux/sched.h
) chứa nhiều trường được đưa vào có điều kiện tuỳ thuộc vào cấu hình hạt nhân. Trường sched_info
chỉ xuất hiện nếu bạn bật CONFIG_SCHED_INFO
(xảy ra khi bạn bật CONFIG_SCHEDSTATS
hoặc CONFIG_TASK_DELAY_ACCT
). Nếu các tuỳ chọn cấu hình này thay đổi trạng thái, bố cục của cấu trúc task_struct
sẽ thay đổi và mọi giao diện được xuất từ hạt nhân sử dụng task_struct
sẽ bị thay đổi (ví dụ: set_cpus_allowed_ptr
trong kernel/sched/core.c
). Khả năng tương thích với các mô-đun hạt nhân được biên dịch trước đó sử dụng các giao diện này sẽ bị gián đoạn, đòi hỏi các mô-đun đó phải được tạo lại bằng cấu hình hạt nhân mới.
Để biết thêm thông tin chi tiết về CONFIG_MODVERSIONS
, hãy tham khảo tài liệu trong cây nhân hệ điều hành tại Documentation/kbuild/modules.rst
.