4. 设备树编译与反编译
设备树源文件(DTS)本身只是人类可读的文本描述,真正被内核解析的是二进制设备树块(DTB)。在跨平台迁移工程中,dtc(Device Tree Compiler)工具链是连接“可读描述”与“可执行数据”的核心桥梁。掌握编译与反编译,不仅能验证迁移后的设备树是否合法,还能通过反编译逆向分析原厂固件中的硬件配置,是迁移工作中最常用的手段之一。
一、dtc工具链与核心参数
dtc 通常随内核源码的 scripts/dtc 目录提供,也可通过发行版包管理器安装(如 apt install device-tree-compiler)。它支持三种主要工作模式:DTS→DTB 编译、DTB→DTS 反编译、以及 DTS 语法检查。常用参数如下:
| 参数 | 作用 | 典型场景 |
|---|---|---|
| -I dts / -I dtb | 指定输入格式 | 编译或反编译时明确源类型 |
| -O dtb / -O dts | 指定输出格式 | 决定生成二进制还是文本 |
| -o output | 指定输出文件 | 避免默认输出到 stdout |
| -@ | 生成符号节点(__symbols__) | 支持运行时 overlay 叠加 |
| -i include_dir | 添加头文件搜索路径 | 跨目录引用 .dtsi |
| -W no-unit_address_vs_reg | 关闭指定警告 | 抑制迁移中的非致命告警 |
二、DTS到DTB的编译过程
编译并非简单的文本转换,而是包含预处理、语法解析、语义检查、扁平化四个阶段。C 预处理器先处理 #include 与宏,dtc 再将树形结构编码为 FDT(Flattened Device Tree)格式,最终生成 DTB。典型命令如下:
# 基础编译
dtc -I dts -O dtb -o board.dtb board.dts
# 带头文件路径与符号节点
dtc -I dts -O dtb -@ -i include/ -o board.dtb board.dts
# 内核构建系统方式(推荐用于正式迁移)
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- dtbs
编译成功后,DTB 头部包含 magic(0xd00dfeed)、总大小、结构块偏移、字符串块偏移等字段。内核启动时由 bootloader 将该二进制块传入,内核再展开为 device_node 树。迁移时若目标平台 bootloader 对 DTB 大小或对齐有要求,需特别关注头部字段。
三、DTB到DTS的反编译方法
反编译是迁移工程中的“逆向侦察”手段。当拿到原厂固件或目标板 DTB 却缺少源码时,可用以下命令还原为可读文本:
# 反编译为 DTS
dtc -I dtb -O dts -o recovered.dts board.dtb
# 查看 DTB 头部信息
fdtdump board.dtb | head -40
# 从运行中的系统导出当前设备树
dtc -I fs -O dts -o live.dts /proc/device-tree
反编译结果会保留节点层级、reg 地址、compatible 字符串、中断号等关键信息,但注释、宏定义和 include 关系会丢失。迁移时应将反编译结果作为参考,重新整理为带 .dtsi 分层结构的源码,而不是直接用于生产。
四、常见编译错误与调试技巧
- 语法错误:缺少分号、大括号不匹配、属性名拼写错误。dtc 会给出文件名与行号,优先检查报错行上方。
- 未定义引用:使用
&label但对应节点未定义,或 .dtsi 未被包含。检查 include 路径与标签名。 - 地址/单元冲突:reg 属性长度与
#address-cells、#size-cells不匹配,导致解析异常。 - 重复节点:同一路径下节点名重复,dtc 会报 duplicate node name。
- 警告淹没:使用
-W no-xxx关闭非致命警告,聚焦真正错误。
dtc -I dts -O dts board.dts 做纯语法自检,不生成 DTB;再逐步加入 -@、-i 等参数定位问题。反编译得到的 DTS 可用于与迁移后源码做 diff,快速发现属性遗漏。
五、迁移场景复盘
某 ARM64 平台迁移中,原厂 DTB 反编译后发现 ethernet@fe300000 节点缺少 phy-mode 属性,而目标板原理图要求 RGMII。若直接使用原 DTB,网口无法工作。通过反编译对比、补充属性、重新编译并验证,最终解决。这说明:编译与反编译不仅是工具操作,更是迁移中“验证—对比—修正”闭环的关键环节。
掌握 dtc 工具链后,建议将编译命令固化为 Makefile 或脚本,配合 dtc -I dtb -O dts 做版本对比,形成可重复、可追溯的设备树迁移流程。