ডিটিও অপ্টিমাইজ করুন

এই পৃষ্ঠায় আপনার ডিভাইস ট্রি ওভারলে (DTO) ইমপ্লিমেন্টেশনে করা যেতে পারে এমন অপটিমাইজেশনগুলো নিয়ে আলোচনা করা হয়েছে, রুট নোডের উপর ওভারলে করার সীমাবদ্ধতা বর্ণনা করা হয়েছে এবং DTBO ইমেজে কীভাবে কম্প্রেসড ওভারলে কনফিগার করতে হয় তার বিস্তারিত বিবরণ দেওয়া হয়েছে। এতে নমুনা ইমপ্লিমেন্টেশন নির্দেশাবলী এবং কোডও প্রদান করা হয়েছে।

কার্নেল কমান্ড লাইন

ডিভাইস ট্রি (DT)-তে মূল কার্নেল কমান্ড লাইনটি chosen/bootargs নোডে অবস্থিত। বুটলোডারকে অবশ্যই এই অবস্থানটিকে কার্নেল কমান্ড লাইনের অন্যান্য উৎসের সাথে সংযুক্ত করতে হবে:

/dts-v1/;

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

DTO মূল DT এবং ওভারলে DT থেকে মান সংযুক্ত করতে পারে না , তাই আপনাকে অবশ্যই মূল DT-এর কার্নেল কমান্ড লাইন chosen/bootargs এ এবং ওভারলে DT-এর কার্নেল কমান্ড লাইন chosen/bootargs_ext এ রাখতে হবে। এরপর বুটলোডার এই অবস্থানগুলো সংযুক্ত করে ফলাফলটি কার্নেলে পাঠাতে পারে।

main.dts ওভারলে.ডিটিএস
/dts-v1/;

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

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

libufdt

যদিও সর্বশেষ libfdt DTO সমর্থন করে, তবুও DTO বাস্তবায়নের জন্য libufdt ব্যবহার করার পরামর্শ দেওয়া হয় (AOSP সোর্স platform/system/libufdt এ রয়েছে)। libufdt ফ্ল্যাটেনড ডিভাইস ট্রি (FDT) থেকে একটি প্রকৃত ট্রি কাঠামো (আন-ফ্ল্যাটেনড ডিভাইস ট্রি বা ufdt ) তৈরি করে, ফলে এটি দুটি .dtb ফাইল মার্জ করার প্রক্রিয়াকে O( ) থেকে O(N)-এ উন্নত করতে পারে, যেখানে N হলো ট্রির নোডের সংখ্যা।

কর্মক্ষমতা পরীক্ষা

গুগলের অভ্যন্তরীণ পরীক্ষায়, ২৪০৫টি .dtb এবং ২৮৩টি .dtbo ডিটি নোডে libufdt ব্যবহার করার ফলে কম্পাইলেশনের পর ফাইলের আকার হয় যথাক্রমে ৭০,৬১৮ এবং ৮,৫৬৬ বাইট। FreeBSD থেকে পোর্ট করা একটি DTO ইমপ্লিমেন্টেশনের (১২৪ মিলিসেকেন্ড রানটাইম) সাথে তুলনা করলে, libufdt DTO-এর রানটাইম হলো ১০ মিলিসেকেন্ড।

পিক্সেল ডিভাইসগুলির জন্য পারফরম্যান্স পরীক্ষায় libufdt এবং libfdt তুলনা করা হয়েছে। বেস নোডের সংখ্যার প্রভাব একই রকম, তবে এতে নিম্নলিখিত পার্থক্যগুলি অন্তর্ভুক্ত রয়েছে:

  • ৫০০টি ওভারলে (অ্যাপেন্ড বা ওভাররাইড) অপারেশনের ক্ষেত্রে সময়ের পার্থক্য ৬ থেকে ৮ গুণ বেশি।
  • ১০০০টি ওভারলে (অ্যাপেন্ড বা ওভাররাইড) অপারেশনের ক্ষেত্রে সময়ের পার্থক্য ৮ থেকে ১০ গুণ বেশি হয়।

X-এ সেট করা কাউন্ট যুক্ত করার উদাহরণ:

চিত্র ১। সংযোজন সংখ্যা হলো X।

