设备树dtb文件的格式分析

简介: 设备树dtb文件的格式分析

参考设备树内容

/dts-v1/;
/ {
    model = "this is my devicethree!";
        #address-cells = <1>;
        #size-cells = <1>;
    chosen {
        bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";
    };
    cpu: cpu@1 {
            device_type = "cpu";
            compatible = "arm,cortex-a35","arm,armv8";
            reg = <0x0 0x1>;
    };
    aliases{
        led1 = "/gpio22020101";
    };
    node1{
        #address-cells = <1>;
        #size-cells = <1>;
        gpio@22020101{
            reg=<0x20110102 0x40>;
        };
    };
    node2{
        node1-child{
            pinnum = <0 1 2 3 4>;
        };
    };
    gpio@22020101{
        reg=<0x20110101 0x40>;
        status="okay";
    };
};

编译得到dtb文件

/home/alientek/linux/IMX6ULL/linux/temp/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek/scripts/dtc/dtc -I dts -O dtb -o my_device_tree.dtb my_device_tree.dts

使用软件查看生成的dtb文件

DTB文件格式

DTB文件格式主要分为四个部分:header(头部),memory reservation block(内存预留块),structure block(结构块),strings block(字符串块)。free space(自由空间)

不一定存在。

分布

struct fdt_header

free space

memory reservation block

free spacestructure block

free spacestrings block

free space

1.header头部

struct fdt_header {
    uint32_t magic;             /* magic word FDT_MAGIC */ // FDT_MAGIC 魔数
    uint32_t totalsize;         /* total size of DT block */ // DT块的总大小
    uint32_t off_dt_struct;         /* offset to structure */ // 结构体的偏移量
    uint32_t off_dt_strings;     /* offset to strings */ // 字符串的偏移量
    uint32_t off_mem_rsvmap;     /* offset to memory reserve map */ // 内存保留映射的偏移量
    uint32_t version;         /* format version */ // 格式版本
    uint32_t last_comp_version;     /* last compatible version */ // 最后兼容版本
    /* version 2 fields below */
    uint32_t boot_cpuid_phys;     /* Which physical CPU id we're
                        booting on */ // 我们正在启动的物理CPU ID
    /* version 3 fields below */
    uint32_t size_dt_strings;     /* size of the strings block */ // 字符串块的大小
    /* version 17 fields below */
    uint32_t size_dt_struct;     /* size of the structure block */ // 结构块的大小
};

注意:所有成员类型均为32u,为大端模式

1.magic

magic的值必须是0xd00dfeed。打开文件。

2.totalsize

totalsize表示dtb文件的大小。例子中dtb文件大小为676字节。如下图所示:

totalsize的类型为u32,,所以676字节转换成16进制是0x000002a4。打开文件dtb。

3.off_dt_struct

off_dt_struct表示structure block(结构块)在dtb文件中的偏移地址。dtb文件中off_dt_struct的值是0x00000038。

所以structure block(结构块)从下图开始

4.off_dt_strings字符串的偏移量

off_dt_strings表示(字符串块)在dtb文件中的偏移地址。dtb文件中off_dt_strings的值为0x0000024c。

所以strings block(字符串块)从下图位置开始。

5.off_mem_rsvmap 内存保留映射的偏移量

off_mem_rsvmap表示memory reservation block(内存预留块)在dtb文件中的偏移地址,dtb文件中off_mem_rsvmap的值是0x00000028。

所以memory reservation block(内存预留块)从下图位置开始。

6.version 格式版本

version表示设备树数据结构的版本,version的值为0x0000011,对应版本为17。

7.last_comp_version最后兼容版本

last_comp_version表示向后兼容的版本,17版本向后兼容16版本,所以last_comp_version的值为16。

8.boot_cpuid_phys 我们正在启动的物理CPU ID

cpu的id值,它的值应该与设备树文件中CPU节点下的reg属性值相等。boot_cpuid_phys为0。

9.size_dt_strings字符串块的大小

size_dt_strings表示strings block(字符串块)的大小。size_dt_strings的值为0×000000058。

size_dt_strings的偏移为Ox0000024c,大小为0×00000058,0×25C+58=2a4,所以可以知道strings block(字符串块)在dtb文件中的范围。如下图所示

10.size_dt_struct 结构块的大小

size_dt_struct表示structure blockl(结构块)的大小。size_dt_struct的值为0×00000214。

off_dt_struct的偏移值是0×00000038。所以结构块在dtb文件中的范围,如下图所示:0×00000038+0×00000214=24c

2.memory reservation block(内存预留块)

如果在dts文件中使用memreserve描述保留的内存,保留内存的大小就会在这部分保存。

memreserve的使用方法:

/memreserve/  <address> <length>;

eg

//reserve memory region 0x10000000 .0x4000
/memreserve/  0x10000000 0x4000;

在内存保留块的存储格式:

