Ejemplo 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;
}
Ejemplo n.º 2
0
static struct tee_shm *tz_alloc(struct tee *tee, size_t size, uint32_t flags)
{
	struct tee_shm *shm = NULL;
	struct tee_tz *ptee;
	size_t size_aligned;
	BUG_ON(!tee->priv);
	ptee = tee->priv;

	dev_dbg(DEV, "%s: s=%d,flags=0x%08x\n", __func__, (int)size, flags);

/*	comment due to #6357
 *	if ( (flags & ~(tee->shm_flags | TEE_SHM_MAPPED
 *	| TEE_SHM_TEMP | TEE_SHM_FROM_RPC)) != 0 ) {
		dev_err(tee->dev, "%s: flag parameter is invalid\n", __func__);
		return ERR_PTR(-EINVAL);
	}*/

	size_aligned = ((size / SZ_4K) + 1) * SZ_4K;
	if (unlikely(size_aligned == 0)) {
		dev_err(DEV, "[%s] requested size too big\n", __func__);
		return NULL;
	}

	shm = devm_kzalloc(tee->dev, sizeof(struct tee_shm), GFP_KERNEL);
	if (!shm) {
		dev_err(tee->dev, "%s: kzalloc failed\n", __func__);
		return ERR_PTR(-ENOMEM);
	}

	shm->size_alloc = ((size / SZ_4K) + 1) * SZ_4K;
	shm->size_req = size;
	shm->paddr = tee_shm_pool_alloc(tee->dev, ptee->shm_pool,
					shm->size_alloc, ALLOC_ALIGN);
	if (!shm->paddr) {
		dev_err(tee->dev, "%s: cannot alloc memory, size 0x%lx\n",
			__func__, (unsigned long)shm->size_alloc);
		devm_kfree(tee->dev, shm);
		return ERR_PTR(-ENOMEM);
	}
	shm->kaddr = tee_shm_pool_p2v(tee->dev, ptee->shm_pool, shm->paddr);
	if (!shm->kaddr) {
		dev_err(tee->dev, "%s: p2v(%p)=0\n", __func__,
			(void *)shm->paddr);
		tee_shm_pool_free(tee->dev, ptee->shm_pool, shm->paddr, NULL);
		devm_kfree(tee->dev, shm);
		return ERR_PTR(-EFAULT);
	}
	shm->flags = flags;
	if (ptee->shm_cached)
		shm->flags |= TEE_SHM_CACHED;

	dev_dbg(tee->dev, "%s: kaddr=%p, paddr=%p, shm=%p, size %x:%x\n",
		__func__, shm->kaddr, (void *)shm->paddr, shm,
		(unsigned int)shm->size_req, (unsigned int)shm->size_alloc);

	return shm;
}
Ejemplo n.º 3
0
/* free tee service argument buffer (from its physical address) */
static void free_tee_arg(struct tee_tz *ptee, unsigned long p)
{
	dev_dbg(DEV, ">\n");
	BUG_ON(!CAPABLE(ptee->tee));

	if (p)
		tee_shm_pool_free(DEV, ptee->shm_pool, p, 0);

	dev_dbg(DEV, "<\n");
}
Ejemplo n.º 4
0
static void tz_free(struct tee_shm *shm)
{
	size_t size;
	int ret;
	struct tee *tee;
	struct tee_tz *ptee;

	BUG_ON(!shm->tee);
	BUG_ON(!shm->tee->priv);
	tee = shm->tee;
	ptee = tee->priv;

	dev_dbg(tee->dev, "%s: shm=%p\n", __func__, shm);

	ret = tee_shm_pool_free(tee->dev, ptee->shm_pool, shm->paddr, &size);
	if (!ret) {
		devm_kfree(tee->dev, shm);
		shm = NULL;
	}
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
/* free tee service argument buffer (from its physical address) */
static void free_tee_arg(unsigned long p)
{
	if (p)
		tee_shm_pool_free(DEV, TZop.Allocator, p, 0);
}