U-Boot怎么把设备树地址准确告诉内核的?——DTB传递链路

电子说

1.4w人已加入

描述

导读:设备树(Device Tree)是 U‑Boot 传递给 Linux 内核最重要的数据结构。它包含了板级的全部硬件描述信息 —— 内存布局、外设地址、时钟配置、pinmux 设置等。从 FDT 加载到最终写入 x0 寄存器,DTB 经历了一条精心设计的传递链。

问题场景

内核启动到一半报FDT has bad magic或Kernel panic - not syncing: Unable to find DTB—— 这类问题通常不是 DTB 文件本身损坏,而是传递链中间某个环节断开了。DTB 从分区读到内存、经过校验和修补、最终放到 x0 寄存器,每一步都可能出错。本文追踪整条链路的实现代码。

一、DTB 的传递全景

从用户输入booti 命令到内核收到 DTB,整条链路如下:

u-boot

二、DTB 的来源与优先级

在 RK3576 上,DTB 可以从多个来源加载。U‑Boot 按以下优先级选择:

u-boot

RK3576 的典型情况:DTB 通常从 resource 分区加载。resource 分区是 Rockchip 平台特有的分区,存放了内核 DTB 和可能的其他资源文件。在引导时,U‑Boot 的 rockchip_read_dtb_file() 函数从resource 分区读取完整的设备树。

 

// arch/arm/mach-rockchip/resource_img.c (简化)void *rockchip_read_dtb_file(void){    /* 从resource分区读取DTB到fdt_addr_r */    int ret = rockchip_read_resource_file(dtb_buffer,                                         CONFIG_ROCKCHIP_RESOURCE_DTB_NAME);    if (ret <= 0) {        printf("Failed to read DTB from resource partitionn");        return NULL;    }    return dtb_buffer;}

 

三、RD DTB 与 U‑Boot DTB 的分离

RK3576 采用了 双 DTB 策略

U‑Boot DTB (rk3576‑u‑boot.dtsi):仅包含 U‑Boot 自身驱动需要的设备节点,体积小,编译进 U‑Boot 二进制文件

Kernel DTB (rk3576.dts + 板级rk3576‑evb.dts):完整的内核设备树,从 resource 分区加载或 SPI Flash 读取

之所以分离,是因为 U‑Boot 不需要完整的设备树 —— 它只需要驱动自己使用的外设(串口、MMC、网络等)。内核设备树则包含所有外设的完整描述。

四、bootm_find_images — 定位 DTB

bootm_find_images() 函数负责定位和加载 DTB 到内存。以下是经过简化的逻辑示意:

 

// common/bootm.c — bootm_find_images 简化解说int bootm_find_images(int flag, int argc, char *const argv[]){    /* 1. 获取fdt地址:按优先级选择 */    /*    命令行参数 argv[3] → 环境变量 fdt_addr → fdt_addr_r */    /* 2. 验证DTB magic (fdt_check_header) */    /* 3. 设置 images->ft_addr */    /* 另外也处理ramdisk和FDT overlay */    ret = boot_get_fdt(flag, argc, argv, images, &images->ft_addr,                       &images->ft_len);    return ret;}

 

实际实现更复杂:它通过boot_get_fdt() 函数统一处理,支持从 FIT 镜像中提取 DTB、叠加 FDT overlay 等特性。对于 RK3576 平台,当命令行和环境变量未指定时,由 rockchip_read_dtb_file() 从 resource 分区读取。

五、image_setup_libfdt — FDT Fixup

在 DTB 定位之后,image_setup_libfdt() 对 DTB 进行最终的运行时修补。这是 DTB 传递链中最关键的一步:

 

// common/image-fdt.c — 实际实现(简化)int image_setup_libfdt(bootm_headers_t *images, void *blob,                        int of_size, struct lmb *lmb){    /* 1. 架构通用fixup */    if (arch_fixup_fdt(blob) < 0)        goto err;    /* 2. ★ 注入bootargs到chosen节点 */    if (fdt_chosen(blob) < 0)        goto err;    /* 3. 注入MAC地址(从环境变量 ethaddr 读取) */    fdt_fixup_ethernet(blob);    /* 4. 板级特定fixup(通过事件回调链) */    if (IMAGE_OF_BOARD_SETUP) {        if (ft_board_setup(blob, gd->bd) < 0)            goto err;    }    /* 5. 系统级fixup(★ 包含rk_board_dm_fdt_fixup) */    if (IMAGE_OF_SYSTEM_SETUP) {        if (ft_system_setup(blob, gd->bd) < 0)            goto err;    }    /* 6. 收缩和保留 */    ret = fdt_shrink_to_minimum(blob, 0);    fdt_initrd(blob, *initrd_start, *initrd_end);    return 0;err:    printf("ERROR: fdt fixup failedn");    return -1;}

 

注意:rk_board_dm_fdt_fixup() 并非直接在image_setup_libfdt() 中调用,而是通过IMAGE_OF_SYSTEM_SETUP → ft_system_setup() → EVT_FT_FIXUP 事件链间接触发。不同板卡通过实现rk_board_dm_fdt_fixup() 来完成板级 DTB 修改

六、从 ft_addr 到 x0 的最终传递

Fixup 完成后,DTB 地址存储在 images->ft_addr 中。在BOOTM_STATE_OS_GO 阶段,boot_jump_linux() 将其放入 x0:

 

// arch/arm/lib/bootm.cvoid boot_jump_linux(bootm_headers_t *images, int flag){    /* cleanup_before_linux()已经执行完毕 */    /* ★ 关键跳转:x0 = images->ft_addr */    kernel_entry(images->ft_addr, 0, 0, 0);}
u-boot

 

七、调试 DTB 传递

如果在引导时遇到 DTB 相关问题,可以使用以下命令调试:

 

# 查看当前fdt_addr_r的值printenv fdt_addr_r# → 通常为 0x08300000# 手动加载DTB并检查load mmc 0:1 ${fdt_addr_r} /boot/rk3576‑evb.dtbfdt addr ${fdt_addr_r}fdt list /          # 列出根节点fdt list /chosen    # 检查bootargsfdt list /memory    # 检查内存信息

 

八、小结

•DTB 传递是 U‑Boot 到内核信息交换的核心机制,取代了传统的 ATAGS 方式

•DTB 有多来源(命令行、环境变量、resource 分区、FIT、内置),按优先级选择

•RK3576 采用双 DTB 策略,U‑Boot DTB 简化驱动需要,Kernel DTB 从 resource 分区加载

•image_setup_libfdt() 执行关键的 FDT Fixup 链,注入运行时的硬件信息

•最终images->ft_addr 通过boot_jump_linux() 放入 x0 寄存器传递给内核

•理解 DTB 传递链,是排查 "Kernel panic" 和 "bad FDT" 类问题的前提

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 相关推荐
  • 热点推荐
  • u-boot

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分