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