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 219*14df9b24SMasahiro Yamada void add_orphan_node(struct node *dt, struct node *new_node, char *ref) 220*14df9b24SMasahiro Yamada { 221*14df9b24SMasahiro Yamada static unsigned int next_orphan_fragment = 0; 222*14df9b24SMasahiro Yamada struct node *node; 223*14df9b24SMasahiro Yamada struct property *p; 224*14df9b24SMasahiro Yamada struct data d = empty_data; 225*14df9b24SMasahiro Yamada char *name; 226*14df9b24SMasahiro Yamada 227*14df9b24SMasahiro Yamada d = data_add_marker(d, REF_PHANDLE, ref); 228*14df9b24SMasahiro Yamada d = data_append_integer(d, 0xffffffff, 32); 229*14df9b24SMasahiro Yamada 230*14df9b24SMasahiro Yamada p = build_property("target", d); 231*14df9b24SMasahiro Yamada 232*14df9b24SMasahiro Yamada xasprintf(&name, "fragment@%u", 233*14df9b24SMasahiro Yamada next_orphan_fragment++); 234*14df9b24SMasahiro Yamada name_node(new_node, "__overlay__"); 235*14df9b24SMasahiro Yamada node = build_node(p, new_node); 236*14df9b24SMasahiro Yamada name_node(node, name); 237*14df9b24SMasahiro Yamada 238*14df9b24SMasahiro Yamada add_child(dt, node); 239*14df9b24SMasahiro Yamada } 240*14df9b24SMasahiro Yamada 241d18719a4STom Rini struct node *chain_node(struct node *first, struct node *list) 242d18719a4STom Rini { 243d18719a4STom Rini assert(first->next_sibling == NULL); 244d18719a4STom Rini 245d18719a4STom Rini first->next_sibling = list; 246d18719a4STom Rini return first; 247d18719a4STom Rini } 248d18719a4STom Rini 249d18719a4STom Rini void add_property(struct node *node, struct property *prop) 250d18719a4STom Rini { 251d18719a4STom Rini struct property **p; 252d18719a4STom Rini 253d18719a4STom Rini prop->next = NULL; 254d18719a4STom Rini 255d18719a4STom Rini p = &node->proplist; 256d18719a4STom Rini while (*p) 257d18719a4STom Rini p = &((*p)->next); 258d18719a4STom Rini 259d18719a4STom Rini *p = prop; 260d18719a4STom Rini } 261d18719a4STom Rini 262d18719a4STom Rini void delete_property_by_name(struct node *node, char *name) 263d18719a4STom Rini { 264d18719a4STom Rini struct property *prop = node->proplist; 265d18719a4STom Rini 266d18719a4STom Rini while (prop) { 267d18719a4STom Rini if (streq(prop->name, name)) { 268d18719a4STom Rini delete_property(prop); 269d18719a4STom Rini return; 270d18719a4STom Rini } 271d18719a4STom Rini prop = prop->next; 272d18719a4STom Rini } 273d18719a4STom Rini } 274d18719a4STom Rini 275d18719a4STom Rini void delete_property(struct property *prop) 276d18719a4STom Rini { 277d18719a4STom Rini prop->deleted = 1; 278d18719a4STom Rini delete_labels(&prop->labels); 279d18719a4STom Rini } 280d18719a4STom Rini 281d18719a4STom Rini void add_child(struct node *parent, struct node *child) 282d18719a4STom Rini { 283d18719a4STom Rini struct node **p; 284d18719a4STom Rini 285d18719a4STom Rini child->next_sibling = NULL; 286d18719a4STom Rini child->parent = parent; 287d18719a4STom Rini 288d18719a4STom Rini p = &parent->children; 289d18719a4STom Rini while (*p) 290d18719a4STom Rini p = &((*p)->next_sibling); 291d18719a4STom Rini 292d18719a4STom Rini *p = child; 293d18719a4STom Rini } 294d18719a4STom Rini 295d18719a4STom Rini void delete_node_by_name(struct node *parent, char *name) 296d18719a4STom Rini { 297d18719a4STom Rini struct node *node = parent->children; 298d18719a4STom Rini 299d18719a4STom Rini while (node) { 300d18719a4STom Rini if (streq(node->name, name)) { 301d18719a4STom Rini delete_node(node); 302d18719a4STom Rini return; 303d18719a4STom Rini } 304d18719a4STom Rini node = node->next_sibling; 305d18719a4STom Rini } 306d18719a4STom Rini } 307d18719a4STom Rini 308d18719a4STom Rini void delete_node(struct node *node) 309d18719a4STom Rini { 310d18719a4STom Rini struct property *prop; 311d18719a4STom Rini struct node *child; 312d18719a4STom Rini 313d18719a4STom Rini node->deleted = 1; 314d18719a4STom Rini for_each_child(node, child) 315d18719a4STom Rini delete_node(child); 316d18719a4STom Rini for_each_property(node, prop) 317d18719a4STom Rini delete_property(prop); 318d18719a4STom Rini delete_labels(&node->labels); 319d18719a4STom Rini } 320d18719a4STom Rini 321d18719a4STom Rini void append_to_property(struct node *node, 322d18719a4STom Rini char *name, const void *data, int len) 323d18719a4STom Rini { 324d18719a4STom Rini struct data d; 325d18719a4STom Rini struct property *p; 326d18719a4STom Rini 327d18719a4STom Rini p = get_property(node, name); 328d18719a4STom Rini if (p) { 329d18719a4STom Rini d = data_append_data(p->val, data, len); 330d18719a4STom Rini p->val = d; 331d18719a4STom Rini } else { 332d18719a4STom Rini d = data_append_data(empty_data, data, len); 333d18719a4STom Rini p = build_property(name, d); 334d18719a4STom Rini add_property(node, p); 335d18719a4STom Rini } 336d18719a4STom Rini } 337d18719a4STom Rini 338d18719a4STom Rini struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) 339d18719a4STom Rini { 340d18719a4STom Rini struct reserve_info *new = xmalloc(sizeof(*new)); 341d18719a4STom Rini 342d18719a4STom Rini memset(new, 0, sizeof(*new)); 343d18719a4STom Rini 344e23ffda2STom Rini new->address = address; 345e23ffda2STom Rini new->size = size; 346d18719a4STom Rini 347d18719a4STom Rini return new; 348d18719a4STom Rini } 349d18719a4STom Rini 350d18719a4STom Rini struct reserve_info *chain_reserve_entry(struct reserve_info *first, 351d18719a4STom Rini struct reserve_info *list) 352d18719a4STom Rini { 353d18719a4STom Rini assert(first->next == NULL); 354d18719a4STom Rini 355d18719a4STom Rini first->next = list; 356d18719a4STom Rini return first; 357d18719a4STom Rini } 358d18719a4STom Rini 359d18719a4STom Rini struct reserve_info *add_reserve_entry(struct reserve_info *list, 360d18719a4STom Rini struct reserve_info *new) 361d18719a4STom Rini { 362d18719a4STom Rini struct reserve_info *last; 363d18719a4STom Rini 364d18719a4STom Rini new->next = NULL; 365d18719a4STom Rini 366d18719a4STom Rini if (! list) 367d18719a4STom Rini return new; 368d18719a4STom Rini 369d18719a4STom Rini for (last = list; last->next; last = last->next) 370d18719a4STom Rini ; 371d18719a4STom Rini 372d18719a4STom Rini last->next = new; 373d18719a4STom Rini 374d18719a4STom Rini return list; 375d18719a4STom Rini } 376d18719a4STom Rini 377d18719a4STom Rini struct dt_info *build_dt_info(unsigned int dtsflags, 378d18719a4STom Rini struct reserve_info *reservelist, 379d18719a4STom Rini struct node *tree, uint32_t boot_cpuid_phys) 380d18719a4STom Rini { 381d18719a4STom Rini struct dt_info *dti; 382d18719a4STom Rini 383d18719a4STom Rini dti = xmalloc(sizeof(*dti)); 384d18719a4STom Rini dti->dtsflags = dtsflags; 385d18719a4STom Rini dti->reservelist = reservelist; 386d18719a4STom Rini dti->dt = tree; 387d18719a4STom Rini dti->boot_cpuid_phys = boot_cpuid_phys; 388d18719a4STom Rini 389d18719a4STom Rini return dti; 390d18719a4STom Rini } 391d18719a4STom Rini 392d18719a4STom Rini /* 393d18719a4STom Rini * Tree accessor functions 394d18719a4STom Rini */ 395d18719a4STom Rini 396d18719a4STom Rini const char *get_unitname(struct node *node) 397d18719a4STom Rini { 398d18719a4STom Rini if (node->name[node->basenamelen] == '\0') 399d18719a4STom Rini return ""; 400d18719a4STom Rini else 401d18719a4STom Rini return node->name + node->basenamelen + 1; 402d18719a4STom Rini } 403d18719a4STom Rini 404d18719a4STom Rini struct property *get_property(struct node *node, const char *propname) 405d18719a4STom Rini { 406d18719a4STom Rini struct property *prop; 407d18719a4STom Rini 408d18719a4STom Rini for_each_property(node, prop) 409d18719a4STom Rini if (streq(prop->name, propname)) 410d18719a4STom Rini return prop; 411d18719a4STom Rini 412d18719a4STom Rini return NULL; 413d18719a4STom Rini } 414d18719a4STom Rini 415d18719a4STom Rini cell_t propval_cell(struct property *prop) 416d18719a4STom Rini { 417d18719a4STom Rini assert(prop->val.len == sizeof(cell_t)); 418e23ffda2STom Rini return fdt32_to_cpu(*((fdt32_t *)prop->val.val)); 419d18719a4STom Rini } 420d18719a4STom Rini 421*14df9b24SMasahiro Yamada cell_t propval_cell_n(struct property *prop, int n) 422*14df9b24SMasahiro Yamada { 423*14df9b24SMasahiro Yamada assert(prop->val.len / sizeof(cell_t) >= n); 424*14df9b24SMasahiro Yamada return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n)); 425*14df9b24SMasahiro Yamada } 426*14df9b24SMasahiro Yamada 427d18719a4STom Rini struct property *get_property_by_label(struct node *tree, const char *label, 428d18719a4STom Rini struct node **node) 429d18719a4STom Rini { 430d18719a4STom Rini struct property *prop; 431d18719a4STom Rini struct node *c; 432d18719a4STom Rini 433d18719a4STom Rini *node = tree; 434d18719a4STom Rini 435d18719a4STom Rini for_each_property(tree, prop) { 436d18719a4STom Rini struct label *l; 437d18719a4STom Rini 438d18719a4STom Rini for_each_label(prop->labels, l) 439d18719a4STom Rini if (streq(l->label, label)) 440d18719a4STom Rini return prop; 441d18719a4STom Rini } 442d18719a4STom Rini 443d18719a4STom Rini for_each_child(tree, c) { 444d18719a4STom Rini prop = get_property_by_label(c, label, node); 445d18719a4STom Rini if (prop) 446d18719a4STom Rini return prop; 447d18719a4STom Rini } 448d18719a4STom Rini 449d18719a4STom Rini *node = NULL; 450d18719a4STom Rini return NULL; 451d18719a4STom Rini } 452d18719a4STom Rini 453d18719a4STom Rini struct marker *get_marker_label(struct node *tree, const char *label, 454d18719a4STom Rini struct node **node, struct property **prop) 455d18719a4STom Rini { 456d18719a4STom Rini struct marker *m; 457d18719a4STom Rini struct property *p; 458d18719a4STom Rini struct node *c; 459d18719a4STom Rini 460d18719a4STom Rini *node = tree; 461d18719a4STom Rini 462d18719a4STom Rini for_each_property(tree, p) { 463d18719a4STom Rini *prop = p; 464d18719a4STom Rini m = p->val.markers; 465d18719a4STom Rini for_each_marker_of_type(m, LABEL) 466d18719a4STom Rini if (streq(m->ref, label)) 467d18719a4STom Rini return m; 468d18719a4STom Rini } 469d18719a4STom Rini 470d18719a4STom Rini for_each_child(tree, c) { 471d18719a4STom Rini m = get_marker_label(c, label, node, prop); 472d18719a4STom Rini if (m) 473d18719a4STom Rini return m; 474d18719a4STom Rini } 475d18719a4STom Rini 476d18719a4STom Rini *prop = NULL; 477d18719a4STom Rini *node = NULL; 478d18719a4STom Rini return NULL; 479d18719a4STom Rini } 480d18719a4STom Rini 481d18719a4STom Rini struct node *get_subnode(struct node *node, const char *nodename) 482d18719a4STom Rini { 483d18719a4STom Rini struct node *child; 484d18719a4STom Rini 485d18719a4STom Rini for_each_child(node, child) 486d18719a4STom Rini if (streq(child->name, nodename)) 487d18719a4STom Rini return child; 488d18719a4STom Rini 489d18719a4STom Rini return NULL; 490d18719a4STom Rini } 491d18719a4STom Rini 492d18719a4STom Rini struct node *get_node_by_path(struct node *tree, const char *path) 493d18719a4STom Rini { 494d18719a4STom Rini const char *p; 495d18719a4STom Rini struct node *child; 496d18719a4STom Rini 497d18719a4STom Rini if (!path || ! (*path)) { 498d18719a4STom Rini if (tree->deleted) 499d18719a4STom Rini return NULL; 500d18719a4STom Rini return tree; 501d18719a4STom Rini } 502d18719a4STom Rini 503d18719a4STom Rini while (path[0] == '/') 504d18719a4STom Rini path++; 505d18719a4STom Rini 506d18719a4STom Rini p = strchr(path, '/'); 507d18719a4STom Rini 508d18719a4STom Rini for_each_child(tree, child) { 509d7857e40STom Rini if (p && (strlen(child->name) == p-path) && 510d7857e40STom Rini strneq(path, child->name, p-path)) 511d18719a4STom Rini return get_node_by_path(child, p+1); 512d18719a4STom Rini else if (!p && streq(path, child->name)) 513d18719a4STom Rini return child; 514d18719a4STom Rini } 515d18719a4STom Rini 516d18719a4STom Rini return NULL; 517d18719a4STom Rini } 518d18719a4STom Rini 519d18719a4STom Rini struct node *get_node_by_label(struct node *tree, const char *label) 520d18719a4STom Rini { 521d18719a4STom Rini struct node *child, *node; 522d18719a4STom Rini struct label *l; 523d18719a4STom Rini 524d18719a4STom Rini assert(label && (strlen(label) > 0)); 525d18719a4STom Rini 526d18719a4STom Rini for_each_label(tree->labels, l) 527d18719a4STom Rini if (streq(l->label, label)) 528d18719a4STom Rini return tree; 529d18719a4STom Rini 530d18719a4STom Rini for_each_child(tree, child) { 531d18719a4STom Rini node = get_node_by_label(child, label); 532d18719a4STom Rini if (node) 533d18719a4STom Rini return node; 534d18719a4STom Rini } 535d18719a4STom Rini 536d18719a4STom Rini return NULL; 537d18719a4STom Rini } 538d18719a4STom Rini 539d18719a4STom Rini struct node *get_node_by_phandle(struct node *tree, cell_t phandle) 540d18719a4STom Rini { 541d18719a4STom Rini struct node *child, *node; 542d18719a4STom Rini 543d18719a4STom Rini assert((phandle != 0) && (phandle != -1)); 544d18719a4STom Rini 545d18719a4STom Rini if (tree->phandle == phandle) { 546d18719a4STom Rini if (tree->deleted) 547d18719a4STom Rini return NULL; 548d18719a4STom Rini return tree; 549d18719a4STom Rini } 550d18719a4STom Rini 551d18719a4STom Rini for_each_child(tree, child) { 552d18719a4STom Rini node = get_node_by_phandle(child, phandle); 553d18719a4STom Rini if (node) 554d18719a4STom Rini return node; 555d18719a4STom Rini } 556d18719a4STom Rini 557d18719a4STom Rini return NULL; 558d18719a4STom Rini } 559d18719a4STom Rini 560d18719a4STom Rini struct node *get_node_by_ref(struct node *tree, const char *ref) 561d18719a4STom Rini { 562d18719a4STom Rini if (streq(ref, "/")) 563d18719a4STom Rini return tree; 564d18719a4STom Rini else if (ref[0] == '/') 565d18719a4STom Rini return get_node_by_path(tree, ref); 566d18719a4STom Rini else 567d18719a4STom Rini return get_node_by_label(tree, ref); 568d18719a4STom Rini } 569d18719a4STom Rini 570d18719a4STom Rini cell_t get_node_phandle(struct node *root, struct node *node) 571d18719a4STom Rini { 572d18719a4STom Rini static cell_t phandle = 1; /* FIXME: ick, static local */ 573d18719a4STom Rini 574d18719a4STom Rini if ((node->phandle != 0) && (node->phandle != -1)) 575d18719a4STom Rini return node->phandle; 576d18719a4STom Rini 577d18719a4STom Rini while (get_node_by_phandle(root, phandle)) 578d18719a4STom Rini phandle++; 579d18719a4STom Rini 580d18719a4STom Rini node->phandle = phandle; 581d18719a4STom Rini 582d18719a4STom Rini if (!get_property(node, "linux,phandle") 583d18719a4STom Rini && (phandle_format & PHANDLE_LEGACY)) 584d18719a4STom Rini add_property(node, 585d18719a4STom Rini build_property("linux,phandle", 586d18719a4STom Rini data_append_cell(empty_data, phandle))); 587d18719a4STom Rini 588d18719a4STom Rini if (!get_property(node, "phandle") 589d18719a4STom Rini && (phandle_format & PHANDLE_EPAPR)) 590d18719a4STom Rini add_property(node, 591d18719a4STom Rini build_property("phandle", 592d18719a4STom Rini data_append_cell(empty_data, phandle))); 593d18719a4STom Rini 594d18719a4STom Rini /* If the node *does* have a phandle property, we must 595d18719a4STom Rini * be dealing with a self-referencing phandle, which will be 596d18719a4STom Rini * fixed up momentarily in the caller */ 597d18719a4STom Rini 598d18719a4STom Rini return node->phandle; 599d18719a4STom Rini } 600d18719a4STom Rini 601d18719a4STom Rini uint32_t guess_boot_cpuid(struct node *tree) 602d18719a4STom Rini { 603d18719a4STom Rini struct node *cpus, *bootcpu; 604d18719a4STom Rini struct property *reg; 605d18719a4STom Rini 606d18719a4STom Rini cpus = get_node_by_path(tree, "/cpus"); 607d18719a4STom Rini if (!cpus) 608d18719a4STom Rini return 0; 609d18719a4STom Rini 610d18719a4STom Rini 611d18719a4STom Rini bootcpu = cpus->children; 612d18719a4STom Rini if (!bootcpu) 613d18719a4STom Rini return 0; 614d18719a4STom Rini 615d18719a4STom Rini reg = get_property(bootcpu, "reg"); 616d18719a4STom Rini if (!reg || (reg->val.len != sizeof(uint32_t))) 617d18719a4STom Rini return 0; 618d18719a4STom Rini 619d18719a4STom Rini /* FIXME: Sanity check node? */ 620d18719a4STom Rini 621d18719a4STom Rini return propval_cell(reg); 622d18719a4STom Rini } 623d18719a4STom Rini 624d18719a4STom Rini static int cmp_reserve_info(const void *ax, const void *bx) 625d18719a4STom Rini { 626d18719a4STom Rini const struct reserve_info *a, *b; 627d18719a4STom Rini 628d18719a4STom Rini a = *((const struct reserve_info * const *)ax); 629d18719a4STom Rini b = *((const struct reserve_info * const *)bx); 630d18719a4STom Rini 631e23ffda2STom Rini if (a->address < b->address) 632d18719a4STom Rini return -1; 633e23ffda2STom Rini else if (a->address > b->address) 634d18719a4STom Rini return 1; 635e23ffda2STom Rini else if (a->size < b->size) 636d18719a4STom Rini return -1; 637e23ffda2STom Rini else if (a->size > b->size) 638d18719a4STom Rini return 1; 639d18719a4STom Rini else 640d18719a4STom Rini return 0; 641d18719a4STom Rini } 642d18719a4STom Rini 643d18719a4STom Rini static void sort_reserve_entries(struct dt_info *dti) 644d18719a4STom Rini { 645d18719a4STom Rini struct reserve_info *ri, **tbl; 646d18719a4STom Rini int n = 0, i = 0; 647d18719a4STom Rini 648d18719a4STom Rini for (ri = dti->reservelist; 649d18719a4STom Rini ri; 650d18719a4STom Rini ri = ri->next) 651d18719a4STom Rini n++; 652d18719a4STom Rini 653d18719a4STom Rini if (n == 0) 654d18719a4STom Rini return; 655d18719a4STom Rini 656d18719a4STom Rini tbl = xmalloc(n * sizeof(*tbl)); 657d18719a4STom Rini 658d18719a4STom Rini for (ri = dti->reservelist; 659d18719a4STom Rini ri; 660d18719a4STom Rini ri = ri->next) 661d18719a4STom Rini tbl[i++] = ri; 662d18719a4STom Rini 663d18719a4STom Rini qsort(tbl, n, sizeof(*tbl), cmp_reserve_info); 664d18719a4STom Rini 665d18719a4STom Rini dti->reservelist = tbl[0]; 666d18719a4STom Rini for (i = 0; i < (n-1); i++) 667d18719a4STom Rini tbl[i]->next = tbl[i+1]; 668d18719a4STom Rini tbl[n-1]->next = NULL; 669d18719a4STom Rini 670d18719a4STom Rini free(tbl); 671d18719a4STom Rini } 672d18719a4STom Rini 673d18719a4STom Rini static int cmp_prop(const void *ax, const void *bx) 674d18719a4STom Rini { 675d18719a4STom Rini const struct property *a, *b; 676d18719a4STom Rini 677d18719a4STom Rini a = *((const struct property * const *)ax); 678d18719a4STom Rini b = *((const struct property * const *)bx); 679d18719a4STom Rini 680d18719a4STom Rini return strcmp(a->name, b->name); 681d18719a4STom Rini } 682d18719a4STom Rini 683d18719a4STom Rini static void sort_properties(struct node *node) 684d18719a4STom Rini { 685d18719a4STom Rini int n = 0, i = 0; 686d18719a4STom Rini struct property *prop, **tbl; 687d18719a4STom Rini 688d18719a4STom Rini for_each_property_withdel(node, prop) 689d18719a4STom Rini n++; 690d18719a4STom Rini 691d18719a4STom Rini if (n == 0) 692d18719a4STom Rini return; 693d18719a4STom Rini 694d18719a4STom Rini tbl = xmalloc(n * sizeof(*tbl)); 695d18719a4STom Rini 696d18719a4STom Rini for_each_property_withdel(node, prop) 697d18719a4STom Rini tbl[i++] = prop; 698d18719a4STom Rini 699d18719a4STom Rini qsort(tbl, n, sizeof(*tbl), cmp_prop); 700d18719a4STom Rini 701d18719a4STom Rini node->proplist = tbl[0]; 702d18719a4STom Rini for (i = 0; i < (n-1); i++) 703d18719a4STom Rini tbl[i]->next = tbl[i+1]; 704d18719a4STom Rini tbl[n-1]->next = NULL; 705d18719a4STom Rini 706d18719a4STom Rini free(tbl); 707d18719a4STom Rini } 708d18719a4STom Rini 709d18719a4STom Rini static int cmp_subnode(const void *ax, const void *bx) 710d18719a4STom Rini { 711d18719a4STom Rini const struct node *a, *b; 712d18719a4STom Rini 713d18719a4STom Rini a = *((const struct node * const *)ax); 714d18719a4STom Rini b = *((const struct node * const *)bx); 715d18719a4STom Rini 716d18719a4STom Rini return strcmp(a->name, b->name); 717d18719a4STom Rini } 718d18719a4STom Rini 719d18719a4STom Rini static void sort_subnodes(struct node *node) 720d18719a4STom Rini { 721d18719a4STom Rini int n = 0, i = 0; 722d18719a4STom Rini struct node *subnode, **tbl; 723d18719a4STom Rini 724d18719a4STom Rini for_each_child_withdel(node, subnode) 725d18719a4STom Rini n++; 726d18719a4STom Rini 727d18719a4STom Rini if (n == 0) 728d18719a4STom Rini return; 729d18719a4STom Rini 730d18719a4STom Rini tbl = xmalloc(n * sizeof(*tbl)); 731d18719a4STom Rini 732d18719a4STom Rini for_each_child_withdel(node, subnode) 733d18719a4STom Rini tbl[i++] = subnode; 734d18719a4STom Rini 735d18719a4STom Rini qsort(tbl, n, sizeof(*tbl), cmp_subnode); 736d18719a4STom Rini 737d18719a4STom Rini node->children = tbl[0]; 738d18719a4STom Rini for (i = 0; i < (n-1); i++) 739d18719a4STom Rini tbl[i]->next_sibling = tbl[i+1]; 740d18719a4STom Rini tbl[n-1]->next_sibling = NULL; 741d18719a4STom Rini 742d18719a4STom Rini free(tbl); 743d18719a4STom Rini } 744d18719a4STom Rini 745d18719a4STom Rini static void sort_node(struct node *node) 746d18719a4STom Rini { 747d18719a4STom Rini struct node *c; 748d18719a4STom Rini 749d18719a4STom Rini sort_properties(node); 750d18719a4STom Rini sort_subnodes(node); 751d18719a4STom Rini for_each_child_withdel(node, c) 752d18719a4STom Rini sort_node(c); 753d18719a4STom Rini } 754d18719a4STom Rini 755d18719a4STom Rini void sort_tree(struct dt_info *dti) 756d18719a4STom Rini { 757d18719a4STom Rini sort_reserve_entries(dti); 758d18719a4STom Rini sort_node(dti->dt); 759d18719a4STom Rini } 760d18719a4STom Rini 761d18719a4STom Rini /* utility helper to avoid code duplication */ 762d18719a4STom Rini static struct node *build_and_name_child_node(struct node *parent, char *name) 763d18719a4STom Rini { 764d18719a4STom Rini struct node *node; 765d18719a4STom Rini 766d18719a4STom Rini node = build_node(NULL, NULL); 767d18719a4STom Rini name_node(node, xstrdup(name)); 768d18719a4STom Rini add_child(parent, node); 769d18719a4STom Rini 770d18719a4STom Rini return node; 771d18719a4STom Rini } 772d18719a4STom Rini 773d18719a4STom Rini static struct node *build_root_node(struct node *dt, char *name) 774d18719a4STom Rini { 775d18719a4STom Rini struct node *an; 776d18719a4STom Rini 777d18719a4STom Rini an = get_subnode(dt, name); 778d18719a4STom Rini if (!an) 779d18719a4STom Rini an = build_and_name_child_node(dt, name); 780d18719a4STom Rini 781d18719a4STom Rini if (!an) 782d18719a4STom Rini die("Could not build root node /%s\n", name); 783d18719a4STom Rini 784d18719a4STom Rini return an; 785d18719a4STom Rini } 786d18719a4STom Rini 787d18719a4STom Rini static bool any_label_tree(struct dt_info *dti, struct node *node) 788d18719a4STom Rini { 789d18719a4STom Rini struct node *c; 790d18719a4STom Rini 791d18719a4STom Rini if (node->labels) 792d18719a4STom Rini return true; 793d18719a4STom Rini 794d18719a4STom Rini for_each_child(node, c) 795d18719a4STom Rini if (any_label_tree(dti, c)) 796d18719a4STom Rini return true; 797d18719a4STom Rini 798d18719a4STom Rini return false; 799d18719a4STom Rini } 800d18719a4STom Rini 801d18719a4STom Rini static void generate_label_tree_internal(struct dt_info *dti, 802d18719a4STom Rini struct node *an, struct node *node, 803d18719a4STom Rini bool allocph) 804d18719a4STom Rini { 805d18719a4STom Rini struct node *dt = dti->dt; 806d18719a4STom Rini struct node *c; 807d18719a4STom Rini struct property *p; 808d18719a4STom Rini struct label *l; 809d18719a4STom Rini 810d18719a4STom Rini /* if there are labels */ 811d18719a4STom Rini if (node->labels) { 812d18719a4STom Rini 813d18719a4STom Rini /* now add the label in the node */ 814d18719a4STom Rini for_each_label(node->labels, l) { 815d18719a4STom Rini 816d18719a4STom Rini /* check whether the label already exists */ 817d18719a4STom Rini p = get_property(an, l->label); 818d18719a4STom Rini if (p) { 819d18719a4STom Rini fprintf(stderr, "WARNING: label %s already" 820d18719a4STom Rini " exists in /%s", l->label, 821d18719a4STom Rini an->name); 822d18719a4STom Rini continue; 823d18719a4STom Rini } 824d18719a4STom Rini 825d18719a4STom Rini /* insert it */ 826d18719a4STom Rini p = build_property(l->label, 827d18719a4STom Rini data_copy_mem(node->fullpath, 828d18719a4STom Rini strlen(node->fullpath) + 1)); 829d18719a4STom Rini add_property(an, p); 830d18719a4STom Rini } 831d18719a4STom Rini 832d18719a4STom Rini /* force allocation of a phandle for this node */ 833d18719a4STom Rini if (allocph) 834d18719a4STom Rini (void)get_node_phandle(dt, node); 835d18719a4STom Rini } 836d18719a4STom Rini 837d18719a4STom Rini for_each_child(node, c) 838d18719a4STom Rini generate_label_tree_internal(dti, an, c, allocph); 839d18719a4STom Rini } 840d18719a4STom Rini 841d18719a4STom Rini static bool any_fixup_tree(struct dt_info *dti, struct node *node) 842d18719a4STom Rini { 843d18719a4STom Rini struct node *c; 844d18719a4STom Rini struct property *prop; 845d18719a4STom Rini struct marker *m; 846d18719a4STom Rini 847d18719a4STom Rini for_each_property(node, prop) { 848d18719a4STom Rini m = prop->val.markers; 849d18719a4STom Rini for_each_marker_of_type(m, REF_PHANDLE) { 850d18719a4STom Rini if (!get_node_by_ref(dti->dt, m->ref)) 851d18719a4STom Rini return true; 852d18719a4STom Rini } 853d18719a4STom Rini } 854d18719a4STom Rini 855d18719a4STom Rini for_each_child(node, c) { 856d18719a4STom Rini if (any_fixup_tree(dti, c)) 857d18719a4STom Rini return true; 858d18719a4STom Rini } 859d18719a4STom Rini 860d18719a4STom Rini return false; 861d18719a4STom Rini } 862d18719a4STom Rini 863d18719a4STom Rini static void add_fixup_entry(struct dt_info *dti, struct node *fn, 864d18719a4STom Rini struct node *node, struct property *prop, 865d18719a4STom Rini struct marker *m) 866d18719a4STom Rini { 867d18719a4STom Rini char *entry; 868d18719a4STom Rini 869d18719a4STom Rini /* m->ref can only be a REF_PHANDLE, but check anyway */ 870d18719a4STom Rini assert(m->type == REF_PHANDLE); 871d18719a4STom Rini 872d18719a4STom Rini /* there shouldn't be any ':' in the arguments */ 873d18719a4STom Rini if (strchr(node->fullpath, ':') || strchr(prop->name, ':')) 874d18719a4STom Rini die("arguments should not contain ':'\n"); 875d18719a4STom Rini 876d18719a4STom Rini xasprintf(&entry, "%s:%s:%u", 877d18719a4STom Rini node->fullpath, prop->name, m->offset); 878d18719a4STom Rini append_to_property(fn, m->ref, entry, strlen(entry) + 1); 879d18719a4STom Rini 880d18719a4STom Rini free(entry); 881d18719a4STom Rini } 882d18719a4STom Rini 883d18719a4STom Rini static void generate_fixups_tree_internal(struct dt_info *dti, 884d18719a4STom Rini struct node *fn, 885d18719a4STom Rini struct node *node) 886d18719a4STom Rini { 887d18719a4STom Rini struct node *dt = dti->dt; 888d18719a4STom Rini struct node *c; 889d18719a4STom Rini struct property *prop; 890d18719a4STom Rini struct marker *m; 891d18719a4STom Rini struct node *refnode; 892d18719a4STom Rini 893d18719a4STom Rini for_each_property(node, prop) { 894d18719a4STom Rini m = prop->val.markers; 895d18719a4STom Rini for_each_marker_of_type(m, REF_PHANDLE) { 896d18719a4STom Rini refnode = get_node_by_ref(dt, m->ref); 897d18719a4STom Rini if (!refnode) 898d18719a4STom Rini add_fixup_entry(dti, fn, node, prop, m); 899d18719a4STom Rini } 900d18719a4STom Rini } 901d18719a4STom Rini 902d18719a4STom Rini for_each_child(node, c) 903d18719a4STom Rini generate_fixups_tree_internal(dti, fn, c); 904d18719a4STom Rini } 905d18719a4STom Rini 906d18719a4STom Rini static bool any_local_fixup_tree(struct dt_info *dti, struct node *node) 907d18719a4STom Rini { 908d18719a4STom Rini struct node *c; 909d18719a4STom Rini struct property *prop; 910d18719a4STom Rini struct marker *m; 911d18719a4STom Rini 912d18719a4STom Rini for_each_property(node, prop) { 913d18719a4STom Rini m = prop->val.markers; 914d18719a4STom Rini for_each_marker_of_type(m, REF_PHANDLE) { 915d18719a4STom Rini if (get_node_by_ref(dti->dt, m->ref)) 916d18719a4STom Rini return true; 917d18719a4STom Rini } 918d18719a4STom Rini } 919d18719a4STom Rini 920d18719a4STom Rini for_each_child(node, c) { 921d18719a4STom Rini if (any_local_fixup_tree(dti, c)) 922d18719a4STom Rini return true; 923d18719a4STom Rini } 924d18719a4STom Rini 925d18719a4STom Rini return false; 926d18719a4STom Rini } 927d18719a4STom Rini 928d18719a4STom Rini static void add_local_fixup_entry(struct dt_info *dti, 929d18719a4STom Rini struct node *lfn, struct node *node, 930d18719a4STom Rini struct property *prop, struct marker *m, 931d18719a4STom Rini struct node *refnode) 932d18719a4STom Rini { 933d18719a4STom Rini struct node *wn, *nwn; /* local fixup node, walk node, new */ 934e23ffda2STom Rini fdt32_t value_32; 935d18719a4STom Rini char **compp; 936d18719a4STom Rini int i, depth; 937d18719a4STom Rini 938d18719a4STom Rini /* walk back retreiving depth */ 939d18719a4STom Rini depth = 0; 940d18719a4STom Rini for (wn = node; wn; wn = wn->parent) 941d18719a4STom Rini depth++; 942d18719a4STom Rini 943d18719a4STom Rini /* allocate name array */ 944d18719a4STom Rini compp = xmalloc(sizeof(*compp) * depth); 945d18719a4STom Rini 946d18719a4STom Rini /* store names in the array */ 947d18719a4STom Rini for (wn = node, i = depth - 1; wn; wn = wn->parent, i--) 948d18719a4STom Rini compp[i] = wn->name; 949d18719a4STom Rini 950d18719a4STom Rini /* walk the path components creating nodes if they don't exist */ 951d18719a4STom Rini for (wn = lfn, i = 1; i < depth; i++, wn = nwn) { 952d18719a4STom Rini /* if no node exists, create it */ 953d18719a4STom Rini nwn = get_subnode(wn, compp[i]); 954d18719a4STom Rini if (!nwn) 955d18719a4STom Rini nwn = build_and_name_child_node(wn, compp[i]); 956d18719a4STom Rini } 957d18719a4STom Rini 958d18719a4STom Rini free(compp); 959d18719a4STom Rini 960d18719a4STom Rini value_32 = cpu_to_fdt32(m->offset); 961d18719a4STom Rini append_to_property(wn, prop->name, &value_32, sizeof(value_32)); 962d18719a4STom Rini } 963d18719a4STom Rini 964d18719a4STom Rini static void generate_local_fixups_tree_internal(struct dt_info *dti, 965d18719a4STom Rini struct node *lfn, 966d18719a4STom Rini struct node *node) 967d18719a4STom Rini { 968d18719a4STom Rini struct node *dt = dti->dt; 969d18719a4STom Rini struct node *c; 970d18719a4STom Rini struct property *prop; 971d18719a4STom Rini struct marker *m; 972d18719a4STom Rini struct node *refnode; 973d18719a4STom Rini 974d18719a4STom Rini for_each_property(node, prop) { 975d18719a4STom Rini m = prop->val.markers; 976d18719a4STom Rini for_each_marker_of_type(m, REF_PHANDLE) { 977d18719a4STom Rini refnode = get_node_by_ref(dt, m->ref); 978d18719a4STom Rini if (refnode) 979d18719a4STom Rini add_local_fixup_entry(dti, lfn, node, prop, m, refnode); 980d18719a4STom Rini } 981d18719a4STom Rini } 982d18719a4STom Rini 983d18719a4STom Rini for_each_child(node, c) 984d18719a4STom Rini generate_local_fixups_tree_internal(dti, lfn, c); 985d18719a4STom Rini } 986d18719a4STom Rini 987d18719a4STom Rini void generate_label_tree(struct dt_info *dti, char *name, bool allocph) 988d18719a4STom Rini { 989d18719a4STom Rini if (!any_label_tree(dti, dti->dt)) 990d18719a4STom Rini return; 991d18719a4STom Rini generate_label_tree_internal(dti, build_root_node(dti->dt, name), 992d18719a4STom Rini dti->dt, allocph); 993d18719a4STom Rini } 994d18719a4STom Rini 995d18719a4STom Rini void generate_fixups_tree(struct dt_info *dti, char *name) 996d18719a4STom Rini { 997d18719a4STom Rini if (!any_fixup_tree(dti, dti->dt)) 998d18719a4STom Rini return; 999d18719a4STom Rini generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), 1000d18719a4STom Rini dti->dt); 1001d18719a4STom Rini } 1002d18719a4STom Rini 1003d18719a4STom Rini void generate_local_fixups_tree(struct dt_info *dti, char *name) 1004d18719a4STom Rini { 1005d18719a4STom Rini if (!any_local_fixup_tree(dti, dti->dt)) 1006d18719a4STom Rini return; 1007d18719a4STom Rini generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), 1008d18719a4STom Rini dti->dt); 1009d18719a4STom Rini } 1010