diff options
Diffstat (limited to 'scripts/dtc/checks.c')
-rw-r--r-- | scripts/dtc/checks.c | 203 |
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 | ||
34 | enum checklevel { | ||
35 | IGNORE = 0, | ||
36 | WARN = 1, | ||
37 | ERROR = 2, | ||
38 | }; | ||
39 | |||
40 | enum checkstatus { | 34 | enum 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__ |
91 | static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); | 102 | static 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 | ||
168 | out: | 179 | out: |
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 */ | ||
191 | static inline void check_always_fail(struct check *c, struct node *dt) | ||
192 | { | ||
193 | FAIL(c, "always_fail check"); | ||
194 | } | ||
195 | TREE_CHECK(always_fail, NULL); | ||
196 | |||
179 | static void check_is_string(struct check *c, struct node *root, | 197 | static 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 | ||
196 | static void check_is_cell(struct check *c, struct node *root, | 216 | static 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 | } |
230 | NODE_CHECK(duplicate_node_names, NULL, ERROR); | 252 | NODE_ERROR(duplicate_node_names, NULL); |
231 | 253 | ||
232 | static void check_duplicate_property_names(struct check *c, struct node *dt, | 254 | static 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 | } |
243 | NODE_CHECK(duplicate_property_names, NULL, ERROR); | 269 | NODE_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 | } |
259 | NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR); | 285 | NODE_ERROR(node_name_chars, PROPNODECHARS "@"); |
260 | 286 | ||
261 | static void check_node_name_format(struct check *c, struct node *dt, | 287 | static 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 | } |
268 | NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars); | 294 | NODE_ERROR(node_name_format, NULL, &node_name_chars); |
269 | 295 | ||
270 | static void check_property_name_chars(struct check *c, struct node *dt, | 296 | static 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 | } |
279 | PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR); | 305 | PROP_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 | } |
334 | CHECK(duplicate_label, NULL, check_duplicate_label_node, | 360 | ERROR(duplicate_label, NULL, check_duplicate_label_node, |
335 | check_duplicate_label_prop, NULL, ERROR); | 361 | check_duplicate_label_prop, NULL); |
336 | 362 | ||
337 | static void check_explicit_phandles(struct check *c, struct node *root, | 363 | static 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 | } |
394 | PROP_CHECK(explicit_phandles, NULL, ERROR); | 420 | PROP_ERROR(explicit_phandles, NULL); |
395 | 421 | ||
396 | static void check_name_properties(struct check *c, struct node *root, | 422 | static 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 | } |
423 | CHECK_IS_STRING(name_is_string, "name", ERROR); | 449 | ERROR_IF_NOT_STRING(name_is_string, "name"); |
424 | NODE_CHECK(name_properties, NULL, ERROR, &name_is_string); | 450 | NODE_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 | } |
451 | CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR, | 477 | ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL, |
452 | &duplicate_node_names, &explicit_phandles); | 478 | &duplicate_node_names, &explicit_phandles); |
453 | 479 | ||
454 | static void fixup_path_references(struct check *c, struct node *dt, | 480 | static 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 | } |
476 | CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR, | 502 | ERROR(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 | */ |
482 | CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN); | 508 | WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells"); |
483 | CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN); | 509 | WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells"); |
484 | CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN); | 510 | WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells"); |
485 | 511 | ||
486 | CHECK_IS_STRING(device_type_is_string, "device_type", WARN); | 512 | WARNING_IF_NOT_STRING(device_type_is_string, "device_type"); |
487 | CHECK_IS_STRING(model_is_string, "model", WARN); | 513 | WARNING_IF_NOT_STRING(model_is_string, "model"); |
488 | CHECK_IS_STRING(status_is_string, "status", WARN); | 514 | WARNING_IF_NOT_STRING(status_is_string, "status"); |
489 | 515 | ||
490 | static void fixup_addr_size_cells(struct check *c, struct node *dt, | 516 | static 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 | } |
506 | CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN, | 532 | WARNING(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 | } |
541 | NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells); | 567 | NODE_WARNING(reg_format, NULL, &addr_size_cells); |
542 | 568 | ||
543 | static void check_ranges_format(struct check *c, struct node *dt, | 569 | static 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 | } |
582 | NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells); | 608 | NODE_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 | } |
609 | NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells); | 635 | NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells); |
610 | 636 | ||
611 | static void check_obsolete_chosen_interrupt_controller(struct check *c, | 637 | static 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 | } |
626 | TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN); | 652 | TREE_WARNING(obsolete_chosen_interrupt_controller, NULL); |
627 | 653 | ||
628 | static struct check *check_table[] = { | 654 | static 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 | ||
675 | static 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 | |||
688 | static 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 | |||
709 | void 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 | |||
647 | void process_checks(int force, struct boot_info *bi) | 736 | void 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 | ||