מחיצות אתחול של ספקים

אנדרואיד 11 הציגה את הרעיון של תמונת ליבה גנרית (GKI). כדי לאפשר אתחול בקלות של מכשיר שרירותי עם ה-GKI, מכשירי אנדרואיד 11 יכולים להשתמש בגרסה 3 של כותרת אתחול תמונת אתחול. בגרסה 3, כל המידע הספציפי לספק נלקח מתוך מחיצת boot ומועבר למחיצת vendor_boot חדשה. מכשיר ARM64 המופעל עם אנדרואיד 11 בליבת לינוקס 5.4 חייב לתמוך במחיצת vendor_boot ובפורמט מחיצת boot המעודכן כדי לעבור בדיקה עם ה-GKI.

מכשירי אנדרואיד 12 יכולים להשתמש בגרסה 4 של כותרת אתחול של תמונת אתחול, התומכת בהכללה של מספר דיסקים של ספקים במחיצת vendor_boot . שברי ramdisk של ספקים מרושרים בזה אחר זה בקטע ramdisk של הספק. טבלת ramdisk של הספק משמשת לתיאור הפריסה של קטע ה-ramdisk של הספק ואת המטא-נתונים של כל קטע ramdisk של הספק.

מבנה מחיצה

מחיצת האתחול של הספק היא A/B'd עם A/B ​​וירטואלית ומוגנת על ידי Android Verified Boot.

גרסה 3

המחיצה מורכבת מכותרת, ה-ramdisk של הספק ו-Bob עץ ההתקן (DTB).

סָעִיף מספר דפים
כותרת אתחול הספק (n עמודים) n = (2112 + page_size - 1) / page_size
רמדיסק של ספק (דפים או) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (עמודים P) p = (dtb_size + page_size - 1) / page_size

גרסה 4

המחיצה מורכבת מכותרת, מקטע ה-ramdisk של הספק (המורכב מכל קטעי ה-ramdisk של הספק, משורשרים), גוש עץ ההתקן (DTB), וטבלת ramdisk של הספק.

סָעִיף מספר דפים
כותרת אתחול הספק (n עמודים) n = (2128 + page_size - 1) / page_size
שברי ramdisk של הספק (דפים) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (עמודים P) p = (dtb_size + page_size - 1) / page_size
טבלת ramdisk של הספק (דפי q) q = (vendor_ramdisk_table_size + page_size - 1) / page_size
Bootconfig (דפים R) r = (bootconfig_size + page_size - 1) / page_size

כותרת אתחול הספק

התוכן של כותרת מחיצת האתחול של הספק מורכב בעיקר מנתונים שהועברו לשם מכותרת תמונת האתחול . הוא מכיל גם מידע על ה-ramdisk של הספק.

גרסה 3

struct vendor_boot_img_hdr_v3
{
#define VENDOR_BOOT_MAGIC_SIZE 8
    uint8_t magic[VENDOR_BOOT_MAGIC_SIZE];
    uint32_t header_version;
    uint32_t page_size;           /* flash page size we assume */

    uint32_t kernel_addr;         /* physical load addr */
    uint32_t ramdisk_addr;        /* physical load addr */

    uint32_t vendor_ramdisk_size; /* size in bytes */

#define VENDOR_BOOT_ARGS_SIZE 2048
    uint8_t cmdline[VENDOR_BOOT_ARGS_SIZE];

    uint32_t tags_addr;           /* physical addr for kernel tags */

#define VENDOR_BOOT_NAME_SIZE 16
    uint8_t name[VENDOR_BOOT_NAME_SIZE]; /* asciiz product name */
    uint32_t header_size;         /* size of vendor boot image header in
                                   * bytes */
    uint32_t dtb_size;            /* size of dtb image */
    uint64_t dtb_addr;            /* physical load address */

};

גרסה 4

struct vendor_boot_img_hdr_v4
{
#define VENDOR_BOOT_MAGIC_SIZE 8
    uint8_t magic[VENDOR_BOOT_MAGIC_SIZE];
    uint32_t header_version;
    uint32_t page_size;           /* flash page size we assume */

    uint32_t kernel_addr;         /* physical load addr */
    uint32_t ramdisk_addr;        /* physical load addr */

    uint32_t vendor_ramdisk_size; /* size in bytes */

#define VENDOR_BOOT_ARGS_SIZE 2048
    uint8_t cmdline[VENDOR_BOOT_ARGS_SIZE];

