Halaman ini membahas pengoptimalan yang dapat Anda lakukan pada penerapan overlay pohon perangkat (DTO), menjelaskan batasan terhadap overlay node root, dan menjelaskan cara mengonfigurasi overlay yang dikompresi dalam image DTBO. Model Garden juga memberikan petunjuk dan kode implementasi contoh.
Command line kernel
Baris perintah kernel asli di pohon perangkat (DT) berada di
node chosen/bootargs
. Bootloader harus menggabungkan lokasi ini dengan sumber command line kernel lainnya:
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; };
DTO tidak dapat menggabungkan nilai dari DT utama dan DT overlay, jadi
Anda harus menempatkan command line kernel DT utama di
chosen/bootargs
dan command line kernel DT overlay di
chosen/bootargs_ext
. Bootloader kemudian dapat menggabungkan lokasi ini dan meneruskan hasilnya ke kernel.
main.dts | overlay.dts |
---|---|
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; }; |
/dts-v1/; /plugin/; &chosen { bootargs_ext = "..."; }; |
libufdt
Meskipun libfdt
terbaru
libfdt
mendukung DTO, apakah sebaiknya menggunakan libufdt
untuk menerapkan DTO
(sumber AOSP di
platform/system/libufdt
).
libufdt
membangun struktur hierarki yang sebenarnya (hierarki perangkat yang tidak diratakan,
atau ufdt) dari hierarki perangkat yang diratakan (FDT), sehingga dapat meningkatkan
penggabungan dua file .dtb
dari O(N2) menjadi O(N), dengan N adalah
jumlah node dalam hierarki.
Pengujian performa
Dalam pengujian internal Google, penggunaan libufdt
pada 2405
.dtb
dan 283 node DT .dtbo
menghasilkan ukuran file
70.618 dan 8.566 byte setelah kompilasi. Dibandingkan dengan penerapan
DTOyang di-port dari FreeBSD (runtime 124 md), runtime DTO libufdt
adalah 10 md.
Pengujian performa untuk perangkat Pixel dibandingkan dengan libufdt
dan
libfdt
. Jumlah efek node dasar serupa, tetapi mencakup
perbedaan berikut:
- 500 operasi overlay (tambahkan atau ganti) memiliki perbedaan waktu 6x hingga 8x
- 1.000 operasi overlay (tambahkan atau ganti) memiliki perbedaan waktu 8x hingga 10x
Contoh dengan jumlah penambahan yang ditetapkan ke X:
Gambar 1. Jumlah yang ditambahkan adalah X.
Contoh dengan jumlah penggantian yang ditetapkan ke X:
Gambar 2. Jumlah penggantian adalah X.
libufdt
dikembangkan dengan beberapa API dan struktur data libfdt
. 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 ke 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 ditampilkan adalah buffer baru yang berisi
DT yang digabungkan (atau null
jika terjadi error). DT yang digabungkan diformat
dalam FDT, yang dapat Anda teruskan ke kernel saat memulai kernel.
Buffer baru dari nilai yang ditampilkan dibuat oleh dto_malloc()
,
yang harus Anda terapkan saat mem-porting libufdt
ke bootloader.
Untuk penerapan referensi, lihat
sysdeps/libufdt_sysdeps_*.c
.
Batasan node root
Anda tidak dapat menempatkan node atau properti baru ke dalam node root DT utama karena operasi overlay mengandalkan label. Karena DT utama harus menentukan label dan DT overlay menetapkan node yang akan di-overlay dengan label, Anda tidak dapat memberikan label untuk node root (dan oleh karena itu tidak dapat meng-overlay node root).
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 node odm
di bawah
node root di DT dasar, sehingga semua node ODM di DT overlay dapat menambahkan node baru.
Atau, Anda dapat menempatkan semua node terkait SoC di DT dasar ke dalam node
soc
di bawah node root seperti yang dijelaskan di bawah:
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 { ... }; ... }; |
Menggunakan overlay terkompresi
Android 9 menambahkan dukungan untuk menggunakan overlay terkompresi dalam image DTBO saat menggunakan header tabel DT versi 1. Saat menggunakan header DTBO v1, empat bit paling tidak signifikan dari kolom 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' 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 */ };
Saat ini, kompresi zlib
dan gzip
didukung.
enum dt_compression_info { NO_COMPRESSION, ZLIB_COMPRESSION, GZIP_COMPRESSION };
Android 9 menambahkan dukungan untuk menguji overlay terkompresi pada pengujian VtsFirmwareDtboVerification
untuk membantu Anda memverifikasi kebenaran aplikasi overlay.
Contoh penerapan DTO
Petunjuk berikut akan memandu Anda melalui contoh implementasi DTO
dengan libufdt
(kode contoh di bawah).
Contoh petunjuk DTO
- Sertakan library. 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 dalam memori (langkah yang tepat bergantung pada desain Anda). Pada tahap ini, Anda akan 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);
- Overlay 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);
- Teruskan 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); }