W Androidzie 11 wprowadzono koncepcję ogólnego obrazu jądra (GKI). Aby włączyć uruchamianie dowolnego urządzenia za pomocą GKI, urządzenia z Androidem 11 mogą używać wersji 3 nagłówka obrazu rozruchowego. W wersji 3 wszystkie informacje dotyczące dostawcy są wyłączone z boot
partycji i przeniesione do nowej partycji vendor_boot
. Urządzenie z architekturą ARM64, które jest wprowadzane na rynek z Androidem 11 na jądrze Linuksa w wersji 5.4, musi obsługiwać partycję vendor_boot
i zaktualizowany format partycji boot
, aby przejść testy z GKI.
Urządzenia z Androidem 12 mogą używać wersji 4 nagłówka obrazu rozruchowego, która obsługuje umieszczanie wielu dysków RAM dostawcy w vendor_boot
. W sekcji ramdysku dostawcy kilka fragmentów ramdysku dostawcy jest łączonych jeden po drugim. Tabela ramdysku dostawcy służy do opisywania układu sekcji ramdysku dostawcy i metadanych każdego fragmentu ramdysku dostawcy.
Struktura partycji
Partycja rozruchowa dostawcy jest podzielona na 2 wersje (A/B) z wirtualnym podziałem A/B i chroniona przez weryfikację podczas uruchamiania Androida.
Wersja 3
Partycja składa się z nagłówka, dysku RAM dostawcy i pliku binarnego drzewa urządzenia (DTB).
Sekcja | Liczba stron |
---|---|
Nagłówek uruchamiania dostawcy (n stron) | n = (2112 + page_size - 1) / page_size |
Dysk RAM dostawcy (0 stron) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
DTB (strony p) | p = (dtb_size + page_size - 1) / page_size |
Wersja 4
Partycja składa się z nagłówka, sekcji obrazu dysku RAM dostawcy (zawierającej wszystkie połączone fragmenty obrazu dysku RAM dostawcy), pliku binarnego drzewa urządzenia (DTB) i tabeli obrazu dysku RAM dostawcy.
Sekcja | Liczba stron |
---|---|
Nagłówek uruchamiania dostawcy (n stron) | n = (2128 + page_size - 1) / page_size |
Fragmenty ramdysku dostawcy (o stron) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
DTB (strony p) | p = (dtb_size + page_size - 1) / page_size |
Tabela dysku RAM dostawcy (q stron) | q = (vendor_ramdisk_table_size + page_size - 1) / page_size |
Bootconfig (r pages) | r = (bootconfig_size + page_size - 1) / page_size |
Nagłówek uruchamiania dostawcy
Zawartość nagłówka partycji rozruchowej dostawcy składa się głównie z danych przeniesionych z nagłówka obrazu rozruchowego. Zawiera też informacje o dysku RAM dostawcy.
Wersja 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 */
};
Wersja 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
to łączny rozmiar wszystkich fragmentów ramdysku dostawcy.ramdisk_type
oznacza typ dysku RAM. Możliwe wartości:VENDOR_RAMDISK_TYPE_NONE
oznacza, że wartość nie jest określona.VENDOR_RAMDISK_TYPE_PLATFORM
dyski RAM zawierają elementy specyficzne dla platformy. Program rozruchowy musi zawsze ładować je do pamięci.VENDOR_RAMDISK_TYPE_RECOVERY
dyski RAM zawierają zasoby przywracania. Program rozruchowy musi załadować je do pamięci podczas uruchamiania trybu recovery.VENDOR_RAMDISK_TYPE_DLKM
dyski RAM zawierają dynamicznie ładowane moduły jądra.
ramdisk_name
to unikalna nazwa dysku RAM.board_id
to wektor identyfikatorów sprzętu zdefiniowanych przez dostawcę.
Obsługa programu rozruchowego
Partycja rozruchowa dostawcy zawiera informacje (takie jak rozmiar strony pamięci flash, jądro, adresy ładowania dysku RAM, sam DTB), które wcześniej znajdowały się w partycji rozruchowej. Z tego powodu program rozruchowy musi mieć dostęp zarówno do partycji rozruchowej, jak i do partycji rozruchowej dostawcy, aby mieć wystarczającą ilość danych do ukończenia procesu uruchamiania.
Program rozruchowy musi wczytać ogólny dysk RAM do pamięci bezpośrednio po dysku RAM dostawcy (formaty CPIO, Gzip i lz4 obsługują ten typ łączenia). Nie wyrównuj strony ogólnego obrazu ramdysku ani nie wprowadzaj żadnych innych spacji między nim a końcem ramdysku dostawcy w pamięci. Po dekompresji jądra wyodrębnia ono połączony plik do initramfs
, co powoduje powstanie struktury plików, która jest ogólnym dyskiem RAM nałożonym na strukturę plików dysku RAM dostawcy.
Ponieważ ogólny dysk RAM i dysk RAM dostawcy są łączone, muszą być w tym samym formacie. Obraz rozruchowy GKI używa ogólnego dysku RAM skompresowanego za pomocą lz4, więc urządzenie zgodne z GKI musi używać dysku RAM dostawcy skompresowanego za pomocą lz4. Poniżej znajdziesz konfigurację tego ustawienia.
Wymagania dotyczące programu rozruchowego, które umożliwiają obsługę bootconfig, zostały opisane w artykule Implementowanie bootconfig.
Wiele dysków RAM dostawców (wersja 4)
W przypadku wersji 4 nagłówka obrazu rozruchowego program rozruchowy może wybrać podzbiór lub wszystkie dyski RAM dostawcy do załadowania jako initramfs
podczas uruchamiania. Tabela dysku RAM dostawcy zawiera metadane każdego dysku RAM i może pomóc programowi rozruchowemu w podjęciu decyzji, które dyski RAM wczytać. Program rozruchowy może zdecydować o kolejności wczytywania wybranych dysków RAM dostawcy, o ile ogólny dysk RAM jest wczytywany na końcu.
Na przykład program rozruchowy może pominąć ładowanie dysków RAM dostawcy typu VENDOR_RAMDISK_TYPE_RECOVERY
podczas normalnego uruchamiania, aby oszczędzać zasoby, więc do pamięci są ładowane tylko dyski RAM dostawcy typu VENDOR_RAMDISK_TYPE_PLATFORM
i VENDOR_RAMDISK_TYPE_DLKM
. Z drugiej strony dyski RAM dostawcy typu VENDOR_RAMDISK_TYPE_PLATFORM
, VENDOR_RAMDISK_TYPE_RECOVERY
i VENDOR_RAMDISK_TYPE_DLKM
są ładowane do pamięci podczas uruchamiania w trybie odzyskiwania.
Program rozruchowy może też zignorować tabelę ramdysku dostawcy i wczytać całą sekcję ramdysku dostawcy. Daje to taki sam efekt jak wczytanie wszystkich fragmentów ramdysku dostawcy w partycji vendor_boot
.
Pomoc dotycząca kompilacji
Aby zaimplementować obsługę rozruchu dostawcy na urządzeniu:
Ustaw wartość
BOARD_BOOT_HEADER_VERSION
na3
lub większą.Ustaw
BOARD_RAMDISK_USE_LZ4
natrue
, jeśli urządzenie jest zgodne z GKI lub w inny sposób używa ogólnego dysku RAM skompresowanego za pomocą lz4.Ustaw
BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE
na odpowiedni rozmiar dla Twojego urządzenia, biorąc pod uwagę moduły jądra, które muszą znajdować się na dysku RAM dostawcy.Zaktualizuj
AB_OTA_PARTITIONS
, aby uwzględnićvendor_boot
i wszystkie listy partycji OTA na urządzeniu, które są specyficzne dla dostawcy.Skopiuj urządzenie
fstab
do/first_stage_ramdisk
wvendor_boot
partycji, a nie w partycjiboot
. Na przykład:$(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM)
.
Aby uwzględnić w vendor_boot
wiele dysków RAM dostawcy:
- Ustaw wartość
BOARD_BOOT_HEADER_VERSION
na4
. Ustaw
BOARD_VENDOR_RAMDISK_FRAGMENTS
na listę nazw fragmentów logicznego dysku RAM dostawcy, które mają być uwzględnione wvendor_boot
.Aby dodać wstępnie skompilowany dysk RAM dostawcy, ustaw
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT
na wstępnie skompilowaną ścieżkę.Aby dodać dysk RAM dostawcy DLKM, ustaw
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS
na liście katalogów modułów jądra do uwzględnienia.Ustaw argumenty
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS
namkbootimg
. Są to argumenty--board_id[0-15]
i--ramdisk_type
fragmentu ramdysku dostawcy. W przypadku ramdysku dostawcy DLKM domyślna wartość--ramdisk_type
toDLKM
, jeśli nie określono inaczej.
Aby utworzyć zasoby przywracania jako samodzielny dysk RAM recovery
w vendor_boot
:
- Ustaw wartość
BOARD_BOOT_HEADER_VERSION
na4
. - Ustaw wartość
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT
natrue
. - Ustaw wartość
BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT
natrue
. - Spowoduje to dodanie fragmentu ramdysku dostawcy, którego
ramdisk_name
torecovery
, aramdisk_type
toVENDOR_RAMDISK_TYPE_RECOVERY
. Dysk RAM zawiera wszystkie pliki przywracania, czyli pliki zainstalowane w katalogu$(TARGET_RECOVERY_ROOT_OUT)
.
Argumenty mkbootimg
Argument | Opis |
---|---|
--ramdisk_type |
Typ dysku RAM może mieć jedną z tych wartości: NONE , PLATFORM , RECOVERY lub DLKM .
|
--board_id[0-15] |
Określ wektor board_id , domyślnie 0 . |
Oto przykładowa konfiguracja:
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
Wynikowy plik vendor_boot
będzie zawierać 2 fragmenty dysku RAM dostawcy. Pierwszy z nich to „domyślny” dysk RAM, który zawiera katalog DLKM baz
i pozostałe pliki w $(TARGET_VENDOR_RAMDISK_OUT)
. Drugi to dlkm_foobar
ramdisk, który zawiera katalogi DLKM foo
i bar
, a wartość domyślna --ramdisk_type
to DLKM
.