تحسين منظمات الاتّجار بالمخدرات

تتناول هذه الصفحة التحسينات التي يمكنك إجراؤها على عملية تطبيق تراكب شجرة الجهاز (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

  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. إضافة قيم DT:
    1. استخدِم ufdt_install_blob() للحصول على عنوان FDT لجدول البيانات الرئيسي:
      main_fdt_header = ufdt_install_blob(main_buf, main_size);
      main_fdt_size = main_size;
      
    2. يُرجى الاتصال برقم ufdt_apply_overlay() في فريق DTO للحصول على جدول بيانات مُدمَج بتنسيق 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 المدمج لبدء تشغيل النواة:
      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);
}