设备树来源判断:内核还是Bootloader
核心机制设备树的选择优先级Bootloader(PMON/U-Boot)传入的 DTB → 优先使用 ↓ (未传入或地址无效) 内核 built-in 的 DTB → 降级使用内核启动时入口代码会检查 bootloader 通过寄存器传递的 DTB 地址如 MIPS 的a1寄存器、ARM64 的x0如果地址有效且 DTB magic 校验通过就使用它否则回退到内核镜像中内嵌的 DTB。判断方法按实用程度排序1. 看 dmesg 启动日志最直接dmesg|grep-iEdevice.tree|dtb|fdt|boot_command_line关注的关键信息日志关键词含义Booting with flat device tree使用了设备树Using DTB from bootloader/passed from firmware用的是 Bootloader 传的No DTB passed, using built-in用的是内核自带的DTB: 0x...Bootloader 传入的 DTB 物理地址不同平台日志措辞不同但内核启动早期的early_init_devtree()/setup_machine_fdt()阶段通常会打印来源。2. 对比 DTB 内容最可靠取出内核运行时实际使用的设备树# 从运行系统获取当前使用的 DTBcp/sys/firmware/fdt /tmp/running.dtb# 反编译为可读格式dtc-Idtb-Odts /tmp/running.dtb-o/tmp/running.dts取出内核镜像中内嵌的 DTB# 方法一用 scripts/dtc/extract 或手动定位# 在 vmlinuz/vmlinux 中搜索 DTB magic: d00dfeedhexdump-Cvmlinuz|grepd0 0d fe ed# 从偏移量截取ddifvmlinuzbs1skipoffsetof/tmp/builtin.dtb# 方法二如果有 vmlinux未压缩用 fdtgrep 或直接# 对于 many MIPS kernels:dtc-Idtb-Odts /tmp/builtin.dtb-o/tmp/builtin.dts然后对比diff/tmp/running.dts /tmp/builtin.dts完全一致→ 说明用的就是内核自带的或者 Bootloader 传了一份相同的进来有差异→ 说明用的是 Bootloader 修改/单独传入的设备树常见场景Bootloader 在运行时动态 patch 了内存大小、MAC 地址、cmdline 等节点3. 查看 Bootloader 传参U-Boot 侧检查# 在 U-Boot 命令行下printenvfdt_addr# 或 fdt_addr_rprintenvloadaddrprintenvbootargs fdt print# 打印当前加载的设备树如果fdt_addr被设置且bootm/booti命令指定了 DTB 地址那就是传了设备树。PMON 侧检查PMON 一般通过g console等命令设置参数检查是否设置了 DTB 相关变量。在 PMON 命令行下pmon set # 查看所有环境变量 pmon devls # 查看设备4. 从内核配置判断回退行为zcat /proc/config.gz|grep-iUSE_OF\|CMDLINE.*DTB\|MIPS_CMDLINE\|APPEND_DTB关键配置项配置项作用CONFIG_USE_OFy内核支持设备树CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER从 Bootloader 接收 cmdlineCONFIG_MIPS_CMDLINE_BUILTIN_EXTEND以 Bootloader cmdline 为基础扩展CONFIG_ARM64_USE_CMDLINEARM64 cmdline 来源常见实际场景总结┌─────────────────────────────────────────────────────┐ │ 场景 │ 实际使用的 DTB │ ├─────────────────────────────────────────────────────┤ │ U-Boot 执行 bootm $addr - $fdt │ Bootloader 传入 │ │ U-Boot 执行 bootm $addr │ 内核 built-in │ │ PMON 直接 loadg │ 通常 built-in │ │ PMON 配合 DTB 参数加载 │ Bootloader 传入 │ └─────────────────────────────────────────────────────┘最快捷的判断方式在运行系统上cp /sys/firmware/fdt然后和内核 built-in DTB 做二进制对比。如果大小或内容不一致就是 Bootloader 单独传的。