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
, 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, ağaçtaki düğüm sayısı N olmak üzere iki .dtb
dosyasının birleştirilmesini O(N2) yerine O(N) olacak şekilde iyileştirebilir.
Performans testi
Google'ın dahili testinde, 2405 libufdt
.dtb
ve 283 .dtbo
DT düğümünde libufdt
kullanıldığında derleme sonrası dosya boyutları 70.618 ve 8.566 bayt olur. 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ı etkisi benzerdir ancak aşağıdaki farklılıkları içerir:
- 500 yerleştirme (ekleme veya geçersiz kılma) işleminde 6-8 kat zaman farkı vardır.
- 1.000 yerleştirme (ekleme veya geçersiz kılma) işlemi, 8 ila 10 kat zaman farkına sahiptir.
Ekleme sayısı X olarak ayarlanmış örnek:
1. şekil. 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'den DTO'ya şöyledir:
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. Bu biçimi, çekirdeği başlatırken çekirdeğe iletebilirsiniz.
Dönüş değerinden elde edilen yeni arabellek, dto_malloc()
tarafından oluşturulur.
libufdt
öğesini önyükleyiciye aktarırken bu arabelleği uygulamanız gerekir.
Referans uygulamalar için sysdeps/libufdt_sysdeps_*.c
başlıklı makaleyi inceleyin.
Kök düğüm kısıtlamaları
Yer paylaşımı işlemleri etiketlere dayandığından, ana DT'nin kök düğümüne yeni bir düğüm veya mülk yer paylaşımı yapamazsınız. 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 yerleştirme ö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 da 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ılması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.
libufdt
kullanmak için veri yapıları ve API'ler içinlibfdt
ekleyin:#include <libfdt.h> #include <ufdt_overlay.h>
- Ana DT'yi ve yer paylaşımı DT'yi yükleyin. Depolama alanından belleğe
.dtb
ve.dtbo
yükleyin (uygulanacak adımlar tasarımınıza bağlıdır). Bu noktada,.dtb
/.dtbo
arabelleğ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()
numaralı telefondan arayın:merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size, overlay_buf, overlay_size);
merged_fdt
kullanarakdtc_totalsize()
boyutunu alı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); }