Trusted Firmware-A
如图为 ARM TrustedFirmware (可信固件) 开源项目集合,它为带有 Exception Level 3 (EL3) Secure Monitor 的 ARM 架构 (Armv8-A、Armv9-A 和 Armv8-M 等) 提供了安全软件的实施参考实现。
1. TF-A 概述
Trusted Firmware-A (TF-A) project
是 ARM 可信固件的一种实施,主要面向 Armv7-A and Armv8-A class processors。它提供了统一的接口标准,主要保护设备启动过程,通过各种鉴权,保证设备启动的过程中每个阶段的固件都是安全的。TF-A implements Arm interface standards, including:
- Power State Coordination Interface (PSCI)
- Trusted Board Boot Requirements CLIENT (TBBR-CLIENT)
- SMC Calling Convention
- System Control and Management Interface (SCMI)
- Software Delegated Exception Interface (SDEI)
对于传统的 ARM 处理器而言,Linux 系统的启动流程为:BootROM -> U-boot -> kernel -> rootfs
,整个启动过程是一个链式结构,启动过程没有安全校验。加入 TF-A 固件以后, TF-A 就可以对 uboot、kernel、TEE OS(Trusted Execution Environment,TEE)进行校验。安全启动目的是为了保证整个启动过程各个镜像的完整性,防止被不法分子破坏或替换掉。Linux启动是一个链式结构,因此安全启动的鉴权 (校验)过程也是链式结构的。在系统启动的过程中,会先对下一个要加载运行的镜像进行鉴权,只有鉴权成功此镜像才能继续运行,并进入到下一阶段,同样要先对下一阶段的镜像进行鉴权,只要其中有一环鉴权失败,那么整个系统就会启动失败。
if (stage 1) // 阶段 1 鉴权成功{if (stage 2) // 阶段 2 鉴权成功{if (stage 3) // 阶段 3 鉴权成功{if (stage ...) // 阶段 n 鉴权成功boot success! // 安全启动成功elseboot failed! // 启动失败}elseboot failed! // 启动失败}elseboot failed! // 启动失败}elseboot failed! // 启动失败
2. ARM 处理器模式与特权等级
在 ARM 架构中,"EL" 是 "Exception Level" 的缩写,表示异常级别或特权级别。ARMv8 架构定义了四个异常级别,每个级别都有不同的特权和职责。这些级别用于管理和控制系统的不同部分,确保安全性和隔离性。TrustZone 技术将系统分为两个独立的执行环境:安全世界(Secure World)和非安全世界(Non-secure World)。EL3是唯一可以在这两个世界之间切换的级别。
异常/特权 | 级别 | 对应处理器模式 | 运行 | 特点 |
---|---|---|---|---|
EL0 | 最低 | User | 用户程序 | 没有直接访问硬件资源的权限,只能通过系统调用等方式请求更高特权级别的服务 |
EL1 | 较高 | SVC,ABT,IRQ,FIQ,UND,SYS | 操作系统内核 | 可以直接访问和管理硬件资源,处理中断和异常,提供系统调用服务 |
EL2 | 更高 | Hyp | 虚拟机监控器(Hypervisor) | 可以管理和控制多个虚拟机,处理虚拟化相关的中断和异常 |
EL3 | 最高 | Mon | 安全监控器(Secure Monitor) | 可以在安全世界(Secure World)和非安全世界(Non-secure World)之间切换,EL3通常负责安全启动过程,确保系统从一个可信的状态开始运行。 |
可以看出,只有 EL3 是用于安全监视器的,因此 TF-A 主要工作在 EL3 下。
3. TF-A 启动的不同阶段
TF-A 分为多个阶段,不同的阶段其工作内容不同。ATF/TF-A 输出 BL1、BL2、BL31,提供 BL32 和 BL33 接口。ATF/TF-A 冷启动[1]实现分为 5 个步骤:
- BL1(Boot loader stage 1) - AP(Application Processor)[2] Trusted ROM,一般为 BootRom。
- BL2(Boot loader stage 2) - Trusted Boot Firmware,一般为 Trusted Bootloader。
- BL31(Boot loader stage 3-1) - EL3 Runtime Firmware,一般为 SML,管理 SMC 执行处理和中断,运行在 secure monitor 中。
- BL32(Boot loader stage 3-2) - Secure-EL1 Payload,一般为 TEE OS Image。
- BL33(Boot loader stage 3-3) - Non-Trusted Firmware,一般为 uboot、linux kernel。
- 当芯片复位以后首先运行 bl1 代码,bl1 一般是芯片内部的 BOOT ROM 代码,主要工作是将外置 Flash 中的 bl2 固件加载到指定的 RAM 中,然后跳转到 bl2 部分。
- bl2 为安全启动固件,bl2 会将剩余的三个启动阶段 bl31、bl32 和 bl33 对应的镜像文件加载到指定的内存中。比如 bl32 中的安全操作系统(OP-TEE),bl31 中的 EL3 运行时固件(Runtime Firware),bl33 中的 uboot 。bl2将这些固件加载完成以后就会启动相应的固件,也就是进入到第三启动阶段。
- TF-A 启动流程为:
bl1->bl2->(bl31/bl32/bl33)
+ bl31、bl32 和 bl33 对应的镜像不需要全部都有,但 bl33 一般为 Uboot 是必须有的。
4. TF-A 源码与编译启动
- Trusted Firmware-A
- QEMU模拟ATF启动
- Arm Trusted Firmware-A 安全启动
注释
[1]
冷启动 | 热启动 | |
---|---|---|
定义 | 从完全关闭状态(电源断开)重新启动 | 在已通电但关机或休眠状态下重新启动 |
过程 | 电源开启: 用户按下电源按钮,电源供应开始。 硬件初始化: BIOS/UEFI固件进行POST(Power-On Self Test,加电自检),检查硬件是否正常。 引导加载: BIOS/UEFI从预设的启动设备(如硬盘、USB驱动器、网络等)加载引导加载程序(Boot Loader)。 操作系统加载: 引导加载程序加载并启动操作系统内核。 系统初始化: 操作系统进行初始化,加载必要的驱动程序和服务,完成启动过程。 |
操作系统重启: 用户通过操作系统提供的重启选项(如点击“重启”按钮)触发热启动。 硬件重置: 系统重置硬件状态,但不进行完整的硬件检测。 引导加载: 引导加载程序重新加载,但通常不需要进行完整的POST过程。 操作系统加载: 操作系统内核重新加载并启动。 系统初始化: 操作系统进行必要的初始化,但通常比冷启动快。 |
特点 | 完全重启 耗时较长 |
部分重启 耗时较短 |
应用场景 | 系统完全关闭 解决硬件问题 |
快速重启 应用更新 解决软件问题 |
[2] 大多数的手机都含有两个处理器。操作系统、用户界面和应用程序都在 Application Processor(AP)上执行,AP一般采用ARM芯片的CPU。而手机射频通讯控制软件,则运行在另一个分开的CPU上,这个CPU称为Baseband Processor(BP)。把射频功能放在BP上执行的主要原因是:射频控制函数(信号调制、编码、射频位移等)都是高度时间相关的。最好的办法就是把这些函数放在一个主CPU上执行,并且这个主CPU是运行实时操作系统的。
RISC-V Open Source Supervisor Binary Interface (OpenSBI)
RISC-V 处理器模式与执行环境接口
- ABI:Application Binary Interface;
- SBI:Supervisor Binary Interface;
- SEE:Supervisor Execution Environment;
- HBI:Hypervisor Binary Interface;
- HEE:Hypervisor Execution Environment。
- 某一时刻 HART 仅运行在一种 Mode; SBI是类系统调用的 Supervisor 和 SEE 之间的调用转换。
- RISC-V 定义的 Supervisor Binary Interface 称为 SBI,它对所有 RISC-V 硬件平台中共性的功能做了抽象,为运行在 S 模式下的操作系统或者虚拟机监控程序扩展的特权(Hypervisor-extended Supervisor, HS)模式的虚拟化管理软件提供统一的服务接口。通常把提供 SBI 服务的软件称为 SBI 固件,RISC-V 软件生态中比较流行的 SBI 固件有 OpenSBI 等。
- 与系统调用相类似,SBI 为运行在低级别的处理器模式提供访问高级别模式下的硬件资源的抽象接口。保证系统稳定和安全。M 模式下的处理器具有对系统资源的全部访问权限,如果某些硬件资源直接开放给 S 模式和 U 模式,可能会造成系统的安全隐患和可移植性问题。SBI 的作用一般为:
- ① 提高不同OS之间的代码复用。
- ② 提供不同平台共用的OS通用驱动。
- ③ 提供直接访问 M 模式下专有资源接口。
RISC-V 架构典型启动流程
每个启动阶段通过执行相应的代码,完成各自的任务,最终启动操作系统内核接管硬件设备。
- 初始阶段(ROM阶段) 执行 ROM 代码
- 上电复位:当系统上电后,硬件会自动跳转到一个固定的地址,通常是 ROM 区域的起始地址。
- 初始化硬件:ROM 代码负责初始化基本的硬件组件,如时钟、电源管理单元(PMU)、中断控制器等。
- 设置初始环境:包括设置堆栈指针、初始化片上 SRAM 等。
- 次级加载器(Secondary Program Loader, SPL)阶段 执行SPL 代码
- 运行于片上SRAM:SPL 代码通常运行在片上 SRAM 中。
- 初始化DDR内存:SPL 负责初始化外部 DDR 内存,使其可用。
- 加载主引导加载器:SPL 从外部存储设备(如SPI Flash、eMMC、SD卡等)读取主引导加载器(如U-Boot)的代码,并将其加载到DDR内存中。
- 安全和验证:在某些系统中,SPL可能会执行安全检查,验证加载的主引导加载器是否可信。
- 跳转到主引导加载器:SPL完成后,跳转到主引导加载器的入口点,让主引导加载器接管控制。
- 主引导加载器(Main Bootloader)阶段 执行主引导加载器代码
- 运行于DDR内存:主引导加载器(如U-Boot)通常运行在DDR内存中。
- 进一步硬件初始化:主引导加载器继续初始化更多的硬件组件,如网络接口、USB控制器、显示控制器等。
- 文件系统支持:主引导加载器支持多种文件系统(如FAT、EXT4等),可以从这些文件系统中加载内核和其他必要的文件。
- 网络启动支持:支持通过网络(如TFTP、NFS)加载内核和文件系统。
- 启动配置:提供命令行界面或其他方式让用户选择启动项和配置参数。
- 加载内核:从存储设备或网络加载操作系统内核到内存中。
- 跳转到内核:主引导加载器完成后,跳转到内核的入口点,让内核接管控制。
- 操作系统(OS)启动阶段 执行内核代码
- 初始化内核:内核进行自身的初始化,包括调度器、内存管理、设备驱动等。
- 启动用户空间:内核启动第一个用户进程(通常是
/sbin/init
或/init
),开始用户空间的初始化。 - 系统服务启动:用户空间初始化完成后,启动各种系统服务和应用程序。
启动成功后,最终处于运行态的仅有 OpenSBI 和 Linux,Linux 通过 sbi 指令和 OpenSBI 进行交互。
OpenSBI
- Important Features
- Platform specific reference firmware
- 三种不同类型的 RUNTIME 固件,包括 FW_PAYLOAD、FW_JUMP、FW_DYNAMIC。
- Platform Specific Library:平台专用库,应用于特定平台的驱动程序。
- SBI Library:平台级抽象的通用 SBI 库。通常与外部固件和引导程序一起使用,如 EDK2(UEFI 实现) 和安全启动工作组
- Platform specific reference firmware
-
Platform Specific Support
- Any SBI implementation requires hardware dependent (platform-specific) methods
- Print a character to console
- Get an input character from console
- Inject an IPI to any given HART subset
- Get value of memory-mapped system timer
- Start timer event for a given HART
- … more to come …
- platform-specific support 是以
sbi_platform
结构体实例的形式作为一组平台特定 hooks(指向平台相关函数的指针)实现的。 - 平台无关的通用 OpenSBI 代码被链接到 libsbi.a 静态库中
- 对于每个支持的平台,都会创建一个 libplatsbi.a 静态库 ( libplatsbi.a = libsbi.a + struct sbi_platform instance )
- Any SBI implementation requires hardware dependent (platform-specific) methods
-
RUNTIME 固件: OpenSBI 提供了三种类型的参考固件(reference firmware) 全都是基于特定平台(platform-specific)的
-
FW_PAYLOAD:OpenSBI firmware with the next booting stage as a payload 将下一启动阶段作为有效载荷的固件
- OpenSBI 和下一级启动固件绑定在一起。
- 任何 OpenSBI 或 Bootloader 改变,都需要重新编译。
- 无法从前一 bootloader 传递参数到 FW_PAYLOAD。
-
FW_JUMP:OpenSBI firmware with a fixed jump address to the next booting stage 带静态跳转地址到下一启动阶段的固件
- 跳转到一个固定的地址执行下一个固件。
- 优点:对于QEMU需要使用预编译的FW_JUMP很有用,不需要传递参数。
- 前一bootload必须将下一boot镜像加载到固定地址。
- 没有传递参数的机会。
-
FW_DYNAMIC:OpenSBI firmware with dynamic information about the next booting stage 带有下一启动阶段动态信息的固件
- 跳转的时候传递参数个下一个固件。
- 优点:下一Bootloader不需要记载到指定地点。
- 缺点:前一bootloader必须传递号struct fw_dynamic_info参数。
-
-
使用 OpenSBI 作为库
-
编译运行
- RISC-V Open Source Supervisor Binary Interface (OpenSBI)
- opensbi-quickstart
- OpenSBI背景介绍/编译/启动 Linux交互
- 从编译qemu开始,运行opensbi+kernel+rootfs