Tedarikçi firma önyükleme bölümleri

Android 11, Genel Çekirdek Görüntüsü (GKI) kavramını tanıttı. GKI ile rastgele bir cihazın başlatılmasını sağlamak için Android 11 cihazlar, önyükleme görüntüsü başlığı sürüm 3'ü kullanabilir. 3. sürümde, tedarikçiye özgü tüm bilgiler boot bölümünden çıkarılıp 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, GKI ile testi geçmek için vendor_boot bölümünü ve güncellenmiş boot bölüm biçimini desteklemelidir.

Android 12 cihazlar, vendor_boot bölümüne birden fazla tedarikçi ramdiski eklemeyi destekleyen önyükleme görüntüsü başlığı sürüm 4'ü kullanabilir. Birden fazla tedarikçi ramdisk parçası, tedarikçi ramdisk bölümünde art arda birleştirilir. Tedarikçi ramdisk tablosu, tedarikçi ramdisk bölümünün düzenini ve her tedarikçi ramdisk parçasının meta verilerini açıklamak için kullanılır.

Bölüm yapısı

Tedarikçi başlatma bölümü, sanal A/B ile A/B'ye ayrılır ve Android Doğrulanmış Başlatma ile korunur.

Sürüm 3

Bölüm; üstbilgi, tedarikçi ramdiski ve cihaz ağacı blob'undan (DTB) oluşur.

Bölüm Sayfa sayısı
Tedarikçi başlatma üstbilgisi (n sayfa) n = (2112 + page_size - 1) / page_size
Tedarikçi ramdiski (o sayfa) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB (p sayfaları) p = (dtb_size + page_size - 1) / page_size

Sürüm 4

Bölüm; başlık, tedarikçi ramdisk bölümü (birleştirilmiş tüm tedarikçi ramdisk parçalarından oluşur), cihaz ağacı blob'u (DTB) ve tedarikçi ramdisk tablosundan oluşur.

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

Tedarikçi başlatma üstbilgisi

Tedarikçi önyükleme bölümü üstbilgisinin içeriği, temel olarak önyükleme görüntüsü üstbilgisinden buraya taşınan verilerden oluşur. Ayrıca, tedarikçi ramdiski hakkında bilgiler de 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'in türünü gösterir. Olası değerler şunlardır:
    • VENDOR_RAMDISK_TYPE_NONE, değerin belirtilmediğini gösterir.
    • VENDOR_RAMDISK_TYPE_PLATFORM ramdisk'ler platforma özgü bitler içerir. Bootloader, bunları her zaman belleğe yüklemelidir.
    • VENDOR_RAMDISK_TYPE_RECOVERY ramdiskler kurtarma kaynakları içerir. Kurtarma moduna önyükleme yapılırken önyükleyici bunları belleğe yüklemelidir.
    • VENDOR_RAMDISK_TYPE_DLKM ramdisk'ler, dinamik olarak yüklenebilir çekirdek modülleri içeriyor.
  • ramdisk_name, ramdisk'in benzersiz adıdır.
  • board_id, tedarikçi tarafından tanımlanan donanım tanımlayıcılarının bir vektörüdür.

Bootloader desteği

