目录
1、结构
dtb结构由一个小的报头和三个大小可变的部分组成:内存预留块,结构块和字符串块。 这些应该按这个顺序出现在扁平的设备树中。 因此,设备树结构作为一个整体,当以地址载入内存时,将类似于下图的图(较低的地址位于图的顶部)。
注: 内存预留块可能不存在,尽管在某些情况下可能需要它们来满足单个块的对齐约束。
2、dtb报头
所有报头字段都是32位整数,以大端格式存储 。
struct fdt_header {
uint32_t magic;
uint32_t totalsize;
uint32_t off_dt_struct;
uint32_t off_dt_strings;
uint32_t off_mem_rsvmap;
uint32_t version;
uint32_t last_comp_version;
uint32_t boot_cpuid_phys;
uint32_t size_dt_strings;
uint32_t size_dt_struct;
};
magic | 此字段应包含值0xd00dfeed |
totalsize | 包含devicetree数据结构的总大小(以字节为单位)。这个大小应包含所有结构的各个部分(报头,内存预留块,结构块和字符串块),以及块之间或最后一块之后的任何空闲空间间隙 |
off_dt_struct | 结构块的偏移量(从报头开始的字节偏移量)。 |
off_dt_strings | 字符串块的偏移量(从报头开始的字节偏移量)。 |
off_mem_rsvmap | 内存预留块的偏移量(从报头开始的字节偏移量)。 |
version | 该dtb的版本 |
last_comp_version | 兼容版本信息(此字段应包含设备树数据结构的最低版本,使用的版本与之向后兼容)。 |
boot_cpuid_phys | 这个字段应该包含系统启动CPU的物理ID。 它应该与设备树中CPU节点的reg属性中给定的物理ID相同。 |
size_dt_strings | 该字段应包含设备树blob的字符串块部分的字节长度。 |
size_dt_struct | 该字段应包含设备树blob的结构块部分的字节长度 |
3、内存预留块
内存预留块向客户端程序提供物理内存中被预留的区域列表; 也就是说,它不应用于一般内存分配。 它用于保护重要的数据结构不被客户机程序覆盖。
3.1、结构
内存预留块由一个64位大端整数对的列表组成。
struct fdt_reserve_entry {
uint64_t address;
uint64_t size;
};
每一对都给出一个预留内存区域的物理地址和字节大小。 这些给定的区域互不重叠。 内存预留块列表以一个地址和大小都等于0的条目结束。
注:内存预留块由多个uint64_t组成。
4、结构块
结构块描述了设备树本身的结构和内容。 它由带有数据的标记序列组成,这些标记被组织成一个线性树结构。
FDT_BEGIN_NODE(0x00000001) | 标记一个节点表示的开始。 它后面应该有节点的单元名作为额外的数据(即后跟设备节点名称)。 名称存储为一个以空字符结束的字符串,并应包括单元地址(如果有的话)。 如果需要对齐,节点名后面跟着置零填充字节,然后是下一个token(可以是除FDT_END之外的任何token)。 |
FDT_END_NODE(0x00000002) | 标记节点表示的结束。 这个token没有额外的数据; 所以紧随其后的是下一个token(可以是除FDT_PROP之外的任何token)。 |
FDT_PROP(0x00000003) | 标志着设备树中一个属性表示的开始。 其后应附有描述该属性的额外数据。 这个数据首先由属性的长度和名称组成(这个结构中的两个字段都是32位的大端整数) len以字节为单位给出了属性值的长度(可以是0,表示属性为空) nameoff在字符串块中给出了一个偏移量,在该块中,属性的名称被存储为一个以空字符结束的字符串。 |
FDT_NOP(0x00000004) | 将被任何解析设备树的程序忽略。 这个token没有额外的数据; 因此,紧跟其后的是下一个token(可以是任何有效的token)。 树中的属性或节点定义可以被FDT_NOP标记覆盖,从而将其从树中删除,而不需要在devicetree blob中移动树表示的其他部分 |
FDT_END(0x00000009) | 标记结构块的结束。 FDT_END token应该只有一个,并且应该是结构块中的最后一个token。 它没有额外的数据; |
4.2、树结构
设备树结构被表示为一个线性树:每个节点以FDT_BEGIN_NODE token开始,以FDT_END_NODE token结束。 节点的属性和子节点(如果有的话)在FDT_END_NODE之前表示,因此这些子节点的FDT_BEGIN_NODE和FDT_END_NODE token被嵌套在父节点的token中。
结构块作为一个整体由根节点的表示(它包含所有其他节点的表示)组成,后面跟着一个FDT_END标记,表示结构块作为一个整体的结束。
更准确地说,每个节点的表示由以下组件组成:
• (可选)任意数量的FDT_NOP tokens
• FDT_BEGIN_NODE token
—节点名以空字符结尾
—[置零填充字节对齐到4字节边界]
• 对于节点的每个属性:
—(可选)任意数量的FDT_NOP tokens
—FDT_PROP token
—[置零填充字节对齐到4字节边界]
• 描述子节点结束
—(可选)任意数量的FDT_NOP tokens
—FDT_END_NODE token
5、字符串块
字符串块包含设备树中使用的所有属性名称的字符串。这些以空结尾的字符串被简单地连接在一起,并由结构块中的偏移量引用到字符串块中。
注:字符串块没有对齐约束,可以出现在设备树块开始的任意偏移位置 !
5.1、为什么存在单独的字符串块
原因是为了节省内存空间。在设备树文件中,有很多个节点都有相同的属性名称(如compatible),这些相同名字的字符串只需保留一份。通过在字符串块中的偏移量即可获取到。
6、对齐
内存预留块应该对齐到8字节的边界,而结构块应该对齐到4字节的边界 。
7、例子
/dts-v1/;
/ {
model = "dtb";
compatible = "abc,666", "ABC,999";
status = "okay";
node1 {
str = "helloWorld";
};
node2 {
val = <100 200>;
};
};
7.1、报头
magic | 魔数magic,0xd00dfeed。 |
totalsize | 总字节数,0x000000f4。 |
off_dt_struct | 结构块的偏移量,0x00000038。 |
off_dt_strings | 字符串块的偏移量,0x000000d4。 |
off_mem_rsvmap | 内存预留块的偏移量,0x00000028。 |
version | 该dtb的版本为17版本,0x00000011。 |
last_comp_version | 兼容16版本信息,0x00000010,即兼容16版本的设备树。 |
boot_cpuid_phys | 系统启动CPU的物理ID,0x00000000。 |
size_dt_strings | devicetree blob的字符串块部分的字节长度,0x00000020 。 |
size_dt_struct | devicetree blob的结构块部分的字节长度 ,0x0000009c。 |
7.2、内存预留块
内存预留块:off_mem_rsvmap(0x00000028)-off_dt_struct(0x00000038)
内存预留块格式如下:
struct fdt_reserve_entry {
uint64_t address;
uint64_t size;
};
地址和大小都为0,表示内存预留块结束(此例未定义内存预留块内容)。
7.3、结构块
结构块偏移:off_dt_struct(0x00000038)
结构块大小:size_dt_struct(0x0000009c)
7.3.1、树形结构
FDT_BEGIN_NODE(0x0001)标记一个节点表示的开始,FDT_END_NODE(0x0002)标记节点表示的结束,FDT_END(0x0009)标记结构块的结束。
/根设备节点
--node1设备节点
--node2设备节点
7.3.2、根节点"model"属性
token | FDT_PROP(0x00000003) |
属性值长度 | 0x00000004 |
属性名称在字符串块的偏移 | 0x00000000 |
属性值 | "dtb" |
属性名称 | "model" |
7.3.3、根节点"compatible"属性
token | FDT_PROP(0x00000003) |
属性值长度 | 0x00000010 |
属性名称在字符串块的偏移 | 0x00000006 |
属性值 | "abc,666", "ABC,999" |
属性名称 | compatible |
7.3.4、根节点"status"属性
token | FDT_PROP(0x00000003) |
属性值长度 | 0x00000005 |
属性名称在字符串块的偏移 | 0x00000011 |
属性值 | "okay" |
属性名称 | status |
7.3.5、node1节点“str”
token | FDT_PROP(0x00000003) |
属性值长度 | 0x0000000b |
属性名称在字符串块的偏移 | 0x00000018 |
属性值 | "helloWorld" |
属性名称 | status |
7.3.6、node2节点"val"属性
token | FDT_PROP(0x00000003) |
属性值长度 | 0x00000008 |
属性名称在字符串块的偏移 | 0x0000001c |
属性值 | <100 200> |
属性名称 | val |
7.4、字符串块
字符串块偏移:off_dt_strings(0x000000d4)
字符串块大小:size_dt_strings(0x00000020)