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

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

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

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

/dts-v1/;

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

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

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

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

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

libufdt

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

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

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

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

  • 500 ओवरले (संलग्न या ओवरराइड) ऑपरेशन में 6x से 8x समय का अंतर होता है
  • 1000 ओवरले (संलग्न या ओवरराइड) ऑपरेशन में 8x से 10x समय का अंतर होता है

संख्या को X पर सेट करने का उदाहरण:

चित्र 1. संलग्न संख्या X है

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

चित्र 2. ओवरराइडिंग गिनती X है

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

libufdt डीटीओ एपीआई

libufdt में DTO का मुख्य API इस प्रकार है:

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

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

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

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

एसओसी विक्रेताओं को मुख्य डीटी की ओवरलेइंग क्षमता को परिभाषित करना होगा; ODM/OEM केवल SoC विक्रेता द्वारा परिभाषित लेबल वाले नोड्स को जोड़ या ओवरराइड कर सकते हैं। वर्कअराउंड के रूप में, आप बेस डीटी में रूट नोड के तहत एक odm नोड को परिभाषित कर सकते हैं, जिससे ओवरले डीटी में सभी ओडीएम नोड्स नए नोड्स जोड़ने में सक्षम हो जाएंगे। वैकल्पिक रूप से, आप बेस डीटी में सभी एसओसी-संबंधित नोड्स को नीचे बताए अनुसार रूट नोड के तहत एक 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 {
        ...
    };
    ...
};

संपीड़ित ओवरले का उपयोग करना

डिवाइस ट्री टेबल हेडर के संस्करण 1 का उपयोग करते समय एंड्रॉइड 9 डीटीबीओ छवि में संपीड़ित ओवरले का उपयोग करने के लिए समर्थन जोड़ता है। DTBO हेडर v1 का उपयोग करते समय, dt_table_entry में फ़्लैग फ़ील्ड के चार सबसे कम महत्वपूर्ण बिट्स 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' 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. मुख्य DT के लिए FDT हेडर प्राप्त करने के लिए ufdt_install_blob() का उपयोग करें:
      main_fdt_header = ufdt_install_blob(main_buf, main_size);
      main_fdt_size = main_size;
      
    2. FDT प्रारूप में मर्ज किए गए DT को प्राप्त करने के लिए DTO को ufdt_apply_overlay() पर कॉल करें:
      merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size,
                                      overlay_buf, overlay_size);
      
    3. dtc_totalsize() का आकार प्राप्त करने के लिए merged_fdt उपयोग करें:
      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);
}