Exemplo n.º 1
0
static void _update_client_tee_cmd(struct tee_session *sess,
				   struct tee_cmd_io *cmd_io,
				   struct tee_cmd *cmd)
{
	int idx;
	struct tee_context *ctx;

	BUG_ON(!cmd_io);
	BUG_ON(!cmd_io->op);
	BUG_ON(!cmd_io->op->params);
	BUG_ON(!cmd);
	BUG_ON(!sess->ctx);
	ctx = sess->ctx;

	dev_dbg(_DEV_TEE, "%s: returned err=0x%08x (origin=%d)\n", __func__,
		cmd->err, cmd->origin);

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

	if (cmd->param.type_original == TEEC_PARAM_TYPES(TEEC_NONE,
			TEEC_NONE, TEEC_NONE, TEEC_NONE))
		return;

	for (idx = 0; idx < TEEC_CONFIG_PAYLOAD_REF_COUNT; ++idx) {
		int type = TEEC_PARAM_TYPE_GET(cmd->param.type_original, idx);
		int offset = 0;
		size_t size;
		size_t size_new;
		TEEC_SharedMemory *parent;

		dev_dbg(_DEV_TEE, "%s: id %d type %d\n", __func__, idx, type);
		BUG_ON(!tee_session_is_supported_type(sess, type));
		switch (type) {
		case TEEC_NONE:
		case TEEC_VALUE_INPUT:
		case TEEC_MEMREF_TEMP_INPUT:
		case TEEC_MEMREF_PARTIAL_INPUT:
			break;
		case TEEC_VALUE_OUTPUT:
		case TEEC_VALUE_INOUT:
			dev_dbg(_DEV_TEE, "%s: a=%08x, b=%08x\n",
				__func__,
				cmd->param.params[idx].value.a,
				cmd->param.params[idx].value.b);
			if (tee_copy_to_user
			    (ctx, &cmd_io->op->params[idx].value,
			     &cmd->param.params[idx].value,
			     sizeof(cmd_io->op->params[idx].value)))
				dev_err(_DEV_TEE,
					"%s:%d: can't update %d result to user\n",
					__func__, __LINE__, idx);
			break;
		case TEEC_MEMREF_TEMP_OUTPUT:
		case TEEC_MEMREF_TEMP_INOUT:
			/* Returned updated size */
			size_new = cmd->param.params[idx].shm->size_req;
			if (size_new !=
				cmd_io->op->params[idx].tmpref.size) {
				dev_dbg(_DEV_TEE,
					"Size has been updated by the TA %zd != %zd\n",
					size_new,
					cmd_io->op->params[idx].tmpref.size);
				tee_put_user(ctx, size_new,
				     &cmd_io->op->params[idx].tmpref.size);
			}

			dev_dbg(_DEV_TEE, "%s: tmpref %p\n", __func__,
				cmd->param.params[idx].shm->kaddr);

			/* ensure we do not exceed the shared buffer length */
			if (size_new > cmd_io->op->params[idx].tmpref.size)
				dev_err(_DEV_TEE,
					"  *** Wrong returned size from %d:%zd > %zd\n",
					idx, size_new,
					cmd_io->op->params[idx].tmpref.size);

			else if (tee_copy_to_user
				 (ctx,
				  cmd_io->op->params[idx].tmpref.buffer,
				  cmd->param.params[idx].shm->kaddr,
				  size_new))
				dev_err(_DEV_TEE,
					"%s:%d: can't update %d result to user\n",
					__func__, __LINE__, idx);
			break;

		case TEEC_MEMREF_PARTIAL_OUTPUT:
		case TEEC_MEMREF_PARTIAL_INOUT:
		case TEEC_MEMREF_WHOLE:
			parent = &cmd->param.c_shm[idx];
			if (type == TEEC_MEMREF_WHOLE) {
				offset = 0;
				size = parent->size;
			} else {
				offset = cmd_io->op->params[idx].memref.offset;
				size = cmd_io->op->params[idx].memref.size;
			}

			/* Returned updated size */
			size_new = cmd->param.params[idx].shm->size_req;
			tee_put_user(ctx, size_new,
					&cmd_io->op->params[idx].memref.size);

			/*
			 * If we allocated a tmpref buffer,
			 * copy back data to the user buffer
			 */
			if (is_mapped_temp(cmd->param.params[idx].shm->flags)) {
				if (parent->buffer &&
					offset + size_new <= parent->size) {
					if (tee_copy_to_user(ctx,
					   parent->buffer + offset,
					   cmd->param.params[idx].shm->kaddr,
					   size_new))
							dev_err(_DEV_TEE,
								"%s: can't update %d data to user\n",
								__func__, idx);
				}
			}
			break;
		default:
			BUG_ON(1);
		}
	}

}
Exemplo n.º 2
0
static void _update_client_tee_cmd(struct tee_session *sess,
				   struct tee_cmd_io *cmd_io,
				   struct tee_cmd *cmd)
{
	int idx;
	struct tee_context *ctx;
	BUG_ON(!cmd_io);
	BUG_ON(!cmd_io->op);
	BUG_ON(!cmd_io->op->params);
	BUG_ON(!cmd);
	BUG_ON(!sess->ctx);
	ctx = sess->ctx;

