// ------------------------------------------------------------- static mcResult_t executeCmd(uint32_t *num1, uint32_t *num2, uint32_t *result, tciCommandId_t cmd) { mcResult_t ret; if(NULL == tci) { LOG_E("TCI has not been set up properly - exiting"); return MC_DRV_ERR_NO_FREE_MEMORY; } tci->cmdfoo.header.commandId = cmd; tci->cmdfoo.len = 0; tci->cmdfoo.respLen = 0; tci->Num1 = *num1; tci->Num2 = *num2; LOG_I("Preparing command message in TCI"); LOG_I("Notifying the trustlet"); ret = mcNotify(&sessionHandle); if (MC_DRV_OK != ret) { LOG_E("Notify failed: %d", ret); goto exit; } LOG_I("Waiting for the Trustlet response"); ret = mcWaitNotification(&sessionHandle, -1); if (MC_DRV_OK != ret) { LOG_E("Wait for response notification failed: 0x%x", ret); goto exit; } *result = tci->ResultData; LOG_I("Verifying that the Trustlet sent a response."); if (RSP_ID(cmd) != tci->rspfoo.header.responseId) { LOG_E("Trustlet did not send a response: %d", tci->rspfoo.header.responseId); ret = MC_DRV_ERR_INVALID_RESPONSE; goto exit; } if (RET_OK != tci->rspfoo.header.returnCode) { LOG_E("Trustlet did not send a valid return code: %d", tci->rspfoo.header.returnCode); ret = tci->rspfoo.header.returnCode; } exit: return ret; }
// ------------------------------------------------------------- static mcResult_t executeCmd(uint32_t *index, uint32_t *result, tciCommandId_t cmd) { mcResult_t ret; if(NULL == tci) { printf("TCI has not been set up properly - exiting\n"); return MC_DRV_ERR_NO_FREE_MEMORY; } tci->cmd.header.commandId = cmd; tci->cmd.len = 0; tci->cmd.respLen = 0; tci->index= *index; printf("Preparing command message in TCI\n"); printf("Notifying the trustlet\n"); ret = mcNotify(&sessionHandle); if (MC_DRV_OK != ret) { printf("Notify failed: %d\n", ret); goto exit; } printf("Waiting for the Trustlet response\n"); ret = mcWaitNotification(&sessionHandle, -1); if (MC_DRV_OK != ret) { printf("Wait for response notification failed: 0x%x\n", ret); goto exit; } *result = tci->result; printf("Verifying that the Trustlet sent a response.\n"); if (RSP_ID(cmd) != tci->rsp.header.responseId) { printf("Trustlet did not send a response: %d\n", tci->rsp.header.responseId); ret = MC_DRV_ERR_INVALID_RESPONSE; goto exit; } if (RET_OK != tci->rsp.header.returnCode) { printf("Trustlet did not send a valid return code: %d\n", tci->rsp.header.returnCode); ret = tci->rsp.header.returnCode; } exit: return ret; }
/** * DCI handler loop. this is the function where notifications from Nwd are handled */ _NORETURN void drDcihLoop( void ) { dciCommandId_t commandId; dciReturnCode_t ret; drDbgPrintLnf("[Driver DrTemplate] drDcihLoop(): DCI handler thread is running"); for(;;) { /* Initialize return value */ ret = RET_OK; /* Wait for IPC signal */ if (DRAPI_OK != drApiIpcSigWait()) { drDbgPrintLnf("[Driver DrTemplate] drDcihLoop(): drApiIpcSigWait failed"); continue; } /* Get commandid */ commandId = message->command.header.commandId; /* Get & process DCI command */ switch( commandId ) { /** * TODO: Add new command ids and and update existing ones when needed * */ //-------------------------------------- case CMD_ID_01: break; //-------------------------------------- case CMD_ID_02: break; //-------------------------------------- default: break; } message->response.header.responseId = RSP_ID(commandId); message->response.header.returnCode = ret; /* Notify Nwd */ if (DRAPI_OK != drApiNotify()) { drDbgPrintLnf("[Driver DrTemplate] drDcihLoop(): drApiNotify failed"); } } }
static uint32_t send_cmd_to_user(uint32_t command_id) { uint32_t ret = TUI_DCI_ERR_NO_RESPONSE; /* Init shared variables */ g_cmd_id = command_id; g_user_rsp.id = TLC_TUI_CMD_NONE; g_user_rsp.return_code = TLC_TUI_ERR_UNKNOWN_CMD; /* S.LSI : Clean up previous response. */ complete_all(&io_comp); INIT_COMPLETION(io_comp); /* Give way to ioctl thread */ complete(&dci_comp); pr_debug("send_cmd_to_user: give way to ioctl thread\n"); /* Wait for ioctl thread to complete */ wait_for_completion_interruptible(&io_comp); pr_debug("send_cmd_to_user: Got an answer from ioctl thread.\n"); INIT_COMPLETION(io_comp); /* Check id of the cmd processed by ioctl thread (paranoia) */ if (g_user_rsp.id != command_id) { pr_debug("ERROR %s: Wrong response id 0x%08x iso 0x%08x\n", __func__, dci->nwd_rsp.id, RSP_ID(command_id)); ret = TUI_DCI_ERR_INTERNAL_ERROR; } else { /* retrieve return code */ switch (g_user_rsp.return_code) { case TLC_TUI_OK: ret = TUI_DCI_OK; break; case TLC_TUI_ERROR: ret = TUI_DCI_ERR_INTERNAL_ERROR; break; case TLC_TUI_ERR_UNKNOWN_CMD: ret = TUI_DCI_ERR_UNKNOWN_CMD; break; } } return ret; }
static uint32_t sendCmdToUser(uint32_t commandId) { dciReturnCode_t ret = TUI_DCI_ERR_NO_RESPONSE; /* Init shared variables */ gCmdId = commandId; gUserRsp.id = TLC_TUI_CMD_NONE; gUserRsp.returnCode = TLC_TUI_ERR_UNKNOWN_CMD; /* Give way to ioctl thread */ complete(&dciComp); pr_debug("sendCmdToUser: give way to ioctl thread\n"); /* Wait for ioctl thread to complete */ wait_for_completion_interruptible(&ioComp); pr_debug("sendCmdToUser: Got an answer from ioctl thread.\n"); INIT_COMPLETION(ioComp); /* Check id of the cmd processed by ioctl thread (paranoïa) */ if (gUserRsp.id != commandId) { pr_debug("sendCmdToUser ERROR: Wrong response id 0x%08x iso 0x%08x\n", pDci->nwdRsp.id, RSP_ID(commandId)); ret = TUI_DCI_ERR_INTERNAL_ERROR; } else { /* retrieve return code */ switch (gUserRsp.returnCode) { case TLC_TUI_OK: ret = TUI_DCI_OK; break; case TLC_TUI_ERROR: ret = TUI_DCI_ERR_INTERNAL_ERROR; break; case TLC_TUI_ERR_UNKNOWN_CMD: ret = TUI_DCI_ERR_UNKNOWN_CMD; break; } } return ret; }
extern "C" g2ddrmResult_t G2DDRM_Terminate(void) { mcResult_t mcRet; g2ddrmResult_t ret = G2DDRM_SUCCESS; struct tciMessage_t *tci = NULL; LOG_I("G2DDRM_Terminate(): secure G2D driver termination"); do { LOG_I("Check TCI buffer"); tci = ctx.tci_msg; if (NULL == tci) { LOG_E("TCI has not been set up properly - exiting"); ret = G2DDRM_ERROR_EXIT_FAILED; close(g_fd_secmem); break; } LOG_I("Prepare command message in TCI"); tci->cmd.id = CMD_G2DDRM_TERMINATE; mcRet = tlc_communicate(&ctx); if (MC_DRV_OK != mcRet) { LOG_E("tlc_communicate Error!"); ret = G2DDRM_ERROR_EXIT_FAILED; break; } if ((RSP_ID(CMD_G2DDRM_TERMINATE) != tci->resp.id)) { LOG_E("Trustlet did not send a response : %d", tci->resp.id); ret = G2DDRM_ERROR_EXIT_FAILED; break; } LOG_I("Trustlet response is completed"); if (tci->resp.return_code != RET_TL_G2DDRM_OK) { LOG_E("Trustlet did not send a valid return code : %d", tci->resp.return_code); ret = G2DDRM_ERROR_EXIT_FAILED; break; } mcRet = tlc_terminate(); if (MC_DRV_OK != mcRet) { LOG_E("Tlc Close Error"); ret = G2DDRM_ERROR_EXIT_FAILED; break; } LOG_I("Check the Trustlet return code is completed"); close(g_fd_secmem); if (sec_g2d_activate(DRV_ACT) != 0) { ret = G2DDRM_ERROR_EXIT_FAILED; break; } ret = G2DDRM_SUCCESS; } while (false); LOG_I("G2DDRM_Terminate(): secure G2D driver is terminated. ret(%d)", ret); return ret; }
extern "C" g2ddrmResult_t G2DDRM_Blit(struct fimg2d_blit_raw *cmd) { mcResult_t mcRet; g2ddrmResult_t ret = G2DDRM_SUCCESS; mcBulkMap_t mapInfo; struct tciMessage_t *tci = NULL; struct secfd_info secfd; mapInfo.sVirtualAddr = NULL; do { secfd.fd = cmd->src.addr.start; if (get_fd_phyaddr_from_kernel(&secfd) < 0) { LOG_E("fail to get src phyaddr from fd(%d)", secfd.fd); ret = G2DDRM_ERROR_BLIT_FAILED; break; } cmd->src.addr.start = secfd.phys; secfd.fd = cmd->dst.addr.start; if (get_fd_phyaddr_from_kernel(&secfd) < 0) { LOG_E("fail to get dst phyaddr from fd(%d)", secfd.fd); ret = G2DDRM_ERROR_BLIT_FAILED; break; } cmd->dst.addr.start = secfd.phys; secfd.fd = cmd->dst.plane2.start; if (get_fd_phyaddr_from_kernel(&secfd) < 0) { LOG_E("fail to get plane2 phyaddr from fd(%d)", secfd.fd); ret = G2DDRM_ERROR_BLIT_FAILED; break; } cmd->dst.plane2.start = secfd.phys; LOG_I("Check TCI buffer"); tci = ctx.tci_msg; if (NULL == tci) { LOG_E("TCI has not been set up properly - exiting"); ret = G2DDRM_ERROR_BLIT_FAILED; close(g_fd_secmem); break; } LOG_I("Prepare command message in TCI"); tci->cmd.id = CMD_G2DDRM_BLIT; tci->blit.op = cmd->op; tci->blit.param = cmd->param; tci->blit.src = cmd->src; tci->blit.dst = cmd->dst; tci->blit.msk = cmd->msk; tci->blit.tmp = cmd->tmp; tci->blit.sync = cmd->sync; tci->blit.seq_no = cmd->seq_no; mcRet = tlc_communicate(&ctx); if (MC_DRV_OK != mcRet) { LOG_E("tlc_communicate Error!"); ret = G2DDRM_ERROR_BLIT_FAILED; break; } if ((RSP_ID(CMD_G2DDRM_BLIT) != tci->resp.id)) { LOG_E("Trustlet did not send a response : %d", tci->resp.id); ret = G2DDRM_ERROR_BLIT_FAILED; break; } LOG_I("Trustlet response is completed"); if (tci->resp.return_code != RET_TL_G2DDRM_OK) { LOG_E("Trustlet did not send a valid return code : %d", tci->resp.return_code); ret = G2DDRM_ERROR_BLIT_FAILED; break; } LOG_I("Check the Trustlet return code is completed"); ret = G2DDRM_SUCCESS; } while (false); LOG_I("G2DDRM_Blit(): secure G2D driver blit is done. ret(%d)", ret); return ret; }
extern "C" g2ddrmResult_t G2DDRM_Initialize(void) { mcResult_t mcRet; g2ddrmResult_t ret = G2DDRM_SUCCESS; struct tciMessage_t *tci = NULL; LOG_I("G2DDRM_Initialize(): secure G2D driver initialization"); do { if (sec_g2d_activate(DRV_DEACT) != 0) { ret = G2DDRM_ERROR_INIT_FAILED; break; } LOG_I("Open the Trustlet"); g_fd_secmem = open(SMEM_PATH, O_RDWR); if (g_fd_secmem < 0) { LOG_E("open S5P-MEM device error"); ret = G2DDRM_ERROR_INIT_FAILED; break; } mcRet = tlc_initialize(); if (MC_DRV_OK != mcRet) { LOG_E("Tlc Open Error"); ret = G2DDRM_ERROR_INIT_FAILED; close(g_fd_secmem); break; } LOG_I("Check TCI buffer"); tci = ctx.tci_msg; if (NULL == tci) { LOG_E("TCI has not been set up properly - exiting"); ret = G2DDRM_ERROR_INIT_FAILED; close(g_fd_secmem); break; } LOG_I("Prepare command message in TCI"); tci->cmd.id = CMD_G2DDRM_INITIALIZE; mcRet = tlc_communicate(&ctx); if (MC_DRV_OK != mcRet) { LOG_E("tlc_communicate Error!"); ret = G2DDRM_ERROR_INIT_FAILED; close(g_fd_secmem); break; } if ((RSP_ID(CMD_G2DDRM_INITIALIZE) != tci->resp.id)) { LOG_E("Trustlet did not send a response : %d", tci->resp.id); ret = G2DDRM_ERROR_INIT_FAILED; close(g_fd_secmem); break; } LOG_I("Trustlet response is completed"); if (tci->resp.return_code != RET_TL_G2DDRM_OK) { LOG_E("Trustlet did not send a valid return code : %d", tci->resp.return_code); ret = G2DDRM_ERROR_INIT_FAILED; close(g_fd_secmem); break; } LOG_I("Check the Trustlet return code is completed"); ret = G2DDRM_SUCCESS; } while (false); LOG_I("G2DDRM_Initialize(): secure G2D driver is initialized. ret(%d)", ret); return ret; }
/* ------------------------------------------------------------- */ static void tlcProcessCmd(void) { uint32_t ret = TUI_DCI_ERR_INTERNAL_ERROR; uint32_t commandId = CMD_TUI_SW_NONE; if (NULL == pDci) { pr_debug("ERROR tlcProcessCmd: DCI has not been set up properly - exiting\n"); return; } else { commandId = pDci->cmdNwd.id; } /* Warn if previous response was not acknowledged */ if (CMD_TUI_SW_NONE == commandId) { pr_debug("ERROR tlcProcessCmd: Notified without command\n"); return; } else { if (pDci->nwdRsp.id != CMD_TUI_SW_NONE) pr_debug("tlcProcessCmd: Warning, previous response not ack\n"); } /* Handle command */ switch (commandId) { case CMD_TUI_SW_OPEN_SESSION: pr_debug("tlcProcessCmd: CMD_TUI_SW_OPEN_SESSION.\n"); /* Start android TUI activity */ ret = sendCmdToUser(TLC_TUI_CMD_START_ACTIVITY); if (TUI_DCI_OK == ret) { /* allocate TUI frame buffer */ if (!allocateTuiBuffer(pDci)) ret = TUI_DCI_ERR_INTERNAL_ERROR; } break; case CMD_TUI_SW_STOP_DISPLAY: pr_debug("tlcProcessCmd: CMD_TUI_SW_STOP_DISPLAY.\n"); #ifndef CONFIG_SOC_EXYNOS5420 /* Set linux TUI flag */ trustedui_set_mask(TRUSTEDUI_MODE_TUI_SESSION); #endif trustedui_blank_set_counter(0); #ifdef CONFIG_TRUSTONIC_TRUSTED_UI_FB_BLANK blank_framebuffer(1); disable_irq(gpio_to_irq(190)); #endif trustedui_set_mask(TRUSTEDUI_MODE_VIDEO_SECURED|TRUSTEDUI_MODE_INPUT_SECURED); ret = TUI_DCI_OK; break; case CMD_TUI_SW_CLOSE_SESSION: pr_debug("tlcProcessCmd: CMD_TUI_SW_CLOSE_SESSION.\n"); freeTuiBuffer(); // Protect NWd trustedui_clear_mask(TRUSTEDUI_MODE_VIDEO_SECURED|TRUSTEDUI_MODE_INPUT_SECURED); #ifdef CONFIG_TRUSTONIC_TRUSTED_UI_FB_BLANK pr_info("Unblanking"); enable_irq(gpio_to_irq(190)); unblank_framebuffer(1); #endif /* Clear linux TUI flag */ trustedui_set_mode(TRUSTEDUI_MODE_OFF); #ifdef CONFIG_TRUSTONIC_TRUSTED_UI_FB_BLANK pr_info("Unsetting TUI flag (blank counter=%d)", trustedui_blank_get_counter()); if (0 < trustedui_blank_get_counter()) { blank_framebuffer(0); } #endif /* Stop android TUI activity */ ret = sendCmdToUser(TLC_TUI_CMD_STOP_ACTIVITY); break; default: pr_debug("ERROR tlcProcessCmd: Unknown command %d\n", commandId); break; } /* Fill in response to SWd, fill ID LAST */ pr_debug("tlcProcessCmd: return 0x%08x to cmd 0x%08x\n", ret, commandId); pDci->nwdRsp.returnCode = ret; pDci->nwdRsp.id = RSP_ID(commandId); /* Acknowledge command */ pDci->cmdNwd.id = CMD_TUI_SW_NONE; /* Notify SWd */ pr_debug("DCI RSP NOTIFY CORE\n"); ret = mc_notify(&drSessionHandle); if (MC_DRV_OK != ret) pr_debug("ERROR tlcProcessCmd: Notify failed: %d\n", ret); }
/* ------------------------------------------------------------- */ static void tlc_process_cmd(void) { uint32_t ret = TUI_DCI_ERR_INTERNAL_ERROR; uint32_t command_id = CMD_TUI_SW_NONE; #if defined(CONFIG_SECURE_OS_BOOSTER_API) int ret_val = 0; u8 retry_cnt = 0; #endif if (NULL == dci) { pr_debug("ERROR %s: DCI has not been set up properly - exiting"\ "\n", __func__); return; } else { command_id = dci->cmd_nwd.id; } /* Warn if previous response was not acknowledged */ if (CMD_TUI_SW_NONE == command_id) { pr_debug("ERROR %s: Notified without command\n", __func__); return; } else { if (dci->nwd_rsp.id != CMD_TUI_SW_NONE) pr_debug("%s: Warning, previous response not ack\n", __func__); } /* Handle command */ switch (command_id) { case CMD_TUI_SW_OPEN_SESSION: pr_debug("%s: CMD_TUI_SW_OPEN_SESSION.\n", __func__); #if defined(CONFIG_SECURE_OS_BOOSTER_API) pr_info("%s TUI_CPU_SPEEDUP ON retry: %d\n", __func__, retry_cnt); do { ret_val = secos_booster_start(MAX_PERFORMANCE); retry_cnt++; if (ret_val) { pr_err("%s: booster start failed. (%d) retry: %d\n" , __func__, ret_val, retry_cnt); if (retry_cnt < 7) usleep_range(500, 510); } } while (ret_val && retry_cnt < 7); #endif /* Start android TUI activity */ ret = send_cmd_to_user(TLC_TUI_CMD_START_ACTIVITY); if (TUI_DCI_OK != ret) break; /* allocate TUI frame buffer */ ret = hal_tui_alloc(dci->nwd_rsp.alloc_buffer, dci->cmd_nwd.payload.alloc_data.alloc_size, dci->cmd_nwd.payload.alloc_data.num_of_buff); if (TUI_DCI_OK != ret) { pr_err("%s: hal_tui_alloc error : %d\n", __func__ ,ret); /* no need to call tui_i2c_reset, because there will be no TUI * session */ //tui_i2c_reset(); send_cmd_to_user(TLC_TUI_CMD_STOP_ACTIVITY); break; } /* Deactivate linux UI drivers */ ret = hal_tui_deactivate(); if (TUI_DCI_OK != ret) { pr_err("%s: hal_tui_deactivate error : %d\n", __func__ ,ret); hal_tui_free(); send_cmd_to_user(TLC_TUI_CMD_STOP_ACTIVITY); break; } break; case CMD_TUI_SW_CLOSE_SESSION: pr_debug("%s: CMD_TUI_SW_CLOSE_SESSION.\n", __func__); /* Activate linux UI drivers */ ret = hal_tui_activate(); hal_tui_free(); #if defined(CONFIG_SECURE_OS_BOOSTER_API) ret_val = secos_booster_stop(); if (ret_val) pr_err("%s: booster stop failed. (%d)\n" , __func__, ret_val); #endif /* Stop android TUI activity */ ret = send_cmd_to_user(TLC_TUI_CMD_STOP_ACTIVITY); break; default: pr_debug("ERROR %s: Unknown command %d\n", __func__, command_id); break; } /* Fill in response to SWd, fill ID LAST */ pr_debug("%s: return 0x%08x to cmd 0x%08x\n", __func__, ret, command_id); dci->nwd_rsp.return_code = ret; dci->nwd_rsp.id = RSP_ID(command_id); /* Acknowledge command */ dci->cmd_nwd.id = CMD_TUI_SW_NONE; /* Notify SWd */ pr_debug("DCI RSP NOTIFY CORE\n"); ret = mc_notify(&dr_session_handle); if (MC_DRV_OK != ret) pr_debug("ERROR %s: Notify failed: %d\n", __func__, ret); }
/* ------------------------------------------------------------- */ static void tlcProcessCmd(void) { uint32_t ret = TUI_DCI_ERR_INTERNAL_ERROR; uint32_t commandId = CMD_TUI_SW_NONE; pDci->cmdNwd.payload.allocData.numOfBuff = TUI_BUFFER_NUM; if (NULL == pDci) { pr_debug("ERROR tlcProcessCmd: DCI has not been set up properly - exiting\n"); return; } else { commandId = pDci->cmdNwd.id; } /* Warn if previous response was not acknowledged */ if (CMD_TUI_SW_NONE == commandId) { pr_debug("ERROR tlcProcessCmd: Notified without command\n"); return; } else { if (pDci->nwdRsp.id != CMD_TUI_SW_NONE) pr_debug("tlcProcessCmd: Warning, previous response not ack\n"); } /* Handle command */ switch (commandId) { case CMD_TUI_SW_OPEN_SESSION: printk(KERN_ERR "tlcProcessCmd: CMD_TUI_SW_OPEN_SESSION.\n"); /* Start android TUI activity */ ret = sendCmdToUser(TLC_TUI_CMD_START_ACTIVITY); if (TUI_DCI_OK == ret) { /* allocate TUI frame buffer */ ret = hal_tui_alloc(&pDci->nwdRsp.allocBuffer[MAX_DCI_BUFFER_NUMBER], pDci->cmdNwd.payload.allocData.allocSize, pDci->cmdNwd.payload.allocData.numOfBuff); printk(KERN_ERR "tlcProcessCmd: CMD_TUI_SW_OPEN_SESSION & disable_irq(%d);.\n",tsp_irq_num); disable_irq(tsp_irq_num); msleep(100); // temp code } hal_tui_video_space_alloc(); pDci->nwdRsp.allocBuffer[0].pa = g_sec_tuiMemPool.pa; pDci->nwdRsp.allocBuffer[1].pa = (g_sec_tuiMemPool.pa + g_sec_tuiMemPool.size/2); pDci->cmdNwd.payload.allocData.allocSize = g_sec_tuiMemPool.size; break; case CMD_TUI_SW_STOP_DISPLAY: printk(KERN_ERR "tlcProcessCmd: CMD_TUI_SW_STOP_DISPLAY.\n"); /* Deactivate linux UI drivers */ ret = hal_tui_deactivate(); break; case CMD_TUI_SW_CLOSE_SESSION: printk(KERN_ERR "tlcProcessCmd: CMD_TUI_SW_CLOSE_SESSION & enable_irq(%d).\n", tsp_irq_num); disable_irq(pwr_irq_num); /* Activate linux UI drivers */ ret = hal_tui_activate(); tui_i2c_reset(); enable_irq(tsp_irq_num); hal_tui_free(); enable_irq(pwr_irq_num); /* Stop android TUI activity */ ret = sendCmdToUser(TLC_TUI_CMD_STOP_ACTIVITY); break; default: pr_debug("ERROR tlcProcessCmd: Unknown command %d\n", commandId); break; } /* Fill in response to SWd, fill ID LAST */ pr_debug("tlcProcessCmd: return 0x%08x to cmd 0x%08x\n", ret, commandId); pDci->nwdRsp.returnCode = ret; pDci->nwdRsp.id = RSP_ID(commandId); /* Acknowledge command */ pDci->cmdNwd.id = CMD_TUI_SW_NONE; /* Notify SWd */ pr_debug("DCI RSP NOTIFY CORE\n"); ret = mc_notify(&drSessionHandle); if (MC_DRV_OK != ret) pr_debug("ERROR tlcProcessCmd: Notify failed: %d\n", ret); }