Device Tree (二) - dtb格式

dtb作为二进制文件被加载到内存中,然后由内核读取并进行解析,如果对dtb文件的格式不了解,那么在看设备树解析相关的内核代码时将会寸步难行,而阅读源代码才是了解设备树最好的方式,所以,如果需要更透彻的了解设备树解析的细节,第一步就是需要了解设备树的格式。

1,DTB整体结构

经过Device Tree Compiler编译,Device Tree source file变成了Device Tree Blob(又称作flattened device tree)的格式。Device Tree Blob的数据组织如下图所示:

2,DTB header

struct fdt_header结构体的定义如下:

struct fdt_header {fdt32_t magic;             /* 用来识别DTB的。通过这个magic,kernel可以确定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在内存中的位置 */
};

3,memory 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 0x0000a800,fdt_reserve_entry的结构体成员address = 0x00000000,size = 0x0000a800。

4, device tree structure block的格式描述

device tree structure block区域是由若干的分片组成,每个分片开始位置都是保存了token,以此来描述该分片的属性和内容。共计有5种token:

(1)FDT_BEGIN_NODE (0x00000001)。该token描述了一个node的开始位置,紧挨着该token的就是node name(包括unit address)

(2)FDT_END_NODE (0x00000002)。该token描述了一个node的结束位置。

(3)FDT_PROP (0x00000003)。该token描述了一个property的开始位置,该token之后是两个u32的数据,分别是length和name offset。length表示该property value data的size。name offset表示该属性字符串在device tree strings block的偏移值。length和name offset之后就是长度为length具体的属性值数据。

(4)FDT_NOP (0x00000004)。

被解析设备树的程序忽略,可用于覆盖其他属性,以删除它。

(5)FDT_END (0x00000009)。该token标识了一个DTB的结束位置。

单个节点在structure block的存储格式如下图所示(子节点的存储格式也是一样):

5, device tree strings block的格式描述

在dtb中有大量的重复字符串,比如"model","compatile"等等,为了节省空间,将这些字符串统一放在某个地址,需要使用的时候直接使用索引来查看。

需要注意的是,属性部分格式为key = value,key部分被放置在strings部分,而value部分的字符串并不会放在这一部分,而是直接放在structure中。

6,dtb文件解析示例

编译生成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";};memory@80000000 {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

