238 lines
5.3 KiB
C
238 lines
5.3 KiB
C
|
|
// SPDX-License-Identifier: GPL-2.0
|
||
|
|
/*
|
||
|
|
* Copyright (c) 2015 MediaTek Inc.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "cmdq_core.h"
|
||
|
|
#include "cmdq_sec_trustonic.h"
|
||
|
|
|
||
|
|
void cmdq_sec_setup_tee_context(struct cmdq_sec_tee_context *tee)
|
||
|
|
{
|
||
|
|
/* 09010000 0000 0000 0000000000000000 */
|
||
|
|
tee->uuid = (struct mc_uuid_t){ { 9, 1, 0, 0, 0, 0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0, 0, 0, 0 } };
|
||
|
|
}
|
||
|
|
|
||
|
|
s32 cmdq_sec_init_context(struct cmdq_sec_tee_context *tee)
|
||
|
|
{
|
||
|
|
s32 status;
|
||
|
|
enum mc_result mcRet = MC_DRV_ERR_UNKNOWN;
|
||
|
|
s32 retry_cnt = 0, max_retry = 30;
|
||
|
|
|
||
|
|
do {
|
||
|
|
status = 0;
|
||
|
|
mcRet = mc_open_device(MC_DEVICE_ID_DEFAULT);
|
||
|
|
|
||
|
|
/* Currently, a process context limits to open mobicore device
|
||
|
|
* once, and mc_open_device dose not support reference cout
|
||
|
|
* so skip the false alarm error....
|
||
|
|
*/
|
||
|
|
if (mcRet == MC_DRV_ERR_INVALID_OPERATION) {
|
||
|
|
CMDQ_MSG(
|
||
|
|
"[SEC]init_context: already opened, continue to execution\n");
|
||
|
|
status = 0;
|
||
|
|
tee->open_mobicore_by_other = 1;
|
||
|
|
} else if (mcRet != MC_DRV_OK) {
|
||
|
|
CMDQ_ERR("[SEC]init_context: err:0x%x, retry:%d\n",
|
||
|
|
mcRet, retry_cnt);
|
||
|
|
status = -1;
|
||
|
|
msleep_interruptible(2000);
|
||
|
|
retry_cnt++;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
} while (retry_cnt < max_retry);
|
||
|
|
|
||
|
|
if (retry_cnt >= max_retry) {
|
||
|
|
/* print error message */
|
||
|
|
CMDQ_ERR(
|
||
|
|
"[SEC]init_context fail: status:%d mcRet:0x%x retry:%d\n",
|
||
|
|
status, mcRet, retry_cnt);
|
||
|
|
} else {
|
||
|
|
CMDQ_MSG("[SEC]init_context: status:%d mcRet:0x%x retry:%d\n",
|
||
|
|
status, mcRet, retry_cnt);
|
||
|
|
}
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
s32 cmdq_sec_deinit_context(struct cmdq_sec_tee_context *tee)
|
||
|
|
{
|
||
|
|
s32 status = 0;
|
||
|
|
enum mc_result mcRet = 0;
|
||
|
|
|
||
|
|
if (tee->open_mobicore_by_other == 1) {
|
||
|
|
/* do nothing */
|
||
|
|
/* let last user to close mobicore.... */
|
||
|
|
CMDQ_MSG(
|
||
|
|
"[SEC]_MOBICORE_CLOSE: opened by other, bypass device close\n");
|
||
|
|
} else {
|
||
|
|
mcRet = mc_close_device(MC_DEVICE_ID_DEFAULT);
|
||
|
|
CMDQ_MSG(
|
||
|
|
"[SEC]_MOBICORE_CLOSE: status:%d ret:0x%x openMobicoreByOther:%d\n",
|
||
|
|
status, mcRet, tee->open_mobicore_by_other);
|
||
|
|
if (mcRet != MC_DRV_OK) {
|
||
|
|
CMDQ_ERR("[SEC]_MOBICORE_CLOSE: err:0x%x\n", mcRet);
|
||
|
|
status = -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
s32 cmdq_sec_allocate_wsm(struct cmdq_sec_tee_context *tee,
|
||
|
|
void **wsm_buffer, u32 size)
|
||
|
|
{
|
||
|
|
s32 status;
|
||
|
|
enum mc_result mcRet = MC_DRV_OK;
|
||
|
|
|
||
|
|
if (!wsm_buffer)
|
||
|
|
return -EINVAL;
|
||
|
|
|
||
|
|
/* because world shared mem(WSM) will ba managed by mobicore device,
|
||
|
|
* instead of linux kernel vmalloc/kmalloc, call mc_malloc_wasm to
|
||
|
|
* alloc WSM to prvent error such as "can not resolve tci physicall
|
||
|
|
* address" etc
|
||
|
|
*/
|
||
|
|
mcRet = mc_malloc_wsm(MC_DEVICE_ID_DEFAULT, 0, size,
|
||
|
|
(u8 **)wsm_buffer, 0);
|
||
|
|
if (mcRet != MC_DRV_OK) {
|
||
|
|
CMDQ_ERR("[SEC]allocate_wsm: err:0x%x\n", mcRet);
|
||
|
|
status = -EINVAL;
|
||
|
|
} else {
|
||
|
|
CMDQ_MSG("[SEC]allocate_wsm: status:%d *ppWsm:0x%p\n",
|
||
|
|
status, *wsm_buffer);
|
||
|
|
tee->wsm_size = size;
|
||
|
|
}
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
s32 cmdq_sec_free_wsm(struct cmdq_sec_tee_context *tee,
|
||
|
|
void **wsm_buffer)
|
||
|
|
{
|
||
|
|
s32 status = 0;
|
||
|
|
enum mc_result mcRet;
|
||
|
|
|
||
|
|
if (!wsm_buffer)
|
||
|
|
return -EINVAL;
|
||
|
|
|
||
|
|
mcRet = mc_free_wsm(MC_DEVICE_ID_DEFAULT,
|
||
|
|
*wsm_buffer);
|
||
|
|
|
||
|
|
if (mcRet != MC_DRV_OK) {
|
||
|
|
CMDQ_ERR("free_wsm: err:0x%x", mcRet);
|
||
|
|
status = -EINVAL;
|
||
|
|
} else {
|
||
|
|
*wsm_buffer = NULL;
|
||
|
|
CMDQ_VERBOSE("free_wsm: ret:0x%x\n", mcRet);
|
||
|
|
}
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
s32 cmdq_sec_open_session(struct cmdq_sec_tee_context *tee,
|
||
|
|
void *wsm_buffer)
|
||
|
|
{
|
||
|
|
s32 status;
|
||
|
|
s32 retry_cnt = 0, max_retry = 30;
|
||
|
|
enum mc_result mcRet = MC_DRV_OK;
|
||
|
|
|
||
|
|
if (!wsm_buffer) {
|
||
|
|
CMDQ_ERR("[SEC]open_session: invalid param wsm buffer:0x%p\n",
|
||
|
|
wsm_buffer);
|
||
|
|
return -EINVAL;
|
||
|
|
}
|
||
|
|
|
||
|
|
tee->session.device_id = MC_DEVICE_ID_DEFAULT;
|
||
|
|
|
||
|
|
do {
|
||
|
|
mcRet = mc_open_session(&tee->session,
|
||
|
|
&tee->uuid, wsm_buffer, tee->wsm_size);
|
||
|
|
if (mcRet != MC_DRV_OK) {
|
||
|
|
CMDQ_ERR("[SEC]open_session: err:0x%x retry:%d\n",
|
||
|
|
mcRet, retry_cnt);
|
||
|
|
retry_cnt++;
|
||
|
|
msleep_interruptible(2000);
|
||
|
|
status = -1;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Open Session success */
|
||
|
|
status = 0;
|
||
|
|
break;
|
||
|
|
} while (retry_cnt < max_retry);
|
||
|
|
|
||
|
|
if (retry_cnt >= max_retry) {
|
||
|
|
/* print error message */
|
||
|
|
CMDQ_ERR(
|
||
|
|
"[SEC]open_session fail: status:%d mcRet:0x%x retry:%d\n",
|
||
|
|
status, mcRet, retry_cnt);
|
||
|
|
} else {
|
||
|
|
CMDQ_MSG(
|
||
|
|
"[SEC]open_session: status:%d mcRet:0x%x retry:%d\n",
|
||
|
|
status, mcRet, retry_cnt);
|
||
|
|
}
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
s32 cmdq_sec_close_session(struct cmdq_sec_tee_context *tee)
|
||
|
|
{
|
||
|
|
s32 status = 0;
|
||
|
|
enum mc_result mcRet = mc_close_session(&tee->session);
|
||
|
|
|
||
|
|
if (mcRet != MC_DRV_OK) {
|
||
|
|
CMDQ_ERR("close_session: err:0x%x", mcRet);
|
||
|
|
status = -1;
|
||
|
|
}
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
s32 cmdq_sec_execute_session(struct cmdq_sec_tee_context *tee,
|
||
|
|
s32 timeout_ms)
|
||
|
|
{
|
||
|
|
enum mc_result mcRet;
|
||
|
|
s32 status = 0;
|
||
|
|
const s32 sec_timeout = timeout_ms > 0 ?
|
||
|
|
timeout_ms : MC_INFINITE_TIMEOUT;
|
||
|
|
|
||
|
|
CMDQ_PROF_START(current->pid, "CMDQ_SEC_EXE");
|
||
|
|
|
||
|
|
do {
|
||
|
|
/* notify to secure world */
|
||
|
|
mcRet = mc_notify(&tee->session);
|
||
|
|
if (mcRet != MC_DRV_OK) {
|
||
|
|
CMDQ_ERR("[SEC]EXEC: mc_notify err:0x%x\n", mcRet);
|
||
|
|
status = -1;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
CMDQ_MSG("[SEC]EXEC: mc_notify ret:0x%x\n", mcRet);
|
||
|
|
|
||
|
|
/* wait respond */
|
||
|
|
mcRet = mc_wait_notification(&tee->session, sec_timeout);
|
||
|
|
if (mcRet == MC_DRV_ERR_TIMEOUT) {
|
||
|
|
CMDQ_ERR(
|
||
|
|
"[SEC]EXEC: mc_wait_notification timeout, err:0x%x secureWoldTimeout_ms:%d\n",
|
||
|
|
mcRet, sec_timeout);
|
||
|
|
status = -ETIMEDOUT;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (mcRet != MC_DRV_OK) {
|
||
|
|
CMDQ_ERR("[SEC]EXEC: mc_wait_notification err:0x%x\n",
|
||
|
|
mcRet);
|
||
|
|
status = -1;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
CMDQ_MSG("[SEC]EXEC: mc_wait_notification err:%d\n", mcRet);
|
||
|
|
} while (0);
|
||
|
|
|
||
|
|
CMDQ_PROF_END(current->pid, "CMDQ_SEC_EXE");
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|