    uint32_t tags_addr;           /* physical addr for kernel tags */

#define VENDOR_BOOT_NAME_SIZE 16
    uint8_t name[VENDOR_BOOT_NAME_SIZE]; /* asciiz product name */
    uint32_t header_size;         /* size of vendor boot image header in
                                   * bytes */
    uint32_t dtb_size;            /* size of dtb image */
    uint64_t dtb_addr;            /* physical load address */

    uint32_t vendor_ramdisk_table_size; /* size in bytes for the vendor ramdisk table */
    uint32_t vendor_ramdisk_table_entry_num; /* number of entries in the vendor ramdisk table */
    uint32_t vendor_ramdisk_table_entry_size; /* size in bytes for a vendor ramdisk table entry */
    uint32_t bootconfig_size; /* size in bytes for the bootconfig section */
};

#define VENDOR_RAMDISK_TYPE_NONE 0
#define VENDOR_RAMDISK_TYPE_PLATFORM 1
#define VENDOR_RAMDISK_TYPE_RECOVERY 2
#define VENDOR_RAMDISK_TYPE_DLKM 3

struct vendor_ramdisk_table_entry_v4
{
    uint32_t ramdisk_size; /* size in bytes for the ramdisk image */
    uint32_t ramdisk_offset; /* offset to the ramdisk image in vendor ramdisk section */
    uint32_t ramdisk_type; /* type of the ramdisk */
#define VENDOR_RAMDISK_NAME_SIZE 32
    uint8_t ramdisk_name[VENDOR_RAMDISK_NAME_SIZE]; /* asciiz ramdisk name */

#define VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE 16
    // Hardware identifiers describing the board, soc or platform which this
    // ramdisk is intended to be loaded on.
    uint32_t board_id[VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE];
};
  • vendor_ramdisk_size הוא הגודל הכולל של כל שברי ה-ramdisk של הספק.
  • ramdisk_type מציין את סוג ה-ramdisk, ערכים אפשריים הם:
    • VENDOR_RAMDISK_TYPE_NONE מציין שהערך לא צוין.
    • VENDOR_RAMDISK_TYPE_PLATFORM דיסקים ramdisk מכילים ביטים ספציפיים לפלטפורמה. טוען האתחול חייב תמיד לטעון אותם לזיכרון.
    • VENDOR_RAMDISK_TYPE_RECOVERY דיסקים ramdisk מכילים משאבי שחזור. טוען האתחול חייב לטעון אותם לזיכרון בעת ​​אתחול לשחזור.
    • VENDOR_RAMDISK_TYPE_DLKM דיסקים ramdisk מכילים מודולי ליבה דינמיים לטעינה.
  • ramdisk_name הוא שם ייחודי של ramdisk.
  • board_id הוא וקטור של מזהי חומרה המוגדרים על ידי הספק.

תמיכה בטעינת האתחול

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

על טוען האתחול לטעון את ה-ramdisk הגנרי לזיכרון מיד לאחר ה-ramdisk של הספק (הפורמטים CPIO, Gzip ו-lz4 תומכים בסוג זה של שרשור). אין ליישר דפים את תמונת ה-ramdisk הגנרית או להכניס רווח אחר בינה לבין קצה ה-ramdisk של הספק בזיכרון. לאחר שחרור הליבה, הוא מחלץ את הקובץ המשורשר ל- initramfs , מה שמביא למבנה קובץ שהוא רמדיסק גנרי המונחת על מבנה הקובץ ramdisk של הספק.

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

הדרישות של טוען האתחול לתמיכה ב-bootconfig מוסברות בדף יישום Bootconfig .

מספר רמדיסקים של ספקים (גרסה 4)

בגרסה 4 של כותרת התמונה של האתחול, טוען האתחול יכול לבחור תת-קבוצה או את כל רדיסק ה-ramdisks של הספק לטעון כ- initramfs במהלך זמן האתחול. טבלת ה-ramdisk של הספק מכילה את המטא-נתונים של כל ramdisk, ויכולה לסייע למטען האתחול להחליט אילו דיסקים לטעון. טוען האתחול יכול להחליט על הסדר לטעינת ה-ramdisks של הספק הנבחר, כל עוד ה-ramdisk הגנרי נטען אחרון.

