تتناول هذه الصفحة التحسينات التي يمكنك إجراؤها على عملية تطبيق تراكب شجرة الأجهزة (DTO)، ويصف القيود المفروضة على تراكب العقدة الجذر، ويوضّح بالتفصيل كيفية ضبط التراكبات المضغوطة في صورة DTBO. ويقدّم أيضًا نموذجًا لتعليمات التنفيذ والرمز البرمجي.
سطر أوامر النواة
يمكن العثور على سطر أوامر kernel الأصلي في شجرة الجهاز (DT) في ملف node
chosen/bootargs
. يجب أن يربط مشغّل الإقلاع هذا
الموقع الجغرافي بمصادر أخرى لسطر أوامر kernel:
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; };
لا يمكن لملف DTO تسلسل القيم من ملف DT الرئيسي وملف DT المتراكب، لذا
عليك وضع سطر أوامر kernel لملف DT الرئيسي في
chosen/bootargs
وسطر أوامر kernel لملف DT المتراكب في
chosen/bootargs_ext
. يمكن لبرنامج Bootloader بعد ذلك تسلسل هذه المواقع
ونقل النتيجة إلى النواة.
main.dts | overlay.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(N2) إلى O(N)، حيث يكون N هو
عدد العقد في الشجرة.
اختبار الأداء
في الاختبارات الداخلية التي أجرتها Google، يؤدّي استخدام libufdt
على 2405
.dtb
و283 .dtbo
عقد DT إلى أحجام ملفات تبلغ
70,618 و8,566 بايت بعد التجميع. مقارنةً بأحد عمليات تنفيذ DTO التي تم نقلها من FreeBSD (مدة التنفيذ 124 ملي ثانية)، تبلغ مدة تنفيذ libufdt
DTO 10 ملي ثانية.
اختبار الأداء لأجهزة Pixel مقارنةً libufdt
و
libfdt
يشبه تأثير عدد العقد الأساسية، ولكنّه يتضمّن
الاختلافات التالية:
- تختلف مدة تنفيذ 500 عملية تراكب (إضافية أو إلغاء) من 6 إلى 8 أضعاف مقارنةً بعمليات الإضافة.
- تختلف مدّة تنفيذ 1,000 عملية تراكب (إلحاق أو إلغاء) من 8 إلى 10 أضعاف مقارنةً بعمليات الإضافة.
مثال مع ضبط عدد العناصر المُلحَقة على X:
الشكل 1: عدد عمليات الإضافة هو X.
مثال على عدد الإلغاء الذي تم ضبطه على X:
الشكل 2: عدد القيم التي تم إلغاؤها هو X.
تم تطوير libufdt
باستخدام بعض واجهات برمجة التطبيقات
وبيانات libfdt
. عند استخدام libufdt
، يجب تضمين libfdt
وربطه (ومع ذلك، يمكنك استخدام واجهة برمجة التطبيقات libfdt
في الرمز البرمجي الخاص بك لتشغيل DTB أو DTBO).
واجهة برمجة تطبيقات libufdt DTO
في ما يلي واجهة برمجة التطبيقات الرئيسية التي تؤدي إلى 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، والذي يمكنك تمريره إلى النواة عند بدء تشغيلها.
يتم إنشاء المخزن المؤقت الجديد من القيمة المعروضة من خلال dto_malloc()
،
الذي يجب تنفيذه عند نقل libufdt
إلى أداة تحميل التشغيل.
للحصول على عمليات التنفيذ المرجعية، يُرجى الرجوع إلى
sysdeps/libufdt_sysdeps_*.c
.
القيود المفروضة على العقدة الأساسية
لا يمكنك تراكب عقدة أو موقع جديد في العقدة الجذرية لجدول DT الرئيسي، لأنّ عمليات التراكب تعتمد على التصنيفات. ولأنّ جدول البيانات الرئيسي يجب أن يحدِّد علامة وجدول البيانات المتراكب يحدِّد العقد التي سيتمّ وضع علامات عليها، لا يمكنك منح علامة للعقدة الجذر (وبالتالي لا يمكنك تراكب العقدة الجذر).
على مورّدي المنظومة على الرقاقة تحديد إمكانية التراكب لملف DT الرئيسي، ولا يمكن لمصنّعي الأجهزة الأصليين أو المصنّعين المحدّدين فقط
إلحاق العقد أو إلغاء ربطها بتصنيفات يحدّدها مورّد المنظومة على الرقاقة. كحل بديل، يمكنك تحديد عقدة odm
ضمن العقدة الجذر
في DT الأساسية، ما يتيح لجميع عقد ODM في DT المتراكبة إضافة عقد جديدة.
بدلاً من ذلك، يمكنك وضع جميع العقد ذات الصلة بوحدة المعالجة المركزية (SoC) في DT الأساسية في node
soc
ضمن العقدة الجذر كما هو موضّح أدناه:
main.dts | overlay.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 من عنوان جدول DT. عند استخدام الإصدار 1 من عنوان DTBO، تشير الأرقام الأربعة الأقل أهمية من حقل العلامات في 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' 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 };
يتيح نظام التشغيل 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);
- التراكب على البيانات الوصفية:
- استخدِم
ufdt_install_blob()
للحصول على عنوان FDT لجدول البيانات الرئيسي:main_fdt_header = ufdt_install_blob(main_buf, main_size); main_fdt_size = main_size;
- يُرجى الاتصال برقم
ufdt_apply_overlay()
في فريق DTO للحصول على جدول بيانات مبيعات مدمج بتنسيق 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 المدمج لبدء تشغيل النواة:
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); }