1 /* 2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 3 * 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of the 8 * License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 18 * USA 19 */ 20 21 #include "dtc.h" 22 23 /* 24 * Tree building functions 25 */ 26 27 struct property *build_property(char *name, struct data val, char *label) 28 { 29 struct property *new = xmalloc(sizeof(*new)); 30 31 new->name = name; 32 new->val = val; 33 34 new->next = NULL; 35 36 new->label = label; 37 38 return new; 39 } 40 41 struct property *chain_property(struct property *first, struct property *list) 42 { 43 assert(first->next == NULL); 44 45 first->next = list; 46 return first; 47 } 48 49 struct property *reverse_properties(struct property *first) 50 { 51 struct property *p = first; 52 struct property *head = NULL; 53 struct property *next; 54 55 while (p) { 56 next = p->next; 57 p->next = head; 58 head = p; 59 p = next; 60 } 61 return head; 62 } 63 64 struct node *build_node(struct property *proplist, struct node *children) 65 { 66 struct node *new = xmalloc(sizeof(*new)); 67 struct node *child; 68 69 memset(new, 0, sizeof(*new)); 70 71 new->proplist = reverse_properties(proplist); 72 new->children = children; 73 74 for_each_child(new, child) { 75 child->parent = new; 76 } 77 78 return new; 79 } 80 81 struct node *name_node(struct node *node, char *name, char * label) 82 { 83 assert(node->name == NULL); 84 85 node->name = name; 86 87 node->label = label; 88 89 return node; 90 } 91 92 struct node *chain_node(struct node *first, struct node *list) 93 { 94 assert(first->next_sibling == NULL); 95 96 first->next_sibling = list; 97 return first; 98 } 99 100 void add_property(struct node *node, struct property *prop) 101 { 102 struct property **p; 103 104 prop->next = NULL; 105 106 p = &node->proplist; 107 while (*p) 108 p = &((*p)->next); 109 110 *p = prop; 111 } 112 113 void add_child(struct node *parent, struct node *child) 114 { 115 struct node **p; 116 117 child->next_sibling = NULL; 118 child->parent = parent; 119 120 p = &parent->children; 121 while (*p) 122 p = &((*p)->next_sibling); 123 124 *p = child; 125 } 126 127 struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size, 128 char *label) 129 { 130 struct reserve_info *new = xmalloc(sizeof(*new)); 131 132 new->re.address = address; 133 new->re.size = size; 134 135 new->next = NULL; 136 137 new->label = label; 138 139 return new; 140 } 141 142 struct reserve_info *chain_reserve_entry(struct reserve_info *first, 143 struct reserve_info *list) 144 { 145 assert(first->next == NULL); 146 147 first->next = list; 148 return first; 149 } 150 151 struct reserve_info *add_reserve_entry(struct reserve_info *list, 152 struct reserve_info *new) 153 { 154 struct reserve_info *last; 155 156 new->next = NULL; 157 158 if (! list) 159 return new; 160 161 for (last = list; last->next; last = last->next) 162 ; 163 164 last->next = new; 165 166 return list; 167 } 168 169 struct boot_info *build_boot_info(struct reserve_info *reservelist, 170 struct node *tree, uint32_t boot_cpuid_phys) 171 { 172 struct boot_info *bi; 173 174 bi = xmalloc(sizeof(*bi)); 175 bi->reservelist = reservelist; 176 bi->dt = tree; 177 bi->boot_cpuid_phys = boot_cpuid_phys; 178 179 return bi; 180 } 181 182 /* 183 * Tree accessor functions 184 */ 185 186 const char *get_unitname(struct node *node) 187 { 188 if (node->name[node->basenamelen] == '\0') 189 return ""; 190 else 191 return node->name + node->basenamelen + 1; 192 } 193 194 struct property *get_property(struct node *node, const char *propname) 195 { 196 struct property *prop; 197 198 for_each_property(node, prop) 199 if (streq(prop->name, propname)) 200 return prop; 201 202 return NULL; 203 } 204 205 cell_t propval_cell(struct property *prop) 206 { 207 assert(prop->val.len == sizeof(cell_t)); 208 return fdt32_to_cpu(*((cell_t *)prop->val.val)); 209 } 210 211 struct node *get_subnode(struct node *node, const char *nodename) 212 { 213 struct node *child; 214 215 for_each_child(node, child) 216 if (streq(child->name, nodename)) 217 return child; 218 219 return NULL; 220 } 221 222 struct node *get_node_by_path(struct node *tree, const char *path) 223 { 224 const char *p; 225 struct node *child; 226 227 if (!path || ! (*path)) 228 return tree; 229 230 while (path[0] == '/') 231 path++; 232 233 p = strchr(path, '/'); 234 235 for_each_child(tree, child) { 236 if (p && strneq(path, child->name, p-path)) 237 return get_node_by_path(child, p+1); 238 else if (!p && streq(path, child->name)) 239 return child; 240 } 241 242 return NULL; 243 } 244 245 struct node *get_node_by_label(struct node *tree, const char *label) 246 { 247 struct node *child, *node; 248 249 assert(label && (strlen(label) > 0)); 250 251 if (tree->label && streq(tree->label, label)) 252 return tree; 253 254 for_each_child(tree, child) { 255 node = get_node_by_label(child, label); 256 if (node) 257 return node; 258 } 259 260 return NULL; 261 } 262 263 struct node *get_node_by_phandle(struct node *tree, cell_t phandle) 264 { 265 struct node *child, *node; 266 267 assert((phandle != 0) && (phandle != -1)); 268 269 if (tree->phandle == phandle) 270 return tree; 271 272 for_each_child(tree, child) { 273 node = get_node_by_phandle(child, phandle); 274 if (node) 275 return node; 276 } 277 278 return NULL; 279 } 280 281 struct node *get_node_by_ref(struct node *tree, const char *ref) 282 { 283 if (ref[0] == '/') 284 return get_node_by_path(tree, ref); 285 else 286 return get_node_by_label(tree, ref); 287 } 288 289 cell_t get_node_phandle(struct node *root, struct node *node) 290 { 291 static cell_t phandle = 1; /* FIXME: ick, static local */ 292 293 if ((node->phandle != 0) && (node->phandle != -1)) 294 return node->phandle; 295 296 assert(! get_property(node, "linux,phandle")); 297 298 while (get_node_by_phandle(root, phandle)) 299 phandle++; 300 301 node->phandle = phandle; 302 add_property(node, 303 build_property("linux,phandle", 304 data_append_cell(empty_data, phandle), 305 NULL)); 306 307 return node->phandle; 308 } 309