第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到底该怎么用。