0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux设备树详解(二) DTB文件格式

ebaina 来源:ebaina 作者:ebaina 2023-08-10 16:02 次阅读

一、背景

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

所以,如果需要更透彻的了解设备树解析的细节,第一步就是需要了解设备树的格式。

二、dtb的由来

设备树的一般操作方式是:开发人员根据开发需求编写dts文件,然后使用dtc将dts编译成dtb文件。

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

dts文件是文本格式的文件,而dtb是二进制文件,在linux启动时被加载到内存中,接下来我们需要来分析设备树dtb文件的格式。

三、dts和dtb文件的

编译.dts文件生成DTB文件:

dtc -I dts -O dtb -o output.dtb input.dts

汇编DTB文件生成.dts文件:

dtc -I dtb -O dts -o output.dts input.dtb

四、dtb格式总览

dtb的格式是这样的:

wKgZomTUmKWADopgAABaAVU3oUE911.png

4.1dtbheader

但凡涉及到数据的记录,就一定会有一个总的描述部分,就像磁盘的超级块,书的目录,dtb当然也不例外,这个描述头部就是dtb的header部分,通过这个header部分,用户可以快速地了解到整个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 */ };

各字段含义如下:

magic

设备树的魔数,魔数其实就是一个用于识别的数字,表示设备树的开始,linuxdtb的魔数为0xd00dfeed.

totalsize

这个设备树的size,也可以理解为所占用的实际内存空间。

off_dt_struct

offsettodt_struct,表示整个dtb中structure部分所在内存相对头部的偏移地址

off_dt_strings

offsettodt_string,表示整个dtb中string部分所在内存相对头部的偏移地址

off_mem_rsvmap

offsettomemoryreservemap,dtb中memoryreservemap所在内存相对头部的偏移地址,

version

设备树的版本,截至目前的最新版本为17.

last_comp_version

最新的兼容版本

boot_cpuid_phys

这部分仅在版本2中存在,后续版本不再使用。

size_dt_strings

表示整个dtb中string部分的大小

size_dt_struct

表示整个dtb中struct部分的大小

alignmentgap

中间的alignmentgap部分表示对齐间隙,它并非是必须的,它是否被提供以及大小由具体的平台对数据对齐和的要求以及数据是否已经对齐来决定。

memoryreservemap

memoryreservemap:描述保留的内存部分,这个map的数据结构是这样的:

{ uint64_t physical_address; uint64_t size; }

这部分存储了此结构的列表,整个部分的结尾由一个数据为0的结构来表示(即physical_address和size都为0,总共16字节)。

这一部分的数据并非是节点中的memory子节点,而是在设备开始之前(也就是第一个花括号之前)定义的,例如:

/dts-v1/ /memreserve/ 0x10000000 0x100000 /*在结构提中的表示为 physical_address=0x10000000,size=0x100000 */ { ... }

这一部分的作用是告诉内核哪一些内存空间需要被保留而不应该被系统覆盖使用,因为在内核启动时常常需要动态申请大量的内存空间,只有提前进行注册,用户需要使用的内存才不会被系统征用而造成数据覆盖。

值得一提的是,对于设备树而言,即使不指定保留内存,系统也会默认为设备树保留相应的内存空间。

同时,这一部分需要64位(8字节)对齐。

4.2device-treestructure

device-treestructure:每个节点都会被描述为一个struct,节点之间可以嵌套,因此也会有嵌套的struct。

structure的的结构是这样的:

一个node开始信号,OF_DT_BEGIN_NODE,内容为:0x00000001

对于版本1-3而言,这一部分是节点的全路径,以/开头,而对于版本16及以上,这部分只是unitname(root除外,它没有unitname),unitname是以0结尾的字符串

可选的对齐字节

对于每个属性字段:

如果有子节点,递归地对子节点进行描述。

节点结束信号,OF_DT_END_NODE,数据为0x00000002.

每个节点的信息都按照上述结构被描述,需要注意的是,所有用于描述一个特定节点的属性都必须在任何子节点之前定义,虽然设备树的层次结构不会因此产生二义性,但是linuxkernel的解析程序要求这么做。

4.3device-treestrings

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

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

五、dtb文件解析示例

光说不练假把式,下面我就使用一个简单的示例来剖析dtb的文件格式。

下述示例仅仅是一个演示demo,不针对任何平台,为了演示方便,编写了一个非常简单的dts文件。

