| <html devsite> |
| <head> |
| <title>DTB/DTBO Partitions</title> |
| <meta name="project_path" value="/_project.yaml" /> |
| <meta name="book_path" value="/_book.yaml" /> |
| </head> |
| <body> |
| <!-- |
| Copyright 2018 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| |
| <p>If your DTB/DTBO is in a unique partition, e.g. <code>dtb</code> and |
| <code>dtbo</code> partition, use the following table structure and header |
| format:</p> |
| |
| <p><img src="../images/treble_dto_partition_layout.png"></p> |
| <figcaption><strong>Figure 1.</strong> Example |
| <code>dtb</code>/<code>dtbo</code> partition layout (for AVB signature, see |
| <a href="/devices/architecture/dto/implement.html#security">Security</a>). |
| </figcaption> |
| |
| <h2 id=structures>Data structures</h2> |
| <p>The <code>dt_table_header</code> is <strong>only</strong> for the |
| <code>dtb</code>/<code>dtbo</code> partition; you CANNOT append this format |
| after the end of <code>image.gz</code>. If you have a single DTB/DTBO, you must |
| still use this format (and the <code>dt_entry_size</code> in |
| <code>dt_table_header</code> is 1).</p> |
| |
| <pre class="prettyprint"> |
| #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 will be 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 |
| }; |
| </pre> |
| |
| <p>To read all <code>dt_table_entry</code>, use the <code>dt_entry_size</code>, |
| <code>dt_entry_count</code>, and <code>dt_entries_offset</code>. Example:</p> |
| <pre class="prettyprint"> |
| my_read(entries_buf, |
| header_addr + header->dt_entries_offset, |
| header->dt_entry_size * header->dt_entry_count); |
| </pre> |
| |
| <p>The <code>id</code>, <code>rev</code>, <code>custom</code> in |
| <code>dt_table_entry</code> are optional hardware identifications of the device |
| tree the bootloader can use to efficiently identify the DTB/DTBO to load. If the |
| bootloader requires additional information, put it in the DTB/DTBO where |
| bootloader can read it by parsing DTB/DTBO (see the sample code below).</p> |
| |
| <h2 id=sample-code>Sample code</h2> |
| <p>The following sample code checks the hardware identification in bootloader. |
| </p> |
| |
| <ul> |
| <li>The <code>check_dtbo()</code> function checks the hardware identification. |
| It first checks the data in struct <code>dt_table_entry</code> (<code>id</code>, |
| <code>rev</code>, etc.). If this data is not enough, it loads <code>dtb</code> |
| data into memory and checks the value in <code>dtb</code>.</li> |
| <li>The values of <code>my_hw_information</code> and <code>soc_id</code> |
| properties are parsed in the root node (example in <code>my_dtbo_1.dts</code>). |
| |
| <pre class="prettyprint"> |
| [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 != ...) { |
| ... |
| } |
| ... |
| } |
| </pre></li></ul> |
| |
| <h2 id=mkdtimg>mkdtimg</h2> |
| <p><code>mkdtimg</code> is a tool for creating |
| <code>dtb</code>/<code>dtbo</code> images |
| (<a href="https://android-review.googlesource.com/#/q/topic:mkdtimg+(status:open+OR+status:merged+OR+status:pending)" class="external">source |
| code</a> at <code>system/libufdt</code> in AOSP). <code>mkdtimg</code> supports |
| several commands, including <code>create</code>, <code>cfg_create</code>, and |
| <code>dump</code>.</p> |
| |
| <h3 id=create>create</h3> |
| <p>Use the <code>create</code> command to create a |
| <code>dtb</code>/<code>dtbo</code> image:</p> |
| <pre class="devsite-click-to-copy"> |
| <code class="devsite-terminal">mkdtimg create <image_filename> (<global-option>...) \</code> |
| <ftb1_filename> (<entry1_option>...) \ |
| <ftb2_filename> (<entry2_option>...) \ |
| ... |
| </pre> |
| |
| <p><code>ftbX_filename</code> generates a <code>dt_table_entry</code> in the |
| image. <code>entryX_option</code>s are the values to assign to |
| <code>dt_table_entry</code>. These values can be any of the following:</p> |
| <pre class="prettyprint"> |
| --id=<number|path> |
| --rev=<number|path> |
| --custom0=<number|path> |
| --custom1=<number|path> |
| --custom2=<number|path> |
| --custom3=<number|path> |
| </pre> |
| |
| <p>Number values can be a 32-bit digit (such as 68000) or a hex number (such as |
| 0x6800). Alternatively, you can specify a path using the format:</p> |
| <pre class="prettyprint"> |
| <full_node_path>:<property_name> |
| </pre> |
| |
| <p>For example, <code>/board/:id</code>. <code>mkdtimg</code> reads the value |
| from the path in the DTB/DTBO file and assigns the value (32-bit) to a relative |
| property in <code>dt_table_entry</code>. Alternatively, you can give a |
| <code>global_option</code> as a default option for all entries. The default |
| value of <code>page_size</code> in <code>dt_table_header</code> is 2048; use |
| <code>global_option --page_size=<number></code> to assign a different |
| value.</p> |
| |
| <p>Example:</p> |
| <pre class="devsite-click-to-copy"> |
| [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"; |
| }; |
| |
| |
| <code class="devsite-terminal">mkdtimg create dtbo.img --id=/:board_id --custom0=0xabc \</code> |
| board1.dtbo \ |
| board2.dtbo --id=0x6800 \ |
| board3.dtbo --id=0x6801 --custom0=0x123 |
| </pre> |
| |
| <ul> |
| <li>First <code>dt_table_entry</code> (<code>board1.dtbo</code>) <code>id</code> |
| is <code>0x00010000</code> and <code>custom[0]</code> is |
| <code>0x00000abc</code>.</li> |
| <li>Second <code>id</code> is <code>0x00006800</code> and |
| <code>custom[0]</code> is <code>0x00000abc</code>.</li> |
| <li>Third <code>id</code> is <code>0x00006801</code> and <code>custom[0]</code> |
| is <code>0x00000123</code>.</li> |
| <li>All others use the default value (<code>0</code>).</li> |
| </ul> |
| |
| <h3 id=cfg-create>cfg_create</h3> |
| <p>The <code>cfg_create</code> command creates an image with a config file in |
| the following format:</p> |
| <pre class="prettyprint"> |
| # global options |
| <global_option> |
| ... |
| # entries |
| <ftb1_filename> # comment |
| <entry1_option> # comment |
| ... |
| <ftb2_filename> |
| <entry2_option> |
| ... |
| ... |
| </pre> |
| |
| <p>Options <code>global_option</code> and <code>entryX_option</code> must start |
| with one or more space characters (these options are the same as |
| <code>create</code> options, without the <code>--</code> prefix). Empty lines or |
| lines beginning with <code>#</code> are ignored.</p> |
| |
| <p>Example:</p> |
| <pre class="devsite-click-to-copy"> |
| [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 |
| |
| |
| <code class="devsite-terminal">mkdtimg cfg_create dtbo.img dtboimg.cfg</code> |
| </pre> |
| |
| <p><code>mkdtimg</code> does not handle alignment for |
| <code>.dtb</code>/<code>.dtbo</code> files but rather appends them to the image. |
| When you use <code>dtc</code> to compile <code>.dts</code> to |
| <code>.dtb</code>/<code>.dtbo</code>, you must add option <code>-a</code>. For |
| example, adding the option <code>-a 4</code> adds padding so the size of |
| <code>.dtb</code>/<code>.dtbo</code> aligns to 4 bytes.</p> |
| |
| <p>Several DT table entries can share a <code>.dtb</code>/<code>.dtbo</code>. If |
| you use the same filename for different entries, it stores only one content in |
| the image with same <code>dt_offset</code> and <code>dt_size</code>. This is |
| useful when using different hardware with identical DTs.</p> |
| |
| <h3 id=dump>dump</h3> |
| <p>For <code>dtb</code>/<code>dtbo</code> images, use the <code>dump</code> |
| command to print the information in the image. Example:</p> |
| <pre class="devsite-click-to-copy"> |
| <code class="devsite-terminal">mkdtimg dump dtbo.img</code> |
| 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 |
| ... |
| </pre> |
| |
| </body> |
| </html> |