设备树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结尾。


目录
相关文章
|
编解码 Linux
Linux MIPI DSI驱动调试笔记-设备树DCS格式序列之配置LCD初始化代码(二)
Linux MIPI DSI驱动调试笔记-设备树DCS格式序列之配置LCD初始化代码(二)
1416 0
ENVI_IDL:如何读取HDF4文件和HDF5文件的数据集和属性?
参考Documentation Center (l3harrisgeospatial.com) 由于时间和精力,这里并没有对其中的函数进行详细的说明,只是介绍了函数作用以及用法。
225 0
|
Linux Windows
PE格式:实现ELF结构解析工具
ELF文件格式,是一个开放的可执行文件和链接文件格式,其主要工作在Linux系统上,是一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件,ELF文件格式类似于PE格式,但比起PE结构来ELF结构显得更加的简单,Linux文件结构相比于Windows结构来说简单一些.
245 0
|
存储 编解码
ENVI_IDL:读取OMI数据(HDF5)并输出为Geotiff文件+详细解析
ENVI_IDL:读取OMI数据(HDF5)并输出为Geotiff文件+详细解析
408 1
ENVI_IDL:(批量处理)如何对HDF5文件进行GLT文件的创建并进行几何校正最终输出为IMG格式?
ENVI_IDL:(批量处理)如何对HDF5文件进行GLT文件的创建并进行几何校正最终输出为IMG格式?
177 0
|
存储
ENVI_IDL: 创建HDF5文件并写入数据(以将Geotiff文件写入HDF文件为例) + 详细解析
ENVI_IDL: 创建HDF5文件并写入数据(以将Geotiff文件写入HDF文件为例) + 详细解析
186 0
|
Linux 编译器 SoC
内核笔记](一)——设备树的概述(硬件、目标、效果、文件类型)
内核笔记](一)——设备树的概述(硬件、目标、效果、文件类型)
281 0
内核笔记](一)——设备树的概述(硬件、目标、效果、文件类型)
|
Linux 数据安全/隐私保护
使用ofd6x工具解析elf文件
使用ofd6x工具解析elf文件
221 0
使用ofd6x工具解析elf文件
|
编译器 Android开发
【Android 逆向】ELF 文件格式 ( ELF 文件头 | ELF 文件头标志 | ELF 文件位数 | ELF 文件大小端格式 )(二)
【Android 逆向】ELF 文件格式 ( ELF 文件头 | ELF 文件头标志 | ELF 文件位数 | ELF 文件大小端格式 )(二)
187 0
【Android 逆向】ELF 文件格式 ( ELF 文件头 | ELF 文件头标志 | ELF 文件位数 | ELF 文件大小端格式 )(二)
|
Android开发
【Android 逆向】ELF 文件格式 ( ELF 文件头 | ELF 文件头标志 | ELF 文件位数 | ELF 文件大小端格式 )(一)
【Android 逆向】ELF 文件格式 ( ELF 文件头 | ELF 文件头标志 | ELF 文件位数 | ELF 文件大小端格式 )(一)
173 0
【Android 逆向】ELF 文件格式 ( ELF 文件头 | ELF 文件头标志 | ELF 文件位数 | ELF 文件大小端格式 )(一)