Android 11 wprowadził koncepcję ogólnego obrazu jądra (GKI). Aby umożliwić uruchamianie dowolnego urządzenia za pomocą GKI, urządzenia z Androidem 11 mogą używać nagłówka obrazu rozruchowego w wersji 3. W
wersji 3 wszystkie informacje specyficzne dla dostawcy są wyodrębnione z boot
partycji i przeniesione do nowej partycji vendor_boot. Urządzenie ARM64
z Androidem 11 i jądrem Linux 5.4 musi
obsługiwać partycję vendor_boot oraz zaktualizowany format partycji boot, aby
przejść testy z GKI.
Urządzenia z Androidem 12 mogą używać nagłówka obrazu rozruchowego w wersji 4, który umożliwia umieszczanie wielu dysków RAM dostawcy w partycji vendor_boot. Wiele fragmentów dysku RAM dostawcy jest łączonych jeden po drugim w sekcji dysku RAM dostawcy. Tabela dysku RAM dostawcy służy do opisywania układu sekcji dysku RAM dostawcy i metadanych każdego fragmentu dysku RAM dostawcy.
Struktura partycji
Partycja rozruchowa dostawcy jest podzielona na partycje A/B z wirtualnymi partycjami A/B i chroniona przez weryfikację podczas uruchamiania Androida.
Wersja 3
Partycja składa się z nagłówka, dysku RAM dostawcy i obiektu drzewa urządzenia (DTB).
| Sekcja | Liczba stron |
|---|---|
| Nagłówek rozruchowy dostawcy (n stron) | n = (2112 + page_size - 1) / page_size |
| Dysk RAM dostawcy (o stron) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
| DTB (p stron) | p = (dtb_size + page_size - 1) / page_size |
Wersja 4
Partycja składa się z nagłówka, sekcji dysku RAM dostawcy (zawierającej wszystkie połączone fragmenty dysku RAM dostawcy), obiektu drzewa urządzenia (DTB) i tabeli dysku RAM dostawcy.
| Sekcja | Liczba stron |
|---|---|
| Nagłówek rozruchowy dostawcy (n stron) | n = (2128 + page_size - 1) / page_size |
| Fragmenty dysku RAM dostawcy (o stron) | o = (vendor_ramdisk_size + page_size - 1) / page_size |
| DTB (p stron) | 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 stron) | r = (bootconfig_size + page_size - 1) / page_size |
Nagłówek rozruchowy dostawcy
Zawartość nagłówka partycji rozruchowej dostawcy składa się głównie z danych , które zostały przeniesione 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_sizeto łączny rozmiar wszystkich fragmentów dysku RAM dostawcy.ramdisk_typeoznacza typ dysku RAM. Możliwe wartości:VENDOR_RAMDISK_TYPE_NONEoznacza, że wartość nie jest określona.VENDOR_RAMDISK_TYPE_PLATFORMdyski RAM zawierają bity specyficzne dla platformy. Program rozruchowy musi zawsze ładować je do pamięci.VENDOR_RAMDISK_TYPE_RECOVERYdyski RAM zawierają zasoby odzyskiwania. Program rozruchowy musi ładować je do pamięci podczas uruchamiania w trybie odzyskiwania.VENDOR_RAMDISK_TYPE_DLKMdyski RAM zawierają dynamicznie ładowane moduły jądra.
ramdisk_nameto unikalna nazwa dysku RAM.board_idto wektor identyfikatorów sprzętu zdefiniowanych przez dostawcę.
Obsługa programu rozruchowego
Ponieważ partycja rozruchowa dostawcy zawiera informacje (takie jak rozmiar strony flash, jądro, adresy ładowania dysku RAM, sam DTB), które wcześniej znajdowały się w partycji rozruchowej, 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 uruchamiania.
Program rozruchowy musi załadować 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 obrazu ogólnego dysku RAM do strony ani nie wprowadzaj żadnych innych spacji między nim a końcem dysku RAM dostawcy w pamięci. Po dekompresji jądro wyodrębnia 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. Konfiguracja jest pokazana poniżej.
Wymagania dotyczące programu rozruchowego w zakresie obsługi bootconfig są opisane w sekcji Implementowanie bootconfig.
Wiele dysków RAM dostawcy (wersja 4)
W przypadku nagłówka obrazu rozruchowego w wersji 4 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 należy załadować. Program rozruchowy może zdecydować o kolejności ładowania wybranych dysków RAM dostawcy, o ile ogólny dysk RAM zostanie załadowany jako ostatni.
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. W takim przypadku do pamięci są ładowane tylko dyski RAM dostawcy typu VENDOR_RAMDISK_TYPE_PLATFORM i VENDOR_RAMDISK_TYPE_DLKM. Z drugiej strony, podczas uruchamiania w trybie odzyskiwania do pamięci są ładowane dyski RAM dostawcy typu VENDOR_RAMDISK_TYPE_PLATFORM, VENDOR_RAMDISK_TYPE_RECOVERY i VENDOR_RAMDISK_TYPE_DLKM.
Program rozruchowy może też zignorować tabelę dysku RAM dostawcy i załadować całą sekcję dysku RAM dostawcy. Ma to taki sam efekt jak załadowanie wszystkich fragmentów dysku RAM dostawcy w partycji vendor_boot.
Obsługa kompilacji
Aby zaimplementować obsługę rozruchu dostawcy na urządzeniu:
Ustaw
BOARD_BOOT_HEADER_VERSIONna3lub wyższą.Jeśli Twoje urządzenie jest zgodne z GKI lub używa ogólnego dysku RAM skompresowanego za pomocą lz4, ustaw
BOARD_RAMDISK_USE_LZ4natrue.Ustaw
BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZEna 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_booti wszelkie listy partycji OTA specyficzne dla dostawcy na urządzeniu.Skopiuj
fstaburządzenia do/first_stage_ramdiskw partycjivendor_boot, 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ć wiele dysków RAM dostawcy w vendor_boot:
- Ustaw
BOARD_BOOT_HEADER_VERSIONna4. Ustaw
BOARD_VENDOR_RAMDISK_FRAGMENTSna listę logicznych nazw fragmentów 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).PREBUILTna ścieżkę wstępnie skompilowanego dysku.Aby dodać dysk RAM dostawcy DLKM, ustaw
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRSna listę katalogów modułów jądra, które mają być uwzględnione.Ustaw
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGSna argumentymkbootimg. Są to argumenty--board_id[0-15]i--ramdisk_typedla fragmentu dysku RAM dostawcy. W przypadku dysku RAM dostawcy DLKM domyślna wartość--ramdisk_typetoDLKM, jeśli nie określono inaczej.
Aby skompilować zasoby odzyskiwania jako samodzielny dysk RAM recovery w vendor_boot:
- Ustaw
BOARD_BOOT_HEADER_VERSIONna4. - Ustaw
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOTnatrue. - Ustaw
BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOTnatrue. - Spowoduje to dodanie fragmentu dysku RAM dostawcy, którego
ramdisk_nametorecovery, aramdisk_typetoVENDOR_RAMDISK_TYPE_RECOVERY. Dysk RAM będzie wtedy zawierać wszystkie pliki odzyskiwania, czyli pliki zainstalowane w$(TARGET_RECOVERY_ROOT_OUT).
Argumenty mkbootimg
| Argument | Opis |
|---|---|
--ramdisk_type |
Typ dysku RAM. Może to być jedna z tych wartości: NONE,
PLATFORM, RECOVERY lub DLKM.
|
--board_id[0-15] |
Określ wektor board_id. Domyślnie jest to 0. |
Oto przykład konfiguracji:
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 vendor_boot będzie zawierać 2 fragmenty dysku RAM dostawcy. Pierwszy to dysk RAM „default”, który zawiera katalog DLKM baz i pozostałe pliki w $(TARGET_VENDOR_RAMDISK_OUT). Drugi to
dlkm_foobar dysk RAM, który zawiera katalogi DLKM foo i bar, a
--ramdisk_type domyślnie ma wartość DLKM.