1 /* prom_common.c: OF device tree support common code. 2 * 3 * Paul Mackerras August 1996. 4 * Copyright (C) 1996-2005 Paul Mackerras. 5 * 6 * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. 7 * {engebret|bergner}@us.ibm.com 8 * 9 * Adapted for sparc by David S. Miller davem@davemloft.net 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation; either version 14 * 2 of the License, or (at your option) any later version. 15 */ 16 17 #include <linux/kernel.h> 18 #include <linux/module.h> 19 #include <linux/errno.h> 20 #include <linux/mutex.h> 21 #include <linux/slab.h> 22 #include <linux/of.h> 23 #include <asm/prom.h> 24 #include <asm/oplib.h> 25 #include <asm/leon.h> 26 27 #include "prom.h" 28 29 void (*prom_build_more)(struct device_node *dp, struct device_node ***nextp); 30 31 struct device_node *of_console_device; 32 EXPORT_SYMBOL(of_console_device); 33 34 char *of_console_path; 35 EXPORT_SYMBOL(of_console_path); 36 37 char *of_console_options; 38 EXPORT_SYMBOL(of_console_options); 39 40 struct device_node *of_find_node_by_phandle(phandle handle) 41 { 42 struct device_node *np; 43 44 for (np = allnodes; np; np = np->allnext) 45 if (np->node == handle) 46 break; 47 48 return np; 49 } 50 EXPORT_SYMBOL(of_find_node_by_phandle); 51 52 int of_getintprop_default(struct device_node *np, const char *name, int def) 53 { 54 struct property *prop; 55 int len; 56 57 prop = of_find_property(np, name, &len); 58 if (!prop || len != 4) 59 return def; 60 61 return *(int *) prop->value; 62 } 63 EXPORT_SYMBOL(of_getintprop_default); 64 65 DEFINE_MUTEX(of_set_property_mutex); 66 EXPORT_SYMBOL(of_set_property_mutex); 67 68 int of_set_property(struct device_node *dp, const char *name, void *val, int len) 69 { 70 struct property **prevp; 71 void *new_val; 72 int err; 73 74 new_val = kmalloc(len, GFP_KERNEL); 75 if (!new_val) 76 return -ENOMEM; 77 78 memcpy(new_val, val, len); 79 80 err = -ENODEV; 81 82 write_lock(&devtree_lock); 83 prevp = &dp->properties; 84 while (*prevp) { 85 struct property *prop = *prevp; 86 87 if (!strcasecmp(prop->name, name)) { 88 void *old_val = prop->value; 89 int ret; 90 91 mutex_lock(&of_set_property_mutex); 92 ret = prom_setprop(dp->node, name, val, len); 93 mutex_unlock(&of_set_property_mutex); 94 95 err = -EINVAL; 96 if (ret >= 0) { 97 prop->value = new_val; 98 prop->length = len; 99 100 if (OF_IS_DYNAMIC(prop)) 101 kfree(old_val); 102 103 OF_MARK_DYNAMIC(prop); 104 105 err = 0; 106 } 107 break; 108 } 109 prevp = &(*prevp)->next; 110 } 111 write_unlock(&devtree_lock); 112 113 /* XXX Upate procfs if necessary... */ 114 115 return err; 116 } 117 EXPORT_SYMBOL(of_set_property); 118 119 int of_find_in_proplist(const char *list, const char *match, int len) 120 { 121 while (len > 0) { 122 int l; 123 124 if (!strcmp(list, match)) 125 return 1; 126 l = strlen(list) + 1; 127 list += l; 128 len -= l; 129 } 130 return 0; 131 } 132 EXPORT_SYMBOL(of_find_in_proplist); 133 134 unsigned int prom_unique_id; 135 136 static struct property * __init build_one_prop(phandle node, char *prev, 137 char *special_name, 138 void *special_val, 139 int special_len) 140 { 141 static struct property *tmp = NULL; 142 struct property *p; 143 const char *name; 144 145 if (tmp) { 146 p = tmp; 147 memset(p, 0, sizeof(*p) + 32); 148 tmp = NULL; 149 } else { 150 p = prom_early_alloc(sizeof(struct property) + 32); 151 p->unique_id = prom_unique_id++; 152 } 153 154 p->name = (char *) (p + 1); 155 if (special_name) { 156 strcpy(p->name, special_name); 157 p->length = special_len; 158 p->value = prom_early_alloc(special_len); 159 memcpy(p->value, special_val, special_len); 160 } else { 161 if (prev == NULL) { 162 name = prom_firstprop(node, p->name); 163 } else { 164 name = prom_nextprop(node, prev, p->name); 165 } 166 167 if (!name || strlen(name) == 0) { 168 tmp = p; 169 return NULL; 170 } 171 #ifdef CONFIG_SPARC32 172 strcpy(p->name, name); 173 #endif 174 p->length = prom_getproplen(node, p->name); 175 if (p->length <= 0) { 176 p->length = 0; 177 } else { 178 int len; 179 180 p->value = prom_early_alloc(p->length + 1); 181 len = prom_getproperty(node, p->name, p->value, 182 p->length); 183 if (len <= 0) 184 p->length = 0; 185 ((unsigned char *)p->value)[p->length] = '\0'; 186 } 187 } 188 return p; 189 } 190 191 static struct property * __init build_prop_list(phandle node) 192 { 193 struct property *head, *tail; 194 195 head = tail = build_one_prop(node, NULL, 196 ".node", &node, sizeof(node)); 197 198 tail->next = build_one_prop(node, NULL, NULL, NULL, 0); 199 tail = tail->next; 200 while(tail) { 201 tail->next = build_one_prop(node, tail->name, 202 NULL, NULL, 0); 203 tail = tail->next; 204 } 205 206 return head; 207 } 208 209 static char * __init get_one_property(phandle node, const char *name) 210 { 211 char *buf = "<NULL>"; 212 int len; 213 214 len = prom_getproplen(node, name); 215 if (len > 0) { 216 buf = prom_early_alloc(len); 217 len = prom_getproperty(node, name, buf, len); 218 } 219 220 return buf; 221 } 222 223 static struct device_node * __init prom_create_node(phandle node, 224 struct device_node *parent) 225 { 226 struct device_node *dp; 227 228 if (!node) 229 return NULL; 230 231 dp = prom_early_alloc(sizeof(*dp)); 232 dp->unique_id = prom_unique_id++; 233 dp->parent = parent; 234 235 kref_init(&dp->kref); 236 237 dp->name = get_one_property(node, "name"); 238 dp->type = get_one_property(node, "device_type"); 239 dp->node = node; 240 241 dp->properties = build_prop_list(node); 242 243 irq_trans_init(dp); 244 245 return dp; 246 } 247 248 char * __init build_full_name(struct device_node *dp) 249 { 250 int len, ourlen, plen; 251 char *n; 252 253 plen = strlen(dp->parent->full_name); 254 ourlen = strlen(dp->path_component_name); 255 len = ourlen + plen + 2; 256 257 n = prom_early_alloc(len); 258 strcpy(n, dp->parent->full_name); 259 if (!is_root_node(dp->parent)) { 260 strcpy(n + plen, "/"); 261 plen++; 262 } 263 strcpy(n + plen, dp->path_component_name); 264 265 return n; 266 } 267 268 static struct device_node * __init prom_build_tree(struct device_node *parent, 269 phandle node, 270 struct device_node ***nextp) 271 { 272 struct device_node *ret = NULL, *prev_sibling = NULL; 273 struct device_node *dp; 274 275 while (1) { 276 dp = prom_create_node(node, parent); 277 if (!dp) 278 break; 279 280 if (prev_sibling) 281 prev_sibling->sibling = dp; 282 283 if (!ret) 284 ret = dp; 285 prev_sibling = dp; 286 287 *(*nextp) = dp; 288 *nextp = &dp->allnext; 289 290 dp->path_component_name = build_path_component(dp); 291 dp->full_name = build_full_name(dp); 292 293 dp->child = prom_build_tree(dp, prom_getchild(node), nextp); 294 295 if (prom_build_more) 296 prom_build_more(dp, nextp); 297 298 node = prom_getsibling(node); 299 } 300 301 return ret; 302 } 303 304 unsigned int prom_early_allocated __initdata; 305 306 void __init prom_build_devicetree(void) 307 { 308 struct device_node **nextp; 309 310 allnodes = prom_create_node(prom_root_node, NULL); 311 allnodes->path_component_name = ""; 312 allnodes->full_name = "/"; 313 314 nextp = &allnodes->allnext; 315 allnodes->child = prom_build_tree(allnodes, 316 prom_getchild(allnodes->node), 317 &nextp); 318 of_console_init(); 319 320 printk("PROM: Built device tree with %u bytes of memory.\n", 321 prom_early_allocated); 322 } 323