ওভাররাইডিং কাউন্ট X-এ সেট করা থাকলে উদাহরণ:

চিত্র ২। অগ্রাহ্যকারী গণনা হলো X।

libufdt কিছু libfdt API এবং ডেটা স্ট্রাকচার দিয়ে তৈরি করা হয়েছে। libufdt ব্যবহার করার সময়, আপনাকে অবশ্যই libfdt অন্তর্ভুক্ত এবং লিঙ্ক করতে হবে (তবে, আপনার কোডে আপনি DTB বা DTBO পরিচালনা করার জন্য libfdt API ব্যবহার করতে পারেন)।

libufdt DTO API

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 )। মার্জ করা ডিটি-টি `FDT` ফরম্যাটে থাকে, যা আপনি কার্নেল চালু করার সময় কার্নেলে পাঠাতে পারেন।

রিটার্ন ভ্যালু থেকে নতুন বাফারটি dto_malloc() দ্বারা তৈরি করা হয়, যা libufdt বুটলোডারে পোর্ট করার সময় আপনার ইমপ্লিমেন্ট করা উচিত। রেফারেন্স ইমপ্লিমেন্টেশনের জন্য, sysdeps/libufdt_sysdeps_*.c দেখুন।

রুট নোড সীমাবদ্ধতা

আপনি মূল ডিটি-র রুট নোডের উপর কোনো নতুন নোড বা প্রপার্টি ওভারলে করতে পারবেন না, কারণ ওভারলে অপারেশন লেবেলের উপর নির্ভর করে। যেহেতু মূল ডিটি-কে অবশ্যই একটি লেবেল নির্ধারণ করতে হয় এবং ওভারলে ডিটি যে নোডগুলোকে ওভারলে করা হবে সেগুলোকে লেবেল প্রদান করে, তাই আপনি রুট নোডের জন্য কোনো লেবেল দিতে পারবেন না (এবং ফলস্বরূপ রুট নোডটিকে ওভারলে করতেও পারবেন না)।

SoC ভেন্ডরদের অবশ্যই মূল DT-এর ওভারলেয়িং ক্ষমতা নির্ধারণ করতে হবে; ODM/OEM-রা শুধুমাত্র SoC ভেন্ডর দ্বারা নির্ধারিত লেবেলযুক্ত নোড যুক্ত বা ওভাররাইড করতে পারে। একটি বিকল্প সমাধান হিসেবে, আপনি বেস DT-তে রুট নোডের অধীনে একটি odm নোড নির্ধারণ করতে পারেন, যা ওভারলে DT-তে থাকা সমস্ত ODM নোডকে নতুন নোড যুক্ত করার সুযোগ দেবে। বিকল্পভাবে, আপনি বেস DT-তে থাকা সমস্ত 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 {
        ...
    };
    ...
};

সংকুচিত ওভারলে ব্যবহার করুন

অ্যান্ড্রয়েড ৯, ডিটি টেবিল হেডারের সংস্করণ ১ ব্যবহার করার সময় ডিটিবিও (DTBO) ইমেজে কম্প্রেসড ওভারলে ব্যবহারের সুবিধা যোগ করেছে। ডিটিবিও হেডার ভি১ (dt_table_entry) ব্যবহার করার সময়, dt_table_entry- এর flags ফিল্ডের সর্বনিম্ন চারটি গুরুত্বপূর্ণ বিট ডিটি এন্ট্রির কম্প্রেশন ফরম্যাট নির্দেশ করে।

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
};

অ্যান্ড্রয়েড ৯, ওভারলে অ্যাপের সঠিকতা যাচাই করতে সাহায্য করার জন্য VtsFirmwareDtboVerification টেস্টে কম্প্রেসড ওভারলে পরীক্ষা করার সুবিধা যোগ করেছে।

নমুনা DTO বাস্তবায়ন

নিম্নলিখিত নির্দেশাবলীতে libufdt ব্যবহার করে DTO-এর একটি নমুনা বাস্তবায়নের পদ্ধতি ধাপে ধাপে দেখানো হয়েছে (নমুনা কোড নিচে দেওয়া হলো)।

নমুনা DTO নির্দেশাবলী

  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);

নমুনা 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);
}