डीटीओ का अनुकूलन

यह पृष्ठ उन अनुकूलन पर चर्चा करता है जो आप अपने डीटीओ कार्यान्वयन के लिए कर सकते हैं, रूट नोड को ओवरले करने के खिलाफ प्रतिबंधों का वर्णन करता है, और विवरण देता है कि डीबीटीओ छवि में संपीड़ित ओवरले को कैसे कॉन्फ़िगर किया जाए। यह नमूना कार्यान्वयन निर्देश और कोड भी प्रदान करता है।

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

डिवाइस पेड़ में मूल कर्नेल कमांड लाइन में स्थित है chosen/bootargs नोड। बूटलोडर को इस स्थान को कर्नेल कमांड लाइन के अन्य स्रोतों के साथ जोड़ना चाहिए:

/dts-v1/;

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

डीटीओ नहीं कर सकते हैं, मुख्य डीटी से और डीटी ओवरले ताकि आप में मुख्य डीटी के कर्नेल कमांड लाइन डाल चाहिए CONCATENATE मूल्यों chosen/bootargs और में ओवरले डीटी के कर्नेल कमांड लाइन chosen/bootargs_ext । बूटलोडर फिर इन स्थानों को जोड़ सकता है और परिणाम को कर्नेल में पास कर सकता है।

main.dts ओवरले.डीटीएस
/dts-v1/;

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

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

libufdt

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

प्रदर्शन का परीक्षण

Google के आंतरिक परीक्षण में, का उपयोग कर libufdt 2405 पर .dtb और 283 .dtbo संकलन के बाद 70,618 और 8566 बाइट्स की फ़ाइल आकार में डीटी नोड्स का परिणाम है। एक के साथ तुलना में डीटीओ कार्यान्वयन (124 एमएस क्रम) FreeBSD से मोड़ा, libufdt डीटीओ क्रम 10 एमएस है।

पिक्सेल उपकरणों के लिए निष्पादन परीक्षण की तुलना में libufdt और libfdt । बेस नोड्स प्रभाव की संख्या समान है, लेकिन इसमें निम्नलिखित अंतर शामिल हैं:

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

X पर सेट की गई गणना के साथ उदाहरण:

चित्र 1 जोड़कर गणना है एक्स

एक्स पर सेट ओवरराइडिंग गिनती वाला उदाहरण:

चित्रा 2. अधिभावी गणना है एक्स

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

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 त्रुटि के मामले में)। मर्ज किए गए DT को FDT में फ़ॉर्मेट किया जाता है, जिसे आप कर्नेल को प्रारंभ करते समय कर्नेल को पास कर सकते हैं।

वापसी मान से नए बफर द्वारा बनाई गई है dto_malloc() , जो आप जब पोर्टिंग को लागू करना चाहिए libufdt बूटलोडर में। संदर्भ कार्यान्वयन के लिए, का उल्लेख sysdeps/libufdt_sysdeps_*.c

रूट नोड प्रतिबंध

आप मुख्य डीटी के रूट नोड में एक नया नोड या प्रॉपर्टी ओवरले नहीं कर सकते क्योंकि ओवरले ऑपरेशन लेबल पर निर्भर करते हैं। चूंकि मुख्य डीटी को एक लेबल को परिभाषित करना चाहिए और ओवरले डीटी नोड्स को लेबल के साथ ओवरलेड करने के लिए असाइन करता है, आप रूट नोड के लिए एक लेबल नहीं दे सकते (और इसलिए रूट नोड को ओवरले नहीं कर सकते)।

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

main.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 का उपयोग करते समय DTBO छवि में संपीड़ित ओवरले का उपयोग करने के लिए समर्थन जोड़ता है। DTBO हैडर 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' 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 */
};

वर्तमान में, zlib और gzip संपीड़न समर्थित हैं।

enum dt_compression_info {
    NO_COMPRESSION,
    ZLIB_COMPRESSION,
    GZIP_COMPRESSION
};

एंड्रॉयड 9 के लिए संकुचित ओवरले के परीक्षण के लिए समर्थन जोड़ता है VtsFirmwareDtboVerification आप ओवरले आवेदन की सत्यता की पुष्टि की मदद करने के लिए परीक्षण।

नमूना डीटीओ कार्यान्वयन

निम्नलिखित निर्देश के साथ डीटीओ का एक नमूना कार्यान्वयन के माध्यम से आप चलना libufdt (नमूना नीचे कोड)।

नमूना डीटीओ निर्देश

  1. पुस्तकालयों को शामिल करें। उपयोग करने के लिए libufdt शामिल libfdt डाटा संरचनाओं और एपीआई के लिए:
    #include <libfdt.h>
    #include <ufdt_overlay.h>
    
  2. मुख्य डीटी और ओवरले डीटी लोड करें। लोड .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. का प्रयोग करें ufdt_install_blob() मुख्य डीटी के लिए FDT हैडर पाने के लिए:
      main_fdt_header = ufdt_install_blob(main_buf, main_size);
      main_fdt_size = main_size;
      
    2. कॉल ufdt_apply_overlay() डीटीओ को एक FDT प्रारूप में डीटी विलय कर दिया पाने के लिए:
      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. : पास गिरी शुरू करने के लिए डीटी विलय कर दिया
      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);
}