Ejemplo n.º 1
0
static int _copy_ta_image(struct tee_session *sess, struct tee_cmd_io *cmd_io,
			  struct tee_cmd *cmd)
{
	int res = -EINVAL;

	dev_dbg(_DEV_TEE, "%s: > data=%p uuid=%p\n",
		__func__, cmd_io->data, cmd_io->uuid);

	if (((cmd_io->data != NULL) && (cmd_io->data_size == 0)) ||
	    ((cmd_io->data == NULL) && (cmd_io->data_size != 0)))
		goto out_failed;

	if ((cmd_io->data != NULL) && (cmd_io->data_size > 0)) {
		dev_dbg(_DEV_TEE, "%s: copy DATA image (s=%d)...\n", __func__,
			cmd_io->data_size);
		cmd->ta =
		    tee_context_alloc_shm_tmp(sess->ctx, cmd_io->data_size,
					      cmd_io->data, TEEC_MEM_INPUT);
		if (IS_ERR_OR_NULL(cmd->ta))
			goto out_failed;
	}

	if (cmd_io->uuid != NULL) {
		dev_dbg(_DEV_TEE, "%s: copy UUID value...\n", __func__);
		cmd->uuid =
		    tee_context_alloc_shm_tmp(sess->ctx, sizeof(*cmd_io->uuid),
					      cmd_io->uuid, TEEC_MEM_INPUT);
		if (IS_ERR_OR_NULL(cmd->uuid))
			goto out_failed;
	}

	res = 0;
	goto out;

out_failed:
	tee_shm_free(cmd->uuid);
	tee_shm_free(cmd->ta);

out:
	dev_dbg(_DEV_TEE, "%s: < res=%d", __func__, res);
	return res;
}
Ejemplo n.º 2
0
static int _init_tee_cmd(struct tee_session *sess, struct tee_cmd_io *cmd_io,
			 struct tee_cmd *cmd)
{
	int ret = -EINVAL;
	int idx;
	TEEC_Operation op;
	struct tee_data *param = &cmd->param;
	struct tee *tee;
	struct tee_context *ctx;

	BUG_ON(!sess->ctx);
	BUG_ON(!sess->ctx->tee);
	ctx = sess->ctx;
	tee = sess->ctx->tee;

	dev_dbg(_DEV(tee), "%s: > sessid=%08x\n", __func__, sess->sessid);

	memset(cmd, 0, sizeof(struct tee_cmd));

	cmd->cmd = cmd_io->cmd;
	cmd->origin = TEEC_ORIGIN_TEE;
	cmd->err = TEEC_ERROR_BAD_PARAMETERS;
	cmd_io->origin = cmd->origin;
	cmd_io->err = cmd->err;

	if (tee_context_copy_from_client(ctx, &op, cmd_io->op, sizeof(op)))
		goto out;

	cmd->param.type_original = op.paramTypes;

	for (idx = 0; idx < TEEC_CONFIG_PAYLOAD_REF_COUNT; ++idx) {
		uint32_t offset = 0;
		uint32_t size = 0;
		int type = TEEC_PARAM_TYPE_GET(op.paramTypes, idx);

		switch (type) {
		case TEEC_NONE:
			break;

		case TEEC_VALUE_INPUT:
		case TEEC_VALUE_OUTPUT:
		case TEEC_VALUE_INOUT:
			param->params[idx].value = op.params[idx].value;
			dev_dbg(_DEV_TEE,
				"%s: param[%d]:type=%d,a=%08x,b=%08x (VALUE)\n",
				__func__, idx, type, param->params[idx].value.a,
				param->params[idx].value.b);
			break;

		case TEEC_MEMREF_TEMP_INPUT:
		case TEEC_MEMREF_TEMP_OUTPUT:
		case TEEC_MEMREF_TEMP_INOUT:
			dev_dbg(_DEV_TEE,
				"> param[%d]:type=%d,buffer=%p,s=%zu (TMPREF)\n",
				idx, type, op.params[idx].tmpref.buffer,
				op.params[idx].tmpref.size);

			param->params[idx].shm =
			    tee_context_create_tmpref_buffer(ctx,
					     op.params[idx].tmpref.size,
					     op.params[idx].tmpref.buffer,
					     type);
			if (IS_ERR_OR_NULL(param->params[idx].shm))
				goto out;

			dev_dbg(_DEV_TEE, "< %d %p:%zd\n", idx,
					(void *)param->params[idx].shm->paddr,
					param->params[idx].shm->size_alloc);
			break;

		case TEEC_MEMREF_PARTIAL_INPUT:
		case TEEC_MEMREF_PARTIAL_OUTPUT:
		case TEEC_MEMREF_PARTIAL_INOUT:
		case TEEC_MEMREF_WHOLE:
			if (tee_copy_from_user(ctx, &param->c_shm[idx],
						op.params[idx].memref.parent,
						sizeof(param->c_shm[idx]))) {
				goto out;
			}

			if (type == TEEC_MEMREF_WHOLE) {
				offset = 0;
				size = param->c_shm[idx].size;
			} else { /* for PARTIAL, check the size */
				offset = op.params[idx].memref.offset;
				size = op.params[idx].memref.size;
				if (param->c_shm[idx].size < size + offset) {
					dev_err(_DEV(tee), "A PARTIAL parameter is bigger than the parent %zd < %d + %d\n",
						param->c_shm[idx].size, size,
						offset);
					goto out;
				}
			}

			dev_dbg(_DEV_TEE, "> param[%d]:type=%d,buffer=%p, offset=%d size=%d\n",
					idx, type, param->c_shm[idx].buffer,
					offset, size);

			type = to_memref_type(param->c_shm[idx].flags);
			if (type == 0)
				goto out;

			param->params[idx].shm = tee_shm_get(ctx,
					&param->c_shm[idx], size, offset);

			if (IS_ERR_OR_NULL(param->params[idx].shm)) {
				param->params[idx].shm =
				    tee_context_create_tmpref_buffer(ctx, size,
				       param->c_shm[idx].buffer + offset, type);

				if (IS_ERR_OR_NULL(param->params[idx].shm))
					goto out;
			}

			dev_dbg(_DEV_TEE, "< %d %p:%zd\n", idx,
				(void *)param->params[idx].shm->paddr,
				param->params[idx].shm->size_req);
			break;

		default:
			BUG_ON(1);
		}

		param->type |= (type << (idx * 4));
	}

	if (cmd_io->uuid != NULL) {
		dev_dbg(_DEV_TEE, "%s: copy UUID value...\n", __func__);
		cmd->uuid = tee_context_alloc_shm_tmp(sess->ctx,
			sizeof(*cmd_io->uuid), cmd_io->uuid, TEEC_MEM_INPUT);
		if (IS_ERR_OR_NULL(cmd->uuid)) {
			ret = -EINVAL;
			goto out;
		}
	}

	ret = 0;

out:
	if (ret)
		_release_tee_cmd(sess, cmd);

	dev_dbg(_DEV_TEE, "%s: < ret=%d\n", __func__, ret);
	return ret;
}