डीटीओ ऑप्टिमाइज़ करें

इस पेज पर उन ऑप्टिमाइज़ेशन के बारे में बताया गया है जिन्हें डिवाइस ट्री ओवरले (डीटीओ) को लागू करने और रूट नोड को ओवरले करने से जुड़ी पाबंदियों के बारे में बताता है. साथ ही, DTBO इमेज में कंप्रेस किए गए ओवरले कॉन्फ़िगर कर सकता है. यह सैंपल लागू करने के निर्देश और कोड.

कर्नेल कमांड लाइन

डिवाइस ट्री (DT) में मूल कर्नेल कमांड लाइन chosen/bootargs नोड. बूटलोडर को इसे जोड़ना होगा कर्नेल कमांड लाइन के अन्य सोर्स के साथ लोकेशन:

/dts-v1/;

/ {
  chosen: chosen {
    bootargs = "...";
  };
};

DTO मुख्य DT से मानों को नहीं जोड़ सकता और DT को ओवरले नहीं कर सकता, इसलिए आपको मुख्य DT की कर्नेल कमांड लाइन chosen/bootargs और इसमें ओवरले DT की कर्नेल कमांड लाइन chosen/bootargs_ext. इसके बाद, बूटलोडर इन कोड को एक साथ जोड़कर जगहों की जानकारी इकट्ठा करता है और नतीजे को कर्नेल में पास करता है.

मुख्य.डीटीएस ओवरले.डीटीएस
/dts-v1/;

/ {
  chosen: chosen {
    bootargs = "...";
  };
};
/dts-v1/;
/plugin/;

&chosen {
  bootargs_ext = "...";
};

Libufdt

हालांकि, नई libfdt डीटीओ का इस्तेमाल किया जा सकता है. क्या डीटीओ लागू करने के लिए, libufdt का इस्तेमाल किया जाना चाहिए (AOSP का स्रोत: platform/system/libufdt). libufdt, असल में ट्री स्ट्रक्चर बनाता है (बिना चपटे डिवाइस ट्री, या ufdt), फ़्लैटन डिवाइस ट्री (FDT) से मिलता है, ताकि यह दो .dtb फ़ाइलों को O(N2) से O(N) में मर्ज करने पर, जहां N ट्री में नोड की संख्या.

परफ़ॉर्मेंस टेस्टिंग

Google की इंटरनल टेस्टिंग में, 2405 पर libufdt का इस्तेमाल किया जा रहा है .dtb और 283 .dtbo DT नोड्स का फ़ाइल आकार इस प्रकार होता है कंपाइलेशन के बाद 70,618 और 8,566 बाइट. इसकी तुलना में डीटीओ लागू करना FreeBSD (124 मि॰से॰ रनटाइम), libufdt से पोर्ट किया गया डीटीओ रनटाइम 10 मि॰से॰ है.

libufdt और libufdt की तुलना में, Pixel डिवाइसों के लिए परफ़ॉर्मेंस टेस्टिंग libfdt. आधार नोड की संख्या समान है, लेकिन इसमें ये शामिल हैं तो ये अंतर हैं:

  • 500 ओवरले (जोड़ें या बदलें) से जुड़ी कार्रवाइयों का समय 6x से 8 गुना होता है अंतर
  • 1000 ओवरले (जोड़ें या बदलें) कार्रवाइयों का समय 8x से 10 गुना होता है अंतर

X पर सेट की गई संख्या का उदाहरण:

पहला डायग्राम. जोड़े गए योग की संख्या X है.

X पर सेट की गई संख्या का उदाहरण:

दूसरी इमेज. ओवरराइड की संख्या X है.

libufdt को कुछ libfdt एपीआई और डेटा का इस्तेमाल करके डेवलप किया गया है स्ट्रक्चर. libufdt का इस्तेमाल करते समय, आपको इन्हें शामिल करना होगा और लिंक करना होगा libfdt (हालांकि, अपने कोड में libfdt का इस्तेमाल किया जा सकता है DTB या DTBO को चलाने के लिए एपीआई).

libufdt DTO API

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 मुख्य DT है और overlay_fdt एक बफ़र है, जिसमें .dtbo फ़ाइल. रिटर्न वैल्यू एक नया बफ़र है जिसमें मर्ज किया गया DT (या गड़बड़ी की स्थिति में null). मर्ज किया गया DT फ़ॉर्मैट किया गया है FDT में, जिसे कर्नेल को शुरू करते समय कर्नेल में पास किया जा सकता है.

