پارتیشن‌های راه‌اندازی فروشنده

‫Android 11 مفهوم «تصویر هسته عمومی» (GKI) را معرفی کرد. برای فعال کردن راه‌اندازی دستگاه دلخواه با GKI، دستگاه‌های Android 11 می‌توانند از نسخه ۳ سرصفحه تصویر راه‌اندازی استفاده کنند. در نسخه ۳، همه اطلاعات مختص فروشنده از boot بخش جدا شده و به بخش جدید vendor_boot منتقل می‌شود. دستگاه ARM64 که با Android 11 در هسته Linux نسخه ۵.۴ راه‌اندازی می‌شود باید از پارتیشن vendor_boot و قالب پارتیشن boot به‌روزرسانی‌شده پشتیبانی کند تا در آزمایش با GKI موفق شود.

دستگاه‌های Android 12 می‌توانند از نسخه ۴ سرصفحه تصویر راه‌اندازی استفاده کنند، که از افزودن چندین ramdisk فروشنده در vendor_boot بخش پشتیبانی می‌کند. چندین تکه ramdisk فروشنده یکی پس‌از دیگری در بخش ramdisk فروشنده به‌هم متصل می‌شوند. از جدول ramdisk فروشنده برای توصیف چیدمان بخش ramdisk فروشنده و فراداده هر تکه ramdisk فروشنده استفاده می‌شود.

ساختار پارتیشن

پارتیشن راه‌اندازی فروشنده با A/B مجازی A/B می‌شود و با «راه‌اندازی درستی‌سنجی‌شده Android» محافظت می‌شود.

نسخه ۳

این پارتیشن شامل یک سرایند، دیسک مجازی فروشنده، و حباب ساختار درختی دستگاه (DTB) است.

بخش تعداد صفحه‌ها
سرصفحه راه‌اندازی فروشنده (n صفحه) n = (2112 + page_size - 1) / page_size
دیسک مجازی ارائه‌دهنده (صفحات o) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (صفحه p) p = (dtb_size + page_size - 1) / page_size

نسخه ۴

این پارتیشن از سرصفحه، بخش ramdisk فروشنده (شامل همه تکه‌های ramdisk فروشنده، به‌هم پیوسته)، blob درخت دستگاه (DTB)، و جدول ramdisk فروشنده تشکیل شده است.

بخش تعداد صفحه‌ها
سرصفحه راه‌اندازی فروشنده (n صفحه) n = (2128 + page_size - 1) / page_size
تکه‌های دیسک مجازی ارائه‌دهنده (o صفحه) 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

سرایند راه‌اندازی فروشنده

محتوای سرصفحه پارتیشن راه‌اندازی فروشنده عمدتاً از داده‌هایی تشکیل شده است که از سرصفحه تصویر راه‌اندازی به آنجا منتقل شده است. همچنین حاوی اطلاعاتی درباره دیسک مجازی فروشنده است.

نسخه ۳

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 */

};

نسخه ۴

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 نام منحصربه‌فرد دیسک مجازی است.
  • ‫board_id برداری از شناسه‌های سخت‌افزار تعریف‌شده توسط فروشنده است.

پشتیبانی از راه‌انداز سیستم

ازآنجایی‌که پارتیشن بوت فروشنده حاوی اطلاعاتی (مانند اندازه صفحه حافظه فلش، هسته، نشانی‌های بار ramdisk، خود DTB) است که قبلاً در پارتیشن بوت وجود داشت، بارگذار بوت باید به هر دو پارتیشن بوت و بوت فروشنده دسترسی داشته باشد تا داده‌های کافی برای تکمیل بوت داشته باشد.

