Android 11 ได้เปิดตัวแนวคิดของ Generic Kernel
Image (GKI) หากต้องการเปิดใช้การบูตอุปกรณ์ใดก็ได้ด้วย GKI อุปกรณ์ Android 11 จะใช้ส่วนหัวของอิมเมจบูตเวอร์ชัน 3 ได้ ใน
เวอร์ชัน 3 ระบบจะแยกข้อมูลเฉพาะของผู้ให้บริการทั้งหมดออกจากพาร์ติชัน boot
และย้ายไปยังพาร์ติชัน vendor_boot ใหม่ อุปกรณ์ ARM64
ที่เปิดตัวด้วย Android 11 ในเคอร์เนล Linux 5.4 ต้อง
รองรับพาร์ติชัน vendor_boot และรูปแบบพาร์ติชัน boot ที่อัปเดตแล้วเพื่อ
ผ่านการทดสอบด้วย GKI
อุปกรณ์ Android 12 สามารถใช้ส่วนหัวของอิมเมจบูตเวอร์ชัน 4 ซึ่งรองรับการรวม ramdisk ของผู้ให้บริการหลายรายการไว้ในพาร์ติชัน vendor_boot ระบบจะต่อชิ้นส่วน ramdisk ของผู้ให้บริการหลายรายเข้าด้วยกัน
ในส่วน ramdisk ของผู้ให้บริการ ตาราง Vendor Ramdisk ใช้เพื่ออธิบายเลย์เอาต์ของส่วน Vendor Ramdisk และข้อมูลเมตาของแต่ละส่วน Vendor Ramdisk
โครงสร้างพาร์ติชัน
พาร์ติชันการบูตของผู้ให้บริการจะใช้ A/B กับ A/B เสมือนและได้รับการปกป้องโดยการเปิดเครื่องที่ได้รับการยืนยันของ Android
เวอร์ชัน 3
พาร์ติชันประกอบด้วยส่วนหัว, ramdisk ของผู้ให้บริการ และ Blob ของแผนผังอุปกรณ์ (DTB)
| ส่วน | จำนวนหน้า |
|---|---|
| ส่วนหัวการบูตของผู้ให้บริการ (n หน้า) | n = (2112 + page_size - 1) / page_size |
| Vendor ramdisk (o หน้า) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
| DTB (หน้า p) | p = (dtb_size + page_size - 1) / page_size |
เวอร์ชัน 4
พาร์ติชันประกอบด้วยส่วนหัว ส่วน Vendor Ramdisk (ประกอบด้วย Vendor Ramdisk Fragment ทั้งหมดที่ต่อกัน), Device Tree Blob (DTB) และ ตาราง Vendor Ramdisk
| ส่วน | จำนวนหน้า |
|---|---|
| ส่วนหัวของการบูตของผู้ให้บริการ (n หน้า) | n = (2128 + page_size - 1) / page_size |
| Vendor ramdisk fragments (o pages) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
| DTB (หน้า p) | p = (dtb_size + page_size - 1) / page_size |
| ตาราง Vendor Ramdisk (หน้า q) | q = (vendor_ramdisk_table_size + page_size - 1) / page_size |
| Bootconfig (หน้า r) | r = (bootconfig_size + page_size - 1) / page_size |
ส่วนหัวการบูตของผู้ให้บริการ
เนื้อหาของส่วนหัวของพาร์ติชันการบูตของผู้ให้บริการประกอบด้วยข้อมูลเป็นหลัก ซึ่งย้ายมาจาก ส่วนหัวของอิมเมจบูต นอกจากนี้ ยังมีข้อมูลเกี่ยวกับ Vendor 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_PLATFORMramdisk มีบิตที่เฉพาะเจาะจงของแพลตฟอร์ม Bootloader ต้องโหลดข้อมูลเหล่านี้ลงในหน่วยความจำเสมอVENDOR_RAMDISK_TYPE_RECOVERYramdisk มีทรัพยากรการกู้คืน โปรแกรมโหลดต้องโหลดไฟล์เหล่านี้ลงในหน่วยความจำเมื่อบูตเข้าสู่การกู้คืนVENDOR_RAMDISK_TYPE_DLKMแรมดิสก์มีโมดูลเคอร์เนลที่โหลดได้แบบไดนามิก
ramdisk_nameเป็นชื่อที่ไม่ซ้ำกันของ Ramdiskboard_idคือเวกเตอร์ของตัวระบุฮาร์ดแวร์ที่ผู้ให้บริการกำหนด
การรองรับ Bootloader
เนื่องจากพาร์ติชันการบูตของผู้ให้บริการมีข้อมูล (เช่น ขนาดหน้าแฟลช เคอร์เนล ที่อยู่โหลด ramdisk และ DTB เอง) ซึ่งก่อนหน้านี้อยู่ใน พาร์ติชันการบูต Bootloader จึงต้องเข้าถึงทั้งพาร์ติชันการบูตและพาร์ติชันการบูตของผู้ให้บริการ เพื่อให้มีข้อมูลเพียงพอที่จะทำการบูตให้เสร็จสมบูรณ์
Bootloader ต้องโหลด Ramdisk ทั่วไปลงในหน่วยความจำทันทีหลังจาก
Ramdisk ของผู้ให้บริการ (รูปแบบ CPIO, Gzip และ lz4 รองรับการต่อกันประเภทนี้) อย่าจัดหน้าให้รูปภาพ ramdisk ทั่วไป หรือเว้นที่ว่าง
อื่นๆ ระหว่างรูปภาพกับจุดสิ้นสุดของ ramdisk ของผู้ขายในหน่วยความจำ หลังจาก
เคอร์เนลคลายการบีบอัดแล้ว เคอร์เนลจะแตกไฟล์ที่ต่อกันเป็นinitramfs
ซึ่งส่งผลให้เกิดโครงสร้างไฟล์ที่เป็นแรมดิสก์ทั่วไปที่ซ้อนทับอยู่บน
โครงสร้างไฟล์แรมดิสก์ของผู้ให้บริการ
เนื่องจากมีการต่อกันของ ramdisk ทั่วไปและ ramdisk ของผู้ให้บริการ จึงต้องอยู่ในรูปแบบเดียวกัน อิมเมจบูต GKI ใช้ ramdisk ทั่วไปที่บีบอัดด้วย lz4 ดังนั้น อุปกรณ์ที่สอดคล้องกับ GKI ต้องใช้ ramdisk ของผู้ให้บริการที่บีบอัดด้วย lz4 การกำหนดค่าสำหรับฟีเจอร์นี้แสดงอยู่ด้านล่าง
ข้อกำหนดของ Bootloader สำหรับการรองรับ Bootconfig อธิบายไว้ใน Implement Bootconfig
Ramdisk ของผู้ให้บริการหลายราย (เวอร์ชัน 4)
เมื่อใช้ส่วนหัวของอิมเมจบูตเวอร์ชัน 4 Bootloader จะเลือกชุดย่อยหรือทั้งหมดของ Ramdisk ของผู้ให้บริการเพื่อโหลดเป็น initramfs ในระหว่างเวลาบูตได้ ตาราง vendor ramdisk มีข้อมูลเมตาของ ramdisk แต่ละรายการ และช่วยให้ Bootloader สามารถตัดสินใจได้ว่าจะโหลด ramdisk ใด Bootloader สามารถกำหนดลำดับการโหลด Ramdisk ของผู้ให้บริการที่เลือกได้ ตราบใดที่โหลด Ramdisk ทั่วไปเป็นรายการสุดท้าย
ตัวอย่างเช่น Bootloader สามารถละเว้นการโหลด Ramdisk ของผู้ให้บริการประเภท
VENDOR_RAMDISK_TYPE_RECOVERY ในระหว่างการบูตปกติเพื่อประหยัดทรัพยากร ดังนั้นเฉพาะ Ramdisk ของผู้ให้บริการประเภท VENDOR_RAMDISK_TYPE_PLATFORM และ
VENDOR_RAMDISK_TYPE_DLKM เท่านั้นที่จะโหลดลงในหน่วยความจำ ในทางกลับกัน ระบบจะโหลด vendor
ramdisk ประเภท VENDOR_RAMDISK_TYPE_PLATFORM, VENDOR_RAMDISK_TYPE_RECOVERY
และ VENDOR_RAMDISK_TYPE_DLKM ลงในหน่วยความจำเมื่อบูตเข้าสู่โหมดการกู้คืน
หรือ Bootloader จะไม่สนใจตาราง Vendor Ramdisk และโหลด
ทั้งส่วน Vendor Ramdisk ก็ได้ ซึ่งให้ผลเหมือนกับการโหลดชิ้นส่วน ramdisk ของผู้ขายทั้งหมดในพาร์ติชัน vendor_boot
สร้างการสนับสนุน
วิธีติดตั้งใช้งานการรองรับการบูตของผู้ให้บริการสำหรับอุปกรณ์
ตั้งค่า
BOARD_BOOT_HEADER_VERSIONเป็น3ขึ้นไปตั้งค่า
BOARD_RAMDISK_USE_LZ4เป็นtrueหากอุปกรณ์เป็นไปตามข้อกำหนดของ GKI หรือหาก ใช้อิมเมจ RAM ทั่วไปที่บีบอัดด้วย lz4ตั้งค่า
BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZEให้มีขนาดที่เหมาะสมสำหรับ อุปกรณ์ โดยพิจารณาโมดูลเคอร์เนลที่ต้องอยู่ใน Vendor 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เป็นรายการชื่อของแรมดิสก์ของผู้ให้บริการเชิงตรรกะ ที่จะรวมไว้ใน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เป็นอาร์กิวเมนต์สำหรับ Vendor Ramdisk Fragment สำหรับ Ramdisk ของผู้ให้บริการ DLKM ค่าเริ่มต้นของ--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 - ซึ่งจะเพิ่มส่วนย่อยของ Vendor 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 ของผู้ให้บริการ 2 ชิ้น
อันแรกคือ Ramdisk "default" ซึ่งมีไดเรกทอรี DLKM baz และ
ไฟล์ที่เหลือใน $(TARGET_VENDOR_RAMDISK_OUT) ส่วนที่ 2 คือ dlkm_foobarramdisk ซึ่งมีไดเรกทอรี DLKM foo และ bar และ--ramdisk_type จะมีค่าเริ่มต้นเป็น DLKM