Example #1
0
static int opiocset(void __user *argp, DATA *data)
{
	struct opiocdesc op;
	struct device_node *dp;
	char *str, *tmp;
	int err;

	if (copy_from_user(&op, argp, sizeof(op)))
		return -EFAULT;

	dp = get_node(op.op_nodeid, data);
	if (!dp)
		return -EINVAL;

	err = copyin_string(op.op_name, op.op_namelen, &str);
	if (err)
		return err;

	err = copyin_string(op.op_buf, op.op_buflen, &tmp);
	if (err) {
		kfree(str);
		return err;
	}

	err = of_set_property(dp, str, tmp, op.op_buflen);

	kfree(str);
	kfree(tmp);

	return err;
}
Example #2
0
/*
 *	NetBSD /dev/openprom ioctl calls.
 */
static int opiocget(void __user *argp, DATA *data)
{
	struct opiocdesc op;
	struct device_node *dp;
	char *str;
	void *pval;
	int err, len;

	if (copy_from_user(&op, argp, sizeof(op)))
		return -EFAULT;

	dp = get_node(op.op_nodeid, data);

	err = copyin_string(op.op_name, op.op_namelen, &str);
	if (err)
		return err;

	pval = of_get_property(dp, str, &len);
	err = 0;
	if (!pval || len > op.op_buflen) {
		err = -EINVAL;
	} else {
		op.op_buflen = len;
		if (copy_to_user(argp, &op, sizeof(op)) ||
		    copy_to_user(op.op_buf, pval, len))
			err = -EFAULT;
	}
	kfree(str);

	return err;
}
Example #3
0
static int opiocnextprop(void __user *argp, DATA *data)
{
	struct opiocdesc op;
	struct device_node *dp;
	struct property *prop;
	char *str;
	int err, len;

	if (copy_from_user(&op, argp, sizeof(op)))
		return -EFAULT;

	dp = get_node(op.op_nodeid, data);
	if (!dp)
		return -EINVAL;

	err = copyin_string(op.op_name, op.op_namelen, &str);
	if (err)
		return err;

	if (str[0] == '\0') {
		prop = dp->properties;
	} else {
		prop = of_find_property(dp, str, NULL);
		if (prop)
			prop = prop->next;
	}
	kfree(str);

	if (!prop)
		len = 0;
	else
		len = prop->length;

	if (len > op.op_buflen)
		len = op.op_buflen;

	if (copy_to_user(argp, &op, sizeof(op)))
		return -EFAULT;

	if (len &&
	    copy_to_user(op.op_buf, prop->value, len))
		return -EFAULT;

	return 0;
}
Example #4
0
/*
 *	NetBSD /dev/openprom ioctl calls.
 */
static int openprom_bsd_ioctl(struct inode * inode, struct file * file,
			      unsigned int cmd, unsigned long arg)
{
	DATA *data = (DATA *) file->private_data;
	struct opiocdesc op;
	unsigned long flags;
	int error, node, len;
	char *str, *tmp;
	char buffer[64];
	static int cnt;

	switch (cmd) {
	case OPIOCGET:
		if (copy_from_user(&op, (void *)arg, sizeof(op)))
			return -EFAULT;

		if (!goodnode(op.op_nodeid,data))
			return -EINVAL;

		error = copyin_string(op.op_name, op.op_namelen, &str);
		if (error)
			return error;

		save_and_cli(flags);
		len = prom_getproplen(op.op_nodeid,str);
		restore_flags(flags);

		if (len > op.op_buflen) {
			kfree(str);
			return -ENOMEM;
		}

		op.op_buflen = len;

		if (len <= 0) {
			kfree(str);
			/* Verified by the above copy_from_user */
			if (__copy_to_user((void *)arg, &op,
				       sizeof(op)))
				return -EFAULT;
			return 0;
		}

		tmp = kmalloc(len + 1, GFP_KERNEL);
		if (!tmp) {
			kfree(str);
			return -ENOMEM;
		}

		save_and_cli(flags);
		prom_getproperty(op.op_nodeid, str, tmp, len);
		restore_flags(flags);

		tmp[len] = '\0';

		error = __copy_to_user((void *)arg, &op, sizeof(op));
		if (!error)
			error = copy_to_user(op.op_buf, tmp, len);

		kfree(tmp);
		kfree(str);

		return error;

	case OPIOCNEXTPROP:
		if (copy_from_user(&op, (void *)arg, sizeof(op)))
			return -EFAULT;

		if (!goodnode(op.op_nodeid,data))
			return -EINVAL;

		error = copyin_string(op.op_name, op.op_namelen, &str);
		if (error)
			return error;

		save_and_cli(flags);
		tmp = prom_nextprop(op.op_nodeid,str,buffer);
		restore_flags(flags);

		if (tmp) {
			len = strlen(tmp);
			if (len > op.op_buflen)
				len = op.op_buflen;
			else
				op.op_buflen = len;
		} else {
			len = op.op_buflen = 0;
		}

		error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(op));
		if (error) {
			kfree(str);
			return error;
		}

		error = verify_area(VERIFY_WRITE, op.op_buf, len);
		if (error) {
			kfree(str);
			return error;
		}

		error = __copy_to_user((void *)arg, &op, sizeof(op));
		if (!error) error = __copy_to_user(op.op_buf, tmp, len);

		kfree(str);

		return error;

	case OPIOCSET:
		if (copy_from_user(&op, (void *)arg, sizeof(op)))
			return -EFAULT;

		if (!goodnode(op.op_nodeid,data))
			return -EINVAL;

		error = copyin_string(op.op_name, op.op_namelen, &str);
		if (error)
			return error;

		error = copyin_string(op.op_buf, op.op_buflen, &tmp);
		if (error) {
			kfree(str);
			return error;
		}

		save_and_cli(flags);
		len = prom_setprop(op.op_nodeid,str,tmp,op.op_buflen+1);
		restore_flags(flags);

		if (len != op.op_buflen)
			return -EINVAL;

		kfree(str);
		kfree(tmp);

		return 0;

	case OPIOCGETOPTNODE:
		if (copy_to_user((void *)arg, &options_node, sizeof(int)))
			return -EFAULT;
		return 0;

	case OPIOCGETNEXT:
	case OPIOCGETCHILD:
		if (copy_from_user(&node, (void *)arg, sizeof(int)))
			return -EFAULT;

		save_and_cli(flags);
		if (cmd == OPIOCGETNEXT)
			node = __prom_getsibling(node);
		else
			node = __prom_getchild(node);
		restore_flags(flags);

		if (__copy_to_user((void *)arg, &node, sizeof(int)))
			return -EFAULT;

		return 0;

	default:
		if (cnt++ < 10)
			printk(KERN_INFO "openprom_bsd_ioctl: cmd 0x%X\n", cmd);
		return -EINVAL;

	}
}