static TEE_Result gprof_send_rpc(TEE_UUID *uuid, void *buf, size_t len, uint32_t *id) { struct mobj *mobj; TEE_Result res = TEE_ERROR_GENERIC; char *va; mobj = thread_rpc_alloc_payload(sizeof(*uuid) + len); if (!mobj) return TEE_ERROR_OUT_OF_MEMORY; va = mobj_get_va(mobj, 0); if (!va) goto exit; memcpy(va, uuid, sizeof(*uuid)); memcpy(va + sizeof(*uuid), buf, len); struct thread_param params[3] = { [0] = THREAD_PARAM_VALUE(INOUT, *id, 0, 0), [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, sizeof(*uuid)), [2] = THREAD_PARAM_MEMREF(IN, mobj, sizeof(*uuid), len), }; res = thread_rpc_cmd(OPTEE_RPC_CMD_GPROF, 3, params); if (res != TEE_SUCCESS) goto exit; *id = (uint32_t)params[0].u.value.a; exit: thread_rpc_free_payload(mobj); return res; }
void *tee_fs_rpc_cache_alloc(size_t size, struct mobj **mobj, uint64_t *cookie) { struct thread_specific_data *tsd = thread_get_tsd(); size_t sz = size; uint64_t c = 0; paddr_t p; void *va; if (!size) return NULL; /* * Always allocate in page chunks as normal world allocates payload * memory as complete pages. */ sz = ROUNDUP(size, SMALL_PAGE_SIZE); if (sz > tsd->rpc_fs_payload_size) { tee_fs_rpc_cache_clear(tsd); *mobj = thread_rpc_alloc_payload(sz, &c); if (!*mobj) return NULL; if (mobj_get_pa(*mobj, 0, 0, &p)) goto err; if (!ALIGNMENT_IS_OK(p, uint64_t)) goto err; va = mobj_get_va(*mobj, 0); if (!va) goto err; tsd->rpc_fs_payload = va; tsd->rpc_fs_payload_mobj = *mobj; tsd->rpc_fs_payload_cookie = c; tsd->rpc_fs_payload_size = sz; } else *mobj = tsd->rpc_fs_payload_mobj; *cookie = tsd->rpc_fs_payload_cookie; return tsd->rpc_fs_payload; err: thread_rpc_free_payload(c, *mobj); return NULL; }
/* * Load a TA via RPC with UUID defined by input param @uuid. The virtual * address of the raw TA binary is received in out parameter @ta. */ static TEE_Result rpc_load(const TEE_UUID *uuid, struct shdr **ta, size_t *ta_size, struct mobj **mobj) { TEE_Result res; struct thread_param params[2]; if (!uuid || !ta || !mobj || !ta_size) return TEE_ERROR_BAD_PARAMETERS; memset(params, 0, sizeof(params)); params[0].attr = THREAD_PARAM_ATTR_VALUE_IN; tee_uuid_to_octets((void *)¶ms[0].u.value, uuid); params[1].attr = THREAD_PARAM_ATTR_MEMREF_OUT; res = thread_rpc_cmd(OPTEE_RPC_CMD_LOAD_TA, 2, params); if (res != TEE_SUCCESS) return res; *mobj = thread_rpc_alloc_payload(params[1].u.memref.size); if (!*mobj) return TEE_ERROR_OUT_OF_MEMORY; if ((*mobj)->size < params[1].u.memref.size) { res = TEE_ERROR_SHORT_BUFFER; goto exit; } *ta = mobj_get_va(*mobj, 0); /* We don't expect NULL as thread_rpc_alloc_payload() was successful */ assert(*ta); *ta_size = params[1].u.memref.size; params[0].attr = THREAD_PARAM_ATTR_VALUE_IN; tee_uuid_to_octets((void *)¶ms[0].u.value, uuid); params[1].attr = THREAD_PARAM_ATTR_MEMREF_OUT; params[1].u.memref.offs = 0; params[1].u.memref.mobj = *mobj; res = thread_rpc_cmd(OPTEE_RPC_CMD_LOAD_TA, 2, params); exit: if (res != TEE_SUCCESS) thread_rpc_free_payload(*mobj); return res; }
static TEE_Result gprof_send_rpc(TEE_UUID *uuid, void *buf, size_t len, uint32_t *id) { struct optee_msg_param params[3]; TEE_Result res = TEE_ERROR_GENERIC; uint64_t c = 0; paddr_t pa; char *va; thread_rpc_alloc_payload(sizeof(*uuid) + len, &pa, &c); if (!pa) return TEE_ERROR_OUT_OF_MEMORY; va = phys_to_virt(pa, MEM_AREA_NSEC_SHM); if (!va) goto exit; memcpy(va, uuid, sizeof(*uuid)); memcpy(va + sizeof(*uuid), buf, len); memset(params, 0, sizeof(params)); params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INOUT; params[0].u.value.a = *id; params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; params[1].u.tmem.buf_ptr = pa; params[1].u.tmem.size = sizeof(*uuid); params[1].u.tmem.shm_ref = c; params[2].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; params[2].u.tmem.buf_ptr = pa + sizeof(*uuid); params[2].u.tmem.size = len; params[2].u.tmem.shm_ref = c; res = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_GPROF, 3, params); if (res != TEE_SUCCESS) goto exit; *id = (uint32_t)params[0].u.value.a; exit: thread_rpc_free_payload(c); return res; }