2013-12-13 22:24:55 +00:00
|
|
|
/*
|
|
|
|
* drivers/staging/android/ion/compat_ion.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 2013 Google, Inc.
|
|
|
|
*
|
|
|
|
* This software is licensed under the terms of the GNU General Public
|
|
|
|
* License version 2, as published by the Free Software Foundation, and
|
|
|
|
* may be copied, distributed, and modified under those terms.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/compat.h>
|
|
|
|
#include <linux/fs.h>
|
|
|
|
#include <linux/uaccess.h>
|
|
|
|
|
|
|
|
#include "ion.h"
|
|
|
|
#include "compat_ion.h"
|
|
|
|
|
2013-12-13 22:24:57 +00:00
|
|
|
/* See drivers/staging/android/uapi/ion.h for the definition of these structs */
|
2013-12-13 22:24:55 +00:00
|
|
|
struct compat_ion_allocation_data {
|
|
|
|
compat_size_t len;
|
|
|
|
compat_size_t align;
|
|
|
|
compat_uint_t heap_id_mask;
|
|
|
|
compat_uint_t flags;
|
|
|
|
compat_int_t handle;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct compat_ion_custom_data {
|
|
|
|
compat_uint_t cmd;
|
|
|
|
compat_ulong_t arg;
|
|
|
|
};
|
|
|
|
|
2014-02-05 00:08:39 +00:00
|
|
|
struct compat_ion_handle_data {
|
|
|
|
compat_int_t handle;
|
|
|
|
};
|
|
|
|
|
2013-12-13 22:24:58 +00:00
|
|
|
#define COMPAT_ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \
|
|
|
|
struct compat_ion_allocation_data)
|
2014-02-05 00:08:39 +00:00
|
|
|
#define COMPAT_ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, \
|
|
|
|
struct compat_ion_handle_data)
|
2013-12-13 22:24:58 +00:00
|
|
|
#define COMPAT_ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, \
|
|
|
|
struct compat_ion_custom_data)
|
|
|
|
|
2013-12-13 22:24:55 +00:00
|
|
|
static int compat_get_ion_allocation_data(
|
|
|
|
struct compat_ion_allocation_data __user *data32,
|
|
|
|
struct ion_allocation_data __user *data)
|
|
|
|
{
|
|
|
|
compat_size_t s;
|
|
|
|
compat_uint_t u;
|
|
|
|
compat_int_t i;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = get_user(s, &data32->len);
|
|
|
|
err |= put_user(s, &data->len);
|
|
|
|
err |= get_user(s, &data32->align);
|
|
|
|
err |= put_user(s, &data->align);
|
|
|
|
err |= get_user(u, &data32->heap_id_mask);
|
|
|
|
err |= put_user(u, &data->heap_id_mask);
|
|
|
|
err |= get_user(u, &data32->flags);
|
|
|
|
err |= put_user(u, &data->flags);
|
|
|
|
err |= get_user(i, &data32->handle);
|
|
|
|
err |= put_user(i, &data->handle);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2014-02-05 00:08:39 +00:00
|
|
|
static int compat_get_ion_handle_data(
|
|
|
|
struct compat_ion_handle_data __user *data32,
|
|
|
|
struct ion_handle_data __user *data)
|
|
|
|
{
|
|
|
|
compat_int_t i;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = get_user(i, &data32->handle);
|
|
|
|
err |= put_user(i, &data->handle);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2013-12-13 22:24:55 +00:00
|
|
|
static int compat_put_ion_allocation_data(
|
|
|
|
struct compat_ion_allocation_data __user *data32,
|
|
|
|
struct ion_allocation_data __user *data)
|
|
|
|
{
|
|
|
|
compat_size_t s;
|
|
|
|
compat_uint_t u;
|
|
|
|
compat_int_t i;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = get_user(s, &data->len);
|
|
|
|
err |= put_user(s, &data32->len);
|
|
|
|
err |= get_user(s, &data->align);
|
|
|
|
err |= put_user(s, &data32->align);
|
|
|
|
err |= get_user(u, &data->heap_id_mask);
|
|
|
|
err |= put_user(u, &data32->heap_id_mask);
|
|
|
|
err |= get_user(u, &data->flags);
|
|
|
|
err |= put_user(u, &data32->flags);
|
|
|
|
err |= get_user(i, &data->handle);
|
|
|
|
err |= put_user(i, &data32->handle);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int compat_get_ion_custom_data(
|
|
|
|
struct compat_ion_custom_data __user *data32,
|
|
|
|
struct ion_custom_data __user *data)
|
|
|
|
{
|
2013-12-14 03:26:33 +00:00
|
|
|
compat_uint_t cmd;
|
|
|
|
compat_ulong_t arg;
|
2013-12-13 22:24:55 +00:00
|
|
|
int err;
|
|
|
|
|
|
|
|
err = get_user(cmd, &data32->cmd);
|
|
|
|
err |= put_user(cmd, &data->cmd);
|
|
|
|
err |= get_user(arg, &data32->arg);
|
|
|
|
err |= put_user(arg, &data->arg);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
};
|
|
|
|
|
|
|
|
long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|
|
|
{
|
|
|
|
long ret;
|
|
|
|
|
2014-09-02 21:29:40 +00:00
|
|
|
if (!filp->f_op->unlocked_ioctl)
|
2013-12-13 22:24:55 +00:00
|
|
|
return -ENOTTY;
|
|
|
|
|
|
|
|
switch (cmd) {
|
2013-12-13 22:24:58 +00:00
|
|
|
case COMPAT_ION_IOC_ALLOC:
|
2013-12-13 22:24:55 +00:00
|
|
|
{
|
|
|
|
struct compat_ion_allocation_data __user *data32;
|
|
|
|
struct ion_allocation_data __user *data;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
data32 = compat_ptr(arg);
|
|
|
|
data = compat_alloc_user_space(sizeof(*data));
|
2015-11-01 14:38:20 +00:00
|
|
|
if (!data)
|
2013-12-13 22:24:55 +00:00
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
err = compat_get_ion_allocation_data(data32, data);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2013-12-13 22:24:58 +00:00
|
|
|
ret = filp->f_op->unlocked_ioctl(filp, ION_IOC_ALLOC,
|
2013-12-13 22:24:55 +00:00
|
|
|
(unsigned long)data);
|
|
|
|
err = compat_put_ion_allocation_data(data32, data);
|
|
|
|
return ret ? ret : err;
|
|
|
|
}
|
2013-12-13 22:24:58 +00:00
|
|
|
case COMPAT_ION_IOC_FREE:
|
2013-12-13 22:24:55 +00:00
|
|
|
{
|
2014-02-05 00:08:39 +00:00
|
|
|
struct compat_ion_handle_data __user *data32;
|
|
|
|
struct ion_handle_data __user *data;
|
2013-12-13 22:24:55 +00:00
|
|
|
int err;
|
|
|
|
|
|
|
|
data32 = compat_ptr(arg);
|
|
|
|
data = compat_alloc_user_space(sizeof(*data));
|
2015-11-01 14:38:20 +00:00
|
|
|
if (!data)
|
2013-12-13 22:24:55 +00:00
|
|
|
return -EFAULT;
|
|
|
|
|
2014-02-05 00:08:39 +00:00
|
|
|
err = compat_get_ion_handle_data(data32, data);
|
2013-12-13 22:24:55 +00:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
2013-12-13 22:24:58 +00:00
|
|
|
return filp->f_op->unlocked_ioctl(filp, ION_IOC_FREE,
|
2013-12-13 22:24:55 +00:00
|
|
|
(unsigned long)data);
|
|
|
|
}
|
2013-12-13 22:24:58 +00:00
|
|
|
case COMPAT_ION_IOC_CUSTOM: {
|
2013-12-13 22:24:55 +00:00
|
|
|
struct compat_ion_custom_data __user *data32;
|
|
|
|
struct ion_custom_data __user *data;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
data32 = compat_ptr(arg);
|
|
|
|
data = compat_alloc_user_space(sizeof(*data));
|
2015-11-01 14:38:20 +00:00
|
|
|
if (!data)
|
2013-12-13 22:24:55 +00:00
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
err = compat_get_ion_custom_data(data32, data);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
2013-12-13 22:24:58 +00:00
|
|
|
return filp->f_op->unlocked_ioctl(filp, ION_IOC_CUSTOM,
|
2013-12-13 22:24:55 +00:00
|
|
|
(unsigned long)data);
|
|
|
|
}
|
|
|
|
case ION_IOC_SHARE:
|
|
|
|
case ION_IOC_MAP:
|
|
|
|
case ION_IOC_IMPORT:
|
|
|
|
case ION_IOC_SYNC:
|
|
|
|
return filp->f_op->unlocked_ioctl(filp, cmd,
|
|
|
|
(unsigned long)compat_ptr(arg));
|
|
|
|
default:
|
|
|
|
return -ENOIOCTLCMD;
|
|
|
|
}
|
|
|
|
}
|