15. TF-A的介绍与编译

Trusted Firmware-A 是Arm提供的安全世界软件的参考实现。它最初是为 Armv8-A 平台设计的,并已被 STMicroelectronics 调整为在 Armv7-A 平台上使用。Trusted Firmware-A 是 Trusted Firmware 项目的一部分,该项目是由 Linaro 托管的开放治理社区项目。

当使用可信引导链时,它被用作STM32 MPU平台上的第一阶段引导加载程序(FSBL)。

15.1. 获取TF-A源码

TF-A官网: https://www.trustedfirmware.org/

野火TF-A仓库: https://gitee.com/Embedfire/ebf_linux_tfa/tree/ebf_2.0-r0_star/

注意:本教程以野火提供的TF-A源码为分析样本

1
2
#使用-b参数指定ebf_2.0-r0_star分支
git clone -b ebf_2.0-r0_star https://gitee.com/Embedfire/ebf_linux_tfa.git

15.2. TF-A工程结构分析

学习一个软件,尤其是开源软件,首先应该从分析软件的工程结构开始。一个好的软件有良好的工程结构,对于读者学习和理解软件的架构以及工作流程都有很好的帮助。

TF-A的源代码布局和我们讲的Linux内核源码类似,使用了按照模块划分的结构,并且充分考虑了体系结构和跨平台问题,其源代码树结构请参考下图

TF-A目录

目录/文件

说明

bl1、bl2、bl31、bl32

包含了TF-A 的不同阶段的引导加载程序的代码。

common

公共的代码,可以被各个部分共享使用。

drivers

包含了设备驱动程序的代码,用于与处理器和外设进行交互。

docs

包含了项目的文档,包括用户手册、开发者指南等

include

包含了一些头文件。

lib

包含了一些通用的库函数或者工具函数。

Makefile、Makefile.sdk

用于构建项目的 Makefile 文件,定义了编译、链接和构建过程中的规则和命令。

plat

包含了针对特定平台的代码或者配置。

services

包含了一些辅助工具,用于项目的构建、调试等。

maintainers.rst

维护者指南文件,记录了项目的维护者联系信息等。

dco.txt、license.rst、readme.rst

包含了项目的许可证信息、开发者签署协议等重要说明。

15.3. TF-A 不同启动阶段

对于32位Arm处理器,可信启动分为四个阶段(按执行顺序):

  • 引导加载程序阶段1 (BL1)应用程序处理器信任的ROM

  • 引导加载程序阶段2 (BL2)可信引导固件

  • 引导加载程序阶段3-2 (BL32)可信运行时固件

  • 引导加载程序阶段3-3 (BL33)不受信任的固件

其中BL1和BL2是TF-A的一部分,BL32可以在TF-A内也可以在TF-A外(例如OP-TEE)。

由于STM32 MPU平台使用专用的ROM代码,因此删除了BL1引导阶段。

BL33在TF-A之外。这是TF-A加载的第一个非安全代码。在引导序列中,这是二级引导加载程序(SSBL)。对于STM32 MPU平台,SSBL默认为U-Boot。

TF-A可以通过设备树进行配置管理。在BL2阶段,它是Linux内核的简化版本,在引导过程中只使用所需的设备。

../../_images/tfa0.jpg

TF-A加载步骤:

  • ROM代码加载并调用BL2

  • BL2装载BL32

  • BL2装载BL33

  • BL2呼叫BL32

  • BL32呼叫BL33

15.3.1. BL1

BL1是执行的第一阶段,被设计为ROM代码,它在内部RAM中加载和执行。它不用于STM32 MPU,由于STM32 MPU有自己的专有ROM代码,可以删除该部分,然后BL2是第一个要执行的TF-A二进制文件。

15.3.2. BL2

BL2负责加载下一阶段的固件(安全和非安全)。要实现这个任务,BL2必须初始化所有必需的外设。

  • 系统组件:时钟,DDR,…

  • 安全组件:加密外设,内存防火墙,…

  • 存储

  • BL2提供了不同的功能来加载和验证固件。

