第3章:设备树编译与反编译:dtc工具的使用,从.dts到.dtb,从.dtb反编译回.dts
3.1 dtc工具到底是什么?
说实话,我刚接触设备树那会儿,最困惑的就是这个.dts和.dtb的关系。你想想看,我们辛辛苦苦写了一大堆.dts文件,板子怎么就不认呢?
其实道理很简单。.dts是给人看的文本文件,而.dtb是给机器吃的二进制文件。中间那个翻译官,就是dtc——Device Tree Compiler。我习惯叫它「设备树编译器」。
dtc的作用就两件事:
- 把.dts编译成.dtb(人→机器)
- 把.dtb反编译回.dts(机器→人)
我在项目中遇到过好几次这样的情况:拿到一块开发板,厂商只给了.dtb文件,没有源码。这时候怎么办?反编译啊!用dtc把.dtb还原成.dts,就能看懂人家是怎么配置的了。
3.2 编译:从.dts到.dtb
先说说最常用的编译操作。命令长这样:
dtc -I dts -O dtb -o my_board.dtb my_board.dts
参数解释一下:
-I dts:输入格式是.dts(文本)-O dtb:输出格式是.dtb(二进制)-o my_board.dtb:指定输出文件名- 最后一个参数:输入的源文件
嗯,这里要注意。如果你直接这么编译,大概率会报一堆警告。为什么?因为你的.dts里可能引用了其他.dtsi文件,或者用了某些宏定义。
我曾经在编译一个复杂的设备树时,忘了加-@选项,结果生成的.dtb里没有符号表,导致后续的overlay加载失败。折腾了我大半天才找到原因。
我个人习惯在编译时加上这几个选项:
dtc -I dts -O dtb -@ -H epapr -o my_board.dtb my_board.dts
-@:生成符号表,支持设备树叠加(overlay)-H epapr:指定phandle格式,兼容性更好
3.3 反编译:从.dtb回到.dts
反编译的命令更简单:
dtc -I dtb -O dts -o my_board_reverse.dts my_board.dtb
说白了就是把输入输出格式对调一下。但反编译出来的.dts和原始.dts会有差异,你想想看为什么?
因为编译过程中,dtc会做一些优化和转换:
- 注释全部丢失(这个没办法,二进制不存注释)
- 宏定义被展开(#include和#define都被解析掉了)
- 节点顺序可能调整(dtc会按地址排序)
- 标签(label)变成数字phandle
💡 实用技巧:
反编译时加个-s选项,可以保留一些排序信息,方便对比差异:
dtc -I dtb -O dts -s -o reverse.dts board.dtb
3.4 实战:我的一次反编译经历
记得有一次,客户反馈说某款ARM板子的网口不工作。我手头只有他们提供的.dtb文件,没有源码。
第一步,反编译:
dtc -I dtb -O dts -o debug.dts board.dtb
打开debug.dts一看,果然发现问题。以太网节点的phy-mode被设置成了rgmii-id,但实际硬件用的是rmii。这就是典型的设备树配置错误。
我修改了.dts文件,重新编译:
dtc -I dts -O dtb -o fixed.dtb debug_fixed.dts
烧进去,网口立马就通了。你看,反编译+修改+重新编译,三板斧解决问题。
3.5 常用选项速查表
| 选项 | 说明 | 我的建议 |
|---|---|---|
-I dts |
输入为.dts格式 | 编译时必用 |
-I dtb |
输入为.dtb格式 | 反编译时必用 |
-O dtb |
输出为.dtb格式 | 编译时必用 |
-O dts |
输出为.dts格式 | 反编译时必用 |
-@ |
生成符号表 | 建议默认加上 |
-H epapr |
使用epapr phandle格式 | 兼容性最好 |
-s |
排序输出节点 | 调试时很有用 |
-V |
显示dtc版本 | 确认工具版本 |
3.6 避坑指南
✅ 我的经验总结:
- 编译前先检查.dts语法:
dtc -I dts -O dtb -o /dev/null test.dts,只检查不输出 - 反编译后的.dts不要直接拿去用,要手动清理一下冗余信息
- 不同版本的dtc可能生成不同的.dtb,尽量用内核源码里的dtc
- 如果遇到
FATAL: Input tree has errors,先检查include路径
⚠️ 我曾经踩过的坑:
有一次我反编译了一个.dtb,修改后重新编译,结果板子起不来了。排查了半天才发现,原始.dtb是用旧版dtc编译的,而我用的新版dtc默认启用了某些新特性。从那以后,我养成了一个习惯:编译设备树时,一定用内核源码树里自带的dtc,版本匹配最安全。
3.7 小结
dtc这个工具,说白了就是设备树世界的「翻译官」。你写.dts给它,它给你.dtb;你给.dtb它,它给你.dts。掌握了编译和反编译,你就能在文本和二进制之间自由穿梭。
我个人觉得,反编译这个能力特别重要。因为在实际工作中,你拿到的往往不是源码,而是编译好的.dtb。能把它还原成可读的.dts,就等于拿到了硬件的「说明书」。下次遇到板子不工作,别急着怀疑硬件,先反编译看看设备树对不对。
嗯,这一章就到这里。下一章我们聊聊设备树的语法细节,那些让人头疼的#address-cells和#size-cells到底该怎么用。