OPTEE std call process
Table of Contents
OPTEE 主要通过std call的方式来给non-secure world来提供服务,在本文中主要研究一下这个服务如何实现,给以后的框架设计提供参考。
为了方便起见,这里使用optee example中的hello_world来作为例子
Example Code
#include <err.h>#include <stdio.h>#include <string.h>/* OP-TEE TEE client API (built by optee_client) */#include <tee_client_api.h>/* For the UUID (found in the TA's h-file(s)) */#include <hello_world_ta.h>int main(void){TEEC_Result res;TEEC_Context ctx;TEEC_Session sess;TEEC_Operation op;TEEC_UUID uuid = TA_HELLO_WORLD_UUID;uint32_t err_origin;/* Initialize a context connecting us to the TEE */res = TEEC_InitializeContext(NULL, &ctx);if (res != TEEC_SUCCESS)errx(1, "TEEC_InitializeContext failed with code 0x%x", res);/** Open a session to the "hello world" TA, the TA will print "hello* world!" in the log when the session is created.*/res = TEEC_OpenSession(&ctx, &sess, &uuid,TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);if (res != TEEC_SUCCESS)errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x",res, err_origin);/** Execute a function in the TA by invoking it, in this case* we're incrementing a number.** The value of command ID part and how the parameters are* interpreted is part of the interface provided by the TA.*//* Clear the TEEC_Operation struct */memset(&op, 0, sizeof(op));/** Prepare the argument. Pass a value in the first parameter,* the remaining three parameters are unused.*/op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE,TEEC_NONE, TEEC_NONE);op.params[0].value.a = 42;/** TA_HELLO_WORLD_CMD_INC_VALUE is the actual function in the TA to be* called.*/printf("Invoking TA to increment %d\n", op.params[0].value.a);res = TEEC_InvokeCommand(&sess, TA_HELLO_WORLD_CMD_INC_VALUE, &op,&err_origin);if (res != TEEC_SUCCESS)errx(1, "TEEC_InvokeCommand failed with code 0x%x origin 0x%x",res, err_origin);printf("TA incremented value to %d\n", op.params[0].value.a);/** We're done with the TA, close the session and* destroy the context.** The TA will print "Goodbye!" in the log when the* session is closed.*/TEEC_CloseSession(&sess);TEEC_FinalizeContext(&ctx);return 0;}
由上面的代码可知,non secureworld共需要5步来完成整个服务调用
- 初始化context
- 打开session
- 调用session中的服务,命令
- 关闭session
- 释放context
std call process
下图展示了一次helloworld的调用中,系统内部的大致流程,由此图可知,每次系统进行trusted world服务调用时,系统都需要进入smc来进行运行环境的切换(aarch64进行secure/non secure的切换必须通过EL3来完成)

通过上面示意图可以看到,系统调用trusted world的服务时,系统会经过比较长的链路,从 NSEL0 -> NSEL2/NSEL1 -> EL3 -> SEL1 -> SEL0 一共需要切换多次的cpu执行环境
optee data struct
optee服务调用时涉及很多个数据结构的传递,下面的图展示了一下open_session操作时各个数据结构之间的大致关系,分析代码时可以作为参考