在其执行结束时,在加载了BL32和下一个引导阶段(BL33)之后,BL2跳转到BL32。

15.3.3. BL32

BL32提供运行时安全服务。

在Armv7架构上,BL32必须嵌入安全监视器,因为它将在相同的特权级别(PL1-SVC安全)中执行。

BL32作为安全监视器,为不安全的操作系统提供安全服务。这些服务由带有安全监视器调用的非安全软件调用。

参考资料:

https://wiki.stmicroelectronics.cn/stm32mpu/wiki/TF-A_overview

15.4. 编译TF-A源码

进入TF-A源码顶层目录,执行以下命令进行编译。

1
2
  #-f指定使用Makefile.sdk
  make -f Makefile.sdk all

如果编译成功,输出信息如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
  make[1]: Entering directory '/home/hyw/157/ebf-image-builder/ebf_linux_tfa'
  Including bl32/sp_min/sp_min.mk
  make[2]: Nothing to be done for 'all'.
  AS      plat/st/stm32mp1/stm32mp1.S
  LDS     plat/st/stm32mp1/stm32mp1.ld.S
  LDS     /home/hyw/157/ebf-image-builder/ebf_linux_tfa/build/trusted/stm32mp1.o

  Built /home/hyw/157/ebf-image-builder/ebf_linux_tfa/build/trusted/tf-a-stm32mp157a-star.bin successfully


  Generated /home/hyw/157/ebf-image-builder/ebf_linux_tfa/build/trusted/tf-a-stm32mp157a-star.stm32
  tools/stm32image/stm32image -s /home/hyw/157/ebf-image-builder/ebf_linux_tfa/build/trusted/tf-a-stm32mp157a-star.bin -d /home/hyw/157/ebf-image-builder/ebf_linux_tfa/build/trusted/tf-a-stm32mp157a-star.stm32 -l 0x000000002ffc2500 -e 0x000000002ffd8000 -v 0
  Image Type   : ST Microelectronics STM32 V1.0
  Image Size   : 245128 bytes
  Image Load   : 0x2ffc2500
  Entry Point  : 0x2ffd8000
  Checksum     : 0x00eaa04d
  Option     : 0x00000001
  Version    : 0x00000000

  Building stm32mp1
  make[1]: Leaving directory '/home/hyw/157/ebf-image-builder/ebf_linux_tfa'

编译会生成build目录,其中build目录下的trusted目录保存了编译生成的MP1所有型号的TF-A固件,野火使用的固件为:tf-a-stm32mp157a-star-trusted.stm32

../../_images/tfa1.jpg

15.5. TF-A固件烧录

如果是SD镜像,请编译完整镜像然后烧录到SD卡进行启动。

如果是usb镜像,替换usb烧录包stm32mp157_release_xxx/stm32mp157-cubeprogrammer/目录下的tf-a-stm32mp157a-star-trusted.stm32,然后烧录到emmc中进行启动。

