Linux-libre 3.0.78-gnu1
[librecmc/linux-libre.git] / scripts / dtc / checks.c
1 /*
2  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2007.
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.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18  *                                                                   USA
19  */
20
21 #include "dtc.h"
22
23 #ifdef TRACE_CHECKS
24 #define TRACE(c, ...) \
25         do { \
26                 fprintf(stderr, "=== %s: ", (c)->name); \
27                 fprintf(stderr, __VA_ARGS__); \
28                 fprintf(stderr, "\n"); \
29         } while (0)
30 #else
31 #define TRACE(c, fmt, ...)      do { } while (0)
32 #endif
33
34 enum checklevel {
35         IGNORE = 0,
36         WARN = 1,
37         ERROR = 2,
38 };
39
40 enum checkstatus {
41         UNCHECKED = 0,
42         PREREQ,
43         PASSED,
44         FAILED,
45 };
46
47 struct check;
48
49 typedef void (*tree_check_fn)(struct check *c, struct node *dt);
50 typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node);
51 typedef void (*prop_check_fn)(struct check *c, struct node *dt,
52                               struct node *node, struct property *prop);
53
54 struct check {
55         const char *name;
56         tree_check_fn tree_fn;
57         node_check_fn node_fn;
58         prop_check_fn prop_fn;
59         void *data;
60         enum checklevel level;
61         enum checkstatus status;
62         int inprogress;
63         int num_prereqs;
64         struct check **prereq;
65 };
66
67 #define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \
68         static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
69         static struct check nm = { \
70                 .name = #nm, \
71                 .tree_fn = (tfn), \
72                 .node_fn = (nfn), \
73                 .prop_fn = (pfn), \
74                 .data = (d), \
75                 .level = (lvl), \
76                 .status = UNCHECKED, \
77                 .num_prereqs = ARRAY_SIZE(nm##_prereqs), \
78                 .prereq = nm##_prereqs, \
79         };
80
81 #define TREE_CHECK(nm, d, lvl, ...) \
82         CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__)
83 #define NODE_CHECK(nm, d, lvl, ...) \
84         CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__)
85 #define PROP_CHECK(nm, d, lvl, ...) \
86         CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__)
87 #define BATCH_CHECK(nm, lvl, ...) \
88         CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__)
89
90 #ifdef __GNUC__
91 static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
92 #endif
93 static inline void check_msg(struct check *c, const char *fmt, ...)
94 {
95         va_list ap;
96         va_start(ap, fmt);
97
98         if ((c->level < WARN) || (c->level <= quiet))
99                 return; /* Suppress message */
100
101         fprintf(stderr, "%s (%s): ",
102                 (c->level == ERROR) ? "ERROR" : "Warning", c->name);
103         vfprintf(stderr, fmt, ap);
104         fprintf(stderr, "\n");
105 }
106
107 #define FAIL(c, ...) \
108         do { \
109                 TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
110                 (c)->status = FAILED; \
111                 check_msg((c), __VA_ARGS__); \
112         } while (0)
113
114 static void check_nodes_props(struct check *c, struct node *dt, struct node *node)
115 {
116         struct node *child;
117         struct property *prop;
118
119         TRACE(c, "%s", node->fullpath);
120         if (c->node_fn)
121                 c->node_fn(c, dt, node);
122
123         if (c->prop_fn)
124                 for_each_property(node, prop) {
125                         TRACE(c, "%s\t'%s'", node->fullpath, prop->name);
126                         c->prop_fn(c, dt, node, prop);
127                 }
128
129         for_each_child(node, child)
130                 check_nodes_props(c, dt, child);
131 }
132
133 static int run_check(struct check *c, struct node *dt)
134 {
135         int error = 0;
136         int i;
137
138         assert(!c->inprogress);
139
140         if (c->status != UNCHECKED)
141                 goto out;
142
143         c->inprogress = 1;
144
145         for (i = 0; i < c->num_prereqs; i++) {
146                 struct check *prq = c->prereq[i];
147                 error |= run_check(prq, dt);
148                 if (prq->status != PASSED) {
149                         c->status = PREREQ;
150                         check_msg(c, "Failed prerequisite '%s'",
151                                   c->prereq[i]->name);
152                 }
153         }
154
155         if (c->status != UNCHECKED)
156                 goto out;
157
158         if (c->node_fn || c->prop_fn)
159                 check_nodes_props(c, dt, dt);
160
161         if (c->tree_fn)
162                 c->tree_fn(c, dt);
163         if (c->status == UNCHECKED)
164                 c->status = PASSED;
165
166         TRACE(c, "\tCompleted, status %d", c->status);
167
168 out:
169         c->inprogress = 0;
170         if ((c->status != PASSED) && (c->level == ERROR))
171                 error = 1;
172         return error;
173 }
174
175 /*
176  * Utility check functions
177  */
178
179 static void check_is_string(struct check *c, struct node *root,
180                             struct node *node)
181 {
182         struct property *prop;
183         char *propname = c->data;
184
185         prop = get_property(node, propname);
186         if (!prop)
187                 return; /* Not present, assumed ok */
188
189         if (!data_is_one_string(prop->val))
190                 FAIL(c, "\"%s\" property in %s is not a string",
191                      propname, node->fullpath);
192 }
193 #define CHECK_IS_STRING(nm, propname, lvl) \
194         CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl))
195
196 static void check_is_cell(struct check *c, struct node *root,
197                           struct node *node)
198 {
199         struct property *prop;
200         char *propname = c->data;
201
202         prop = get_property(node, propname);
203         if (!prop)
204                 return; /* Not present, assumed ok */
205
206         if (prop->val.len != sizeof(cell_t))
207                 FAIL(c, "\"%s\" property in %s is not a single cell",
208                      propname, node->fullpath);
209 }
210 #define CHECK_IS_CELL(nm, propname, lvl) \
211         CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl))
212
213 /*
214  * Structural check functions
215  */
216
217 static void check_duplicate_node_names(struct check *c, struct node *dt,
218                                        struct node *node)
219 {
220         struct node *child, *child2;
221
222         for_each_child(node, child)
223                 for (child2 = child->next_sibling;
224                      child2;
225                      child2 = child2->next_sibling)
226                         if (streq(child->name, child2->name))
227                                 FAIL(c, "Duplicate node name %s",
228                                      child->fullpath);
229 }
230 NODE_CHECK(duplicate_node_names, NULL, ERROR);
231
232 static void check_duplicate_property_names(struct check *c, struct node *dt,
233                                            struct node *node)
234 {
235         struct property *prop, *prop2;
236
237         for_each_property(node, prop)
238                 for (prop2 = prop->next; prop2; prop2 = prop2->next)
239                         if (streq(prop->name, prop2->name))
240                                 FAIL(c, "Duplicate property name %s in %s",
241                                      prop->name, node->fullpath);
242 }
243 NODE_CHECK(duplicate_property_names, NULL, ERROR);
244
245 #define LOWERCASE       "abcdefghijklmnopqrstuvwxyz"
246 #define UPPERCASE       "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
247 #define DIGITS          "0123456789"
248 #define PROPNODECHARS   LOWERCASE UPPERCASE DIGITS ",._+*#?-"
249
250 static void check_node_name_chars(struct check *c, struct node *dt,
251                                   struct node *node)
252 {
253         int n = strspn(node->name, c->data);
254
255         if (n < strlen(node->name))
256                 FAIL(c, "Bad character '%c' in node %s",
257                      node->name[n], node->fullpath);
258 }
259 NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);
260
261 static void check_node_name_format(struct check *c, struct node *dt,
262                                    struct node *node)
263 {
264         if (strchr(get_unitname(node), '@'))
265                 FAIL(c, "Node %s has multiple '@' characters in name",
266                      node->fullpath);
267 }
268 NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);
269
270 static void check_property_name_chars(struct check *c, struct node *dt,
271                                       struct node *node, struct property *prop)
272 {
273         int n = strspn(prop->name, c->data);
274
275         if (n < strlen(prop->name))
276                 FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
277                      prop->name[n], prop->name, node->fullpath);
278 }
279 PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);
280
281 #define DESCLABEL_FMT   "%s%s%s%s%s"
282 #define DESCLABEL_ARGS(node,prop,mark)          \
283         ((mark) ? "value of " : ""),            \
284         ((prop) ? "'" : ""), \
285         ((prop) ? (prop)->name : ""), \
286         ((prop) ? "' in " : ""), (node)->fullpath
287
288 static void check_duplicate_label(struct check *c, struct node *dt,
289                                   const char *label, struct node *node,
290                                   struct property *prop, struct marker *mark)
291 {
292         struct node *othernode = NULL;
293         struct property *otherprop = NULL;
294         struct marker *othermark = NULL;
295
296         othernode = get_node_by_label(dt, label);
297
298         if (!othernode)
299                 otherprop = get_property_by_label(dt, label, &othernode);
300         if (!othernode)
301                 othermark = get_marker_label(dt, label, &othernode,
302                                                &otherprop);
303
304         if (!othernode)
305                 return;
306
307         if ((othernode != node) || (otherprop != prop) || (othermark != mark))
308                 FAIL(c, "Duplicate label '%s' on " DESCLABEL_FMT
309                      " and " DESCLABEL_FMT,
310                      label, DESCLABEL_ARGS(node, prop, mark),
311                      DESCLABEL_ARGS(othernode, otherprop, othermark));
312 }
313
314 static void check_duplicate_label_node(struct check *c, struct node *dt,
315                                        struct node *node)
316 {
317         struct label *l;
318
319         for_each_label(node->labels, l)
320                 check_duplicate_label(c, dt, l->label, node, NULL, NULL);
321 }
322 static void check_duplicate_label_prop(struct check *c, struct node *dt,
323                                        struct node *node, struct property *prop)
324 {
325         struct marker *m = prop->val.markers;
326         struct label *l;
327
328         for_each_label(prop->labels, l)
329                 check_duplicate_label(c, dt, l->label, node, prop, NULL);
330
331         for_each_marker_of_type(m, LABEL)
332                 check_duplicate_label(c, dt, m->ref, node, prop, m);
333 }
334 CHECK(duplicate_label, NULL, check_duplicate_label_node,
335       check_duplicate_label_prop, NULL, ERROR);
336
337 static void check_explicit_phandles(struct check *c, struct node *root,
338                                     struct node *node, struct property *prop)
339 {
340         struct marker *m;
341         struct node *other;
342         cell_t phandle;
343
344         if (!streq(prop->name, "phandle")
345             && !streq(prop->name, "linux,phandle"))
346                 return;
347
348         if (prop->val.len != sizeof(cell_t)) {
349                 FAIL(c, "%s has bad length (%d) %s property",
350                      node->fullpath, prop->val.len, prop->name);
351                 return;
352         }
353
354         m = prop->val.markers;
355         for_each_marker_of_type(m, REF_PHANDLE) {
356                 assert(m->offset == 0);
357                 if (node != get_node_by_ref(root, m->ref))
358                         /* "Set this node's phandle equal to some
359                          * other node's phandle".  That's nonsensical
360                          * by construction. */ {
361                         FAIL(c, "%s in %s is a reference to another node",
362                              prop->name, node->fullpath);
363                         return;
364                 }
365                 /* But setting this node's phandle equal to its own
366                  * phandle is allowed - that means allocate a unique
367                  * phandle for this node, even if it's not otherwise
368                  * referenced.  The value will be filled in later, so
369                  * no further checking for now. */
370                 return;
371         }
372
373         phandle = propval_cell(prop);
374
375         if ((phandle == 0) || (phandle == -1)) {
376                 FAIL(c, "%s has bad value (0x%x) in %s property",
377                      node->fullpath, phandle, prop->name);
378                 return;
379         }
380
381         if (node->phandle && (node->phandle != phandle))
382                 FAIL(c, "%s has %s property which replaces existing phandle information",
383                      node->fullpath, prop->name);
384
385         other = get_node_by_phandle(root, phandle);
386         if (other && (other != node)) {
387                 FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
388                      node->fullpath, phandle, other->fullpath);
389                 return;
390         }
391
392         node->phandle = phandle;
393 }
394 PROP_CHECK(explicit_phandles, NULL, ERROR);
395
396 static void check_name_properties(struct check *c, struct node *root,
397                                   struct node *node)
398 {
399         struct property **pp, *prop = NULL;
400
401         for (pp = &node->proplist; *pp; pp = &((*pp)->next))
402                 if (streq((*pp)->name, "name")) {
403                         prop = *pp;
404                         break;
405                 }
406
407         if (!prop)
408                 return; /* No name property, that's fine */
409
410         if ((prop->val.len != node->basenamelen+1)
411             || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
412                 FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
413                      " of base node name)", node->fullpath, prop->val.val);
414         } else {
415                 /* The name property is correct, and therefore redundant.
416                  * Delete it */
417                 *pp = prop->next;
418                 free(prop->name);
419                 data_free(prop->val);
420                 free(prop);
421         }
422 }
423 CHECK_IS_STRING(name_is_string, "name", ERROR);
424 NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
425
426 /*
427  * Reference fixup functions
428  */
429
430 static void fixup_phandle_references(struct check *c, struct node *dt,
431                                      struct node *node, struct property *prop)
432 {
433         struct marker *m = prop->val.markers;
434         struct node *refnode;
435         cell_t phandle;
436
437         for_each_marker_of_type(m, REF_PHANDLE) {
438                 assert(m->offset + sizeof(cell_t) <= prop->val.len);
439
440                 refnode = get_node_by_ref(dt, m->ref);
441                 if (! refnode) {
442                         FAIL(c, "Reference to non-existent node or label \"%s\"\n",
443                              m->ref);
444                         continue;
445                 }
446
447                 phandle = get_node_phandle(dt, refnode);
448                 *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
449         }
450 }
451 CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
452       &duplicate_node_names, &explicit_phandles);
453
454 static void fixup_path_references(struct check *c, struct node *dt,
455                                   struct node *node, struct property *prop)
456 {
457         struct marker *m = prop->val.markers;
458         struct node *refnode;
459         char *path;
460
461         for_each_marker_of_type(m, REF_PATH) {
462                 assert(m->offset <= prop->val.len);
463
464                 refnode = get_node_by_ref(dt, m->ref);
465                 if (!refnode) {
466                         FAIL(c, "Reference to non-existent node or label \"%s\"\n",
467                              m->ref);
468                         continue;
469                 }
470
471                 path = refnode->fullpath;
472                 prop->val = data_insert_at_marker(prop->val, m, path,
473                                                   strlen(path) + 1);
474         }
475 }
476 CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR,
477       &duplicate_node_names);
478
479 /*
480  * Semantic checks
481  */
482 CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN);
483 CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
484 CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
485
486 CHECK_IS_STRING(device_type_is_string, "device_type", WARN);
487 CHECK_IS_STRING(model_is_string, "model", WARN);
488 CHECK_IS_STRING(status_is_string, "status", WARN);
489
490 static void fixup_addr_size_cells(struct check *c, struct node *dt,
491                                   struct node *node)
492 {
493         struct property *prop;
494
495         node->addr_cells = -1;
496         node->size_cells = -1;
497
498         prop = get_property(node, "#address-cells");
499         if (prop)
500                 node->addr_cells = propval_cell(prop);
501
502         prop = get_property(node, "#size-cells");
503         if (prop)
504                 node->size_cells = propval_cell(prop);
505 }
506 CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN,
507       &address_cells_is_cell, &size_cells_is_cell);
508
509 #define node_addr_cells(n) \
510         (((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
511 #define node_size_cells(n) \
512         (((n)->size_cells == -1) ? 1 : (n)->size_cells)
513
514 static void check_reg_format(struct check *c, struct node *dt,
515                              struct node *node)
516 {
517         struct property *prop;
518         int addr_cells, size_cells, entrylen;
519
520         prop = get_property(node, "reg");
521         if (!prop)
522                 return; /* No "reg", that's fine */
523
524         if (!node->parent) {
525                 FAIL(c, "Root node has a \"reg\" property");
526                 return;
527         }
528
529         if (prop->val.len == 0)
530                 FAIL(c, "\"reg\" property in %s is empty", node->fullpath);
531
532         addr_cells = node_addr_cells(node->parent);
533         size_cells = node_size_cells(node->parent);
534         entrylen = (addr_cells + size_cells) * sizeof(cell_t);
535
536         if ((prop->val.len % entrylen) != 0)
537                 FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
538                      "(#address-cells == %d, #size-cells == %d)",
539                      node->fullpath, prop->val.len, addr_cells, size_cells);
540 }
541 NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells);
542
543 static void check_ranges_format(struct check *c, struct node *dt,
544                                 struct node *node)
545 {
546         struct property *prop;
547         int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen;
548
549         prop = get_property(node, "ranges");
550         if (!prop)
551                 return;
552
553         if (!node->parent) {
554                 FAIL(c, "Root node has a \"ranges\" property");
555                 return;
556         }
557
558         p_addr_cells = node_addr_cells(node->parent);
559         p_size_cells = node_size_cells(node->parent);
560         c_addr_cells = node_addr_cells(node);
561         c_size_cells = node_size_cells(node);
562         entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t);
563
564         if (prop->val.len == 0) {
565                 if (p_addr_cells != c_addr_cells)
566                         FAIL(c, "%s has empty \"ranges\" property but its "
567                              "#address-cells (%d) differs from %s (%d)",
568                              node->fullpath, c_addr_cells, node->parent->fullpath,
569                              p_addr_cells);
570                 if (p_size_cells != c_size_cells)
571                         FAIL(c, "%s has empty \"ranges\" property but its "
572                              "#size-cells (%d) differs from %s (%d)",
573                              node->fullpath, c_size_cells, node->parent->fullpath,
574                              p_size_cells);
575         } else if ((prop->val.len % entrylen) != 0) {
576                 FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) "
577                      "(parent #address-cells == %d, child #address-cells == %d, "
578                      "#size-cells == %d)", node->fullpath, prop->val.len,
579                      p_addr_cells, c_addr_cells, c_size_cells);
580         }
581 }
582 NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells);
583
584 /*
585  * Style checks
586  */
587 static void check_avoid_default_addr_size(struct check *c, struct node *dt,
588                                           struct node *node)
589 {
590         struct property *reg, *ranges;
591
592         if (!node->parent)
593                 return; /* Ignore root node */
594
595         reg = get_property(node, "reg");
596         ranges = get_property(node, "ranges");
597
598         if (!reg && !ranges)
599                 return;
600
601         if ((node->parent->addr_cells == -1))
602                 FAIL(c, "Relying on default #address-cells value for %s",
603                      node->fullpath);
604
605         if ((node->parent->size_cells == -1))
606                 FAIL(c, "Relying on default #size-cells value for %s",
607                      node->fullpath);
608 }
609 NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells);
610
611 static void check_obsolete_chosen_interrupt_controller(struct check *c,
612                                                        struct node *dt)
613 {
614         struct node *chosen;
615         struct property *prop;
616
617         chosen = get_node_by_path(dt, "/chosen");
618         if (!chosen)
619                 return;
620
621         prop = get_property(chosen, "interrupt-controller");
622         if (prop)
623                 FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
624                      "property");
625 }
626 TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
627
628 static struct check *check_table[] = {
629         &duplicate_node_names, &duplicate_property_names,
630         &node_name_chars, &node_name_format, &property_name_chars,
631         &name_is_string, &name_properties,
632
633         &duplicate_label,
634
635         &explicit_phandles,
636         &phandle_references, &path_references,
637
638         &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
639         &device_type_is_string, &model_is_string, &status_is_string,
640
641         &addr_size_cells, &reg_format, &ranges_format,
642
643         &avoid_default_addr_size,
644         &obsolete_chosen_interrupt_controller,
645 };
646
647 void process_checks(int force, struct boot_info *bi)
648 {
649         struct node *dt = bi->dt;
650         int i;
651         int error = 0;
652
653         for (i = 0; i < ARRAY_SIZE(check_table); i++) {
654                 struct check *c = check_table[i];
655
656                 if (c->level != IGNORE)
657                         error = error || run_check(c, dt);
658         }
659
660         if (error) {
661                 if (!force) {
662                         fprintf(stderr, "ERROR: Input tree has errors, aborting "
663                                 "(use -f to force output)\n");
664                         exit(2);
665                 } else if (quiet < 3) {
666                         fprintf(stderr, "Warning: Input tree has errors, "
667                                 "output forced\n");
668                 }
669         }
670 }