struct fdt_reserve_entry {
    uint64_t address; // 地址
    uint64_t size; // 大小
};

3.structure block(结构块)

结构块描述的是设备树的结构,也就是设备树的节点。那如何表示一个节点的开始和结束呢。

使用0x00000001表示节点的开始,然后跟上节点名字(根节点的名字用0表示),然后

使用0x00000003表示一个属性的开始(每表示一个节点,都要用0x00000003表示开始),

属性的名字和值用结构体表示。

struct fdt_property {
    uint32_t tag; // 标签
    uint32_t len; // 长度
    uint32_t nameoff; // 名称偏移量
    char data[0]; // 数据
};

len表示属性值的长度,nameoff表示属性名字在字符串块中的偏移。使用0x00000002表示

节点的结束。使用表示根节点的结束。也就是整个结构块的结束。

例子中以下节点在dtb中是如何表示的呢?

/ {
    model = "this is my devicethree!";
        #address-cells = <1>;
        #size-cells = <1>;
    chosen {
        bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";
    };

如下图所示:

4.strings block(字符串块)

字符串块用来存放属性的名字,比如compatible,reg等。通过分析dtb的头部,我们已经知道字符串块的位置,如model在dtb中的表示:

0x6D6F6465表示的是model的acell码,表示完一个字符串,用00结尾。


目录
相关文章
|
存储 数据库 Docker
Docker Hub和镜像仓库
Docker Hub 是 Docker 公司提供的官方公共 Docker 镜像注册表,允许用户存储、分享和获取 Docker 镜像。在 Docker Hub 上,你可以找到许多官方和社区维护的 Docker 镜像,这些镜像涵盖了各种常见的应用程序和服务,如数据库、Web 服务器、应用程序框架等。
6965 0
|
消息中间件 Java Kafka
Java消息队列总结只需一篇解决ActiveMQ、RabbitMQ、ZeroMQ、Kafka
  一、消息队列概述 消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构。
3666 0
|
6月前
|
人工智能 测试技术 开发者
聊聊OpenAI那份Codex内部指南,以及它给我的启发
OpenAI发布《如何使用Codex》揭秘工程师真实用法:AI不仅是代码补全,更是重构助手、测试生成器和新人导师。几分钟完成数小时工作,保护开发“心流”,提升效率惊人。这才是AI编程的正确打开方式!
719 1
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
这篇文章是关于如何在SpringBoot应用中整合Redis并处理分布式场景下的缓存问题,包括缓存穿透、缓存雪崩和缓存击穿。文章详细讨论了在分布式情况下如何添加分布式锁来解决缓存击穿问题,提供了加锁和解锁的实现过程,并展示了使用JMeter进行压力测试来验证锁机制有效性的方法。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
|
11月前
|
机器学习/深度学习 传感器 数据采集
可穿戴设备助力远程医疗:从数据监测到智能诊疗的技术变革
可穿戴设备助力远程医疗:从数据监测到智能诊疗的技术变革
489 3
|
Linux SoC
Linux设备树(DTS)介绍
**设备树(DTS)是Linux中用于描述硬件信息的文本文件,旨在减少内核与平台相关代码的耦合。DTS文件包含静态硬件配置,不支持动态变更。它被编译成DTB二进制文件,供内核在启动时解析以了解硬件布局。设备树解决了ARM体系结构代码维护的复杂性问题,通过解耦实现vendor修改的独立和共二进制目标。设备树overlay允许对配置进行增量修改,遵循特定规则,如dts覆盖dtsi,先引用后修改。调试时,可使用内置工具反编译dtb或dtbo映像为dts文本以检查内容。**
1410 7
|
JavaScript 调度
Vue事件总线(EventBus)使用指南:详细解析与实战应用
Vue事件总线(EventBus)使用指南:详细解析与实战应用
887 1
|
JSON 算法 数据挖掘
基于图论算法有向图PageRank与无向图Louvain算法构建指令的方式方法 用于支撑qwen agent中的统计相关组件
利用图序列进行数据解读,主要包括节点序列分析、边序列分析以及结合节点和边序列的综合分析。节点序列分析涉及节点度分析(如入度、出度、度中心性)、节点属性分析(如品牌、价格等属性的分布与聚类)、节点标签分析(如不同标签的分布及标签间的关联)。边序列分析则关注边的权重分析(如关联强度)、边的类型分析(如管理、协作等关系)及路径分析(如最短路径计算)。结合节点和边序列的分析,如子图挖掘和图的动态分析,可以帮助深入理解图的结构和功能。例如,通过子图挖掘可以发现具有特定结构的子图,而图的动态分析则能揭示图随时间的变化趋势。这些分析方法结合使用,能够从多个角度全面解读图谱数据,为决策提供有力支持。
679 0
|
Linux 调度
理解linux的CPU上下文切换
理解linux的CPU上下文切换
315 0