Exemplo n.º 1
0
static u32 handle_rpc(struct tee_tz *ptee, struct smc_param *param)
{
	struct tee_shm *shm;
	int cookie;

	switch (TEESMC_RETURN_GET_RPC_FUNC(param->a0)) {
	case TEESMC_RPC_FUNC_ALLOC_ARG:
		param->a1 = tee_shm_pool_alloc(DEV, ptee->shm_pool,
					param->a1, 4);
		break;
	case TEESMC_RPC_FUNC_ALLOC_PAYLOAD:
		/* Can't support payload shared memory with this interface */
		param->a2 = 0;
		break;
	case TEESMC_RPC_FUNC_FREE_ARG:
		tee_shm_pool_free(DEV, ptee->shm_pool, param->a1, 0);
		break;
	case TEESMC_RPC_FUNC_FREE_PAYLOAD:
		/* Can't support payload shared memory with this interface */
		break;
	case TEESMC_ST_RPC_FUNC_ALLOC_PAYLOAD:
		shm = tee_shm_alloc_from_rpc(ptee->tee, param->a1,
					TEE_SHM_TEMP | TEE_SHM_FROM_RPC);
		if (!shm) {
			param->a1 = 0;
			break;
		}
		cookie = handle_get(&shm_handle_db, shm);
		if (cookie < 0) {
			tee_shm_free_from_rpc(shm);
			param->a1 = 0;
			break;
		}
		param->a1 = shm->paddr;
		param->a2 = cookie;
		break;
	case TEESMC_ST_RPC_FUNC_FREE_PAYLOAD:
		if (true || param->a1) {
			shm = handle_put(&shm_handle_db, param->a1);
			if (shm)
				tee_shm_free_from_rpc(shm);
		}
		break;
	case TEESMC_RPC_FUNC_IRQ:
		break;
	case TEESMC_RPC_FUNC_CMD:
		handle_rpc_func_cmd(ptee, param->a1);
		break;
	default:
		dev_warn(DEV, "Unknown RPC func 0x%x\n",
			 (u32)TEESMC_RETURN_GET_RPC_FUNC(param->a0));
		break;
	}

	if (irqs_disabled())
		return TEESMC32_FASTCALL_RETURN_FROM_RPC;
	else
		return TEESMC32_CALL_RETURN_FROM_RPC;
}
Exemplo n.º 2
0
static u32 handle_rpc(struct smc_param *param)
{
	switch (TEESMC_RETURN_GET_RPC_FUNC(param->a0)) {
	case TEESMC_RPC_FUNC_ALLOC_ARG:
		param->a1 = tee_shm_pool_alloc(DEV, TZop.Allocator,
					param->a1, 4);
	case TEESMC_RPC_FUNC_ALLOC_PAYLOAD:
		/* Can't support payload shared memory with this interface */
		param->a2 = 0;
		break;
	case TEESMC_RPC_FUNC_FREE_ARG:
		tee_shm_pool_free(DEV, TZop.Allocator, param->a1, 0);
		break;
	case TEESMC_RPC_FUNC_FREE_PAYLOAD:
		/* Can't support payload shared memory with this interface */
		break;
	case TEESMC_ST_RPC_FUNC_ALLOC_PAYLOAD:
	{
		struct tee_shm *shm;

		shm = tee_shm_allocate(&TZop, 0, param->a1, 0);
		if (!shm) {
			param->a1 = 0;
			break;
		}
		param->a1 = shm->paddr;
		param->a2 = (uint32_t)shm;
		break;
	}
	case TEESMC_ST_RPC_FUNC_FREE_PAYLOAD:
		if (param->a1)
			tee_shm_unallocate((struct tee_shm *)param->a1);
		break;
	case TEESMC_RPC_FUNC_IRQ:
		break;
	case TEESMC_RPC_FUNC_CMD:
	{
		struct teesmc32_arg *arg32;
		struct teesmc32_param *params;
		struct tee_rpc_invoke inv;
		size_t n;
		uint32_t ret;

		arg32 = tee_shm_pool_p2v(DEV, TZop.Allocator, param->a1);

		if (arg32->num_params > TEE_RPC_BUFFER_NUMBER) {
			arg32->ret = TEEC_ERROR_GENERIC;
			goto out;
		}

		params = TEESMC32_GET_PARAMS(arg32);

		memset(&inv, 0, sizeof(inv));
		inv.cmd = arg32->cmd;
		/*
		 * Set a suitable error code in case tee-supplicant
		 * ignores the request.
		 */
		inv.res = TEEC_ERROR_NOT_IMPLEMENTED;
		inv.nbr_bf = arg32->num_params;
		for (n = 0; n < arg32->num_params; n++) {
			inv.cmds[n].buffer = (void *)params[n].u.memref.buf_ptr;
			inv.cmds[n].size = params[n].u.memref.size;
			switch (params[n].attr & TEESMC_ATTR_TYPE_MASK) {
			case TEESMC_ATTR_TYPE_VALUE_INPUT:
			case TEESMC_ATTR_TYPE_VALUE_OUTPUT:
			case TEESMC_ATTR_TYPE_VALUE_INOUT:
				inv.cmds[n].type = TEE_RPC_VALUE;
				break;
			case TEESMC_ATTR_TYPE_MEMREF_INPUT:
			case TEESMC_ATTR_TYPE_MEMREF_OUTPUT:
			case TEESMC_ATTR_TYPE_MEMREF_INOUT:
				inv.cmds[n].type = TEE_RPC_BUFFER;
				break;
			default:
				arg32->ret = TEEC_ERROR_GENERIC;
				goto out;
			}
		}

		ret = tee_supp_cmd(&TZop, TEE_RPC_ICMD_INVOKE,
					  &inv, sizeof(inv));
		if (ret == TEEC_RPC_OK)
			arg32->ret = inv.res;

		for (n = 0; n < arg32->num_params; n++) {
			switch (params[n].attr & TEESMC_ATTR_TYPE_MASK) {
			case TEESMC_ATTR_TYPE_VALUE_INPUT:
			case TEESMC_ATTR_TYPE_VALUE_OUTPUT:
			case TEESMC_ATTR_TYPE_VALUE_INOUT:
			case TEESMC_ATTR_TYPE_MEMREF_OUTPUT:
			case TEESMC_ATTR_TYPE_MEMREF_INOUT:
				/*
				 * Allow supplicant to assign a new pointer
				 * to an out-buffer. Needed when the
				 * supplicant allocates a new buffer, for
				 * instance when loading a TA.
				 */
				params[n].u.memref.buf_ptr =
						(uint32_t)inv.cmds[n].buffer;
				params[n].u.memref.size = inv.cmds[n].size;
				break;
			default:
				break;
			}
		}

		break;
	}
	default:
		dev_warn(DEV, "Unknown RPC func 0x%x\n",
			 TEESMC_RETURN_GET_RPC_FUNC(param->a0));
		break;
	}

out:
	if (irqs_disabled())
		return TEESMC32_FASTCALL_RETURN_FROM_RPC;
	else
		return TEESMC32_CALL_RETURN_FROM_RPC;
}