Пример #1
0
static int tf_map_temp_shmem(struct tf_connection *connection,
	 struct tf_command_param_temp_memref *temp_memref,
	 u32 param_type,
	 struct tf_shmem_desc **shmem_desc)
{
	u32 flags;
	u32 error = S_SUCCESS;
	bool in_user_space = connection->owner != TF_CONNECTION_OWNER_KERNEL;

	dprintk(KERN_INFO "tf_map_temp_shmem(%p, "
		"0x%08x[size=0x%08x], offset=0x%08x)\n",
		connection,
		temp_memref->descriptor,
		temp_memref->size,
		temp_memref->offset);

	switch (param_type) {
	case TF_PARAM_TYPE_MEMREF_TEMP_INPUT:
		flags = TF_SHMEM_TYPE_READ;
		break;
	case TF_PARAM_TYPE_MEMREF_TEMP_OUTPUT:
		flags = TF_SHMEM_TYPE_WRITE;
		break;
	case TF_PARAM_TYPE_MEMREF_TEMP_INOUT:
		flags = TF_SHMEM_TYPE_WRITE | TF_SHMEM_TYPE_READ;
		break;
	default:
		error = -EINVAL;
		goto error;
	}

	if (temp_memref->descriptor == 0) {
		/* NULL tmpref */
		temp_memref->offset = 0;
		*shmem_desc = NULL;
	} else if ((temp_memref->descriptor != 0) &&
			(temp_memref->size == 0)) {
		/* Empty tmpref */
		temp_memref->offset = temp_memref->descriptor;
		temp_memref->descriptor = 0;
		temp_memref->size = 0;
		*shmem_desc = NULL;
	} else {
		/* Map the temp shmem block */

		u32 shared_mem_descriptors[TF_MAX_COARSE_PAGES];
		u32 descriptor_count;

		if (in_user_space) {
			error = tf_validate_shmem_and_flags(
				temp_memref->descriptor,
				temp_memref->size,
				flags);
			if (error != 0)
				goto error;
		}

		error = tf_map_shmem(
				connection,
				temp_memref->descriptor,
				flags,
				in_user_space,
				shared_mem_descriptors,
				&(temp_memref->offset),
				temp_memref->size,
				shmem_desc,
				&descriptor_count);
		temp_memref->descriptor = shared_mem_descriptors[0];
	 }

error:
	 return error;
}
Пример #2
0
static long tf_ctrl_device_ioctl(struct file *file, unsigned int ioctl_num,
	unsigned long ioctl_param)
{
	int result = S_SUCCESS;
	struct tf_pa_ctrl pa_ctrl;
	struct tf_device *dev = tf_get_device();

	dpr_info("%s(%p, %u, %p)\n",
		__func__, file, ioctl_num, (void *) ioctl_param);

	mutex_lock(&dev->dev_mutex);

	if (ioctl_num != IOCTL_TF_PA_CTRL) {
		dpr_err("%s(%p): ioctl number is invalid (%p)\n",
			__func__, file, (void *)ioctl_num);

		result = -EFAULT;
		goto exit;
	}

	if ((ioctl_param & 0x3) != 0) {
		dpr_err("%s(%p): ioctl command message pointer is not word "
			"aligned (%p)\n",
			__func__, file, (void *)ioctl_param);

		result = -EFAULT;
		goto exit;
	}

	if (copy_from_user(&pa_ctrl, (struct tf_pa_ctrl *)ioctl_param,
			sizeof(struct tf_pa_ctrl))) {
		dpr_err("%s(%p): cannot access ioctl parameter (%p)\n",
			__func__, file, (void *)ioctl_param);

		result = -EFAULT;
		goto exit;
	}

	switch (pa_ctrl.nPACommand) {
	case TF_PA_CTRL_START: {
		struct tf_shmem_desc *shmem_desc = NULL;
		u32 shared_mem_descriptors[TF_MAX_COARSE_PAGES];
		u32 descriptor_count;
		u32 offset;
		struct tf_connection *connection;

		dpr_info("%s(%p): Start the SMC PA (%d bytes) with conf "
			"(%d bytes)\n",
			__func__, file, pa_ctrl.pa_size, pa_ctrl.conf_size);

		connection = tf_conn_from_file(file);

		if (dev->workspace_addr == 0) {
			result = -ENOMEM;
			goto start_exit;
		}

		result = tf_validate_shmem_and_flags(
				(u32)pa_ctrl.conf_buffer,
				pa_ctrl.conf_size,
				TF_SHMEM_TYPE_READ);
		if (result != 0)
			goto start_exit;

		offset = 0;
		result = tf_map_shmem(
				connection,
				(u32)pa_ctrl.conf_buffer,
				TF_SHMEM_TYPE_READ,
				true, /* in user space */
				shared_mem_descriptors,
				&offset,
				pa_ctrl.conf_size,
				&shmem_desc,
				&descriptor_count);
		if (result != 0)
			goto start_exit;

		if (descriptor_count > 1) {
			dpr_err("%s(%p): configuration file is too long (%d)\n",
				__func__, file, descriptor_count);
			result = -ENOMEM;
			goto start_exit;
		}

		result = tf_start(&dev->sm,
			dev->workspace_addr,
			dev->workspace_size,
			pa_ctrl.pa_buffer,
			pa_ctrl.pa_size,
			shared_mem_descriptors[0],
			offset,
			pa_ctrl.conf_size);
		if (result)
			dpr_err("SMC: start failed\n");
		else
			dpr_info("SMC: started\n");

start_exit:
		tf_unmap_shmem(connection, shmem_desc, true); /* full cleanup */
		break;
	}

	case TF_PA_CTRL_STOP:
		dpr_info("%s(%p): Stop the SMC PA\n", __func__, file);

		result = tf_power_management(&dev->sm,
			TF_POWER_OPERATION_SHUTDOWN);
		if (result)
			dpr_err("SMC: stop failed [0x%x]\n", result);
		else
			dpr_info("SMC: stopped\n");
		break;

	default:
		result = -EOPNOTSUPP;
		break;
	}

exit:
	mutex_unlock(&dev->dev_mutex);
	return result;
}
Пример #3
0
/*
 * Registers a shared memory to the Secure World
 */
