livetree.c (204488) | livetree.c (238742) |
---|---|
1/* 2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 3 * 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of the 8 * License, or (at your option) any later version. --- 10 unchanged lines hidden (view full) --- 19 */ 20 21#include "dtc.h" 22 23/* 24 * Tree building functions 25 */ 26 | 1/* 2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 3 * 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of the 8 * License, or (at your option) any later version. --- 10 unchanged lines hidden (view full) --- 19 */ 20 21#include "dtc.h" 22 23/* 24 * Tree building functions 25 */ 26 |
27struct property *build_property(char *name, struct data val, char *label) | 27void add_label(struct label **labels, char *label) |
28{ | 28{ |
29 struct label *new; 30 31 /* Make sure the label isn't already there */ 32 for_each_label(*labels, new) 33 if (streq(new->label, label)) 34 return; 35 36 new = xmalloc(sizeof(*new)); 37 new->label = label; 38 new->next = *labels; 39 *labels = new; 40} 41 42struct property *build_property(char *name, struct data val) 43{ |
|
29 struct property *new = xmalloc(sizeof(*new)); 30 | 44 struct property *new = xmalloc(sizeof(*new)); 45 |
46 memset(new, 0, sizeof(*new)); 47 |
|
31 new->name = name; 32 new->val = val; 33 | 48 new->name = name; 49 new->val = val; 50 |
34 new->next = NULL; 35 36 new->label = label; 37 | |
38 return new; 39} 40 41struct property *chain_property(struct property *first, struct property *list) 42{ 43 assert(first->next == NULL); 44 45 first->next = list; --- 27 unchanged lines hidden (view full) --- 73 74 for_each_child(new, child) { 75 child->parent = new; 76 } 77 78 return new; 79} 80 | 51 return new; 52} 53 54struct property *chain_property(struct property *first, struct property *list) 55{ 56 assert(first->next == NULL); 57 58 first->next = list; --- 27 unchanged lines hidden (view full) --- 86 87 for_each_child(new, child) { 88 child->parent = new; 89 } 90 91 return new; 92} 93 |
81struct node *name_node(struct node *node, char *name, char * label) | 94struct node *name_node(struct node *node, char *name) |
82{ 83 assert(node->name == NULL); 84 85 node->name = name; 86 | 95{ 96 assert(node->name == NULL); 97 98 node->name = name; 99 |
87 node->label = label; 88 | |
89 return node; 90} 91 | 100 return node; 101} 102 |
103struct node *merge_nodes(struct node *old_node, struct node *new_node) 104{ 105 struct property *new_prop, *old_prop; 106 struct node *new_child, *old_child; 107 struct label *l; 108 109 /* Add new node labels to old node */ 110 for_each_label(new_node->labels, l) 111 add_label(&old_node->labels, l->label); 112 113 /* Move properties from the new node to the old node. If there 114 * is a collision, replace the old value with the new */ 115 while (new_node->proplist) { 116 /* Pop the property off the list */ 117 new_prop = new_node->proplist; 118 new_node->proplist = new_prop->next; 119 new_prop->next = NULL; 120 121 /* Look for a collision, set new value if there is */ 122 for_each_property(old_node, old_prop) { 123 if (streq(old_prop->name, new_prop->name)) { 124 /* Add new labels to old property */ 125 for_each_label(new_prop->labels, l) 126 add_label(&old_prop->labels, l->label); 127 128 old_prop->val = new_prop->val; 129 free(new_prop); 130 new_prop = NULL; 131 break; 132 } 133 } 134 135 /* if no collision occurred, add property to the old node. */ 136 if (new_prop) 137 add_property(old_node, new_prop); 138 } 139 140 /* Move the override child nodes into the primary node. If 141 * there is a collision, then merge the nodes. */ 142 while (new_node->children) { 143 /* Pop the child node off the list */ 144 new_child = new_node->children; 145 new_node->children = new_child->next_sibling; 146 new_child->parent = NULL; 147 new_child->next_sibling = NULL; 148 149 /* Search for a collision. Merge if there is */ 150 for_each_child(old_node, old_child) { 151 if (streq(old_child->name, new_child->name)) { 152 merge_nodes(old_child, new_child); 153 new_child = NULL; 154 break; 155 } 156 } 157 158 /* if no collision occured, add child to the old node. */ 159 if (new_child) 160 add_child(old_node, new_child); 161 } 162 163 /* The new node contents are now merged into the old node. Free 164 * the new node. */ 165 free(new_node); 166 167 return old_node; 168} 169 |
|
92struct node *chain_node(struct node *first, struct node *list) 93{ 94 assert(first->next_sibling == NULL); 95 96 first->next_sibling = list; 97 return first; 98} 99 --- 19 unchanged lines hidden (view full) --- 119 120 p = &parent->children; 121 while (*p) 122 p = &((*p)->next_sibling); 123 124 *p = child; 125} 126 | 170struct node *chain_node(struct node *first, struct node *list) 171{ 172 assert(first->next_sibling == NULL); 173 174 first->next_sibling = list; 175 return first; 176} 177 --- 19 unchanged lines hidden (view full) --- 197 198 p = &parent->children; 199 while (*p) 200 p = &((*p)->next_sibling); 201 202 *p = child; 203} 204 |
127struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size, 128 char *label) | 205struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) |
129{ 130 struct reserve_info *new = xmalloc(sizeof(*new)); 131 | 206{ 207 struct reserve_info *new = xmalloc(sizeof(*new)); 208 |
209 memset(new, 0, sizeof(*new)); 210 |
|
132 new->re.address = address; 133 new->re.size = size; 134 | 211 new->re.address = address; 212 new->re.size = size; 213 |
135 new->next = NULL; 136 137 new->label = label; 138 | |
139 return new; 140} 141 142struct reserve_info *chain_reserve_entry(struct reserve_info *first, 143 struct reserve_info *list) 144{ 145 assert(first->next == NULL); 146 --- 56 unchanged lines hidden (view full) --- 203} 204 205cell_t propval_cell(struct property *prop) 206{ 207 assert(prop->val.len == sizeof(cell_t)); 208 return fdt32_to_cpu(*((cell_t *)prop->val.val)); 209} 210 | 214 return new; 215} 216 217struct reserve_info *chain_reserve_entry(struct reserve_info *first, 218 struct reserve_info *list) 219{ 220 assert(first->next == NULL); 221 --- 56 unchanged lines hidden (view full) --- 278} 279 280cell_t propval_cell(struct property *prop) 281{ 282 assert(prop->val.len == sizeof(cell_t)); 283 return fdt32_to_cpu(*((cell_t *)prop->val.val)); 284} 285 |
286struct property *get_property_by_label(struct node *tree, const char *label, 287 struct node **node) 288{ 289 struct property *prop; 290 struct node *c; 291 292 *node = tree; 293 294 for_each_property(tree, prop) { 295 struct label *l; 296 297 for_each_label(prop->labels, l) 298 if (streq(l->label, label)) 299 return prop; 300 } 301 302 for_each_child(tree, c) { 303 prop = get_property_by_label(c, label, node); 304 if (prop) 305 return prop; 306 } 307 308 *node = NULL; 309 return NULL; 310} 311 312struct marker *get_marker_label(struct node *tree, const char *label, 313 struct node **node, struct property **prop) 314{ 315 struct marker *m; 316 struct property *p; 317 struct node *c; 318 319 *node = tree; 320 321 for_each_property(tree, p) { 322 *prop = p; 323 m = p->val.markers; 324 for_each_marker_of_type(m, LABEL) 325 if (streq(m->ref, label)) 326 return m; 327 } 328 329 for_each_child(tree, c) { 330 m = get_marker_label(c, label, node, prop); 331 if (m) 332 return m; 333 } 334 335 *prop = NULL; 336 *node = NULL; 337 return NULL; 338} 339 |
|
211struct node *get_subnode(struct node *node, const char *nodename) 212{ 213 struct node *child; 214 215 for_each_child(node, child) 216 if (streq(child->name, nodename)) 217 return child; 218 --- 21 unchanged lines hidden (view full) --- 240 } 241 242 return NULL; 243} 244 245struct node *get_node_by_label(struct node *tree, const char *label) 246{ 247 struct node *child, *node; | 340struct node *get_subnode(struct node *node, const char *nodename) 341{ 342 struct node *child; 343 344 for_each_child(node, child) 345 if (streq(child->name, nodename)) 346 return child; 347 --- 21 unchanged lines hidden (view full) --- 369 } 370 371 return NULL; 372} 373 374struct node *get_node_by_label(struct node *tree, const char *label) 375{ 376 struct node *child, *node; |
377 struct label *l; |
|
248 249 assert(label && (strlen(label) > 0)); 250 | 378 379 assert(label && (strlen(label) > 0)); 380 |
251 if (tree->label && streq(tree->label, label)) 252 return tree; | 381 for_each_label(tree->labels, l) 382 if (streq(l->label, label)) 383 return tree; |
253 254 for_each_child(tree, child) { 255 node = get_node_by_label(child, label); 256 if (node) 257 return node; 258 } 259 260 return NULL; --- 36 unchanged lines hidden (view full) --- 297 phandle++; 298 299 node->phandle = phandle; 300 301 if (!get_property(node, "linux,phandle") 302 && (phandle_format & PHANDLE_LEGACY)) 303 add_property(node, 304 build_property("linux,phandle", | 384 385 for_each_child(tree, child) { 386 node = get_node_by_label(child, label); 387 if (node) 388 return node; 389 } 390 391 return NULL; --- 36 unchanged lines hidden (view full) --- 428 phandle++; 429 430 node->phandle = phandle; 431 432 if (!get_property(node, "linux,phandle") 433 && (phandle_format & PHANDLE_LEGACY)) 434 add_property(node, 435 build_property("linux,phandle", |
305 data_append_cell(empty_data, phandle), 306 NULL)); | 436 data_append_cell(empty_data, phandle))); |
307 308 if (!get_property(node, "phandle") 309 && (phandle_format & PHANDLE_EPAPR)) 310 add_property(node, 311 build_property("phandle", | 437 438 if (!get_property(node, "phandle") 439 && (phandle_format & PHANDLE_EPAPR)) 440 add_property(node, 441 build_property("phandle", |
312 data_append_cell(empty_data, phandle), 313 NULL)); | 442 data_append_cell(empty_data, phandle))); |
314 315 /* If the node *does* have a phandle property, we must 316 * be dealing with a self-referencing phandle, which will be 317 * fixed up momentarily in the caller */ 318 319 return node->phandle; 320} | 443 444 /* If the node *does* have a phandle property, we must 445 * be dealing with a self-referencing phandle, which will be 446 * fixed up momentarily in the caller */ 447 448 return node->phandle; 449} |
450 451uint32_t guess_boot_cpuid(struct node *tree) 452{ 453 struct node *cpus, *bootcpu; 454 struct property *reg; 455 456 cpus = get_node_by_path(tree, "/cpus"); 457 if (!cpus) 458 return 0; 459 460 461 bootcpu = cpus->children; 462 if (!bootcpu) 463 return 0; 464 465 reg = get_property(bootcpu, "reg"); 466 if (!reg || (reg->val.len != sizeof(uint32_t))) 467 return 0; 468 469 /* FIXME: Sanity check node? */ 470 471 return propval_cell(reg); 472} 473 474static int cmp_reserve_info(const void *ax, const void *bx) 475{ 476 const struct reserve_info *a, *b; 477 478 a = *((const struct reserve_info * const *)ax); 479 b = *((const struct reserve_info * const *)bx); 480 481 if (a->re.address < b->re.address) 482 return -1; 483 else if (a->re.address > b->re.address) 484 return 1; 485 else if (a->re.size < b->re.size) 486 return -1; 487 else if (a->re.size > b->re.size) 488 return 1; 489 else 490 return 0; 491} 492 493static void sort_reserve_entries(struct boot_info *bi) 494{ 495 struct reserve_info *ri, **tbl; 496 int n = 0, i = 0; 497 498 for (ri = bi->reservelist; 499 ri; 500 ri = ri->next) 501 n++; 502 503 if (n == 0) 504 return; 505 506 tbl = xmalloc(n * sizeof(*tbl)); 507 508 for (ri = bi->reservelist; 509 ri; 510 ri = ri->next) 511 tbl[i++] = ri; 512 513 qsort(tbl, n, sizeof(*tbl), cmp_reserve_info); 514 515 bi->reservelist = tbl[0]; 516 for (i = 0; i < (n-1); i++) 517 tbl[i]->next = tbl[i+1]; 518 tbl[n-1]->next = NULL; 519 520 free(tbl); 521} 522 523static int cmp_prop(const void *ax, const void *bx) 524{ 525 const struct property *a, *b; 526 527 a = *((const struct property * const *)ax); 528 b = *((const struct property * const *)bx); 529 530 return strcmp(a->name, b->name); 531} 532 533static void sort_properties(struct node *node) 534{ 535 int n = 0, i = 0; 536 struct property *prop, **tbl; 537 538 for_each_property(node, prop) 539 n++; 540 541 if (n == 0) 542 return; 543 544 tbl = xmalloc(n * sizeof(*tbl)); 545 546 for_each_property(node, prop) 547 tbl[i++] = prop; 548 549 qsort(tbl, n, sizeof(*tbl), cmp_prop); 550 551 node->proplist = tbl[0]; 552 for (i = 0; i < (n-1); i++) 553 tbl[i]->next = tbl[i+1]; 554 tbl[n-1]->next = NULL; 555 556 free(tbl); 557} 558 559static int cmp_subnode(const void *ax, const void *bx) 560{ 561 const struct node *a, *b; 562 563 a = *((const struct node * const *)ax); 564 b = *((const struct node * const *)bx); 565 566 return strcmp(a->name, b->name); 567} 568 569static void sort_subnodes(struct node *node) 570{ 571 int n = 0, i = 0; 572 struct node *subnode, **tbl; 573 574 for_each_child(node, subnode) 575 n++; 576 577 if (n == 0) 578 return; 579 580 tbl = xmalloc(n * sizeof(*tbl)); 581 582 for_each_child(node, subnode) 583 tbl[i++] = subnode; 584 585 qsort(tbl, n, sizeof(*tbl), cmp_subnode); 586 587 node->children = tbl[0]; 588 for (i = 0; i < (n-1); i++) 589 tbl[i]->next_sibling = tbl[i+1]; 590 tbl[n-1]->next_sibling = NULL; 591 592 free(tbl); 593} 594 595static void sort_node(struct node *node) 596{ 597 struct node *c; 598 599 sort_properties(node); 600 sort_subnodes(node); 601 for_each_child(node, c) 602 sort_node(c); 603} 604 605void sort_tree(struct boot_info *bi) 606{ 607 sort_reserve_entries(bi); 608 sort_node(bi->dt); 609} |
|