‫bootloader باید ramdisk عمومی را بلافاصله پس‌از ramdisk فروشنده در حافظه بار کند (قالب‌های CPIO،‏ Gzip، و lz4 از این نوع به‌هم پیوستن پشتیبانی می‌کنند). تصویر ramdisk عمومی را صفحه‌بندی نکنید یا هیچ فضای دیگری بین آن و انتهای ramdisk فروشنده در حافظه ایجاد نکنید. پس‌از اینکه هسته از حالت فشرده خارج شد، فایل به‌هم‌پیوسته را در یک initramfs استخراج می‌کند که منجر به ساختار فایلی می‌شود که یک دیسک مجازی عمومی است که روی ساختار فایل دیسک مجازی فروشنده قرار گرفته است.

ازآنجایی‌که ramdisk عمومی و ramdisk فروشنده به‌هم متصل می‌شوند، باید در قالب یکسانی باشند. تصویر بوت GKI از ramdisk عمومی فشرده‌شده با lz4 استفاده می‌کند، بنابراین دستگاه سازگار با GKI باید از ramdisk فروشنده فشرده‌شده با lz4 استفاده کند. پیکربندی این مورد در زیر نشان داده شده است.

الزامات راه‌انداز سیستم برای پشتیبانی از bootconfig در پیاده‌سازی Bootconfig توضیح داده شده است.

چند دیسک مجازی فروشنده (نسخه ۴)

با نسخه ۴ سرصفحه تصویر راه‌اندازی، بوت‌لودر می‌تواند زیرمجموعه‌ای از دیسک‌های مجازی فروشنده یا همه آن‌ها را برای بار کردن به‌عنوان initramfs درطول زمان راه‌اندازی انتخاب کند. جدول ramdisk فروشنده حاوی فراداده‌های هر ramdisk است و می‌تواند به بارکننده در تصمیم‌گیری درباره اینکه کدام ramdiskها را بار کند کمک کند. بارکننده می‌تواند ترتیب بار کردن ramdiskهای فروشنده انتخاب‌شده را تعیین کند، به‌شرطی که ramdisk عمومی در آخر بار شود.

برای مثال، راه‌انداز سیستم می‌تواند از بار کردن دیسک‌های مجازی فروشنده از نوع VENDOR_RAMDISK_TYPE_RECOVERY درطول راه‌اندازی عادی برای صرفه‌جویی در منابع صرف‌نظر کند، بنابراین فقط دیسک‌های مجازی فروشنده از نوع VENDOR_RAMDISK_TYPE_PLATFORM و VENDOR_RAMDISK_TYPE_DLKM در حافظه بار می‌شوند. ازطرف دیگر، ramdiskهای فروشنده از نوع VENDOR_RAMDISK_TYPE_PLATFORM، VENDOR_RAMDISK_TYPE_RECOVERY، و VENDOR_RAMDISK_TYPE_DLKM هنگام بوت شدن در حالت بازیابی در حافظه بار می‌شوند.

یا، راه‌انداز سیستم می‌تواند جدول ramdisk فروشنده را نادیده بگیرد و کل بخش ramdisk فروشنده را بار کند. این کار همان تأثیری را دارد که بار کردن همه تکه‌های ramdisk فروشنده در پارتیشن vendor_boot دارد.

ایجاد پشتیبانی

برای پیاده‌سازی پشتیبانی راه‌اندازی فروشنده برای دستگاه:

  • ‫BOARD_BOOT_HEADER_VERSION را روی 3 یا بیشتر تنظیم کنید.

  • اگر دستگاهتان با GKI سازگار است، یا اگر به‌هرشکل دیگری از ramdisk عمومی فشرده‌شده با lz4 استفاده می‌کند، BOARD_RAMDISK_USE_LZ4 را روی true تنظیم کنید.

  • با درنظر گرفتن واحدهای هسته‌ای که باید در ramdisk فروشنده قرار بگیرند، 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 را روی فهرست نام‌های قطعه 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_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 «پیش‌فرض» است که حاوی دایرکتوری DLKM baz و بقیه فایل‌های موجود در $(TARGET_VENDOR_RAMDISK_OUT) است. دومی dlkm_foobar ramdisk است که حاوی فهرست‌های DLKM foo و bar است، و --ramdisk_type به‌طور پیش‌فرض روی DLKM تنظیم شده است.