aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/dtc/checks.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/dtc/checks.c')
-rw-r--r--scripts/dtc/checks.c203
1 files changed, 146 insertions, 57 deletions
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
index a662a0044798..ee96a2519eff 100644
--- a/scripts/dtc/checks.c
+++ b/scripts/dtc/checks.c
@@ -31,12 +31,6 @@
31#define TRACE(c, fmt, ...) do { } while (0) 31#define TRACE(c, fmt, ...) do { } while (0)
32#endif 32#endif
33 33
34enum checklevel {
35 IGNORE = 0,
36 WARN = 1,
37 ERROR = 2,
38};
39
40enum checkstatus { 34enum checkstatus {
41 UNCHECKED = 0, 35 UNCHECKED = 0,
42 PREREQ, 36 PREREQ,
@@ -57,14 +51,14 @@ struct check {
57 node_check_fn node_fn; 51 node_check_fn node_fn;
58 prop_check_fn prop_fn; 52 prop_check_fn prop_fn;
59 void *data; 53 void *data;
60 enum checklevel level; 54 bool warn, error;
61 enum checkstatus status; 55 enum checkstatus status;
62 int inprogress; 56 int inprogress;
63 int num_prereqs; 57 int num_prereqs;
64 struct check **prereq; 58 struct check **prereq;
65}; 59};
66 60
67#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \ 61#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...) \
68 static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \ 62 static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
69 static struct check nm = { \ 63 static struct check nm = { \
70 .name = #nm, \ 64 .name = #nm, \
@@ -72,20 +66,37 @@ struct check {
72 .node_fn = (nfn), \ 66 .node_fn = (nfn), \
73 .prop_fn = (pfn), \ 67 .prop_fn = (pfn), \
74 .data = (d), \ 68 .data = (d), \
75 .level = (lvl), \ 69 .warn = (w), \
70 .error = (e), \
76 .status = UNCHECKED, \ 71 .status = UNCHECKED, \
77 .num_prereqs = ARRAY_SIZE(nm##_prereqs), \ 72 .num_prereqs = ARRAY_SIZE(nm##_prereqs), \
78 .prereq = nm##_prereqs, \ 73 .prereq = nm##_prereqs, \
79 }; 74 };
80 75#define WARNING(nm, tfn, nfn, pfn, d, ...) \
81#define TREE_CHECK(nm, d, lvl, ...) \ 76 CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
82 CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__) 77#define ERROR(nm, tfn, nfn, pfn, d, ...) \
83#define NODE_CHECK(nm, d, lvl, ...) \ 78 CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__)
84 CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__) 79#define CHECK(nm, tfn, nfn, pfn, d, ...) \
85#define PROP_CHECK(nm, d, lvl, ...) \ 80 CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__)
86 CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__) 81
87#define BATCH_CHECK(nm, lvl, ...) \ 82#define TREE_WARNING(nm, d, ...) \
88 CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__) 83 WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
84#define TREE_ERROR(nm, d, ...) \
85 ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
86#define TREE_CHECK(nm, d, ...) \
87 CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
88#define NODE_WARNING(nm, d, ...) \
89 WARNING(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
90#define NODE_ERROR(nm, d, ...) \
91 ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
92#define NODE_CHECK(nm, d, ...) \
93 CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
94#define PROP_WARNING(nm, d, ...) \
95 WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
96#define PROP_ERROR(nm, d, ...) \
97 ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
98#define PROP_CHECK(nm, d, ...) \
99 CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
89 100
90#ifdef __GNUC__ 101#ifdef __GNUC__
91static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); 102static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
@@ -95,13 +106,13 @@ static inline void check_msg(struct check *c, const char *fmt, ...)
95 va_list ap; 106 va_list ap;
96 va_start(ap, fmt); 107 va_start(ap, fmt);
97 108
98 if ((c->level < WARN) || (c->level <= quiet)) 109 if ((c->warn && (quiet < 1))
99 return; /* Suppress message */ 110 || (c->error && (quiet < 2))) {
100 111 fprintf(stderr, "%s (%s): ",
101 fprintf(stderr, "%s (%s): ", 112 (c->error) ? "ERROR" : "Warning", c->name);
102 (c->level == ERROR) ? "ERROR" : "Warning", c->name); 113 vfprintf(stderr, fmt, ap);
103 vfprintf(stderr, fmt, ap); 114 fprintf(stderr, "\n");
104 fprintf(stderr, "\n"); 115 }
105} 116}
106 117
107#define FAIL(c, ...) \ 118#define FAIL(c, ...) \
@@ -167,7 +178,7 @@ static int run_check(struct check *c, struct node *dt)
167 178
168out: 179out:
169 c->inprogress = 0; 180 c->inprogress = 0;
170 if ((c->status != PASSED) && (c->level == ERROR)) 181 if ((c->status != PASSED) && (c->error))
171 error = 1; 182 error = 1;
172 return error; 183 return error;
173} 184}
@@ -176,6 +187,13 @@ out:
176 * Utility check functions 187 * Utility check functions
177 */ 188 */
178 189
190/* A check which always fails, for testing purposes only */
191static inline void check_always_fail(struct check *c, struct node *dt)
192{
193 FAIL(c, "always_fail check");
194}
195TREE_CHECK(always_fail, NULL);
196
179static void check_is_string(struct check *c, struct node *root, 197static void check_is_string(struct check *c, struct node *root,
180 struct node *node) 198 struct node *node)
181{ 199{
@@ -190,8 +208,10 @@ static void check_is_string(struct check *c, struct node *root,
190 FAIL(c, "\"%s\" property in %s is not a string", 208 FAIL(c, "\"%s\" property in %s is not a string",
191 propname, node->fullpath); 209 propname, node->fullpath);
192} 210}
193#define CHECK_IS_STRING(nm, propname, lvl) \ 211#define WARNING_IF_NOT_STRING(nm, propname) \
194 CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl)) 212 WARNING(nm, NULL, check_is_string, NULL, (propname))
213#define ERROR_IF_NOT_STRING(nm, propname) \
214 ERROR(nm, NULL, check_is_string, NULL, (propname))
195 215
196static void check_is_cell(struct check *c, struct node *root, 216static void check_is_cell(struct check *c, struct node *root,
197 struct node *node) 217 struct node *node)
@@ -207,8 +227,10 @@ static void check_is_cell(struct check *c, struct node *root,
207 FAIL(c, "\"%s\" property in %s is not a single cell", 227 FAIL(c, "\"%s\" property in %s is not a single cell",
208 propname, node->fullpath); 228 propname, node->fullpath);
209} 229}
210#define CHECK_IS_CELL(nm, propname, lvl) \ 230#define WARNING_IF_NOT_CELL(nm, propname) \
211 CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl)) 231 WARNING(nm, NULL, check_is_cell, NULL, (propname))
232#define ERROR_IF_NOT_CELL(nm, propname) \
233 ERROR(nm, NULL, check_is_cell, NULL, (propname))
212 234
213/* 235/*
214 * Structural check functions 236 * Structural check functions
@@ -227,20 +249,24 @@ static void check_duplicate_node_names(struct check *c, struct node *dt,
227 FAIL(c, "Duplicate node name %s", 249 FAIL(c, "Duplicate node name %s",
228 child->fullpath); 250 child->fullpath);
229} 251}
230NODE_CHECK(duplicate_node_names, NULL, ERROR); 252NODE_ERROR(duplicate_node_names, NULL);
231 253
232static void check_duplicate_property_names(struct check *c, struct node *dt, 254static void check_duplicate_property_names(struct check *c, struct node *dt,
233 struct node *node) 255 struct node *node)
234{ 256{
235 struct property *prop, *prop2; 257 struct property *prop, *prop2;
236 258
237 for_each_property(node, prop) 259 for_each_property(node, prop) {
238 for (prop2 = prop->next; prop2; prop2 = prop2->next) 260 for (prop2 = prop->next; prop2; prop2 = prop2->next) {
261 if (prop2->deleted)
262 continue;
239 if (streq(prop->name, prop2->name)) 263 if (streq(prop->name, prop2->name))
240 FAIL(c, "Duplicate property name %s in %s", 264 FAIL(c, "Duplicate property name %s in %s",
241 prop->name, node->fullpath); 265 prop->name, node->fullpath);
266 }
267 }
242} 268}
243NODE_CHECK(duplicate_property_names, NULL, ERROR); 269NODE_ERROR(duplicate_property_names, NULL);
244 270
245#define LOWERCASE "abcdefghijklmnopqrstuvwxyz" 271#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
246#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 272#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -256,7 +282,7 @@ static void check_node_name_chars(struct check *c, struct node *dt,
256 FAIL(c, "Bad character '%c' in node %s", 282 FAIL(c, "Bad character '%c' in node %s",
257 node->name[n], node->fullpath); 283 node->name[n], node->fullpath);
258} 284}
259NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR); 285NODE_ERROR(node_name_chars, PROPNODECHARS "@");
260 286
261static void check_node_name_format(struct check *c, struct node *dt, 287static void check_node_name_format(struct check *c, struct node *dt,
262 struct node *node) 288 struct node *node)
@@ -265,7 +291,7 @@ static void check_node_name_format(struct check *c, struct node *dt,
265 FAIL(c, "Node %s has multiple '@' characters in name", 291 FAIL(c, "Node %s has multiple '@' characters in name",
266 node->fullpath); 292 node->fullpath);
267} 293}
268NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars); 294NODE_ERROR(node_name_format, NULL, &node_name_chars);
269 295
270static void check_property_name_chars(struct check *c, struct node *dt, 296static void check_property_name_chars(struct check *c, struct node *dt,
271 struct node *node, struct property *prop) 297 struct node *node, struct property *prop)
@@ -276,7 +302,7 @@ static void check_property_name_chars(struct check *c, struct node *dt,
276 FAIL(c, "Bad character '%c' in property name \"%s\", node %s", 302 FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
277 prop->name[n], prop->name, node->fullpath); 303 prop->name[n], prop->name, node->fullpath);
278} 304}
279PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR); 305PROP_ERROR(property_name_chars, PROPNODECHARS);
280 306
281#define DESCLABEL_FMT "%s%s%s%s%s" 307#define DESCLABEL_FMT "%s%s%s%s%s"
282#define DESCLABEL_ARGS(node,prop,mark) \ 308#define DESCLABEL_ARGS(node,prop,mark) \
@@ -331,8 +357,8 @@ static void check_duplicate_label_prop(struct check *c, struct node *dt,
331 for_each_marker_of_type(m, LABEL) 357 for_each_marker_of_type(m, LABEL)
332 check_duplicate_label(c, dt, m->ref, node, prop, m); 358 check_duplicate_label(c, dt, m->ref, node, prop, m);
333} 359}
334CHECK(duplicate_label, NULL, check_duplicate_label_node, 360ERROR(duplicate_label, NULL, check_duplicate_label_node,
335 check_duplicate_label_prop, NULL, ERROR); 361 check_duplicate_label_prop, NULL);
336 362
337static void check_explicit_phandles(struct check *c, struct node *root, 363static void check_explicit_phandles(struct check *c, struct node *root,
338 struct node *node, struct property *prop) 364 struct node *node, struct property *prop)
@@ -391,7 +417,7 @@ static void check_explicit_phandles(struct check *c, struct node *root,
391 417
392 node->phandle = phandle; 418 node->phandle = phandle;
393} 419}
394PROP_CHECK(explicit_phandles, NULL, ERROR); 420PROP_ERROR(explicit_phandles, NULL);
395 421
396static void check_name_properties(struct check *c, struct node *root, 422static void check_name_properties(struct check *c, struct node *root,
397 struct node *node) 423 struct node *node)
@@ -420,8 +446,8 @@ static void check_name_properties(struct check *c, struct node *root,
420 free(prop); 446 free(prop);
421 } 447 }
422} 448}
423CHECK_IS_STRING(name_is_string, "name", ERROR); 449ERROR_IF_NOT_STRING(name_is_string, "name");
424NODE_CHECK(name_properties, NULL, ERROR, &name_is_string); 450NODE_ERROR(name_properties, NULL, &name_is_string);
425 451
426/* 452/*
427 * Reference fixup functions 453 * Reference fixup functions
@@ -448,7 +474,7 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
448 *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); 474 *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
449 } 475 }
450} 476}
451CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR, 477ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,
452 &duplicate_node_names, &explicit_phandles); 478 &duplicate_node_names, &explicit_phandles);
453 479
454static void fixup_path_references(struct check *c, struct node *dt, 480static void fixup_path_references(struct check *c, struct node *dt,
@@ -473,19 +499,19 @@ static void fixup_path_references(struct check *c, struct node *dt,
473 strlen(path) + 1); 499 strlen(path) + 1);
474 } 500 }
475} 501}
476CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR, 502ERROR(path_references, NULL, NULL, fixup_path_references, NULL,
477 &duplicate_node_names); 503 &duplicate_node_names);
478 504
479/* 505/*
480 * Semantic checks 506 * Semantic checks
481 */ 507 */
482CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN); 508WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
483CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN); 509WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
484CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN); 510WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
485 511
486CHECK_IS_STRING(device_type_is_string, "device_type", WARN); 512WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
487CHECK_IS_STRING(model_is_string, "model", WARN); 513WARNING_IF_NOT_STRING(model_is_string, "model");
488CHECK_IS_STRING(status_is_string, "status", WARN); 514WARNING_IF_NOT_STRING(status_is_string, "status");
489 515
490static void fixup_addr_size_cells(struct check *c, struct node *dt, 516static void fixup_addr_size_cells(struct check *c, struct node *dt,
491 struct node *node) 517 struct node *node)
@@ -503,8 +529,8 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt,
503 if (prop) 529 if (prop)
504 node->size_cells = propval_cell(prop); 530 node->size_cells = propval_cell(prop);
505} 531}
506CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN, 532WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL,
507 &address_cells_is_cell, &size_cells_is_cell); 533 &address_cells_is_cell, &size_cells_is_cell);
508 534
509#define node_addr_cells(n) \ 535#define node_addr_cells(n) \
510 (((n)->addr_cells == -1) ? 2 : (n)->addr_cells) 536 (((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
@@ -538,7 +564,7 @@ static void check_reg_format(struct check *c, struct node *dt,
538 "(#address-cells == %d, #size-cells == %d)", 564 "(#address-cells == %d, #size-cells == %d)",
539 node->fullpath, prop->val.len, addr_cells, size_cells); 565 node->fullpath, prop->val.len, addr_cells, size_cells);
540} 566}
541NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells); 567NODE_WARNING(reg_format, NULL, &addr_size_cells);
542 568
543static void check_ranges_format(struct check *c, struct node *dt, 569static void check_ranges_format(struct check *c, struct node *dt,
544 struct node *node) 570 struct node *node)
@@ -579,7 +605,7 @@ static void check_ranges_format(struct check *c, struct node *dt,
579 p_addr_cells, c_addr_cells, c_size_cells); 605 p_addr_cells, c_addr_cells, c_size_cells);
580 } 606 }
581} 607}
582NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells); 608NODE_WARNING(ranges_format, NULL, &addr_size_cells);
583 609
584/* 610/*
585 * Style checks 611 * Style checks
@@ -606,7 +632,7 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt,
606 FAIL(c, "Relying on default #size-cells value for %s", 632 FAIL(c, "Relying on default #size-cells value for %s",
607 node->fullpath); 633 node->fullpath);
608} 634}
609NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells); 635NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells);
610 636
611static void check_obsolete_chosen_interrupt_controller(struct check *c, 637static void check_obsolete_chosen_interrupt_controller(struct check *c,
612 struct node *dt) 638 struct node *dt)
@@ -623,7 +649,7 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
623 FAIL(c, "/chosen has obsolete \"interrupt-controller\" " 649 FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
624 "property"); 650 "property");
625} 651}
626TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN); 652TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
627 653
628static struct check *check_table[] = { 654static struct check *check_table[] = {
629 &duplicate_node_names, &duplicate_property_names, 655 &duplicate_node_names, &duplicate_property_names,
@@ -642,8 +668,71 @@ static struct check *check_table[] = {
642 668
643 &avoid_default_addr_size, 669 &avoid_default_addr_size,
644 &obsolete_chosen_interrupt_controller, 670 &obsolete_chosen_interrupt_controller,
671
672 &always_fail,
645}; 673};
646 674
675static void enable_warning_error(struct check *c, bool warn, bool error)
676{
677 int i;
678
679 /* Raising level, also raise it for prereqs */
680 if ((warn && !c->warn) || (error && !c->error))
681 for (i = 0; i < c->num_prereqs; i++)
682 enable_warning_error(c->prereq[i], warn, error);
683
684 c->warn = c->warn || warn;
685 c->error = c->error || error;
686}
687
688static void disable_warning_error(struct check *c, bool warn, bool error)
689{
690 int i;
691
692 /* Lowering level, also lower it for things this is the prereq
693 * for */
694 if ((warn && c->warn) || (error && c->error)) {
695 for (i = 0; i < ARRAY_SIZE(check_table); i++) {
696 struct check *cc = check_table[i];
697 int j;
698
699 for (j = 0; j < cc->num_prereqs; j++)
700 if (cc->prereq[j] == c)
701 disable_warning_error(cc, warn, error);
702 }
703 }
704
705 c->warn = c->warn && !warn;
706 c->error = c->error && !error;
707}
708
709void parse_checks_option(bool warn, bool error, const char *optarg)
710{
711 int i;
712 const char *name = optarg;
713 bool enable = true;
714
715 if ((strncmp(optarg, "no-", 3) == 0)
716 || (strncmp(optarg, "no_", 3) == 0)) {
717 name = optarg + 3;
718 enable = false;
719 }
720
721 for (i = 0; i < ARRAY_SIZE(check_table); i++) {
722 struct check *c = check_table[i];
723
724 if (streq(c->name, name)) {
725 if (enable)
726 enable_warning_error(c, warn, error);
727 else
728 disable_warning_error(c, warn, error);
729 return;
730 }
731 }
732
733 die("Unrecognized check name \"%s\"\n", name);
734}
735
647void process_checks(int force, struct boot_info *bi) 736void process_checks(int force, struct boot_info *bi)
648{ 737{
649 struct node *dt = bi->dt; 738 struct node *dt = bi->dt;
@@ -653,7 +742,7 @@ void process_checks(int force, struct boot_info *bi)
653 for (i = 0; i < ARRAY_SIZE(check_table); i++) { 742 for (i = 0; i < ARRAY_SIZE(check_table); i++) {
654 struct check *c = check_table[i]; 743 struct check *c = check_table[i];
655 744
656 if (c->level != IGNORE) 745 if (c->warn || c->error)
657 error = error || run_check(c, dt); 746 error = error || run_check(c, dt);
658 } 747 }
659 748