تناقش هذه الصفحة التحسينات التي يمكنك إجراؤها على تنفيذ 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:
مثال مع تجاوز العد مضبوطًا على 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
- تشمل المكتبات. لاستخدام
libufdt
، قم بتضمينlibfdt
لهياكل البيانات وواجهات برمجة التطبيقات:#include <libfdt.h> #include <ufdt_overlay.h>
- قم بتحميل 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);
- تراكب DTs:
- استخدم
ufdt_install_blob()
للحصول على رأس FDT لـ DT الرئيسي:main_fdt_header = ufdt_install_blob(main_buf, main_size); main_fdt_size = main_size;
- اتصل
ufdt_apply_overlay()
بـ DTO للحصول على DT مدمج بتنسيق FDT:merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size, overlay_buf, overlay_size);
- استخدم
merged_fdt
للحصول على حجمdtc_totalsize()
:merged_fdt_size = dtc_totalsize(merged_fdt);
- قم بتمرير 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); }