0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/kernel.h>
0011 #include <linux/notifier.h>
0012 #include <linux/proc_fs.h>
0013 #include <linux/slab.h>
0014 #include <linux/of.h>
0015
0016 #include <asm/machdep.h>
0017 #include <linux/uaccess.h>
0018 #include <asm/mmu.h>
0019
0020 #include "of_helpers.h"
0021
0022 static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
0023 {
0024 struct device_node *np;
0025 int err = -ENOMEM;
0026
0027 np = kzalloc(sizeof(*np), GFP_KERNEL);
0028 if (!np)
0029 goto out_err;
0030
0031 np->full_name = kstrdup(kbasename(path), GFP_KERNEL);
0032 if (!np->full_name)
0033 goto out_err;
0034
0035 np->properties = proplist;
0036 of_node_set_flag(np, OF_DYNAMIC);
0037 of_node_init(np);
0038
0039 np->parent = pseries_of_derive_parent(path);
0040 if (IS_ERR(np->parent)) {
0041 err = PTR_ERR(np->parent);
0042 goto out_err;
0043 }
0044
0045 err = of_attach_node(np);
0046 if (err) {
0047 printk(KERN_ERR "Failed to add device node %s\n", path);
0048 goto out_err;
0049 }
0050
0051 of_node_put(np->parent);
0052
0053 return 0;
0054
0055 out_err:
0056 if (np) {
0057 of_node_put(np->parent);
0058 kfree(np->full_name);
0059 kfree(np);
0060 }
0061 return err;
0062 }
0063
0064 static int pSeries_reconfig_remove_node(struct device_node *np)
0065 {
0066 struct device_node *parent, *child;
0067
0068 parent = of_get_parent(np);
0069 if (!parent)
0070 return -EINVAL;
0071
0072 if ((child = of_get_next_child(np, NULL))) {
0073 of_node_put(child);
0074 of_node_put(parent);
0075 return -EBUSY;
0076 }
0077
0078 of_detach_node(np);
0079 of_node_put(parent);
0080 return 0;
0081 }
0082
0083
0084
0085
0086
0087
0088
0089 static void release_prop_list(const struct property *prop)
0090 {
0091 struct property *next;
0092 for (; prop; prop = next) {
0093 next = prop->next;
0094 kfree(prop->name);
0095 kfree(prop->value);
0096 kfree(prop);
0097 }
0098
0099 }
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113 static char * parse_next_property(char *buf, char *end, char **name, int *length,
0114 unsigned char **value)
0115 {
0116 char *tmp;
0117
0118 *name = buf;
0119
0120 tmp = strchr(buf, ' ');
0121 if (!tmp) {
0122 printk(KERN_ERR "property parse failed in %s at line %d\n",
0123 __func__, __LINE__);
0124 return NULL;
0125 }
0126 *tmp = '\0';
0127
0128 if (++tmp >= end) {
0129 printk(KERN_ERR "property parse failed in %s at line %d\n",
0130 __func__, __LINE__);
0131 return NULL;
0132 }
0133
0134
0135 *length = -1;
0136 *length = simple_strtoul(tmp, &tmp, 10);
0137 if (*length == -1) {
0138 printk(KERN_ERR "property parse failed in %s at line %d\n",
0139 __func__, __LINE__);
0140 return NULL;
0141 }
0142 if (*tmp != ' ' || ++tmp >= end) {
0143 printk(KERN_ERR "property parse failed in %s at line %d\n",
0144 __func__, __LINE__);
0145 return NULL;
0146 }
0147
0148
0149 *value = tmp;
0150 tmp += *length;
0151 if (tmp > end) {
0152 printk(KERN_ERR "property parse failed in %s at line %d\n",
0153 __func__, __LINE__);
0154 return NULL;
0155 }
0156 else if (tmp < end && *tmp != ' ' && *tmp != '\0') {
0157 printk(KERN_ERR "property parse failed in %s at line %d\n",
0158 __func__, __LINE__);
0159 return NULL;
0160 }
0161 tmp++;
0162
0163
0164 return tmp;
0165 }
0166
0167 static struct property *new_property(const char *name, const int length,
0168 const unsigned char *value, struct property *last)
0169 {
0170 struct property *new = kzalloc(sizeof(*new), GFP_KERNEL);
0171
0172 if (!new)
0173 return NULL;
0174
0175 if (!(new->name = kstrdup(name, GFP_KERNEL)))
0176 goto cleanup;
0177 if (!(new->value = kmalloc(length + 1, GFP_KERNEL)))
0178 goto cleanup;
0179
0180 memcpy(new->value, value, length);
0181 *(((char *)new->value) + length) = 0;
0182 new->length = length;
0183 new->next = last;
0184 return new;
0185
0186 cleanup:
0187 kfree(new->name);
0188 kfree(new->value);
0189 kfree(new);
0190 return NULL;
0191 }
0192
0193 static int do_add_node(char *buf, size_t bufsize)
0194 {
0195 char *path, *end, *name;
0196 struct device_node *np;
0197 struct property *prop = NULL;
0198 unsigned char* value;
0199 int length, rv = 0;
0200
0201 end = buf + bufsize;
0202 path = buf;
0203 buf = strchr(buf, ' ');
0204 if (!buf)
0205 return -EINVAL;
0206 *buf = '\0';
0207 buf++;
0208
0209 if ((np = of_find_node_by_path(path))) {
0210 of_node_put(np);
0211 return -EINVAL;
0212 }
0213
0214
0215 while (buf < end &&
0216 (buf = parse_next_property(buf, end, &name, &length, &value))) {
0217 struct property *last = prop;
0218
0219 prop = new_property(name, length, value, last);
0220 if (!prop) {
0221 rv = -ENOMEM;
0222 prop = last;
0223 goto out;
0224 }
0225 }
0226 if (!buf) {
0227 rv = -EINVAL;
0228 goto out;
0229 }
0230
0231 rv = pSeries_reconfig_add_node(path, prop);
0232
0233 out:
0234 if (rv)
0235 release_prop_list(prop);
0236 return rv;
0237 }
0238
0239 static int do_remove_node(char *buf)
0240 {
0241 struct device_node *node;
0242 int rv = -ENODEV;
0243
0244 if ((node = of_find_node_by_path(buf)))
0245 rv = pSeries_reconfig_remove_node(node);
0246
0247 of_node_put(node);
0248 return rv;
0249 }
0250
0251 static char *parse_node(char *buf, size_t bufsize, struct device_node **npp)
0252 {
0253 char *handle_str;
0254 phandle handle;
0255 *npp = NULL;
0256
0257 handle_str = buf;
0258
0259 buf = strchr(buf, ' ');
0260 if (!buf)
0261 return NULL;
0262 *buf = '\0';
0263 buf++;
0264
0265 handle = simple_strtoul(handle_str, NULL, 0);
0266
0267 *npp = of_find_node_by_phandle(handle);
0268 return buf;
0269 }
0270
0271 static int do_add_property(char *buf, size_t bufsize)
0272 {
0273 struct property *prop = NULL;
0274 struct device_node *np;
0275 unsigned char *value;
0276 char *name, *end;
0277 int length;
0278 end = buf + bufsize;
0279 buf = parse_node(buf, bufsize, &np);
0280
0281 if (!np)
0282 return -ENODEV;
0283
0284 if (parse_next_property(buf, end, &name, &length, &value) == NULL)
0285 return -EINVAL;
0286
0287 prop = new_property(name, length, value, NULL);
0288 if (!prop)
0289 return -ENOMEM;
0290
0291 of_add_property(np, prop);
0292
0293 return 0;
0294 }
0295
0296 static int do_remove_property(char *buf, size_t bufsize)
0297 {
0298 struct device_node *np;
0299 char *tmp;
0300 buf = parse_node(buf, bufsize, &np);
0301
0302 if (!np)
0303 return -ENODEV;
0304
0305 tmp = strchr(buf,' ');
0306 if (tmp)
0307 *tmp = '\0';
0308
0309 if (strlen(buf) == 0)
0310 return -EINVAL;
0311
0312 return of_remove_property(np, of_find_property(np, buf, NULL));
0313 }
0314
0315 static int do_update_property(char *buf, size_t bufsize)
0316 {
0317 struct device_node *np;
0318 unsigned char *value;
0319 char *name, *end, *next_prop;
0320 int length;
0321 struct property *newprop;
0322 buf = parse_node(buf, bufsize, &np);
0323 end = buf + bufsize;
0324
0325 if (!np)
0326 return -ENODEV;
0327
0328 next_prop = parse_next_property(buf, end, &name, &length, &value);
0329 if (!next_prop)
0330 return -EINVAL;
0331
0332 if (!strlen(name))
0333 return -ENODEV;
0334
0335 newprop = new_property(name, length, value, NULL);
0336 if (!newprop)
0337 return -ENOMEM;
0338
0339 if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size"))
0340 slb_set_size(*(int *)value);
0341
0342 return of_update_property(np, newprop);
0343 }
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357 static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t count,
0358 loff_t *off)
0359 {
0360 int rv;
0361 char *kbuf;
0362 char *tmp;
0363
0364 kbuf = memdup_user_nul(buf, count);
0365 if (IS_ERR(kbuf))
0366 return PTR_ERR(kbuf);
0367
0368 tmp = strchr(kbuf, ' ');
0369 if (!tmp) {
0370 rv = -EINVAL;
0371 goto out;
0372 }
0373 *tmp = '\0';
0374 tmp++;
0375
0376 if (!strcmp(kbuf, "add_node"))
0377 rv = do_add_node(tmp, count - (tmp - kbuf));
0378 else if (!strcmp(kbuf, "remove_node"))
0379 rv = do_remove_node(tmp);
0380 else if (!strcmp(kbuf, "add_property"))
0381 rv = do_add_property(tmp, count - (tmp - kbuf));
0382 else if (!strcmp(kbuf, "remove_property"))
0383 rv = do_remove_property(tmp, count - (tmp - kbuf));
0384 else if (!strcmp(kbuf, "update_property"))
0385 rv = do_update_property(tmp, count - (tmp - kbuf));
0386 else
0387 rv = -EINVAL;
0388 out:
0389 kfree(kbuf);
0390 return rv ? rv : count;
0391 }
0392
0393 static const struct proc_ops ofdt_proc_ops = {
0394 .proc_write = ofdt_write,
0395 .proc_lseek = noop_llseek,
0396 };
0397
0398
0399 static int proc_ppc64_create_ofdt(void)
0400 {
0401 struct proc_dir_entry *ent;
0402
0403 ent = proc_create("powerpc/ofdt", 0200, NULL, &ofdt_proc_ops);
0404 if (ent)
0405 proc_set_size(ent, 0);
0406
0407 return 0;
0408 }
0409 machine_device_initcall(pseries, proc_ppc64_create_ofdt);