//------------------------------------------------------------------------------ static TEEC_Result _TEEC_UnwindOperation( _TEEC_TCI *tci, mcSessionHandle_t *handle, TEEC_Operation *operation, bool copyValues, uint32_t *returnOrigin) { uint32_t i; _TEEC_ParameterInternal *imp; TEEC_Parameter *ext; uint8_t *buffer; //operation can be NULL if (operation == NULL) return TEEC_SUCCESS; LOG_I(" %s()", __func__); operation->started = 2; // Some sanity checks if (tci->returnOrigin == 0 || ((tci->returnOrigin != TEEC_ORIGIN_TRUSTED_APP) && (tci->returnStatus != TEEC_SUCCESS))) { *returnOrigin = TEEC_ORIGIN_COMMS; return TEEC_ERROR_COMMUNICATION; } *returnOrigin = tci->returnOrigin; //Clear sVirtualLen to unMap further for (i = 0; i < _TEEC_PARAMETER_NUMBER; i++) { imp = &tci->operation.params[i]; ext = &operation->params[i]; buffer = NULL; switch (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i)) { case TEEC_VALUE_INPUT: LOG_I(" cycle %d, TEEC_VALUE_INPUT", i); break; case TEEC_NONE: LOG_I(" cycle %d, TEEC_NONE", i); break; case TEEC_VALUE_OUTPUT: case TEEC_VALUE_INOUT: { LOG_I(" cycle %d, TEEC_VALUE_*OUT", i); if (copyValues) { ext->value.a = imp->value.a; ext->value.b = imp->value.b; } break; } case TEEC_MEMREF_TEMP_OUTPUT: case TEEC_MEMREF_TEMP_INPUT: case TEEC_MEMREF_TEMP_INOUT: { LOG_I(" cycle %d, TEEC_TEMP*", i); if ((copyValues) && (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i) != TEEC_MEMREF_TEMP_INPUT)) { ext->tmpref.size = imp->memref.outputSize; } buffer = (uint8_t *)ext->tmpref.buffer; break; } case TEEC_MEMREF_WHOLE: { LOG_I(" cycle %d, TEEC_MEMREF_WHOLE", i); if ((copyValues) && (ext->memref.parent->flags != TEEC_MEM_INPUT)) { ext->memref.size = imp->memref.outputSize; } buffer = (uint8_t *)ext->memref.parent->buffer; break; } case TEEC_MEMREF_PARTIAL_OUTPUT: case TEEC_MEMREF_PARTIAL_INOUT: case TEEC_MEMREF_PARTIAL_INPUT: { LOG_I(" cycle %d, TEEC_MEMREF_PARTIAL*", i); if ((copyValues) && (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i) != TEEC_MEMREF_PARTIAL_INPUT)) { ext->memref.size = imp->memref.outputSize; } buffer = (uint8_t *)ext->memref.parent->buffer + ext->memref.offset; break; } default: LOG_E("cycle %d, bad parameter", i); break; } if ((buffer != NULL) && (imp->memref.mapInfo.sVirtualLen != 0)) { // This function assumes that we cannot handle error of mcUnmap (void)mcUnmap(handle, buffer, &imp->memref.mapInfo); } } return tci->returnStatus; }
rootpaerror_t executeOneCmpCommand(CMTHANDLE handle, CmpMessage* commandP, CmpMessage* responseP) { LOGD(">>executeOneCmpCommand"); if (unlikely( bad_write_ptr(handle,sizeof(CMTSTRUCT)))) { return ROOTPA_ERROR_INTERNAL; } if(unlikely (commandP->contentP==NULL || commandP->length< sizeof(cmpCommandId_t))) { return ROOTPA_ERROR_INTERNAL; } mcResult_t mcRet=MC_DRV_OK; cmpCommandId_t commandId=getCmpCommandId(commandP->contentP); handle->mappedSize=getTotalMappedBufferSize(commandP); if(0==handle->mappedSize) { LOGE("<<executeOneCmpCommand, command %d not supported", commandId); return ROOTPA_COMMAND_NOT_SUPPORTED; } rootpaerror_t ret=ROOTPA_OK; while(true) { handle->mappedP=malloc((size_t) handle->mappedSize); if(NULL==handle->mappedP) { ret=ROOTPA_ERROR_OUT_OF_MEMORY; break; } memset(handle->mappedP, 0,handle->mappedSize); mcRet=mcMap(&handle->session, handle->mappedP, handle->mappedSize, &handle->mapInfo); if(mcRet!=MC_DRV_OK) { LOGE("executeOneCmpCommand not able to map memory %d", mcRet); ret=ROOTPA_ERROR_MOBICORE_CONNECTION; commandP->hdr.intRet=mcRet; responseP->hdr.intRet=mcRet; break; } if((ret = prepareCommand(commandId, commandP, handle, responseP))!=ROOTPA_OK) { LOGE("prepareCommand failed %d", ret); break; } if (unlikely( !tltChannelTransmit(handle, NOTIFICATION_WAIT_TIMEOUT_MS))) { ret=ROOTPA_ERROR_MOBICORE_CONNECTION; commandP->hdr.intRet=handle->lasterror; responseP->hdr.intRet=handle->lasterror; break; } uint32_t neededBytes=getNeededBytesFromResponse(handle->wsmP); if(0==neededBytes) { break; } if(-1==neededBytes) { ret=ROOTPA_ERROR_MOBICORE_CONNECTION; break; } if(neededBytes <= handle->mappedSize) { LOGE("executeOneCmpCommand, there is something wrong. CMTL is requesting smaller buffer than we originally had. Command: %d, original %d requested %d", commandId, handle->mappedSize, neededBytes); ret=ROOTPA_ERROR_MOBICORE_CONNECTION; break; } // this is Info level LOGI on purpose LOGI("executeOneCmpCommand, updating RootPA recommended (%d bytes was not enough for %d response, allocating %d bytes and retrying)", handle->mappedSize, commandId, neededBytes); mcRet=mcUnmap(&handle->session, handle->mappedP, &handle->mapInfo); if(mcRet!=MC_DRV_OK) { LOGE("executeOneCmpCommand not able to free mapped memory %d", mcRet); ret=ROOTPA_ERROR_MOBICORE_CONNECTION; commandP->hdr.intRet=mcRet; responseP->hdr.intRet=mcRet; break; } free(handle->mappedP); memset(&handle->mapInfo, 0 , sizeof(handle->mapInfo)); handle->mappedSize=neededBytes; } if(ROOTPA_OK==ret) { ret=handleResponse(commandId, responseP, handle); } else { responseP->hdr.ret=ret; } LOGD("cleaning up mapped memory %ld",(long int) handle->mappedP); mcRet=mcUnmap(&handle->session, handle->mappedP, &handle->mapInfo); if(mcRet!=MC_DRV_OK) { LOGE("executeOneCmpCommand not able to free mapped memory %d", mcRet); ret=ROOTPA_ERROR_MOBICORE_CONNECTION; } LOGD("freeing mapped memory %ld", (long int) handle->mappedP); free(handle->mappedP); if(commandP->hdr.ret==ROOTPA_OK) commandP->hdr.ret=ret; if(responseP->hdr.ret==ROOTPA_OK) responseP->hdr.ret=ret; LOGD("<<executeOneCmpCommand %d %d",commandId, ret); return ret; }