Bu sayfada DTO uygulamanızda yapabileceğiniz optimizasyonlar anlatılır, kök düğümün yer paylaşımına karşı kısıtlamalar açıklanır ve DTBO görüntüsünde sıkıştırılmış yer paylaşımlarının nasıl yapılandırılacağı ayrıntılarıyla anlatılır. Ayrıca örnek uygulama talimatları ve kodu da sağlar.
Çekirdek komut satırı
Aygıt ağacındaki orijinal çekirdek komut satırı chosen/bootargs
düğümünde bulunur. Önyükleyicinin bu konumu diğer çekirdek komut satırı kaynaklarıyla birleştirmesi gerekir:
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; };
DTO, ana CE'den ve yer paylaşımlı CE'den gelen değerleri birleştiremez , bu nedenle ana CE'nin çekirdek komut satırını chosen/bootargs
ve yer paylaşımlı CE'nin çekirdek komut satırını chosen/bootargs_ext
içine koymalısınız. Bootloader daha sonra bu konumları birleştirebilir ve sonucu çekirdeğe aktarabilir.
ana.dts | kaplama.dts |
---|---|
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; }; | /dts-v1/; /plugin/; &chosen { bootargs_ext = "..."; }; |
özgürlük
En son libfdt
DTO'yu desteklerken, DTO'yu uygulamak için libufdt
kullanılması önerilir ( platform/system/libufdt
adresindeki AOSP kaynağı). 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 (burada N) birleştirilmesini iyileştirebilir. ağaçtaki düğümlerin sayısıdır.
Performans testi
Google'ın dahili testinde, 2405 .dtb
ve 283 .dtbo
DT düğümlerinde libufdt
kullanılması, derleme sonrasında 70.618 ve 8.566 baytlık dosya boyutlarıyla sonuçlanır. FreeBSD'den (124 ms çalışma süresi) taşınan bir DTO uygulamasıyla karşılaştırıldığında, libufdt
DTO çalışma süresi 10 ms'dir.
Pixel cihazları için performans testleri libufdt
ve libfdt
karşılaştırdı. Temel düğüm sayısı etkisi benzerdir ancak aşağıdaki farklılıkları içerir:
- 500 katmanlama (ekleme veya geçersiz kılma) işleminde 6 ila 8 kat zaman farkı vardır
- 1000 katmanlama (ekleme veya geçersiz kılma) işleminde 8 ila 10 kat zaman farkı vardır
Ekleme sayısının X olarak ayarlandığı örnek:
Geçersiz kılma sayısının X olarak ayarlandığı örnek:
libufdt
bazı libfdt
API'leri ve veri yapılarıyla geliştirilmiştir. libufdt
kullanırken, libfdt
eklemeniz ve bağlamanız gerekir (ancak kodunuzda DTB veya DTBO'yu çalıştırmak için libfdt
API'sini kullanabilirsiniz).
libufdt DTO API'si
libufdt
DTO'ya yönelik ana API 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 CE'dir ve overlay_fdt
bir .dtbo
dosyasının içeriğini içeren arabellektir. Dönüş değeri, birleştirilmiş CE'yi içeren yeni bir arabellektir (veya hata durumunda null
). Birleştirilmiş DT, çekirdeği başlatırken çekirdeğe iletebileceğiniz FDT'de biçimlendirilir.
Dönüş değerinden gelen yeni arabellek, libufdt
önyükleyiciye taşırken uygulamanız gereken dto_malloc()
tarafından oluşturulur. Referans uygulamaları için sysdeps/libufdt_sysdeps_*.c
dosyasına bakın.
Kök düğüm kısıtlamaları
Yer paylaşımı işlemleri etiketlere bağlı olduğundan, ana CE'nin kök düğümüne yeni bir düğümü veya özelliği yerleştiremezsiniz. Ana DT'nin bir etiket tanımlaması gerektiğinden ve kaplama DT'si, etiketlerle kaplanacak düğümlere 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 üst üste bindirme 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, kaplama 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:
ana.dts | kaplama.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ış kaplamaları kullanma
Android 9, cihaz ağacı tablosu başlığının 1. sürümünü kullanırken DTBO görüntüsünde sıkıştırılmış kaplamaların kullanılmasına yönelik destek ekler. DTBO başlığı v1 kullanıldığında, dt_table_entry'deki flags alanının en az anlamlı dört biti, DT girişinin sıkıştırma formatını belirtir.
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, katman uygulamasının doğruluğunu doğrulamanıza yardımcı olmak için VtsFirmwareDtboVerification
testine sıkıştırılmış katmanları test etme desteği ekler.
Örnek DTO uygulaması
Aşağıdaki talimatlar, libufdt
ile DTO'nun örnek uygulaması konusunda size yol gösterecektir (örnek kod aşağıdadır).
Örnek DTO talimatları
- Kitaplıkları dahil edin.
libufdt
kullanmak için veri yapıları ve API'ler içinlibfdt
ekleyin:#include <libfdt.h> #include <ufdt_overlay.h>
- Ana CE'yi ve bindirme CE'yi yükleyin.
.dtb
ve.dtbo
depolamadan belleğe yükleyin (tam adımlar tasarımınıza bağlıdır). Bu noktada.dtb
/.dtbo
tamponuna 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);
- CE'leri kaplayın:
- Ana DT'nin FDT başlığını almak için
ufdt_install_blob()
işlevini kullanın:main_fdt_header = ufdt_install_blob(main_buf, main_size); main_fdt_size = main_size;
- FDT formatında birleştirilmiş bir DT almak için DTO'ya
ufdt_apply_overlay()
işlevini çağırın:merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size, overlay_buf, overlay_size);
-
dtc_totalsize()
boyutunu elde etmek içinmerged_fdt
kullanın:merged_fdt_size = dtc_totalsize(merged_fdt);
- Çekirdeği başlatmak için birleştirilmiş CE'yi iletin:
my_kernel_entry(0, machine_type, merged_fdt);
- Ana DT'nin FDT başlığını almak için
Ö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); }