أقسام التشغيل الخاصة بالمورّد

قدّم Android 11 مفهوم "صورة النواة العامة" (GKI). لتفعيل إقلاع أي جهاز باستخدام "صورة النواة العامة"، يمكن لأجهزة Android 11 استخدام الإصدار 3 من عنوان صورة الإقلاع. في الإصدار 3، يتم استبعاد جميع المعلومات الخاصة بالمورّد من قسم boot ونقلها إلى قسم جديد باسم vendor_boot يجب أن يتيح جهاز ARM64 الذي يتم إطلاقه باستخدام Android 11 على النواة 5.4 من Linux قسم vendor_boot وتنسيق قسم boot المعدَّل لاجتياز الاختبار باستخدام "صورة النواة العامة".

يمكن لأجهزة Android 12 استخدام الإصدار 4 من عنوان صورة الإقلاع، الذي يتيح تضمين أقراص ذاكرة عشوائية متعددة خاصة بالمورّد في قسم vendor_boot. يتم ربط أجزاء متعددة من قرص ذاكرة عشوائية خاص بالمورّد بعضها ببعض في قسم قرص الذاكرة العشوائية الخاص بالمورّد. يتم استخدام جدول قرص الذاكرة العشوائية الخاص بالمورّد لوصف تنسيق قسم قرص الذاكرة العشوائية الخاص بالمورّد والبيانات الوصفية لكل جزء من قرص الذاكرة العشوائية الخاص بالمورّد.

بنية القسم

يتم تقسيم قسم إقلاع المورّد باستخدام ميزة "التقسيم الافتراضي A/B" وحمايته من خلال ميزة "الإقلاع الآمن الذي تم التحقق منه على Android".

الإصدار 3

يتألف القسم من عنوان وقرص ذاكرة عشوائية خاص بالمورّد وكتلة شجرة الجهاز (DTB).

القسم عدد الصفحات
عنوان إقلاع المورّد (عدد n من الصفحات) n = (2112 + page_size - 1) / page_size
قرص الذاكرة العشوائية الخاص بالمورّد (عدد o من الصفحات) o = (vendor_ramdisk_size + page_size - 1) / page_size
كتلة شجرة الجهاز (عدد p من الصفحات) p = (dtb_size + page_size - 1) / page_size

الإصدار 4

يتألف القسم من عنوان وقسم قرص الذاكرة العشوائية الخاص بالمورّد (الذي يتألف من جميع أجزاء قرص الذاكرة العشوائية الخاص بالمورّد، التي تم ربطها) وكتلة شجرة الجهاز (DTB) وجدول قرص الذاكرة العشوائية الخاص بالمورّد.

القسم عدد الصفحات
عنوان إقلاع المورّد (عدد n من الصفحات) n = (2128 + page_size - 1) / page_size
أجزاء قرص الذاكرة العشوائية الخاص بالمورّد (عدد o من الصفحات) o = (vendor_ramdisk_size + page_size - 1) / page_size
كتلة شجرة الجهاز (عدد p من الصفحات) p = (dtb_size + page_size - 1) / page_size
جدول قرص الذاكرة العشوائية الخاص بالمورّد (عدد q من الصفحات) q = (vendor_ramdisk_table_size + page_size - 1) / page_size
Bootconfig (عدد r من الصفحات) r = (bootconfig_size + page_size - 1) / page_size

عنوان إقلاع المورّد

يتألف محتوى عنوان قسم إقلاع المورّد بشكل أساسي من بيانات تم نقلها إليه من عنوان صورة التشغيل. ويحتوي أيضًا على معلومات عن قرص الذاكرة العشوائية الخاص بالمورّد.

