static int __init prom_common_nextprop(phandle node, char *prev, char *buf)
{
	const char *name;

	buf[0] = '\0';
	name = prom_nextprop(node, prev, buf);
	return handle_nextprop_quirks(buf, name);
}
Beispiel #2
0
static struct property * __init build_one_prop(phandle node, char *prev,
					       char *special_name,
					       void *special_val,
					       int special_len)
{
	static struct property *tmp = NULL;
	struct property *p;
	const char *name;

	if (tmp) {
		p = tmp;
		memset(p, 0, sizeof(*p) + 32);
		tmp = NULL;
	} else {
		p = prom_early_alloc(sizeof(struct property) + 32);
		p->unique_id = prom_unique_id++;
	}

	p->name = (char *) (p + 1);
	if (special_name) {
		strcpy(p->name, special_name);
		p->length = special_len;
		p->value = prom_early_alloc(special_len);
		memcpy(p->value, special_val, special_len);
	} else {
		if (prev == NULL) {
			name = prom_firstprop(node, p->name);
		} else {
			name = prom_nextprop(node, prev, p->name);
		}

		if (!name || strlen(name) == 0) {
			tmp = p;
			return NULL;
		}
#ifdef CONFIG_SPARC32
		strcpy(p->name, name);
#endif
		p->length = prom_getproplen(node, p->name);
		if (p->length <= 0) {
			p->length = 0;
		} else {
			int len;

			p->value = prom_early_alloc(p->length + 1);
			len = prom_getproperty(node, p->name, p->value,
					       p->length);
			if (len <= 0)
				p->length = 0;
			((unsigned char *)p->value)[p->length] = '\0';
		}
	}
	return p;
}
Beispiel #3
0
int prom_node_has_property(int node, char *prop)
{
	char *current_property = "";

	do {
		current_property = prom_nextprop(node, current_property, NULL);
		if(!strcmp(current_property, prop))
		   return 1;
	} while (*current_property);
	return 0;
}
Beispiel #4
0
int prom_node_has_property(phandle node, const char *prop)
{
	char buf [32];
        
	*buf = 0;
	do {
		prom_nextprop(node, buf, buf);
		if (!strcmp(buf, prop))
			return 1;
	} while (*buf);
	return 0;
}
Beispiel #5
0
ddi_prop_t *
get_proplist(char *name)
{
    ddi_prop_t *plist, *npp, *plast;
    char *curprop, *newprop;
    unsigned char *propval;
    unsigned long id;

    plist = NULL;
    plast = NULL;
    id = prom_findnode_byname(prom_rootnode(), name);
    if (id == 0)
        return (plist);
    curprop = "";
    while (newprop = (char *)prom_nextprop(curprop)) {
        curprop = strdup(newprop);
        npp = (ddi_prop_t *)malloc(sizeof (ddi_prop_t));
        if (npp == 0)
            exit(_error(PERROR, mfail));
        propval = prom_getprop(curprop, &npp->prop_len);
        npp->prop_name = curprop;
        if (propval != NULL) {
            npp->prop_val = (char *)malloc(npp->prop_len);
            if (npp->prop_val == 0)
                exit(_error(PERROR, mfail));
            memcpy(npp->prop_val, propval, npp->prop_len);
        } else
            npp->prop_val = NULL;
        npp->prop_next = NULL;
        if (plast == NULL) {
            plist = npp;
        } else {
            plast->prop_next = npp;
        }
        plast = npp;
    }
    return (plist);
}
Beispiel #6
0
static ssize_t property_read(struct file *filp, char __user *buf,
			     size_t count, loff_t *ppos)
{
	struct inode *inode = filp->f_dentry->d_inode;
	int i, j, k;
	u32 node;
	char *p, *s;
	u32 *q;
	openprom_property *op;
	char buffer[64];
	
	if (filp->f_pos >= 0xffffff || count >= 0xffffff)
		return -EINVAL;
	if (!filp->private_data) {
		node = nodes[(u16)((long)inode->u.generic_ip)].node;
		i = ((u32)(long)inode->u.generic_ip) >> 16;
		if ((u16)((long)inode->u.generic_ip) == aliases) {
			if (i >= aliases_nodes)
				p = NULL;
			else
				p = alias_names [i];
		} else
			for (p = prom_firstprop (node, buffer);
			     i && p && *p;
			     p = prom_nextprop (node, p, buffer), i--)
				/* nothing */ ;
		if (!p || !*p)
			return -EIO;
		i = prom_getproplen (node, p);
		if (i < 0) {
			if ((u16)((long)inode->u.generic_ip) == aliases)
				i = 0;
			else
				return -EIO;
		}
		k = i;
		if (i < 64) i = 64;
		filp->private_data = kmalloc (sizeof (openprom_property)
					      + (j = strlen (p)) + 2 * i,
					      GFP_KERNEL);
		if (!filp->private_data)
			return -ENOMEM;
		op = (openprom_property *)filp->private_data;
		op->flag = 0;
		op->alloclen = 2 * i;
		strcpy (op->name, p);
		op->value = (char *)(((unsigned long)(op->name + j + 4)) & ~3);
		op->len = k;
		if (k && prom_getproperty (node, p, op->value, i) < 0)
			return -EIO;
		op->value [k] = 0;
		if (k) {
			for (s = NULL, p = op->value; p < op->value + k; p++) {
				if ((*p >= ' ' && *p <= '~') || *p == '\n') {
					op->flag |= OPP_STRING;
					s = p;
					continue;
				}
				if (p > op->value && !*p && s == p - 1) {
					if (p < op->value + k - 1)
						op->flag |= OPP_STRINGLIST;
					else
						op->flag |= OPP_ASCIIZ;
					continue;
				}
				if (k == 1 && !*p) {
					op->flag |= (OPP_STRING|OPP_ASCIIZ);
					break;
				}
				op->flag &= ~(OPP_STRING|OPP_STRINGLIST);
				if (k & 3)
					op->flag |= OPP_HEXSTRING;
				else
					op->flag |= OPP_BINARY;
				break;
			}
			if (op->flag & OPP_STRINGLIST)
				op->flag &= ~(OPP_STRING);
			if (op->flag & OPP_ASCIIZ)
				op->len--;
		}
	} else
Beispiel #7
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;

	}
}
Beispiel #8
0
/*
 *	SunOS and Solaris /dev/openprom ioctl calls.
 */
