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 322*e23ffda2STom Rini new->address = address; 323*e23ffda2STom 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)); 396*e23ffda2STom 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) { 481d18719a4STom Rini if (p && strneq(path, child->name, p-path)) 482d18719a4STom Rini return get_node_by_path(child, p+1); 483d18719a4STom Rini else if (!p && streq(path, child->name)) 484d18719a4STom Rini return child; 485d18719a4STom Rini } 486d18719a4STom Rini 487d18719a4STom Rini return NULL; 488d18719a4STom Rini } 489d18719a4STom Rini 490d18719a4STom Rini struct node *get_node_by_label(struct node *tree, const char *label) 491d18719a4STom Rini { 492d18719a4STom Rini struct node *child, *node; 493d18719a4STom Rini struct label *l; 494d18719a4STom Rini 495d18719a4STom Rini assert(label && (strlen(label) > 0)); 496d18719a4STom Rini 497d18719a4STom Rini for_each_label(tree->labels, l) 498d18719a4STom Rini if (streq(l->label, label)) 499d18719a4STom Rini return tree; 500d18719a4STom Rini 501d18719a4STom Rini for_each_child(tree, child) { 502d18719a4STom Rini node = get_node_by_label(child, label); 503d18719a4STom Rini if (node) 504d18719a4STom Rini return node; 505d18719a4STom Rini } 506d18719a4STom Rini 507d18719a4STom Rini return NULL; 508d18719a4STom Rini } 509d18719a4STom Rini 510d18719a4STom Rini struct node *get_node_by_phandle(struct node *tree, cell_t phandle) 511d18719a4STom Rini { 512d18719a4STom Rini struct node *child, *node; 513d18719a4STom Rini 514d18719a4STom Rini assert((phandle != 0) && (phandle != -1)); 515d18719a4STom Rini 516d18719a4STom Rini if (tree->phandle == phandle) { 517d18719a4STom Rini if (tree->deleted) 518d18719a4STom Rini return NULL; 519d18719a4STom Rini return tree; 520d18719a4STom Rini } 521d18719a4STom Rini 522d18719a4STom Rini for_each_child(tree, child) { 523d18719a4STom Rini node = get_node_by_phandle(child, phandle); 524d18719a4STom Rini if (node) 525d18719a4STom Rini return node; 526d18719a4STom Rini } 527d18719a4STom Rini 528d18719a4STom Rini return NULL; 529d18719a4STom Rini } 530d18719a4STom Rini 531d18719a4STom Rini struct node *get_node_by_ref(struct node *tree, const char *ref) 532d18719a4STom Rini { 533d18719a4STom Rini if (streq(ref, "/")) 534d18719a4STom Rini return tree; 535d18719a4STom Rini else if (ref[0] == '/') 536d18719a4STom Rini return get_node_by_path(tree, ref); 537d18719a4STom Rini else 538d18719a4STom Rini return get_node_by_label(tree, ref); 539d18719a4STom Rini } 540d18719a4STom Rini 541d18719a4STom Rini cell_t get_node_phandle(struct node *root, struct node *node) 542d18719a4STom Rini { 543d18719a4STom Rini static cell_t phandle = 1; /* FIXME: ick, static local */ 544d18719a4STom Rini 545d18719a4STom Rini if ((node->phandle != 0) && (node->phandle != -1)) 546d18719a4STom Rini return node->phandle; 547d18719a4STom Rini 548d18719a4STom Rini while (get_node_by_phandle(root, phandle)) 549d18719a4STom Rini phandle++; 550d18719a4STom Rini 551d18719a4STom Rini node->phandle = phandle; 552d18719a4STom Rini 553d18719a4STom Rini if (!get_property(node, "linux,phandle") 554d18719a4STom Rini && (phandle_format & PHANDLE_LEGACY)) 555d18719a4STom Rini add_property(node, 556d18719a4STom Rini build_property("linux,phandle", 557d18719a4STom Rini data_append_cell(empty_data, phandle))); 558d18719a4STom Rini 559d18719a4STom Rini if (!get_property(node, "phandle") 560d18719a4STom Rini && (phandle_format & PHANDLE_EPAPR)) 561d18719a4STom Rini add_property(node, 562d18719a4STom Rini build_property("phandle", 563d18719a4STom Rini data_append_cell(empty_data, phandle))); 564d18719a4STom Rini 565d18719a4STom Rini /* If the node *does* have a phandle property, we must 566d18719a4STom Rini * be dealing with a self-referencing phandle, which will be 567d18719a4STom Rini * fixed up momentarily in the caller */ 568d18719a4STom Rini 569d18719a4STom Rini return node->phandle; 570d18719a4STom Rini } 571d18719a4STom Rini 572d18719a4STom Rini uint32_t guess_boot_cpuid(struct node *tree) 573d18719a4STom Rini { 574d18719a4STom Rini struct node *cpus, *bootcpu; 575d18719a4STom Rini struct property *reg; 576d18719a4STom Rini 577d18719a4STom Rini cpus = get_node_by_path(tree, "/cpus"); 578d18719a4STom Rini if (!cpus) 579d18719a4STom Rini return 0; 580d18719a4STom Rini 581d18719a4STom Rini 582d18719a4STom Rini bootcpu = cpus->children; 583d18719a4STom Rini if (!bootcpu) 584d18719a4STom Rini return 0; 585d18719a4STom Rini 586d18719a4STom Rini reg = get_property(bootcpu, "reg"); 587d18719a4STom Rini if (!reg || (reg->val.len != sizeof(uint32_t))) 588d18719a4STom Rini return 0; 589d18719a4STom Rini 590d18719a4STom Rini /* FIXME: Sanity check node? */ 591d18719a4STom Rini 592d18719a4STom Rini return propval_cell(reg); 593d18719a4STom Rini } 594d18719a4STom Rini 595d18719a4STom Rini static int cmp_reserve_info(const void *ax, const void *bx) 596d18719a4STom Rini { 597d18719a4STom Rini const struct reserve_info *a, *b; 598d18719a4STom Rini 599d18719a4STom Rini a = *((const struct reserve_info * const *)ax); 600d18719a4STom Rini b = *((const struct reserve_info * const *)bx); 601d18719a4STom Rini 602*e23ffda2STom Rini if (a->address < b->address) 603d18719a4STom Rini return -1; 604*e23ffda2STom Rini else if (a->address > b->address) 605d18719a4STom Rini return 1; 606*e23ffda2STom Rini else if (a->size < b->size) 607d18719a4STom Rini return -1; 608*e23ffda2STom Rini else if (a->size > b->size) 609d18719a4STom Rini return 1; 610d18719a4STom Rini else 611d18719a4STom Rini return 0; 612d18719a4STom Rini } 613d18719a4STom Rini 614d18719a4STom Rini static void sort_reserve_entries(struct dt_info *dti) 615d18719a4STom Rini { 616d18719a4STom Rini struct reserve_info *ri, **tbl; 617d18719a4STom Rini int n = 0, i = 0; 618d18719a4STom Rini 619d18719a4STom Rini for (ri = dti->reservelist; 620d18719a4STom Rini ri; 621d18719a4STom Rini ri = ri->next) 622d18719a4STom Rini n++; 623d18719a4STom Rini 624d18719a4STom Rini if (n == 0) 625d18719a4STom Rini return; 626d18719a4STom Rini 627d18719a4STom Rini tbl = xmalloc(n * sizeof(*tbl)); 628d18719a4STom Rini 629d18719a4STom Rini for (ri = dti->reservelist; 630d18719a4STom Rini ri; 631d18719a4STom Rini ri = ri->next) 632d18719a4STom Rini tbl[i++] = ri; 633d18719a4STom Rini 634d18719a4STom Rini qsort(tbl, n, sizeof(*tbl), cmp_reserve_info); 635d18719a4STom Rini 636d18719a4STom Rini dti->reservelist = tbl[0]; 637d18719a4STom Rini for (i = 0; i < (n-1); i++) 638d18719a4STom Rini tbl[i]->next = tbl[i+1]; 639d18719a4STom Rini tbl[n-1]->next = NULL; 640d18719a4STom Rini 641d18719a4STom Rini free(tbl); 642d18719a4STom Rini } 643d18719a4STom Rini 644d18719a4STom Rini static int cmp_prop(const void *ax, const void *bx) 645d18719a4STom Rini { 646d18719a4STom Rini const struct property *a, *b; 647d18719a4STom Rini 648d18719a4STom Rini a = *((const struct property * const *)ax); 649d18719a4STom Rini b = *((const struct property * const *)bx); 650d18719a4STom Rini 651d18719a4STom Rini return strcmp(a->name, b->name); 652d18719a4STom Rini } 653d18719a4STom Rini 654d18719a4STom Rini static void sort_properties(struct node *node) 655d18719a4STom Rini { 656d18719a4STom Rini int n = 0, i = 0; 657d18719a4STom Rini struct property *prop, **tbl; 658d18719a4STom Rini 659d18719a4STom Rini for_each_property_withdel(node, prop) 660d18719a4STom Rini n++; 661d18719a4STom Rini 662d18719a4STom Rini if (n == 0) 663d18719a4STom Rini return; 664d18719a4STom Rini 665d18719a4STom Rini tbl = xmalloc(n * sizeof(*tbl)); 666d18719a4STom Rini 667d18719a4STom Rini for_each_property_withdel(node, prop) 668d18719a4STom Rini tbl[i++] = prop; 669d18719a4STom Rini 670d18719a4STom Rini qsort(tbl, n, sizeof(*tbl), cmp_prop); 671d18719a4STom Rini 672d18719a4STom Rini node->proplist = tbl[0]; 673d18719a4STom Rini for (i = 0; i < (n-1); i++) 674d18719a4STom Rini tbl[i]->next = tbl[i+1]; 675d18719a4STom Rini tbl[n-1]->next = NULL; 676d18719a4STom Rini 677d18719a4STom Rini free(tbl); 678d18719a4STom Rini } 679d18719a4STom Rini 680d18719a4STom Rini static int cmp_subnode(const void *ax, const void *bx) 681d18719a4STom Rini { 682d18719a4STom Rini const struct node *a, *b; 683d18719a4STom Rini 684d18719a4STom Rini a = *((const struct node * const *)ax); 685d18719a4STom Rini b = *((const struct node * const *)bx); 686d18719a4STom Rini 687d18719a4STom Rini return strcmp(a->name, b->name); 688d18719a4STom Rini } 689d18719a4STom Rini 690d18719a4STom Rini static void sort_subnodes(struct node *node) 691d18719a4STom Rini { 692d18719a4STom Rini int n = 0, i = 0; 693d18719a4STom Rini struct node *subnode, **tbl; 694d18719a4STom Rini 695d18719a4STom Rini for_each_child_withdel(node, subnode) 696d18719a4STom Rini n++; 697d18719a4STom Rini 698d18719a4STom Rini if (n == 0) 699d18719a4STom Rini return; 700d18719a4STom Rini 701d18719a4STom Rini tbl = xmalloc(n * sizeof(*tbl)); 702d18719a4STom Rini 703d18719a4STom Rini for_each_child_withdel(node, subnode) 704d18719a4STom Rini tbl[i++] = subnode; 705d18719a4STom Rini 706d18719a4STom Rini qsort(tbl, n, sizeof(*tbl), cmp_subnode); 707d18719a4STom Rini 708d18719a4STom Rini node->children = tbl[0]; 709d18719a4STom Rini for (i = 0; i < (n-1); i++) 710d18719a4STom Rini tbl[i]->next_sibling = tbl[i+1]; 711d18719a4STom Rini tbl[n-1]->next_sibling = NULL; 712d18719a4STom Rini 713d18719a4STom Rini free(tbl); 714d18719a4STom Rini } 715d18719a4STom Rini 716d18719a4STom Rini static void sort_node(struct node *node) 717d18719a4STom Rini { 718d18719a4STom Rini struct node *c; 719d18719a4STom Rini 720d18719a4STom Rini sort_properties(node); 721d18719a4STom Rini sort_subnodes(node); 722d18719a4STom Rini for_each_child_withdel(node, c) 723d18719a4STom Rini sort_node(c); 724d18719a4STom Rini } 725d18719a4STom Rini 726d18719a4STom Rini void sort_tree(struct dt_info *dti) 727d18719a4STom Rini { 728d18719a4STom Rini sort_reserve_entries(dti); 729d18719a4STom Rini sort_node(dti->dt); 730d18719a4STom Rini } 731d18719a4STom Rini 732d18719a4STom Rini /* utility helper to avoid code duplication */ 733d18719a4STom Rini static struct node *build_and_name_child_node(struct node *parent, char *name) 734d18719a4STom Rini { 735d18719a4STom Rini struct node *node; 736d18719a4STom Rini 737d18719a4STom Rini node = build_node(NULL, NULL); 738d18719a4STom Rini name_node(node, xstrdup(name)); 739d18719a4STom Rini add_child(parent, node); 740d18719a4STom Rini 741d18719a4STom Rini return node; 742d18719a4STom Rini } 743d18719a4STom Rini 744d18719a4STom Rini static struct node *build_root_node(struct node *dt, char *name) 745d18719a4STom Rini { 746d18719a4STom Rini struct node *an; 747d18719a4STom Rini 748d18719a4STom Rini an = get_subnode(dt, name); 749d18719a4STom Rini if (!an) 750d18719a4STom Rini an = build_and_name_child_node(dt, name); 751d18719a4STom Rini 752d18719a4STom Rini if (!an) 753d18719a4STom Rini die("Could not build root node /%s\n", name); 754d18719a4STom Rini 755d18719a4STom Rini return an; 756d18719a4STom Rini } 757d18719a4STom Rini 758d18719a4STom Rini static bool any_label_tree(struct dt_info *dti, struct node *node) 759d18719a4STom Rini { 760d18719a4STom Rini struct node *c; 761d18719a4STom Rini 762d18719a4STom Rini if (node->labels) 763d18719a4STom Rini return true; 764d18719a4STom Rini 765d18719a4STom Rini for_each_child(node, c) 766d18719a4STom Rini if (any_label_tree(dti, c)) 767d18719a4STom Rini return true; 768d18719a4STom Rini 769d18719a4STom Rini return false; 770d18719a4STom Rini } 771d18719a4STom Rini 772d18719a4STom Rini static void generate_label_tree_internal(struct dt_info *dti, 773d18719a4STom Rini struct node *an, struct node *node, 774d18719a4STom Rini bool allocph) 775d18719a4STom Rini { 776d18719a4STom Rini struct node *dt = dti->dt; 777d18719a4STom Rini struct node *c; 778d18719a4STom Rini struct property *p; 779d18719a4STom Rini struct label *l; 780d18719a4STom Rini 781d18719a4STom Rini /* if there are labels */ 782d18719a4STom Rini if (node->labels) { 783d18719a4STom Rini 784d18719a4STom Rini /* now add the label in the node */ 785d18719a4STom Rini for_each_label(node->labels, l) { 786d18719a4STom Rini 787d18719a4STom Rini /* check whether the label already exists */ 788d18719a4STom Rini p = get_property(an, l->label); 789d18719a4STom Rini if (p) { 790d18719a4STom Rini fprintf(stderr, "WARNING: label %s already" 791d18719a4STom Rini " exists in /%s", l->label, 792d18719a4STom Rini an->name); 793d18719a4STom Rini continue; 794d18719a4STom Rini } 795d18719a4STom Rini 796d18719a4STom Rini /* insert it */ 797d18719a4STom Rini p = build_property(l->label, 798d18719a4STom Rini data_copy_mem(node->fullpath, 799d18719a4STom Rini strlen(node->fullpath) + 1)); 800d18719a4STom Rini add_property(an, p); 801d18719a4STom Rini } 802d18719a4STom Rini 803d18719a4STom Rini /* force allocation of a phandle for this node */ 804d18719a4STom Rini if (allocph) 805d18719a4STom Rini (void)get_node_phandle(dt, node); 806d18719a4STom Rini } 807d18719a4STom Rini 808d18719a4STom Rini for_each_child(node, c) 809d18719a4STom Rini generate_label_tree_internal(dti, an, c, allocph); 810d18719a4STom Rini } 811d18719a4STom Rini 812d18719a4STom Rini static bool any_fixup_tree(struct dt_info *dti, struct node *node) 813d18719a4STom Rini { 814d18719a4STom Rini struct node *c; 815d18719a4STom Rini struct property *prop; 816d18719a4STom Rini struct marker *m; 817d18719a4STom Rini 818d18719a4STom Rini for_each_property(node, prop) { 819d18719a4STom Rini m = prop->val.markers; 820d18719a4STom Rini for_each_marker_of_type(m, REF_PHANDLE) { 821d18719a4STom Rini if (!get_node_by_ref(dti->dt, m->ref)) 822d18719a4STom Rini return true; 823d18719a4STom Rini } 824d18719a4STom Rini } 825d18719a4STom Rini 826d18719a4STom Rini for_each_child(node, c) { 827d18719a4STom Rini if (any_fixup_tree(dti, c)) 828d18719a4STom Rini return true; 829d18719a4STom Rini } 830d18719a4STom Rini 831d18719a4STom Rini return false; 832d18719a4STom Rini } 833d18719a4STom Rini 834d18719a4STom Rini static void add_fixup_entry(struct dt_info *dti, struct node *fn, 835d18719a4STom Rini struct node *node, struct property *prop, 836d18719a4STom Rini struct marker *m) 837d18719a4STom Rini { 838d18719a4STom Rini char *entry; 839d18719a4STom Rini 840d18719a4STom Rini /* m->ref can only be a REF_PHANDLE, but check anyway */ 841d18719a4STom Rini assert(m->type == REF_PHANDLE); 842d18719a4STom Rini 843d18719a4STom Rini /* there shouldn't be any ':' in the arguments */ 844d18719a4STom Rini if (strchr(node->fullpath, ':') || strchr(prop->name, ':')) 845d18719a4STom Rini die("arguments should not contain ':'\n"); 846d18719a4STom Rini 847d18719a4STom Rini xasprintf(&entry, "%s:%s:%u", 848d18719a4STom Rini node->fullpath, prop->name, m->offset); 849d18719a4STom Rini append_to_property(fn, m->ref, entry, strlen(entry) + 1); 850d18719a4STom Rini 851d18719a4STom Rini free(entry); 852d18719a4STom Rini } 853d18719a4STom Rini 854d18719a4STom Rini static void generate_fixups_tree_internal(struct dt_info *dti, 855d18719a4STom Rini struct node *fn, 856d18719a4STom Rini struct node *node) 857d18719a4STom Rini { 858d18719a4STom Rini struct node *dt = dti->dt; 859d18719a4STom Rini struct node *c; 860d18719a4STom Rini struct property *prop; 861d18719a4STom Rini struct marker *m; 862d18719a4STom Rini struct node *refnode; 863d18719a4STom Rini 864d18719a4STom Rini for_each_property(node, prop) { 865d18719a4STom Rini m = prop->val.markers; 866d18719a4STom Rini for_each_marker_of_type(m, REF_PHANDLE) { 867d18719a4STom Rini refnode = get_node_by_ref(dt, m->ref); 868d18719a4STom Rini if (!refnode) 869d18719a4STom Rini add_fixup_entry(dti, fn, node, prop, m); 870d18719a4STom Rini } 871d18719a4STom Rini } 872d18719a4STom Rini 873d18719a4STom Rini for_each_child(node, c) 874d18719a4STom Rini generate_fixups_tree_internal(dti, fn, c); 875d18719a4STom Rini } 876d18719a4STom Rini 877d18719a4STom Rini static bool any_local_fixup_tree(struct dt_info *dti, struct node *node) 878d18719a4STom Rini { 879d18719a4STom Rini struct node *c; 880d18719a4STom Rini struct property *prop; 881d18719a4STom Rini struct marker *m; 882d18719a4STom Rini 883d18719a4STom Rini for_each_property(node, prop) { 884d18719a4STom Rini m = prop->val.markers; 885d18719a4STom Rini for_each_marker_of_type(m, REF_PHANDLE) { 886d18719a4STom Rini if (get_node_by_ref(dti->dt, m->ref)) 887d18719a4STom Rini return true; 888d18719a4STom Rini } 889d18719a4STom Rini } 890d18719a4STom Rini 891d18719a4STom Rini for_each_child(node, c) { 892d18719a4STom Rini if (any_local_fixup_tree(dti, c)) 893d18719a4STom Rini return true; 894d18719a4STom Rini } 895d18719a4STom Rini 896d18719a4STom Rini return false; 897d18719a4STom Rini } 898d18719a4STom Rini 899d18719a4STom Rini static void add_local_fixup_entry(struct dt_info *dti, 900d18719a4STom Rini struct node *lfn, struct node *node, 901d18719a4STom Rini struct property *prop, struct marker *m, 902d18719a4STom Rini struct node *refnode) 903d18719a4STom Rini { 904d18719a4STom Rini struct node *wn, *nwn; /* local fixup node, walk node, new */ 905*e23ffda2STom Rini fdt32_t value_32; 906d18719a4STom Rini char **compp; 907d18719a4STom Rini int i, depth; 908d18719a4STom Rini 909d18719a4STom Rini /* walk back retreiving depth */ 910d18719a4STom Rini depth = 0; 911d18719a4STom Rini for (wn = node; wn; wn = wn->parent) 912d18719a4STom Rini depth++; 913d18719a4STom Rini 914d18719a4STom Rini /* allocate name array */ 915d18719a4STom Rini compp = xmalloc(sizeof(*compp) * depth); 916d18719a4STom Rini 917d18719a4STom Rini /* store names in the array */ 918d18719a4STom Rini for (wn = node, i = depth - 1; wn; wn = wn->parent, i--) 919d18719a4STom Rini compp[i] = wn->name; 920d18719a4STom Rini 921d18719a4STom Rini /* walk the path components creating nodes if they don't exist */ 922d18719a4STom Rini for (wn = lfn, i = 1; i < depth; i++, wn = nwn) { 923d18719a4STom Rini /* if no node exists, create it */ 924d18719a4STom Rini nwn = get_subnode(wn, compp[i]); 925d18719a4STom Rini if (!nwn) 926d18719a4STom Rini nwn = build_and_name_child_node(wn, compp[i]); 927d18719a4STom Rini } 928d18719a4STom Rini 929d18719a4STom Rini free(compp); 930d18719a4STom Rini 931d18719a4STom Rini value_32 = cpu_to_fdt32(m->offset); 932d18719a4STom Rini append_to_property(wn, prop->name, &value_32, sizeof(value_32)); 933d18719a4STom Rini } 934d18719a4STom Rini 935d18719a4STom Rini static void generate_local_fixups_tree_internal(struct dt_info *dti, 936d18719a4STom Rini struct node *lfn, 937d18719a4STom Rini struct node *node) 938d18719a4STom Rini { 939d18719a4STom Rini struct node *dt = dti->dt; 940d18719a4STom Rini struct node *c; 941d18719a4STom Rini struct property *prop; 942d18719a4STom Rini struct marker *m; 943d18719a4STom Rini struct node *refnode; 944d18719a4STom Rini 945d18719a4STom Rini for_each_property(node, prop) { 946d18719a4STom Rini m = prop->val.markers; 947d18719a4STom Rini for_each_marker_of_type(m, REF_PHANDLE) { 948d18719a4STom Rini refnode = get_node_by_ref(dt, m->ref); 949d18719a4STom Rini if (refnode) 950d18719a4STom Rini add_local_fixup_entry(dti, lfn, node, prop, m, refnode); 951d18719a4STom Rini } 952d18719a4STom Rini } 953d18719a4STom Rini 954d18719a4STom Rini for_each_child(node, c) 955d18719a4STom Rini generate_local_fixups_tree_internal(dti, lfn, c); 956d18719a4STom Rini } 957d18719a4STom Rini 958d18719a4STom Rini void generate_label_tree(struct dt_info *dti, char *name, bool allocph) 959d18719a4STom Rini { 960d18719a4STom Rini if (!any_label_tree(dti, dti->dt)) 961d18719a4STom Rini return; 962d18719a4STom Rini generate_label_tree_internal(dti, build_root_node(dti->dt, name), 963d18719a4STom Rini dti->dt, allocph); 964d18719a4STom Rini } 965d18719a4STom Rini 966d18719a4STom Rini void generate_fixups_tree(struct dt_info *dti, char *name) 967d18719a4STom Rini { 968d18719a4STom Rini if (!any_fixup_tree(dti, dti->dt)) 969d18719a4STom Rini return; 970d18719a4STom Rini generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), 971d18719a4STom Rini dti->dt); 972d18719a4STom Rini } 973d18719a4STom Rini 974d18719a4STom Rini void generate_local_fixups_tree(struct dt_info *dti, char *name) 975d18719a4STom Rini { 976d18719a4STom Rini if (!any_local_fixup_tree(dti, dti->dt)) 977d18719a4STom Rini return; 978d18719a4STom Rini generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), 979d18719a4STom Rini dti->dt); 980d18719a4STom Rini } 981