تتناول هذه الصفحة التحسينات التي يمكنك إجراؤها على عملية تطبيق تراكب شجرة الجهاز (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
. يمكن لبرنامج الإقلاع بعد ذلك ربط هذه
المواقع الجغرافية وتمرير النتيجة إلى النواة.
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
من عقدة N2 في شجرة 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 أضعاف
- 1000 عملية تراكب (إلحاق أو إلغاء) يكون بها فارق زمني يتراوح بين 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 الرئيسي، لأنّ عمليات التراكب تعتمد على التصنيفات. وبما أنّ جدول البيانات الرئيسي يجب أن يحدِّد علامة وجدول البيانات المتراكب يحدِّد العقد التي سيتمّ وضع علامات عليها، لا يمكنك منح علامة للعقدة الجذر (وبالتالي لا يمكنك التراكب على العقدة الجذر).
على مورّدي المنظومة على الرقاقة (SoC) تحديد القدرة المركّبة على DT الرئيسي، ويمكن للمصنّعين الأصليين أو المصنّعين الأصليين للأجهزة إلحاق أو إلغاء العُقد فقط بتصنيفات يحددها مورّد المنظومة على الرقاقة (SoC). كحل بديل، يمكنك تحديد عقدة 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);
- إضافة قيم DT:
- استخدِم
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); }