前言
上文我们创建好了通道,现在就是操作,怎么操作TA呢?
REE侧的CA执行创建会话操作成功后,CA就可使用获取到的会话ID和命令ID调用TEEC_InvokeCommand接口来让TA执行特定的命令。
在CA中调用TEEC_InvokeCommand接口时,该函数会将会话ID、命令ID,以及需要传递给TA的参数信息通过ioctl的系统调用发送到OP-TEE的驱动中,OP-TEE驱动会调用optee_invoke_func函数将需要传递给TA的参数信息保存在共享内存中,并触发安全监控模式调用(smc)切换到Monitor模式(ARMv7)或EL3(ARMv8)中进行安全世界状态的处理。
调用TA命令触发的安全监控模式调用最终会被作为标准安全监控模式调用进行解析,并建立一个专门的线程进入thread_std_smc_entry函数去执行,线程运行到tee_entry_std函数时会对安全监控模式调用(smc)进行判定,并进入调用TA命令的分支。调用TA命令的操作在OP-TEE中的执行流程如图13-5所示。(这里如果你知道学习过atf的的smc调用就很好理解。)
根据会话ID获取到已经创建的会话内容后,OP-TEE会调用tee_ta_invoke_command函数开始对调用TA命令的操作请求进行处理,该函数的内容如下:
(最后)
下面详细看看这个静态TA的调用命令操作的实现
1、静态TA的调用命令操作的实现
静态的TA运行于OP-TEE的内核空间。
TEE通过从CA传来的会话ID获取需要被调用的静态TA的上下文,然后从上下文中获取该静态TA提供的invoke_command_entry_point接口。
invoke_command_entry_point对应的函数会根据不同的命令ID执行相应的操作,并将执行结果返回给CA。
静态TA的调用命令操作的整个操作过程如图13-6所示。
在对静态的TA执行创建会话操作时会将该TA的运行上下文中的ctx->ops变量赋值成pseudo_ta_ops,故调用ss->ctx->ops->enter_invoke_cmd就会调用pseudo_ta_enter_invoke_cmd函数。该函数的内容和注释如下:
2、动态TA的调用命令操作实现
动态TA运行在OP-TEE的用户空间,OP-TEE通过从CA传来的会话ID找到对应动态TA,并获取该动态TA的运行上下文,然后调用sess->ctx->ops成员中的调用命令的方法,即user_ta_enter_invoke_cmd函数。
这是因为在创建CA与该动态TA的会话时,sess->ctx->ops被赋值成user_ta_ops,该变量中的enter_invoke_cmd成员指向的就是user_ta_enter_invoke_cmd函数。
user_ta_enter_invoke_cmd函数会执行运行空间的切换操作,关于如何从OP-TEE的内核空间进入OP-TEE的用户空间,可参阅13.1.2节“用户空间的entry_open_session函数”部分。动态TA的调用命令的整个操作过程如图13-7所示
当系统运行于OP-TEE的用户空间后,会调用用户空间的entry_invoke_command函数执行调用命令的操作。用户空间的entry_invoke_command函数定义在optee_os/lib/libutee/arch/arm/user_ta_entry.c文件中,该函数内容如下:
OP-TEE调用用户空间的entry_invoke_command函数时,创建的线程就已进入到TA镜像的上下文中运行了,当调用TA_InvokeCommandEntryPoint函数时就会去执行TA镜像中定义的TA_InvokeCommandEntryPoint函数,该函数具体会执行什么操作就由具体的TA决定,一般是根据命令id执行定义好的操作。
下一篇就是关于关闭这个TA的,然后对于整个TA与CA的流程就画句号。
参考资料:
《手机安全和可信应用开发指南》