Satıcı Önyükleme Bölümleri

Android 11, Genel Çekirdek Görüntüsü (GKI) kavramını tanıttı. GKI ile rastgele bir cihazın kolayca önyüklenmesini sağlamak için, Android 11 cihazları, önyükleme görüntüsü üstbilgisi sürüm 3'ü kullanabilir. Sürüm 3'te, satıcıya özel tüm bilgiler, boot bölümünden çıkarılır ve yeni bir vendor_boot bölümüne taşınır. 5.4 Linux çekirdeğinde Android 11 ile başlatılan bir ARM64 cihazının, GKI ile testi geçebilmesi için vendor_boot bölümünü ve güncellenmiş boot bölümü biçimini desteklemesi gerekir.

Android 12 cihazları, vendor_boot bölümüne birden çok satıcı ramdiskini dahil etmeyi destekleyen önyükleme görüntüsü üstbilgisi sürüm 4'ü kullanabilir. Birden çok satıcı ramdisk parçası, satıcı ramdisk bölümünde birbiri ardına birleştirilir. Satıcı ramdisk bölümünün düzenini ve her satıcı ramdisk parçasının meta verilerini açıklamak için bir satıcı ramdisk tablosu kullanılır.

bölme yapısı

Satıcı önyükleme bölümü, sanal A/B ile A/B'dir ve Android Verified Boot tarafından korunur.

Sürüm 3

Bölüm, bir başlık, satıcı ramdiski ve aygıt ağacı bloğundan (DTB) oluşur.

Bölüm Sayfa sayısı
Satıcı önyükleme başlığı (n sayfa) n = (2112 + page_size - 1) / page_size
Satıcı ramdiski (o sayfalar) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (s sayfa) p = (dtb_size + page_size - 1) / page_size

Sürüm 4

Bölüm, bir başlıktan, satıcı ramdisk bölümünden (birleştirilmiş tüm satıcı ramdisk parçalarından oluşur), aygıt ağacı blobundan (DTB) ve satıcı ramdisk tablosundan oluşur.

Bölüm Sayfa sayısı
Satıcı önyükleme başlığı (n sayfa) n = (2128 + page_size - 1) / page_size
Satıcı ramdisk parçaları (o sayfalar) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (s sayfa) p = (dtb_size + page_size - 1) / page_size
Satıcı ramdisk tablosu (q sayfa) q = (vendor_ramdisk_table_size + page_size - 1) / page_size
Bootconfig (r sayfaları) r = (bootconfig_size + page_size - 1) / page_size

Satıcı önyükleme başlığı

Satıcı önyükleme bölümü başlığının içeriği, öncelikle, önyükleme görüntüsü başlığından oraya taşınan verilerden oluşur. Ayrıca satıcı ramdiski hakkında bilgi içerir.

Sürüm 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 */

};

Sürüm 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 , tüm satıcı ramdisk parçalarının toplam boyutudur.
  • ramdisk_type , ramdisk türünü belirtir, olası değerler şunlardır:
    • VENDOR_RAMDISK_TYPE_NONE , değerin belirtilmediğini gösterir.
    • VENDOR_RAMDISK_TYPE_PLATFORM ramdiskleri, platforma özel bitler içerir. Önyükleyici bunları her zaman belleğe yüklemelidir.
    • VENDOR_RAMDISK_TYPE_RECOVERY ramdiskleri kurtarma kaynakları içerir. Önyükleyici, kurtarma işlemine başlarken bunları belleğe yüklemelidir.
    • VENDOR_RAMDISK_TYPE_DLKM ramdiskleri, dinamik yüklenebilir çekirdek modülleri içerir.
  • ramdisk_name , ramdisk'in benzersiz bir adıdır.
  • board_id , satıcı tanımlı donanım tanımlayıcılarının bir vektörüdür.

Önyükleyici desteği