static int openprom_sunos_ioctl(struct inode * inode, struct file * file,
				unsigned int cmd, unsigned long arg, int node)
{
	DATA *data = (DATA *) file->private_data;
	char buffer[OPROMMAXPARAM+1], *buf;
	struct openpromio *opp;
	unsigned long flags;
	int bufsize, len, error = 0;
	extern char saved_command_line[];
	static int cnt;

	if (cmd == OPROMSETOPT)
		bufsize = getstrings((void *)arg, &opp);
	else
		bufsize = copyin((void *)arg, &opp);

	if (bufsize < 0)
		return bufsize;

	switch (cmd) {
	case OPROMGETOPT:
	case OPROMGETPROP:
		save_and_cli(flags);
		len = prom_getproplen(node, opp->oprom_array);
		restore_flags(flags);

		if (len <= 0 || len > bufsize) {
			error = copyout((void *)arg, opp, sizeof(int));
			break;
		}

		save_and_cli(flags);
		len = prom_getproperty(node, opp->oprom_array, buffer, bufsize);
		restore_flags(flags);

		memcpy(opp->oprom_array, buffer, len);
		opp->oprom_array[len] = '\0';
		opp->oprom_size = len;

		error = copyout((void *)arg, opp, sizeof(int) + bufsize);
		break;

	case OPROMNXTOPT:
	case OPROMNXTPROP:
		save_and_cli(flags);
		buf = prom_nextprop(node, opp->oprom_array, buffer);
		restore_flags(flags);

		len = strlen(buf);
		if (len == 0 || len + 1 > bufsize) {
			error = copyout((void *)arg, opp, sizeof(int));
			break;
		}

		memcpy(opp->oprom_array, buf, len);
		opp->oprom_array[len] = '\0';
		opp->oprom_size = ++len;

		error = copyout((void *)arg, opp, sizeof(int) + bufsize);
		break;

	case OPROMSETOPT:
	case OPROMSETOPT2:
		buf = opp->oprom_array + strlen(opp->oprom_array) + 1;
		len = opp->oprom_array + bufsize - buf;

		save_and_cli(flags);
		error = prom_setprop(options_node, opp->oprom_array,
				     buf, len);
		restore_flags(flags);

		if (error < 0)
			error = -EINVAL;
		break;

	case OPROMNEXT:
	case OPROMCHILD:
	case OPROMSETCUR:
		if (bufsize < sizeof(int)) {
			error = -EINVAL;
			break;
		}

		node = *((int *) opp->oprom_array);

		save_and_cli(flags);
		switch (cmd) {
		case OPROMNEXT: node = __prom_getsibling(node); break;
		case OPROMCHILD: node = __prom_getchild(node); break;
		case OPROMSETCUR: break;
		}
		restore_flags(flags);

		data->current_node = node;
		*((int *)opp->oprom_array) = node;
		opp->oprom_size = sizeof(int);

		error = copyout((void *)arg, opp, bufsize + sizeof(int));
		break;

	case OPROMPCI2NODE:
		error = -EINVAL;

		if (bufsize >= 2*sizeof(int)) {
#ifdef CONFIG_PCI
			struct pci_dev *pdev;
			struct pcidev_cookie *pcp;
			pdev = pci_find_slot (((int *) opp->oprom_array)[0],
					      ((int *) opp->oprom_array)[1]);

			pcp = pdev->sysdata;
			if (pcp != NULL && pcp->prom_node != -1 && pcp->prom_node) {
				node = pcp->prom_node;
				data->current_node = node;
				*((int *)opp->oprom_array) = node;
				opp->oprom_size = sizeof(int);
				error = copyout((void *)arg, opp, bufsize + sizeof(int));
			}
#endif
		}
		break;

	case OPROMPATH2NODE:
		save_and_cli(flags);
		node = prom_finddevice(opp->oprom_array);
		restore_flags(flags);
		data->current_node = node;
		*((int *)opp->oprom_array) = node;
		opp->oprom_size = sizeof(int);

		error = copyout((void *)arg, opp, bufsize + sizeof(int));
		break;

	case OPROMGETBOOTARGS:
		buf = saved_command_line;

		len = strlen(buf);

		if (len > bufsize) {
			error = -EINVAL;
			break;
		}

		strcpy(opp->oprom_array, buf);
		opp->oprom_size = len;

		error = copyout((void *)arg, opp, bufsize + sizeof(int));
		break;

	case OPROMU2P:
	case OPROMGETCONS:
	case OPROMGETFBNAME:
		if (cnt++ < 10)
			printk(KERN_INFO "openprom_sunos_ioctl: unimplemented ioctl\n");
		error = -EINVAL;
		break;
	default:
		if (cnt++ < 10)
			printk(KERN_INFO "openprom_sunos_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg);
		error = -EINVAL;
		break;
	}

	kfree(opp);
	return error;
}
int
openpromioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
{
	struct opiocdesc *op;
	int node, optionsnode, len, ok, error, s;
	char *name, *value, *nextprop;

	optionsnode = prom_getoptionsnode();

	/* All too easy... */
	if (cmd == OPIOCGETOPTNODE) {
		*(int *)data = optionsnode;
		return (0);
	}

	/* Verify node id */
	op = (struct opiocdesc *)data;
	node = op->op_nodeid;
	if (node != 0 && node != lastnode && node != optionsnode) {
		/* Not an easy one, must search for it */
		s = splhigh();
		ok = openpromcheckid(findroot(), node);
		splx(s);
		if (!ok)
			return (EINVAL);
		lastnode = node;
	}

	name = value = NULL;
	error = 0;
	switch (cmd) {

	case OPIOCGET:
		if ((flags & FREAD) == 0)
			return (EBADF);
		if (node == 0)
			return (EINVAL);
		error = openpromgetstr(op->op_namelen, op->op_name, &name);
		if (error)
			break;
		s = splhigh();
		len = prom_proplen(node, name);
		splx(s);
		if (len > op->op_buflen) {
			error = ENOMEM;
			break;
		}
		op->op_buflen = len;
		/* -1 means no entry; 0 means no value */
		if (len <= 0)
			break;
		value = malloc(len, M_TEMP, M_WAITOK);
		s = splhigh();
		error = prom_getprop(node, name, 1, &len, &value);
		splx(s);
		if (error != 0)
			break;
		error = copyout(value, op->op_buf, len);
		break;

	case OPIOCSET:
		if ((flags & FWRITE) == 0)
			return (EBADF);
		if (node == 0)
			return (EINVAL);
		error = openpromgetstr(op->op_namelen, op->op_name, &name);
		if (error)
			break;
		error = openpromgetstr(op->op_buflen, op->op_buf, &value);
		if (error)
			break;
		s = splhigh();
		len = prom_setprop(node, name, value, op->op_buflen + 1);
		splx(s);
		if (len != op->op_buflen)
			error = EINVAL;
		break;

	case OPIOCNEXTPROP:
		if ((flags & FREAD) == 0)
			return (EBADF);
		if (node == 0)
			return (EINVAL);
		error = openpromgetstr(op->op_namelen, op->op_name, &name);
		if (error)
			break;
		s = splhigh();
		nextprop = prom_nextprop(node, name);
		splx(s);
		len = strlen(nextprop);
		if (len > op->op_buflen)
			len = op->op_buflen;
		else
			op->op_buflen = len;
		error = copyout(nextprop, op->op_buf, len);
		break;

	case OPIOCGETNEXT:
		if ((flags & FREAD) == 0)
			return (EBADF);
		s = splhigh();
		node = nextsibling(node);
		splx(s);
		*(int *)data = lastnode = node;
		break;

	case OPIOCGETCHILD:
		if ((flags & FREAD) == 0)
			return (EBADF);
		if (node == 0)
			return (EINVAL);
		s = splhigh();
		node = firstchild(node);
		splx(s);
		*(int *)data = lastnode = node;
		break;

	case OPIOCFINDDEVICE:
		if ((flags & FREAD) == 0)
			return (EBADF);
		error = openpromgetstr(op->op_namelen, op->op_name, &name);
		if (error)
			break;
		node = prom_finddevice(name);
		if (node == 0 || node == -1) {
			error = ENOENT;
			break;
		}
		op->op_nodeid = lastnode = node;
		break;

	default:
		return (ENOTTY);
	}

	if (name)
		free(name, M_TEMP);
	if (value)
		free(value, M_TEMP);

	return (error);
}