Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 610d9151 authored by Dave C Boutcher's avatar Dave C Boutcher Committed by Paul Mackerras
Browse files

[PATCH] powerpc: Add support for changing properties from userspace



Add support to reconfigure the device tree through the existing
proc filesystem interface.  Add "add_property", "remove_property",
and "update_property" commands to the existing interface.

Signed-off-by: default avatarDave Boutcher <sleddog@us.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent ecaa8b0f
Loading
Loading
Loading
Loading
+100 −0
Original line number Original line Diff line number Diff line
@@ -350,6 +350,100 @@ static int do_remove_node(char *buf)
	return rv;
	return rv;
}
}


static char *parse_node(char *buf, size_t bufsize, struct device_node **npp)
{
	char *handle_str;
	phandle handle;
	*npp = NULL;

	handle_str = buf;

	buf = strchr(buf, ' ');
	if (!buf)
		return NULL;
	*buf = '\0';
	buf++;

	handle = simple_strtoul(handle_str, NULL, 10);

	*npp = of_find_node_by_phandle(handle);
	return buf;
}

static int do_add_property(char *buf, size_t bufsize)
{
	struct property *prop = NULL;
	struct device_node *np;
	unsigned char *value;
	char *name, *end;
	int length;
	end = buf + bufsize;
	buf = parse_node(buf, bufsize, &np);

	if (!np)
		return -ENODEV;

	if (parse_next_property(buf, end, &name, &length, &value) == NULL)
		return -EINVAL;

	prop = new_property(name, length, value, NULL);
	if (!prop)
		return -ENOMEM;

	prom_add_property(np, prop);

	return 0;
}

static int do_remove_property(char *buf, size_t bufsize)
{
	struct device_node *np;
	char *tmp;
	struct property *prop;
	buf = parse_node(buf, bufsize, &np);

	if (!np)
		return -ENODEV;

	tmp = strchr(buf,' ');
	if (tmp)
		*tmp = '\0';

	if (strlen(buf) == 0)
		return -EINVAL;

	prop = of_find_property(np, buf, NULL);

	return prom_remove_property(np, prop);
}

static int do_update_property(char *buf, size_t bufsize)
{
	struct device_node *np;
	unsigned char *value;
	char *name, *end;
	int length;
	struct property *newprop, *oldprop;
	buf = parse_node(buf, bufsize, &np);
	end = buf + bufsize;

	if (!np)
		return -ENODEV;

	if (parse_next_property(buf, end, &name, &length, &value) == NULL)
		return -EINVAL;

	newprop = new_property(name, length, value, NULL);
	if (!newprop)
		return -ENOMEM;

	oldprop = of_find_property(np, name,NULL);
	if (!oldprop)
		return -ENODEV;

	return prom_update_property(np, newprop, oldprop);
}

/**
/**
 * ofdt_write - perform operations on the Open Firmware device tree
 * ofdt_write - perform operations on the Open Firmware device tree
 *
 *
@@ -392,6 +486,12 @@ static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t coun
		rv = do_add_node(tmp, count - (tmp - kbuf));
		rv = do_add_node(tmp, count - (tmp - kbuf));
	else if (!strcmp(kbuf, "remove_node"))
	else if (!strcmp(kbuf, "remove_node"))
		rv = do_remove_node(tmp);
		rv = do_remove_node(tmp);
	else if (!strcmp(kbuf, "add_property"))
		rv = do_add_property(tmp, count - (tmp - kbuf));
	else if (!strcmp(kbuf, "remove_property"))
		rv = do_remove_property(tmp, count - (tmp - kbuf));
	else if (!strcmp(kbuf, "update_property"))
		rv = do_update_property(tmp, count - (tmp - kbuf));
	else
	else
		rv = -EINVAL;
		rv = -EINVAL;
out:
out: