Пример #1
0
static int smcmod_send_buf_cmd(struct smcmod_buf_req *reqp)
{
	int ret = 0;
	struct ion_client *ion_clientp = NULL;
	struct ion_handle *ion_cmd_handlep = NULL;
	struct ion_handle *ion_resp_handlep = NULL;
	void *cmd_vaddrp = NULL;
	void *resp_vaddrp = NULL;
	unsigned long cmd_buf_size = 0;
	unsigned long resp_buf_size = 0;

	/* sanity check the argument */
	if (IS_ERR_OR_NULL(reqp))
		return -EINVAL;

	/* sanity check the fds */
	if (reqp->ion_cmd_fd < 0)
		return -EINVAL;

	/* create an ion client */
	ion_clientp = msm_ion_client_create(UINT_MAX, "smcmod");

	/* check for errors */
	if (IS_ERR_OR_NULL(ion_clientp))
		return -EINVAL;

	/* import the command buffer fd */
	ion_cmd_handlep = ion_import_dma_buf(ion_clientp, reqp->ion_cmd_fd);

	/* sanity check the handle */
	if (IS_ERR_OR_NULL(ion_cmd_handlep)) {
		ret = -EINVAL;
		goto buf_cleanup;
	}

	/* retrieve the size of the buffer */
	if (ion_handle_get_size(ion_clientp, ion_cmd_handlep,
		&cmd_buf_size) < 0) {
		ret = -EINVAL;
		goto buf_cleanup;
	}

	/* ensure that the command buffer size is not
	 * greater than the size of the buffer.
	 */
	if (reqp->cmd_len > cmd_buf_size) {
		ret = -EINVAL;
		goto buf_cleanup;
	}

	/* map the area to get a virtual address */
	cmd_vaddrp = ion_map_kernel(ion_clientp, ion_cmd_handlep);

	/* sanity check the address */
	if (IS_ERR_OR_NULL(cmd_vaddrp)) {
		ret = -EINVAL;
		goto buf_cleanup;
	}

	/* check if there is a response buffer */
	if (reqp->ion_resp_fd >= 0) {
		/* import the handle */
		ion_resp_handlep =
			ion_import_dma_buf(ion_clientp, reqp->ion_resp_fd);

		/* sanity check the handle */
		if (IS_ERR_OR_NULL(ion_resp_handlep)) {
			ret = -EINVAL;
			goto buf_cleanup;
		}

		/* retrieve the size of the buffer */
		if (ion_handle_get_size(ion_clientp, ion_resp_handlep,
			&resp_buf_size) < 0) {
			ret = -EINVAL;
			goto buf_cleanup;
		}

		/* ensure that the command buffer size is not
		 * greater than the size of the buffer.
		 */
		if (reqp->resp_len > resp_buf_size) {
			ret = -EINVAL;
			goto buf_cleanup;
		}

		/* map the area to get a virtual address */
		resp_vaddrp = ion_map_kernel(ion_clientp, ion_resp_handlep);

		/* sanity check the address */
		if (IS_ERR_OR_NULL(resp_vaddrp)) {
			ret = -EINVAL;
			goto buf_cleanup;
		}
	}

	/* No need to flush the cache lines for the command buffer here,
	 * because the buffer will be flushed by scm_call.
	 */

	/* call scm function to switch to secure world */
	reqp->return_val = scm_call(reqp->service_id, reqp->command_id,
		cmd_vaddrp, reqp->cmd_len, resp_vaddrp, reqp->resp_len);

	/* The cache lines for the response buffer have already been
	 * invalidated by scm_call before returning.
	 */

buf_cleanup:
	/* if the client and handle(s) are valid, free them */
	if (!IS_ERR_OR_NULL(ion_clientp)) {
		if (!IS_ERR_OR_NULL(ion_cmd_handlep)) {
			if (!IS_ERR_OR_NULL(cmd_vaddrp))
				ion_unmap_kernel(ion_clientp, ion_cmd_handlep);
			ion_free(ion_clientp, ion_cmd_handlep);
		}

		if (!IS_ERR_OR_NULL(ion_resp_handlep)) {
			if (!IS_ERR_OR_NULL(resp_vaddrp))
				ion_unmap_kernel(ion_clientp, ion_resp_handlep);
			ion_free(ion_clientp, ion_resp_handlep);
		}

		ion_client_destroy(ion_clientp);
	}

	return ret;
}
static long ion_test_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
	int ret;
	ion_phys_addr_t phys_addr;
	void *addr;
	size_t len;
	unsigned long flags, size;
	struct msm_ion_test *ion_test = file->private_data;
	struct ion_test_data *test_data = &ion_test->test_data;

	switch (cmd) {
	case IOC_ION_KCLIENT_CREATE:
	{
		ret = create_ion_client(ion_test);
		break;
	}
	case IOC_ION_KCLIENT_DESTROY:
	{
		free_ion_client(ion_test);
		ret = 0;
		break;
	}
	case IOC_ION_KALLOC:
	{
		if (copy_from_user(test_data, (void __user *)arg,
						sizeof(struct ion_test_data)))
			return -EFAULT;
		ret = alloc_ion_buf(ion_test, test_data);
		if (ret)
			pr_info("allocating ion buffer failed\n");
		break;
	}
	case IOC_ION_KFREE:
	{
		free_ion_buf(ion_test);
		ret = 0;
		break;
	}
	case IOC_ION_KPHYS:
	{
		ret = ion_phys(ion_test->ion_client, ion_test->ion_handle,
							&phys_addr, &len);
		if (!ret)
			pr_info("size is 0x%x\n phys addr 0x%x", len,
						(unsigned int)phys_addr);
		break;
	}
	case IOC_ION_KMAP:
	{
		addr = ion_map_kernel(ion_test->ion_client,
					ion_test->ion_handle);
		if (IS_ERR_OR_NULL(addr)) {
			ret = -EIO;
			pr_info("mapping kernel buffer failed\n");
		} else {
			ret = 0;
			test_data->vaddr = (unsigned long)addr;
		}
		break;
	}
	case IOC_ION_KUMAP:
	{
		ion_unmap_kernel(ion_test->ion_client, ion_test->ion_handle);
		ret = 0;
		break;
	}
	case IOC_ION_UIMPORT:
	{
		if (copy_from_user(test_data, (void __user *)arg,
						sizeof(struct ion_test_data)))
			return -EFAULT;
		ion_test->ion_handle = ion_import_dma_buf(ion_test->ion_client,
							test_data->shared_fd);
		if (IS_ERR_OR_NULL(ion_test->ion_handle)) {
			ret = -EIO;
			pr_info("import of user buf failed\n");
		} else
			ret = 0;
		break;
	}
	case IOC_ION_UBUF_FLAGS:
	{
		ret = ion_handle_get_flags(ion_test->ion_client,
						ion_test->ion_handle, &flags);
		if (ret)
			pr_info("user flags cannot be retrieved\n");
		else
			if (copy_to_user((void __user *)arg, &flags,
						sizeof(unsigned long)))
				ret = -EFAULT;
		break;
	}
	case IOC_ION_UBUF_SIZE:
	{
		ret = ion_handle_get_size(ion_test->ion_client,
						ion_test->ion_handle, &size);
		if (ret)
			pr_info("buffer size cannot be retrieved\n");
		else
			if (copy_to_user((void __user *)arg, &size,
							sizeof(unsigned long)))
				ret = -EFAULT;
		break;
	}
	case IOC_ION_WRITE_VERIFY:
	{
		write_pattern(test_data->vaddr, test_data->size);
		if (verify_pattern(test_data->vaddr, test_data->size)) {
			pr_info("verify of mapped buf failed\n");
			ret = -EIO;
		} else
			ret = 0;
		break;
	}
	case IOC_ION_VERIFY:
	{
		if (verify_pattern(test_data->vaddr, test_data->size)) {
			pr_info("fail in verifying imported buffer\n");
			ret = -EIO;
		} else
			ret = 0;
		break;
	}
	case IOC_ION_SEC:
	{
		ret = msm_ion_secure_heap(ION_CP_MM_HEAP_ID);
		if (ret)
			pr_info("unable to secure heap\n");
		else
			pr_info("able to secure heap\n");
		break;
	}
	case IOC_ION_UNSEC:
	{
		ret = msm_ion_unsecure_heap(ION_CP_MM_HEAP_ID);
		if (ret)
			pr_info("unable to unsecure heap\n");
		else
			pr_info("able to unsecure heap\n");
		break;
	}
	default:
	{
		pr_info("command not supproted\n");
		ret = -EINVAL;
	}
	};
	return ret;
}