Partycje rozruchowe dostawcy

Android 11 wprowadził koncepcję Generic Kernel Image (GKI). Aby umożliwić uruchamianie dowolnego urządzenia za pomocą interfejsu GKI, urządzenia z Androidem 11 mogą używać nagłówka obrazu rozruchu w wersji 3. W wersji 3 wszystkie informacje o dostawcy są wykluczane z partycji boot i przenoszone do nowej partycji vendor_boot. urządzenie z architekturą ARM64, uruchamianie systemu Android 11 z jądrem systemu Linux 5.4 musi obsługują partycję vendor_boot i zaktualizowany format partycji boot na zalicza testy w GKI.

Urządzenia z Androidem 12 mogą używać nagłówka obrazu rozruchowego w wersji 4, który umożliwia uwzględnienie wielu dysków RAM dostawców w pliku vendor_boot partycji danych. W sekcji dotyczącej ramdiska dostawcy wiele fragmentów ramdiska jest łączonych jeden po drugim. Tabela ramdisk dostawcy służy do opisania układu sekcji ramdisk dostawcy i metadanych każdego fragmentu ramdisk dostawcy.

Struktura partycji

Partycja rozruchu dostawcy jest skonfigurowana w trybie A/B z wirtualnym trybem A/B i chroniona przez funkcję Verified Boot w Androidzie.

Wersja 3

Partycja składa się z nagłówka, dysku Ramdisk dostawcy i bloba drzewa urządzenia. (DTB).

Sekcja Liczba stron
Nagłówek uruchamiania dostawcy (n stron) n = (2112 + page_size - 1) / page_size
Dostawca ramdisk (o strony) 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 dostawcy ramdisk (która zawiera wszystkie złączone fragmenty ramdisk dostawcy), pliku danych drzewa urządzenia (DTB) i tabeli ramdisk dostawcy.

Sekcja Liczba stron
Nagłówek uruchamiania dostawcy (n stron) n = (2128 + page_size - 1) / page_size
Fragmenty dostawcy dotyczące dysku RAM (o stronach) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (strony: p) p = (dtb_size + page_size - 1) / page_size
Tabela ramdisk dostawcy (strony Q) q = (vendor_ramdisk_table_size + page_size - 1) / page_size
Bootconfig (strony r) 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 on również informacje o pamięci 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 pamięci RAM dostawcy.
  • ramdisk_type określa typ dysku ramdy. Możliwe wartości to:
    • VENDOR_RAMDISK_TYPE_NONE oznacza, że wartość nie została określona.
    • VENDOR_RAMDISK_TYPE_PLATFORM Ramdiski zawierają bity specyficzne dla platformy. Program rozruchowy musi zawsze wczytywać je do pamięci.
    • VENDOR_RAMDISK_TYPE_RECOVERY Pamięci RAM zawierają zasoby odzyskiwania. program rozruchowy musi wczytać je do pamięci podczas uruchamiania systemu przywracania.
    • VENDOR_RAMDISK_TYPE_DLKM Ramdysk zawiera dynamicznie ładowalne moduły jądra.
  • ramdisk_name to niepowtarzalna nazwa dysku ramdysk.
  • board_id to wektor identyfikatorów sprzętowych zdefiniowanych przez dostawcę.
.

Obsługa programu rozruchowego

Ponieważ partycja rozruchowa dostawcy zawiera informacje (takie jak rozmiar strony w formacie Flash, jądra systemu, adresy wczytywania Ramdisk czy plik DTB), które wcześniej istniały w w partycji rozruchowej, program rozruchowy musi mieć dostęp zarówno do partycje muszą mieć wystarczającą ilość danych do ukończenia rozruchu.

Program rozruchowy musi załadować ogólny dysk RAM do pamięci natychmiast po na dysku ramdisk dostawcy (formaty CPIO, Gzip i Lz4 obsługują ten typ konkatenacja). Nie wyrównywaj strony z ogólnym obrazem dysku RAM ani nie wprowadzaj żadnego między nim a końcem dysku RAM dostawcy w pamięci. Po jądro dekompresuje, wyodrębnia połączony plik do pliku initramfs, co daje strukturę pliku, która jest ogólnym plikiem ramdisk nałożonym na strukturę pliku Ramdisk dostawcy.

Ogólny ramdysk i ramdysk dostawcy są łączone, więc muszą znajdować się taki sam format. Obraz rozruchowy GKI korzysta z ogólnego pliku RAM skompresowanego w formacie LZ4, urządzenie zgodne z GKI musi korzystać z pliku ramdisk dostawcy skompresowanego w formacie lz4. Konfiguracja tego ustawienia jest pokazana poniżej.

Wymagania programu rozruchowego dotyczące obsługi rozruchu zostały objaśnione w Wdrożenie Bootconfig.

