aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/dtc/livetree.c
diff options
context:
space:
mode:
authorJohn Bonesio <bones@secretlab.ca>2010-11-17 18:28:20 -0500
committerGrant Likely <grant.likely@secretlab.ca>2011-01-03 18:02:49 -0500
commit658f29a51e9830e620bb9a1ce3534b318a38bfeb (patch)
treee6cc7cd9b9e17d97308619fd8516b77bcc038114 /scripts/dtc/livetree.c
parentcd1e65044d4473cca9a01bae7b7938f065044a4b (diff)
of/flattree: Update dtc to current mainline.
Pull in recent changes from the main dtc repository. These changes primarily allow multiple device trees to be declared which are merged by dtc. This feature allows us to include a basic dts file and then provide more information for the specific system through the merging functionality. Changes pulled from git://git.jdl.com/software/dtc.git commit id: 37c0b6a0, "dtc: Add code to make diffing trees easier" Signed-off-by: John Bonesio <bones@secretlab.ca> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'scripts/dtc/livetree.c')
-rw-r--r--scripts/dtc/livetree.c345
1 files changed, 323 insertions, 22 deletions
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index 0ca3de550b3f..c9209d5c999e 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -24,17 +24,30 @@
24 * Tree building functions 24 * Tree building functions
25 */ 25 */
26 26
27struct property *build_property(char *name, struct data val, char *label) 27void add_label(struct label **labels, char *label)
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)
28{ 43{
29 struct property *new = xmalloc(sizeof(*new)); 44 struct property *new = xmalloc(sizeof(*new));
30 45
46 memset(new, 0, sizeof(*new));
47
31 new->name = name; 48 new->name = name;
32 new->val = val; 49 new->val = val;
33 50
34 new->next = NULL;
35
36 new->label = label;
37
38 return new; 51 return new;
39} 52}
40 53
@@ -78,17 +91,82 @@ struct node *build_node(struct property *proplist, struct node *children)
78 return new; 91 return new;
79} 92}
80 93
81struct node *name_node(struct node *node, char *name, char * label) 94struct node *name_node(struct node *node, char *name)
82{ 95{
83 assert(node->name == NULL); 96 assert(node->name == NULL);
84 97
85 node->name = name; 98 node->name = name;
86 99
87 node->label = label;
88
89 return node; 100 return node;
90} 101}
91 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) 170struct node *chain_node(struct node *first, struct node *list)
93{ 171{
94 assert(first->next_sibling == NULL); 172 assert(first->next_sibling == NULL);
@@ -124,18 +202,15 @@ void add_child(struct node *parent, struct node *child)
124 *p = child; 202 *p = child;
125} 203}
126 204
127struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size, 205struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
128 char *label)
129{ 206{
130 struct reserve_info *new = xmalloc(sizeof(*new)); 207 struct reserve_info *new = xmalloc(sizeof(*new));
131 208
209 memset(new, 0, sizeof(*new));
210
132 new->re.address = address; 211 new->re.address = address;
133 new->re.size = size; 212 new->re.size = size;
134 213
135 new->next = NULL;
136
137 new->label = label;
138
139 return new; 214 return new;
140} 215}
141 216
@@ -208,6 +283,60 @@ cell_t propval_cell(struct property *prop)
208 return fdt32_to_cpu(*((cell_t *)prop->val.val)); 283 return fdt32_to_cpu(*((cell_t *)prop->val.val));
209} 284}
210 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) 340struct node *get_subnode(struct node *node, const char *nodename)
212{ 341{
213 struct node *child; 342 struct node *child;
@@ -245,11 +374,13 @@ struct node *get_node_by_path(struct node *tree, const char *path)
245struct node *get_node_by_label(struct node *tree, const char *label) 374struct node *get_node_by_label(struct node *tree, const char *label)
246{ 375{
247 struct node *child, *node; 376 struct node *child, *node;
377 struct label *l;
248 378
249 assert(label && (strlen(label) > 0)); 379 assert(label && (strlen(label) > 0));
250 380
251 if (tree->label && streq(tree->label, label)) 381 for_each_label(tree->labels, l)
252 return tree; 382 if (streq(l->label, label))
383 return tree;
253 384
254 for_each_child(tree, child) { 385 for_each_child(tree, child) {
255 node = get_node_by_label(child, label); 386 node = get_node_by_label(child, label);
@@ -293,16 +424,186 @@ cell_t get_node_phandle(struct node *root, struct node *node)
293 if ((node->phandle != 0) && (node->phandle != -1)) 424 if ((node->phandle != 0) && (node->phandle != -1))
294 return node->phandle; 425 return node->phandle;
295 426
296 assert(! get_property(node, "linux,phandle"));
297
298 while (get_node_by_phandle(root, phandle)) 427 while (get_node_by_phandle(root, phandle))
299 phandle++; 428 phandle++;
300 429
301 node->phandle = phandle; 430 node->phandle = phandle;
302 add_property(node, 431
303 build_property("linux,phandle", 432 if (!get_property(node, "linux,phandle")
304 data_append_cell(empty_data, phandle), 433 && (phandle_format & PHANDLE_LEGACY))
305 NULL)); 434 add_property(node,
435 build_property("linux,phandle",
436 data_append_cell(empty_data, phandle)));
437
438 if (!get_property(node, "phandle")
439 && (phandle_format & PHANDLE_EPAPR))
440 add_property(node,
441 build_property("phandle",
442 data_append_cell(empty_data, phandle)));
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 */
306 447
307 return node->phandle; 448 return node->phandle;
308} 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}