DTO'ları Optimize Etme

Bu sayfada, DTO uygulamanızda yapabileceğiniz optimizasyonlar anlatılmakta, kök düğümün üst üste bindirilmesine yönelik kısıtlamalar açıklanmakta ve DTBO görüntüsünde sıkıştırılmış kaplamaların nasıl yapılandırılacağı ayrıntılı olarak açıklanmaktadır. Ayrıca örnek uygulama talimatları ve kodu sağlar.

Çekirdek komut satırı

Cihaz ağacında orijinal çekirdek komut satırı bulunur chosen/bootargs düğümü. Önyükleyici, bu konumu diğer çekirdek komut satırı kaynaklarıyla birleştirmelidir:

/dts-v1/;

/ {
  chosen: chosen {
    bootargs = "...";
  };
};

DTO yapamazmısın ana DT çekirdek komut satırı koymak gerekir, böylece ana DT'nin gelen ve DT'nin bindirme concatenate değerler chosen/bootargs ve bindirme DT'nin çekirdek komut satırı chosen/bootargs_ext . Bootloader daha sonra bu konumları birleştirebilir ve sonucu çekirdeğe iletebilir.

main.dts overlay.dts
/dts-v1/;

/ {
  chosen: chosen {
    bootargs = "...";
  };
};
/dts-v1/;
/plugin/;

&chosen {
  bootargs_ext = "...";
};

libufdt

En son ise libfdt DTO destekler, kullanımı önerilir libufdt DTO (en AOSP kaynağını uygulamak için platform/system/libufdt ). libufdt iki birleştirme artırabilir böylece, düzleştirilmiş aygıt ağacından (FMD) gerçek bir ağaç yapısı (BM-düzleştirilmiş cihaz ağaç veya ufdt) oluşturur .dtb O (N), N, O (N2) dosyaları ağaçtaki düğüm sayısıdır.

Performans testi

Google'ın dahili testlerde, kullanan libufdt 2405 tarihinde .dtb ve 283 .dtbo derleme sonra 70.618 ve 8.566 bayt dosya boyutlarında DT'nin düğümleri sonuçları. Bir karşılaştırıldığında DTO uygulanması , (124 ms çalışma zamanı) FreeBSD taşıdık libufdt DTO çalışma zamanı 10 ms.

Piksel cihazlar için performans testleri karşılaştırıldı libufdt ve libfdt . Temel düğüm sayısı etkisi benzerdir, ancak aşağıdaki farklılıkları içerir:

  • 500 bindirme (ekleme veya geçersiz kılma) işlemi 6x ila 8x zaman farkına sahiptir
  • 1000 bindirme (ekleme veya geçersiz kılma) işlemi 8x ila 10x zaman farkına sahiptir

Sayının X olarak ayarlandığı ekleme örneği:

Şekil 1. Eklemeye sayısı, X

Geçersiz kılma sayısı X olarak ayarlanmış örnek:

Şekil 2. kılma sayısı, X

libufdt bazılarıyla geliştirilen libfdt API'leri ve veri yapıları. Kullanırken libufdt , sen içermelidir ve bağlantı libfdt (ancak, kodunuzda kullanabileceğiniz libfdt DTB veya DTBO işletmek API).

libufdt DTO API'si

İçinde DTO ana API libufdt aşağıdaki gibidir:

struct fdt_header *ufdt_apply_overlay(
        struct fdt_header *main_fdt_header,
        size_t main_fdt_size,
        void *overlay_fdt,
        size_t overlay_size);

Parametre main_fdt_header ana DT ve overlay_fdt bir içeriğini ihtiva eden bir tampondur .dtbo dosyası. Dönüş değeri yeni birleştirilmiş DT ihtiva eden tampon maddesi (ya da null bir hata durumunda). Birleştirilmiş DT, çekirdeği başlatırken çekirdeğe iletebileceğiniz FDT'de biçimlendirilir.

Dönüş değeri yeni tampon tarafından oluşturulan dto_malloc() taşıma yaparken uygulamaları gerektiğini de libufdt bootloader içine. Referans uygulamalar için, bakınız sysdeps/libufdt_sysdeps_*.c .

Kök düğüm kısıtlamaları

Bindirme işlemleri etiketlere dayandığından, ana DT'nin kök düğümüne yeni bir düğüm veya özellik yerleştiremezsiniz. Ana CE'nin bir etiket tanımlaması gerektiğinden ve bindirme CE, etiketlerle kaplanacak düğümleri atadığından, kök düğüm için bir etiket veremezsiniz (ve dolayısıyla kök düğümü kaplayamazsınız).

