• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

SOC/IP验证工程师

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

arm中常说的bootrom和bootloader

我们首先需要区分这两个概念:BootROM和Bootloader。它们都是系统启动过程中的重要组成部分,但位于不同的层次,扮演不同的角色。

BootROM(启动只读存储器)

定义:BootROM是固化在芯片内部的一段不可修改的代码(通常是在芯片制造时就被写入,或者是一次性可编程的)。它是芯片上电后执行的第一段代码,因此也称为“芯片内置引导程序”。

位置:位于CPU的复位向量处(例如,ARM芯片复位后从地址0x00000000或0xFFFF0000开始执行,这个地址通常映射到BootROM)。

作用:

初始化芯片最基本的硬件,例如时钟、堆栈等。

根据芯片的启动模式(通过芯片的引脚电平或熔丝位设置)决定从哪个外部设备(如NAND Flash、SD卡、USB等)加载下一阶段的启动代码(通常是Bootloader)到内存中。

验证下一阶段代码的完整性(例如,通过校验和或数字签名),确保其可信。

跳转到加载到内存中的Bootloader继续执行。

特点:

代码大小有限,因为ROM容量通常很小(几KB到几十KB)。

不可修改,因此如果存在漏洞,无法通过软件升级修复(但可以通过后续阶段进行弥补)。

Bootloader(引导加载程序)

定义:Bootloader是一段存储在外部存储设备(如Flash、SD卡)上的软件,由BootROM加载到内存中并执行。它负责进一步的硬件初始化,并加载操作系统内核。

位置:存储在外部非易失性存储器中,由BootROM根据启动模式选择并加载到内存(通常是RAM)中。

作用:

完成更复杂的硬件初始化,例如内存控制器、更复杂的时钟树、外设等。

提供用户交互界面(例如,通过串口或显示屏),允许用户选择启动不同的操作系统或内核。

加载操作系统内核镜像(可能从硬盘、网络、SD卡等)到内存中,并传递必要的参数(如设备树、ATAGS等)。

验证操作系统内核的完整性,并在支持安全启动的系统上进行数字签名验证。

跳转到操作系统内核的入口点,将控制权交给操作系统。

特点:

代码大小相对较大(几十KB到几百KB,甚至几MB),因为功能更复杂。

通常可以升级(因为存储在外部可擦写存储器中)。

常见的Bootloader有:U-Boot、RedBoot、ARM的Bootmon等。

启动流程
典型的ARM系统启动流程如下:
a. 芯片上电,CPU从复位向量(BootROM的起始地址)开始执行BootROM代码。
b. BootROM根据启动引脚配置,从选定的启动设备(如eMMC)中加载Bootloader到内存(通常是内部SRAM或外部DRAM)。
c. BootROM验证Bootloader的签名(如果启用了安全启动),然后跳转到Bootloader。
d. Bootloader初始化更多的硬件,然后从存储设备(或网络)加载操作系统内核到内存,并跳转到内核。

两者区别总结

特性	BootROM	Bootloader
存储位置	芯片内部ROM	外部存储(Flash, SD卡等)
代码大小	小(几KB-几十KB)	较大(几十KB-几MB)
可升级性	不可升级(一次性固化)	可升级(存储在可擦写存储器)
功能	最基本的初始化,加载Bootloader	复杂的初始化,加载操作系统内核
执行顺序	最先执行	第二段执行
示例(以常见的嵌入式Linux系统为例)

芯片上电后,执行BootROM。

BootROM从SD卡中读取U-Boot的前一部分(可能是一个SPL,即Secondary Program Loader)到内部SRAM,因为此时外部DRAM尚未初始化。

U-Boot的SPL初始化外部DRAM,然后将完整的U-Boot加载到DRAM并跳转执行。

U-Boot初始化更多硬件,然后从SD卡中加载Linux内核镜像和设备树到DRAM,并跳转到内核。

