أقسام DTB وDTBO

إذا كان ملف الجهاز (DTB) أو ملف الجهاز المخصّص للتراكب (DTBO) في قسم فريد، مثل القسمَين dtb وdtbo، استخدِم بنية الجدول التالية وتنسيق العنوان التالي:

الشكل 1: مثال على تنسيق قسم DTB وDTBO

هياكل البيانات

يُستخدم dt_table_header فقط للقسيمة dtb/dtbo، ولا يمكنك إلحاق هذا التنسيق بعد نهاية image.gz. إذا كان لديك ملف DTB أو DTBO واحد، يجب مواصلة استخدام هذا التنسيق (ويكون dt_entry_count في dt_table_header هو 1).

#define DT_TABLE_MAGIC 0xd7b7ab1e

struct dt_table_header {
  uint32_t magic;             // DT_TABLE_MAGIC
  uint32_t total_size;        // includes dt_table_header + all dt_table_entry
                              // and all dtb/dtbo
  uint32_t header_size;       // sizeof(dt_table_header)

  uint32_t dt_entry_size;     // sizeof(dt_table_entry)
  uint32_t dt_entry_count;    // number of dt_table_entry
  uint32_t dt_entries_offset; // offset to the first dt_table_entry
                              // from head of dt_table_header

  uint32_t page_size;         // flash page size we assume
  uint32_t version;       // DTBO image version, the current version is 0.
                          // The version is incremented when the
                          // dt_table_header struct is updated.
};

struct dt_table_entry {
  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 custom[4];         // optional, must be zero if unused
};

لقراءة كل dt_table_entry، استخدِم dt_entry_size، dt_entry_count، وdt_entries_offset. مثال:

my_read(entries_buf,
        header_addr + header->dt_entries_offset,
        header->dt_entry_size * header->dt_entry_count);

إنّ id وrev وcustom في dt_table_entry هي معرّفات اختيارية للأجهزة في شجرة الجهاز يمكن لبرنامج التمهيد استخدامها لتحديد DTB أو DTBO بكفاءة لتحميله. إذا كان ملف التمهيد يحتاج إلى معلومات إضافية، ضَع هذه المعلومات في DTB أو DTBO حيث يمكن لملف التمهيد قراءتها من خلال تحليل DTB أو DTBO (اطّلِع على نموذج الرمز البرمجي أدناه).

نموذج التعليمات البرمجية

يتحقّق الرمز النموذجي التالي من معرّف الجهاز في أداة تحميل التشغيل.

  • تتحقّق الدالة check_dtbo() من معرّف الجهاز. يفحص أولاً البيانات في البنية dt_table_entry (id rev، وما إلى ذلك). إذا لم تكن هذه البيانات كافية، يتم تحميل بيانات dtb في الذاكرة والتحقّق من القيمة في dtb.
  • يتمّ تحليل قيم السمتَين my_hw_information وsoc_id في العقدة الجذر (مثال في my_dtbo_1.dts).
    [my_dtbo_1.dts]
    /dts-v1/;
    /plugin/;
    
    / {
      /* As DTS design, these properties only for loader, won't overlay */
      compatible = "board_manufacturer,board_model";
    
      /* These properties are examples */
      board_id = <0x00010000>;
      board_rev = <0x00010001>;
      another_hw_information = "some_data";
      soc_id = <0x68000000>;
      ...
    };
    
    &device@0 {
      value = <0x1>;
      status = "okay";
    };
    
    
    [my_bootloader.c]
    int check_dtbo(const dt_table_entry *entry, uint32_t header_addr) {
      ...
      if (entry->id != ... || entry->rev != ...) {
        ...
      }
      ...
      void * fdt_buf = my_load_dtb(header_addr + entry->dt_offset, entry->dt_size);
      int root_node_off = fdt_path_offset(fdt_buf, "/");
      ...
      const char *my_hw_information =
        (const char *)fdt_getprop(fdt_buf, root_node_off, "my_hw_information", NULL);
      if (my_hw_information != NULL && strcmp(my_hw_information, ...) != 0) {
        ...
      }
      const fdt32_t *soc_id = fdt_getprop(fdt_buf, root_node_off, "soc_id", NULL);
      if (soc_id != NULL && *soc_id != ...) {
        ...
      }
      ...
    }

mkdtimg

mkdtimg هي أداة لإنشاء صورdtb/dtbo (رمز برمجي مصدر في system/libufdt في AOSP). يتيح mkdtimg تنفيذ العديد من الطلبات، بما في ذلك create وcfg_create و dump.

إنشاء

استخدِم الأمر create لإنشاء dtb/dtbo صورة:

mkdtimg create <image_filename> (<global-option>...) \
    <ftb1_filename> (<entry1_option>...) \
    <ftb2_filename> (<entry2_option>...) \
    ...

