DTO'ları Optimize Etme

Koleksiyonlar ile düzeninizi koruyun İçeriği tercihlerinize göre kaydedin ve kategorilere ayırın.

Bu sayfada, DTO uygulamanızda yapabileceğiniz optimizasyonlar anlatılmakta, kök düğümün üst üste bindirilmesine karşı 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ı

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

/dts-v1/;

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

DTO , ana DT ve bindirme DT'sinden gelen değerleri birleştiremez, bu nedenle ana DT'nin çekirdek komut satırını chosen/bootargs ve bindirme DT'sinin çekirdek komut satırını 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 libfdt , DTO'yu desteklerken, libufdt uygulamak için libufdt kullanılması önerilir (AOSP kaynağı, platform/system/libufdt ). libufdt , düzleştirilmiş aygıt ağacından (FDT) gerçek bir ağaç yapısı (düzleştirilmemiş aygıt ağacı veya ufdt ) oluşturur, böylece iki .dtb dosyasının O(N 2 )'den O(N'ye) birleştirilmesini iyileştirebilir, burada N ağaçtaki düğüm sayısıdır.

Performans testi

Google'ın dahili testinde, 2405 libufdt ve 283 .dtbo DT düğümlerinde .dtb kullanılması, derlemeden sonra 70.618 ve 8.566 bayt dosya boyutlarıyla sonuçlanır. FreeBSD'den (124 ms çalışma zamanı) taşınan bir DTO uygulamasıyla karşılaştırıldığında, libufdt DTO çalışma zamanı 10 ms'dir.

Pixel cihazları için libufdt ve libfdt karşılaştıran performans testi. 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. Eklenen sayı X

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

Şekil 2. Geçersiz kılma sayısı X

libufdt , bazı libfdt API'leri ve veri yapıları ile geliştirilmiştir. libufdt kullanırken, libufdt dahil etmeli ve libfdt (ancak kodunuzda DTB veya DTBO'yu çalıştırmak için libfdt API'sini kullanabilirsiniz).

libufdt DTO API'si

libufdt ana API'si 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);

main_fdt_header parametresi ana DT'dir ve overlay_fdt , bir .dtbo dosyasının içeriğini içeren arabellektir. Dönüş değeri, birleştirilmiş DT'yi (veya hata durumunda null ) içeren yeni bir arabellektir. Birleştirilmiş DT, çekirdeği başlatırken çekirdeğe iletebileceğiniz FDT'de biçimlendirilir.

Dönüş değerinden yeni arabellek, libufdt önyükleyiciye taşırken uygulamanız gereken dto_malloc() tarafından oluşturulur. Başvuru uygulamaları için sysdeps/libufdt_sysdeps_*.c bakın.

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, temel DT'deki kök düğümün altında bir odm düğümü tanımlayarak, bindirmeli DT'deki tüm ODM düğümlerinin yeni düğümler eklemesini sağlayabilirsiniz. Alternatif olarak, temel DT'deki tüm SoC ile ilgili düğümleri, aşağıda açıklandığı gibi kök düğüm altındaki bir soc düğümüne yerleştirebilirsiniz:

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ığı v1 kullanılırken, dt_table_entry içindeki bayraklar alanının en önemsiz dört biti, DT girişinin sıkıştırma biçimini gösterir.

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 sıkıştırmaları desteklenmektedir.

enum dt_compression_info {
    NO_COMPRESSION,
    ZLIB_COMPRESSION,
    GZIP_COMPRESSION
};

Android 9, kaplama uygulamasının doğruluğunu doğrulamanıza yardımcı olmak için VtsFirmwareDtboVerification testine sıkıştırılmış kaplamaları test etme desteği ekler.

Örnek DTO uygulaması

Aşağıdaki talimatlar, libufdt ile örnek bir DTO uygulamasında size yol gösterir (aşağıdaki örnek kod).

Örnek DTO talimatları

  1. Kitaplıkları dahil et. libufdt kullanmak için veri yapıları ve API'ler için libfdt :
    #include <libfdt.h>
    #include <ufdt_overlay.h>
    
  2. Ana DT'yi yükleyin ve DT'yi yerleştirin. .dtb ve .dtbo depolamadan belleğe yükleyin (kesin adımlar tasarımınıza bağlıdır). Bu noktada, .dtb / .dtbo arabelleğine ve boyutuna sahip olmalısınız:
    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. Ana DT için FDT başlığını almak için ufdt_install_blob() kullanın:
      main_fdt_header = ufdt_install_blob(main_buf, main_size);
      main_fdt_size = main_size;
      
    2. FDT biçiminde birleştirilmiş bir DT almak için ufdt_apply_overlay() 'i DTO'ya çağırın:
      merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size,
                                      overlay_buf, overlay_size);
      
    3. dtc_totalsize() boyutunu elde etmek için merged_fdt kullanın:
      merged_fdt_size = dtc_totalsize(merged_fdt);
      
    4. Çekirdeği başlatmak için birleştirilmiş DT'yi iletin:
      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);
}