因此,BootROM和Bootloader是系统启动链中的两个环节,BootROM是芯片内置的、不可更改的,而Bootloader是存储在外部的、可升级的,两者协作完成从硬件上电到操作系统启动的过程。

在ARM架构的嵌入式系统中,BootROM和Bootloader是系统启动过程中两个关键但不同的组件。它们就像计算机启动时按下电源键到Windows/Linux完全加载之间的多个阶段。

BootROM(芯片内置启动代码)

BootROM是固化在ARM芯片内部的不可修改的只读存储器,包含芯片上电后执行的第一段代码。

特性与作用:

  1. 位置固定,无法修改:

    • 在芯片制造时就烧录到硅片中
    • 用户无法修改或擦除
    • 位于芯片内部,不依赖外部存储
  2. 最小化的硬件初始化:

    • 初始化最基本的时钟(通常是内部RC振荡器)
    • 配置最小的内存(内部SRAM)
    • 设置初始堆栈指针和程序计数器
  3. 启动模式检测:
    读取芯片引脚(Boot mode pins)或熔丝位,决定从哪里加载下一级代码:

    例如:
    BOOT[2:0] = 000 → 从SPI Flash启动
    BOOT[2:0] = 001 → 从SD卡启动  
    BOOT[2:0] = 010 → 从eMMC启动
    BOOT[2:0] = 011 → 从USB下载
    
  4. 加载下一级引导程序:

    • 从指定存储设备读取Bootloader的前几个扇区到内部SRAM
    • 通常只加载很小的一段代码(几KB到几十KB)
  5. 安全启动的根信任:

    • 验证Bootloader的数字签名(如果支持安全启动)
    • 提供初始的加解密服务

简单类比:BootROM就像是计算机主板上的BIOS/UEFI固件,是硬件的一部分。

Bootloader(引导加载程序)

Bootloader是存储在外部非易失性存储器(如Flash、SD卡)中的可升级的软件,负责完成更复杂的初始化并加载操作系统。

常见Bootloader示例:

  • U-Boot:最流行的开源Bootloader
  • ARM Trusted Firmware:ARM官方参考实现
  • Little Kernel (LK):Android设备常用
  • RedBoot:传统嵌入式系统使用

主要功能:

// 简化版Bootloader执行流程
void bootloader_main(void) {
    // 1. 早期硬件初始化
    init_clocks();      // 设置PLL,系统主频
    init_dram();        // 初始化外部DDR内存
    init_serial();      // 初始化调试串口
    
    // 2. 环境与命令行
    setup_env();        // 读取环境变量
    if (serial_key_pressed()) {
        enter_cli();    // 进入命令行交互模式
    }
    
    // 3. 加载操作系统
    kernel = load_image("zImage");     // 从存储设备读取内核
    dtb = load_image("dtb");           // 加载设备树
    
    // 4. 设置启动参数
    setup_boot_args(kernel, dtb, cmdline);
    
    // 5. 安全验证(可选)
    if (secure_boot_enabled) {
        verify_signature(kernel);      // 验证内核签名
    }
    
    // 6. 跳转到操作系统
    jump_to_kernel(kernel_entry);
}

详细功能分解:

1. 完整硬件初始化

  • 配置系统时钟树(PLL、分频器等)
  • 初始化外部DDR内存控制器
  • 设置外设控制器(如NAND、SDIO、USB、Ethernet等)

2. 存储设备驱动

  • 实现Flash驱动(NOR/NAND)
  • 实现文件系统支持(FAT、EXT4等)
  • 支持网络引导(TFTP、HTTP)

3. 交互式命令行

# U-Boot命令行示例
U-Boot > printenv          # 打印环境变量
U-Boot > setenv ipaddr 192.168.1.100
U-Boot > tftp 0x80008000 zImage  # 从网络加载内核
U-Boot > bootm 0x80008000        # 启动内核

4. 操作系统加载

  • 解析内核镜像格式(zImage、uImage、FIT等)
  • 加载设备树二进制(DTB)
  • 设置启动参数(ATAGS或FDT)

