Halaman ini membahas pengoptimalan yang dapat Anda lakukan pada implementasi overlay hierarki perangkat (DTO), menjelaskan pembatasan terhadap {i>overlay<i} node {i>root<i}, dan merinci cara bagaimana melakukan konfigurasi overlay terkompresi pada gambar DTBO. Halaman ini juga menyediakan contoh kode dan petunjuk penerapan.
Command line kernel
Baris perintah kernel asli di pohon perangkat (DT) terletak di
Node chosen/bootargs
. Bootloader harus menyambungkan ini
dengan sumber command line kernel lain:
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; };
DTO tidak dapat menggabungkan nilai dari DT utama dan DT overlay, jadi
Anda harus meletakkan
baris perintah {i>kernel<i} DT utama di
chosen/bootargs
dan command line kernel DT overlay di
chosen/bootargs_ext
. {i>Bootloader<i} kemudian dapat menyambungkan ini
lokasi dan meneruskan
hasilnya ke {i>kernel<i}.
main.dts | overlay.dts |
---|---|
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; }; |
/dts-v1/; /plugin/; &chosen { bootargs_ext = "..."; }; |
Libufdt
Meskipun model
libfdt
mendukung DTO, sebaiknya gunakan libufdt
untuk menerapkan DTO
(Sumber AOSP di
platform/system/libufdt
).
libufdt
membangun struktur pohon sesungguhnya (hierarki perangkat yang tidak diratakan,
atau ufdt) dari hierarki perangkat yang diratakan (FDT), sehingga dapat meningkatkan
penggabungan dua file .dtb
dari O(N2) ke O(N), di mana N adalah
jumlah {i>node <i}dalam pohon.
Pengujian performa
Dalam pengujian internal Google, menggunakan libufdt
pada 2405
Node DT .dtb
dan 283 .dtbo
menghasilkan ukuran file sebesar
70.618 dan 8.566 byte setelah kompilasi. Dibandingkan dengan
DTO
implementasi yang ditransfer dari FreeBSD (runtime 124 md), libufdt
Waktu proses DTO adalah 10 milidetik.
Pengujian performa untuk perangkat Pixel dibandingkan dengan libufdt
dan
libfdt
. Jumlah efek node dasar serupa, tetapi mencakup
perbedaan berikut:
- Operasi 500 overlay (tambahkan atau ganti) memiliki waktu 6x hingga 8x perbedaan
- Operasi 1000 overlay (tambahkan atau ganti) memiliki waktu 8x hingga 10x perbedaan
Contoh dengan jumlah penambahan yang ditetapkan ke X:
Gambar 1. Jumlah yang ditambahkan adalah X.
Contoh dengan jumlah penggantian ditetapkan ke X:
Gambar 2. Jumlah penggantian adalah X.
libufdt
dikembangkan dengan beberapa API dan data libfdt
Google. Saat menggunakan libufdt
, Anda harus menyertakan dan menautkan
libfdt
(tetapi dalam kode, Anda dapat menggunakan libfdt
API untuk mengoperasikan DTB atau DTBO).
API DTO libufdt
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 dari
File .dtbo
. Nilai yang ditampilkan adalah buffer baru yang berisi
DT gabungan (atau null
jika terjadi error). DT gabungan diformat
di FDT, yang bisa Anda teruskan
ke {i>kernel<i} saat memulai {i>kernel<i}.
Buffer baru dari nilai yang ditampilkan dibuat oleh dto_malloc()
,
yang harus Anda implementasikan saat mem-port libufdt
ke bootloader.
Untuk penerapan referensi, lihat
sysdeps/libufdt_sysdeps_*.c
.
Batasan node root
Anda tidak dapat menempatkan node atau properti baru ke node root DT utama karena operasi overlay bergantung pada label. Karena DT utama harus mendefinisikan label dan DT overlay menetapkan {i>node<i} yang akan dihamparkan dengan label, Anda tidak dapat memberi label untuk node root (sehingga tidak dapat menempatkan root ).
Vendor SoC harus menentukan kemampuan overlay dari DT utama; ODM/OEM hanya dapat
menambahkan atau mengganti {i>node<i} dengan
label yang ditentukan oleh vendor SoC. Sebagai seorang
solusi, Anda dapat menentukan node odm
di bawah
node root di DT dasar, memungkinkan semua node ODM di DT overlay untuk menambahkan node baru.
Atau, Anda bisa menempatkan semua {i>node<i}
terkait SoC di DT dasar ke dalam
Node soc
di bawah node root seperti yang dijelaskan di bawah ini:
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 { ... }; ... }; |
Gunakan overlay terkompresi
Android 9 menambahkan dukungan untuk menggunakan overlay terkompresi dalam gambar DTBO saat menggunakan versi 1 dari {i>header<i} tabel DT. Saat menggunakan header DTBO v1, empat bit paling tidak signifikan pada isian 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 pengujian terkompresi
overlay ke pengujian VtsFirmwareDtboVerification
untuk membantu Anda
memverifikasi ketepatan aplikasi overlay.
Contoh penerapan DTO
Petunjuk berikut akan memandu Anda melalui contoh penerapan DTO
dengan libufdt
(kode contoh di bawah).
Contoh petunjuk DTO
- Menyertakan 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 memori (langkah tepatnya bergantung pada desain Anda). Pada tahap ini, Anda harus 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);
- Buat 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 di FDT format: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 yang digabungkan 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); }