15.6. TF-A启动信息分析

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  NOTICE:  CPU: STM32MP157AAC Rev.Z
  NOTICE:  Model: STMicroelectronics STM32MP157A-DK1 Discovery Board
  INFO:    Reset reason (0x15):
  INFO:      Power-on Reset (rst_por)
  INFO:    Using EMMC
  INFO:      Instance 2
  INFO:    Boot used partition fsbl1
  NOTICE:  BL2: v1.6-r3.0(debug):d64a19a
  NOTICE:  BL2: Built : 15:17:50, Feb  3 2021
  INFO:    BL2: Doing platform setup
  INFO:    RAM: DDR3-1066/888 bin G 2x4Gb 533MHz v1.45
  INFO:    Memory size = 0x40000000 (1024 MB)
  INFO:    BL2 runs SP_MIN setup
  INFO:    BL2: Loading image id 4
  INFO:    Loading image id=4 at address 0x2ffef000
  INFO:    Image id=4 loaded: 0x2ffef000 - 0x30000000
  INFO:    BL2: Loading image id 5
  INFO:    Loading image id=5 at address 0xc0100000
  INFO:    STM32 Image size : 823559
  WARNING: Skip signature check (header option)
  INFO:    Image id=5 loaded: 0xc0100000 - 0xc01c9107
  NOTICE:  BL2: Booting BL32
  INFO:    Entry point address = 0x2ffef000
  INFO:    SPSR = 0x1d3
  INFO:    Cannot find st,stpmic1 node in DT
  NOTICE:  SP_MIN: v1.6-r3.0(debug):d64a19a
  NOTICE:  SP_MIN: Built : 15:17:50, Feb  3 2021
  INFO:    ARM GICv2 driver initialized
  INFO:    stm32mp HSE (20): Secure only
  INFO:    stm32mp PLL2 (27): Secure only
  INFO:    stm32mp PLL2_R (30): Secure only
  INFO:    SP_MIN: Initializing runtime services
  INFO:    SP_MIN: Preparing exit to normal world


  U-Boot 2018.11-stm32mp-r4-g569038fc (Feb 11 2022 - 03:03:27 +0000)

  CPU: STM32MP157AAC Rev.Z
  Model: STMicroelectronics STM32MP157A-DK1 Discovery Board
  Board: stm32mp1 in trusted mode (st,stm32mp157a-dk1)
  DRAM:  1 GiB
  • 第1行,使用的CPU型号是STM32MP157AAC,Rev.Z表示某个修订版本。

  • 第2行,开发板型号是STMicroelectronics的STM32MP157A-DK1 Discovery Board。

  • 第3行到第4行,系统复位的代码为0x15,复位的具体原因是上电复位。

  • 第5行到第6行,正在使用EMMC作为存储设备,通道2。

  • 第7行,启动过程中使用了名为“fsbl1”的分区通常是一个引导加载程序(Boot Loader)分区。

  • 第8行到第9行,BL2版本、构建时间。

  • 第10行,BL2正在执行平台设置。

  • 第11行到第12行,使用的RAM类型是DDR3,速度533MHz,容量为2x4Gb(8Gb),版本为v1.45,换算GB为1024MB(1GB)。

  • 第13行,BL2正在运行一个名为“SP_MIN”的设置或配置。

  • 第14行到15行,BL2正在加载一个标识为“id 4”的镜像,被加载到内存地址0x2ffef000。

  • 第16行,镜像id 4已加载,并占用了从0x2ffef000到0x30000000的内存空间。

  • 第17行到第21行,BL2正在加载另一个标识为“id 5”的镜像。加载镜像id 5时跳过了签名检查。加载到内存地址0xc0100000到0xc01c9107。

  • 第22行,BL2正在启动BL32。

  • 第23行,BL32的入口点地址是0x2ffef000。

  • 第24行,ARM处理器相关的特殊程序状态寄存器(SPSR)的值

  • 第25行,在设备树中找不到名为“st,stpmic1”的节点。

  • 第26行到27行,SP_MIN的版本信息,构建时间。

  • 第28行,ARM Generic Interrupt Controller (GIC) v2的驱动程序已初始化。GIC是ARM架构中用于处理中断的组件。

  • 第29行,HSE(High Speed Ethernet)接口在20MHz的频率下仅用于安全环境。

  • 第30行,PLL2(Phase-Locked Loop 2)在27MHz的频率下仅用于安全环境。PLL通常用于生成时钟信号。

  • 第31行,PLL2_R(PLL2的某种派生或分频)在30MHz的频率下也仅用于安全环境。

  • 第32行,SP_MIN正在初始化运行时服务,这些服务可能在后续的正常世界操作中使用。

  • 第33行,SP_MIN正在准备退出到正常环境。

  • 第36行,U-Boot的版本信息,包括版本号、针对STM32MP的修改和构建时间。