تحسين DTOs

تنظيم صفحاتك في مجموعات يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.

تناقش هذه الصفحة التحسينات التي يمكنك إجراؤها على تنفيذ DTO الخاص بك ، وتصف القيود ضد تراكب العقدة الجذرية ، وتفاصيل كيفية تكوين التراكبات المضغوطة في صورة DTBO. كما يوفر نموذجًا لإرشادات التنفيذ والتعليمات البرمجية.

سطر أوامر Kernel

يقع سطر أوامر kernel الأصلي في شجرة الجهاز في العقدة chosen/bootargs . يجب أن يربط محمل الإقلاع هذا الموقع بمصادر أخرى لسطر أوامر kernel:

/dts-v1/;

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

لا يمكن لـ DTO تسلسل القيم من DT الرئيسي والتراكب DT ، لذلك يجب عليك وضع سطر أوامر kernel الخاص بـ DT الرئيسي في chosen/bootargs وسطر أوامر kernel الخاص بالتراكب DT في chosen/bootargs_ext . يمكن لـ Bootloader بعد ذلك أن يربط هذه المواقع ويمرر النتيجة إلى النواة.

main.dts تراكب. dts
/dts-v1/;

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

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

libufdt

بينما يدعم أحدث libfdt DTO ، يوصى باستخدام libufdt لتنفيذ DTO (مصدر AOSP في platform/system/libufdt ). يبني libufdt بنية شجرة حقيقية (شجرة جهاز غير مسطحة ، أو ufdt ) من شجرة الجهاز المسطحة (FDT) ، لذلك يمكنه تحسين دمج ملفين .dtb من O (N 2 ) إلى O (N) ، حيث N هو عدد العقد في الشجرة.

اختبار أداء

في اختبار Google الداخلي ، يؤدي استخدام libufdt على 2405 .dtb و 283 .dtbo DT إلى أحجام ملفات تبلغ 70618 و 8.566 بايت بعد التجميع. بالمقارنة مع تنفيذ DTO المنقول من FreeBSD (وقت تشغيل 124 مللي ثانية) ، فإن وقت تشغيل libufdt DTO هو 10 مللي ثانية.

مقارنة اختبار الأداء لأجهزة Pixel libufdt و libfdt . عدد تأثير العقد الأساسية مشابه ، لكنه يتضمن الاختلافات التالية:

  • 500 عملية تراكب (إلحاق أو تجاوز) لها فرق زمني 6x إلى 8x
  • 1000 عملية تراكب (إلحاق أو تجاوز) لها فرق زمني 8x إلى 10x

مثال على إلحاق العدد مضبوطًا على X:

الشكل 1. إلحاق العد هو X

مثال مع تجاوز العد مضبوطًا على X:

الشكل 2. تجاوز العد X

تم تطوير libufdt مع بعض واجهات برمجة التطبيقات libfdt وهياكل البيانات. عند استخدام libufdt ، يجب عليك تضمين libfdt (ومع ذلك ، في التعليمات البرمجية الخاصة بك يمكنك استخدام libfdt API لتشغيل DTB أو DTBO).

libufdt DTO API

واجهة برمجة التطبيقات الرئيسية لـ DTO في 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 ، والذي يمكنك تمريره إلى kernel عند بدء kernel.

يتم إنشاء المخزن المؤقت الجديد من قيمة الإرجاع بواسطة dto_malloc() ، والذي يجب عليك تنفيذه عند نقل libufdt إلى أداة تحميل التشغيل. للتطبيقات المرجعية ، ارجع إلى sysdeps/libufdt_sysdeps_*.c .

قيود عقدة الجذر

لا يمكنك تراكب عقدة أو خاصية جديدة في العقدة الجذرية لـ DT الرئيسي لأن عمليات التراكب تعتمد على التسميات. نظرًا لأن DT الرئيسي يجب أن يحدد تسمية وأن التراكب DT يعين العقد التي سيتم تراكبها بالتسميات ، لا يمكنك إعطاء تسمية لعقدة الجذر (وبالتالي لا يمكنك تراكب العقدة الجذرية).

يجب على بائعي SoC تحديد قدرة التراكب الخاصة بـ DT الرئيسي ؛ يمكن لـ ODM / OEMs إلحاق أو تجاوز العقد ذات التسميات المحددة بواسطة بائع SoC فقط. كحل بديل ، يمكنك تحديد عقدة odm أسفل العقدة الجذرية في DT الأساسي ، مما يتيح لجميع عقد ODM في تراكب DT لإضافة عقد جديدة. بدلاً من ذلك ، يمكنك وضع جميع العقد المرتبطة بـ SoC في DT الأساسي في عقدة soc ضمن عقدة الجذر كما هو موضح أدناه:

main.dts تراكب. 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 دعمًا لاستخدام التراكبات المضغوطة في صورة DTBO عند استخدام الإصدار 1 من رأس جدول شجرة الجهاز. عند استخدام رأس 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
};

يضيف Android 9 دعمًا لاختبار التراكبات المضغوطة إلى اختبار VtsFirmwareDtboVerification لمساعدتك على التحقق من صحة تطبيق التراكب.

نموذج تنفيذ DTO

ترشدك الإرشادات التالية خلال نموذج تنفيذ DTO باستخدام libufdt (نموذج التعليمات البرمجية أدناه).

نموذج تعليمات DTO

  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. تراكب DTs:
    1. استخدم ufdt_install_blob() للحصول على رأس FDT لـ DT الرئيسي:
      main_fdt_header = ufdt_install_blob(main_buf, main_size);
      main_fdt_size = main_size;
      
    2. اتصل ufdt_apply_overlay() بـ DTO للحصول على DT مدمج بتنسيق 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. قم بتمرير DT المدمج لبدء kernel:
      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);
}