تنشئ الدالة ftbX_filename dt_table_entry في الصورة. وentryX_option هي القيم التي يتم تعيينها dt_table_entry. يمكن أن تكون هذه القيم أيًّا ممّا يلي:

--id=<number|path>
--rev=<number|path>
--custom0=<number|path>
--custom1=<number|path>
--custom2=<number|path>
--custom3=<number|path>

يمكن أن تكون القيم الرقمية رقمًا بتنسيق 32 بت (مثل 68000) أو رقمًا سداسيًا (مثل 0x6800). بدلاً من ذلك، يمكنك تحديد مسار باستخدام التنسيق التالي:

<full_node_path>:<property_name>

على سبيل المثال، /board/:id. يقرأ mkdtimg القيمة من المسار في ملف DTB أو DTBO ويحدّد القيمة (32 بت) لسمة نسبية في dt_table_entry. بدلاً من ذلك، يمكنك استخدام global_option كخيار تلقائي لجميع الإدخالات. القيمة التلقائية لـ page_size في dt_table_header هي 2048. استخدِم global_option --page_size=<number> لتحديد قيمة مختلفة.

مثال:

[board1.dts]
/dts-v1/;
/plugin/;

/ {
  compatible = "board_manufacturer,board_model";
  board_id = <0x00010000>;
  board_rev = <0x00010001>;
  another_hw_information = "some_data";
  ...
};

&device@0 {
  value = <0x1>;
  status = "okay";
};


mkdtimg create dtbo.img --id=/:board_id --custom0=0xabc \
  board1.dtbo \
  board2.dtbo --id=0x6800 \
  board3.dtbo --id=0x6801 --custom0=0x123
  • المجموعة الأولى dt_table_entry (board1.dtbo) id هي 0x00010000 وcustom[0] هو 0x00000abc.
  • الرمز id الثاني هو 0x00006800 و custom[0] هو 0x00000abc.
  • id الثالث هو 0x00006801 وcustom[0] هو 0x00000123.
  • وتستخدم جميع القيم الأخرى القيمة التلقائية (0).

cfg_create

ينشئ الأمر cfg_create صورة باستخدام ملف إعدادات بالتنسيق التالي:

# global options
  <global_option>
  ...
# entries
<ftb1_filename>     # comment
  <entry1_option>   # comment
  ...
<ftb2_filename>
  <entry2_option>
  ...
...

يجب أن يبدأ الخياران global_option وentryX_option بحرف مسافة واحد أو أكثر (تُعدّ هذه الخيارات مماثلة لخيارات create، بدون البادئة --). يتم تجاهل السطور الفارغة أو السطور التي تبدأ بالرمز #.

مثال:

[dtboimg.cfg]
# global options
  id=/:board_id
  rev=/:board_rev
  custom0=0xabc

board1.dtbo

board2.dtbo
  id=0x6800       # override the value of id in global options

board2.dtbo
  id=0x6801       # override the value of id in global options
  custom0=0x123   # override the value of custom0 in global options


mkdtimg cfg_create dtbo.img dtboimg.cfg

لا تعالج أداة mkdtimg محاذاة ملفات .dtb/.dtbo، بل تُلحقها بالصورة. عند استخدام dtc لتجميع .dts إلى .dtb/.dtbo، يجب إضافة الخيار -a. على سبيل المثال، تؤدي إضافة الخيار -a 4 إلى إضافة حشو حتى يتم ضبط حجم .dtb/.dtbo على 4 بايت.

يمكن أن تتشارك عدة إدخالات في جدول DT قيمة .dtb/.dtbo. إذا كنت تستخدم اسم الملف نفسه لإدخالات مختلفة، يتم تخزين محتوى واحد فقط في الصورة التي تحتوي على dt_offset وdt_size نفسهما. ويُعدّ ذلك مفيداً عند استخدام أجهزة مختلفة مع بيانات اختبار تشغيل متطابقة.

تفريغ

بالنسبة إلى صور dtb/dtbo، استخدِم الأمر dump لطباعة المعلومات الواردة في الصورة. مثال:

mkdtimg dump dtbo.img
dt_table_header:
               magic = d7b7ab1e
          total_size = 1300
         header_size = 32
       dt_entry_size = 32
      dt_entry_count = 3
   dt_entries_offset = 32
           page_size = 2048
             version = 0
dt_table_entry[0]:
             dt_size = 380
           dt_offset = 128
                  id = 00010000
                 rev = 00010001
           custom[0] = 00000abc
           custom[1] = 00000000
           custom[2] = 00000000
           custom[3] = 00000000
           (FDT)size = 380
     (FDT)compatible = board_manufacturer,board_model
...