源码 网站建设教程,廊坊做企业网站公司,线上营销图片,深圳网站设计比较好的公司dtb作为二进制文件被加载到内存中#xff0c;然后由内核读取并进行解析#xff0c;如果对dtb文件的格式不了解#xff0c;那么在看设备树解析相关的内核代码时将会寸步难行#xff0c;而阅读源代码才是了解设备树最好的方式#xff0c;所以#xff0c;如果需要更透彻的了…dtb作为二进制文件被加载到内存中然后由内核读取并进行解析如果对dtb文件的格式不了解那么在看设备树解析相关的内核代码时将会寸步难行而阅读源代码才是了解设备树最好的方式所以如果需要更透彻的了解设备树解析的细节第一步就是需要了解设备树的格式。 1DTB整体结构
经过Device Tree Compiler编译Device Tree source file变成了Device Tree Blob又称作flattened device tree的格式。Device Tree Blob的数据组织如下图所示 2DTB header
struct fdt_header结构体的定义如下
struct fdt_header {fdt32_t magic; /* 用来识别DTB的。通过这个magickernel可以确定bootloader传递的参数block是一个DTB还是tag list以大端模式保存 */fdt32_t totalsize; /* 整个DTB文件的大小 */fdt32_t off_dt_struct; /* structure block的偏移地址 */fdt32_t off_dt_strings; /* strings block的偏移地址 */fdt32_t off_mem_rsvmap; /* memory reservation block的偏移地址 */fdt32_t version; /* 该DTB的版本 */fdt32_t last_comp_version; /* 兼容版本信息 *//* version 2 fields below */fdt32_t boot_cpuid_phys; /* 我们在哪一个CPU用ID标识上booting *//* version 3 fields below */fdt32_t size_dt_strings; /* device tree strings block的size。和off_dt_strings一起确定了strings block在内存中的位置 *//* version 17 fields below */fdt32_t size_dt_struct; /* device tree structure block的size。和和off_dt_struct一起确定了device tree structure block在内存中的位置 */
};
3memory reserve map的格式描述
fdt_reserve_entry结构体如下
struct fdt_reserve_entry {fdt64_t address;fdt64_t size;
};
该结构体用于表示memreserve的起始地址和内存空间的大小它紧跟在struct fdt_header结构体后面。
这一部分的作用是告诉内核哪一些内存空间需要被保留而不应该被系统覆盖使用因为在内核启动时常常需要动态申请大量的内存空间只有提前进行注册用户需要使用的内存才不会被系统征用而造成数据覆盖。
值得一提的是对于设备树而言即使不指定保留内存系统也会默认为设备树保留相应的内存空间。
同时这一部分需要64位(8字节)对齐。 例如
kernel/arch/arm/boot/dts/rtd1195.dtsi// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* Copyright (c) 2017-2019 Andreas Färber
*//memreserve/ 0x00000000 0x0000a800; /* boot code */
/memreserve/ 0x0000a800 0x000f5800;
/memreserve/ 0x17fff000 0x00001000;#include dt-bindings/interrupt-controller/arm-gic.h
#include dt-bindings/reset/realtek,rtd1195.h/ {compatible realtek,rtd1195;interrupt-parent gic;#address-cells 1;#size-cells 1;
/memreserve/ 0x00000000 0x0000a800fdt_reserve_entry的结构体成员address 0x00000000size 0x0000a800。
4 device tree structure block的格式描述
device tree structure block区域是由若干的分片组成每个分片开始位置都是保存了token以此来描述该分片的属性和内容。共计有5种token
1FDT_BEGIN_NODE (0x00000001)。该token描述了一个node的开始位置紧挨着该token的就是node name包括unit address
2FDT_END_NODE (0x00000002)。该token描述了一个node的结束位置。
3FDT_PROP (0x00000003)。该token描述了一个property的开始位置该token之后是两个u32的数据分别是length和name offset。length表示该property value data的size。name offset表示该属性字符串在device tree strings block的偏移值。length和name offset之后就是长度为length具体的属性值数据。
4FDT_NOP (0x00000004)。
被解析设备树的程序忽略可用于覆盖其他属性以删除它。
5FDT_END (0x00000009)。该token标识了一个DTB的结束位置。 单个节点在structure block的存储格式如下图所示子节点的存储格式也是一样 5 device tree strings block的格式描述
在dtb中有大量的重复字符串比如model,compatile等等为了节省空间将这些字符串统一放在某个地址需要使用的时候直接使用索引来查看。
需要注意的是属性部分格式为key valuekey部分被放置在strings部分而value部分的字符串并不会放在这一部分而是直接放在structure中。 6dtb文件解析示例
编译生成dtb文件的源设备树test_dts.dts文件如下
/dts-v1/;/memreserve/ 0x00000000 0x00001000;/ {compatible brcm,bcm2835;model BCM2835;#address-cells 1;#size-cells 1;chosen {stdout-path serial0:115200n8;};memory80000000 {device_type memory;reg 0x80000000 0x10000000;};usbphy: phy {compatible usb-nop-xceiv;#phy-cells 0;};
};
使用如下指令生成test_dtb.dtb文件
dtc -I dts -O dtb -o test_dtb.dtb test_dts.dts
hexdump -C test_dtb.dtb 显示dtb文件的内容 device Tree的文件是以大端模式储存 1) d0 0d fe ed magic
2) 00 00 01 a3 totalsize
3) 00 00 00 48 offdtstruct 0x48
4) 00 00 01 50 offdtstrings
5) 00 00 00 28 off memreserve map
6) 00 00 00 11 version
7) 00 00 00 10 compatible version
8) 00 00 00 00 bootcpu ID
9) 00 00 00 53 size dt strings
10) 00 00 01 08 size dt structure
11) 00 00 00 00 00 00 00 00 memreserve address
12) 00 00 00 00 00 00 10 00 memreserve size
13) 00 00 00 01 所处地址为0x48,处在structure block中0x00000001表示设备节点的开始
14) 00 00 00 00 紧跟着的是设备节点的名字这里是根节点所以为0x00000000
15) 00 00 00 03 0x00000003表示的开始描述设备节点的一个属性 16) 00 00 00 0d 表示这个属性值的长度为0x0d
17) 00 00 00 00 表示这个属性的名字在strings block的偏移量是0找到strings block的地址0x0150的地方可知这个属性的名字是compatible
18) 62 72 63 6d 2c 62 63 6d 32 38 33 35 00 这个compatible属性的值是brcm,bcm2835,加上字符串结束符NULL正好是13个字节 19) 00 00 00 01 chosen节点的开始
20) 63 68 6f 73 65 6e 00 chosen节点的名字
21) 00 00 00 02 chosen节点的结束 22) 00 00 00 09 structure block的结束
23) 63 6f 6d 70 61 74 69 62 6c 65 00 属性名字compatible 7Device Tree文件结构
通过以上分析可以得到Device Tree文件结构如下图所示。dtb的头部首先存放的是fdt_header的结构体信息接着是填充区域填充大小为off_dt_struct – sizeof(struct fdt_header)填充的值为0。接着就是struct fdt_property结构体的相关信息。最后是dt_string部分。 Device Tree源文件的结构分为header、fill_area、dt_struct及dt_string四个区域。fill_area区域填充数值0。节点node信息使用struct fdt_node_header结构体描述。属性信息使用struct fdt_property结构体描述。各个结构体信息如下:
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];
};
struct fdt_node_header描述节点信息tag是标识node的起始结束等信息的标志位name指向node名称的首地址。tag的取值如下
1. #define FDT_BEGIN_NODE 0x1 /* Start node: full name */
2. #define FDT_END_NODE 0x2 /* End node */
3. #define FDT_PROP 0x3 /* Property: name off, size, content */
4. #define FDT_NOP 0x4 /* nop */
5. #define FDT_END 0x9
FDT_BEGIN_NODE和FDT_END_NODE标识node节点的起始和结束FDT_PROP标识node节点下面的属性起始符FDT_END标识Device Tree的结束标识符。因此对于每个node节点的tag标识符一般为FDT_BEGIN_NODE对于每个node节点下面的属性的tag标识符一般是FDT_PROP。
描述属性采用struct fdt_property描述tag标识是属性取值为FDT_PROPlen为属性值的长度包括‘\0’单位字节nameoff为属性名称存储位置相对于off_dt_strings的偏移地址。
struct fdt_property {fdt32_t tag;fdt32_t len;fdt32_t nameoff;char data[0];
};
dt_struct在Device Tree中的结构如下图所示。节点的嵌套也带来tag标识符的嵌套。 参考链接
https://blog.51cto.com/u_15169172/4065013
https://www.cnblogs.com/downey-blog/p/10485529.html