7,Device 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_PROP;len为属性值的长度(包括‘\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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/740473.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】哈希表(Hash Table)

文章目录 一&#xff1a;哈希表&#xff08;Hash Table&#xff09;1.1 简介1.2 可以将算法思想分为两个部分1.3 相关术语1.4 性质 二&#xff1a;哈希冲突2.1 什么是哈希冲突2.2 为何要避免哈希冲突2.3 如何避免哈希冲突2.4 如何减少哈希冲突2.4.1 直接地址法2.4.1 除留余数法…

C语言入门学习 --- 7.结构体

文章目录 第七章结构体1.结构体的声明1.1结构的基础知识1.2结构的声明1.3结构成员的类型1.4结构体变量的定义和初始化 2.结构体成员的访问2.1结构体变量访问成员2.2结构体指针访问指向变量的成员 3.结构体传参配套练习&#xff1a; 第七章结构体 1.结构体类型的声明 2.结构体初…

工具篇--分布式定时任务springBoot 整合 elasticjob使用(3)

文章目录 前言一、Springboot 整合&#xff1a;1.1 引入jar&#xff1a;1.2 配置zookeeper 注册中心&#xff1a;1.3 定义job 业务类&#xff1a;1.4 job 注册到zookeeper&#xff1a;1.5 项目启动&#xff1a;1.5.1 zookeeper 注册中心实例&#xff1a;1.5.2 任务执行日志输出…

Ubuntu 14.04:PaddleOCR基于PaddleServing的在线服务化部署(失败)

一、 二、安装 注&#xff1a; 安装 PaddleOCR 2.3 。 因为 PaddleOCR 2.4 的 推荐环境 PaddlePaddle > 2.1.2。 https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.4/doc/doc_ch/environment.md 安装前的环境准备 在使用Paddle Serving之前&#xff0c;需要完…

flink重温笔记(十五): flinkSQL 顶层 API ——实时数据流转化为SQL表的操作

Flink学习笔记 前言&#xff1a;今天是学习 flink 的第 15 天啦&#xff01;学习了 flinkSQL 基础入门&#xff0c;主要是解决大数据领域数据处理采用表的方式&#xff0c;而不是写复杂代码逻辑&#xff0c;学会了如何初始化环境&#xff0c;鹅湖将流数据转化为表数据&#xff…

数据结构和算法:复杂度分析

算法效率评估 时间效率&#xff1a;算法运行速度的快慢。 空间效率&#xff1a;算法占用内存空间的大小。 效率评估方法主要分为两种&#xff1a;实际测试、理论估算 实际测试问题&#xff1a; 1.难以排除测试环境的干扰因素。 硬件配置会影响算法的性能。需要在各种机器上进…

Web 常用的 扩展开发框架

当谈到提升浏览器功能和用户体验时&#xff0c;浏览器扩展成了一股强大的力量&#xff0c;备受用户青睐。在众多的Web扩展开发框架中&#xff0c;WXT和Plasmo凭借其丰富的工具和特性&#xff0c;以及简化的开发流程&#xff0c;成为开发者们的首选。在本文中&#xff0c;我们将…

【嵌入式DIY实例】-DIY锂电池电压检测表

DIY锂电池电压检测表 文章目录 DIY锂电池电压检测表1、直流电压检测传感器介绍2、硬件准备3、代码实现4、OLED显示在电子应用中,通常需要使用到电池,电源管理是必不可少的部分。本文将详细介绍如何使用一个0-25V的直流电压传感器来检测锂电池的电压。 1、直流电压检测传感器介…

数据分析-Pandas如何画自相关图

数据分析-Pandas如何画自相关图 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表&#x…

C#,文字排版的折行问题(Word-wrap problem)的算法与源代码

1、英文的折行问题 给定一个单词序列&#xff0c;以及一行中可以输入的字符数限制&#xff08;线宽&#xff09;。 在给定的顺序中放置换行符&#xff0c;以便打印整齐。 假设每个单词的长度小于线宽。 像MS word这样的文字处理程序负责放置换行符。 这个想法是要有平衡的线条。…

Android kotlin开启协程的几种方式

在Android开发中&#xff0c;使用Kotlin协程&#xff08;coroutines&#xff09;可以极大地简化异步编程的复杂性&#xff0c;提高代码的可读性和可维护性。以下是几种在Android Kotlin项目中开启协程的常用方式&#xff1a; 1. 使用GlobalScope.launch 这是最简单直接的开启…

2024.3.12-408学习笔记-C-C++

1、引用& #include <stdio.h>void modify_pointer(int* &p1, int* q1) {p1 q1; }int main() {int* p NULL;int i 10;int* q &i;modify_pointer(p, q);printf("after modify_pointer *p %d\n", *p);//after modify_pointer *p 10return 0; }…

专业140+总分430+西南交通大学924信号与系统考研经验电子信息与通信工程,真题,大纲,参考书

今年报考西南交通大学&#xff0c;考研分数专业课924信号与系统140&#xff0c;总分430&#xff0c;各门分数都还是比较均衡&#xff0c;经过一年的复习&#xff0c;有得有失&#xff0c;总结一下自己的复习经历&#xff0c;希望给大家有点帮助&#xff0c;在复习中做的更好&am…

Android 使用AIDL HAL

生成的目录结构 以audioControl 为例: 首先编写的是aidl文件。 其文件目录结构是:── android │ └── hardware │ └── automotive │ └── audiocontrol │ ├── AudioFocusChange.aidl │ ├── AudioGainConf…

LeetCode 1409.查询带键的排列

给定一个正整数数组 queries &#xff0c;其取值范围在 1 到 m 之间。 请你根据以下规则按顺序处理所有 queries[i]&#xff08;从 i0 到 iqueries.length-1&#xff09;&#xff1a; 首先&#xff0c;你有一个排列 P[1,2,3,…,m]。 对于当前的 i &#xff0c;找到 queries[i]…

Sklearn基本算法

sklearn&#xff08;Scikit-learn&#xff09;是一个非常流行的Python机器学习库&#xff0c;它提供了一系列简单高效的算法和工具&#xff0c;适用于各种机器学习任务。下面是一些基本的机器学习算法类别和对应的常用算法&#xff1a; 分类算法 逻辑回归&#xff08;Logisti…

请列出60个Python热点面试题目

以下是60个Python热点面试题目&#xff0c;涵盖了Python基础知识、数据类型、面向对象编程、函数和模块、文件操作、错误处理、并发编程、数据库操作、网络编程、框架和库等多个方面&#xff1a; 谈谈你对Python语言的理解&#xff0c;它有哪些主要特点&#xff1f;Python有哪…

钉钉平台“智”领宠物界,开启萌宠智能新时代!

在当前数字化转型的浪潮中&#xff0c;钉钉用便捷的数字化解决方案推动了宠物业界的智能升级。一家宠物用品公司采用无雀科技数字化管理系统&#xff0c;与钉钉平台结合&#xff0c;解决了小型企业普遍存在的财务管理不清晰、业务流程不规范、客户信息核对繁琐等痛点问题。 针对…

html5cssjs代码 012 我的像册

html5&css&js代码 012 我的像册 一、代码二、解释 这段HTML代码定义了一个简单的网页&#xff0c;实现了一个简洁、响应式的图片相册页面。 一、代码 <!DOCTYPE html> <html lang"zh-cn"> <head><title>编程笔记 html5&css&…

AHU 汇编 实验六

一、实验名称&#xff1a;实验6 输入一个16进制数&#xff0c;把它转换为10进制数输出 实验目的&#xff1a; 培养汇编中设计子程序的能力 实验过程&#xff1a; 源代码&#xff1a; data segmentbuff1 db Please input a number(H):$buff2 db 30,?,30 dup(?),13,10buff3 …