ماژول های هسته قابل بارگیری

به عنوان بخشی از الزامات هسته ماژول معرفی شده در Android 8.0، همه هسته های سیستم روی تراشه (SoC) باید از ماژول های هسته قابل بارگیری پشتیبانی کنند.

گزینه های پیکربندی هسته

برای پشتیبانی از ماژول‌های کرنل قابل بارگذاری، android-base.config در همه هسته‌های رایج شامل گزینه‌های پیکربندی هسته زیر (یا معادل نسخه هسته آنها) است:

CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y

تمام هسته های دستگاه باید این گزینه ها را فعال کنند. ماژول های کرنل نیز باید در صورت امکان از تخلیه و بارگیری مجدد پشتیبانی کنند.

امضای ماژول

امضای ماژول برای ماژول های فروشنده GKI پشتیبانی نمی شود. در دستگاه‌های مورد نیاز برای پشتیبانی از بوت تایید شده، اندروید نیاز دارد که ماژول‌های هسته در پارتیشن‌هایی باشند که dm-verity را فعال کرده‌اند. این امر نیاز به امضای ماژول های جداگانه را برای صحت آنها از بین می برد. اندروید 13 مفهوم ماژول های GKI را معرفی کرد. ماژول‌های GKI از زیرساخت امضای زمان ساخت هسته برای تمایز بین GKI و سایر ماژول‌ها در زمان اجرا استفاده می‌کنند. ماژول‌های بدون امضا مجاز به بارگیری هستند تا زمانی که فقط از نمادهایی استفاده کنند که در لیست مجاز ظاهر می‌شوند یا توسط سایر ماژول‌های بدون امضا ارائه شده‌اند. برای تسهیل امضای ماژول‌های GKI در طول ساخت GKI با استفاده از جفت کلید زمان ساخت هسته، پیکربندی هسته GKI CONFIG_MODULE_SIG_ALL=y فعال کرده است. برای جلوگیری از امضای ماژول‌های غیر GKI در طول ساخت‌های هسته دستگاه، باید # CONFIG_MODULE_SIG_ALL is not set اضافه کنید.

مکان های فایل

در حالی که Android 7.x و پایین‌تر ماژول‌های هسته را اجباری نمی‌کند (و شامل پشتیبانی از insmod و rmmod )، Android 8.x و بالاتر استفاده از ماژول‌های هسته را در اکوسیستم توصیه می‌کند. جدول زیر پشتیبانی بالقوه جانبی مخصوص برد مورد نیاز را در سه حالت بوت اندروید نشان می دهد.

حالت بوت ذخیره سازی نمایش صفحه کلید باتری PMIC صفحه لمسی NFC، Wi-Fi،
بلوتوث
حسگرها دوربین
بازیابی
شارژر
اندروید

علاوه بر در دسترس بودن در حالت‌های بوت اندروید، ماژول‌های هسته ممکن است بر اساس مالک آنها (فروشنده SoC یا ODM) نیز دسته‌بندی شوند. اگر از ماژول های هسته استفاده می شود، الزامات برای قرار دادن آنها در سیستم فایل به شرح زیر است:

  • همه کرنل ها باید پشتیبانی داخلی برای بوت کردن و نصب پارتیشن ها داشته باشند.
  • ماژول های هسته باید از یک پارتیشن فقط خواندنی بارگیری شوند.
  • برای دستگاه هایی که باید بوت تایید شده داشته باشند، ماژول های هسته باید از پارتیشن های تایید شده بارگیری شوند.
  • ماژول های هسته نباید در /system قرار بگیرند.
  • ماژول‌های GKI مورد نیاز دستگاه باید از /system/lib/modules بارگیری شوند که پیوندی نمادین به /system_dlkm/lib/modules است.
  • ماژول‌های هسته از فروشنده SoC که برای حالت‌های کامل Android یا Charger مورد نیاز هستند، باید در /vendor/lib/modules قرار گیرند.
  • اگر یک پارتیشن ODM وجود داشته باشد، ماژول‌های هسته از ODM که برای حالت‌های کامل Android یا Charger مورد نیاز هستند باید در /odm/lib/modules قرار گیرند. در غیر این صورت، این ماژول ها باید در /vendor/lib/modules قرار گیرند.
  • ماژول های هسته از فروشنده SoC و ODM که برای حالت Recovery مورد نیاز هستند باید در ramfs بازیابی در /lib/modules قرار گیرند.
  • ماژول های هسته مورد نیاز برای هر دو حالت Recovery و Android یا Charger کامل باید هم در rootfs بازیابی و هم در پارتیشن های /vendor یا /odm (همانطور که در بالا توضیح داده شد) وجود داشته باشند.
  • ماژول‌های هسته‌ای که در حالت بازیابی استفاده می‌شوند نباید به ماژول‌هایی که فقط در /vendor یا /odm قرار دارند وابسته باشند، زیرا آن پارتیشن‌ها در حالت Recovery نصب نشده‌اند.
  • ماژول‌های هسته فروشنده SoC نباید به ماژول‌های هسته ODM وابسته باشند.

