इस पेज पर, डिवाइस ट्री ओवरले (डीटीओ) को लागू करने के तरीके में किए जा सकने वाले ऑप्टिमाइज़ेशन के बारे में बताया गया है. इसमें, रूट नोड पर ओवरले करने से जुड़ी पाबंदियों के बारे में भी बताया गया है. साथ ही, डीटीबीओ इमेज में कंप्रेस किए गए ओवरले को कॉन्फ़िगर करने का तरीका भी बताया गया है. इसमें, डीटीओ को लागू करने के निर्देशों और कोड का सैंपल भी दिया गया है.
कर्नेल कमांड लाइन
डिवाइस ट्री (डीटी) में, ओरिजनल कर्नेल कमांड लाइन,
chosen/bootargs नोड में मौजूद होती है. बूटलोडर को इस
जगह को कर्नेल कमांड लाइन के अन्य सोर्स के साथ जोड़ना होगा:
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; };
डीटीओ, मुख्य डीटी और ओवरले डीटी की वैल्यू को नहीं जोड़ सकता. इसलिए, आपको मुख्य डीटी की कर्नेल कमांड लाइन को chosen/bootargs में और ओवरले डीटी की कर्नेल कमांड लाइन को chosen/bootargs_ext में रखना होगा. इसके बाद, बूटलोडर इन जगहों को जोड़कर, नतीजे को कर्नेल को पास कर सकता है.
| main.dts | overlay.dts |
|---|---|
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; }; |
/dts-v1/;
/plugin/;
&chosen {
bootargs_ext = "...";
}; |
libufdt
हालांकि,
libfdt
के नए वर्शन में डीटीओ की सुविधा उपलब्ध है, लेकिन डीटीओ को लागू करने के लिए libufdt का इस्तेमाल करने का सुझाव दिया जाता है.
libufdt का AOSP सोर्स,
platform/system/libufdt पर मौजूद है.
libufdt, फ़्लैटंड डिवाइस ट्री (एफ़डीटी) से असली ट्री स्ट्रक्चर (अन-फ़्लैटंड डिवाइस ट्री या यूएफ़डीटी) बनाता है. इसलिए, यह O(N2) से O(N) तक दो .dtb फ़ाइलों को मर्ज करने की प्रोसेस को बेहतर बना सकता है. यहां N, ट्री में मौजूद नोड की संख्या है.
परफ़ॉर्मेंस की जांच
Google की इंटरनल टेस्टिंग में, 2405
.dtb और 283 .dtbo डीटी नोड पर libufdt का इस्तेमाल करने पर, कंपाइल करने के बाद फ़ाइल का साइज़
70,618 और 8,566 बाइट होता है. FreeBSD से पोर्ट किए गए
डीटीओ
को लागू करने के तरीके (रनटाइम 124 मि॰से॰) की तुलना में, libufdt
डीटीओ का रनटाइम 10 मि॰से॰ है.
Pixel डिवाइसों के लिए परफ़ॉर्मेंस की जांच में, libufdt और
libfdt की तुलना की गई. बेस नोड की संख्या का असर एक जैसा होता है, लेकिन इसमें
ये अंतर शामिल हैं:
- 500 ओवरले (जोड़ने या बदलने) की कार्रवाइयों में, 6 से 8 गुना समय का अंतर होता है
- 1000 ओवरले (जोड़ने या बदलने) की कार्रवाइयों में, 8 से 10 गुना समय का अंतर होता है
जोड़ने की संख्या को X पर सेट करने का उदाहरण:

पहली इमेज. जोड़ने की संख्या X है.
बदलने की संख्या को X पर सेट करने का उदाहरण:

दूसरी इमेज. बदलने की संख्या X है.
libufdt को कुछ libfdt एपीआई और डेटा स्ट्रक्चर के साथ डेवलप किया गया है. libufdt का इस्तेमाल करते समय, आपको
libfdt को शामिल और लिंक करना होगा. हालांकि, अपने कोड में, डीटीबी या डीटीबीओ को ऑपरेट करने के लिए, libfdt
एपीआई का इस्तेमाल किया जा सकता है.
libufdt डीटीओ एपीआई
libufdt में डीटीओ का मुख्य एपीआई इस तरह है:
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 पैरामीटर, मुख्य डीटी है. वहीं, overlay_fdt वह बफ़र है जिसमें .dtbo फ़ाइल का कॉन्टेंट शामिल होता है. इससे मिलने वाली वैल्यू, मर्ज किए गए डीटी वाला नया बफ़र होती है. गड़बड़ी होने पर, यह null होती है. मर्ज किए गए डीटी को एफ़डीटी में फ़ॉर्मैट किया जाता है
. इसे कर्नेल शुरू करते समय, कर्नेल को पास किया जा सकता है.
इससे मिलने वाली वैल्यू से नया बफ़र, dto_malloc(),
से बनाया जाता है. बूटलोडर में libufdt को पोर्ट करते समय, आपको इसे लागू करना चाहिए.
रेफ़रंस के लिए, देखेंsysdeps/libufdt_sysdeps_*.c.
रूट नोड से जुड़ी पाबंदियां
मुख्य डीटी के रूट नोड में, नया नोड या प्रॉपर्टी ओवरले नहीं की जा सकती . ऐसा इसलिए, क्योंकि ओवरले की कार्रवाइयां लेबल पर निर्भर करती हैं. मुख्य डीटी में लेबल तय करना ज़रूरी है. साथ ही, ओवरले डीटी, ओवरले किए जाने वाले नोड को लेबल असाइन करता है. इसलिए, रूट नोड के लिए लेबल नहीं दिया जा सकता. इस वजह से, रूट नोड को ओवरले नहीं किया जा सकता.
एसओसी वेंडर को मुख्य डीटी की ओवरले करने की क्षमता तय करनी होगी. ओडीएम/ओईएम, एसओसी वेंडर की ओर से तय किए गए लेबल वाले नोड को ही
जोड़ या बदल सकते हैं. समाधान के तौर पर, बेस डीटी में रूट नोड के तहत odm नोड तय किया जा सकता है. इससे, ओवरले डीटी में मौजूद सभी ओडीएम नोड, नए नोड जोड़ सकते हैं.
इसके अलावा, बेस डीटी में एसओसी से जुड़े सभी नोड को रूट नोड के तहत
soc नोड में रखा जा सकता है. इसके लिए, यहां दिया गया तरीका अपनाएं:
| 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 { ... }; ... }; |
कंप्रेस किए गए ओवरले का इस्तेमाल करना
Android 9 में, डीटी टेबल हेडर के वर्शन 1 का इस्तेमाल करते समय, डीटीबीओ इमेज में कंप्रेस किए गए ओवरले का इस्तेमाल करने की सुविधा जोड़ी गई है. डीटीबीओ हेडर v1 का इस्तेमाल करते समय, फ़्लैग फ़ील्ड में dt_table_entry के चार सबसे कम अहम बिट, डीटी एंट्री के कंप्रेस करने के फ़ॉर्मैट के बारे में बताते हैं.
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 */ };
फ़िलहाल, zlib और gzip कंप्रेस करने के फ़ॉर्मैट इस्तेमाल किए जा सकते हैं.
enum dt_compression_info { NO_COMPRESSION, ZLIB_COMPRESSION, GZIP_COMPRESSION };
Android 9 में, कंप्रेस किए गए
ओवरले की जांच करने की सुविधा जोड़ी गई है. इसके लिए, VtsFirmwareDtboVerification टेस्ट का इस्तेमाल किया जा सकता है. इससे, आपको
ओवरले ऐप्लिकेशन की सही जानकारी की पुष्टि करने में मदद मिलती है.
डीटीओ को लागू करने का सैंपल
यहां दिए गए निर्देशों में, डीटीओ
को libufdt के साथ लागू करने का सैंपल दिया गया है. इसका कोड यहां दिया गया है.
डीटीओ को लागू करने के निर्देशों का सैंपल
- लाइब्रेरी शामिल करें.
libufdtका इस्तेमाल करने के लिए, डेटा स्ट्रक्चर और एपीआई के लिएlibfdtशामिल करें:#include <libfdt.h> #include <ufdt_overlay.h>
- मुख्य डीटी और ओवरले डीटी लोड करें. स्टोरेज से
.dtbऔर.dtboको मेमोरी में लोड करें. सटीक चरण आपके डिज़ाइन पर निर्भर करते हैं. इस समय, आपके पास.dtb/.dtboका बफ़र और साइज़ होना चाहिए:main_size = my_load_main_dtb(main_buf, main_buf_size)
overlay_size = my_load_overlay_dtb(overlay_buf, overlay_buf_size);
- डीटी को ओवरले करें:
- मुख्य डीटी के लिए एफ़डीटी हेडर पाने के लिए,
ufdt_install_blob()का इस्तेमाल करें:main_fdt_header = ufdt_install_blob(main_buf, main_size); main_fdt_size = main_size;
- एफ़डीटी फ़ॉर्मैट में मर्ज किया गया डीटी पाने के लिए, डीटीओ पर
ufdt_apply_overlay()को कॉल करें:merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size, overlay_buf, overlay_size); -
का साइज़ पाने के लिए,
merged_fdtका इस्तेमाल करें:dtc_totalsize()merged_fdt_size = dtc_totalsize(merged_fdt);
- कर्नेल शुरू करने के लिए, मर्ज किए गए डीटी को पास करें:
my_kernel_entry(0, machine_type, merged_fdt);
- मुख्य डीटी के लिए एफ़डीटी हेडर पाने के लिए,
डीटीओ कोड का सैंपल
#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); }