SoC satıcıları, ana DT'nin kaplama yeteneğini tanımlamalıdır; ODM/OEM'ler yalnızca SoC satıcısı tarafından tanımlanan etiketlere sahip düğümleri ekleyebilir veya geçersiz kılabilir. Geçici bir çözüm olarak, bir tanımlayabilirsiniz odm yeni düğüm eklemek için bindirme DT'de tüm ODM düğümleri sağlayan baz DT'de kök düğümü altında düğümü. Alternatif olarak, bir içine baz DT tüm SoC ilişkili düğümleri koymak soc aşağıda tarif edildiği gibi kök düğümün altında düğümün:

main.dts overlay.dts
/dts-v1/;

/ {
    compatible = "corp,bar";
    ...

    chosen: chosen {
        bootargs = "...";
    };

    /* nodes for all soc nodes */
    soc {
        ...
        soc_device@0: soc_device@0 {
            compatible = "corp,bar";
            ...
        };
        ...
    };

    odm: odm {
        /* reserved for overlay by odm */
    };
};
/dts-v1/;
/plugin/;

/ {
};

&chosen {
    bootargs_ex = "...";
};

&odm {
    odm_device@0 {
        ...
    };
    ...
};

Sıkıştırılmış bindirmeleri kullanma

Android 9, cihaz ağacı tablo başlığının 1. sürümünü kullanırken DTBO görüntüsünde sıkıştırılmış bindirmeleri kullanmak için destek ekler. DTBO başlık v1 kullanırken, dt_table_entry içinde bayraklar alanın dört adet en önemsiz biti DT girdisinin sıkıştırma formatını göstermektedir.

struct dt_table_entry_v1 {
  uint32_t dt_size;
  uint32_t dt_offset;  /* offset from head of dt_table_header */
  uint32_t id;         /* optional, must be zero if unused */
  uint32_t rev;        /* optional, must be zero if unused */
  uint32_t flags;      /* For version 1 of dt_table_header, the 4 least significant bits
                        of 'flags' will be used to indicate the compression
                        format of the DT entry as per the enum 'dt_compression_info' */
  uint32_t custom[3];  /* optional, must be zero if unused */
};

Şu anda, zlib ve gzip kompresyon desteklenmektedir.

enum dt_compression_info {
    NO_COMPRESSION,
    ZLIB_COMPRESSION,
    GZIP_COMPRESSION
};

Android 9'a sıkıştırılmış bindirmeleri test için destek ekler VtsFirmwareDtboVerification bindirme uygulamanın doğruluğunu kontrol yardımına testi.

Örnek DTO uygulaması

Aşağıdaki talimatlar ile DTO örnek bir uygulamaya size yol libufdt (örnek kod aşağıda).

Örnek DTO talimatları

  1. Kitaplıkları dahil et. Kullanım için libufdt içerir libfdt veri yapıları ve ilaç aktif maddeleri için:
    #include <libfdt.h>
    #include <ufdt_overlay.h>
    
  2. Ana DT'yi yükleyin ve DT'yi yerleştirin. Yük .dtb ve .dtbo belleğe depolama (tam adımlar tasarımına bağlıdır). Bu noktada, bir tampon ve büyüklüğe sahip olmalıdır .dtb / .dtbo :
    main_size = my_load_main_dtb(main_buf, main_buf_size)
    
    overlay_size = my_load_overlay_dtb(overlay_buf, overlay_buf_size);
    
  3. DT'leri kaplayın:
    1. Kullanın ufdt_install_blob() : Ana DT için FDT başlığını almak için
      main_fdt_header = ufdt_install_blob(main_buf, main_size);
      main_fdt_size = main_size;
      
    2. Çağrı ufdt_apply_overlay() bir FDT formatında DT birleşti almak için DTO için:
      merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size,
                                      overlay_buf, overlay_size);
      
    3. Kullanım merged_fdt boyutunu almak için dtc_totalsize() :
      merged_fdt_size = dtc_totalsize(merged_fdt);
      
    4. : Pass çekirdek başlatmak için DT birleşti
      my_kernel_entry(0, machine_type, merged_fdt);
      

Örnek DTO kodu

#include <libfdt.h>
#include <ufdt_overlay.h>

…

{
  struct fdt_header *main_fdt_header;
  struct fdt_header *merged_fdt;

  /* load main dtb into memory and get the size */
  main_size = my_load_main_dtb(main_buf, main_buf_size);

  /* load overlay dtb into memory and get the size */
  overlay_size = my_load_overlay_dtb(overlay_buf, overlay_buf_size);

  /* overlay */
  main_fdt_header = ufdt_install_blob(main_buf, main_size);
  main_fdt_size = main_size;
  merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size,
                                  overlay_buf, overlay_size);
  merged_fdt_size = dtc_totalsize(merged_fdt);

  /* pass to kernel */
  my_kernel_entry(0, machine_type, merged_fdt);
}