forked from Minki/linux
[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: Dave Boutcher <sleddog@us.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
ecaa8b0ff3
commit
610d91511f
@ -350,6 +350,100 @@ static int do_remove_node(char *buf)
|
||||
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
|
||||
*
|
||||
@ -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));
|
||||
else if (!strcmp(kbuf, "remove_node"))
|
||||
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
|
||||
rv = -EINVAL;
|
||||
out:
|
||||
|
Loading…
Reference in New Issue
Block a user