रिटर्न वैल्यू से नया बफ़र, dto_malloc() ने बनाया है, जिसे आपको बूटलोडर में libufdt को पोर्ट करते समय लागू करना चाहिए. रेफ़रंस फ़ाइलों को लागू करने के बारे में जानने के लिए, यहां जाएं sysdeps/libufdt_sysdeps_*.c.

रूट नोड की सीमाएं

मुख्य DT के रूट नोड में नया नोड या प्रॉपर्टी ओवरले नहीं की जा सकती क्योंकि ओवरले की कार्रवाइयां लेबल के हिसाब से होती हैं. क्योंकि मुख्य DT को लेबल और ओवरले DT लेबलों से ओवरले करने के लिए नोड असाइन करता है, ताकि रूट नोड के लिए लेबल नहीं दे सकता (और इसलिए रूट को ओवरले नहीं कर सकता नोड) के लिए फ़िल्टर का इस्तेमाल किया जा सकता है.

SoC वेंडर को मुख्य डीटी की ओवरले करने की क्षमता तय करनी चाहिए; ODM/OEM सिर्फ़ ये काम कर सकते हैं SoC वेंडर के तय किए गए लेबल से नोड जोड़ना या बदलना. बतौर इस समस्या को हल करना है, तो आपodm बेस DT में रूट नोड, ओवरले DT में सभी ODM नोड को नए नोड जोड़ने में चालू करते हैं. इसके अलावा, बेस डीटी में मौजूद SoC से जुड़े सभी नोड को soc नोड को रूट नोड में ले जाया जा सकता है, जैसा कि नीचे बताया गया है:

मुख्य.डीटीएस ओवरले.डीटीएस
/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, कंप्रेस किए गए ओवरले इस्तेमाल करने की सुविधा देता है DT तालिका हेडर के वर्शन 1 का उपयोग करते समय DTBO इमेज में दिखाई देगा. DTBO हेडर v1 का इस्तेमाल करते समय, फ़्लैग फ़ील्ड के चार सबसे कम ज़रूरी बिट dt_table_try में 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 */
};

फ़िलहाल, zlib और gzip कंप्रेस करने की सुविधा काम करती है.

enum dt_compression_info {
    NO_COMPRESSION,
    ZLIB_COMPRESSION,
    GZIP_COMPRESSION
};

Android 9 में, कंप्रेस की गई टेस्टिंग की सुविधा जोड़ी गई है को ओवरले करता है, ताकि VtsFirmwareDtboVerification की जांच की जा सके. ओवरले ऐप्लिकेशन के सही होने की पुष्टि करें.

डीटीओ को लागू करने का सैंपल

यहां दिए गए निर्देशों से, आपको डीटीओ को लागू करने के सैंपल के बारे में जानकारी मिलती है libufdt के साथ (सैंपल कोड नीचे दिया गया है).

डीटीओ के निर्देशों का सैंपल

  1. लाइब्रेरी शामिल करें. libufdt का इस्तेमाल करने के लिए, शामिल करें डेटा स्ट्रक्चर और एपीआई के लिए libfdt:
    #include <libfdt.h>
    #include <ufdt_overlay.h>
    
  2. मुख्य DT और ओवरले DT लोड करें. .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);
    
  3. डीटी को ओवरले करें:
    1. मुख्य DT का एफ़डीटी हेडर पाने के लिए ufdt_install_blob() का इस्तेमाल करें:
      main_fdt_header = ufdt_install_blob(main_buf, main_size);
      main_fdt_size = main_size;
      
    2. एफ़डीटी में मर्ज किया गया डीटी पाने के लिए, ufdt_apply_overlay() को कॉल करके डीटीओ को कॉल करें फ़ॉर्मैट:
      merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size,
                                      overlay_buf, overlay_size);
      
    3. साइज़ जानने के लिए merged_fdt का इस्तेमाल करें dtc_totalsize():
      merged_fdt_size = dtc_totalsize(merged_fdt);
      
    4. कर्नेल को शुरू करने के लिए, मर्ज किया गया DT पास करें:
      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);
}