unplugged-kernel/drivers/misc/mediatek/m4u/2.0/m4u_sec_gp.c

213 lines
4.4 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include <linux/notifier.h>
#include "m4u_priv.h"
#include "m4u.h"
#include "m4u_hw.h"
#include "m4u_priv.h"
#include "tee_client_api.h"
#include "tz_m4u.h"
#include "m4u_sec_gp.h"
static struct m4u_sec_gp_context m4u_gp_ta_ctx = {
#if defined(CONFIG_MICROTRUST_TEE_SUPPORT) || \
defined(CONFIG_TRUSTONIC_TEE_SUPPORT)
.uuid = (struct TEEC_UUID)M4U_TA_UUID,
#else
.uuid = (TEEC_UUID)M4U_TA_UUID,
#endif
.ctx_lock = __MUTEX_INITIALIZER(m4u_gp_ta_ctx.ctx_lock),
.ctx_type = CTX_TYPE_TA,
};
struct m4u_sec_context m4u_ta_ctx;
void m4u_sec_set_context(void)
{
m4u_ta_ctx.name = "m4u_ta";
m4u_ta_ctx.imp = &m4u_gp_ta_ctx;
}
static int m4u_exec_session(struct m4u_sec_context *ctx)
{
int ret;
struct TEEC_Operation m4u_operation;
struct m4u_sec_gp_context *gp_ctx = ctx->imp;
if (!ctx->m4u_msg) {
m4u_err("%s TCI/DCI error\n", __func__);
return -1;
}
m4u_high_info("%s, Notify 0x%x\n", __func__, ctx->m4u_msg->cmd);
memset(&m4u_operation, 0, sizeof(struct TEEC_Operation));
#if defined(CONFIG_MICROTRUST_TEE_SUPPORT) || \
defined(CONFIG_TRUSTONIC_TEE_SUPPORT)
m4u_operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INPUT,
TEEC_NONE, TEEC_NONE, TEEC_NONE);
#endif
m4u_operation.params[0].memref.parent = &gp_ctx->shared_mem;
m4u_operation.params[0].memref.offset = 0;
m4u_operation.params[0].memref.size = gp_ctx->shared_mem.size;
ret = TEEC_InvokeCommand(&gp_ctx->session,
ctx->m4u_msg->cmd, &m4u_operation, NULL);
if (ret != TEEC_SUCCESS) {
m4u_aee_err("tz_m4u Notify failed: %d\n", ret);
goto exit;
}
m4u_high_info("%s, get_resp %x\n", __func__, ctx->m4u_msg->cmd);
exit:
return ret;
}
static int m4u_sec_gp_init(struct m4u_sec_context *ctx)
{
int ret;
struct m4u_sec_gp_context *gp_ctx = ctx->imp;
ret = TEEC_InitializeContext(TA_UUID, &gp_ctx->ctx);
if (ret != TEEC_SUCCESS) {
m4u_err("teec_initialize_context failed: %x\n", ret);
return ret;
}
m4u_high_info("%s, ta teec_initialize_context\n", __func__);
memset(&gp_ctx->shared_mem, 0, sizeof(struct TEEC_SharedMemory));
gp_ctx->shared_mem.size = sizeof(struct m4u_msg);
gp_ctx->shared_mem.flags = TEEC_MEM_INPUT;
ret = TEEC_AllocateSharedMemory(&gp_ctx->ctx, &gp_ctx->shared_mem);
if (ret == TEEC_SUCCESS) {
ctx->m4u_msg = (struct m4u_msg *)gp_ctx->shared_mem.buffer;
m4u_high_info("teec_allocate_shared_memory buf: 0x%p\n",
gp_ctx->shared_mem.buffer);
} else {
m4u_err("teec_allocate_shared_memory failed: %d\n", ret);
goto exit_finalize;
}
if (!ctx->m4u_msg) {
m4u_err("m4u msg is invalid\n");
return -1;
}
if (!gp_ctx->init) {
ret = TEEC_OpenSession(&gp_ctx->ctx, &gp_ctx->session,
&gp_ctx->uuid, TEEC_LOGIN_PUBLIC, NULL, NULL, NULL);
if (ret != TEEC_SUCCESS) {
m4u_err("teec_open_session failed: %x\n", ret);
goto exit_release;
}
gp_ctx->init = 1;
}
m4u_high_info("%s, open TCI session success\n", __func__);
return ret;
exit_release:
TEEC_ReleaseSharedMemory(&gp_ctx->shared_mem);
exit_finalize:
TEEC_FinalizeContext(&gp_ctx->ctx);
return ret;
}
static int m4u_sec_gp_deinit(struct m4u_sec_context *ctx)
{
struct m4u_sec_gp_context *gp_ctx = ctx->imp;
TEEC_ReleaseSharedMemory(&gp_ctx->shared_mem);
TEEC_CloseSession(&gp_ctx->session);
TEEC_FinalizeContext(&gp_ctx->ctx);
gp_ctx->init = 0;
m4u_err("%s done\n", __func__);
return 0;
}
static int m4u_sec_ta_open(void)
{
int ret;
ret = m4u_sec_gp_init(&m4u_ta_ctx);
return ret;
}
static int m4u_sec_ta_close(void)
{
int ret;
ret = m4u_sec_gp_deinit(&m4u_ta_ctx);
return ret;
}
int m4u_sec_context_init(void)
{
int ret;
ret = m4u_sec_ta_open();
if (ret)
return ret;
m4u_high_info("%s:ta open session success\n", __func__);
return 0;
}
int m4u_sec_context_deinit(void)
{
int ret;
ret = m4u_sec_ta_close();
return ret;
}
struct m4u_sec_context *m4u_sec_ctx_get(unsigned int cmd)
{
struct m4u_sec_context *ctx = NULL;
struct m4u_sec_gp_context *gp_ctx;
ctx = &m4u_ta_ctx;
gp_ctx = ctx->imp;
if (!gp_ctx->init) {
M4UERR("%s before init\n", __func__);
return NULL;
}
mutex_lock(&gp_ctx->ctx_lock);
return ctx;
}
int m4u_sec_ctx_put(struct m4u_sec_context *ctx)
{
struct m4u_sec_gp_context *gp_ctx = ctx->imp;
mutex_unlock(&gp_ctx->ctx_lock);
return 0;
}
int m4u_exec_cmd(struct m4u_sec_context *ctx)
{
int ret;
if (ctx->m4u_msg == NULL) {
m4u_err("%s TCI/DCI error\n", __func__);
return -1;
}
ret = m4u_exec_session(ctx);
if (ret < 0)
return -1;
return 0;
}