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