3. 配置TZASC地址空间控制器
任务说明
本案例目标是在支持TrustZone的ARM平台上,通过编程方式配置TZASC(TrustZone Address Space Controller),将外部DDR内存划分为安全区域与非安全区域,并验证安全世界与非安全世界对各自区域的访问权限是否符合预期。
环境依赖
- 硬件:ARM Cortex-A系列处理器(支持TrustZone)+ TZASC-400或TZASC-380控制器
- 软件:裸机环境或最小RTOS,使用ARM GCC交叉编译工具链
- 内存布局:假设DDR基地址0x80000000,总大小256MB
核心实现
以下代码完成TZASC的初始化配置:将低64MB划分为安全区域(Region 0),其余192MB划分为非安全区域(Region 1),并设置访问权限。代码直接操作TZASC寄存器,不依赖操作系统驱动。
#include <stdint.h>
// TZASC寄存器映射(以TZASC-400为例,基地址0xE1200000)
#define TZASC_BASE 0xE1200000UL
#define TZASC_REGION_BASE 0x100UL // Region Base Address寄存器偏移
// 寄存器偏移定义
#define TZASC_CONFIG 0x000UL // 配置寄存器
#define TZASC_GATE_KEEPER 0x00CUL // Gate Keeper寄存器
#define TZASC_REGION_CTRL 0x110UL // Region Control寄存器(Region 0)
#define TZASC_REGION_ATTR 0x114UL // Region Attributes寄存器
// 寄存器位定义
#define GATE_KEEPER_OPEN (1UL << 0) // 允许region访问
#define REGION_ENABLE (1UL << 0) // Region使能
#define REGION_SECURITY (1UL << 1) // 1=安全, 0=非安全
#define REGION_SIZE_64MB (0x1BUL << 4) // 64MB大小编码
#define REGION_SIZE_192MB (0x1DUL << 4) // 192MB大小编码
#define REGION_READ_WRITE (0x3UL << 8) // 安全世界读写权限
// 内存区域定义
#define DDR_BASE 0x80000000UL
#define SECURE_REGION_SIZE 0x04000000UL // 64MB安全区域
#define NON_SECURE_REGION_SIZE 0x0C000000UL // 192MB非安全区域
// 寄存器访问宏
#define TZASC_REG(offset) (*(volatile uint32_t *)(TZASC_BASE + offset))
// 配置Region 0为安全区域(低64MB)
static void tzasc_configure_secure_region(void) {
// 设置Region 0基地址
TZASC_REG(TZASC_REGION_BASE + 0x00) = DDR_BASE;
// 设置Region 0控制:使能,安全,64MB大小
TZASC_REG(TZASC_REGION_CTRL) = REGION_ENABLE | REGION_SECURITY |
REGION_SIZE_64MB | REGION_READ_WRITE;
// 设置Region 0属性:允许安全世界读写,非安全世界不可访问
TZASC_REG(TZASC_REGION_ATTR) = 0x0; // 非安全世界无访问权限
}
// 配置Region 1为非安全区域(高192MB)
static void tzasc_configure_nonsecure_region(void) {
uint32_t region1_base = DDR_BASE + SECURE_REGION_SIZE;
// 设置Region 1基地址
TZASC_REG(TZASC_REGION_BASE + 0x20) = region1_base;
// 设置Region 1控制:使能,非安全,192MB大小
TZASC_REG(TZASC_REGION_BASE + 0x24) = REGION_ENABLE | REGION_SIZE_192MB;
// 设置Region 1属性:允许所有世界读写
TZASC_REG(TZASC_REGION_BASE + 0x28) = 0x3; // 非安全世界可读写
}
// 初始化TZASC
void tzasc_init(void) {
// 关闭所有region访问(安全起见)
TZASC_REG(TZASC_GATE_KEEPER) = 0x0;
// 配置两个内存区域
tzasc_configure_secure_region();
tzasc_configure_nonsecure_region();
// 打开gate keeper,允许region访问
TZASC_REG(TZASC_GATE_KEEPER) = GATE_KEEPER_OPEN;
}
// 验证函数:检查TZASC配置是否生效
uint32_t tzasc_verify_config(void) {
uint32_t status = 0;
// 检查Region 0控制寄存器
uint32_t ctrl0 = TZASC_REG(TZASC_REGION_CTRL);
if ((ctrl0 & REGION_ENABLE) && (ctrl0 & REGION_SECURITY)) {
status |= 0x1; // Region 0配置正确
}
// 检查Region 1控制寄存器
uint32_t ctrl1 = TZASC_REG(TZASC_REGION_BASE + 0x24);
if ((ctrl1 & REGION_ENABLE) && !(ctrl1 & REGION_SECURITY)) {
status |= 0x2; // Region 1配置正确
}
return status;
}
// 主函数入口
int main(void) {
tzasc_init();
uint32_t verify_result = tzasc_verify_config();
// 验证结果:0x3表示两个region均配置正确
if (verify_result == 0x3) {
// 配置成功
return 0;
} else {
// 配置失败
return -1;
}
}
编译与运行
# 交叉编译(以ARMv8-A为例)
aarch64-none-elf-gcc -c tzasc_config.c -o tzasc_config.o
aarch64-none-elf-ld -Ttext=0x80000000 tzasc_config.o -o tzasc_config.elf
# 烧录到目标板或使用QEMU验证
qemu-system-aarch64 -machine virt -cpu cortex-a57 -nographic -kernel tzasc_config.elf
验证方法
通过以下步骤验证访问控制是否生效:
- 寄存器回读验证:程序执行后,检查返回值。返回0表示两个Region配置均正确写入。
- 功能验证:在安全世界(Secure World)尝试访问非安全区域(0x84000000),应成功;在非安全世界(Normal World)尝试访问安全区域(0x80000000),应触发异常或返回错误。
- 判定标准:
tzasc_verify_config()返回0x3,且安全/非安全世界的访问行为符合预期,即判定配置成功。
注意事项
- 实际TZASC寄存器偏移可能因具体芯片型号而异,请参考对应芯片手册调整基地址和偏移量。
- Region大小编码(如64MB对应0x1B)需根据TZASC版本确认,不同版本编码可能不同。
- 在切换安全/非安全世界时,需确保CPU的SCR.NS位设置正确,否则TZASC的过滤规则不会生效。