Satıcı önyükleme bölümü, önyükleme bölümünde önceden var olan bilgileri (flash sayfa boyutu, çekirdek, ramdisk yükleme adresleri, DTB'nin kendisi gibi) içerdiğinden, önyüklemeyi tamamlamak için yeterli veriye sahip olmak için önyükleyicinin hem önyükleme hem de satıcı önyükleme bölümlerine erişmesi gerekir. .

Önyükleyici, satıcı ramdiskinden hemen sonra genel ramdisk'i belleğe yüklemelidir (CPIO, Gzip ve lz4 biçimleri bu tür birleştirmeyi destekler). Genel ramdisk görüntüsünü sayfa hizalamayın veya bellekteki satıcı ramdisk'inin sonu ile arasına başka bir boşluk koymayın. Çekirdek sıkıştırmayı açtıktan sonra, birleştirilmiş dosyayı initramfs içine ayıklar, bu da satıcı ramdisk dosya yapısı üzerine yerleştirilmiş genel bir ramdisk olan bir dosya yapısıyla sonuçlanır.

Genel ramdisk ve satıcı ramdiski birleştirildiğinden, aynı biçimde olmaları gerekir. GKI önyükleme görüntüsü, lz4 ile sıkıştırılmış genel bir ramdisk kullanır, bu nedenle GKI uyumlu bir cihaz, lz4 ile sıkıştırılmış bir satıcı ramdisk'i kullanmalıdır. Bunun için yapılandırma aşağıda gösterilmiştir.

Bootconfig'i desteklemek için önyükleyici gereksinimleri, Bootconfig'i Uygulama sayfasında açıklanmıştır.

Çoklu satıcı ramdiskleri (sürüm 4)

Önyükleme görüntüsü üstbilgisi sürüm 4 ile önyükleyici, önyükleme süresi sırasında initramfs olarak yüklemek için bir alt kümeyi veya satıcı ramdisklerinin tümünü seçebilir. Satıcı ramdisk tablosu, her bir ramdisk'in meta verilerini içerir ve hangi ramdisklerin yükleneceğine karar vermede önyükleyiciye yardımcı olabilir. Önyükleyici, jenerik ramdisk en son yüklendiği sürece, seçilen satıcı ramdisklerini yükleme sırasına karar verebilir.

Örneğin, önyükleyici kaynakları korumak için normal önyükleme sırasında VENDOR_RAMDISK_TYPE_RECOVERY satıcı ramdisklerini yüklemeyi atlayabilir, bu nedenle yalnızca VENDOR_RAMDISK_TYPE_PLATFORM ve VENDOR_RAMDISK_TYPE_DLKM türündeki satıcı ramdiskleri belleğe yüklenir. Öte yandan, VENDOR_RAMDISK_TYPE_PLATFORM , VENDOR_RAMDISK_TYPE_RECOVERY ve VENDOR_RAMDISK_TYPE_DLKM türündeki satıcı ramdiskleri, kurtarma modunda önyükleme yapılırken belleğe yüklenir.

Alternatif olarak, önyükleyici satıcı ramdisk tablosunu yok sayabilir ve tüm satıcı ramdisk bölümünü yükleyebilir. Bu, bütün satıcı ramdisk parçalarının vendor_boot bölümüne yüklenmesiyle aynı etkiye sahiptir.

Destek oluştur

Bir aygıt için satıcı önyükleme desteğini uygulamak için:

  • BOARD_BOOT_HEADER_VERSION 3 veya daha fazla olarak ayarlayın.

  • Cihazınız BOARD_RAMDISK_USE_LZ4 uyumluysa veya lz4 sıkıştırılmış genel bir ramdisk kullanıyorsa, BOARD_RAMDISK_USE_LZ4'ü true olarak ayarlayın.

  • Satıcı ramdiskinde olması gereken çekirdek modüllerini göz önünde bulundurarak, BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE öğesini cihazınız için uygun bir boyuta ayarlayın.

  • AB_OTA_PARTITIONS , vendor_boot ve satıcıya özel OTA bölümleri listelerini içerecek şekilde güncelleyin.

  • Aygıtınızın fstab boot bölümüne değil, vendor_boot bölümündeki /first_stage_ramdisk kopyalayın. Örneğin, $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM) .

vendor_boot birden çok satıcı ramdiskini dahil etmek için:

  • BOARD_BOOT_HEADER_VERSION 4 olarak ayarlayın.
  • BOARD_VENDOR_RAMDISK_FRAGMENTS , vendor_boot dahil edilecek mantıksal satıcı ramdisk parça adlarının bir listesine ayarlayın.

  • Önceden oluşturulmuş bir satıcı ramdiski eklemek için BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT önceden oluşturulmuş dosya yoluna ayarlayın.

  • Bir DLKM satıcı ramdiski eklemek için BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS dahil edilecek çekirdek modülü dizinleri listesine ayarlayın.

  • BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS mkbootimg argümanlarına ayarlayın. Bunlar, satıcı ramdisk parçası için --board_id[0-15] ve --ramdisk_type bağımsız değişkenleridir. DLKM satıcı ramdiski için, aksi belirtilmedikçe varsayılan --ramdisk_type DLKM .

vendor_boot içinde kurtarma kaynaklarını bağımsız bir recovery ramdiski olarak oluşturmak için:

  • BOARD_BOOT_HEADER_VERSION 4 olarak ayarlayın.
  • BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT öğesini true olarak ayarlayın.
  • BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT öğesini true olarak ayarlayın.
  • Bu, ramdisk_name recovery ve ramdisk_type VENDOR_RAMDISK_TYPE_RECOVERY olan bir satıcı ramdisk parçası ekler. Ardından ramdisk, $(TARGET_RECOVERY_ROOT_OUT) altında yüklenen dosyalar olan tüm kurtarma dosyalarını içerir.

mkbootimg argümanları

Argüman Tanım
--ramdisk_type Ramdisk tipi, NONE , PLATFORM , RECOVERY veya DLKM biri olabilir.
--board_id[0-15] board_id vektörünü belirtin, varsayılan olarak 0 .

Aşağıda örnek bir yapılandırma verilmiştir:

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

Ortaya çıkan vendor_boot , iki satıcı ramdisk parçası içerecektir. İlki, baz dizin tabanını ve dosyaların geri kalanını $(TARGET_VENDOR_RAMDISK_OUT) içindeki "varsayılan" ramdisk'tir. İkincisi, foo ve bar DLKM dizinlerini içeren dlkm_foobar ramdisk'tir ve --ramdisk_type varsayılanı DLKM .