/dts-v1/; / { compatible = "hd,test_dts", "hd,test_xxx"; #address-cells = < 0x1 >; #size-cells = < 0x1 >; model = "HD test dts"; chosen { stdout-path = "/ocp/serial@ffff"; }; memory@80000000 { device_type = "memory"; reg = < 0x80000000 0x10000000 >; }; led1:led@2000000 { compatible = "test_led"; #address-cells = < 0x1 >; #size-cells = < 0x1 >; reg = < 0x200 0x4 >; }; };

编译当前dts文件,获取对应的dtb文件。

鉴于dtb文件为二进制文件,普通编辑器打开显示乱码,我们使用ultraEdit查看,它将数据以16进制形式显示:

wKgZomTUmW-AFGDEAAiLY7gzX50799.png

整个头部为40字节,16进制为0x28,从头部信息中off_mem_rsvmap部分可以得到,reservememory起始地址为0x28,上文中提到,这一部分使用一个16字节的struct来描述,以一个全为0的struct结尾。

后16字节全为0,可以看出,这里并没有设置reservememory。

structure部分

上文回顾:每一个属性都是以key=value的形式来描述,value部分可选。

偏移地址来到0x00000038(0x28+0x10),接下来8个字节为00000003,根据上述structure中的描述,这是OF_DT_PROP,即标示属性的开始。

接下来4字节为00000018,表明该属性的value部分size为24字节。

接下来4字节是当前属性的key在string部分的偏移地址,这里是00000000,由头部信息中off_dt_strings可以得到,string部分的开始为00000174,偏移地址为0,所以对应字符串为"compatible"。

之后就是value部分,这部分的数据是字符串,可以直接从图片右侧栏看出,总共24字节的字符串"hd,test_dts","hd,test_xxx",因为字符串之间以0结尾,所以程序可以识别出这是两个字符串。

可以看出,到这里,compatible="hd,test_dts","hd,test_xxx";这个属性就被描述完了,对于属性的描述还是非常简单的。

按照固有的规律,接下来就是对#address-cells=<0x1>的解析,然后是#size-cells=<0x1>...

然后就是递归的子节点chosen,memory@80000000等等都是按照上文中提到的structure解析规则来进行解析,最后以00000002结尾。

与根节点不同的是,子节点有一个unitname,即chosen,memory@80000000这些名称,并非节点中的.name属性。

而整个结构的结束由00000009来描述。

一般而言,在32位系统中,dtc在编译dts文件时会自动考虑对齐问题,所以对于设备树的对齐字节,我们只需要有所了解即可,并不会常接触到。

文章来源:易百纳技术社区

https://www.ebaina.com/articles/140000016352

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    10991

    浏览量

    206742
收藏 人收藏

    评论

    相关推荐

    stm32mp1-seeed-npi-full.dtb设备

    stm32mp1-seeed-npi-full.dtb这个设备。直接修改uEnv.txt文件,此文件会在uboot引导
    发表于 08-03 06:06

    如何编译设备Linux内核镜像文件

    安装Linux内核源码,清理Linux内核,配置Linux内核照着实验指导书上敲命令就完事了配置Linux内核的这一步骤,可以跳过:2.编译设备
    发表于 12-20 07:11

    linux设备详解

    linux设备详解 2003 年毕业于中国科学技术大学,电子专业、软件专业...
    发表于 12-23 08:16

    Linux内核的设备DTS使用方法详解

    dtb文件就是真正的设备;dts:一般情况下,一个dts代表公司的具体某一个产品,适用于同一套源码内适配不同的公司产品,而每次编译的时候只编译与该dts有关的信息。dtsi: dt
    发表于 05-06 16:14

    如何光绘输出AutoCAD文件格式

    教你光绘输出AutoCAD文件格式
    发表于 06-07 15:16 36次下载

    .mpp文件格式打开软件下载

    .mpp文件格式打开
    发表于 07-07 13:14 2517次下载

    数码相机伴侣的文件格式

    数码相机伴侣的文件格式              文件格式指的是数码相机伴侣独特的文件系统结构在
    发表于 12-23 10:05 823次阅读

    GIF图形文件格式文档

    GIF图形文件格式文档 GIF图形文件格式文档 GIF图形文件格式文档
    发表于 05-24 10:53 2次下载

    GIF文件格式详解

    GIF文件格式详解 GIF文件格式详解 GIF文件格式详解
    发表于 05-24 10:53 2次下载

    编译设备树dts为dtb,制作根文件系统

    : -I是输入文件格式,在本文中是dts -O是目标文件格式,在本文中是dtb -o是目标文件路径 最后一个参数是输入文件路径 编译之后会在
    发表于 02-08 16:59 2088次阅读

    了解在Linux下可执行文件格式

    Linux下面,目标文件、共享对象文件、可执行文件都是使用ELF文件格式来存储的。程序经过编译之后会输出目标
    发表于 05-15 08:49 1771次阅读

    Linux下可执行文件格式

    Linux支持的可执行文件主要有:Coff,elf,flat,类似Windows的.exeCoff文件格式  Common Object File Format,最早与uclinux
    发表于 04-02 14:46 1371次阅读

    Linux设备树原始dtb格式

    要的。 1、设备树原始 dtb 格式 在如下目录,fdt 就是我们的 设备树*.dtb文件 /s
    的头像 发表于 07-30 15:22 515次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>设备</b>树原始<b class='flag-5'>dtb</b><b class='flag-5'>格式</b>

    Linux设备树目录结构dtb格式

    要的。 设备树目录结构 dtb 格式 /sys/firmware/devicetree 以目录结构程现的 dtb 文件, 根节点对应 bas
    的头像 发表于 07-30 15:25 450次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>设备</b>树目录结构<b class='flag-5'>dtb</b><b class='flag-5'>格式</b>

    WAV文件格式详解

    WAV是微软公司开发的一种音频格式文件,用于保存Windows平台的音频信息资源,它符合资源互换文件格式(Resource Interchange File Format,RIFF)文件规范。标准
    的头像 发表于 10-21 09:52 2193次阅读
    WAV<b class='flag-5'>文件格式</b><b class='flag-5'>详解</b>