5. 高级功能

  • 恢复模式:允许刷写新固件
  • 快速启动:跳过不必要的初始化
  • 多重引导:选择不同的操作系统

典型启动流程对比

让我们用一个实际例子说明两者的分工(以STM32F7系列启动Linux为例):

flowchart TD A[上电/复位] --> B[BootROM执行] B --> C{检测启动模式} C -->|BOOT0=0| D[从主Flash启动<br>用户应用] C -->|BOOT0=1| E[从系统存储器启动<br>内置Bootloader] subgraph F [BootROM阶段] B C E end E --> G[加载SPL<br>(U-Boot第一阶段)] subgraph H [Bootloader阶段] G I[SPL初始化<br>时钟, SRAM, 串口] J[加载完整U-Boot<br>到外部RAM] K[U-Boot初始化<br>DRAM, 网络, 文件系统] L[加载Linux内核<br>和设备树] M[跳转到内核] end I --> J J --> K K --> L L --> M

时间线视角:

时间        | 组件       | 位置         | 主要任务
-----------|------------|--------------|------------------
t=0-10ms   | BootROM    | 芯片内部ROM  | 引脚检测,时钟初始化
t=10-50ms  | Bootloader | 外部Flash    | DRAM初始化,外设设置
t=50-100ms | Bootloader | 外部Flash    | 加载内核,准备启动参数
t=100ms+   | Linux内核  | 外部Flash    | 启动完成,运行用户空间

Bootloader的演进:多阶段启动

现代复杂系统通常使用多阶段Bootloader:

  1. SPL(Secondary Program Loader):

    • 由BootROM加载到内部SRAM
    • 初始化外部DRAM
    • 加载完整的Bootloader到DRAM
  2. TPL(Tertiary Program Loader):

    • 在某些SoC中存在
    • 进一步初始化复杂外设
  3. 主Bootloader(如U-Boot):

    • 功能完整的引导程序
    • 支持命令行、网络、文件系统
  4. ARM特定流程:

    BootROM → SPL(EL3/安全监控模式)
           → ATF(ARM Trusted Firmware,可选)
           → U-Boot(EL2/非安全模式)
           → Linux内核(EL1/内核模式)
    

实际开发中的注意事项

1. Bootloader调试

// 早期调试技巧
void early_debug(char *msg) {
    // 在DRAM初始化前,使用串口输出
    // 可能需要轮询方式,因为中断还没初始化
    while (*msg) {
        while (!(UART->SR & UART_SR_TXE));
        UART->DR = *msg++;
    }
}

2. Bootloader大小优化

# U-Boot配置示例,减小尺寸
CONFIG_SYS_THUMB_BUILD=y      # 使用Thumb指令集
CONFIG_SPL=y                   # 启用SPL
CONFIG_SPL_SIZE_LIMIT=0x10000 # 限制SPL为64KB

3. 安全启动实现

// 验证引导链
bool verify_boot_chain(void) {
    // 1. BootROM验证SPL签名
    // 2. SPL验证U-Boot签名  
    // 3. U-Boot验证内核签名
    // 4. 内核验证根文件系统
    return check_signature(image, public_key);
}

总结:关键区别

特性 BootROM Bootloader
位置 芯片内部ROM 外部存储(Flash/SD)
可修改性 不可修改 可升级、可替换
大小 很小(几KB) 较大(几十KB到几MB)
功能 最基本初始化 完整硬件初始化
信任根 是(安全起点) 可被验证的组件
开发者 芯片厂商 系统开发者/开源社区

简单记忆:

  • BootROM = "硬"引导,芯片自带,固定不变
  • Bootloader = "软"引导,用户可定制,功能丰富

在嵌入式开发中,Bootloader是开发者需要重点关注和定制的部分,而BootROM通常只需要了解其支持的启动模式即可。

posted on 2026-02-08 19:40  SOC验证工程师  阅读(406)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3