设备树 dtb结构

目录

1、结构

2、dtb报头

3、内存预留块

3.1、结构

4、结构块

4.2、树结构

5、字符串块

5.1、为什么存在单独的字符串块

6、对齐

7、例子

7.1、报头

7.2、内存预留块

7.3、结构块

7.3.1、树形结构

7.3.2、属性1

7.3.3、属性2

 7.3.4、属性3

 7.3.5、属性4

7.3.6、属性5

7.4、字符串块


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位的大端整数)

struct {
    uint32_t len;
    uint32_t nameoff;
}

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_NODEFDT_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_structdevicetree 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"属性

tokenFDT_PROP(0x00000003)
属性值长度0x00000004
属性名称在字符串块的偏移0x00000000
属性值"dtb"
属性名称"model"

7.3.3、根节点"compatible"属性

tokenFDT_PROP(0x00000003)
属性值长度0x00000010
属性名称在字符串块的偏移0x00000006
属性值"abc,666", "ABC,999"
属性名称compatible

 7.3.4、根节点"status"属性

tokenFDT_PROP(0x00000003)
属性值长度0x00000005
属性名称在字符串块的偏移0x00000011
属性值"okay"
属性名称status

 7.3.5、node1节点“str”

tokenFDT_PROP(0x00000003)
属性值长度0x0000000b
属性名称在字符串块的偏移0x00000018
属性值"helloWorld"
属性名称status

7.3.6、node2节点"val"属性

tokenFDT_PROP(0x00000003)
属性值长度0x00000008
属性名称在字符串块的偏移0x0000001c
属性值<100 200>
属性名称val

7.4、字符串块

字符串块偏移:off_dt_strings(0x000000d4)

字符串块大小:size_dt_strings(0x00000020)

     

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值