לדוגמה, טוען האתחול יכול להשמיט טעינת רדיסק של ספקים מסוג VENDOR_RAMDISK_TYPE_RECOVERY במהלך אתחול רגיל כדי לחסוך במשאבים, כך שרק דיסקים של ספק מסוג VENDOR_RAMDISK_TYPE_PLATFORM ו- VENDOR_RAMDISK_TYPE_DLKM נטענים לזיכרון. מצד שני, דיסקים של ספקים מסוג VENDOR_RAMDISK_TYPE_PLATFORM , VENDOR_RAMDISK_TYPE_RECOVERY ו- VENDOR_RAMDISK_TYPE_DLKM נטענים לזיכרון בעת ​​האתחול למצב שחזור.

לחלופין, טוען האתחול יכול להתעלם מטבלת ramdisk של הספק ולטעון את כל סעיף ramdisk של הספק. יש לזה אותה השפעה כמו לטעינת כל שברי ה-ramdisk של הספק במחיצת vendor_boot .

בנה תמיכה

כדי ליישם תמיכה באתחול של ספק עבור מכשיר:

  • הגדר BOARD_BOOT_HEADER_VERSION ל 3 או יותר.

  • הגדר את BOARD_RAMDISK_USE_LZ4 ל- true אם המכשיר שלך תואם GKI, או אם הוא משתמש בדרך אחרת ב-ramdisk גנרי דחוס ב-lz4.

  • הגדר את BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE לגודל המתאים למכשיר שלך, בהתחשב במודולי הליבה שחייבים להיכנס ל-ramdisk של הספק.

  • עדכן את AB_OTA_PARTITIONS כדי לכלול vendor_boot וכל רשימות ספק ספציפיות של מחיצות OTA במכשיר.

  • העתק את fstab המכשיר שלך לתוך /first_stage_ramdisk במחיצת vendor_boot , לא למחיצת boot . לדוגמה, $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM) .

כדי לכלול מספר דיסקים של ספקים ב- vendor_boot :

  • הגדר את BOARD_BOOT_HEADER_VERSION ל 4 .
  • הגדר את BOARD_VENDOR_RAMDISK_FRAGMENTS לרשימה של שמות מקטעי ramdisk של ספקים לוגיים שייכללו ב- vendor_boot .

  • כדי להוסיף רמדיסק של ספק בנוי מראש, הגדר את BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT לנתיב הקובץ שנבנה מראש.

  • כדי להוסיף ramdisk של ספק DLKM, הגדר את BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS לרשימת ספריות מודולי הליבה שיש לכלול.

  • הגדר BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS לארגומנטים mkbootimg . אלו הם הארגומנטים --board_id[0-15] ו-- --ramdisk_type עבור קטע ramdisk של הספק. עבור ramdisk של ספק DLKM, ברירת המחדל --ramdisk_type תהיה DLKM אם לא צוין אחרת.

כדי לבנות משאבי שחזור כ-ramdisk recovery עצמאי ב- vendor_boot :

  • הגדר את BOARD_BOOT_HEADER_VERSION ל 4 .
  • הגדר את BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT למצב true .
  • הגדר את BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT למצב true .
  • זה מוסיף קטע ramdisk של הספק ש- ramdisk_name שלו הוא recovery ו- ramdisk_type הוא VENDOR_RAMDISK_TYPE_RECOVERY . ה-ramdisk מכיל אז את כל קבצי השחזור, שהם קבצים המותקנים תחת $(TARGET_RECOVERY_ROOT_OUT) .

ארגומנטים mkbootimg

טַעֲנָה תיאור
--ramdisk_type סוג ה-ramdisk יכול להיות אחד של NONE , PLATFORM , RECOVERY או DLKM .
--board_id[0-15] ציין את וקטור board_id , ברירת המחדל היא 0 .

להלן דוגמה לתצורה:

BOARD_KERNEL_MODULE_DIRS := foo bar baz
BOARD_BOOT_HEADER_VERSION := 4
BOARD_VENDOR_RAMDISK_FRAGMENTS := dlkm_foobar
BOARD_VENDOR_RAMDISK_FRAGMENT.dlkm_foobar.KERNEL_MODULE_DIRS := foo bar
BOARD_VENDOR_RAMDISK_FRAGMENT.dlkm_foobar.MKBOOTIMG_ARGS := --board_id0 0xF00BA5 --board_id1 0xC0FFEE

ה- vendor_boot שהתקבל יכיל שני שברי ramdisk של הספק. הראשון הוא ה-ramdisk "ברירת המחדל", המכיל את ספריית DLKM baz ואת שאר הקבצים ב $(TARGET_VENDOR_RAMDISK_OUT) . השני הוא dlkm_foobar ramdisk, המכיל את ספריות DLKM foo ו- bar , וה-- --ramdisk_type כברירת מחדל היא DLKM .