	dev_dbg(_DEV_TEE, "%s: returned err=0x%08x (origin=%d)\n", __func__,
		cmd->err, cmd->origin);

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

	if (cmd->param.type_original == TEEC_PARAM_TYPES(TEEC_NONE,
			TEEC_NONE, TEEC_NONE, TEEC_NONE))
		return;

	for (idx = 0; idx < TEEC_CONFIG_PAYLOAD_REF_COUNT; ++idx) {
		int type = TEEC_PARAM_TYPE_GET(cmd->param.type_original, idx);
		dev_dbg(_DEV_TEE, "%s: id %d type %d\n", __func__, idx, type);
		BUG_ON(!tee_session_is_supported_type(sess, type));
		switch (type) {
		case TEEC_NONE:
		case TEEC_VALUE_INPUT:
		case TEEC_MEMREF_TEMP_INPUT:
		case TEEC_MEMREF_PARTIAL_INPUT:
			break;
		case TEEC_VALUE_OUTPUT:
		case TEEC_VALUE_INOUT:{
				dev_dbg(_DEV_TEE, "%s: a=%08x, b=%08x\n",
					__func__,
					cmd->param.params[idx].value.a,
					cmd->param.params[idx].value.b);
				if (tee_copy_to_user
				    (ctx, &cmd_io->op->params[idx].value,
				     &cmd->param.params[idx].value,
				     sizeof(cmd_io->op->params[idx].value)))
					dev_err(_DEV_TEE,
						"%s:%d: can't update %d result to user\n",
						__func__, __LINE__, idx);
				break;
			}
		case TEEC_MEMREF_TEMP_OUTPUT:
		case TEEC_MEMREF_TEMP_INOUT:{
				/* Returned updated size */
				size_t size =
					cmd->param.params[idx].shm->size_req;
				if (size !=
					cmd_io->op->params[idx].tmpref.size) {
					dev_dbg(_DEV_TEE,
						"Size has been updated by the TA %zu != %zu\n",
						size,
						cmd_io->op->params[idx].tmpref.
						size);
					tee_put_user(ctx, size,
						     &cmd_io->op->params[idx].
						     tmpref.size);
				}

				BUG_ON(!cmd->param.params[idx].shm);
				BUG_ON(!
				       (cmd->param.params[idx].shm->
					flags & TEE_SHM_TEMP));
				dev_dbg(_DEV_TEE, "%s: tmpref %p\n", __func__,
					cmd->param.params[idx].shm->kaddr);

				/* ensure we do not exceed
				 * the shared buffer length */
				if (size > cmd_io->op->params[idx].tmpref.size)
					dev_err(_DEV_TEE,
						"  *** Wrong returned size from %d:%zu > %zu\n",
						idx, size,
						cmd_io->op->params[idx].tmpref.
						size);

				else if (tee_copy_to_user
					 (ctx,
					  cmd_io->op->params[idx].tmpref.buffer,
					  cmd->param.params[idx].shm->kaddr,
					  size))
					dev_err(_DEV_TEE,
						"%s:%d: can't update %d result to user\n",
						__func__, __LINE__, idx);
				break;
			}
		case TEEC_MEMREF_WHOLE:{
				/* Returned updated size */
				size_t size =
					cmd->param.params[idx].shm->size_req;
				if (size !=
					cmd_io->op->params[idx].memref.size) {
					dev_dbg(_DEV_TEE,
						"Size has been updated by the TA %zu != %zu\n",
						size,
						cmd_io->op->params[idx].memref.
						size);
					tee_put_user(ctx, size,
						     &cmd_io->op->params[idx].
						     memref.size);
				}

				/* ensure we do not exceed
				 * the shared buffer length */
				if (size > cmd->param.c_shm[idx].size)
					dev_err(_DEV_TEE,
						"  *** Wrong returned size from %d:%zu > %zu\n",
						idx, size,
						cmd->param.c_shm[idx].size);

				else if ((cmd->param.params[idx].shm->flags &
					(TEE_SHM_MAPPED | TEE_SHM_TEMP)) ==
					(TEE_SHM_MAPPED | TEE_SHM_TEMP)) {
					BUG_ON(!cmd->param.c_shm[idx].buffer);
					BUG_ON(!cmd->param.c_shm[idx].size > 0);
					dev_dbg(_DEV_TEE, "%s: whole %p\n",
						__func__,
						cmd->param.params[idx].shm->
						kaddr);
					if (tee_copy_to_user
					    (ctx, cmd->param.c_shm[idx].buffer,
					     cmd->param.params[idx].shm->kaddr,
					     size))
						dev_err(_DEV_TEE,
							"%s: can't update %d result to user\n",
							__func__, idx);
				}
				break;
			}
		case TEEC_MEMREF_PARTIAL_OUTPUT:
		case TEEC_MEMREF_PARTIAL_INOUT:{
				int offset =
				    cmd_io->op->params[idx].memref.offset;
				/* Returned updated size */
				size_t size =
					cmd->param.params[idx].shm->size_req;

				if (size !=
					cmd_io->op->params[idx].memref.size) {
					dev_dbg(_DEV_TEE,
						"Size has been updated by the TA %zu != %zu\n",
						size,
						cmd_io->op->params[idx].memref.
						size);
					tee_put_user(ctx, size,
						     &cmd_io->op->params[idx].
						     memref.size);
				}

				/* ensure we do not exceed
				 * the shared buffer length */
				if ((offset + size) >
				    cmd->param.c_shm[idx].size)
					dev_err(_DEV_TEE,
						"  *** Wrong returned size from %d:%d +%zu > %zu\n",
						idx, offset, size,
						cmd->param.c_shm[idx].size);

				/* If we allocated a tmpref buffer,
				 * copy back data to the user buffer */
				else if ((cmd->param.params[idx].shm->flags &
					(TEE_SHM_MAPPED | TEE_SHM_TEMP)) ==
					(TEE_SHM_MAPPED | TEE_SHM_TEMP)) {
					BUG_ON(!cmd->param.c_shm[idx].buffer);
					BUG_ON(!cmd->param.c_shm[idx].size > 0);
					if (tee_copy_to_user
					    (ctx,
					     cmd->param.c_shm[idx].buffer +
					     offset,
					     cmd->param.params[idx].shm->kaddr,
					     size))
						dev_err(_DEV_TEE,
							"%s: can't update %d result to user\n",
							__func__, idx);
				}
				break;
			}
		default:
			BUG_ON(1);
		}
	}

}