پارتیشن بوت فروشنده

اندروید 11 مفهوم تصویر هسته عمومی (GKI) را معرفی کرد. برای فعال کردن راه‌اندازی آسان یک دستگاه دلخواه با GKI، دستگاه‌های Android 11 می‌توانند از هدر تصویر بوت نسخه 3 استفاده کنند. در نسخه 3، تمام اطلاعات خاص فروشنده از پارتیشن boot خارج می‌شوند و به پارتیشن vendor_boot جدید منتقل می‌شوند. دستگاه ARM64 که با اندروید 11 روی هسته لینوکس 5.4 راه اندازی می شود، باید از پارتیشن vendor_boot و فرمت پارتیشن boot به روز شده پشتیبانی کند تا بتواند با GKI آزمایش کند.

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

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

پارتیشن بوت فروشنده A/B'd با A/B مجازی است و توسط Android Verified Boot محافظت می شود.

نسخه 3

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

بخش تعدادی از صفحات
هدر بوت فروشنده (n صفحه) n = (2112 + page_size - 1) / page_size
ramdisk فروشنده (o pages) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (صفحه های ص) p = (dtb_size + page_size - 1) / page_size

نسخه 4

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

بخش تعدادی از صفحات
هدر بوت فروشنده (n صفحه) n = (2128 + page_size - 1) / page_size
قطعات ramdisk فروشنده (o pages) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (صفحه های ص) 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 حاوی بیت های خاص پلت فرم هستند. بوت لودر باید همیشه اینها را در حافظه بارگذاری کند.
    • VENDOR_RAMDISK_TYPE_RECOVERY ramdisk حاوی منابع بازیابی است. بوت لودر هنگام بوت شدن در ریکاوری باید اینها را در حافظه بارگذاری کند.
    • رمدیسک های VENDOR_RAMDISK_TYPE_DLKM حاوی ماژول های هسته قابل بارگیری پویا هستند.
  • ramdisk_name نام منحصر به فرد ramdisk است.
  • board_id یک بردار از شناسه های سخت افزاری تعریف شده توسط فروشنده است.

پشتیبانی از بوت لودر

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

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

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

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

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

با هدر تصویر بوت نسخه 4، بوت لودر می تواند یک زیرمجموعه یا همه رم دیسک های فروشنده را برای بارگذاری به عنوان 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 تنظیم کنید.

  • 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) .

برای قرار دادن چندین ramdisk فروشنده در vendor_boot :

  • BOARD_BOOT_HEADER_VERSION را روی 4 تنظیم کنید.
  • BOARD_VENDOR_RAMDISK_FRAGMENTS را روی فهرستی از نام‌های قطعات ramdisk فروشنده منطقی قرار دهید تا در vendor_boot گنجانده شوند.

  • برای افزودن یک ramdisk فروشنده از پیش ساخته شده، 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 "پیش‌فرض" است که حاوی baz دایرکتوری DLKM و بقیه فایل‌ها در $(TARGET_VENDOR_RAMDISK_OUT) است. مورد دوم ramdisk dlkm_foobar است که شامل دایرکتوری های DLKM foo و bar است و --ramdisk_type پیش فرض DLKM است.