Wiele dysków RAM dostawców (wersja 4)

Jeśli używasz nagłówka obrazu rozruchowego w wersji 4, program rozruchowy może wybrać podzbiór wszystkie pliki pamięci RAM dostawcy, które są wczytywane jako initramfs podczas rozruchu. Tabela vendor ramdisk zawiera metadane każdego dysku RAM i może pomóc programowi rozruchowemu w podejmowaniu decyzji, które dyski RAM mają być ładowane. Program rozruchowy może określić do wczytywania dysków RAM wybranych dostawców, o ile tylko ogólny jako ostatni.

Na przykład program rozruchowy może pominąć wczytywanie pamięci RAM typu VENDOR_RAMDISK_TYPE_RECOVERY w ramce normalnego rozruchu, aby oszczędzać zasoby. W pamięci są wczytywane tylko pamięci RAM typu VENDOR_RAMDISK_TYPE_PLATFORMVENDOR_RAMDISK_TYPE_DLKM. Z drugiej strony, ramdysk dostawcy typu VENDOR_RAMDISK_TYPE_PLATFORM, VENDOR_RAMDISK_TYPE_RECOVERY i VENDOR_RAMDISK_TYPE_DLKM jest ładowany do pamięci podczas uruchamiania w trybie odzyskiwania.

Alternatywnie bootloader może zignorować tabelę ramdisk dostawcy i wczytać całą sekcję ramdisk dostawcy. Ma to taki sam efekt jak wczytywanie wszystkich fragmentów pamięci RAM dostarczyciela na partycji vendor_boot.

Wsparcie

Aby wdrożyć na urządzeniu obsługę uruchamiania dostawcy:

  • Ustaw BOARD_BOOT_HEADER_VERSION na wartość 3 lub większą.

  • Ustaw BOARD_RAMDISK_USE_LZ4 na true, jeśli Twoje urządzenie jest zgodne z GKI lub w przeciwnym razie korzysta z ogólnego pliku ramdisk skompresowanego za pomocą algorytmu lz4.

  • Ustaw BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE na odpowiedni rozmiar dla urządzenia, biorąc pod uwagę moduły jądra, które muszą znajdować się na partycji RAM dostawcy.

  • Zaktualizuj pole AB_OTA_PARTITIONS, aby uwzględnić element vendor_boot i wszystkie odpowiednie dla tego dostawcy listy partycji OTA na urządzeniu.

  • Skopiuj urządzenie fstab do /first_stage_ramdisk w partycji vendor_boot, a nie boot. Przykład: $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM)

Aby uwzględnić w pliku vendor_boot więcej plików pamięci RAM różnych dostawców:

  • Ustaw BOARD_BOOT_HEADER_VERSION na 4.
  • Ustaw BOARD_VENDOR_RAMDISK_FRAGMENTS na listę pamięci RAMdysk logicznego dostawcy nazwy fragmentów do uwzględnienia w polu vendor_boot.

  • Aby dodać gotowy obraz pamięci RAM od dostawcy, ustaw parametr BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT na ścieżkę do gotowego obrazu.

  • Aby dodać ramdisk dostawcy DLKM, ustaw BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS na liście katalogów modułów jądra, które mają być uwzględnione.

  • Ustaw argumenty BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS na mkbootimg. Są to argumenty --board_id[0-15]--ramdisk_type w ramce fragmentu ramdisk dostawcy. W przypadku pamięci ramowej dostawcy w ramach usługi DLKM domyślna wartość parametru --ramdisk_type to DLKM, jeśli nie zostanie określona inna wartość.

Aby utworzyć zasoby do przywracania jako samodzielny dysk RAM recovery w vendor_boot:

  • Ustaw BOARD_BOOT_HEADER_VERSION na 4.
  • Ustaw BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT na true.
  • Ustaw BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT na true.
  • Dodaje fragment ramdisk dostawcy, którego ramdisk_name to recovery, a ramdisk_type to VENDOR_RAMDISK_TYPE_RECOVERY. Dysk RAM zawiera wszystkie pliki odzyskiwania, czyli pliki zainstalowane w katalogu $(TARGET_RECOVERY_ROOT_OUT).

Argumenty mkbootimg

Argument Opis
--ramdisk_type Typ dysku RAM może być NONE, PLATFORM, RECOVERY lub DLKM.
--board_id[0-15] Określ wektor board_id, który domyślnie ma wartość 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

Powstały vendor_boot zawierałby 2 fragmenty ramdisk dostawcy. Pierwszy jest „domyślny” ramdisk, który zawiera katalog DLKM baz oraz pozostałe pliki w folderze $(TARGET_VENDOR_RAMDISK_OUT). Drugim jest dysk RAM dlkm_foobar, który zawiera katalogi DLKM foobar, a wartość domyślna --ramdisk_type to DLKM.