أقسام 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_options هي القيم التي يتم تعيينها إليها dt_table_entry ويمكن أن تكون هذه القيم أي مما يلي:

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

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

<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 صورة تحتوي على ملف إعداد في بالتنسيق التالي:

# 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. هذا هو فائدة عند استخدام أجهزة مختلفة بوحدات DT متطابقة.

تفريغ

بالنسبة إلى 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
...