1169|2

274

帖子

8

TA的资源

纯净的硅(初级)

楼主
 

[ ST NUCLEO-U575ZI-Q 测评] 5-TrustZone模式下-将安全区代码注册到非安全区 [复制链接]

上一个帖子说的是非安全区调用安全区的代码,这个帖子反过来了,说的是安全区调用非安全区的代码。

因为安全区是可以通过绝对地址访问非安全区的函数的。但是非安全区函数的绝对地址不容易获取或者容易更改。因此我们可以使用函数指针的形式指向非安全区对应的函数。

那么是如何将非安全区的函数赋值给安全区的函数指针呢?可以通过注册函数的形式获取非安全区的函数地址。

1.代码存放位置与特点

这个注册函数也是在"secure_nsc.c"文件中,代码如下所示。可以看到也是需要添加CMSE_NS_ENTRY前缀的。因为这个函数要在非安全区进行调用来注册非安全区的函数,被调用的非安全区的函数是作为第2个参数的。这样就可以将函数赋值给NSC区的一个指针。然后通过指针可以调用对应的函数。注意第二个参数的类型是void的指针类型,这个指针在这里还不需要指定成真正的函数指针类型,而是在调用这个指针的时候才会强制转换成真正的函数指针类型。

void *pSecureFaultCallback = NULL;   
void *pSecureErrorCallback = NULL;  

CMSE_NS_ENTRY void SECURE_RegisterCallback(SECURE_CallbackIDTypeDef CallbackId, void *func)
{
  if(func != NULL)
  {
    switch(CallbackId)
    {
      case SECURE_FAULT_CB_ID:           /* SecureFault Interrupt occurred */
        pSecureFaultCallback = func;
        break;
      case GTZC_ERROR_CB_ID:             /* GTZC Interrupt occurred */
        pSecureErrorCallback = func;
        break;
      default:
        /* unknown */
        break;
    }
  }
}

下面的代码为在非安全区调用上面的注册函数,注册相应的非安全区函数到安全区的函数指针处。

SECURE_RegisterCallback(SECURE_FAULT_CB_ID, (void *)SecureFault_Callback);

2.在安全区调用注册后的函数

安全区的代码调用非安全区代码时,使用的汇编指令是BLXNS。在安全状态向非安全状态切换时,返回地址和一些运行状态需要压入安全区的堆栈中,以防止泄露给非安全区,并且要将LR寄存器设置成FNC_RETURN的特殊值,这个目的应该是为了当函数返回时,告知CPU是从非安全区返回的。当然这些操作不用使用者进行操作,而是由编译器进行的。用户通过关键字cmse_nsfptr_create告知编译器执行上面的操作。除了这个关键字,还有一个关键字是要用到的,CMSE_NS_CALL,这个关键字与上一个帖子里,安全区函数的入口函数关键字CMSE_NS_ENTRY是相对的。CMSE_NS_CALL是声明为非安全区的入口函数。

调用非安全区函数的代码如下:

/*main.h*/
typedef void CMSE_NS_CALL (*funcptr)(void);
typedef funcptr funcptr_NS;

/*stm32u5xx_it.c*/
funcptr_NS callback_NS;
if(pSecureErrorCallback != (funcptr_NS)NULL)
  {
   /* return function pointer with cleared LSB */
   callback_NS = (funcptr_NS)cmse_nsfptr_create(pSecureErrorCallback);

   callback_NS();
  }

前两行的typedef是在main.h中定义好的,这个指定了函数指针真正的原型,可以看到下面的代码用这个类型对(void *)的那个指针进行了强制类型转化。最后一行的callback_NS()就调用了非安全区的代码。

3.安全区调用非安全区的函数,能否传递参数和获取返回值

同上一个帖子一样,两者之间只能通过通用寄存器R0-R3传递参数。过多的参数会放入栈中,使得函数无法使用,因为栈顶指针是无法从安全区传递到非安全区的。

返回值是放在R0寄存器中的,也是可以传递回来的。

但是不像上一个帖子中非安全区调用安全区函数那样,将指针以参数的形式传递给被调函数时,是无法使用的。因为指针指向的是安全区的内存,这个是非安全区所不能访问的。那么如何传递大量的数据呢?可以迂回一下,再在安全区注册一个缓存区的指针,指向非安全区的一块区域,然后通过这个指针操作非安全区的数据,并把这个指针传递给被调函数。这样非安全区的代码访问的还是非安全区的数据,就可以了。

至此安全区和非安全区之间的交互方式就学习完了,这个交互包括函数的交互,也包括数据的交互。下一个帖子,分享一下TrustZone工程的启动流程。

此帖出自RF/无线论坛

最新回复

测评汇总:免费申请|ST NUCLEO-U575ZI-Q https://bbs.eeworld.com.cn/thread-1228653-1-1.html   详情 回复 发表于 2023-1-12 09:22
点赞 关注
 

回复
举报

6841

帖子

11

TA的资源

版主

沙发
 
感谢分享!
此帖出自RF/无线论坛
 
 

回复

1万

帖子

203

TA的资源

管理员

板凳
 

测评汇总:免费申请|ST NUCLEO-U575ZI-Q https://bbs.eeworld.com.cn/thread-1228653-1-1.html

此帖出自RF/无线论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
个人签名

玩板看这里:

https://bbs.eeworld.com.cn/elecplay.html

EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
快速回复 返回顶部 返回列表