Bu sayfada, cihaz ağacı yer paylaşımı (DTO) uygulamanızda yapabileceğiniz optimizasyonlar ele alınmakta, kök düğümün yer paylaşımına yönelik kısıtlamalar açıklanmakta ve DTBO resminde sıkıştırılmış yer paylaşımlarının nasıl yapılandırılacağı ayrıntılı olarak açıklanmaktadır. Ayrıca örnek uygulama talimatları ve kod da sağlanır.
Çekirdek komut satırı
Cihaz ağacındaki (DT) orijinal çekirdek komut satırı, chosen/bootargs
düğümünde yer alır. Önyükleyici bu konumu, çekirdek komut satırı kaynaklarının diğerleriyle birleştirmelidir:
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; };
DTO, ana DT ve yer paylaşımlı DT'deki değerleri birleştiremez. Bu nedenle, ana DT'nin çekirdek komut satırını chosen/bootargs
, yer paylaşımlı DT'nin çekirdek komut satırını ise chosen/bootargs_ext
içine koymanız gerekir. Ardından önyükleme programı 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 yeni libfdt
, DTO'yu desteklese de DTO'yu (platform/system/libufdt
adresindeki AOSP kaynağı) uygulamak için libufdt
kullanılması önerilir. 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. Böylece, iki .dtb
düğümünün N(N2) numarasından O(N) numaraya doğru bir şekilde birleştirilmesini iyileştirebilir.
Performans testi
Google'ın dahili testine göre, 2405 .dtb
ve 283 .dtbo
DT düğümlerinde libufdt
kullanıldığında, derleme sonrasında dosya boyutları 70.618 ve 8.566 bayttır. FreeBSD'ten (124 ms çalışma süresi) ported bir DTO uygulamasına kıyasla libufdt
DTO çalışma süresi 10 ms'dir.
libufdt
ve libfdt
ile karşılaştırıldığında Pixel cihazlar için performans testi. Temel düğüm sayısı etkisi benzer olsa da aşağıdaki farklılıkları içerir:
- 500 yer paylaşımı (ekleme veya geçersiz kılma) işleminin süresi 6 ila 8 kat daha uzundur
- 1.000 yer paylaşımı (ekleme veya geçersiz kılma) işleminin süresi 8 ila 10 kat daha uzundur
Ekleme sayısının X olarak ayarlandığı örnek:
Şekil 1. Ekleme sayısı X.
Geçersiz kılma sayısının X olarak ayarlandığı ö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'sı
libufdt
bölgesinde DTO'ya gönderilen 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 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ştirilen DT, FDT biçimindedir. Bu dosyayı, çekirdeği başlatırken çekirdeğe iletebilirsiniz.
Döndürülen değerdeki yeni arabellek, libufdt
'u önyükleyiciye taşırken uygulamanız gereken dto_malloc()
tarafından oluşturulur.
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 bağlı olduğundan 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ı gerektiğinden ve bindirme DT'si etiketlerle yerleştirilecek düğümleri atadığından kök düğüm için etiket veremezsiniz (dolayısıyla kök düğümün üzerine yerleştiremezsiniz).
SoC tedarikçileri, ana DT'nin yer paylaşımı özelliğini tanımlamalıdır. ODM/OEM'ler yalnızca SoC tedarikçisi 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ımlayabilirsiniz. Bu sayede, yer paylaşımı DT'sindeki tüm ODM düğümleri yeni düğümler ekleyebilir.
Alternatif olarak, temel DT'deki SoC ile ilgili tüm düğümleri aşağıda açıklandığı gibi kök düğümün altındaki bir soc
düğümüne de yerleştirebilirsiniz:
main.dts | yer paylaşımlı.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ı kullanın
Android 9, DT tablo başlığının 1. sürümünü kullanırken DTBO resminde sıkıştırılmış yer paylaşımları kullanma desteği ekler. DTBO başlığı v1 kullanıldığında, dt_table_entry içindeki flags alanının en az anlamlı dört biti DT girişinin sıkıştırma biçimini 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' 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, yer paylaşımı uygulamasının doğruluğunu doğrulamanıza yardımcı olmak için VtsFirmwareDtboVerification
testine sıkıştırılmış yer paylaşımlarını test etme desteği ekler.
Örnek DTO uygulaması
Aşağıdaki talimatlarda, libufdt
ile DTO'nun örnek uygulamasında size yol gösterilmektedir (aşağıdaki örnek kod).
Örnek DTO talimatları
- Kitaplıkları dahil et.
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şımlı DT'yi yükleyin.
.dtb
ve.dtbo
'ı depolama alanından belleğe yükleyin (uygulanacak adımlar tasarımınıza bağlıdır). Bu noktada,.dtb
/.dtbo
arabellek 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);
- DT'leri yer paylaşımı olarak ekleme:
- Ana DT için FDT üst bilgisini 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ş bir DT almak için
ufdt_apply_overlay()
'ü DTO'ya çağırın:merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size, overlay_buf, overlay_size);
dtc_totalsize()
boyutunu almak içinmerged_fdt
kullanın:merged_fdt_size = dtc_totalsize(merged_fdt);
- Çekirdeği başlatmak için birleştirilmiş DT'yi iletin:
my_kernel_entry(0, machine_type, merged_fdt);
- Ana DT için FDT üst bilgisini 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); }