W Androidzie 11 wprowadzono koncepcję ogólnego obrazu jądra (GKI). Aby umożliwić łatwe uruchamianie dowolnego urządzenia za pomocą GKI, urządzenia z systemem Android 11 mogą używać nagłówka obrazu rozruchowego w wersji 3. W wersji 3 wszystkie informacje specyficzne dla dostawcy są usuwane z partycji boot
i przenoszone do nowej partycji vendor_boot
. Urządzenie ARM64 uruchamiane z systemem Android 11 na jądrze Linux 5.4 musi obsługiwać partycję vendor_boot
i zaktualizowany format partycji boot
, aby przejść testy z GKI.
Urządzenia z systemem Android 12 mogą korzystać z nagłówka obrazu rozruchowego w wersji 4, który obsługuje włączanie wielu ramdysków dostawcy do partycji vendor_boot
. Fragmenty wielu ramdysków dostawców są łączone jeden po drugim w sekcji ramdysku dostawcy. Tabela RAMdysku dostawcy służy do opisu układu sekcji RAMdysku dostawcy i metadanych każdego fragmentu RAMdysku dostawcy.
Struktura partycji
Partycja rozruchowa dostawcy to A/B z wirtualnym A/B i chroniona przez Android Verified Boot.
Wersja 3
Partycja składa się z nagłówka, dysku RAM dostawcy i obiektu blob drzewa urządzeń (DTB).
Sekcja | Numer stron |
---|---|
Nagłówek rozruchowy dostawcy (n stron) | n = (2112 + page_size - 1) / page_size |
Ramdysk 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 RAMdysku dostawcy (składającej się ze wszystkich fragmentów RAMdysku dostawcy, połączonych), obiektu blob drzewa urządzeń (DTB) i tabeli RAMdysku dostawcy.
Sekcja | Numer stron |
---|---|
Nagłówek rozruchowy 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 (p stron) | p = (dtb_size + page_size - 1) / page_size |
Tabela ramdysku 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 tam przeniesione z nagłówka obrazu rozruchowego . Zawiera także informacje o ramdysku 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 całkowity rozmiar wszystkich fragmentów RAMdysku dostawcy. -
ramdisk_type
oznacza typ ramdysku, możliwe wartości to:-
VENDOR_RAMDISK_TYPE_NONE
wskazuje, że wartość jest nieokreślona. - Ramdyski
VENDOR_RAMDISK_TYPE_PLATFORM
zawierają bity specyficzne dla platformy. Program ładujący musi zawsze ładować je do pamięci. - Ramdyski
VENDOR_RAMDISK_TYPE_RECOVERY
zawierają zasoby do odzyskiwania. Program ładujący musi załadować je do pamięci podczas uruchamiania systemu odzyskiwania. - Ramdyski
VENDOR_RAMDISK_TYPE_DLKM
zawierają dynamicznie ładowalne moduły jądra.
-
-
ramdisk_name
to unikalna nazwa ramdysku. -
board_id
to wektor zdefiniowanych przez dostawcę identyfikatorów sprzętu.
Obsługa bootloadera
Ponieważ partycja rozruchowa dostawcy zawiera informacje (takie jak rozmiar strony flash, jądro, adresy ładowania ramdysku, sam DTB), które wcześniej znajdowały się na partycji rozruchowej, program ładujący musi uzyskać dostęp zarówno do partycji rozruchowej, jak i partycji rozruchowej dostawcy, aby mieć wystarczającą ilość danych do ukończenia rozruchu .
Program ładujący musi załadować ogólny ramdysk do pamięci bezpośrednio po ramdysku dostawcy (formaty CPIO, Gzip i lz4 obsługują ten typ konkatenacji). Nie wyrównuj strony ogólnego obrazu ramdysku ani nie wprowadzaj żadnej innej spacji pomiędzy nim a końcem RAMdysku dostawcy w pamięci. Po dekompresji jądro wyodrębnia połączony plik do pliku initramfs
, co skutkuje strukturą pliku będącą ogólnym ramdyskiem nałożonym na strukturę pliku ramdysku dostawcy.
Ponieważ ogólny ramdysk i ramdysk dostawcy są łączone, muszą mieć ten sam format. Obraz rozruchowy GKI wykorzystuje ogólny dysk RAM skompresowany przy użyciu lz4, więc urządzenie zgodne z GKI musi korzystać z RAMdysku dostawcy skompresowanego przy użyciu lz4. Konfiguracja tego została pokazana poniżej.
Wymagania programu ładującego dotyczące obsługi bootconfig są wyjaśnione na stronie Implementowanie Bootconfig .
Ramdyski wielu dostawców (wersja 4)
W przypadku nagłówka obrazu rozruchowego w wersji 4 program ładujący może wybrać podzbiór lub wszystkie dyski ramkowe dostawcy do załadowania jako pliki initramfs
podczas rozruchu. Tabela ramdysku dostawcy zawiera metadane każdego ramdysku i może pomóc programowi ładującemu w podjęciu decyzji, które ramdyski załadować. Program ładujący może zdecydować o kolejności ładowania ramdysków wybranego dostawcy, o ile ogólny ramdysk zostanie załadowany jako ostatni.
Na przykład program ładujący może pominąć ładowanie ramdysków dostawcy typu VENDOR_RAMDISK_TYPE_RECOVERY
podczas normalnego rozruchu, aby oszczędzać zasoby, więc do pamięci ładowane są tylko ramdyski dostawcy typu VENDOR_RAMDISK_TYPE_PLATFORM
i VENDOR_RAMDISK_TYPE_DLKM
. Z drugiej strony, ramdyski 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.
Alternatywnie program ładujący może zignorować tabelę RAMdysku dostawcy i załadować całą sekcję RAMdysku dostawcy. Ma to taki sam efekt, jak ładowanie wszystkich fragmentów RAMdysku dostawcy na partycję vendor_boot
.
Buduj wsparcie
Aby zaimplementować obsługę rozruchu dostawcy dla urządzenia:
Ustaw
BOARD_BOOT_HEADER_VERSION
na3
lub więcej.Ustaw
BOARD_RAMDISK_USE_LZ4
natrue
, jeśli twoje urządzenie jest zgodne z GKI lub jeśli w inny sposób używa ogólnego RAMdysku skompresowanego lz4.Ustaw
BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE
na rozmiar odpowiedni dla Twojego urządzenia, biorąc pod uwagę moduły jądra, które muszą znaleźć się na dysku RAM dostawcy.Zaktualizuj
AB_OTA_PARTITIONS
, aby uwzględnićvendor_boot
i wszelkie specyficzne dla dostawcy listy partycji OTA na urządzeniu.Skopiuj
fstab
urządzenia do/first_stage_ramdisk
na partycjivendor_boot
, a nie na partycjiboot
. Na przykład$(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM)
.
Aby dołączyć wiele ramdysków dostawcy do vendor_boot
:
- Ustaw
BOARD_BOOT_HEADER_VERSION
na4
. Ustaw
BOARD_VENDOR_RAMDISK_FRAGMENTS
na listę nazw logicznych fragmentów ramdysku dostawcy, które mają zostać uwzględnione wvendor_boot
.Aby dodać wstępnie zbudowany ramdysk dostawcy, ustaw
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT
na ścieżkę gotowego pliku.Aby dodać ramdysk dostawcy DLKM, ustaw
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS
na listę katalogów modułów jądra, które mają zostać uwzględnione.Ustaw
BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS
na argumentymkbootimg
. Są to argumenty--board_id[0-15]
i--ramdisk_type
dla fragmentu ramdysku dostawcy. W przypadku ramdysku dostawcy DLKM domyślnym--ramdisk_type
będzieDLKM
, jeśli nie określono inaczej.
Aby zbudować zasoby odzyskiwania jako samodzielny ramdysk recovery
w vendor_boot
:
- Ustaw
BOARD_BOOT_HEADER_VERSION
na4
. - Ustaw
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT
natrue
. - Ustaw
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
. Ramdysk zawiera wówczas wszystkie pliki odzyskiwania, które są plikami zainstalowanymi w$(TARGET_RECOVERY_ROOT_OUT)
.
argumenty mkbootimg
Argument | Opis |
---|---|
--ramdisk_type | Typ ramdysku może być NONE , PLATFORM , RECOVERY lub DLKM . |
--board_id[0-15] | Określ wektor board_id , domyślnie 0 . |
Poniżej znajduje się 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 vendor_boot
będzie zawierał dwa fragmenty RAMdysku dostawcy. Pierwszy z nich to „domyślny” ramdysk, który zawiera katalog DLKM baz
i resztę plików w $(TARGET_VENDOR_RAMDISK_OUT)
. Drugi to ramdysk dlkm_foobar
, który zawiera katalogi DLKM foo
i bar
, a parametr --ramdisk_type
ma wartość domyślną DLKM
.