2. u-boot启动流程概览:从ROM代码到SPL再到u-boot proper的加载链,CRC校验在哪个环节触发

嵌入式系统的启动是一个多阶段、逐级验证的过程。理解从片上ROM到SPL再到u-boot proper的完整加载链,是定位CRC校验失败故障的前提。本章将拆解这一流程,并明确指出CRC校验在哪个环节被触发。

2.1 三阶段启动模型

现代嵌入式处理器(如i.MX、Rockchip、TI OMAP等)普遍采用三级启动架构,每一级都承担着“加载并验证下一级”的职责。

阶段 存储位置 主要职责 是否包含CRC校验
ROM Code 芯片内部Mask ROM 初始化基础硬件(时钟、PLL、DDR),从启动介质读取SPL 通常由硬件或固定算法校验SPL头部
SPL (Secondary Program Loader) SPI Flash / eMMC / SD卡 初始化DDR、时钟、存储控制器,加载u-boot proper 是(对u-boot proper镜像进行CRC校验)
u-boot proper SPI Flash / eMMC / SD卡 加载内核、设备树、文件系统,提供命令行环境 可选(对内核/DTB进行CRC校验)
关键结论:在标准u-boot启动流程中,CRC校验的主要触发点位于SPL加载u-boot proper的阶段。SPL在将u-boot proper从存储介质读入DDR后,会对其镜像头部或整体进行CRC校验,以确认镜像完整性。

2.2 启动流程详细拆解

下图展示了从芯片上电到u-boot proper运行的完整加载链,以及CRC校验的触发位置。

u-boot三级启动加载链与CRC校验触发点 u-boot 三级启动加载链与 CRC 校验触发点 阶段1: ROM Code 初始化BootROM环境 读取SPL头部 阶段2: SPL 初始化DDR/时钟/存储 加载u-boot proper 阶段3: u-boot proper ⚠ CRC 校验触发点 SPL 将 u-boot proper 读入 DDR 后 校验镜像头部 CRC 或整体 CRC 存储介质:SPI Flash / eMMC / SD卡 / NAND 镜像布局:SPL头部 + SPL主体 | u-boot proper头部 + u-boot proper主体 图例: ROM Code SPL u-boot proper 存储介质 CRC校验触发点

2.3 SPL中的CRC校验机制

SPL对u-boot proper的CRC校验通常发生在以下代码路径中:

  1. 读取镜像头部:SPL从存储介质中读取u-boot proper的头部结构(通常为struct image_header或struct legacy_img_hdr)。
  2. 提取CRC值:从头部中提取预存的CRC校验值(ih_hcrc或image_header->ih_hcrc)。
  3. 计算实际CRC:对头部数据或整个镜像数据重新计算CRC32。
  4. 比较验证:将计算值与预存值比较,一致则跳转到u-boot proper入口,不一致则进入错误处理流程。
调试提示:在SPL启动日志中,如果看到 Bad CRC、CRC error 或 Verification failed 等关键字,说明CRC校验失败。此时应优先检查u-boot proper镜像在存储介质中的写入是否正确,以及SPL读取的地址是否与镜像实际存储位置匹配。

2.4 CRC校验触发的具体代码位置

在u-boot源码中,CRC校验的核心函数位于以下文件中:

文件路径 关键函数 说明
common/image.c image_check_hcrc() 校验镜像头部CRC(ih_hcrc)
common/image.c image_check_dcrc() 校验镜像数据CRC(ih_dcrc)
common/spl/spl.c spl_load_image() SPL加载镜像入口,内部调用校验函数
common/spl/spl_legacy.c spl_parse_legacy_header() 解析传统镜像头部并触发CRC校验

典型的校验调用链如下:

// spl_load_image() 中调用
spl_load_image(&bdev, &header, image_sector, count);

// 内部调用 spl_parse_legacy_header()
spl_parse_legacy_header(&header);

// 最终调用 image_check_hcrc() 进行CRC校验
if (!image_check_hcrc(&header)) {
    printf("Bad CRC: header CRC check failed\n");
    return -EINVAL;
}

2.5 不同启动介质下的CRC校验差异

CRC校验的触发时机和方式会因启动介质的不同而略有差异:

  • SPI Flash:SPL通过SPI控制器读取u-boot proper镜像,CRC校验在数据完全读入DDR后执行。常见故障:SPI时钟配置错误导致数据读取错位。
  • eMMC/SD卡:通过MMC控制器读取,CRC校验在块读取完成后触发。常见故障:分区表错误或块偏移量配置不正确。
  • NAND Flash:由于NAND存在坏块,SPL需要处理ECC校验后再进行CRC校验。常见故障:坏块管理表损坏或ECC纠错失败。
  • USB/网络启动:在开发调试阶段使用,CRC校验在数据接收完成后触发。常见故障:传输中断或数据包乱序。
常见误区:很多开发者误以为CRC校验失败一定是镜像文件损坏。实际上,SPL读取地址错误、存储介质驱动配置不当、DDR初始化不稳定等硬件或驱动层面的问题,同样会导致读入DDR的数据与原始镜像不一致,从而触发CRC校验失败。

2.6 本章小结