در اندروید 7.x و پایین‌تر، پارتیشن‌های /vendor و /odm زود نصب نمی‌شوند . در Android 8.x و بالاتر، برای امکان بارگیری ماژول از این پارتیشن‌ها، مقدماتی برای نصب زودهنگام پارتیشن‌ها برای دستگاه‌های غیر A/B و A/B در نظر گرفته شده است. این همچنین باعث می شود که پارتیشن ها در هر دو حالت اندروید و شارژر نصب شوند.

پشتیبانی از سیستم ساخت اندروید

در BoardConfig.mk ، ساخت اندروید یک متغیر BOARD_VENDOR_KERNEL_MODULES را تعریف می‌کند که فهرست کاملی از ماژول‌های هسته در نظر گرفته شده برای تصویر فروشنده را ارائه می‌دهد. ماژول های فهرست شده در این متغیر در تصویر فروشنده در /lib/modules/ کپی می شوند و پس از نصب در اندروید، در /vendor/lib/modules (طبق شرایط فوق) ظاهر می شوند. پیکربندی مثالی از ماژول های هسته فروشنده:

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

در این مثال، یک مخزن از پیش ساخته شده ماژول هسته فروشنده در محل ذکر شده در بالا به بیلد اندروید نگاشت می شود.

تصویر بازیابی ممکن است حاوی زیرمجموعه‌ای از ماژول‌های فروشنده باشد. ساخت اندروید متغیر BOARD_RECOVERY_KERNEL_MODULES را برای این ماژول ها تعریف می کند. مثال:

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

ساخت اندروید از اجرای depmod برای تولید فایل‌های modules.dep مورد نیاز در /vendor/lib/modules و /lib/modules ( recovery ramfs ) مراقبت می‌کند.

بارگذاری و نسخه سازی ماژول

با فراخوانی modprobe -a همه ماژول‌های هسته را در یک پاس از init.rc* بارگیری کنید. این امر از هزینه اولیه اولیه سازی مکرر محیط زمان اجرا C برای باینری modprobe جلوگیری می کند. رویداد early-init می توان برای فراخوانی modprobe تغییر داد:

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

به طور معمول، یک ماژول هسته باید با هسته ای که ماژول با آن استفاده می شود کامپایل شود (در غیر این صورت هسته از بارگذاری ماژول خودداری می کند). CONFIG_MODVERSIONS با تشخیص شکستگی در رابط باینری برنامه (ABI) راه حلی را ارائه می دهد. این ویژگی یک مقدار بررسی افزونگی چرخه ای (CRC) را برای نمونه اولیه هر نماد صادر شده در هسته محاسبه می کند و مقادیر را به عنوان بخشی از هسته ذخیره می کند. برای نمادهای استفاده شده توسط یک ماژول هسته، مقادیر نیز در ماژول هسته ذخیره می شوند. هنگامی که ماژول بارگذاری می شود، مقادیر نمادهای استفاده شده توسط ماژول با موارد موجود در هسته مقایسه می شود. اگر مقادیر مطابقت داشته باشند، ماژول بارگذاری می شود. در غیر این صورت بار از کار می افتد.

برای فعال کردن به‌روزرسانی تصویر هسته جدا از تصویر فروشنده، CONFIG_MODVERSIONS را فعال کنید. انجام این کار باعث می شود که به روز رسانی های کوچک هسته (مانند رفع اشکال از LTS) در حالی که سازگاری با ماژول های هسته موجود در تصویر فروشنده حفظ شود، انجام شود. با این حال، CONFIG_MODVERSIONS شکستگی ABI را به تنهایی رفع نمی‌کند. اگر نمونه اولیه یک نماد صادر شده در هسته تغییر کند، یا به دلیل تغییر منبع یا به دلیل تغییر پیکربندی هسته، این امر سازگاری با ماژول‌های هسته را که از آن نماد استفاده می‌کنند، از بین می‌برد. در چنین مواردی، ماژول هسته باید دوباره کامپایل شود.

به عنوان مثال، ساختار task_struct در هسته (تعریف شده در include/linux/sched.h ) شامل بسیاری از فیلدهای مشروط بسته به پیکربندی هسته است. فیلد sched_info تنها در صورتی وجود دارد که CONFIG_SCHED_INFO فعال باشد (که زمانی رخ می‌دهد که CONFIG_SCHEDSTATS یا CONFIG_TASK_DELAY_ACCT فعال باشد). اگر این گزینه‌های پیکربندی تغییر حالت دهند، طرح‌بندی ساختار task_struct تغییر می‌کند و هر رابط صادر شده از هسته که از task_struct استفاده می‌کند تغییر می‌کند (به عنوان مثال، set_cpus_allowed_ptr در kernel/sched/core.c ). سازگاری با ماژول‌های هسته که قبلاً کامپایل شده‌اند و از این رابط‌ها استفاده می‌کنند، شکسته می‌شود و نیاز است که آن ماژول‌ها با پیکربندی هسته جدید بازسازی شوند.

برای جزئیات بیشتر در مورد CONFIG_MODVERSIONS ، به اسناد موجود در درخت هسته در Documentation/kbuild/modules.rst مراجعه کنید.