3. 设备树编译与反编译

设备树源文件(.dts)是人类可读的文本描述,而内核引导时实际使用的是二进制格式的设备树二进制文件(.dtb)。DTC(Device Tree Compiler)是完成这两种格式之间转换的核心工具。掌握DTC的使用,是进行设备树开发与调试的基础。

3.1 DTC工具概述

DTC是设备树的官方编译器,通常集成在Linux内核源码的 scripts/dtc/ 目录下。它负责将 .dts 源文件编译为 .dtb 二进制文件,也能将 .dtb 反编译回 .dts 格式,便于逆向分析与调试。

工具获取: 在Ubuntu/Debian系统中,可通过 apt-get install device-tree-compiler 安装;在Yocto/Buildroot等嵌入式构建系统中,DTC通常作为主机工具自动编译。

3.2 DTS到DTB的编译流程

编译过程将文本格式的设备树源文件转换为内核可解析的扁平二进制格式。基本命令格式如下:

dtc -I dts -O dtb -o output.dtb input.dts

参数说明:

参数 含义 示例
-I dts 指定输入格式为DTS源文件 输入文本格式
-O dtb 指定输出格式为DTB二进制 输出二进制格式
-o 指定输出文件名 output.dtb
-@ 生成可叠加的DTB(支持插件) 用于设备树覆盖
-W no-unit_address_vs_reg 忽略特定警告 减少编译噪音
实践案例: 编译一个包含GPIO和I2C子节点的设备树:
dtc -I dts -O dtb -o myboard.dtb myboard.dts -W no-unit_address_vs_reg
若编译成功,终端无错误输出;若存在语法错误,DTC会报告行号和错误类型。

3.3 DTB到DTS的反编译流程

反编译用于从已生成的DTB文件还原出可读的DTS源码,常用于分析现有设备树或调试硬件兼容性问题。基本命令格式:

dtc -I dtb -O dts -o output.dts input.dtb

反编译时,DTC会尝试恢复原始结构,但会丢失原始DTS中的注释和部分宏定义。常用选项:

  • -I dtb:输入为二进制DTB格式
  • -O dts:输出为文本DTS格式
  • -s:在输出中显示节点排序后的结构
  • -f:强制覆盖输出文件
注意事项: 反编译得到的DTS中,所有标签(label)和引用(&label)会被展开为绝对路径形式。例如 &i2c1 会变成 /soc/i2c@... ,可读性下降,但结构完整。

3.4 编译与反编译流程示意图

下图展示了DTS与DTB之间的双向转换关系,以及DTC在其中的核心作用:

DTC 编译与反编译流程 DTS 源文件 文本格式 .dts / .dtsi DTB 二进制文件 二进制格式 .dtb 编译 -I dts -O dtb 反编译 -I dtb -O dts 内核引导加载 说明: 编译:DTS → DTB,用于内核引导;反编译:DTB → DTS,用于调试分析。

3.5 常用编译选项与调试技巧

DTC提供了丰富的选项来控制编译行为,以下为开发中常用的选项列表:

选项 功能描述 使用场景
-V 17 指定DTB版本为17(当前标准版本) 确保兼容性
-@ 生成符号表,支持设备树覆盖 模块化设备树
-H epapr 使用ePAPR标准布局 PowerPC架构
-W no-... 关闭特定警告 减少编译输出
-E no-... 关闭特定错误检查 快速原型验证
-O asm 输出汇编格式(.S) 特殊调试需求
调试技巧: 使用 dtc -I dtb -O dts -s input.dtb 可以输出排序后的设备树结构,便于快速查看节点层级关系。结合 grep 命令可快速定位特定节点:
dtc -I dtb -O dts -s myboard.dtb | grep -A 10 "i2c"

3.6 设备树包含文件与预处理

实际项目中,DTS文件通常通过 #include 引入头文件(.dtsi 或 .h),这些头文件定义了SoC的通用节点和宏。DTC在编译前会调用C预处理器(cpp)处理这些包含指令。

手动调用预处理器进行编译的完整命令:

cpp -nostdinc -I include -undef -x assembler-with-cpp input.dts | dtc -I dts -O dtb -o output.dtb -

更简洁的方式是使用内核构建系统提供的 make dtbs 命令,它会自动处理依赖关系和预处理步骤。

常见错误: 如果编译时出现 FATAL ERROR: Unable to parse input tree,通常是因为DTS文件中存在语法错误,如缺少分号、括号不匹配或属性值格式错误。使用 dtc -I dts -O dts input.dts 进行语法检查,可以快速定位问题行。

3.7 反编译实战:从DTB提取设备树信息

当拿到一个现成的DTB文件(如从运行中的系统提取),反编译是了解硬件配置的首选方法。以下是从运行系统提取并反编译设备树的完整流程:

  1. 提取DTB: 从 /sys/firmware/devicetree/base 复制或使用 dtc -I fs -O dtb -o extracted.dtb /sys/firmware/devicetree/base
  2. 反编译: dtc -I dtb -O dts -o extracted.dts extracted.dtb
  3. 查看结构: dtc -I dtb -O dts -s extracted.dtb | less

反编译后的DTS文件虽然丢失了原始注释,但完整保留了所有节点、属性和值,是逆向分析硬件配置的宝贵资料。

从运行系统提取设备树流程 /sys/firmware/ devicetree/base dtc -I fs -O dtb extracted.dtb dtc -I dtb -O dts extracted.dts 应用场景: 调试硬件兼容性问题、分析第三方设备树配置、验证设备树修改效果、学习参考板卡硬件布局。

3.8 本章小结

DTC工具是设备树开发的核心工具链,掌握其编译与反编译操作是进行嵌入式Linux驱动开发的基本功。通过本章学习,应掌握以下关键点:

  • DTS到DTB的编译命令及常用选项
  • DTB到DTS的反编译命令及注意事项
  • 预处理包含文件(.dtsi / .h)的编译方法
  • 从运行系统提取设备树并进行反编译的实战流程
  • 常见编译错误的排查与解决