TrustZone Demo 使用说明文档
TrustZone是ARM公司针对消费电子设备设计的一种硬件架构,其目的是为消费电子产品构建一个安全框架来抵御各种可能的攻击。 在处理器架构上,每个物理的处理器核提供两个虚拟核,一个是非安全核(Non-secure, NS),另一个是安全核(Secure),在这二者之间切换的机制叫做monitor模式。NS核只能访问NS的系统资源,而安全核能访问所有资源。普通世界的软件可以使用SMC指令或者通过硬件异常机制的一个子集来进入到monitor模式。
IDAU 一般规定好了内存的类型,用户无须配置它,它的规则是 :
所以用户更改内存的属性类型只要通过改变 SAU 的安全级别,然后综合两者的级别等级就可以实现配置用户所需要的内存属性类型 配置 SAU :按照用户内存区域划分好的类型进行配置,使得内存的属性类型符合用户区域的属性(安全 、 非安全 、 安全可调用,也就是实现用户安全代码 、 堆栈和数据内存为安全类型,非安全代码 、 堆栈和数据内存为非安全类型,Veneer Table 为非安全可调用类型 ),选择安全级别为 NS 或 NSC
内存保护单元 MPC 的配置主要是决定内存的访问许可,通过与内存区域的安全级别进行对比决定是否能够访问该内存地址 MPC 可以设置四个安全级别类型 :S-User 、 S-Priv 、 NS-User 、 NS-Priv 根据 SAU & IDAU 所确定的内存安全类型级别,配置 MPC 的安全级别类型,使其一致
2.1 安全世界代码工程的属性配置Build MCU settings 2.1.1 安全代码所在 flash 首地址和代码空间大小 Size 2.1.2 非安全可调用函数代码所在 flash 首地址和空间大小 Size 2.1.3 安全代码的堆栈和数据所在的 RAM 的首地址和空间大小 Size
2.2 安全世界代码工程的属性配置Build Settings 2.2.1 MCU C compiler 的架构(Architecture)选择:选择 Cortex-M33 2.2.2 MCU C compiler 的 TrustZone 工程类型:Secure 2.2.3 MCU Link 的架构(Architecture)选择 Cortex-M33 2.2.4 MCU Link 的TrustZone : TruseZone 工程类型为 Secure 安全网关导入库选择 SG-Veneer_table memory region
2.3 MCU Debugger TrustZone 勾选使能非安全的预编程镜像 选择非安全世界代码的工程问文件
3.1 非安全世界代码工程的属性配置Build MCU settings 3.1.1 非安全代码所在 flash 首地址和代码空间大小 Size 3.1.2 非安全代码的堆栈和数据所在的 RAM 的首地址和空间大小 Size
3.2 非安全世界代码工程的属性配置Build Settings 3.2.1 MCU C compiler 的架构(Architecture)选择:选择 Cortex-M33 3.2.2 MCU C compiler 的 TrustZone 工程类型:Non-Secure 3.2.3 MCU Link 的架构(Architecture)选择 Cortex-M33 3.2.4 MCU Link 的TrustZone : TrustZone 工程类型类型为 Non-Secure 安全网关导入库选择 :工作区间的安全代码工程的镜像文件内
4.1 安全世界代码需要在执行main 函数前进入 TrustZone 的内存配置操作,所以调用弱函数 SystemInitHook() ,把TrustZone 初始化函数放在里面执行,在调试时,执行启动文件的时候就会调用该系统初始化的函数,所以无需将其放在 main() 函数中去执行,其他如一般工程文件一样,正常配置外设即可
4.2 跳转非安全世界代码的条件入口 : 4.2.1 首先将之前配置的非安全代码所在 Flash 的首地址定义保留,方便调用
#define NON_SECURE_START DEMO_CODE_START_NS 重定义非安全回调函数的功能,这是ARM 定义的修饰的语句,编译会转化为汇编语言跳转到非安全世界去执行代码,用户从安全世界切换到非安全世界的入口地址变量需要利用这一语句去定义: typedef void (*funcptr_ns) (void) __attribute__((cmse_nonsecure_call)); funcptr_ns ResetHandler_ns; 4.2.2 在执行完安全世界代码后,在 main() 函数里添加调转入口: 利用上述定义的变量进行以下操作: main() 函数中安全的代码函数执行完毕后,设置跳转入口 :
配置好上述的语句,代码执行到这里会切换到非安全世界的 main() 中去执行语句。
这个文件下的函数主要是供非安全世界代码语句进行调用的,并且该文件的函数主要的执行代码语句是在安全世界内的,由于非安全世界不能直接调用,所以需要设置这一个跳转板供非安全世界去调用,所以该文件的函数需要直接被调用的都需要重新定义修饰一下,在函数的前面增加 __attribute__ ((cmse_nonsecure_entry))
6.1 TrustZone 非安全世界的工程中,不需要去设置 TrustZone 内存区域的代码 但是在进入 main() 函数之前,需要定义一个系统的初始化函数 void SystemInit(void) { } 配置这一语句就可以了,如果缺失该语句,从安全世界无法调转到非安全世界来执行代码,会出现 HardFault
6.2 在main() 函数中无需进行初始化,直接调用 Veneer_table.c 中的打印和比较语句 之前尝试在 main() 函数中初始化 GPIO 、USART 、PININT 都出现 HardFault,而且尝试在 SystemInit() 中去初始化它们,结果一样出现 HardFault 6.3 在main.c 文件中,需要包含头文件 veneer_table.h 以及其他在本工程中的头文件
7.1 TrustZone 工程文件中,一般先编译 非安全世界的工程代码, 然后再编译安全世界的工程代码 7.2 TrustZone 工程先执行安全世界的代码语句,执行完成后,调转到非安全世界去执行非安全代码语句,当非安全世界代码语句调用到安全世界的函数,会用到安全网关向量表进入到 veneer_table.c 去调用打印函数,执行完就停留在非安全世界的 while(1); 死循环中。
在安全世界代码中,也可以配置安全 GPIO 来区别普通的 GPIO ,使得 GPIO 的状态可以通过 Secure GPIO 来读取。
END TrustZone |