デバイスツリー blob(DTB)またはオーバーレイ用デバイスツリー blob(DTBO)が固有のパーティション(dtb
や dtbo
パーティションなど)にある場合は、以下のテーブル構造とヘッダー形式を使用します。
図 1. DTB および DTBO パーティション レイアウトの例。
データ構造
dt_table_header
は、dtb
/dtbo
パーティションにのみ使用できます。image.gz
の末尾にこの形式を追加することはできません。単一の DTB または DTBO を使用する場合でも、この形式を使用する必要があります(dt_table_header
の dt_entry_count
は 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);
dt_table_entry
の id
、rev
、custom
は、ブートローダーが読み込む DTB または DTBO を効率的に識別するために使用できるデバイスツリーのオプションのハードウェア ID です。ブートローダーが追加情報を必要とする場合、その追加情報は DTB または DTBO に挿入します。ブートローダーは DTB またあ DTBO を解析することによって追加情報を読み込むことができます(以下のサンプルコードを参照してください)。
サンプルコード
次のサンプルコードで、ブートローダーのハードウェア ID を確認します。
check_dtbo()
関数は、ハードウェア ID を確認します。 この関数は最初に構造体dt_table_entry
のデータ(id
、rev
など)を確認します。このデータが十分でない場合、dtb
データをメモリに読み込んで、dtb
の値を確認します。my_dtbo_1.dts
の例では、my_hw_information
プロパティとsoc_id
プロパティの値がルートノードで解析されています。[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
イメージを作成するためのツールです(AOSP の system/libufdt
にソースコードがあります)。mkdtimg
は、create
、cfg_create
、dump
などの複数のコマンドをサポートしています。
create
dtb
/dtbo
イメージを作成するには、create
コマンドを使用します。
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 など)または 16 進数(0x6800 など)を使用できます。または、次の形式を使用してパスを指定することもできます。
<full_node_path>:<property_name>
たとえば、/board/:id
.mkdtimg
は DTB または DTBO ファイル内のパスから値を読み取り、dt_table_entry
の相対プロパティに値(32 ビット)を割り当てます。または、global_option
をすべてのエントリのデフォルト オプションとして指定することもできます。dt_table_header
にある page_size
のデフォルト値は 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
です。 - 2 番目の
id
は0x00006800
で、custom[0]
は0x00000abc
です。 - 3 番目の
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
は、1 つ以上の空白文字から開始します(これらのオプションは 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
が同じイメージ内には 1 つのコンテンツのみが格納されます。これは、同一の DT を持つ異なるハードウェアを使用する場合に便利です。
dump
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
...