user space发送的open session命令最终是在tee_entry_std中处理的
void tee_entry_std(struct thread_smc_args *smc_args)
{
/* Enable foreign interrupts for STD calls */
thread_set_foreign_intr(true);
switch (arg->cmd) {
case OPTEE_MSG_CMD_OPEN_SESSION:
entry_open_session(smc_args, arg, num_params);
break;
case OPTEE_MSG_CMD_CLOSE_SESSION:
entry_close_session(smc_args, arg, num_params);
break;
case OPTEE_MSG_CMD_INVOKE_COMMAND:
entry_invoke_command(smc_args, arg, num_params);
break;
case OPTEE_MSG_CMD_CANCEL:
entry_cancel(smc_args, arg, num_params);
break;
default:
EMSG("Unknown cmd 0x%x\n", arg->cmd);
smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD;
}
}
可以看到tee_entry_std中处理的命令有三个分别是open session/close session/invoke/cancel,这里先已open session为例
在entry_open_session 中调用get_open_session_meta和copy_in_params 检查参数后,最终调用tee_ta_open_session->tee_ta_init_session 来找到session
static TEE_Result tee_ta_init_session(TEE_ErrorOrigin *err,
struct tee_ta_session_head *open_sessions,
const TEE_UUID *uuid,
struct tee_ta_session **sess)
{
TEE_Result res;
struct tee_ta_ctx *ctx;
struct tee_ta_session *s = calloc(1, sizeof(struct tee_ta_session));
*err = TEE_ORIGIN_TEE;
if (!s)
return TEE_ERROR_OUT_OF_MEMORY;
s->cancel_mask = true;
condvar_init(&s->refc_cv);
condvar_init(&s->lock_cv);
s->lock_thread = THREAD_ID_INVALID;
s->ref_count = 1;
/*
* We take the global TA mutex here and hold it while doing
* RPC to load the TA. This big critical section should be broken
* down into smaller pieces.
*/
mutex_lock(&tee_ta_mutex);
TAILQ_INSERT_TAIL(open_sessions, s, link);
/* Look for already loaded TA */
//tee_ctxes 这个list上根据uuid 查找TA,所有已经load到dram中的TA都会在这个list中
ctx = tee_ta_context_find(uuid);
if (ctx) {
//如果已经找到TA,就直接返回了
res = tee_ta_init_session_with_context(ctx, s);
if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND)
goto out;
}
/* Look for static TA */
res = tee_ta_init_pseudo_ta_session(uuid, s);
if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND)
goto out;
/* Look for user TA */
res = tee_ta_init_user_ta_session(uuid, s);
out:
if (res == TEE_SUCCESS) {
*sess = s;
} else {
TAILQ_REMOVE(open_sessions, s, link);
free(s);
}
mutex_unlock(&tee_ta_mutex);
return res;
}
//从tee_ta_init_session 中知道TA 有两种,一种是所谓的静态TA,是和optee build在一起的,因此调用tee_ta_init_pseudo_ta_session来查找
TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid,
struct tee_ta_session *s)
{
struct pseudo_ta_ctx *stc = NULL;
struct tee_ta_ctx *ctx;
const struct pseudo_ta_head *ta;
DMSG(" Lookup for pseudo TA %pUl", (void *)uuid);
//可见所有的静态TA 都是放在__start_ta_head_section ~ __stop_ta_head_section 这个段中
ta = &__start_ta_head_section;
while (true) {
if (ta >= &__stop_ta_head_section)
return TEE_ERROR_ITEM_NOT_FOUND;
//根据uuid 比较是否找到TA
if (memcmp(&ta->uuid, uuid, sizeof(TEE_UUID)) == 0)
break;
ta++;
}
/* Load a new TA and create a session */
DMSG(" Open %s", ta->name);
找到后对struct tee_ta_ctx *ctx; 赋值
stc = calloc(1, sizeof(struct pseudo_ta_ctx));
if (!stc)
return TEE_ERROR_OUT_OF_MEMORY;
ctx = &stc->ctx;
ctx->ref_count = 1;
s->ctx = ctx;
ctx->flags = ta->flags;
stc->pseudo_ta = ta;
ctx->uuid = ta->uuid;
ctx->ops = &pseudo_ta_ops;
TAILQ_INSERT_TAIL(&tee_ctxes, ctx, link);
DMSG(" %s : %pUl", stc->pseudo_ta->name, (void *)&ctx->uuid);
return TEE_SUCCESS;
}
第二中是user TA在tee_ta_init_session 中通过tee_ta_init_user_ta_session 来查找
/* Look for user TA */
res = tee_ta_init_user_ta_session(uuid, s);
TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid,
struct tee_ta_session *s)
{
TEE_Result res;
if (!user_ta_store)
return TEE_ERROR_ITEM_NOT_FOUND;
DMSG("Load user TA %pUl", (void *)uuid);
可见调用ta_load来加载
res = ta_load(uuid, user_ta_store, &s->ctx);
if (res == TEE_SUCCESS)
s->ctx->ops = &user_ta_ops;
return res;
}
在ta_load 中会调用user_ta_store的open函数
而这里的
TEE_Result tee_ta_register_ta_store(const struct user_ta_store_ops *ops)
{
user_ta_store = ops;
return TEE_SUCCESS;
}
static const struct user_ta_store_ops ops = {
.open = ta_open,
.get_size = ta_get_size,
.read = ta_read,
.close = ta_close,
};
static TEE_Result register_supplicant_user_ta(void)
{
return tee_ta_register_ta_store(&ops);
}
可见这里的user_ta_store 就是ops
static TEE_Result ta_load(const TEE_UUID *uuid,
const struct user_ta_store_ops *ta_store,
struct tee_ta_ctx **ta_ctx)
{
TEE_Result res;
uint32_t mandatory_flags = TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR;
uint32_t optional_flags = mandatory_flags | TA_FLAG_SINGLE_INSTANCE |
TA_FLAG_MULTI_SESSION | TA_FLAG_SECURE_DATA_PATH |
TA_FLAG_INSTANCE_KEEP_ALIVE | TA_FLAG_CACHE_MAINTENANCE;
struct user_ta_ctx *utc = NULL;
struct ta_head *ta_head;
struct user_ta_store_handle *ta_handle = NULL;
//调用ops的open 函数得到ta_handle
res = ta_store->open(uuid, &ta_handle);
if (res != TEE_SUCCESS)
return res;
/* Register context */
//申请注册的struct user_ta_ctx *utc
utc = calloc(1, sizeof(struct user_ta_ctx));
if (!utc) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto error_return;
}
TAILQ_INIT(&utc->open_sessions);
TAILQ_INIT(&utc->cryp_states);
TAILQ_INIT(&utc->objects);
TAILQ_INIT(&utc->storage_enums);
//调用load_elf 来装载ta_handle对应的elf
res = load_elf(utc, ta_store, ta_handle);
if (res != TEE_SUCCESS)
goto error_return;
utc->load_addr = tee_mmu_get_load_addr(&utc->ctx);
ta_head = (struct ta_head *)(vaddr_t)utc->load_addr;
if (memcmp(&ta_head->uuid, uuid, sizeof(TEE_UUID)) != 0) {
res = TEE_ERROR_SECURITY;
goto error_return;
}
/* check input flags bitmask consistency and save flags */
if ((ta_head->flags & optional_flags) != ta_head->flags ||
(ta_head->flags & mandatory_flags) != mandatory_flags) {
EMSG("TA flag issue: flags=%x optional=%x mandatory=%x",
ta_head->flags, optional_flags, mandatory_flags);
res = TEE_ERROR_BAD_FORMAT;
goto error_return;
}
}
void tee_entry_std(struct thread_smc_args *smc_args)
{
/* Enable foreign interrupts for STD calls */
thread_set_foreign_intr(true);
switch (arg->cmd) {
case OPTEE_MSG_CMD_OPEN_SESSION:
entry_open_session(smc_args, arg, num_params);
break;
case OPTEE_MSG_CMD_CLOSE_SESSION:
entry_close_session(smc_args, arg, num_params);
break;
case OPTEE_MSG_CMD_INVOKE_COMMAND:
entry_invoke_command(smc_args, arg, num_params);
break;
case OPTEE_MSG_CMD_CANCEL:
entry_cancel(smc_args, arg, num_params);
break;
default:
EMSG("Unknown cmd 0x%x\n", arg->cmd);
smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD;
}
}
可以看到tee_entry_std中处理的命令有三个分别是open session/close session/invoke/cancel,这里先已open session为例
在entry_open_session 中调用get_open_session_meta和copy_in_params 检查参数后,最终调用tee_ta_open_session->tee_ta_init_session 来找到session
static TEE_Result tee_ta_init_session(TEE_ErrorOrigin *err,
struct tee_ta_session_head *open_sessions,
const TEE_UUID *uuid,
struct tee_ta_session **sess)
{
TEE_Result res;
struct tee_ta_ctx *ctx;
struct tee_ta_session *s = calloc(1, sizeof(struct tee_ta_session));
*err = TEE_ORIGIN_TEE;
if (!s)
return TEE_ERROR_OUT_OF_MEMORY;
s->cancel_mask = true;
condvar_init(&s->refc_cv);
condvar_init(&s->lock_cv);
s->lock_thread = THREAD_ID_INVALID;
s->ref_count = 1;
/*
* We take the global TA mutex here and hold it while doing
* RPC to load the TA. This big critical section should be broken
* down into smaller pieces.
*/
mutex_lock(&tee_ta_mutex);
TAILQ_INSERT_TAIL(open_sessions, s, link);
/* Look for already loaded TA */
//tee_ctxes 这个list上根据uuid 查找TA,所有已经load到dram中的TA都会在这个list中
ctx = tee_ta_context_find(uuid);
if (ctx) {
//如果已经找到TA,就直接返回了
res = tee_ta_init_session_with_context(ctx, s);
if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND)
goto out;
}
/* Look for static TA */
res = tee_ta_init_pseudo_ta_session(uuid, s);
if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND)
goto out;
/* Look for user TA */
res = tee_ta_init_user_ta_session(uuid, s);
out:
if (res == TEE_SUCCESS) {
*sess = s;
} else {
TAILQ_REMOVE(open_sessions, s, link);
free(s);
}
mutex_unlock(&tee_ta_mutex);
return res;
}
//从tee_ta_init_session 中知道TA 有两种,一种是所谓的静态TA,是和optee build在一起的,因此调用tee_ta_init_pseudo_ta_session来查找
TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid,
struct tee_ta_session *s)
{
struct pseudo_ta_ctx *stc = NULL;
struct tee_ta_ctx *ctx;
const struct pseudo_ta_head *ta;
DMSG(" Lookup for pseudo TA %pUl", (void *)uuid);
//可见所有的静态TA 都是放在__start_ta_head_section ~ __stop_ta_head_section 这个段中
ta = &__start_ta_head_section;
while (true) {
if (ta >= &__stop_ta_head_section)
return TEE_ERROR_ITEM_NOT_FOUND;
//根据uuid 比较是否找到TA
if (memcmp(&ta->uuid, uuid, sizeof(TEE_UUID)) == 0)
break;
ta++;
}
/* Load a new TA and create a session */
DMSG(" Open %s", ta->name);
找到后对struct tee_ta_ctx *ctx; 赋值
stc = calloc(1, sizeof(struct pseudo_ta_ctx));
if (!stc)
return TEE_ERROR_OUT_OF_MEMORY;
ctx = &stc->ctx;
ctx->ref_count = 1;
s->ctx = ctx;
ctx->flags = ta->flags;
stc->pseudo_ta = ta;
ctx->uuid = ta->uuid;
ctx->ops = &pseudo_ta_ops;
TAILQ_INSERT_TAIL(&tee_ctxes, ctx, link);
DMSG(" %s : %pUl", stc->pseudo_ta->name, (void *)&ctx->uuid);
return TEE_SUCCESS;
}
第二中是user TA在tee_ta_init_session 中通过tee_ta_init_user_ta_session 来查找
/* Look for user TA */
res = tee_ta_init_user_ta_session(uuid, s);
TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid,
struct tee_ta_session *s)
{
TEE_Result res;
if (!user_ta_store)
return TEE_ERROR_ITEM_NOT_FOUND;
DMSG("Load user TA %pUl", (void *)uuid);
可见调用ta_load来加载
res = ta_load(uuid, user_ta_store, &s->ctx);
if (res == TEE_SUCCESS)
s->ctx->ops = &user_ta_ops;
return res;
}
在ta_load 中会调用user_ta_store的open函数
而这里的
TEE_Result tee_ta_register_ta_store(const struct user_ta_store_ops *ops)
{
user_ta_store = ops;
return TEE_SUCCESS;
}
static const struct user_ta_store_ops ops = {
.open = ta_open,
.get_size = ta_get_size,
.read = ta_read,
.close = ta_close,
};
static TEE_Result register_supplicant_user_ta(void)
{
return tee_ta_register_ta_store(&ops);
}
可见这里的user_ta_store 就是ops
static TEE_Result ta_load(const TEE_UUID *uuid,
const struct user_ta_store_ops *ta_store,
struct tee_ta_ctx **ta_ctx)
{
TEE_Result res;
uint32_t mandatory_flags = TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR;
uint32_t optional_flags = mandatory_flags | TA_FLAG_SINGLE_INSTANCE |
TA_FLAG_MULTI_SESSION | TA_FLAG_SECURE_DATA_PATH |
TA_FLAG_INSTANCE_KEEP_ALIVE | TA_FLAG_CACHE_MAINTENANCE;
struct user_ta_ctx *utc = NULL;
struct ta_head *ta_head;
struct user_ta_store_handle *ta_handle = NULL;
//调用ops的open 函数得到ta_handle
res = ta_store->open(uuid, &ta_handle);
if (res != TEE_SUCCESS)
return res;
/* Register context */
//申请注册的struct user_ta_ctx *utc
utc = calloc(1, sizeof(struct user_ta_ctx));
if (!utc) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto error_return;
}
TAILQ_INIT(&utc->open_sessions);
TAILQ_INIT(&utc->cryp_states);
TAILQ_INIT(&utc->objects);
TAILQ_INIT(&utc->storage_enums);
//调用load_elf 来装载ta_handle对应的elf
res = load_elf(utc, ta_store, ta_handle);
if (res != TEE_SUCCESS)
goto error_return;
utc->load_addr = tee_mmu_get_load_addr(&utc->ctx);
ta_head = (struct ta_head *)(vaddr_t)utc->load_addr;
if (memcmp(&ta_head->uuid, uuid, sizeof(TEE_UUID)) != 0) {
res = TEE_ERROR_SECURITY;
goto error_return;
}
/* check input flags bitmask consistency and save flags */
if ((ta_head->flags & optional_flags) != ta_head->flags ||
(ta_head->flags & mandatory_flags) != mandatory_flags) {
EMSG("TA flag issue: flags=%x optional=%x mandatory=%x",
ta_head->flags, optional_flags, mandatory_flags);
res = TEE_ERROR_BAD_FORMAT;
goto error_return;
}
}