Tedarikçi önyükleme bölümü, daha önce önyükleme bölümünde bulunan bilgileri (ör. flash sayfa boyutu, çekirdek, ramdisk yükleme adresleri, DTB'nin kendisi) içerdiğinden önyükleyicinin önyüklemeyi tamamlamak için yeterli veriye sahip olması için hem önyükleme hem de tedarikçi önyükleme bölümlerine erişmesi gerekir.

Bootloader, satıcı ramdisk'ini (CPIO, Gzip ve lz4 biçimleri bu tür bir birleştirmeyi destekler) takiben hemen genel ramdisk'i belleğe yüklemelidir. Genel ramdisk görüntüsünü sayfa hizalamayın veya bellek içinde satıcı ramdiski ile sonu arasında başka bir alan oluşturmayın. Çekirdek sıkıştırması açıldıktan sonra birleştirilmiş dosyayı initramfs içine çıkarır. Bu işlem, satıcı ramdisk dosya yapısı üzerine yerleştirilmiş genel bir ramdisk olan bir dosya yapısıyla sonuçlanır.

Genel ramdisk ve tedarikçi ramdisk birleştirildiğinden aynı biçimde olmalıdır. GKI önyükleme görüntüsü, lz4 ile sıkıştırılmış genel bir ramdisk kullandığından GKI uyumlu bir cihazın lz4 ile sıkıştırılmış bir satıcı ramdiski kullanması gerekir. Bununla ilgili yapılandırma aşağıda gösterilmiştir.

Bootconfig'i desteklemek için bootloader gereksinimleri Bootconfig'i Uygulama bölümünde açıklanmıştır.

Birden fazla satıcı ramdiski (sürüm 4)

Önyükleme görüntüsü başlık sürümü 4 ile önyükleyici, önyükleme sırasında initramfs olarak yüklenecek satıcı ramdisk'lerinin bir alt kümesini veya tamamını seçebilir. Tedarikçi ramdisk tablosu, her ramdiskin meta verilerini içerir ve önyükleyicinin hangi ramdisklerin yükleneceğine karar vermesine yardımcı olabilir. Önyükleyici, genel ramdisk en son yüklendiği sürece seçilen tedarikçi ramdisklerinin yüklenme sırasına karar verebilir.

Örneğin, bootloader, kaynakları korumak için normal başlatma sırasında VENDOR_RAMDISK_TYPE_RECOVERY türündeki satıcı ramdisklerinin yüklenmesini atlayabilir. Bu durumda, yalnızca VENDOR_RAMDISK_TYPE_PLATFORM ve VENDOR_RAMDISK_TYPE_DLKM türündeki satıcı ramdiskleri belleğe yüklenir. Diğer yandan, VENDOR_RAMDISK_TYPE_PLATFORM, VENDOR_RAMDISK_TYPE_RECOVERY ve VENDOR_RAMDISK_TYPE_DLKM türündeki satıcı ramdiskleri, kurtarma modunda başlatılırken belleğe yüklenir.

Alternatif olarak, bootloader, satıcı ramdisk tablosunu yok sayabilir ve satıcı ramdisk bölümünün tamamını yükleyebilir. Bu, vendor_boot bölümündeki tüm satıcı ramdisk parçalarını yüklemekle aynı etkiye sahiptir.

Destek oluşturma

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

  • BOARD_BOOT_HEADER_VERSION değerini 3 veya daha yüksek bir değere ayarlayın.

  • Cihazınız GKI uyumluysa veya başka bir şekilde lz4 sıkıştırılmış genel bir ramdisk kullanıyorsa BOARD_RAMDISK_USE_LZ4 değerini true olarak ayarlayın.

  • BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE değerini, satıcı ramdisk'ine gitmesi gereken çekirdek modüllerini göz önünde bulundurarak cihazınız için uygun bir boyuta ayarlayın.

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

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

vendor_boot'ya birden fazla tedarikçi ramdiski eklemek için:

  • BOARD_BOOT_HEADER_VERSION değerini 4 olarak ayarlayın.
  • BOARD_VENDOR_RAMDISK_FRAGMENTS, vendor_boot'ye dahil edilecek mantıksal tedarikçi ramdisk parça adlarının listesi olarak ayarlayın.

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

  • DLKM tedarikçisi ramdiski eklemek için BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS değerini eklenecek çekirdek modülü dizinleri listesi olarak ayarlayın.

  • BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGS öğesini mkbootimg bağımsız değişkenleri olarak ayarlayın. Bunlar, tedarikçi ramdisk parçası için --board_id[0-15] ve --ramdisk_type argümanlarıdır. DLKM satıcı ramdiski için varsayılan --ramdisk_type, aksi belirtilmediği sürece DLKM olur.

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

  • BOARD_BOOT_HEADER_VERSION değerini 4 olarak ayarlayın.
  • BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT değerini true olarak ayarlayın.
  • BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT değerini true olarak ayarlayın.
  • Bu, ramdisk_name değeri recovery ve ramdisk_type değeri VENDOR_RAMDISK_TYPE_RECOVERY olan bir satıcı ramdisk parçası ekler. Ramdisk daha sonra $(TARGET_RECOVERY_ROOT_OUT) altına yüklenen tüm kurtarma dosyalarını içerir.

mkbootimg bağımsız değişkenleri

Bağımsız değişken Açıklama
--ramdisk_type Ramdisk türü; NONE, PLATFORM, RECOVERY veya DLKM olabilir.
--board_id[0-15] board_id vektörünü belirtin. Varsayılan değer 0'dir.

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

Sonuçtaki vendor_boot iki tedarikçi ramdisk parçası içerir. Birincisi, DLKM dizinini baz ve $(TARGET_VENDOR_RAMDISK_OUT) içindeki diğer dosyaları içeren "varsayılan" ramdisk'tir. İkincisi ise DLKM dizinleri foo ve bar'yi içeren dlkm_foobar ramdisk'tir. --ramdisk_type varsayılan olarak DLKM'dir.