设备树dts格式、编译和dtb文件结构分析

1 FDT 概念

FDT:Flatted Device Tree
DTC:Device Tree Compiler
DTS:Device Tree Source
DTB:Device Tree Binary
在 DTS 文件中按照指定格式结构配置设备信息,通过 DTC 编译后生成 DTB 文件。U-Boot 和 Linux kernel 运行时加载 DTB 信息到内存中,解析设备配置。
编译命令:dtc -I dts -O dtb -o xxx.dtb xxx.dts

2 dts 文件结构

/dts-v1/;

/ {
	model = " ";
	compatible = " ";

	aliases {
        ...
	};

	memory@0 {
		device_type = "memory";
		reg = <0x0 0x40000000>;
	};

	chosen {
		bootargs = "";
		stdout-path = "serial0:115200n8";
	};

	device1 {
		compatible = " ";

		device1-subdevice {

		};
	};
};

dts 文件基本结构包括 node、property 和 value。root node 只能有一个,其余 node 有且只有一个 parent node;每个 node 有多个 property 和 value,并且用 node name 标识;value 的形式可能是空、数值、数组和字符串。

3 dtb 文件结构

dtb 文件内部信息排列
dtb header
memory reserve map
device-tree structure
device-tree string

3.1 dtb header

struct fdt_header {
	fdt32_t magic;			 /* magic word FDT_MAGIC */
	fdt32_t totalsize;		 /* total size of DT block */
	fdt32_t off_dt_struct;		 /* offset to structure */
	fdt32_t off_dt_strings;		 /* offset to strings */
	fdt32_t off_mem_rsvmap;		 /* offset to memory reserve map */
	fdt32_t version;		 /* format version */
	fdt32_t last_comp_version;	 /* last compatible version */

	/* version 2 fields below */
	fdt32_t boot_cpuid_phys;	 /* Which physical CPU id we're
					    booting on */
	/* version 3 fields below */
	fdt32_t size_dt_strings;	 /* size of the strings block */

	/* version 17 fields below */
	fdt32_t size_dt_struct;		 /* size of the structure block */
};

文件头包括的信息有:幻数、文件大小、设备树结构信息偏移地址和大小、设备树参数西信息偏移地址和大小、以及文件格式版本号等。

3.2 memory reserve map

struct fdt_reserve_entry {
	fdt64_t address;
	fdt64_t size;
};

3.3 device-tree structure

struct fdt_node_header {
	fdt32_t tag;
	char name[0];
};

struct fdt_property {
	fdt32_t tag;
	fdt32_t len;
	fdt32_t nameoff;
	char data[0];
};

#define FDT_BEGIN_NODE	0x1		/* Start node: full name */
#define FDT_END_NODE	0x2		/* End node */
#define FDT_PROP	    0x3		/* Property: name off,
                            size, content */
#define FDT_NOP		    0x4		/* nop */
#define FDT_END		    0x9

dts 文件中 node 和 property 按照以上格式存储在 dtb 文件。tag 类型有以上五种,name 和 data 都是指针,所以 node 占用 8 bytes,property 占用 16 bytes。
node 结构的 name 记录 node name 的存储地址;property 的 nameoff 记录 property name 的存储地址,data 位置开始存储 property value 的值,len 记录 value 占用字节长度。

3.4 device-tree string

dts 文件中所有的 node name 和 property name 信息存储区域。

4 dtb 实际文件分析

4.1 dtb 文件反汇编

fdtdump -sd /zynq-zc702.dtb

/zynq-zc702.dtb: found fdt at offset 0
/dts-v1/;
// magic:		        0xd00dfeed
// totalsize:		    0x42c7 (17095)
// off_dt_struct:	    0x38
// off_dt_strings:	    0x3e08
// off_mem_rsvmap:	    0x28
// version:		        17
// last_comp_version:	16
// boot_cpuid_phys:	    0x0
// size_dt_strings:	    0x4bf
// size_dt_struct:	    0x3dd0

// 0038: tag: 0x00000001 (FDT_BEGIN_NODE)
/ {
// 0040: tag: 0x00000003 (FDT_PROP)
// 3e08: string: #address-cells
// 004c: value
    #address-cells = <0x00000001>;
// 0050: tag: 0x00000003 (FDT_PROP)
// 3e17: string: #size-cells
// 005c: value
    #size-cells = <0x00000001>;
// 0060: tag: 0x00000003 (FDT_PROP)
// 3e23: string: compatible
// 006c: value
    compatible = "xlnx,zynq-zc702", "xlnx,zynq-7000";
// 008c: tag: 0x00000003 (FDT_PROP)
// 3e2e: string: model
// 0098: value
    model = "Xilinx ZC702 board";
// 00ac: tag: 0x00000001 (FDT_BEGIN_NODE)
    cpus {
// 00b8: tag: 0x00000003 (FDT_PROP)
// 3e08: string: #address-cells
// 00c4: value
        #address-cells = <0x00000001>;
// 00c8: tag: 0x00000003 (FDT_PROP)
// 3e17: string: #size-cells
// 00d4: value
        #size-cells = <0x00000000>;
// 00d8: tag: 0x00000001 (FDT_BEGIN_NODE)
        cpu@0 {
// 00e4: tag: 0x00000003 (FDT_PROP)
// 3e23: string: compatible
// 00f0: value
            compatible = "arm,cortex-a9";
// 0100: tag: 0x00000003 (FDT_PROP)
// 3e34: string: device_type
// 010c: value
            device_type = "cpu";
...
// 3e00: tag: 0x00000002 (FDT_END_NODE)
};

从 ftddump 结果可以看到文件头的信息,通过 off_dt_struct 和 off_mem_rsvmap 可以计算出文件头占用 40 bytes(0x28), reserve map 占用 16 bytes(0x10),device tree struct 的起始偏移地址为 0x38;根据最后一个 FDT_END_NODE 的地址可以推算出 dt_string 的开始地址为 0x3e08, dt_struct 的总大小为 0x3dd0,与 size_dt_struct 和 off_dt_strings 的信息一致。

在 0x38 地址找到第一个 root node,与上面的起始偏移信息完全吻合,根据 3.3 的分析可知下一个 node 地址应该是 0x40。在 0x40 地址找到一个 property,nameoff 指向 0x3e08(第一个 device-tree string),property name 为 #address-cells。

0x4c、0x6c、0x010c 都是存储 property value,0x4c 后面的 property 地址是 0x5c,因为0x4c 是一个数值<0x00000001>占用了 4 bytes;0x6c 后面的 property 地址是 0x8c,因为 0x6c 是一个字符串(“xlnx,zynq-zc702”, “xlnx,zynq-7000”)占用了不超过 32 bytes;0x010c 后面的 property 地址是 0x0110,因为 0x010c 是一个字符串(“cpu”)占用了不超过 4 bytes。根据 0x4c 和 0x6c 的对比可以得出 property value 确实直接从 property 的 data 位置开始存储,通过 0x6c 和 0x010c 的对比可以得出字符串存储内容是双引号内的字符并且做 4 bytes 对齐。

4.2 dts文件

/dts-v1/;
/ {
	#address-cells = <1>;
	#size-cells = <1>;
	compatible = "xlnx,zynq-7000";

	cpus {
		#address-cells = <1>;
		#size-cells = <0>;

		cpu0: cpu@0 {
			compatible = "arm,cortex-a9";
			device_type = "cpu";
...
};

实际 dts 文件内容与 fdtdump 得到的结果一致。

推荐链接

蜗窝科技 Device Tree

  • 19
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怦然心动如往昔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值