1 // SPDX-License-Identifier: GPL-2.0+ 2 /* pdt.c: OF PROM device tree support code. 3 * 4 * Paul Mackerras August 1996. 5 * Copyright (C) 1996-2005 Paul Mackerras. 6 * 7 * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. 8 * {engebret|bergner}@us.ibm.com 9 * 10 * Adapted for sparc by David S. Miller davem@davemloft.net 11 * Adapted for multiple architectures by Andres Salomon <dilinger@queued.net> 12 */ 13 14 #include <linux/kernel.h> 15 #include <linux/module.h> 16 #include <linux/errno.h> 17 #include <linux/mutex.h> 18 #include <linux/slab.h> 19 #include <linux/of.h> 20 #include <linux/of_pdt.h> 21 22 static struct of_pdt_ops *of_pdt_prom_ops __initdata; 23 24 void __initdata (*of_pdt_build_more)(struct device_node *dp); 25 26 #if defined(CONFIG_SPARC) 27 unsigned int of_pdt_unique_id __initdata; 28 29 #define of_pdt_incr_unique_id(p) do { \ 30 (p)->unique_id = of_pdt_unique_id++; \ 31 } while (0) 32 33 static char * __init of_pdt_build_full_name(struct device_node *dp) 34 { 35 int len, ourlen, plen; 36 char *n; 37 38 dp->path_component_name = build_path_component(dp); 39 40 plen = strlen(dp->parent->full_name); 41 ourlen = strlen(dp->path_component_name); 42 len = ourlen + plen + 2; 43 44 n = prom_early_alloc(len); 45 strcpy(n, dp->parent->full_name); 46 if (!of_node_is_root(dp->parent)) { 47 strcpy(n + plen, "/"); 48 plen++; 49 } 50 strcpy(n + plen, dp->path_component_name); 51 52 return n; 53 } 54 55 #else /* CONFIG_SPARC */ 56 57 static inline void of_pdt_incr_unique_id(void *p) { } 58 static inline void irq_trans_init(struct device_node *dp) { } 59 60 static char * __init of_pdt_build_full_name(struct device_node *dp) 61 { 62 static int failsafe_id = 0; /* for generating unique names on failure */ 63 char *buf; 64 int len; 65 66 if (of_pdt_prom_ops->pkg2path(dp->phandle, NULL, 0, &len)) 67 goto failsafe; 68 69 buf = prom_early_alloc(len + 1); 70 if (of_pdt_prom_ops->pkg2path(dp->phandle, buf, len, &len)) 71 goto failsafe; 72 return buf; 73 74 failsafe: 75 buf = prom_early_alloc(strlen(dp->parent->full_name) + 76 strlen(dp->name) + 16); 77 sprintf(buf, "%s/%s@unknown%i", 78 of_node_is_root(dp->parent) ? "" : dp->parent->full_name, 79 dp->name, failsafe_id++); 80 pr_err("%s: pkg2path failed; assigning %s\n", __func__, buf); 81 return buf; 82 } 83 84 #endif /* !CONFIG_SPARC */ 85 86 static struct property * __init of_pdt_build_one_prop(phandle node, char *prev, 87 char *special_name, 88 void *special_val, 89 int special_len) 90 { 91 static struct property *tmp = NULL; 92 struct property *p; 93 int err; 94 95 if (tmp) { 96 p = tmp; 97 memset(p, 0, sizeof(*p) + 32); 98 tmp = NULL; 99 } else { 100 p = prom_early_alloc(sizeof(struct property) + 32); 101 of_pdt_incr_unique_id(p); 102 } 103 104 p->name = (char *) (p + 1); 105 if (special_name) { 106 strcpy(p->name, special_name); 107 p->length = special_len; 108 p->value = prom_early_alloc(special_len); 109 memcpy(p->value, special_val, special_len); 110 } else { 111 err = of_pdt_prom_ops->nextprop(node, prev, p->name); 112 if (err) { 113 tmp = p; 114 return NULL; 115 } 116 p->length = of_pdt_prom_ops->getproplen(node, p->name); 117 if (p->length <= 0) { 118 p->length = 0; 119 } else { 120 int len; 121 122 p->value = prom_early_alloc(p->length + 1); 123 len = of_pdt_prom_ops->getproperty(node, p->name, 124 p->value, p->length); 125 if (len <= 0) 126 p->length = 0; 127 ((unsigned char *)p->value)[p->length] = '\0'; 128 } 129 } 130 return p; 131 } 132 133 static struct property * __init of_pdt_build_prop_list(phandle node) 134 { 135 struct property *head, *tail; 136 137 head = tail = of_pdt_build_one_prop(node, NULL, 138 ".node", &node, sizeof(node)); 139 140 tail->next = of_pdt_build_one_prop(node, NULL, NULL, NULL, 0); 141 tail = tail->next; 142 while(tail) { 143 tail->next = of_pdt_build_one_prop(node, tail->name, 144 NULL, NULL, 0); 145 tail = tail->next; 146 } 147 148 return head; 149 } 150 151 static char * __init of_pdt_get_one_property(phandle node, const char *name) 152 { 153 char *buf = "<NULL>"; 154 int len; 155 156 len = of_pdt_prom_ops->getproplen(node, name); 157 if (len > 0) { 158 buf = prom_early_alloc(len); 159 len = of_pdt_prom_ops->getproperty(node, name, buf, len); 160 } 161 162 return buf; 163 } 164 165 static struct device_node * __init of_pdt_create_node(phandle node, 166 struct device_node *parent) 167 { 168 struct device_node *dp; 169 170 if (!node) 171 return NULL; 172 173 dp = prom_early_alloc(sizeof(*dp)); 174 of_node_init(dp); 175 of_pdt_incr_unique_id(dp); 176 dp->parent = parent; 177 178 dp->name = of_pdt_get_one_property(node, "name"); 179 dp->type = of_pdt_get_one_property(node, "device_type"); 180 dp->phandle = node; 181 182 dp->properties = of_pdt_build_prop_list(node); 183 184 irq_trans_init(dp); 185 186 return dp; 187 } 188 189 static struct device_node * __init of_pdt_build_tree(struct device_node *parent, 190 phandle node) 191 { 192 struct device_node *ret = NULL, *prev_sibling = NULL; 193 struct device_node *dp; 194 195 while (1) { 196 dp = of_pdt_create_node(node, parent); 197 if (!dp) 198 break; 199 200 if (prev_sibling) 201 prev_sibling->sibling = dp; 202 203 if (!ret) 204 ret = dp; 205 prev_sibling = dp; 206 207 dp->full_name = of_pdt_build_full_name(dp); 208 209 dp->child = of_pdt_build_tree(dp, of_pdt_prom_ops->getchild(node)); 210 211 if (of_pdt_build_more) 212 of_pdt_build_more(dp); 213 214 node = of_pdt_prom_ops->getsibling(node); 215 } 216 217 return ret; 218 } 219 220 static void * __init kernel_tree_alloc(u64 size, u64 align) 221 { 222 return prom_early_alloc(size); 223 } 224 225 void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops) 226 { 227 BUG_ON(!ops); 228 of_pdt_prom_ops = ops; 229 230 of_root = of_pdt_create_node(root_node, NULL); 231 #if defined(CONFIG_SPARC) 232 of_root->path_component_name = ""; 233 #endif 234 of_root->full_name = "/"; 235 236 of_root->child = of_pdt_build_tree(of_root, 237 of_pdt_prom_ops->getchild(of_root->phandle)); 238 239 /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */ 240 of_alias_scan(kernel_tree_alloc); 241 } 242