int tf_register_shared_memory(
	struct tf_connection *connection,
	union tf_command *command,
	union tf_answer *answer)
{
	int error = 0;
	struct tf_shmem_desc *shmem_desc = NULL;
	bool in_user_space = connection->owner != TF_CONNECTION_OWNER_KERNEL;
	struct tf_command_register_shared_memory *msg =
		&command->register_shared_memory;

	dprintk(KERN_INFO "tf_register_shared_memory(%p) "
		"%p[0x%08X][0x%08x]\n",
		connection,
		(void *)msg->shared_mem_descriptors[0],
		msg->shared_mem_size,
		(u32)msg->memory_flags);

	if (in_user_space) {
		error = tf_validate_shmem_and_flags(
			msg->shared_mem_descriptors[0],
			msg->shared_mem_size,
			(u32)msg->memory_flags);
		if (error != 0)
			goto error;
	}

	/* Initialize message_size with no descriptors */
	msg->message_size
		= (offsetof(struct tf_command_register_shared_memory,
						shared_mem_descriptors) -
			sizeof(struct tf_command_header)) / 4;

	/* Map the shmem block and update the message */
	if (msg->shared_mem_size == 0) {
		/* Empty shared mem */
		msg->shared_mem_start_offset = msg->shared_mem_descriptors[0];
	} else {
		u32 descriptor_count;
		error = tf_map_shmem(
			connection,
			msg->shared_mem_descriptors[0],
			msg->memory_flags,
			in_user_space,
			msg->shared_mem_descriptors,
			&(msg->shared_mem_start_offset),
			msg->shared_mem_size,
			&shmem_desc,
			&descriptor_count);
		if (error != 0) {
			dprintk(KERN_ERR "tf_register_shared_memory: "
				"unable to map shared memory block\n");
			goto error;
		}
		msg->message_size += descriptor_count;
	}

	/*
	 * write the correct device context handle and the address of the shared
	 * memory descriptor in the message
	 */
	msg->device_context = connection->device_context;
	msg->block_id = (u32)shmem_desc;

	/* Send the updated message */
	error = tf_send_receive(
		&connection->dev->sm,
		command,
		answer,
		connection,
		true);

	if ((error != 0) ||
		(answer->register_shared_memory.error_code
			!= S_SUCCESS)) {
		dprintk(KERN_ERR "tf_register_shared_memory: "
			"operation failed. Unmap block\n");
		goto error;
	}

	/* Saves the block handle returned by the secure world */
	if (shmem_desc != NULL)
		shmem_desc->block_identifier =
			answer->register_shared_memory.block;

	/* successful completion */
	dprintk(KERN_INFO "tf_register_shared_memory(%p):"
		" block_id=0x%08x block=0x%08x\n",
		connection, msg->block_id,
		answer->register_shared_memory.block);
	return 0;

	/* error completion */
error:
	tf_unmap_shmem(
		connection,
		shmem_desc,
		0);

	if (error != 0)
		dprintk(KERN_ERR "tf_register_shared_memory returns %d\n",
			error);
	else
		dprintk(KERN_ERR "tf_register_shared_memory returns "
			"error_code 0x%08X\n",
			answer->register_shared_memory.error_code);

	return error;
}