mcResult_t tlc_communicate(mc_comm_ctx *comm_ctx) { mcResult_t mcRet; do { // ------------------------------------------------------------- // Step 1: signal the Trustlet mcRet = mcNotify(&(comm_ctx->handle)); if (MC_DRV_OK != mcRet) { LOG_E("Notify failed: %d", mcRet); break; } LOG_I("mcNotify is completed\n"); // ------------------------------------------------------------- // Step 2: Wait for the Trustlet response mcRet = mcWaitNotification(&(comm_ctx->handle), -1); if (MC_DRV_OK != mcRet) { LOG_E("Wait for response notification failed: %d", mcRet); break; } LOG_I("mcWaitNotification is completed"); } while (false); return mcRet; }
//------------------------------------------------------------------------------ void TEEC_RequestCancellation( TEEC_Operation *operation) { LOG_I("== %s() ==============", __func__); while (operation->started == 0); LOG_I("while(operation->started ==0) passed"); if (operation->started > 1) { LOG_I("The operation has finished"); return; } TEEC_Session_IMP *session = operation->imp.session; operation->started = 2; if (!session->active) { LOG_I("Corresponding session is not active"); return; } ((_TEEC_TCI *)session->tci)->operation.isCancelled = true; // Step 4.3: signal the Trustlet mcResult_t mcRet = mcNotify(&session->handle); if (MC_DRV_OK != mcRet) { LOG_E("Notify failed (%08x)", mcRet); } }
// ------------------------------------------------------------- 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; }
//------------------------------------------------------------------------------ static TEEC_Result _TEEC_CallTA( TEEC_Session *session, TEEC_Operation *operation, uint32_t *returnOrigin) { mcResult_t mcRet; TEEC_Result teecRes; TEEC_Result teecError = TEEC_SUCCESS; LOG_I(" %s()", __func__); // Phase 1: start the operation and wait for the result teecRes = _TEEC_SetupOperation((_TEEC_TCI *)session->imp.tci, &session->imp.handle, operation, returnOrigin); if (teecRes != TEEC_SUCCESS ) { LOG_E("_TEEC_SetupOperation failed (%08x)", teecRes); return teecRes; } // Signal the Trusted App mcRet = mcNotify(&session->imp.handle); if (MC_DRV_OK != mcRet) { LOG_E("Notify failed (%08x)", mcRet); teecError = TEEC_ERROR_COMMUNICATION; goto end; } // ------------------------------------------------------------- // Wait for the Trusted App response mcRet = mcWaitNotification(&session->imp.handle, MC_INFINITE_TIMEOUT); if (mcRet != MC_DRV_OK) { teecError = TEEC_ERROR_COMMUNICATION; if (mcRet == MC_DRV_INFO_NOTIFICATION) { int32_t lastErr = SESSION_ERR_NO; mcGetSessionErrorCode(&session->imp.handle, &lastErr); switch (lastErr) { case TA_EXIT_CODE_FINISHED: // We may get here if the TA_OpenSessionEntryPoint returns an error and TA goes fast through DestroyEntryPoint and exits the TA. teecError = TEEC_SUCCESS; break; case ERR_SESSION_KILLED: teecError = TEEC_ERROR_TARGET_KILLED; break; case ERR_INVALID_SID: case ERR_SID_NOT_ACTIVE: LOG_E("mcWaitNotification failed (%08x)", mcRet); LOG_E("mcGetSessionErrorCode returned %d", lastErr); break; default: LOG_E("Target is DEAD"); *returnOrigin = TEEC_ORIGIN_TEE; teecError = TEEC_ERROR_TARGET_DEAD; break; } } } // Phase 2: Return values and cleanup end: // unmap memory and copy values if no error teecRes = _TEEC_UnwindOperation((_TEEC_TCI *)session->imp.tci, &session->imp.handle, operation, (teecError == TEEC_SUCCESS), returnOrigin); if (teecRes != TEEC_SUCCESS ) { LOG_E("_TEEC_UnwindOperation (%08x)", teecRes); /* continue even in case of error */; } // Cleanup if (teecError != TEEC_SUCCESS) { // Previous interactions failed, either TA is dead or communication error mcRet = mcCloseSession(&session->imp.handle); if (mcRet != MC_DRV_OK) { LOG_E("mcCloseSession failed (%08x)", mcRet); /* continue even in case of error */; } session->imp.active = false; if (teecError == TEEC_ERROR_COMMUNICATION) { *returnOrigin = TEEC_ORIGIN_COMMS; } munmap(session->imp.tci, sysconf(_SC_PAGESIZE)); session->imp.tci = NULL; } return teecError; }