300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > Linux设备树学习2 - DTB文件格式

Linux设备树学习2 - DTB文件格式

时间:2019-08-03 00:01:55

相关推荐

Linux设备树学习2 - DTB文件格式

一. DTB文件简介

DTB文件是由DTS文件通过dtc命令编译生成的二进制文件。DTS文件不能直接被内核解析,需要编译成DTB文件才可以直接被内核识别并解析使用的。

二. DTB文件内容布局

从上图可以看出,DTB由四个部分组成,分别是struct fdt_header,memory reservation,structure block,strings block,free space用于填充,使以上四个块的数据能满足四字节对齐,所以free space并不总是会显示出来。下面会详细介绍DTB文件各个部分。

三. FDT Header介绍

struct fdt_header的布局可以使用一个C语言结构体定义,占用的内存大小为40字节,如下

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;};

示例:

00000000 d0 0d fe ed 00 00 1a 77 00 00 00 38 00 00 18 60 |.......w...8...`|00000010 00 00 00 28 00 00 00 11 00 00 00 10 00 00 00 00 |...(............|00000020 00 00 02 17 00 00 18 28 |.......(........|

magic :该字段应该被设置成0xd00dfeed,字节序是大端字节序

totalsize :DTB文件的总大小,示例中为0x00001a77

off_dt_struct :structure block相对于DTB文件头的偏移的字节数,示例中为0x00000038

off_dt_strings :strings block相对于DTB文件头的偏移的字节数,示例中为0x00001860

off_mem_rsvmap :memory reservation相对于DTB文件头的字节数,示例中为0x00000028

version :DTB的版本号,示例中为0x00000011

last_comp_version :DTB的上一个版本,示例中为0x00000010

boot_cpuid_phys :保存系统CPU的ID号,示例中为0x00

size_dt_strings :strings block的大小,示例中为0x00000217

size_dt_struct :structure block的大小,示例中为0x00001828

四. Memory Reservation介绍

memory reservation指定的内存范围将会被保留,它不能被一般的内存分配函数使用,防止这块内存内的重要数据被内核破坏。memory reservation也可以用C语言的结构体表示,如下

struct fdt_reserve_entry {uint64_t address;uint64_t size;};

struct fdt_reserve_entry占用16字节大小,address和size都由u64数表示。

五. Structure Block介绍

structure block由五个标识包含设备树的一些数据,形成一个树形结构,五个标识分别如下

FDT_BEGIN_NODE (0x00000001) :表示一个设备节点的开始。接下来跟着设备节点的名字,设备备节点名字如果有unit-address,需要加上去,节点名字最后以NULL结尾。如果结尾没有4字节对齐,需要填充0x00,保证4字节对齐。

FDT_END_NODE (0x00000002) :表示一个设备节点的结束。它的后面不用跟数据,通常是跟下一个标识,除了FDT_DROP。

示例:

DTS代码片段:

cpus {cpu@0 {compatible = "mips,mips24KEc";};};

DTB代码片段:

000000b0 00 00 00 01 63 70 75 73 00 00 00 00 |........cpus....|000000c0 00 00 00 01 63 70 75 40 30 00 00 00 00 00 00 03 |....cpu@0.......|000000d0 00 00 00 0f 00 00 00 1b 6d 69 70 73 2c 6d 69 70 |........mips,mip|000000e0 73 32 34 4b 45 63 00 00 00 00 00 02 00 00 00 02 |s24KEc..........|

从上面的代码可知,包含了两个device_node,分别是cpus和cpu@0,cpu@0是cpus的子节点,所以代码中有两个FDT_BEGIN_NODE (0x00000001),和FDT_END_NODE (0x00000002)。FDT_BEGIN后跟着节点名称。从DTB的组织方式也可以看出structure block是以树状层次结构布局的。

FDT_DROP (0x00000003) :表示一个属性的开始。后面需要跟一个属性名的长度和偏移量,再后面跟属性的值,属性的长度和偏移量可以用C语言结构体表示

struct {uint32_t len;uint32_t nameoff;}

len表示此结构后跟的属性值的长度,NULL也包含在内,nameoff表示属性名在strings block中偏移量。示例如下

00000090 00 00 00 03 00 00 00 15 00 00 00 26 57 6f 6f 79 |...........&Wooy|000000a0 61 20 49 4f 54 20 53 6d 61 72 74 20 37 36 32 30 |a IOT Smart 7620|000000b0 00 00 00 00 |.... |

节选strings block:

00001860 23 61 64 64 72 65 73 73 2d 63 65 6c 6c 73 00 23 |#address-cells.#|00001870 73 69 7a 65 2d 63 65 6c 6c 73 00 63 6f 6d 70 61 |size-pa|00001880 74 69 62 6c 65 00 6d 6f 64 65 6c 00 62 6f 6f 74 |tible.model.boot|00001890 61 72 67 73 00 23 69 6e 74 65 72 72 75 70 74 2d |args.#interrupt-|000018a0 63 65 6c 6c 73 00 69 6e 74 65 72 72 75 70 74 2d |cells.interrupt-|000018b0 63 6f 6e 74 72 6f 6c 6c 65 72 00 6c 69 6e 75 78 |controller.linux|000018c0 2c 70 68 61 6e 64 6c 65 00 72 65 67 00 72 61 6e |,phandle.reg.ran|000018d0 67 65 73 00 69 6e 74 65 72 72 75 70 74 2d 70 61 |ges.interrupt-pa|000018e0 72 65 6e 74 00 69 6e 74 65 72 72 75 70 74 73 00 |rent.interrupts.|

00 00 00 03 :表示FDT_DROP

00 00 00 15 :表示"Wooya IOT Smart 7620"的长度,记得结尾的NULL也计算在内

00 00 00 26 :表示"Wooya IOT Smart 7620"的属性名在strings block中的偏移,从节选的strings block可以看出属性名是"model"。

tips :结尾多出的00 00 00是为了保证4字节对齐

FDT_NOP (0x00000004) :FDT_NOP程序在解析时将被忽略,此标识不跟任何数据,只跟下一个标识。

FDT_END (0x00000009) :FDT_END表示structure block的结束,DTB文件只有一个FDT_END标识,并且是structure block的最后一个标识,所以后面跟的是strings block的开始。

根节点示例:

DTS代码片段:

/ {#address-cells = <0x1>;#size-cells = <0x1>;................}

DTB代码片段:

00000030 00 00 00 01 00 00 00 00 |................|00000040 00 00 00 03 00 00 00 04 00 00 00 00 00 00 00 01 |................|00000050 00 00 00 03 00 00 00 04 00 00 00 0f 00 00 00 01 |................|......../* strings blcok start */00001860 23 61 64 64 72 65 73 73 2d 63 65 6c 6c 73 00 23 |#address-cells.#|00001870 73 69 7a 65 2d 63 65 6c 6c 73 00 63 6f 6d 70 61 |size-pa|00001880 74 69 62 6c 65 00 6d 6f 64 65 6c 00 62 6f 6f 74 |tible.model.boot|00001890 61 72 67 73 00 23 69 6e 74 65 72 72 75 70 74 2d |args.#interrupt-|000018a0 63 65 6c 6c 73 00 69 6e 74 65 72 72 75 70 74 2d |cells.interrupt-|000018b0 63 6f 6e 74 72 6f 6c 6c 65 72 00 6c 69 6e 75 78 |controller.linux|000018c0 2c 70 68 61 6e 64 6c 65 00 72 65 67 00 72 61 6e |,phandle.reg.ran|

以上DTB片段是根节点的,根节点比较特殊,根节点00 00 00 01后接着的是00 00 00 00,可以看出根节点节点名是空的,00 00 00 03后是属性值的长度为0x04,strings block中的偏移为0,值为00 00 00 01,表示#address-cells = <0x1>;后面00 00 00 03则表示#size-cells = <0x1>。

六. Strings Block介绍

string block包含了在设备树中出现的所有的属性名,所有的名字都是以NULL结尾,structure block通过nameoff来引用其中的属性名。strings block的结尾不需要4字节对齐。

七. 总结

本文介绍了DTB文件的四个块,分别是struct header,memory reservation,structure block,strings block,并介绍了他们的各自的组织方式。熟悉DTB的数据组织方式,是理解Linux内核解析DTB文件流程的基础,所以熟悉DTB非常的重要。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。