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 ของผู้จำหน่าย ตาราง ramdisk ของผู้จำหน่ายใช้เพื่ออธิบายโครงร่างของส่วน ramdisk ของผู้จำหน่าย และข้อมูลเมตาของแฟรกเมนต์ ramdisk ของผู้จำหน่ายแต่ละราย
โครงสร้างพาร์ติชั่น
พาร์ติชันสำหรับเริ่มระบบของผู้จำหน่ายเป็นแบบ A/B พร้อมด้วย A/B เสมือนและได้รับการปกป้องโดย Android Verified Boot
เวอร์ชัน 3
พาร์ติชันประกอบด้วยส่วนหัว ramdisk ของผู้จำหน่าย และแผนผังอุปกรณ์ (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
ramdisk มีบิตเฉพาะแพลตฟอร์ม bootloader จะต้องโหลดสิ่งเหล่านี้ลงในหน่วยความจำเสมอ -
VENDOR_RAMDISK_TYPE_RECOVERY
ramdisk มีทรัพยากรการกู้คืน bootloader จะต้องโหลดสิ่งเหล่านี้ลงในหน่วยความจำเมื่อทำการบู๊ตเข้าสู่การกู้คืน -
VENDOR_RAMDISK_TYPE_DLKM
ramdisk มีโมดูลเคอร์เนลที่โหลดได้แบบไดนามิก
-
-
ramdisk_name
เป็นชื่อเฉพาะของ ramdisk -
board_id
เป็นเวกเตอร์ของตัวระบุฮาร์ดแวร์ที่ผู้ขายกำหนด
การสนับสนุนบูตโหลดเดอร์
เนื่องจากพาร์ติชั่นสำหรับบู๊ตของผู้จำหน่ายมีข้อมูล (เช่น ขนาดเพจแฟลช, เคอร์เนล, ที่อยู่โหลด ramdisk, DTB เอง) ที่มีอยู่ก่อนหน้านี้ในพาร์ติชั่นสำหรับบู๊ต, bootloader จะต้องเข้าถึงทั้งพาร์ติชั่นสำหรับบู๊ตและพาร์ติชั่นสำหรับบู๊ตของผู้จำหน่ายเพื่อให้มีข้อมูลเพียงพอที่จะทำการบูทให้เสร็จสมบูรณ์ .
bootloader ต้องโหลด ramdisk ทั่วไปลงในหน่วยความจำ ทันที หลังจาก ramdisk ของผู้จำหน่าย (รูปแบบ CPIO, Gzip และ lz4 รองรับการต่อข้อมูลประเภทนี้) อย่าจัดแนวหน้าอิมเมจ ramdisk ทั่วไปหรือแนะนำช่องว่างอื่น ๆ ระหว่างมันกับจุดสิ้นสุดของ ramdisk ของผู้จำหน่ายในหน่วยความจำ หลังจากที่เคอร์เนลคลายการบีบอัด มันจะแยกไฟล์ที่ต่อกันออกเป็น initramfs
ซึ่งส่งผลให้โครงสร้างไฟล์เป็น ramdisk ทั่วไปซ้อนทับบนโครงสร้างไฟล์ ramdisk ของผู้จำหน่าย
เนื่องจาก ramdisk ทั่วไปและ ramdisk ของผู้จำหน่ายถูกต่อเข้าด้วยกัน จึงต้องอยู่ในรูปแบบเดียวกัน อิมเมจสำหรับบูต GKI ใช้ ramdisk ทั่วไปที่บีบอัด lz4 ดังนั้นอุปกรณ์ที่เป็นไปตาม GKI จะต้องใช้ ramdisk ของผู้จำหน่ายที่บีบอัด lz4 การกำหนดค่าสำหรับสิ่งนี้แสดงอยู่ด้านล่าง
ข้อกำหนดของ bootloader สำหรับการรองรับ bootconfig มีอธิบายอยู่ในหน้า การนำ Bootconfig ไปใช้
ramdisk ของผู้จำหน่ายหลายราย (เวอร์ชัน 4)
ด้วยส่วนหัวของอิมเมจสำหรับบูตเวอร์ชัน 4 โปรแกรมโหลดบูตสามารถเลือกชุดย่อยหรือ ramdisk ของผู้จำหน่ายทั้งหมดเพื่อโหลดเป็น initramfs
ในระหว่างเวลาบูต ตาราง ramdisk ของผู้จำหน่ายประกอบด้วยข้อมูลเมตาของ ramdisk แต่ละตัว และสามารถช่วย Bootloader ในการตัดสินใจว่าจะโหลด ramdisk ใด บูตโหลดเดอร์สามารถตัดสินใจลำดับในการโหลด ramdisk ของผู้จำหน่ายที่เลือกได้ ตราบใดที่ ramdisk ทั่วไปถูกโหลดครั้งล่าสุด
ตัวอย่างเช่น โปรแกรมโหลดบูตสามารถละเว้นการโหลด ramdisk ของผู้จำหน่ายประเภท VENDOR_RAMDISK_TYPE_RECOVERY
ในระหว่างการบูตปกติเพื่อประหยัดทรัพยากร ดังนั้นเฉพาะ ramdisk ของผู้จำหน่ายประเภท VENDOR_RAMDISK_TYPE_PLATFORM
และ VENDOR_RAMDISK_TYPE_DLKM
เท่านั้นที่จะโหลดลงในหน่วยความจำ ในทางกลับกัน ramdisk ของผู้จำหน่ายประเภท VENDOR_RAMDISK_TYPE_PLATFORM
, VENDOR_RAMDISK_TYPE_RECOVERY
และ VENDOR_RAMDISK_TYPE_DLKM
จะถูกโหลดเข้าสู่หน่วยความจำเมื่อบูตเข้าสู่โหมดการกู้คืน
อีกทางหนึ่ง bootloader สามารถละเว้นตาราง ramdisk ของผู้จำหน่าย และโหลดส่วน ramdisk ของผู้จำหน่ายทั้งหมด สิ่งนี้มีผลเช่นเดียวกับการโหลดแฟรกเมนต์ ramdisk ของผู้จำหน่ายทั้งหมดในพาร์ติ vendor_boot
สร้างการสนับสนุน
หากต้องการใช้การสนับสนุนการบูตของผู้ขายสำหรับอุปกรณ์:
ตั้งค่า
BOARD_BOOT_HEADER_VERSION
เป็น3
หรือสูงกว่าตั้งค่า
BOARD_RAMDISK_USE_LZ4
เป็นtrue
หากอุปกรณ์ของคุณเป็นไปตามมาตรฐาน GKI หรือหากใช้ ramdisk ทั่วไปที่บีบอัด lz4ตั้งค่า
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 ของผู้จำหน่าย สำหรับ 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 "เริ่มต้น" ซึ่งมีไดเร็กทอรี DLKM baz
และไฟล์ที่เหลือใน $(TARGET_VENDOR_RAMDISK_OUT)
อันที่สองคือ dlkm_foobar
ramdisk ซึ่งมีไดเรกทอรี DLKM foo
และ bar
และ --ramdisk_type
มีค่าเริ่มต้นเป็น DLKM