الإصدار 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_type يشير إلى نوع قرص الذاكرة العشوائية، والقيم المحتمَلة هي:
    • VENDOR_RAMDISK_TYPE_NONE يشير إلى أنّ القيمة غير محدّدة.
    • تحتوي VENDOR_RAMDISK_TYPE_PLATFORM ramdisks على وحدات بت خاصة بالنظام الأساسي. يجب أن يحمِّل برنامج الإقلاع هذه الأجزاء دائمًا في الذاكرة.
    • VENDOR_RAMDISK_TYPE_RECOVERY تحتوي أقراص الذاكرة العشوائية على موارد الاسترداد. يجب أن يحمِّل برنامج الإقلاع هذه الأجزاء في الذاكرة عند الإقلاع في وضع الاسترداد.
    • VENDOR_RAMDISK_TYPE_DLKM تحتوي أقراص الذاكرة العشوائية على وحدات النواة القابلة للتحميل بشكل ديناميكي.
  • ramdisk_name هو اسم فريد لقرص الذاكرة العشوائية.
  • board_id هو متّجه من معرّفات الأجهزة التي يحدّدها المورّد.

دعم برنامج الإقلاع

بما أنّ قسم إقلاع المورّد يحتوي على معلومات (مثل حجم صفحة الذاكرة الفلاش، والنواة، وعناوين تحميل قرص الذاكرة العشوائية، وكتلة شجرة الجهاز نفسها) كانت موجودة سابقًا في قسم الإقلاع، يجب أن يصل برنامج الإقلاع إلى قسمَي الإقلاع وإقلاع المورّد للحصول على بيانات كافية لإكمال عملية الإقلاع.

يجب أن يحمِّل برنامج الإقلاع قرص الذاكرة العشوائية العام في الذاكرة مباشرةً بعد قرص الذاكرة العشوائية الخاص بالمورّد (تتيح تنسيقات CPIO وGzip وlz4 هذا النوع من الربط). لا تضبط صورة قرص الذاكرة العشوائية العام على مستوى الصفحة أو تُضِف أي مساحة أخرى بينها وبين نهاية قرص الذاكرة العشوائية الخاص بالمورّد في الذاكرة. بعد فك ضغط النواة، تستخرج النواة الملف الذي تم ربطه إلى initramfs، ما يؤدي إلى بنية ملفات تمثّل قرص ذاكرة عشوائية عامًا تم وضعه فوق بنية ملفات قرص الذاكرة العشوائية الخاص بالمورّد.

بما أنّه يتم ربط قرص الذاكرة العشوائية العام وقرص الذاكرة العشوائية الخاص بالمورّد، يجب أن يكونا بالتنسيق نفسه. تستخدم صورة تشغيل "صورة النواة العامة" قرص ذاكرة عشوائية عامًا مضغوطًا باستخدام lz4، لذا يجب أن يستخدم الجهاز المتوافق مع "صورة النواة العامة" قرص ذاكرة عشوائية خاصًا بالمورّد مضغوطًا باستخدام lz4. يظهر أدناه الإعداد الخاص بذلك.

تم توضيح متطلبات برنامج الإقلاع لدعم Bootconfig في مقالة تنفيذ Bootconfig.

أقراص ذاكرة عشوائية متعددة خاصة بالمورّد (الإصدار 4)

باستخدام الإصدار 4 من عنوان صورة الإقلاع، يمكن لبرنامج الإقلاع اختيار مجموعة فرعية أو كل أقراص الذاكرة العشوائية الخاصة بالمورّد لتحميلها كـ initramfs أثناء وقت الإقلاع. يحتوي جدول قرص الذاكرة العشوائية الخاص بالمورّد على البيانات الوصفية لكل قرص ذاكرة عشوائية، ويمكن أن يساعد برنامج الإقلاع في تحديد أقراص الذاكرة العشوائية التي يجب تحميلها. يمكن لبرنامج الإقلاع تحديد ترتيب تحميل أقراص الذاكرة العشوائية الخاصة بالمورّد التي تم اختيارها، طالما يتم تحميل قرص الذاكرة العشوائية العام أخيرًا.

