1d18719a4STom Rini /* 2d18719a4STom Rini * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 3d18719a4STom Rini * 4d18719a4STom Rini * 5d18719a4STom Rini * This program is free software; you can redistribute it and/or 6d18719a4STom Rini * modify it under the terms of the GNU General Public License as 7d18719a4STom Rini * published by the Free Software Foundation; either version 2 of the 8d18719a4STom Rini * License, or (at your option) any later version. 9d18719a4STom Rini * 10d18719a4STom Rini * This program is distributed in the hope that it will be useful, 11d18719a4STom Rini * but WITHOUT ANY WARRANTY; without even the implied warranty of 12d18719a4STom Rini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13d18719a4STom Rini * General Public License for more details. 14d18719a4STom Rini * 15d18719a4STom Rini * You should have received a copy of the GNU General Public License 16d18719a4STom Rini * along with this program; if not, write to the Free Software 17d18719a4STom Rini * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 18d18719a4STom Rini * USA 19d18719a4STom Rini */ 20d18719a4STom Rini 21d18719a4STom Rini #include "dtc.h" 22d18719a4STom Rini 23d18719a4STom Rini /* 24d18719a4STom Rini * Tree building functions 25d18719a4STom Rini */ 26d18719a4STom Rini 27d18719a4STom Rini void add_label(struct label **labels, char *label) 28d18719a4STom Rini { 29d18719a4STom Rini struct label *new; 30d18719a4STom Rini 31d18719a4STom Rini /* Make sure the label isn't already there */ 32d18719a4STom Rini for_each_label_withdel(*labels, new) 33d18719a4STom Rini if (streq(new->label, label)) { 34d18719a4STom Rini new->deleted = 0; 35d18719a4STom Rini return; 36d18719a4STom Rini } 37d18719a4STom Rini 38d18719a4STom Rini new = xmalloc(sizeof(*new)); 39d18719a4STom Rini memset(new, 0, sizeof(*new)); 40d18719a4STom Rini new->label = label; 41d18719a4STom Rini new->next = *labels; 42d18719a4STom Rini *labels = new; 43d18719a4STom Rini } 44d18719a4STom Rini 45d18719a4STom Rini void delete_labels(struct label **labels) 46d18719a4STom Rini { 47d18719a4STom Rini struct label *label; 48d18719a4STom Rini 49d18719a4STom Rini for_each_label(*labels, label) 50d18719a4STom Rini label->deleted = 1; 51d18719a4STom Rini } 52d18719a4STom Rini 53d18719a4STom Rini struct property *build_property(char *name, struct data val) 54d18719a4STom Rini { 55d18719a4STom Rini struct property *new = xmalloc(sizeof(*new)); 56d18719a4STom Rini 57d18719a4STom Rini memset(new, 0, sizeof(*new)); 58d18719a4STom Rini 59d18719a4STom Rini new->name = name; 60d18719a4STom Rini new->val = val; 61d18719a4STom Rini 62d18719a4STom Rini return new; 63d18719a4STom Rini } 64d18719a4STom Rini 65d18719a4STom Rini struct property *build_property_delete(char *name) 66d18719a4STom Rini { 67d18719a4STom Rini struct property *new = xmalloc(sizeof(*new)); 68d18719a4STom Rini 69d18719a4STom Rini memset(new, 0, sizeof(*new)); 70d18719a4STom Rini 71d18719a4STom Rini new->name = name; 72d18719a4STom Rini new->deleted = 1; 73d18719a4STom Rini 74d18719a4STom Rini return new; 75d18719a4STom Rini } 76d18719a4STom Rini 77d18719a4STom Rini struct property *chain_property(struct property *first, struct property *list) 78d18719a4STom Rini { 79d18719a4STom Rini assert(first->next == NULL); 80d18719a4STom Rini 81d18719a4STom Rini first->next = list; 82d18719a4STom Rini return first; 83d18719a4STom Rini } 84d18719a4STom Rini 85d18719a4STom Rini struct property *reverse_properties(struct property *first) 86d18719a4STom Rini { 87d18719a4STom Rini struct property *p = first; 88d18719a4STom Rini struct property *head = NULL; 89d18719a4STom Rini struct property *next; 90d18719a4STom Rini 91d18719a4STom Rini while (p) { 92d18719a4STom Rini next = p->next; 93d18719a4STom Rini p->next = head; 94d18719a4STom Rini head = p; 95d18719a4STom Rini p = next; 96d18719a4STom Rini } 97d18719a4STom Rini return head; 98d18719a4STom Rini } 99d18719a4STom Rini 100d18719a4STom Rini struct node *build_node(struct property *proplist, struct node *children) 101d18719a4STom Rini { 102d18719a4STom Rini struct node *new = xmalloc(sizeof(*new)); 103d18719a4STom Rini struct node *child; 104d18719a4STom Rini 105d18719a4STom Rini memset(new, 0, sizeof(*new)); 106d18719a4STom Rini 107d18719a4STom Rini new->proplist = reverse_properties(proplist); 108d18719a4STom Rini new->children = children; 109d18719a4STom Rini 110d18719a4STom Rini for_each_child(new, child) { 111d18719a4STom Rini child->parent = new; 112d18719a4STom Rini } 113d18719a4STom Rini 114d18719a4STom Rini return new; 115d18719a4STom Rini } 116d18719a4STom Rini 117d18719a4STom Rini struct node *build_node_delete(void) 118d18719a4STom Rini { 119d18719a4STom Rini struct node *new = xmalloc(sizeof(*new)); 120d18719a4STom Rini 121d18719a4STom Rini memset(new, 0, sizeof(*new)); 122d18719a4STom Rini 123d18719a4STom Rini new->deleted = 1; 124d18719a4STom Rini 125d18719a4STom Rini return new; 126d18719a4STom Rini } 127d18719a4STom Rini 128d18719a4STom Rini struct node *name_node(struct node *node, char *name) 129d18719a4STom Rini { 130d18719a4STom Rini assert(node->name == NULL); 131d18719a4STom Rini 132d18719a4STom Rini node->name = name; 133d18719a4STom Rini 134d18719a4STom Rini return node; 135d18719a4STom Rini } 136d18719a4STom Rini 137d18719a4STom Rini struct node *merge_nodes(struct node *old_node, struct node *new_node) 138d18719a4STom Rini { 139d18719a4STom Rini struct property *new_prop, *old_prop; 140d18719a4STom Rini struct node *new_child, *old_child; 141d18719a4STom Rini struct label *l; 142d18719a4STom Rini 143d18719a4STom Rini old_node->deleted = 0; 144d18719a4STom Rini 145d18719a4STom Rini /* Add new node labels to old node */ 146d18719a4STom Rini for_each_label_withdel(new_node->labels, l) 147d18719a4STom Rini add_label(&old_node->labels, l->label); 148d18719a4STom Rini 149d18719a4STom Rini /* Move properties from the new node to the old node. If there 150d18719a4STom Rini * is a collision, replace the old value with the new */ 151d18719a4STom Rini while (new_node->proplist) { 152d18719a4STom Rini /* Pop the property off the list */ 153d18719a4STom Rini new_prop = new_node->proplist; 154d18719a4STom Rini new_node->proplist = new_prop->next; 155d18719a4STom Rini new_prop->next = NULL; 156d18719a4STom Rini 157d18719a4STom Rini if (new_prop->deleted) { 158d18719a4STom Rini delete_property_by_name(old_node, new_prop->name); 159d18719a4STom Rini free(new_prop); 160d18719a4STom Rini continue; 161d18719a4STom Rini } 162d18719a4STom Rini 163d18719a4STom Rini /* Look for a collision, set new value if there is */ 164d18719a4STom Rini for_each_property_withdel(old_node, old_prop) { 165d18719a4STom Rini if (streq(old_prop->name, new_prop->name)) { 166d18719a4STom Rini /* Add new labels to old property */ 167d18719a4STom Rini for_each_label_withdel(new_prop->labels, l) 168d18719a4STom Rini add_label(&old_prop->labels, l->label); 169d18719a4STom Rini 170d18719a4STom Rini old_prop->val = new_prop->val; 171d18719a4STom Rini old_prop->deleted = 0; 172d18719a4STom Rini free(new_prop); 173d18719a4STom Rini new_prop = NULL; 174d18719a4STom Rini break; 175d18719a4STom Rini } 176d18719a4STom Rini } 177d18719a4STom Rini 178d18719a4STom Rini /* if no collision occurred, add property to the old node. */ 179d18719a4STom Rini if (new_prop) 180d18719a4STom Rini add_property(old_node, new_prop); 181d18719a4STom Rini } 182d18719a4STom Rini 183d18719a4STom Rini /* Move the override child nodes into the primary node. If 184d18719a4STom Rini * there is a collision, then merge the nodes. */ 185d18719a4STom Rini while (new_node->children) { 186d18719a4STom Rini /* Pop the child node off the list */ 187d18719a4STom Rini new_child = new_node->children; 188d18719a4STom Rini new_node->children = new_child->next_sibling; 189d18719a4STom Rini new_child->parent = NULL; 190d18719a4STom Rini new_child->next_sibling = NULL; 191d18719a4STom Rini 192d18719a4STom Rini if (new_child->deleted) { 193d18719a4STom Rini delete_node_by_name(old_node, new_child->name); 194d18719a4STom Rini free(new_child); 195d18719a4STom Rini continue; 196d18719a4STom Rini } 197d18719a4STom Rini 198d18719a4STom Rini /* Search for a collision. Merge if there is */ 199d18719a4STom Rini for_each_child_withdel(old_node, old_child) { 200d18719a4STom Rini if (streq(old_child->name, new_child->name)) { 201d18719a4STom Rini merge_nodes(old_child, new_child); 202d18719a4STom Rini new_child = NULL; 203d18719a4STom Rini break; 204d18719a4STom Rini } 205d18719a4STom Rini } 206d18719a4STom Rini 207d18719a4STom Rini /* if no collision occurred, add child to the old node. */ 208d18719a4STom Rini if (new_child) 209d18719a4STom Rini add_child(old_node, new_child); 210d18719a4STom Rini } 211d18719a4STom Rini 212d18719a4STom Rini /* The new node contents are now merged into the old node. Free 213d18719a4STom Rini * the new node. */ 214d18719a4STom Rini free(new_node); 215d18719a4STom Rini 216d18719a4STom Rini return old_node; 217d18719a4STom Rini } 218d18719a4STom Rini 219d18719a4STom Rini struct node *chain_node(struct node *first, struct node *list) 220d18719a4STom Rini { 221d18719a4STom Rini assert(first->next_sibling == NULL); 222d18719a4STom Rini 223d18719a4STom Rini first->next_sibling = list; 224d18719a4STom Rini return first; 225d18719a4STom Rini } 226d18719a4STom Rini 227d18719a4STom Rini void add_property(struct node *node, struct property *prop) 228d18719a4STom Rini { 229d18719a4STom Rini struct property **p; 230d18719a4STom Rini 231d18719a4STom Rini prop->next = NULL; 232d18719a4STom Rini 233d18719a4STom Rini p = &node->proplist; 234d18719a4STom Rini while (*p) 235d18719a4STom Rini p = &((*p)->next); 236d18719a4STom Rini 237d18719a4STom Rini *p = prop; 238d18719a4STom Rini } 239d18719a4STom Rini 240d18719a4STom Rini void delete_property_by_name(struct node *node, char *name) 241d18719a4STom Rini { 242d18719a4STom Rini struct property *prop = node->proplist; 243d18719a4STom Rini 244d18719a4STom Rini while (prop) { 245d18719a4STom Rini if (streq(prop->name, name)) { 246d18719a4STom Rini delete_property(prop); 247d18719a4STom Rini return; 248d18719a4STom Rini } 249d18719a4STom Rini prop = prop->next; 250d18719a4STom Rini } 251d18719a4STom Rini } 252d18719a4STom Rini 253d18719a4STom Rini void delete_property(struct property *prop) 254d18719a4STom Rini { 255d18719a4STom Rini prop->deleted = 1; 256d18719a4STom Rini delete_labels(&prop->labels); 257d18719a4STom Rini } 258d18719a4STom Rini 259d18719a4STom Rini void add_child(struct node *parent, struct node *child) 260d18719a4STom Rini { 261d18719a4STom Rini struct node **p; 262d18719a4STom Rini 263d18719a4STom Rini child->next_sibling = NULL; 264d18719a4STom Rini child->parent = parent; 265d18719a4STom Rini 266d18719a4STom Rini p = &parent->children; 267d18719a4STom Rini while (*p) 268d18719a4STom Rini p = &((*p)->next_sibling); 269d18719a4STom Rini 270d18719a4STom Rini *p = child; 271d18719a4STom Rini } 272d18719a4STom Rini 273d18719a4STom Rini void delete_node_by_name(struct node *parent, char *name) 274d18719a4STom Rini { 275d18719a4STom Rini struct node *node = parent->children; 276d18719a4STom Rini 277d18719a4STom Rini while (node) { 278d18719a4STom Rini if (streq(node->name, name)) { 279d18719a4STom Rini delete_node(node); 280d18719a4STom Rini return; 281d18719a4STom Rini } 282d18719a4STom Rini node = node->next_sibling; 283d18719a4STom Rini } 284d18719a4STom Rini } 285d18719a4STom Rini 286d18719a4STom Rini void delete_node(struct node *node) 287d18719a4STom Rini { 288d18719a4STom Rini struct property *prop; 289d18719a4STom Rini struct node *child; 290d18719a4STom Rini 291d18719a4STom Rini node->deleted = 1; 292d18719a4STom Rini for_each_child(node, child) 293d18719a4STom Rini delete_node(child); 294d18719a4STom Rini for_each_property(node, prop) 295d18719a4STom Rini delete_property(prop); 296d18719a4STom Rini delete_labels(&node->labels); 297d18719a4STom Rini } 298d18719a4STom Rini 299d18719a4STom Rini void append_to_property(struct node *node, 300d18719a4STom Rini char *name, const void *data, int len) 301d18719a4STom Rini { 302d18719a4STom Rini struct data d; 303d18719a4STom Rini struct property *p; 304d18719a4STom Rini 305d18719a4STom Rini p = get_property(node, name); 306d18719a4STom Rini if (p) { 307d18719a4STom Rini d = data_append_data(p->val, data, len); 308d18719a4STom Rini p->val = d; 309d18719a4STom Rini } else { 310d18719a4STom Rini d = data_append_data(empty_data, data, len); 311d18719a4STom Rini p = build_property(name, d); 312d18719a4STom Rini add_property(node, p); 313d18719a4STom Rini } 314d18719a4STom Rini } 315d18719a4STom Rini 316d18719a4STom Rini struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) 317d18719a4STom Rini { 318d18719a4STom Rini struct reserve_info *new = xmalloc(sizeof(*new)); 319d18719a4STom Rini 320d18719a4STom Rini memset(new, 0, sizeof(*new)); 321d18719a4STom Rini 322e23ffda2STom Rini new->address = address; 323e23ffda2STom Rini new->size = size; 324d18719a4STom Rini 325d18719a4STom Rini return new; 326d18719a4STom Rini } 327d18719a4STom Rini 328d18719a4STom Rini struct reserve_info *chain_reserve_entry(struct reserve_info *first, 329d18719a4STom Rini struct reserve_info *list) 330d18719a4STom Rini { 331d18719a4STom Rini assert(first->next == NULL); 332d18719a4STom Rini 333d18719a4STom Rini first->next = list; 334d18719a4STom Rini return first; 335d18719a4STom Rini } 336d18719a4STom Rini 337d18719a4STom Rini struct reserve_info *add_reserve_entry(struct reserve_info *list, 338d18719a4STom Rini struct reserve_info *new) 339d18719a4STom Rini { 340d18719a4STom Rini struct reserve_info *last; 341d18719a4STom Rini 342d18719a4STom Rini new->next = NULL; 343d18719a4STom Rini 344d18719a4STom Rini if (! list) 345d18719a4STom Rini return new; 346d18719a4STom Rini 347d18719a4STom Rini for (last = list; last->next; last = last->next) 348d18719a4STom Rini ; 349d18719a4STom Rini 350d18719a4STom Rini last->next = new; 351d18719a4STom Rini 352d18719a4STom Rini return list; 353d18719a4STom Rini } 354d18719a4STom Rini 355d18719a4STom Rini struct dt_info *build_dt_info(unsigned int dtsflags, 356d18719a4STom Rini struct reserve_info *reservelist, 357d18719a4STom Rini struct node *tree, uint32_t boot_cpuid_phys) 358d18719a4STom Rini { 359d18719a4STom Rini struct dt_info *dti; 360d18719a4STom Rini 361d18719a4STom Rini dti = xmalloc(sizeof(*dti)); 362d18719a4STom Rini dti->dtsflags = dtsflags; 363d18719a4STom Rini dti->reservelist = reservelist; 364d18719a4STom Rini dti->dt = tree; 365d18719a4STom Rini dti->boot_cpuid_phys = boot_cpuid_phys; 366d18719a4STom Rini 367d18719a4STom Rini return dti; 368d18719a4STom Rini } 369d18719a4STom Rini 370d18719a4STom Rini /* 371d18719a4STom Rini * Tree accessor functions 372d18719a4STom Rini */ 373d18719a4STom Rini 374d18719a4STom Rini const char *get_unitname(struct node *node) 375d18719a4STom Rini { 376d18719a4STom Rini if (node->name[node->basenamelen] == '\0') 377d18719a4STom Rini return ""; 378d18719a4STom Rini else 379d18719a4STom Rini return node->name + node->basenamelen + 1; 380d18719a4STom Rini } 381d18719a4STom Rini 382d18719a4STom Rini struct property *get_property(struct node *node, const char *propname) 383d18719a4STom Rini { 384d18719a4STom Rini struct property *prop; 385d18719a4STom Rini 386d18719a4STom Rini for_each_property(node, prop) 387d18719a4STom Rini if (streq(prop->name, propname)) 388d18719a4STom Rini return prop; 389d18719a4STom Rini 390d18719a4STom Rini return NULL; 391d18719a4STom Rini } 392d18719a4STom Rini 393d18719a4STom Rini cell_t propval_cell(struct property *prop) 394d18719a4STom Rini { 395d18719a4STom Rini assert(prop->val.len == sizeof(cell_t)); 396e23ffda2STom Rini return fdt32_to_cpu(*((fdt32_t *)prop->val.val)); 397d18719a4STom Rini } 398d18719a4STom Rini 399d18719a4STom Rini struct property *get_property_by_label(struct node *tree, const char *label, 400d18719a4STom Rini struct node **node) 401d18719a4STom Rini { 402d18719a4STom Rini struct property *prop; 403d18719a4STom Rini struct node *c; 404d18719a4STom Rini 405d18719a4STom Rini *node = tree; 406d18719a4STom Rini 407d18719a4STom Rini for_each_property(tree, prop) { 408d18719a4STom Rini struct label *l; 409d18719a4STom Rini 410d18719a4STom Rini for_each_label(prop->labels, l) 411d18719a4STom Rini if (streq(l->label, label)) 412d18719a4STom Rini return prop; 413d18719a4STom Rini } 414d18719a4STom Rini 415d18719a4STom Rini for_each_child(tree, c) { 416d18719a4STom Rini prop = get_property_by_label(c, label, node); 417d18719a4STom Rini if (prop) 418d18719a4STom Rini return prop; 419d18719a4STom Rini } 420d18719a4STom Rini 421d18719a4STom Rini *node = NULL; 422d18719a4STom Rini return NULL; 423d18719a4STom Rini } 424d18719a4STom Rini 425d18719a4STom Rini struct marker *get_marker_label(struct node *tree, const char *label, 426d18719a4STom Rini struct node **node, struct property **prop) 427d18719a4STom Rini { 428d18719a4STom Rini struct marker *m; 429d18719a4STom Rini struct property *p; 430d18719a4STom Rini struct node *c; 431d18719a4STom Rini 432d18719a4STom Rini *node = tree; 433d18719a4STom Rini 434d18719a4STom Rini for_each_property(tree, p) { 435d18719a4STom Rini *prop = p; 436d18719a4STom Rini m = p->val.markers; 437d18719a4STom Rini for_each_marker_of_type(m, LABEL) 438d18719a4STom Rini if (streq(m->ref, label)) 439d18719a4STom Rini return m; 440d18719a4STom Rini } 441d18719a4STom Rini 442d18719a4STom Rini for_each_child(tree, c) { 443d18719a4STom Rini m = get_marker_label(c, label, node, prop); 444d18719a4STom Rini if (m) 445d18719a4STom Rini return m; 446d18719a4STom Rini } 447d18719a4STom Rini 448d18719a4STom Rini *prop = NULL; 449d18719a4STom Rini *node = NULL; 450d18719a4STom Rini return NULL; 451d18719a4STom Rini } 452d18719a4STom Rini 453d18719a4STom Rini struct node *get_subnode(struct node *node, const char *nodename) 454d18719a4STom Rini { 455d18719a4STom Rini struct node *child; 456d18719a4STom Rini 457d18719a4STom Rini for_each_child(node, child) 458d18719a4STom Rini if (streq(child->name, nodename)) 459d18719a4STom Rini return child; 460d18719a4STom Rini 461d18719a4STom Rini return NULL; 462d18719a4STom Rini } 463d18719a4STom Rini 464d18719a4STom Rini struct node *get_node_by_path(struct node *tree, const char *path) 465d18719a4STom Rini { 466d18719a4STom Rini const char *p; 467d18719a4STom Rini struct node *child; 468d18719a4STom Rini 469d18719a4STom Rini if (!path || ! (*path)) { 470d18719a4STom Rini if (tree->deleted) 471d18719a4STom Rini return NULL; 472d18719a4STom Rini return tree; 473d18719a4STom Rini } 474d18719a4STom Rini 475d18719a4STom Rini while (path[0] == '/') 476d18719a4STom Rini path++; 477d18719a4STom Rini 478d18719a4STom Rini p = strchr(path, '/'); 479d18719a4STom Rini 480d18719a4STom Rini for_each_child(tree, child) { 481*d7857e40STom Rini if (p && (strlen(child->name) == p-path) && 482*d7857e40STom Rini strneq(path, child->name, p-path)) 483d18719a4STom Rini return get_node_by_path(child, p+1); 484d18719a4STom Rini else if (!p && streq(path, child->name)) 485d18719a4STom Rini return child; 486d18719a4STom Rini } 487d18719a4STom Rini 488d18719a4STom Rini return NULL; 489d18719a4STom Rini } 490d18719a4STom Rini 491d18719a4STom Rini struct node *get_node_by_label(struct node *tree, const char *label) 492d18719a4STom Rini { 493d18719a4STom Rini struct node *child, *node; 494d18719a4STom Rini struct label *l; 495d18719a4STom Rini 496d18719a4STom Rini assert(label && (strlen(label) > 0)); 497d18719a4STom Rini 498d18719a4STom Rini for_each_label(tree->labels, l) 499d18719a4STom Rini if (streq(l->label, label)) 500d18719a4STom Rini return tree; 501d18719a4STom Rini 502d18719a4STom Rini for_each_child(tree, child) { 503d18719a4STom Rini node = get_node_by_label(child, label); 504d18719a4STom Rini if (node) 505d18719a4STom Rini return node; 506d18719a4STom Rini } 507d18719a4STom Rini 508d18719a4STom Rini return NULL; 509d18719a4STom Rini } 510d18719a4STom Rini 511d18719a4STom Rini struct node *get_node_by_phandle(struct node *tree, cell_t phandle) 512d18719a4STom Rini { 513d18719a4STom Rini struct node *child, *node; 514d18719a4STom Rini 515d18719a4STom Rini assert((phandle != 0) && (phandle != -1)); 516d18719a4STom Rini 517d18719a4STom Rini if (tree->phandle == phandle) { 518d18719a4STom Rini if (tree->deleted) 519d18719a4STom Rini return NULL; 520d18719a4STom Rini return tree; 521d18719a4STom Rini } 522d18719a4STom Rini 523d18719a4STom Rini for_each_child(tree, child) { 524d18719a4STom Rini node = get_node_by_phandle(child, phandle); 525d18719a4STom Rini if (node) 526d18719a4STom Rini return node; 527d18719a4STom Rini } 528d18719a4STom Rini 529d18719a4STom Rini return NULL; 530d18719a4STom Rini } 531d18719a4STom Rini 532d18719a4STom Rini struct node *get_node_by_ref(struct node *tree, const char *ref) 533d18719a4STom Rini { 534d18719a4STom Rini if (streq(ref, "/")) 535d18719a4STom Rini return tree; 536d18719a4STom Rini else if (ref[0] == '/') 537d18719a4STom Rini return get_node_by_path(tree, ref); 538d18719a4STom Rini else 539d18719a4STom Rini return get_node_by_label(tree, ref); 540d18719a4STom Rini } 541d18719a4STom Rini 542d18719a4STom Rini cell_t get_node_phandle(struct node *root, struct node *node) 543d18719a4STom Rini { 544d18719a4STom Rini static cell_t phandle = 1; /* FIXME: ick, static local */ 545d18719a4STom Rini 546d18719a4STom Rini if ((node->phandle != 0) && (node->phandle != -1)) 547d18719a4STom Rini return node->phandle; 548d18719a4STom Rini 549d18719a4STom Rini while (get_node_by_phandle(root, phandle)) 550d18719a4STom Rini phandle++; 551d18719a4STom Rini 552d18719a4STom Rini node->phandle = phandle; 553d18719a4STom Rini 554d18719a4STom Rini if (!get_property(node, "linux,phandle") 555d18719a4STom Rini && (phandle_format & PHANDLE_LEGACY)) 556d18719a4STom Rini add_property(node, 557d18719a4STom Rini build_property("linux,phandle", 558d18719a4STom Rini data_append_cell(empty_data, phandle))); 559d18719a4STom Rini 560d18719a4STom Rini if (!get_property(node, "phandle") 561d18719a4STom Rini && (phandle_format & PHANDLE_EPAPR)) 562d18719a4STom Rini add_property(node, 563d18719a4STom Rini build_property("phandle", 564d18719a4STom Rini data_append_cell(empty_data, phandle))); 565d18719a4STom Rini 566d18719a4STom Rini /* If the node *does* have a phandle property, we must 567d18719a4STom Rini * be dealing with a self-referencing phandle, which will be 568d18719a4STom Rini * fixed up momentarily in the caller */ 569d18719a4STom Rini 570d18719a4STom Rini return node->phandle; 571d18719a4STom Rini } 572d18719a4STom Rini 573d18719a4STom Rini uint32_t guess_boot_cpuid(struct node *tree) 574d18719a4STom Rini { 575d18719a4STom Rini struct node *cpus, *bootcpu; 576d18719a4STom Rini struct property *reg; 577d18719a4STom Rini 578d18719a4STom Rini cpus = get_node_by_path(tree, "/cpus"); 579d18719a4STom Rini if (!cpus) 580d18719a4STom Rini return 0; 581d18719a4STom Rini 582d18719a4STom Rini 583d18719a4STom Rini bootcpu = cpus->children; 584d18719a4STom Rini if (!bootcpu) 585d18719a4STom Rini return 0; 586d18719a4STom Rini 587d18719a4STom Rini reg = get_property(bootcpu, "reg"); 588d18719a4STom Rini if (!reg || (reg->val.len != sizeof(uint32_t))) 589d18719a4STom Rini return 0; 590d18719a4STom Rini 591d18719a4STom Rini /* FIXME: Sanity check node? */ 592d18719a4STom Rini 593d18719a4STom Rini return propval_cell(reg); 594d18719a4STom Rini } 595d18719a4STom Rini 596d18719a4STom Rini static int cmp_reserve_info(const void *ax, const void *bx) 597d18719a4STom Rini { 598d18719a4STom Rini const struct reserve_info *a, *b; 599d18719a4STom Rini 600d18719a4STom Rini a = *((const struct reserve_info * const *)ax); 601d18719a4STom Rini b = *((const struct reserve_info * const *)bx); 602d18719a4STom Rini 603e23ffda2STom Rini if (a->address < b->address) 604d18719a4STom Rini return -1; 605e23ffda2STom Rini else if (a->address > b->address) 606d18719a4STom Rini return 1; 607e23ffda2STom Rini else if (a->size < b->size) 608d18719a4STom Rini return -1; 609e23ffda2STom Rini else if (a->size > b->size) 610d18719a4STom Rini return 1; 611d18719a4STom Rini else 612d18719a4STom Rini return 0; 613d18719a4STom Rini } 614d18719a4STom Rini 615d18719a4STom Rini static void sort_reserve_entries(struct dt_info *dti) 616d18719a4STom Rini { 617d18719a4STom Rini struct reserve_info *ri, **tbl; 618d18719a4STom Rini int n = 0, i = 0; 619d18719a4STom Rini 620d18719a4STom Rini for (ri = dti->reservelist; 621d18719a4STom Rini ri; 622d18719a4STom Rini ri = ri->next) 623d18719a4STom Rini n++; 624d18719a4STom Rini 625d18719a4STom Rini if (n == 0) 626d18719a4STom Rini return; 627d18719a4STom Rini 628d18719a4STom Rini tbl = xmalloc(n * sizeof(*tbl)); 629d18719a4STom Rini 630d18719a4STom Rini for (ri = dti->reservelist; 631d18719a4STom Rini ri; 632d18719a4STom Rini ri = ri->next) 633d18719a4STom Rini tbl[i++] = ri; 634d18719a4STom Rini 635d18719a4STom Rini qsort(tbl, n, sizeof(*tbl), cmp_reserve_info); 636d18719a4STom Rini 637d18719a4STom Rini dti->reservelist = tbl[0]; 638d18719a4STom Rini for (i = 0; i < (n-1); i++) 639d18719a4STom Rini tbl[i]->next = tbl[i+1]; 640d18719a4STom Rini tbl[n-1]->next = NULL; 641d18719a4STom Rini 642d18719a4STom Rini free(tbl); 643d18719a4STom Rini } 644d18719a4STom Rini 645d18719a4STom Rini static int cmp_prop(const void *ax, const void *bx) 646d18719a4STom Rini { 647d18719a4STom Rini const struct property *a, *b; 648d18719a4STom Rini 649d18719a4STom Rini a = *((const struct property * const *)ax); 650d18719a4STom Rini b = *((const struct property * const *)bx); 651d18719a4STom Rini 652d18719a4STom Rini return strcmp(a->name, b->name); 653d18719a4STom Rini } 654d18719a4STom Rini 655d18719a4STom Rini static void sort_properties(struct node *node) 656d18719a4STom Rini { 657d18719a4STom Rini int n = 0, i = 0; 658d18719a4STom Rini struct property *prop, **tbl; 659d18719a4STom Rini 660d18719a4STom Rini for_each_property_withdel(node, prop) 661d18719a4STom Rini n++; 662d18719a4STom Rini 663d18719a4STom Rini if (n == 0) 664d18719a4STom Rini return; 665d18719a4STom Rini 666d18719a4STom Rini tbl = xmalloc(n * sizeof(*tbl)); 667d18719a4STom Rini 668d18719a4STom Rini for_each_property_withdel(node, prop) 669d18719a4STom Rini tbl[i++] = prop; 670d18719a4STom Rini 671d18719a4STom Rini qsort(tbl, n, sizeof(*tbl), cmp_prop); 672d18719a4STom Rini 673d18719a4STom Rini node->proplist = tbl[0]; 674d18719a4STom Rini for (i = 0; i < (n-1); i++) 675d18719a4STom Rini tbl[i]->next = tbl[i+1]; 676d18719a4STom Rini tbl[n-1]->next = NULL; 677d18719a4STom Rini 678d18719a4STom Rini free(tbl); 679d18719a4STom Rini } 680d18719a4STom Rini 681d18719a4STom Rini static int cmp_subnode(const void *ax, const void *bx) 682d18719a4STom Rini { 683d18719a4STom Rini const struct node *a, *b; 684d18719a4STom Rini 685d18719a4STom Rini a = *((const struct node * const *)ax); 686d18719a4STom Rini b = *((const struct node * const *)bx); 687d18719a4STom Rini 688d18719a4STom Rini return strcmp(a->name, b->name); 689d18719a4STom Rini } 690d18719a4STom Rini 691d18719a4STom Rini static void sort_subnodes(struct node *node) 692d18719a4STom Rini { 693d18719a4STom Rini int n = 0, i = 0; 694d18719a4STom Rini struct node *subnode, **tbl; 695d18719a4STom Rini 696d18719a4STom Rini for_each_child_withdel(node, subnode) 697d18719a4STom Rini n++; 698d18719a4STom Rini 699d18719a4STom Rini if (n == 0) 700d18719a4STom Rini return; 701d18719a4STom Rini 702d18719a4STom Rini tbl = xmalloc(n * sizeof(*tbl)); 703d18719a4STom Rini 704d18719a4STom Rini for_each_child_withdel(node, subnode) 705d18719a4STom Rini tbl[i++] = subnode; 706d18719a4STom Rini 707d18719a4STom Rini qsort(tbl, n, sizeof(*tbl), cmp_subnode); 708d18719a4STom Rini 709d18719a4STom Rini node->children = tbl[0]; 710d18719a4STom Rini for (i = 0; i < (n-1); i++) 711d18719a4STom Rini tbl[i]->next_sibling = tbl[i+1]; 712d18719a4STom Rini tbl[n-1]->next_sibling = NULL; 713d18719a4STom Rini 714d18719a4STom Rini free(tbl); 715d18719a4STom Rini } 716d18719a4STom Rini 717d18719a4STom Rini static void sort_node(struct node *node) 718d18719a4STom Rini { 719d18719a4STom Rini struct node *c; 720d18719a4STom Rini 721d18719a4STom Rini sort_properties(node); 722d18719a4STom Rini sort_subnodes(node); 723d18719a4STom Rini for_each_child_withdel(node, c) 724d18719a4STom Rini sort_node(c); 725d18719a4STom Rini } 726d18719a4STom Rini 727d18719a4STom Rini void sort_tree(struct dt_info *dti) 728d18719a4STom Rini { 729d18719a4STom Rini sort_reserve_entries(dti); 730d18719a4STom Rini sort_node(dti->dt); 731d18719a4STom Rini } 732d18719a4STom Rini 733d18719a4STom Rini /* utility helper to avoid code duplication */ 734d18719a4STom Rini static struct node *build_and_name_child_node(struct node *parent, char *name) 735d18719a4STom Rini { 736d18719a4STom Rini struct node *node; 737d18719a4STom Rini 738d18719a4STom Rini node = build_node(NULL, NULL); 739d18719a4STom Rini name_node(node, xstrdup(name)); 740d18719a4STom Rini add_child(parent, node); 741d18719a4STom Rini 742d18719a4STom Rini return node; 743d18719a4STom Rini } 744d18719a4STom Rini 745d18719a4STom Rini static struct node *build_root_node(struct node *dt, char *name) 746d18719a4STom Rini { 747d18719a4STom Rini struct node *an; 748d18719a4STom Rini 749d18719a4STom Rini an = get_subnode(dt, name); 750d18719a4STom Rini if (!an) 751d18719a4STom Rini an = build_and_name_child_node(dt, name); 752d18719a4STom Rini 753d18719a4STom Rini if (!an) 754d18719a4STom Rini die("Could not build root node /%s\n", name); 755d18719a4STom Rini 756d18719a4STom Rini return an; 757d18719a4STom Rini } 758d18719a4STom Rini 759d18719a4STom Rini static bool any_label_tree(struct dt_info *dti, struct node *node) 760d18719a4STom Rini { 761d18719a4STom Rini struct node *c; 762d18719a4STom Rini 763d18719a4STom Rini if (node->labels) 764d18719a4STom Rini return true; 765d18719a4STom Rini 766d18719a4STom Rini for_each_child(node, c) 767d18719a4STom Rini if (any_label_tree(dti, c)) 768d18719a4STom Rini return true; 769d18719a4STom Rini 770d18719a4STom Rini return false; 771d18719a4STom Rini } 772d18719a4STom Rini 773d18719a4STom Rini static void generate_label_tree_internal(struct dt_info *dti, 774d18719a4STom Rini struct node *an, struct node *node, 775d18719a4STom Rini bool allocph) 776d18719a4STom Rini { 777d18719a4STom Rini struct node *dt = dti->dt; 778d18719a4STom Rini struct node *c; 779d18719a4STom Rini struct property *p; 780d18719a4STom Rini struct label *l; 781d18719a4STom Rini 782d18719a4STom Rini /* if there are labels */ 783d18719a4STom Rini if (node->labels) { 784d18719a4STom Rini 785d18719a4STom Rini /* now add the label in the node */ 786d18719a4STom Rini for_each_label(node->labels, l) { 787d18719a4STom Rini 788d18719a4STom Rini /* check whether the label already exists */ 789d18719a4STom Rini p = get_property(an, l->label); 790d18719a4STom Rini if (p) { 791d18719a4STom Rini fprintf(stderr, "WARNING: label %s already" 792d18719a4STom Rini " exists in /%s", l->label, 793d18719a4STom Rini an->name); 794d18719a4STom Rini continue; 795d18719a4STom Rini } 796d18719a4STom Rini 797d18719a4STom Rini /* insert it */ 798d18719a4STom Rini p = build_property(l->label, 799d18719a4STom Rini data_copy_mem(node->fullpath, 800d18719a4STom Rini strlen(node->fullpath) + 1)); 801d18719a4STom Rini add_property(an, p); 802d18719a4STom Rini } 803d18719a4STom Rini 804d18719a4STom Rini /* force allocation of a phandle for this node */ 805d18719a4STom Rini if (allocph) 806d18719a4STom Rini (void)get_node_phandle(dt, node); 807d18719a4STom Rini } 808d18719a4STom Rini 809d18719a4STom Rini for_each_child(node, c) 810d18719a4STom Rini generate_label_tree_internal(dti, an, c, allocph); 811d18719a4STom Rini } 812d18719a4STom Rini 813d18719a4STom Rini static bool any_fixup_tree(struct dt_info *dti, struct node *node) 814d18719a4STom Rini { 815d18719a4STom Rini struct node *c; 816d18719a4STom Rini struct property *prop; 817d18719a4STom Rini struct marker *m; 818d18719a4STom Rini 819d18719a4STom Rini for_each_property(node, prop) { 820d18719a4STom Rini m = prop->val.markers; 821d18719a4STom Rini for_each_marker_of_type(m, REF_PHANDLE) { 822d18719a4STom Rini if (!get_node_by_ref(dti->dt, m->ref)) 823d18719a4STom Rini return true; 824d18719a4STom Rini } 825d18719a4STom Rini } 826d18719a4STom Rini 827d18719a4STom Rini for_each_child(node, c) { 828d18719a4STom Rini if (any_fixup_tree(dti, c)) 829d18719a4STom Rini return true; 830d18719a4STom Rini } 831d18719a4STom Rini 832d18719a4STom Rini return false; 833d18719a4STom Rini } 834d18719a4STom Rini 835d18719a4STom Rini static void add_fixup_entry(struct dt_info *dti, struct node *fn, 836d18719a4STom Rini struct node *node, struct property *prop, 837d18719a4STom Rini struct marker *m) 838d18719a4STom Rini { 839d18719a4STom Rini char *entry; 840d18719a4STom Rini 841d18719a4STom Rini /* m->ref can only be a REF_PHANDLE, but check anyway */ 842d18719a4STom Rini assert(m->type == REF_PHANDLE); 843d18719a4STom Rini 844d18719a4STom Rini /* there shouldn't be any ':' in the arguments */ 845d18719a4STom Rini if (strchr(node->fullpath, ':') || strchr(prop->name, ':')) 846d18719a4STom Rini die("arguments should not contain ':'\n"); 847d18719a4STom Rini 848d18719a4STom Rini xasprintf(&entry, "%s:%s:%u", 849d18719a4STom Rini node->fullpath, prop->name, m->offset); 850d18719a4STom Rini append_to_property(fn, m->ref, entry, strlen(entry) + 1); 851d18719a4STom Rini 852d18719a4STom Rini free(entry); 853d18719a4STom Rini } 854d18719a4STom Rini 855d18719a4STom Rini static void generate_fixups_tree_internal(struct dt_info *dti, 856d18719a4STom Rini struct node *fn, 857d18719a4STom Rini struct node *node) 858d18719a4STom Rini { 859d18719a4STom Rini struct node *dt = dti->dt; 860d18719a4STom Rini struct node *c; 861d18719a4STom Rini struct property *prop; 862d18719a4STom Rini struct marker *m; 863d18719a4STom Rini struct node *refnode; 864d18719a4STom Rini 865d18719a4STom Rini for_each_property(node, prop) { 866d18719a4STom Rini m = prop->val.markers; 867d18719a4STom Rini for_each_marker_of_type(m, REF_PHANDLE) { 868d18719a4STom Rini refnode = get_node_by_ref(dt, m->ref); 869d18719a4STom Rini if (!refnode) 870d18719a4STom Rini add_fixup_entry(dti, fn, node, prop, m); 871d18719a4STom Rini } 872d18719a4STom Rini } 873d18719a4STom Rini 874d18719a4STom Rini for_each_child(node, c) 875d18719a4STom Rini generate_fixups_tree_internal(dti, fn, c); 876d18719a4STom Rini } 877d18719a4STom Rini 878d18719a4STom Rini static bool any_local_fixup_tree(struct dt_info *dti, struct node *node) 879d18719a4STom Rini { 880d18719a4STom Rini struct node *c; 881d18719a4STom Rini struct property *prop; 882d18719a4STom Rini struct marker *m; 883d18719a4STom Rini 884d18719a4STom Rini for_each_property(node, prop) { 885d18719a4STom Rini m = prop->val.markers; 886d18719a4STom Rini for_each_marker_of_type(m, REF_PHANDLE) { 887d18719a4STom Rini if (get_node_by_ref(dti->dt, m->ref)) 888d18719a4STom Rini return true; 889d18719a4STom Rini } 890d18719a4STom Rini } 891d18719a4STom Rini 892d18719a4STom Rini for_each_child(node, c) { 893d18719a4STom Rini if (any_local_fixup_tree(dti, c)) 894d18719a4STom Rini return true; 895d18719a4STom Rini } 896d18719a4STom Rini 897d18719a4STom Rini return false; 898d18719a4STom Rini } 899d18719a4STom Rini 900d18719a4STom Rini static void add_local_fixup_entry(struct dt_info *dti, 901d18719a4STom Rini struct node *lfn, struct node *node, 902d18719a4STom Rini struct property *prop, struct marker *m, 903d18719a4STom Rini struct node *refnode) 904d18719a4STom Rini { 905d18719a4STom Rini struct node *wn, *nwn; /* local fixup node, walk node, new */ 906e23ffda2STom Rini fdt32_t value_32; 907d18719a4STom Rini char **compp; 908d18719a4STom Rini int i, depth; 909d18719a4STom Rini 910d18719a4STom Rini /* walk back retreiving depth */ 911d18719a4STom Rini depth = 0; 912d18719a4STom Rini for (wn = node; wn; wn = wn->parent) 913d18719a4STom Rini depth++; 914d18719a4STom Rini 915d18719a4STom Rini /* allocate name array */ 916d18719a4STom Rini compp = xmalloc(sizeof(*compp) * depth); 917d18719a4STom Rini 918d18719a4STom Rini /* store names in the array */ 919d18719a4STom Rini for (wn = node, i = depth - 1; wn; wn = wn->parent, i--) 920d18719a4STom Rini compp[i] = wn->name; 921d18719a4STom Rini 922d18719a4STom Rini /* walk the path components creating nodes if they don't exist */ 923d18719a4STom Rini for (wn = lfn, i = 1; i < depth; i++, wn = nwn) { 924d18719a4STom Rini /* if no node exists, create it */ 925d18719a4STom Rini nwn = get_subnode(wn, compp[i]); 926d18719a4STom Rini if (!nwn) 927d18719a4STom Rini nwn = build_and_name_child_node(wn, compp[i]); 928d18719a4STom Rini } 929d18719a4STom Rini 930d18719a4STom Rini free(compp); 931d18719a4STom Rini 932d18719a4STom Rini value_32 = cpu_to_fdt32(m->offset); 933d18719a4STom Rini append_to_property(wn, prop->name, &value_32, sizeof(value_32)); 934d18719a4STom Rini } 935d18719a4STom Rini 936d18719a4STom Rini static void generate_local_fixups_tree_internal(struct dt_info *dti, 937d18719a4STom Rini struct node *lfn, 938d18719a4STom Rini struct node *node) 939d18719a4STom Rini { 940d18719a4STom Rini struct node *dt = dti->dt; 941d18719a4STom Rini struct node *c; 942d18719a4STom Rini struct property *prop; 943d18719a4STom Rini struct marker *m; 944d18719a4STom Rini struct node *refnode; 945d18719a4STom Rini 946d18719a4STom Rini for_each_property(node, prop) { 947d18719a4STom Rini m = prop->val.markers; 948d18719a4STom Rini for_each_marker_of_type(m, REF_PHANDLE) { 949d18719a4STom Rini refnode = get_node_by_ref(dt, m->ref); 950d18719a4STom Rini if (refnode) 951d18719a4STom Rini add_local_fixup_entry(dti, lfn, node, prop, m, refnode); 952d18719a4STom Rini } 953d18719a4STom Rini } 954d18719a4STom Rini 955d18719a4STom Rini for_each_child(node, c) 956d18719a4STom Rini generate_local_fixups_tree_internal(dti, lfn, c); 957d18719a4STom Rini } 958d18719a4STom Rini 959d18719a4STom Rini void generate_label_tree(struct dt_info *dti, char *name, bool allocph) 960d18719a4STom Rini { 961d18719a4STom Rini if (!any_label_tree(dti, dti->dt)) 962d18719a4STom Rini return; 963d18719a4STom Rini generate_label_tree_internal(dti, build_root_node(dti->dt, name), 964d18719a4STom Rini dti->dt, allocph); 965d18719a4STom Rini } 966d18719a4STom Rini 967d18719a4STom Rini void generate_fixups_tree(struct dt_info *dti, char *name) 968d18719a4STom Rini { 969d18719a4STom Rini if (!any_fixup_tree(dti, dti->dt)) 970d18719a4STom Rini return; 971d18719a4STom Rini generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), 972d18719a4STom Rini dti->dt); 973d18719a4STom Rini } 974d18719a4STom Rini 975d18719a4STom Rini void generate_local_fixups_tree(struct dt_info *dti, char *name) 976d18719a4STom Rini { 977d18719a4STom Rini if (!any_local_fixup_tree(dti, dti->dt)) 978d18719a4STom Rini return; 979d18719a4STom Rini generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), 980d18719a4STom Rini dti->dt); 981d18719a4STom Rini } 982