コード例 #1
0
/*
 * Verify target ID is valid (exists in the OPENPROM tree), as
 * listed from node ID sid forward.
 */
int
openpromcheckid(int sid, int tid)
{
	for (; sid != 0; sid = OF_peer(sid))
		if (sid == tid || openpromcheckid(OF_child(sid), tid))
			return (1);

	return (0);
}
コード例 #2
0
/*
 * Verify target ID is valid (exists in the OPENPROM tree), as
 * listed from node ID sid forward.
 */
static int
openpromcheckid(int sid, int tid)
{

	for (; sid != 0; sid = nextsibling(sid))
		if (sid == tid || openpromcheckid(firstchild(sid), tid))
			return (1);

	return (0);
}
コード例 #3
0
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);
}
コード例 #4
0
int
openpromioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
	struct opiocdesc *op;
	int node, len, ok, error, s;
	char *name, *value, *nextprop;
	static char buf[32];	/* XXX */

	if (optionsnode == 0) {
		s = splhigh();
		optionsnode = OF_getnodebyname(0, "options");
		splx(s);
	}

	/* 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(OF_peer(0), 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();
		strlcpy(buf, name, 32);	/* XXX */
		len = OF_getproplen(node, buf);
		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();
		strlcpy(buf, name, 32);	/* XXX */
		OF_getprop(node, buf, value, len);
		splx(s);
		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();
		strlcpy(buf, name, 32);	/* XXX */
		len = OF_setprop(node, buf, 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;
		if (op->op_buflen <= 0) {
			error = ENAMETOOLONG;
			break;
		}
		value = nextprop = malloc(OPROMMAXPARAM, M_TEMP, M_WAITOK);
		if (nextprop == NULL) {
			error = ENOMEM;
			break;
		}
		s = splhigh();
		strlcpy(buf, name, 32);	/* XXX */
		error = OF_nextprop(node, buf, nextprop);
		splx(s);
		if (error == -1) {
			error = EINVAL;
			break;
		}
		if (error == 0) {
			char nul = '\0';

			op->op_buflen = 0;
			error = copyout(&nul, op->op_buf, sizeof(char));
			break;
		}
		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 = OF_peer(node);
		splx(s);
		*(int *)data = lastnode = node;
		break;

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

	default:
		return (ENOTTY);
	}

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

	return (error);
}