على سبيل المثال، يمكن لبرنامج الإقلاع عدم تحميل أقراص الذاكرة العشوائية الخاصة بالمورّد من النوع VENDOR_RAMDISK_TYPE_RECOVERY أثناء الإقلاع العادي للحفاظ على الموارد، لذا يتم تحميل أقراص الذاكرة العشوائية الخاصة بالمورّد من النوعَين VENDOR_RAMDISK_TYPE_PLATFORM وVENDOR_RAMDISK_TYPE_DLKM فقط في الذاكرة. من ناحية أخرى، يتم تحميل أقراص الذاكرة العشوائية الخاصة بالمورّد من الأنواع VENDOR_RAMDISK_TYPE_PLATFORM وVENDOR_RAMDISK_TYPE_RECOVERY وVENDOR_RAMDISK_TYPE_DLKM في الذاكرة عند الإقلاع في وضع الاسترداد.

بدلاً من ذلك، يمكن لبرنامج الإقلاع تجاهل جدول قرص الذاكرة العشوائية الخاص بالمورّد وتحميل قسم قرص الذاكرة العشوائية الخاص بالمورّد بالكامل. ويكون لذلك التأثير نفسه الذي يحدث عند تحميل جميع أجزاء قرص الذاكرة العشوائية الخاص بالمورّد في قسم vendor_boot.

دعم الإصدار

لتنفيذ دعم إقلاع المورّد لجهاز:

  • اضبط BOARD_BOOT_HEADER_VERSION على 3 أو إصدار أحدث.

  • اضبط BOARD_RAMDISK_USE_LZ4 على true إذا كان جهازك متوافقًا مع "صورة النواة العامة"، أو إذا كان يستخدم قرص ذاكرة عشوائية عامًا مضغوطًا باستخدام lz4.

  • اضبط BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE على حجم مناسب لجهازك، مع الأخذ في الاعتبار وحدات النواة التي يجب وضعها على قرص الذاكرة العشوائية الخاص بالمورّد.

  • عدِّل 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 على قائمة بأسماء أجزاء قرص الذاكرة العشوائية الخاص بالمورّد المنطقية التي سيتم تضمينها في vendor_boot.

  • لإضافة قرص ذاكرة عشوائية خاص بالمورّد تم إنشاؤه مسبقًا، اضبط BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT على المسار الذي تم إنشاؤه مسبقًا.

  • لإضافة قرص ذاكرة عشوائية خاص بالمورّد من النوع 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 لجزء قرص الذاكرة العشوائية الخاص بالمورّد. بالنسبة إلى قرص الذاكرة العشوائية الخاص بالمورّد من النوع DLKM، سيكون الإعداد التلقائي لـ --ramdisk_type هو DLKM إذا لم يتم تحديد قيمة أخرى.

لإنشاء موارد الاسترداد كقرص ذاكرة عشوائية مستقل 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_name هو recovery وramdisk_type هو VENDOR_RAMDISK_TYPE_RECOVERY. يحتوي قرص الذاكرة العشوائية بعد ذلك على جميع ملفات الاسترداد، وهي الملفات التي تم تثبيتها ضمن $(TARGET_RECOVERY_ROOT_OUT).

وسيطات mkbootimg

الوسيطة الوصف
--ramdisk_type نوع قرص الذاكرة العشوائية، ويمكن أن يكون أحد الأنواع 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 الناتج على جزأين من قرص الذاكرة العشوائية الخاص بالمورّد. الأول هو قرص الذاكرة العشوائية "التلقائي"، الذي يحتوي على دليل DLKM baz وبقية الملفات في $(TARGET_VENDOR_RAMDISK_OUT). والثاني هو قرص الذاكرة العشوائية dlkm_foobar، الذي يحتوي على أدلة DLKM foo وbar، و يتم ضبط --ramdisk_type تلقائيًا على DLKM.