3. Agilex SoC 启动流程与引导链
Agilex SoC 的启动不是“上电即运行 Linux”这么简单,而是一条由多个引导阶段接力完成的可信链。每个阶段只做有限的事:初始化它必须初始化的硬件,然后把控制权连同“下一阶段在哪里、用什么参数启动”的信息交给下一个阶段。理解这条链的关键,是搞清楚每一棒交接时控制权如何转移、镜像如何被找到和校验、参数如何被传递。
整条链的顺序是:BootROM → U-Boot SPL → ATF(BL31)→ U-Boot(BL33)→ Linux 内核。其中 BootROM 固化在芯片内,不可修改;SPL 和 ATF 通常由 Altera 提供的源码或二进制集成;U-Boot 与内核由开发者自行构建和配置。下面这张图给出各阶段的加载关系与交接内容。
BootROM:不可更改的第一棒
Agilex SoC 上电复位后,CPU 从片内 BootROM 的固定地址开始执行。BootROM 是芯片出厂固化的,开发者无法修改,它的职责非常克制:读取 BOOT_PIN 或熔丝配置确定启动介质(QSPI、SD 卡、eMMC 等),从该介质的约定偏移处读取 SPL 镜像,做基本校验后搬运到片上 SRAM 并跳转执行。由于片上 SRAM 容量有限(通常几百 KB),SPL 必须足够小,这也是为什么 SPL 只做 DDR 初始化等最必要的动作。
如果 BootROM 阶段失败,通常表现为串口无任何输出或输出极短后停止。此时应优先检查启动介质选择引脚、镜像是否烧写到正确偏移、以及 SPL 是否超出 SRAM 容量。
U-Boot SPL:把 DDR 带起来
SPL(Secondary Program Loader)运行在片上 SRAM 中,核心任务是把 DDR 初始化好,因为后续的 ATF、U-Boot 和内核都必须在 DDR 中运行。SPL 的 DDR 参数来自 Altera 提供的配置(如 board/altera/agilex/ 下的 DDR 初始化代码或 handoff 文件),这些参数与具体板卡的 DDR 颗粒、频率、时序强相关,不能随意套用。
DDR 可用后,SPL 从启动介质读取 ATF 和 U-Boot 镜像到 DDR 的指定地址,然后跳转到 ATF。在典型配置中,SPL 会依次加载 bl31.bin(ATF)和 u-boot.itb 或 u-boot.bin。以下是一个简化的 SPL 加载顺序示意(示例参数,非实测):
SPL 阶段(示例):
DDR 初始化完成,容量 2GB
加载 ATF 到 0x8000_0000 附近
加载 U-Boot 到 0x8100_0000 附近
跳转 ATF 入口
ATF(BL31):安全世界的守门人
ARM Trusted Firmware 在 Agilex SoC 上以 BL31 形式运行在 EL3(最高异常等级)。它负责建立安全监控环境,提供 PSCI(Power State Coordination Interface)服务,使 Linux 能够通过 SMC 指令请求 CPU 热插拔、系统复位等操作。ATF 完成初始化后,通过 bl31_main 跳转到 BL33,也就是 U-Boot。
ATF 与 U-Boot 的交接依赖一组“handoff”参数,包括入口地址、设备树地址等。如果 ATF 找不到 BL33 入口,启动会停在 ATF 阶段。排查时可观察串口是否打印 ATF 版本信息,以及是否出现跳转 BL33 的日志。
U-Boot(BL33):真正的引导管理器
U-Boot 运行在 EL2 或 EL1(非安全世界),是开发者最常打交道的阶段。它提供命令行、环境变量、网络启动、文件系统读写等能力。启动 Linux 时,U-Boot 需要完成三件事:把内核镜像(Image)和设备树(.dtb)加载到 DDR,设置 bootargs 内核命令行,然后跳转到内核入口。
典型的手动启动命令如下(示例):
# 从 SD 卡加载内核与 DTB
fatload mmc 0:1 0x82000000 Image
fatload mmc 0:1 0x83000000 socfpga_agilex.dtb
setenv bootargs "console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootwait"
booti 0x82000000 - 0x83000000
其中 booti 用于 64 位 ARM 内核镜像,参数依次为内核地址、initrd 地址(- 表示无 initrd)、DTB 地址。内核启动后,会解析 DTB 获取硬件信息,并根据 bootargs 中的 root= 挂载根文件系统。
参数传递:从 U-Boot 到内核
U-Boot 向内核传递信息有两条主要途径:一是 bootargs 环境变量,最终成为内核命令行;二是设备树 DTB,描述硬件拓扑。两者必须一致,例如 bootargs 中指定的串口设备要与 DTB 中 serial0 的地址匹配,否则会出现“内核启动但无控制台输出”的现象。
Booting Linux 及设备初始化日志。哪一阶段没有输出,问题就定位在该阶段或其前一阶段。常见故障与判断依据
启动失败时,可按以下顺序判断:若串口完全无输出,检查供电、时钟、启动引脚与 BootROM 介质选择;若 SPL 输出后停止,检查 DDR 参数与 ATF/U-Boot 镜像是否存在于介质正确偏移;若 ATF 输出后停止,检查 BL33 入口地址与 U-Boot 镜像格式;若 U-Boot 能进命令行但内核不启动,检查 bootargs、内核地址、DTB 地址与 booti 参数;若内核启动但无法挂载 rootfs,检查 root= 设备名与文件系统类型。