Mô-đun nhân có thể tải được

Là một phần của yêu cầu 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) phải hỗ trợ các mô-đun hạt nhân có thể tải được.

Tùy 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 tùy chọn kernel-config sau (hoặc phiên bản hạt nhân tương đương của chúng):

CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y

Tất cả các hạt nhân của thiết bị phải kích hoạt các tùy chọn này. Các mô-đun hạt nhân cũng phải hỗ trợ việc dỡ tải và tải lại bất cứ khi nào có thể.

Ký mô-đun

Việc ký mô-đun không được hỗ trợ cho các mô-đun của nhà cung cấp GKI. Trên các thiết bị được yêu cầu hỗ trợ 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. Điều này loại bỏ nhu cầu ký các mô-đun riêng lẻ để đảm bảo tính xác thực của chúng. Android 13 đã giới thiệu khái niệm về 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 được ký được phép tải miễn là chúng chỉ sử dụng các ký hiệu xuất hiện trên danh sách cho phép hoặc được cung cấp bởi các mô-đun chưa được ký khác. Để tạo điều kiện thuận lợi cho việc ký các mô-đun GKI trong quá trình xây dựng GKI bằng cặp khóa thời gian xây dựng của kernel, cấu hình kernel GKI đã bật CONFIG_MODULE_SIG_ALL=y . Để tránh ký các mô-đun không phải GKI trong quá trình xây dựng hạt nhân thiết bị, bạn phải thêm # CONFIG_MODULE_SIG_ALL is not set làm một phần của các đoạn cấu hình hạt nhân của bạ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 hỗ trợ cho insmodrmmod ), Android 8.x trở lên khuyến nghị 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ợ ngoại vi dành riêng cho bo mạch cụ thể được yêu cầu trên ba chế độ khởi động Android.

Chế độ khởi động Kho Trưng bày Bàn phím Ắc quy PMIC Màn hình cảm ứng NFC, Wi-Fi,
Bluetooth
Cảm biến Máy ảnh
Sự hồi phục
Bộ sạc
Android

Ngoài tính khả dụng trong chế độ khởi động Android, các mô-đun hạt nhân cũng có thể được phân loại theo người sở hữu chúng (nhà cung cấp SoC hoặc ODM). Nếu các mô-đun hạt nhân đang được sử dụng, các yêu cầu về vị trí của chúng trong hệ thống tệp như sau:

  • Tất cả các hạt nhân phải có hỗ trợ tích hợp để khởi động và gắn kết các phân vùng.
  • Các mô-đun hạt nhân phải được tải từ phân vùng chỉ đọc.
  • Đối với các thiết bị được yêu cầu khởi động đã được xác minh, các mô-đun hạt nhân phải được tải từ các phân vùng đã được xác minh.
  • Các mô-đun hạt nhân không nên được đặt 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à liên kết tượng trưng đến /system_dlkm/lib/modules .
  • Các mô-đun hạt nhân từ nhà cung cấp SoC được yêu cầu cho chế độ Android hoặc Bộ sạc đầy đủ phải được đặt trong /vendor/lib/modules .
  • Nếu phân vùng ODM tồn tại, các mô-đun hạt nhân từ ODM được yêu cầu cho chế độ Android hoặc Bộ sạc đầy đủ phải được đặt trong /odm/lib/modules . Nếu không, các mô-đun này phải được đặt trong /vendor/lib/modules .
  • Các mô-đun hạt nhân từ nhà cung cấp SoC và ODM được yêu cầu cho chế độ Khôi phục phải được đặt 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ế độ Android hoặc Bộ sạc đầy đủ phải tồn tại cả trong rootfs khôi phục và các phân vùng /vendor hoặc /odm (như được mô tả ở trên).
  • Các mô-đun hạt nhân được sử dụng trong chế độ Khôi phục không nên 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 nên 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/odm không được gắn kết sớm. Trong Android 8.x trở lên, để có thể tải mô-đun từ các phân vùng này, các điều khoản đã được thực hiện để gắn kết các phân vùng sớm 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à Bộ sạc.

Hỗ trợ hệ thống xây dựng Android

Trong BoardConfig.mk , bản dựng Android xác định 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 nhà cung cấp. Các mô-đun được liệt kê trong biến này được sao chép vào hình ảnh nhà cung cấp tại /lib/modules/ và sau khi được gắn vào Android, sẽ xuất hiện trong /vendor/lib/modules (theo các yêu cầu trên). Cấu hình ví dụ về 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ữ dựng sẵn mô-đun hạt nhân của nhà cung cấp được ánh xạ vào bản dựng Android tại vị trí được liệt kê ở trên.

Hình ảnh khôi phục có thể chứa một tập hợp con các mô-đun của 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 đảm nhiệm việc chạy depmod để tạo các tệp modules.dep cần thiết trong /vendor/lib/modules/lib/modules ( recovery ramfs ).

Tải mô-đun và phiên bản

Tải tất cả các mô-đun hạt nhân trong một lần truyền từ init.rc* bằng cách gọi modprobe -a . Điều này tránh được chi phí khởi tạo liên tục môi trường thời gian chạy C cho tệp nhị phân modprobe . Sự kiện early-init có thể được sửa đổi để 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ẽ được sử dụng cù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 thay thế bằng cách phát hiện sự cố 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 theo chu kỳ (CRC) cho nguyên mẫu của từng ký hiệu được xuất trong nhân và lưu trữ các giá trị như một phần của nhân; đối với các ký hiệu được mô-đun hạt nhân sử dụng, các giá trị 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 được mô-đun sử dụng sẽ được so sánh với các giá trị trong kernel. Nếu các giá trị khớp nhau thì mô-đun sẽ được tải; nếu không thì tải không thành công.

Để cho phép cập nhật hình ảnh hạt nhân riêng biệt với hình ảnh nhà cung cấp, hãy bật CONFIG_MODVERSIONS . Làm như vậy cho phép thực hiện các cập nhật nhỏ cho hạt nhân (chẳng hạn như 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 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 ký hiệu được 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, điều này sẽ phá vỡ tính tương thích với các mô-đun hạt nhân sử dụng ký hiệu đó. Trong những trường hợp như vậy, mô-đun hạt nhân phải được biên dịch lại.

Ví dụ: cấu trúc task_struct trong kernel (được xác định trong include/linux/sched.h ) chứa nhiều trường được bao gồm có điều kiện tùy thuộc vào cấu hình kernel. Trường sched_info chỉ xuất hiện nếu CONFIG_SCHED_INFO được bật (xảy ra khi CONFIG_SCHEDSTATS hoặc CONFIG_TASK_DELAY_ACCT được bật). Nếu các tùy 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ừ ​​kernel sử dụng task_struct đều 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 bị hỏng, yêu cầu các mô-đun đó phải được xây dựng lại bằng cấu hình hạt nhân mới.

Để biết thêm chi tiết về CONFIG_MODVERSIONS , hãy tham khảo tài liệu trong cây nhân tại Documentation/kbuild/modules.rst .