上一章我们讲了设备树的历史背景和基本概念,现在手里应该有一个模糊的概念了:设备树是一种描述硬件的数据结构,内核通过它来了解板子上有什么设备。
这一章,我们先简单了解一下DTC编译器是如何把.dts文本变成内核能识别的.dtb二进制的,然后重点讲解设备树的语法规则 ——看到任何一个.dts文件,都能一眼看穿它的结构和含义。
DTC编译器:文本到二进制的魔法
dts / dtsi / dtb三兄弟
在设备树的生态里,你会经常看到三种文件后缀,搞清楚它们的区别是第一步:
- .dts
设备树源文件(Device Tree Source),给人看的文本格式。内核不会直接读取它,必须先编译。
- .dtsi
设备树头文件(Device Tree Source Include),类似C语言中的.h文件,包含通用的硬件定义,被多个.dts引用。永远不要直接修改厂商的.dtsi文件!
- .dtb
设备树二进制文件(Device Tree Blob),内核真正加载的格式,由DTC编译器从.dts生成。
DTC工作原理
DTC(Device Tree Compiler)本质上就是一个编译器,它的源码在内核的scripts/dtc目录下。和所有编译器一样,它分为三个阶段:
(1)词法分析
dtc-lexer.l:把文本切分成Token,比如把compatible = "fsl,imx6ull";识别为标识符、赋值号、字符串和分号。
(2)语法分析
dtc-parser.y:根据文法规则,把Token流构建成内存中的树形结构。
(3)代码生成
flattree.c:遍历语法树,“拍扁”成线性的DTB二进制格式。
DTB二进制结构
DTB文件由四部分组成:
+------------------+ | fdt_header | 文件头(40字节,含魔术数字 0xd00dfeed) +------------------+ | memory reserve | 内存保留区域 +------------------+ | structure block| 结构块(节点和属性,用 FDT_BEGIN_NODE / FDT_PROP 等标记) +------------------+ | strings block | 字符串块(属性名,共享存储以节省空间) +------------------+DTB使用大端序(Big Endian),所以用hexdump看到的魔术数字是d0 0d fe ed。
常用命令
# 编译 DTS → DTB dtc -I dts -O dtb -o output.dtb input.dts # 反编译 DTB → DTS(调试利器) dtc -I dtb -O dts /boot/imx6ull-14x14-evk.dtb > current.dts # 查看完整 DTB 信息 fdtdump output.dtb在内核构建中,make dtbs会根据arch/arm/boot/dts/Makefile中的配置自动选择并编译对应的 DTS文件。
以上就是DTC和DTB的核心要点。理解了编译链路,接下来我们进入正题 ——设备树的语法。
更多内容请看下回。