Android 11 đã giới thiệu khái niệm về Hình ảnh hạt nhân chung (GKI). Để bật tính năng khởi động một thiết bị tuỳ ý bằng GKI, các thiết bị Android 11 có thể sử dụng tiêu đề hình ảnh khởi động phiên bản 3. Trong phiên bản 3, tất cả thông tin dành riêng cho nhà cung cấp sẽ được tách ra khỏi phân vùng boot và chuyển sang phân vùng vendor_boot mới. Thiết bị ARM64 chạy Android 11 trên nhân Linux 5.4 phải hỗ trợ phân vùng vendor_boot và định dạng phân vùng boot đã cập nhật để vượt qua quy trình kiểm thử bằng GKI.
Các thiết bị Android 12 có thể sử dụng tiêu đề hình ảnh khởi động phiên bản 4, hỗ trợ việc đưa nhiều ổ đĩa RAM của nhà cung cấp vào phân vùng vendor_boot. Nhiều mảnh ramdisk của nhà cung cấp được nối với nhau trong phần ramdisk của nhà cung cấp. Bảng ramdisk của nhà cung cấp dùng để mô tả bố cục của phần ramdisk của nhà cung cấp và siêu dữ liệu của từng mảnh ramdisk của nhà cung cấp.
Cấu trúc phân vùng
Phân vùng khởi động của nhà cung cấp được phân vùng A/B với A/B ảo và được bảo vệ bằng tính năng Xác minh quy trình khởi động của Android.
Phiên bản 3
Phân vùng này bao gồm một tiêu đề, ramdisk của nhà cung cấp và blob cây thiết bị (DTB).
| Phần | Số trang |
|---|---|
| Tiêu đề khởi động của nhà cung cấp (n trang) | n = (2112 + page_size - 1) / page_size |
| Ramdisk của nhà cung cấp (o trang) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
| DTB (p trang) | p = (dtb_size + page_size - 1) / page_size |
Phiên bản 4
Phân vùng này bao gồm một tiêu đề, phần ramdisk của nhà cung cấp (bao gồm tất cả các mảnh ramdisk của nhà cung cấp, được nối với nhau), blob cây thiết bị (DTB) và bảng ramdisk của nhà cung cấp.
| Phần | Số trang |
|---|---|
| Tiêu đề khởi động của nhà cung cấp (n trang) | n = (2128 + page_size - 1) / page_size |
| Mảnh ramdisk của nhà cung cấp (trang o) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
| DTB (p trang) | p = (dtb_size + page_size - 1) / page_size |
| Bảng ramdisk của nhà cung cấp (q trang) | q = (vendor_ramdisk_table_size + page_size - 1) / page_size |
| Bootconfig (trang r) | r = (bootconfig_size + page_size - 1) / page_size |
Tiêu đề khởi động của nhà cung cấp
Nội dung của tiêu đề phân vùng khởi động của nhà cung cấp chủ yếu bao gồm dữ liệu đã được di chuyển từ tiêu đề hình ảnh khởi động. Tệp này cũng chứa thông tin về ramdisk của nhà cung cấp.
Phiên bản 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 */
};
Phiên bản 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_sizelà tổng kích thước của tất cả các mảnh ramdisk của nhà cung cấp.ramdisk_typebiểu thị loại ổ đĩa RAM, các giá trị có thể là:VENDOR_RAMDISK_TYPE_NONEcho biết giá trị chưa được chỉ định.VENDOR_RAMDISK_TYPE_PLATFORMramdisks chứa các bit dành riêng cho nền tảng. Trình tải khởi động phải luôn tải các tệp này vào bộ nhớ.VENDOR_RAMDISK_TYPE_RECOVERYramdisk chứa các tài nguyên khôi phục. Trình tải khởi động phải tải các tệp này vào bộ nhớ khi khởi động vào chế độ khôi phục.VENDOR_RAMDISK_TYPE_DLKMramdisk chứa các mô-đun hạt nhân có thể tải động.
ramdisk_namelà tên duy nhất của ramdisk.board_idlà một vectơ của các giá trị nhận dạng phần cứng do nhà cung cấp xác định.
Hỗ trợ trình tải khởi động
Vì phân vùng khởi động của nhà cung cấp chứa thông tin (chẳng hạn như kích thước trang flash, hạt nhân, địa chỉ tải ramdisk, chính DTB) trước đây tồn tại trong phân vùng khởi động, nên trình tải khởi động phải truy cập vào cả phân vùng khởi động và phân vùng khởi động của nhà cung cấp để có đủ dữ liệu hoàn tất quá trình khởi động.
Trình tải khởi động phải tải ramdisk chung vào bộ nhớ ngay lập tức sau khi tải ramdisk của nhà cung cấp (các định dạng CPIO, Gzip và lz4 hỗ trợ loại nối này). Đừng căn chỉnh trang hình ảnh ổ đĩa RAM chung hoặc đưa bất kỳ khoảng trống nào khác vào giữa hình ảnh đó và cuối ổ đĩa RAM của nhà cung cấp trong bộ nhớ. Sau khi giải nén, nhân sẽ trích xuất tệp được nối vào initramfs, dẫn đến cấu trúc tệp là một ramdisk chung được phủ lên cấu trúc tệp ramdisk của nhà cung cấp.
Vì ramdisk chung và ramdisk của nhà cung cấp được nối với nhau, nên các ramdisk này phải có cùng định dạng. Hình ảnh khởi động GKI sử dụng một ramdisk chung được nén lz4, vì vậy, một thiết bị tuân thủ GKI phải sử dụng ramdisk của nhà cung cấp được nén lz4. Cấu hình cho việc này được hiển thị bên dưới.
Các yêu cầu của trình tải khởi động để hỗ trợ bootconfig được giải thích trong phần Triển khai Bootconfig.
Nhiều ổ đĩa RAM của nhà cung cấp (phiên bản 4)
Với tiêu đề hình ảnh khởi động phiên bản 4, trình tải khởi động có thể chọn một tập hợp con hoặc tất cả các ổ đĩa RAM của nhà cung cấp để tải dưới dạng initramfs trong thời gian khởi động. Bảng ramdisk của nhà cung cấp chứa siêu dữ liệu của từng ramdisk và có thể hỗ trợ trình tải khởi động trong việc quyết định tải ramdisk nào. Trình tải khởi động có thể quyết định thứ tự tải các ổ đĩa RAM của nhà cung cấp đã chọn, miễn là ổ đĩa RAM chung được tải sau cùng.
Ví dụ: trình tải khởi động có thể bỏ qua việc tải ramdisk của nhà cung cấp thuộc loại VENDOR_RAMDISK_TYPE_RECOVERY trong quá trình khởi động bình thường để tiết kiệm tài nguyên, vì vậy, chỉ ramdisk của nhà cung cấp thuộc loại VENDOR_RAMDISK_TYPE_PLATFORM và VENDOR_RAMDISK_TYPE_DLKM mới được tải vào bộ nhớ. Mặt khác, các ổ đĩa RAM của nhà cung cấp thuộc loại VENDOR_RAMDISK_TYPE_PLATFORM, VENDOR_RAMDISK_TYPE_RECOVERY và VENDOR_RAMDISK_TYPE_DLKM được tải vào bộ nhớ khi khởi động vào chế độ khôi phục.
Ngoài ra, trình tải khởi động có thể bỏ qua bảng ramdisk của nhà cung cấp và tải toàn bộ phần ramdisk của nhà cung cấp. Cách này có tác dụng tương tự như việc tải tất cả các mảnh ramdisk của nhà cung cấp trong phân vùng vendor_boot.
Hỗ trợ xây dựng
Cách triển khai tính năng hỗ trợ khởi động của nhà cung cấp cho thiết bị:
Đặt
BOARD_BOOT_HEADER_VERSIONthành3trở lên.Đặt
BOARD_RAMDISK_USE_LZ4thànhtruenếu thiết bị của bạn tuân thủ GKI hoặc nếu thiết bị sử dụng ramdisk chung được nén lz4.Đặt
BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZEthành kích thước phù hợp cho thiết bị của bạn, có tính đến các mô-đun hạt nhân phải nằm trên ramdisk của nhà cung cấp.Cập nhật
AB_OTA_PARTITIONSđể thêmvendor_bootvà mọi danh sách phân vùng OTA dành riêng cho nhà cung cấp trên thiết bị.Sao chép
fstabcủa thiết bị vào/first_stage_ramdisktrong phân vùngvendor_boot, chứ không phải phân vùngboot. Chẳng hạn như$(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM).
Cách đưa nhiều ổ đĩa RAM của nhà cung cấp vào vendor_boot:
- Đặt
BOARD_BOOT_HEADER_VERSIONthành4. Đặt
BOARD_VENDOR_RAMDISK_FRAGMENTSthành danh sách tên mảnh ramdisk logic của nhà cung cấp để đưa vàovendor_boot.Để thêm một ramdisk của nhà cung cấp được tạo sẵn, hãy đặt
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILTthành đường dẫn được tạo sẵn.Để thêm ramdisk của nhà cung cấp DLKM, hãy đặt
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRSthành danh sách các thư mục mô-đun hạt nhân cần đưa vào.Đặt
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGSthành đối sốmkbootimg. Đây là các đối số--board_id[0-15]và--ramdisk_typecho mảnh ramdisk của nhà cung cấp. Đối với ramdisk của nhà cung cấp DLKM,--ramdisk_typemặc định sẽ làDLKMnếu không được chỉ định khác.
Cách tạo tài nguyên khôi phục dưới dạng recovery ramdisk độc lập trong vendor_boot:
- Đặt
BOARD_BOOT_HEADER_VERSIONthành4. - Đặt
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOTthànhtrue. - Đặt
BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOTthànhtrue. - Thao tác này sẽ thêm một mảnh ramdisk của nhà cung cấp có
ramdisk_namelàrecoveryvàramdisk_typelàVENDOR_RAMDISK_TYPE_RECOVERY. Sau đó, ramdisk sẽ chứa tất cả các tệp khôi phục, là các tệp được cài đặt trong$(TARGET_RECOVERY_ROOT_OUT).
Đối số mkbootimg
| Đối số | Mô tả |
|---|---|
--ramdisk_type |
Loại của ramdisk, có thể là một trong các loại NONE, PLATFORM, RECOVERY hoặc DLKM.
|
--board_id[0-15] |
Chỉ định vectơ board_id, mặc định là 0. |
Sau đây là cấu hình mẫu:
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 thu được sẽ chứa hai mảnh ramdisk của nhà cung cấp. Thư mục đầu tiên là ramdisk "mặc định", chứa thư mục DLKM baz và các tệp còn lại trong $(TARGET_VENDOR_RAMDISK_OUT). Thứ hai là dlkm_foobar ramdisk, chứa các thư mục DLKM foo và bar, và --ramdisk_type mặc định là DLKM.