Bu sayfada, cihaz ağacı yerleşimi (DTO) uygulamanızda yapabileceğiniz optimizasyonlar, kök düğümün yerleştirilmesine yönelik kısıtlamalar ve DTBO görüntüsünde sıkıştırılmış yerleşimlerin nasıl yapılandırılacağı açıklanmaktadır. Ayrıca örnek uygulama talimatları ve kodu da sağlar.
Çekirdek komut satırı
Cihaz ağacındaki (DT) orijinal çekirdek komut satırı, chosen/bootargs düğümünde bulunur. Önyükleyici, bu konumu çekirdek komut satırının diğer kaynaklarıyla birleştirmelidir:
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; };
DTO, ana DT ve yer paylaşımı DT'sindeki değerleri birleştiremez. Bu nedenle, ana DT'nin çekirdek komut satırını chosen/bootargs, yer paylaşımı DT'sinin çekirdek komut satırını ise chosen/bootargs_ext içine yerleştirmeniz gerekir. Önyükleyici daha sonra bu konumları birleştirip sonucu çekirdeğe iletebilir.
| main.dts | overlay.dts |
|---|---|
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; }; |
/dts-v1/;
/plugin/;
&chosen {
bootargs_ext = "...";
}; |
libufdt
En son libfdt sürümü DTO'yu desteklese de DTO'yu uygulamak için libufdt kullanılması önerilir (AOSP kaynağı: platform/system/libufdt). libufdt, düzleştirilmiş cihaz ağacından (FDT) gerçek bir ağaç yapısı (düzleştirilmemiş cihaz ağacı veya ufdt) oluşturur. Bu nedenle, iki .dtb dosyasının birleştirilmesini O(N2) yerine O(N) olacak şekilde iyileştirebilir. Burada N, ağaçtaki düğüm sayısıdır.
Performans testi
Google'ın dahili testinde, 2.405 libufdt .dtb ve 283 .dtbo DT düğümünde libufdt kullanıldığında derleme sonrası dosya boyutları 70.618 ve 8.566 bayt olmaktadır. FreeBSD'den taşınan bir DTO
uygulaması (124 ms çalışma zamanı) ile karşılaştırıldığında, libufdt
DTO çalışma zamanı 10 ms'dir.
Pixel cihazlarda libufdt ve libfdt ile karşılaştırılan performans testi. Temel düğüm sayısı efekti benzerdir ancak aşağıdaki farklılıkları içerir:
- 500 yerleştirme (ekleme veya geçersiz kılma) işlemi 6 ila 8 kat daha uzun sürüyor.
- 1.000 yerleştirme (ekleme veya geçersiz kılma) işlemi arasında 8-10 kat zaman farkı vardır.
Ekleme sayısı X olarak ayarlanmış örnek:

Şekil 1. Ekleme sayısı 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ı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
libufdt'daki ana API-DTO eşlemesi 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, .dtbo dosyasının içeriğini içeren arabellektir. Döndürülen değer, birleştirilmiş DT'yi (veya hata durumunda null) içeren yeni bir arabellektir. Birleştirilmiş DT, FDT biçimindedir ve çekirdeği başlatırken çekirdeğe iletilebilir.
Dönüş değerinden elde edilen yeni arabellek, dto_malloc() tarafından oluşturulur.
Bu işlevi, libufdt öğesini önyükleyiciye aktarırken uygulamanız gerekir.
Referans uygulamalar için sysdeps/libufdt_sysdeps_*.c başlıklı makaleyi inceleyin.
Kök düğüm kısıtlamaları
Yerleştirme işlemleri etiketlere dayandığından, ana DT'nin kök düğümüne yeni bir düğüm veya mülk yerleştiremezsiniz. Ana DT'nin bir etiket tanımlaması ve yer paylaşımı DT'sinin yer paylaşımı yapılacak düğümleri etiketlerle ataması gerektiğinden kök düğüme etiket veremezsiniz (bu nedenle kök düğüme yer paylaşımı yapamazsınız).
SoC tedarikçileri, ana DT'nin katman oluşturma özelliğini tanımlamalıdır. ODM/OEM'ler yalnızca SoC tedarikçisi tarafından tanımlanan etiketlere sahip düğümleri ekleyebilir veya bu düğümleri geçersiz kılabilir. Geçici çözüm olarak, temel DT'deki kök düğümün altında bir odm düğümü tanımlayabilirsiniz. Bu sayede, yer paylaşımı DT'sindeki tüm ODM düğümleri yeni düğümler ekleyebilir.
Alternatif olarak, SoC ile ilgili tüm düğümleri temel DT'deki kök düğümün altına aşağıdaki gibi bir soc düğümü olarak 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ış yer paylaşımlarını kullanma
Android 9, DT tablosu başlığının 1. sürümü kullanılırken DTBO görüntüsünde sıkıştırılmış yerleşimlerin kullanımına destek ekler. DTBO başlığı v1 kullanılırken dt_table_entry içindeki flags alanının en az önemli 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' are 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, VtsFirmwareDtboVerification testine sıkıştırılmış yer paylaşımlarını test etme desteği ekleyerek yer paylaşımı uygulamasının doğruluğunu doğrulamanıza yardımcı olur.
Örnek DTO uygulaması
Aşağıdaki talimatlarda, libufdt ile DTO'nun örnek bir uygulaması adım adım açıklanmaktadır (örnek kod aşağıda verilmiştir).
Örnek DTO talimatları
- Kitaplıkları dahil edin.
libufdtkullanmak için veri yapıları ve API'ler içinlibfdtekleyin:#include <libfdt.h> #include <ufdt_overlay.h>
- Ana 3B'yi ve yer paylaşımı 3B'yi yükleyin. Depolama alanından belleğe
.dtbve.dtboyükleyin (uygulanacak adımlar tasarımınıza bağlıdır). Bu noktada,.dtb/.dtboarabelleği ve boyutu olmalıdır:main_size = my_load_main_dtb(main_buf, main_buf_size)
overlay_size = my_load_overlay_dtb(overlay_buf, overlay_buf_size);
- DT'leri yerleştirin:
- Ana DT için FDT üstbilgisini almak üzere
ufdt_install_blob()kullanın:main_fdt_header = ufdt_install_blob(main_buf, main_size); main_fdt_size = main_size;
- FDT biçiminde birleştirilmiş DT almak için DTO'yu
ufdt_apply_overlay()arayın:merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size, overlay_buf, overlay_size); dtc_totalsize()boyutunu almak içinmerged_fdtkullanın:merged_fdt_size = dtc_totalsize(merged_fdt);
- Birleştirilmiş DT'yi çekirdeği başlatmak için iletin:
my_kernel_entry(0, machine_type, merged_fdt);
- Ana DT için FDT üstbilgisini almak üzere
Ö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); }