Halaman ini membahas pengoptimalan yang dapat Anda lakukan pada implementasi DTO Anda, menjelaskan batasan terhadap overlay node akar, dan merinci cara mengonfigurasi overlay terkompresi pada gambar DTBO. Ini juga memberikan contoh instruksi implementasi dan kode.
Baris perintah kernel
Baris perintah kernel asli di pohon perangkat terletak di node chosen/bootargs
. Bootloader harus menggabungkan lokasi ini dengan sumber baris perintah kernel lainnya:
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; };
DTO tidak dapat menggabungkan nilai-nilai dari DT utama dan DT overlay, jadi Anda harus meletakkan baris perintah kernel dari DT utama di dalam chosen/bootargs
dan baris perintah kernel dari DT overlay di dalam chosen/bootargs_ext
. Bootloader kemudian dapat menggabungkan lokasi-lokasi ini dan meneruskan hasilnya ke kernel.
utama.dts | overlay.dts |
---|---|
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; }; | /dts-v1/; /plugin/; &chosen { bootargs_ext = "..."; }; |
libudt
Meskipun libfdt
terbaru mendukung DTO, apakah disarankan menggunakan libufdt
untuk mengimplementasikan DTO (sumber AOSP di platform/system/libufdt
). libufdt
membangun struktur pohon nyata (pohon perangkat yang tidak diratakan, atau ufdt ) dari pohon perangkat yang diratakan (FDT), sehingga dapat meningkatkan penggabungan dua file .dtb
dari O(N 2 ) ke O(N), di mana N adalah jumlah node di pohon.
Pengujian kinerja
Dalam pengujian internal Google, penggunaan libufdt
pada 2405 .dtb
dan 283 .dtbo
node DT menghasilkan ukuran file 70.618 dan 8.566 byte setelah kompilasi. Dibandingkan dengan implementasi DTO yang di-porting dari FreeBSD (runtime 124 ms), runtime libufdt
DTO adalah 10 ms.
Pengujian performa untuk perangkat Pixel membandingkan libufdt
dan libfdt
. Efek jumlah node dasar serupa, tetapi mencakup perbedaan berikut:
- 500 operasi overlay (tambahkan atau timpa) memiliki perbedaan waktu 6x hingga 8x
- 1000 operasi overlay (tambahkan atau timpa) memiliki perbedaan waktu 8x hingga 10x
Contoh dengan penambahan hitungan yang disetel ke X:
Contoh dengan jumlah penggantian yang disetel ke X:
libufdt
dikembangkan dengan beberapa API libfdt
dan struktur data. Saat menggunakan libufdt
, Anda harus menyertakan dan menautkan libfdt
(namun, dalam kode Anda, Anda dapat menggunakan libfdt
API untuk mengoperasikan DTB atau DTBO).
libufdt DTO API
API utama untuk DTO di libufdt
adalah sebagai berikut:
struct fdt_header *ufdt_apply_overlay( struct fdt_header *main_fdt_header, size_t main_fdt_size, void *overlay_fdt, size_t overlay_size);
Parameter main_fdt_header
adalah DT utama dan overlay_fdt
adalah buffer yang berisi konten file .dtbo
. Nilai yang dikembalikan adalah buffer baru yang berisi DT gabungan (atau null
jika terjadi kesalahan). DT yang digabungkan diformat dalam FDT, yang dapat Anda teruskan ke kernel saat memulai kernel.
Buffer baru dari nilai kembalian dibuat oleh dto_malloc()
, yang harus Anda terapkan saat mem-porting libufdt
ke bootloader. Untuk implementasi referensi, lihat sysdeps/libufdt_sysdeps_*.c
.
Pembatasan simpul akar
Anda tidak dapat melapisi node atau properti baru ke dalam node akar DT utama karena operasi overlay bergantung pada label. Karena DT utama harus mendefinisikan sebuah label dan DT overlay menugaskan node-node yang akan di-overlay dengan label, Anda tidak dapat memberikan label untuk node akar (dan karena itu tidak dapat melapisi node akar).
Vendor SoC harus menentukan kemampuan overlay DT utama; ODM/OEM hanya dapat menambahkan atau mengganti node dengan label yang ditentukan oleh vendor SoC. Sebagai solusinya, Anda dapat menentukan simpul odm
di bawah simpul akar di DT dasar, sehingga semua simpul ODM di DT overlay dapat menambahkan simpul baru. Alternatifnya, Anda dapat menempatkan semua node terkait SoC di DT dasar ke dalam node soc
di bawah node root seperti yang dijelaskan di bawah ini:
utama.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 { ... }; ... }; |
Menggunakan overlay terkompresi
Android 9 menambahkan dukungan untuk menggunakan overlay terkompresi pada gambar DTBO saat menggunakan header tabel pohon perangkat versi 1. Saat menggunakan header DTBO v1, empat bit paling tidak signifikan dari bidang flag di dt_table_entry menunjukkan format kompresi entri DT.
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 */ };
Saat ini, kompresi zlib
dan gzip
didukung.
enum dt_compression_info { NO_COMPRESSION, ZLIB_COMPRESSION, GZIP_COMPRESSION };
Android 9 menambahkan dukungan untuk pengujian overlay terkompresi ke pengujian VtsFirmwareDtboVerification
untuk membantu Anda memverifikasi kebenaran aplikasi overlay.
Contoh implementasi DTO
Petunjuk berikut memandu Anda melalui contoh implementasi DTO dengan libufdt
(contoh kode di bawah).
Contoh instruksi DTO
- Sertakan perpustakaan. Untuk menggunakan
libufdt
, sertakanlibfdt
untuk struktur data dan API:#include <libfdt.h> #include <ufdt_overlay.h>
- Muat DT utama dan DT overlay. Muat
.dtb
dan.dtbo
dari penyimpanan ke memori (langkah pastinya bergantung pada desain Anda). Pada titik ini, Anda seharusnya sudah memiliki buffer dan ukuran.dtb
/.dtbo
:main_size = my_load_main_dtb(main_buf, main_buf_size)
overlay_size = my_load_overlay_dtb(overlay_buf, overlay_buf_size);
- Hamparkan DT:
- Gunakan
ufdt_install_blob()
untuk mendapatkan header FDT untuk DT utama:main_fdt_header = ufdt_install_blob(main_buf, main_size); main_fdt_size = main_size;
- Panggil
ufdt_apply_overlay()
ke DTO untuk mendapatkan DT gabungan dalam format FDT:merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size, overlay_buf, overlay_size);
- Gunakan
merged_fdt
untuk mendapatkan ukurandtc_totalsize()
:merged_fdt_size = dtc_totalsize(merged_fdt);
- Berikan DT gabungan untuk memulai kernel:
my_kernel_entry(0, machine_type, merged_fdt);
- Gunakan
Contoh kode DTO
#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); }