תמיכה במודולים של ליבה

תמונה גנרית של ליבת מערכת ההפעלה (GKI) לא יכולה להכיל את התמיכה הנדרשת במנהלי התקנים כדי לאפשר למכשיר לטעון מחיצות. כדי לאפשר למכשיר להעלות מחיצות ולהמשיך את האתחול, שלב init משופר כדי לטעון את מודולי הליבה שקיימים ב-ramdisk. דיסק ה-RAM מחולק לדיסקי RAM גנריים ולדיסקי RAM של ספקים. מודולי ליבת הספק מאוחסנים ב-ramdisk של הספק. אפשר להגדיר את הסדר שבו נטענים מודולי הליבה.

מיקום המודול

ה-ramdisk הוא מערכת הקבצים של init, בשלב הראשון ושל תמונת השחזור/fastbootd במכשירי A/B ובמכשירי A/B וירטואליים. זהו initramfs שמורכב משני ארכיוני cpio שתוכנת האתחול משרשרת. ארכיון ה-cpio הראשון, שמאוחסן כ-vendor ramdisk במחיצת vendor-boot, מכיל את הרכיבים הבאים:

  • מודולים של ליבת הספק בשלב הראשון init, שנמצאים ב-/lib/modules/.
  • קובצי הגדרות modprobe, שנמצאים ב/lib/modules/: modules.dep, modules.softdep, modules.alias, modules.options.
  • קובץ modules.load שמציין אילו מודולים לטעון במהלך האתחול בשלב הראשון, ובאיזה סדר, ב-/lib/modules/.
  • מודולים של ליבת שחזור של ספקים, למכשירי A/B ו-Virtual A/B, ב-/lib/modules/
  • modules.load.recovery שמציין אילו מודולים לטעון ובאיזה סדר, למכשירי A/B ו-Virtual A/B, ב-/lib/modules.

ארכיון ה-cpio השני, שמסופק עם GKI בתור ramdisk של boot.img ומוחל על הראשון, מכיל את first_stage_init ואת הספריות שהוא תלוי בהן.

טעינת מודולים באתחול בשלב הראשון

בשלב הראשון, init מתחיל בקריאת קובצי ההגדרות של modprobe מ-/lib/modules/ ב-ramdisk. לאחר מכן, הוא קורא את רשימת המודולים שצוינו בקובץ /lib/modules/modules.load (או בקובץ /lib/modules/modules.load.recovery במקרה של שחזור) ומנסה לטעון כל אחד מהמודולים האלה לפי הסדר, בהתאם להגדרה שצוינה בקבצים שנפרסו קודם. יכול להיות שהסדר המבוקש ישתנה כדי לעמוד בתלות קשיחה או רכה.

בניית תמיכה, הפעלה בשלב הראשון

כדי לציין מודולי ליבה שיועתקו ל-vendor ramdisk cpio, צריך לרשום אותם ב-BOARD_VENDOR_RAMDISK_KERNEL_MODULES. ה-build מופעל depmod במודולים האלה ומכניס את קובצי ההגדרה של modprobe שנוצרו ל-vendor ramdisk cpio.

ה-build גם יוצר קובץ modules.load ושומר אותו ב-vendor ramdisk cpio. כברירת מחדל, הוא מכיל את כל המודולים שמופיעים ב-BOARD_VENDOR_RAMDISK_KERNEL_MODULES. כדי להחליף את התוכן של הקובץ, משתמשים ב-BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD, כמו בדוגמה הזו:

BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD := \
    device/vendor/mydevice-kernel/first.ko \
    device/vendor/mydevice-kernel/second.ko \
    device/vendor/mydevice-kernel/third.ko

תמיכה בבנייה, Android מלא

כמו בגרסאות Android 10 ומטה, מודולי ליבה שמופיעים ב-BOARD_VENDOR_KERNEL_MODULES מועתקים על ידי פלטפורמת Android אל מחיצת הספק ב-/vendor/lib/modules. הגרסה של הפלטפורמה מופעלת depmod במודולים האלה, ומעתיקה את קובצי הפלט depmod למחיצת הספק באותו מיקום. המנגנון לטעינת מודולים של ליבת מערכת מ-/vendor נשאר זהה לזה שהיה בגרסאות קודמות של Android. אתם מחליטים איך ומתי לטעון את המודולים האלה, אבל בדרך כלל הטעינה מתבצעת באמצעות סקריפטים של init.rc.

תווים כלליים לחיפוש וגרסאות ליבה משולבות

ספקים שמשלבים את הגרסה של ליבת המכשיר עם הגרסה של פלטפורמת Android, עלולים להיתקל בבעיה בשימוש בפקודות המאקרו BOARD שצוינו למעלה כדי לציין מודולים של ליבת המערכת שיועתקו למכשיר. אם הספק רוצה להימנע מהוספת מודולים של ליבת המערכת לקובצי ה-build של פלטפורמת המכשיר, הוא יכול להשתמש בתו כללי ($(wildcard device/vendor/mydevice/*.ko). חשוב לציין שהתו הכללי לא פועל במקרה של build משולב של ליבת המערכת, כי כשמפעילים את הפקודה make והמאקרו מורחב בקובצי ה-make, המודולים של ליבת המערכת לא נבנו, ולכן המאקרו ריק.

כדי לפתור את הבעיה הזו, יכול להיות שהספק יבנה את ליבת המערכת כך שייווצר ארכיון zip שמכיל את מודולי הליבה שצריך להעתיק לכל מחיצה. מגדירים את הנתיב של קובץ ה-ZIP הזה ב-BOARD_*_KERNEL_MODULES_ARCHIVE כאשר * הוא שם המחיצה (לדוגמה, BOARD_VENDOR_KERNEL_MODULES_ARCHIVE). תהליך הבנייה של פלטפורמת Android מחלץ את קובץ ה-ZIP הזה למיקום המתאים ומריץ את depmod במודולים.

ארכיון ה-zip של מודול הליבה צריך לכלול כלל make שמוודא שניתן ליצור את הארכיון כשנדרש לבנות את הפלטפורמה.

שחזור

בגרסאות קודמות של Android, מודולי ליבה שנדרשים לשחזור צוינו ב-BOARD_RECOVERY_KERNEL_MODULES. ב-Android 12, מודולי ליבה שנדרשים לשחזור עדיין מצוינים באמצעות פקודת המאקרו הזו. עם זאת, מודולי ליבת השחזור מועתקים אל vendor ramdisk cpio ולא אל generic ramdisk cpio. כברירת מחדל, כל מודולי הליבה שמופיעים ב-BOARD_RECOVERY_KERNEL_MODULES נטענים במהלך השלב הראשון של init. אם רוצים לטעון רק קבוצת משנה של המודולים האלה, צריך לציין את התוכן של קבוצת המשנה ב-BOARD_RECOVERY_KERNEL_MODULES_LOAD.

במאמר מחיצות אתחול מוסבר איך ליצור מחיצת אתחול של ספק (שכוללת את ה-ramdisk של הספק שמוזכר בדף הזה).