พาร์ติชันสำหรับเริ่มระบบของผู้จำหน่าย

Android 11 นำเสนอแนวคิดของ Generic Kernel Image (GKI) ต้องการเปิดใช้งานได้อย่างง่ายดายบูตอุปกรณ์พลกับ GKI, Android 11 อุปกรณ์สามารถใช้รุ่นหัวภาพบูต 3. ในรุ่นที่ 3 ข้อมูลเฉพาะผู้ขายทั้งหมดเป็นปัจจัยออกจาก boot พาร์ทิชันและย้ายเข้าใหม่ vendor_boot พาร์ทิชัน เปิดตัวอุปกรณ์ ARM64 กับ Android 11 บนลินุกซ์เคอร์เนล 5.4 ต้องสนับสนุน vendor_boot พาร์ทิชันและปรับปรุง boot รูปแบบพาร์ทิชันที่จะผ่านการทดสอบกับ GKI

Android 12 อุปกรณ์สามารถใช้บูตหัวภาพ 4 รุ่นซึ่งรวมถึงการสนับสนุน ramdisks ผู้ขายหลายแห่งใน vendor_boot พาร์ทิชัน แฟรกเมนต์ ramdisk ของผู้จำหน่ายหลายรายถูกต่อกันในส่วน ramdisk ของผู้จำหน่าย ตาราง ramdisk ของผู้ขายใช้เพื่ออธิบายโครงร่างของส่วน ramdisk ของผู้ขายและข้อมูลเมตาของแฟรกเมนต์ ramdisk ของผู้ขายแต่ละราย

โครงสร้างพาร์ทิชัน

พาร์ติชันสำหรับเริ่มระบบของผู้ขายเป็น A/B ที่มี A/B เสมือนและได้รับการป้องกันโดย Android Verified Boot

เวอร์ชัน 3

พาร์ติชั่นประกอบด้วยส่วนหัว ramdisk ของผู้จำหน่าย และ device tree blob (DTB)

ส่วน เลขหน้า
ส่วนหัวการบูตของผู้จัดจำหน่าย (หน้า n) n = (2112 + page_size - 1) / page_size
ผู้จำหน่าย ramdisk (หน้า o) 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) 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 ramdisks ประกอบด้วยบิตเฉพาะแพลตฟอร์ม bootloader ต้องโหลดสิ่งเหล่านี้ลงในหน่วยความจำเสมอ
    • VENDOR_RAMDISK_TYPE_RECOVERY ramdisks มีทรัพยากรการกู้คืน bootloader ต้องโหลดสิ่งเหล่านี้ลงในหน่วยความจำเมื่อทำการบูทเข้าสู่การกู้คืน
    • VENDOR_RAMDISK_TYPE_DLKM ramdisks ประกอบด้วยแบบไดนามิกโมดูลเคอร์เนลที่ใส่ได้
  • ramdisk_name เป็นชื่อที่ไม่ซ้ำของ ramdisk
  • board_id เป็นเวกเตอร์ของผู้ขายกำหนดตัวระบุฮาร์ดแวร์

รองรับ Bootloader

เนื่องจากพาร์ติชันสำหรับเริ่มระบบของผู้ขายมีข้อมูล (เช่น ขนาดหน้าแฟลช, เคอร์เนล, ที่อยู่โหลด ramdisk, DTB เอง) ที่มีอยู่ก่อนหน้านี้ในพาร์ติชันสำหรับเริ่มระบบ ตัวโหลดบูตจะต้องเข้าถึงทั้งบูตพาร์ติชันและพาร์ติชันสำหรับเริ่มระบบของผู้ขายเพื่อให้มีข้อมูลเพียงพอในการบูตให้เสร็จสมบูรณ์ .

bootloader ต้องโหลด ramdisk ทั่วไปในหน่วยความจำได้ทันทีดังต่อไปนี้ ramdisk ผู้ขาย (คน CPIO, Gzip และรูปแบบ LZ4 สนับสนุนชนิดของการเรียงต่อกันนี้) ห้ามจัดหน้าอิมเมจ ramdisk ทั่วไปหรือแนะนำช่องว่างอื่นระหว่างมันกับจุดสิ้นสุดของ ramdisk ของผู้จำหน่ายในหน่วยความจำ หลังจากคลายเคอร์เนลมันสารสกัดจากไฟล์ตัดแบ่งเป็น initramfs ซึ่งส่งผลให้โครงสร้างของไฟล์ที่เป็นที่วางซ้อน ramdisk ทั่วไปเกี่ยวกับโครงสร้างผู้ขาย ramdisk ไฟล์

เนื่องจาก ramdisk ทั่วไปและ ramdisk ของผู้จำหน่ายถูกต่อกัน พวกเขาจึงต้องอยู่ในรูปแบบเดียวกัน อิมเมจสำหรับบูต GKI ใช้ ramdisk ทั่วไปที่บีบอัด lz4 ดังนั้นอุปกรณ์ที่สอดคล้องกับ GKI ต้องใช้ ramdisk ของผู้ขายที่บีบอัด lz4 การกำหนดค่าสำหรับสิ่งนี้แสดงอยู่ด้านล่าง

ข้อกำหนด bootloader สำหรับการสนับสนุน bootconfig มีการอธิบายเกี่ยวกับ การใช้ Bootconfig หน้า

ramdisks ของผู้ขายหลายราย (เวอร์ชัน 4)

ด้วยการบูตหัวภาพรุ่นที่ 4 bootloader สามารถเลือกชุดย่อยหรือทั้งหมดของผู้ขาย ramdisks โหลดเป็น initramfs ในช่วงเวลาบูต ตาราง ramdisk ของผู้ขายมีข้อมูลเมตาของแต่ละ ramdisk และสามารถช่วย bootloader ในการตัดสินใจว่าจะโหลด ramdisk ใด bootloader สามารถตัดสินใจลำดับที่จะโหลด ramdisk ของผู้จำหน่ายที่เลือก ตราบใดที่ ramdisk ทั่วไปโหลดอยู่ล่าสุด

ยกตัวอย่างเช่น bootloader สามารถละเว้น ramdisks โหลดผู้ขายประเภท VENDOR_RAMDISK_TYPE_RECOVERY ในระหว่างการบูตปกติไปยังแหล่งอนุรักษ์เท่านั้นดังนั้นผู้ขาย ramdisks ประเภท VENDOR_RAMDISK_TYPE_PLATFORM และ VENDOR_RAMDISK_TYPE_DLKM ถูกโหลดลงในหน่วยความจำ บนมืออื่น ๆ , ramdisks ผู้ขายประเภท 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 สอดคล้องหรือหากมีการใช้ LZ4 บีบอัด ramdisk ทั่วไป

  • ชุด 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)

ที่จะรวม ramdisks ผู้ขายหลายใน 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 สำหรับ DLKM ramdisk ผู้ขายเริ่มต้น --ramdisk_type จะ DLKM หากยังไม่ได้ระบุเป็นอย่างอื่น

เพื่อสร้างทรัพยากรการกู้คืนเป็นแบบสแตนด์อโลน recovery ramdisk ใน 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