پارتیشن های 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 s مقادیری هستند که باید به 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
  • id اول dt_table_entry ( board1.dtbo ) 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 ، padding اضافه می شود تا اندازه .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
...