作者信息
作者:彭东林
邮箱:pengdonglin137@163.com
1、反编译设备树
在设备树学习的时候,如果可以看到最终生成的设备树的内容,对于我们学习设备树以及分析问题有很大帮助。这里我们需要使用设备树生成工具dtc的反编译功能
root@pengdl-VirtualBox:~/tq2440/Linux/linux-4.0.# ./scripts/dtc/dtc -h
Usage: dtc [options] <input file> Options: -[qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv]
-q, --quiet
Quiet: -q suppress warnings, -qq errors, -qqq all
-I, --in-format <arg>
Input formats are:
dts - device tree source text
dtb - device tree blob
fs - /proc/device-tree style directory
-o, --out <arg>
Output file
-O, --out-format <arg>
Output formats are:
dts - device tree source text
dtb - device tree blob
asm - assembler source
-V, --out-version <arg>
Blob version to produce, defaults to %d (for dtb and asm output)
-d, --out-dependency <arg>
Output dependency file
-R, --reserve <arg>
tMake space for <number> reserve map entries (for dtb and asm output)
-S, --space <arg>
Make the blob at least <bytes> long (extra space)
-p, --pad <arg>
Add padding to the blob of <bytes> long (extra space)
-b, --boot-cpu <arg>
Set the physical boot cpu
-f, --force
Try to produce output even if the input tree has errors
-i, --include <arg>
Add a path to search for include files
-s, --sort
Sort nodes and properties before outputting (useful for comparing trees)
-H, --phandle <arg>
Valid phandle formats are:
legacy - "linux,phandle" properties only
epapr - "phandle" properties only
both - Both "linux,phandle" and "phandle" properties
-W, --warning <arg>
Enable/disable warnings (prefix with "no-")
-E, --error <arg>
Enable/disable errors (prefix with "no-")
-h, --help
Print this help and exit
-v, --version
Print version and exit
假设我们最终的设备树文件是:arch/arm/boot/dts/s3c2416-smdk2416.dtb
./scripts/dtc/dtc -I dtb -O dts -o output.dts arch/arm/boot/dts/s3c2416-smdk2416.dtb
输出文件output.dts就是反汇编的结果,他就是实际生成的设备树,当然也可以重新将生成的dts文件在编译成dtb文件:
./scripts/dtc/dtc -I dts -O dtb -o s3c2416-smdk2416.dtb output.dts
2、分析工具fdtdump
在Linux的scripts/dtc目录下除了提供dtc工具外,还提供了一个叫做fdtdump的工具,对于分析设备树也非常有帮助。
用法:
fdtdump -h
Usage: fdtdump [options] <file> Options: -[dshV]
-d, --debug Dump debug information while decoding the file
-s, --scan Scan for an embedded fdt in file
-h, --help Print this help and exit
-V, --version Print version and exit
使用范例:
fdtdump -sd vexpress-v2p-ca9.dtb | tee vexpress.dts.debug
看看输出的文件:
vexpress-v2p-ca9.dtb: found fdt at offset
/dts-v1/;
// magic: 0xd00dfeed
// totalsize: 0x2e9c (11932)
// off_dt_struct: 0x38
// off_dt_strings: 0x2bb8
// off_mem_rsvmap: 0x28
// version: 17
// last_comp_version: 16
// boot_cpuid_phys: 0x0
// size_dt_strings: 0x2e4
// size_dt_struct: 0x2b80 // 0038: tag: 0x00000001 (FDT_BEGIN_NODE)
/ {
// 0040: tag: 0x00000003 (FDT_PROP)
// 2bb8: string: model
// 004c: value
model = "V2P-CA9";
可以看到,其中这个工具会同时把分析语句和原始文件打印出来,其中 // 后输出的是分析语句,其他的是原始语句。对分析Linux内核启动时遍历展开设备树镜像很有帮助。
3、Linux配置,支持设备树
make menuconfig ---> Boot options ---> Flattened Device Tree support
4、Linux 编译设备树
可以看看arch/arm/boot/dts/Makefile中你要的那个设备树的dtb文件是否配置上了。
make dtbs
5、从Linux内核代码中编译设备树的工具dtc
在内核源码目录下提供了dtc工具的源码实现, 下面是生成这个工具的命令:
make scripts
6、删除设备树属性的方法
有时我们有这样的需求,需要删除设备树的某些属性, 但是我们又不想修改设备树源文件,那么可以利用delete-property方法。
/ {
... ...
demo1: demo1 {
compatible = "demo1";
property1 = <>;
property2;
property3 = <>;
property4;
};
}; &demo1 {
/delete-property/property2;
/delete-property/property3;
};
编译完成后,执行反编译可以看到property2和property3已经消失了:
demo1 {
compatible = "demo1";
property1 = <0x1>;
property4;
};
7、两个内核新增的设备树调试工具
- ./scripts/dtc/dt_to_config
可以根据传入的设备树解析出每个节点对应那些驱动以及内核是否已经配置,甚至可以通过传递--config-format来直接修改.config文件,如果嫌节点的路径过长,可以传递参数--short-name,用法示例:
# 这里的--include-suspec用于解析设备树中的include字段
$./scripts/dtc/dt_to_config arch/arm/boot/dts/s3c2440-tq2440-dt.dts --include-suspect --config ./.config
-dDc-E-Hx---- : /i2c-gpio-1 : i2c-gpio : arch/arm/mach-ep93xx/core.c : obj-y : x
-dDc-E-H-n--F : /i2c-gpio-1 : i2c-gpio : arch/arm/mach-ixp4xx/avila-setup.c : CONFIG_MACH_AVILA : n
-dDc-E-H-n--F : /i2c-gpio-1 : i2c-gpio : arch/arm/mach-ixp4xx/dsmg600-setup.c : CONFIG_MACH_DSMG600 : n
...
当然后面也可以直接跟dtb文件:
$./scripts/dtc/dt_to_config arch/arm/boot/dts/s3c2440-tq2440-dt.dtb --include-suspect --config ./.config
-dDc-E-Hx---- : /i2c-gpio- : i2c-gpio : arch/arm/mach-ep93xx/core.c : obj-y : x
-dDc-E-H-n--F : /i2c-gpio- : i2c-gpio : arch/arm/mach-ixp4xx/avila-setup.c : CONFIG_MACH_AVILA : n
-dDc-E-H-n--F : /i2c-gpio- : i2c-gpio : arch/arm/mach-ixp4xx/dsmg600-setup.c : CONFIG_MACH_DSMG600 : n
-dDc-E-H-n--F : /i2c-gpio- : i2c-gpio : arch/arm/mach-ixp4xx/fsg-setup.c : CONFIG_MACH_FSG : n
...
- ./scripts/dtc/dtx_diff
这个工具用于比较两个设备树,也可以对设备树反编译。示例:
#传递一个设备树,表示反编译
./scripts/dtc/dtx_diff arch/arm/boot/dts/s3c2440-tq2440-dt.dtb #也可以直接传递一个dts文件,这个工具会将该dts文件展开
./scripts/dtc/dtx_diff arch/arm/boot/dts/s3c2440-tq2440-dt.dts #传递两个设备树表示比较
./scripts/dtc/dtx_diff arch/arm/boot/dts/s3c2440-tq2440-dt.dtb /tftpboot/dtb
--- /dev/fd/ -- ::48.407691984 +
+++ /dev/fd/ -- ::48.407691984 +
@@ -, +, @@
pinctrl-names = "default";
reg = <0x54000000 0x100>;
samsung,i2c-max-bus-freq = <0x30d40>;
- status = "disabled";
+ status = "okay"; demo0@ {
compatible = "demo0";
也可以都是dts文件,或者一个dts一个dtb文件。
8、如何在设备树里控制属性值占用的字节数?
http://www.cnblogs.com/pengdonglin137/p/6044418.html
9、设备树中ranges属性分析
http://www.cnblogs.com/pengdonglin137/p/7401049.html
10、dts中memreserve和reserved-memory的区别
https://www.cnblogs.com/pengdonglin137/articles/10483018.html
11、devicetree-specification
https://files.cnblogs.com/files/pengdonglin137/devicetree-specification.pdf
其他关于设备树的调试文档
2、Youtube:Solving Devicetree Issues, part 3.0
3、Linux kernel的devicetree-compiler邮件列表里有很多好的patch,可以挑选自己想要的, 比如下面几个:
[RFC PATCH 0/3] dtc: dts source location annotation 这个系列的patch为dtc增加了一个annotate配置,这样在编译设备树时会生成annotate.dts.tmp后缀的隐藏文件,可以查看每个属性最终是被那个设备树文件设置的
[RFC PATCH 1/3] dtc: dts source location annotation
[RFC PATCH 2/3] dtc: make check test for dtc --annotate
[RFC PATCH 3/3] dtc: linux kernel build process to create annotated .dts
效果:
sdhci@f9824900 { /* arch/arm/boot/dts/qcom-apq8074-dragonboard.dts:14 */
compatible = "qcom,sdhci-msm-v4"; /* arch/arm/boot/dts/qcom-msm8974.dtsi:240 */
reg = <0xf9824900 0x11c 0xf9824000 0x800>; /* arch/arm/boot/dts/qcom-msm8974.dtsi:241 */
reg-names = "hc_mem", "core_mem"; /* arch/arm/boot/dts/qcom-msm8974.dtsi:242 */
interrupts = <0x0 0x7b 0x0 0x0 0x8a 0x0>; /* arch/arm/boot/dts/qcom-msm8974.dtsi:243 */
interrupt-names = "hc_irq", "pwr_irq"; /* arch/arm/boot/dts/qcom-msm8974.dtsi:244 */
clocks = <0xd 0xd8 0xd 0xd7>; /* arch/arm/boot/dts/qcom-msm8974.dtsi:245 */
clock-names = "core", "iface"; /* arch/arm/boot/dts/qcom-msm8974.dtsi:246 */
status = "ok"; /* arch/arm/boot/dts/qcom-apq8074-dragonboard.dts:17 */
bus-width = <0x8>; /* arch/arm/boot/dts/qcom-apq8074-dragonboard.dts:15 */
non-removable; /* arch/arm/boot/dts/qcom-apq8074-dragonboard.dts:16 */
}; /* arch/arm/boot/dts/qcom-apq8074-dragonboard.dts:18 */
==