4. Layerscape启动流程与安全启动链
Layerscape系列处理器的启动过程是一条严格分层的信任传递链。从上电复位到Linux用户空间,每一级固件在将控制权交给下一级之前,都必须先验证下一级镜像的完整性与真实性。理解这条链的每一环——PBL、SPL、U-Boot、ATF、OP-TEE、Linux内核——以及它们如何借助OTP fuses和SEC引擎完成签名验证,是配置安全启动的前提。
启动阶段的分层结构
Layerscape上电后,最先运行的是芯片内部ROM中的PBL(Pre-Boot Loader)。PBL代码固化在芯片内,不可修改,它读取启动介质(QSPI、SD、eMMC或NAND)上的RCW(Reset Configuration Word)和SPL(Secondary Program Loader)镜像。PBL根据RCW中的启动模式、时钟和DDR参数完成最基础的硬件初始化,然后将SPL加载到片上SRAM并跳转执行。
SPL运行在SRAM中,空间有限,它的职责是初始化DDR控制器,把完整的U-Boot镜像从启动介质搬运到DDR,然后跳转到U-Boot。U-Boot阶段完成更丰富的外设初始化,并负责加载ATF(ARM Trusted Firmware)、OP-TEE和Linux内核。ATF运行在EL3,提供PSCI电源管理和安全监控调用;OP-TEE运行在EL1的安全世界,为可信应用提供隔离执行环境;Linux内核运行在EL1的非安全世界。整个启动链的信任根来自芯片内部的OTP fuses和SEC(Security Engine)硬件模块。
Chain of Trust 与信任根
Chain of Trust的核心思想是:每一级代码在运行前,必须由上一级已可信的代码验证其签名。信任的起点是芯片内不可修改的PBL ROM代码和OTP fuses中烧写的SRK(Super Root Key)哈希值。SRK哈希是整条信任链的锚点,一旦烧写便不可更改。
具体验证流程如下:PBL从启动介质读取SPL镜像及其签名(CSF头),将SRK哈希与OTP fuses中的值比对,确认公钥可信后,用SRK公钥验证SPL镜像的RSA签名。验证通过后,PBL将SPL加载到SRAM执行。SPL、U-Boot、ATF、OP-TEE、Linux内核依次重复这一过程。每一级镜像的CSF(Command Sequence File)中包含签名、公钥和证书链信息,SEC引擎负责加速RSA和SHA运算。
OTP Fuses与SEC密钥存储
OTP fuses是芯片内的一次性可编程存储区,关键字段包括:SRK Hash(256位,存储SRK公钥的SHA-256哈希)、SB_EN(安全启动使能位)、ITS(Image Trust Source,指定启动介质)、BOOT_SEQ(启动顺序)。烧写OTP fuses是不可逆操作,必须在量产前确认所有密钥和配置正确。
SEC引擎提供硬件级密钥存储和加密加速。在安全启动中,SEC的Job Ring接收验签任务,从内存读取镜像和签名数据,执行RSA-2048或RSA-3072验签和SHA-256哈希计算,返回验证结果。SEC还支持密钥封装(Key Blob),将敏感密钥加密后存储,只有SEC内部才能解密使用。
镜像签名与安全启动配置实践
以下以LS1046A为例,展示从生成密钥到烧写OTP的完整流程。假设使用RSA-2048和SHA-256算法。
第一步:生成SRK密钥对和自签名证书。
# 生成SRK私钥
openssl genrsa -out srk.pri 2048
# 生成SRK公钥
openssl rsa -in srk.pri -pubout -out srk.pub
# 生成自签名证书(用于CST工具)
openssl req -new -x509 -key srk.pri -out srk.crt -days 3650 \
-subj "/CN=SRK-LS1046A/O=NXP/C=CN"
# 计算SRK哈希(烧写到OTP fuses的值)
openssl dgst -sha256 -binary srk.pub | openssl enc -base64
第二步:使用NXP CST工具签名镜像。
# 创建输入文件描述
cat <<EOF > input_spl.txt
0x10000000 0x00000000 \
/path/to/spl.bin
EOF
# 生成CSF头
cst -i input_spl.txt -o csf_spl.bin \
-k srk.pri -c srk.crt -a sha256 -e rsa2048
# 将CSF头附加到SPL镜像
cat csf_spl.bin spl.bin > spl_signed.bin
第三步:烧写OTP fuses。
# 在U-Boot中烧写SRK哈希
=> fuse prog 0 0 0x12345678
=> fuse prog 0 1 0x9abcdef0
=> fuse prog 0 2 0x11223344
=> fuse prog 0 3 0x55667788
# 使能安全启动
=> fuse prog 1 0 0x00000002
# 验证烧写结果
=> fuse read 0 0 4
=> fuse read 1 0 1
验证安全启动是否生效
烧写完成后,重新上电。观察串口输出:PBL阶段会打印“SEC: Validating image...”或类似信息。如果签名验证通过,SPL、U-Boot依次启动,最终进入Linux。如果验证失败,PBL会停止启动并输出错误码,常见错误包括“SRK hash mismatch”和“Signature verification failed”。
在U-Boot中可以通过以下命令确认安全启动状态:
=> fuse read 1 0 1
Reading bank 1: 00000002
=> bdinfo
...
secure_boot = 1
...
在Linux中,可以通过检查/proc/device-tree或使用NXP提供的sec_tool读取SEC状态寄存器,确认安全启动已使能且镜像验证通过。
关键参数与常见问题
| 参数/字段 | 说明 | 典型值 |
|---|---|---|
| SRK Hash | SRK公钥的SHA-256哈希,烧写在OTP bank 0 | 256位(8个32位字) |
| SB_EN | 安全启动使能位,位于OTP bank 1 | 0x00000002 |
| ITS | 镜像信任源,指定从哪个介质加载镜像 | 0x00000000(QSPI) |
| RSA密钥长度 | 签名算法强度 | 2048或3072位 |
| 哈希算法 | 镜像摘要算法 | SHA-256 |
常见问题包括:SRK哈希烧写错误导致启动失败(需更换芯片);CSF头未正确附加导致签名验证失败;SEC Job Ring队列满导致验签超时。排查时优先检查OTP烧写值和镜像签名文件是否匹配,再确认SEC驱动是否正常初始化。
安全启动链的每一级都依赖上一级的正确验证。PBL验证SPL,SPL验证U-Boot,U-Boot验证ATF和OP-TEE,ATF验证Linux内核。任何一级验证失败,启动链即中断。理解这条链的结构和验证机制,是配置和维护Layerscape网络安全设备的基础。