1 /* 2 * (C) Copyright David Gibson <dwg (at) 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 checkstatus { 35 UNCHECKED = 0, 36 PREREQ, 37 PASSED, 38 FAILED, 39 }; 40 41 struct check; 42 43 typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node); 44 45 struct check { 46 const char *name; 47 check_fn fn; 48 void *data; 49 bool warn, error; 50 enum checkstatus status; 51 bool inprogress; 52 int num_prereqs; 53 struct check **prereq; 54 }; 55 56 #define CHECK_ENTRY(_nm, _fn, _d, _w, _e, ...) \ 57 static struct check *_nm##_prereqs[] = { __VA_ARGS__ }; \ 58 static struct check _nm = { \ 59 .name = #_nm, \ 60 .fn = (_fn), \ 61 .data = (_d), \ 62 .warn = (_w), \ 63 .error = (_e), \ 64 .status = UNCHECKED, \ 65 .num_prereqs = ARRAY_SIZE(_nm##_prereqs), \ 66 .prereq = _nm##_prereqs, \ 67 }; 68 #define WARNING(_nm, _fn, _d, ...) \ 69 CHECK_ENTRY(_nm, _fn, _d, true, false, __VA_ARGS__) 70 #define ERROR(_nm, _fn, _d, ...) \ 71 CHECK_ENTRY(_nm, _fn, _d, false, true, __VA_ARGS__) 72 #define CHECK(_nm, _fn, _d, ...) \ 73 CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__) 74 75 #ifdef __GNUC__ 76 static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); 77 #endif 78 static inline void check_msg(struct check *c, const char *fmt, ...) 79 { 80 va_list ap; 81 va_start(ap, fmt); 82 83 if ((c->warn && (quiet < 1)) 84 || (c->error && (quiet < 2))) { 85 fprintf(stderr, "%s (%s): ", 86 (c->error) ? "ERROR" : "Warning", c->name); 87 vfprintf(stderr, fmt, ap); 88 fprintf(stderr, "\n"); 89 } 90 va_end(ap); 91 } 92 93 #define FAIL(c, ...) \ 94 do { \ 95 TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \ 96 (c)->status = FAILED; \ 97 check_msg((c), __VA_ARGS__); \ 98 } while (0) 99 100 static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node) 101 { 102 struct node *child; 103 104 TRACE(c, "%s", node->fullpath); 105 if (c->fn) 106 c->fn(c, dti, node); 107 108 for_each_child(node, child) 109 check_nodes_props(c, dti, child); 110 } 111 112 static bool run_check(struct check *c, struct dt_info *dti) 113 { 114 struct node *dt = dti->dt; 115 bool error = false; 116 int i; 117 118 assert(!c->inprogress); 119 120 if (c->status != UNCHECKED) 121 goto out; 122 123 c->inprogress = true; 124 125 for (i = 0; i < c->num_prereqs; i++) { 126 struct check *prq = c->prereq[i]; 127 error = error || run_check(prq, dti); 128 if (prq->status != PASSED) { 129 c->status = PREREQ; 130 check_msg(c, "Failed prerequisite '%s'", 131 c->prereq[i]->name); 132 } 133 } 134 135 if (c->status != UNCHECKED) 136 goto out; 137 138 check_nodes_props(c, dti, dt); 139 140 if (c->status == UNCHECKED) 141 c->status = PASSED; 142 143 TRACE(c, "\tCompleted, status %d", c->status); 144 145 out: 146 c->inprogress = false; 147 if ((c->status != PASSED) && (c->error)) 148 error = true; 149 return error; 150 } 151 152 /* 153 * Utility check functions 154 */ 155 156 /* A check which always fails, for testing purposes only */ 157 static inline void check_always_fail(struct check *c, struct dt_info *dti, 158 struct node *node) 159 { 160 FAIL(c, "always_fail check"); 161 } 162 CHECK(always_fail, check_always_fail, NULL); 163 164 static void check_is_string(struct check *c, struct dt_info *dti, 165 struct node *node) 166 { 167 struct property *prop; 168 char *propname = c->data; 169 170 prop = get_property(node, propname); 171 if (!prop) 172 return; /* Not present, assumed ok */ 173 174 if (!data_is_one_string(prop->val)) 175 FAIL(c, "\"%s\" property in %s is not a string", 176 propname, node->fullpath); 177 } 178 #define WARNING_IF_NOT_STRING(nm, propname) \ 179 WARNING(nm, check_is_string, (propname)) 180 #define ERROR_IF_NOT_STRING(nm, propname) \ 181 ERROR(nm, check_is_string, (propname)) 182 183 static void check_is_cell(struct check *c, struct dt_info *dti, 184 struct node *node) 185 { 186 struct property *prop; 187 char *propname = c->data; 188 189 prop = get_property(node, propname); 190 if (!prop) 191 return; /* Not present, assumed ok */ 192 193 if (prop->val.len != sizeof(cell_t)) 194 FAIL(c, "\"%s\" property in %s is not a single cell", 195 propname, node->fullpath); 196 } 197 #define WARNING_IF_NOT_CELL(nm, propname) \ 198 WARNING(nm, check_is_cell, (propname)) 199 #define ERROR_IF_NOT_CELL(nm, propname) \ 200 ERROR(nm, check_is_cell, (propname)) 201 202 /* 203 * Structural check functions 204 */ 205 206 static void check_duplicate_node_names(struct check *c, struct dt_info *dti, 207 struct node *node) 208 { 209 struct node *child, *child2; 210 211 for_each_child(node, child) 212 for (child2 = child->next_sibling; 213 child2; 214 child2 = child2->next_sibling) 215 if (streq(child->name, child2->name)) 216 FAIL(c, "Duplicate node name %s", 217 child->fullpath); 218 } 219 ERROR(duplicate_node_names, check_duplicate_node_names, NULL); 220 221 static void check_duplicate_property_names(struct check *c, struct dt_info *dti, 222 struct node *node) 223 { 224 struct property *prop, *prop2; 225 226 for_each_property(node, prop) { 227 for (prop2 = prop->next; prop2; prop2 = prop2->next) { 228 if (prop2->deleted) 229 continue; 230 if (streq(prop->name, prop2->name)) 231 FAIL(c, "Duplicate property name %s in %s", 232 prop->name, node->fullpath); 233 } 234 } 235 } 236 ERROR(duplicate_property_names, check_duplicate_property_names, NULL); 237 238 #define LOWERCASE "abcdefghijklmnopqrstuvwxyz" 239 #define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 240 #define DIGITS "0123456789" 241 #define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-" 242 #define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-" 243 244 static void check_node_name_chars(struct check *c, struct dt_info *dti, 245 struct node *node) 246 { 247 int n = strspn(node->name, c->data); 248 249 if (n < strlen(node->name)) 250 FAIL(c, "Bad character '%c' in node %s", 251 node->name[n], node->fullpath); 252 } 253 ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@"); 254 255 static void check_node_name_chars_strict(struct check *c, struct dt_info *dti, 256 struct node *node) 257 { 258 int n = strspn(node->name, c->data); 259 260 if (n < node->basenamelen) 261 FAIL(c, "Character '%c' not recommended in node %s", 262 node->name[n], node->fullpath); 263 } 264 CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT); 265 266 static void check_node_name_format(struct check *c, struct dt_info *dti, 267 struct node *node) 268 { 269 if (strchr(get_unitname(node), '@')) 270 FAIL(c, "Node %s has multiple '@' characters in name", 271 node->fullpath); 272 } 273 ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars); 274 275 static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti, 276 struct node *node) 277 { 278 const char *unitname = get_unitname(node); 279 struct property *prop = get_property(node, "reg"); 280 281 if (!prop) { 282 prop = get_property(node, "ranges"); 283 if (prop && !prop->val.len) 284 prop = NULL; 285 } 286 287 if (prop) { 288 if (!unitname[0]) 289 FAIL(c, "Node %s has a reg or ranges property, but no unit name", 290 node->fullpath); 291 } else { 292 if (unitname[0]) 293 FAIL(c, "Node %s has a unit name, but no reg property", 294 node->fullpath); 295 } 296 } 297 WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL); 298 299 static void check_property_name_chars(struct check *c, struct dt_info *dti, 300 struct node *node) 301 { 302 struct property *prop; 303 304 for_each_property(node, prop) { 305 int n = strspn(prop->name, c->data); 306 307 if (n < strlen(prop->name)) 308 FAIL(c, "Bad character '%c' in property name \"%s\", node %s", 309 prop->name[n], prop->name, node->fullpath); 310 } 311 } 312 ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS); 313 314 static void check_property_name_chars_strict(struct check *c, 315 struct dt_info *dti, 316 struct node *node) 317 { 318 struct property *prop; 319 320 for_each_property(node, prop) { 321 const char *name = prop->name; 322 int n = strspn(name, c->data); 323 324 if (n == strlen(prop->name)) 325 continue; 326 327 /* Certain names are whitelisted */ 328 if (streq(name, "device_type")) 329 continue; 330 331 /* 332 * # is only allowed at the beginning of property names not counting 333 * the vendor prefix. 334 */ 335 if (name[n] == '#' && ((n == 0) || (name[n-1] == ','))) { 336 name += n + 1; 337 n = strspn(name, c->data); 338 } 339 if (n < strlen(name)) 340 FAIL(c, "Character '%c' not recommended in property name \"%s\", node %s", 341 name[n], prop->name, node->fullpath); 342 } 343 } 344 CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT); 345 346 #define DESCLABEL_FMT "%s%s%s%s%s" 347 #define DESCLABEL_ARGS(node,prop,mark) \ 348 ((mark) ? "value of " : ""), \ 349 ((prop) ? "'" : ""), \ 350 ((prop) ? (prop)->name : ""), \ 351 ((prop) ? "' in " : ""), (node)->fullpath 352 353 static void check_duplicate_label(struct check *c, struct dt_info *dti, 354 const char *label, struct node *node, 355 struct property *prop, struct marker *mark) 356 { 357 struct node *dt = dti->dt; 358 struct node *othernode = NULL; 359 struct property *otherprop = NULL; 360 struct marker *othermark = NULL; 361 362 othernode = get_node_by_label(dt, label); 363 364 if (!othernode) 365 otherprop = get_property_by_label(dt, label, &othernode); 366 if (!othernode) 367 othermark = get_marker_label(dt, label, &othernode, 368 &otherprop); 369 370 if (!othernode) 371 return; 372 373 if ((othernode != node) || (otherprop != prop) || (othermark != mark)) 374 FAIL(c, "Duplicate label '%s' on " DESCLABEL_FMT 375 " and " DESCLABEL_FMT, 376 label, DESCLABEL_ARGS(node, prop, mark), 377 DESCLABEL_ARGS(othernode, otherprop, othermark)); 378 } 379 380 static void check_duplicate_label_node(struct check *c, struct dt_info *dti, 381 struct node *node) 382 { 383 struct label *l; 384 struct property *prop; 385 386 for_each_label(node->labels, l) 387 check_duplicate_label(c, dti, l->label, node, NULL, NULL); 388 389 for_each_property(node, prop) { 390 struct marker *m = prop->val.markers; 391 392 for_each_label(prop->labels, l) 393 check_duplicate_label(c, dti, l->label, node, prop, NULL); 394 395 for_each_marker_of_type(m, LABEL) 396 check_duplicate_label(c, dti, m->ref, node, prop, m); 397 } 398 } 399 ERROR(duplicate_label, check_duplicate_label_node, NULL); 400 401 static cell_t check_phandle_prop(struct check *c, struct dt_info *dti, 402 struct node *node, const char *propname) 403 { 404 struct node *root = dti->dt; 405 struct property *prop; 406 struct marker *m; 407 cell_t phandle; 408 409 prop = get_property(node, propname); 410 if (!prop) 411 return 0; 412 413 if (prop->val.len != sizeof(cell_t)) { 414 FAIL(c, "%s has bad length (%d) %s property", 415 node->fullpath, prop->val.len, prop->name); 416 return 0; 417 } 418 419 m = prop->val.markers; 420 for_each_marker_of_type(m, REF_PHANDLE) { 421 assert(m->offset == 0); 422 if (node != get_node_by_ref(root, m->ref)) 423 /* "Set this node's phandle equal to some 424 * other node's phandle". That's nonsensical 425 * by construction. */ { 426 FAIL(c, "%s in %s is a reference to another node", 427 prop->name, node->fullpath); 428 } 429 /* But setting this node's phandle equal to its own 430 * phandle is allowed - that means allocate a unique 431 * phandle for this node, even if it's not otherwise 432 * referenced. The value will be filled in later, so 433 * we treat it as having no phandle data for now. */ 434 return 0; 435 } 436 437 phandle = propval_cell(prop); 438 439 if ((phandle == 0) || (phandle == -1)) { 440 FAIL(c, "%s has bad value (0x%x) in %s property", 441 node->fullpath, phandle, prop->name); 442 return 0; 443 } 444 445 return phandle; 446 } 447 448 static void check_explicit_phandles(struct check *c, struct dt_info *dti, 449 struct node *node) 450 { 451 struct node *root = dti->dt; 452 struct node *other; 453 cell_t phandle, linux_phandle; 454 455 /* Nothing should have assigned phandles yet */ 456 assert(!node->phandle); 457 458 phandle = check_phandle_prop(c, dti, node, "phandle"); 459 460 linux_phandle = check_phandle_prop(c, dti, node, "linux,phandle"); 461 462 if (!phandle && !linux_phandle) 463 /* No valid phandles; nothing further to check */ 464 return; 465 466 if (linux_phandle && phandle && (phandle != linux_phandle)) 467 FAIL(c, "%s has mismatching 'phandle' and 'linux,phandle'" 468 " properties", node->fullpath); 469 470 if (linux_phandle && !phandle) 471 phandle = linux_phandle; 472 473 other = get_node_by_phandle(root, phandle); 474 if (other && (other != node)) { 475 FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)", 476 node->fullpath, phandle, other->fullpath); 477 return; 478 } 479 480 node->phandle = phandle; 481 } 482 ERROR(explicit_phandles, check_explicit_phandles, NULL); 483 484 static void check_name_properties(struct check *c, struct dt_info *dti, 485 struct node *node) 486 { 487 struct property **pp, *prop = NULL; 488 489 for (pp = &node->proplist; *pp; pp = &((*pp)->next)) 490 if (streq((*pp)->name, "name")) { 491 prop = *pp; 492 break; 493 } 494 495 if (!prop) 496 return; /* No name property, that's fine */ 497 498 if ((prop->val.len != node->basenamelen+1) 499 || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) { 500 FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead" 501 " of base node name)", node->fullpath, prop->val.val); 502 } else { 503 /* The name property is correct, and therefore redundant. 504 * Delete it */ 505 *pp = prop->next; 506 free(prop->name); 507 data_free(prop->val); 508 free(prop); 509 } 510 } 511 ERROR_IF_NOT_STRING(name_is_string, "name"); 512 ERROR(name_properties, check_name_properties, NULL, &name_is_string); 513 514 /* 515 * Reference fixup functions 516 */ 517 518 static void fixup_phandle_references(struct check *c, struct dt_info *dti, 519 struct node *node) 520 { 521 struct node *dt = dti->dt; 522 struct property *prop; 523 524 for_each_property(node, prop) { 525 struct marker *m = prop->val.markers; 526 struct node *refnode; 527 cell_t phandle; 528 529 for_each_marker_of_type(m, REF_PHANDLE) { 530 assert(m->offset + sizeof(cell_t) <= prop->val.len); 531 532 refnode = get_node_by_ref(dt, m->ref); 533 if (! refnode) { 534 if (!(dti->dtsflags & DTSF_PLUGIN)) 535 FAIL(c, "Reference to non-existent node or " 536 "label \"%s\"\n", m->ref); 537 else /* mark the entry as unresolved */ 538 *((cell_t *)(prop->val.val + m->offset)) = 539 cpu_to_fdt32(0xffffffff); 540 continue; 541 } 542 543 phandle = get_node_phandle(dt, refnode); 544 *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); 545 } 546 } 547 } 548 ERROR(phandle_references, fixup_phandle_references, NULL, 549 &duplicate_node_names, &explicit_phandles); 550 551 static void fixup_path_references(struct check *c, struct dt_info *dti, 552 struct node *node) 553 { 554 struct node *dt = dti->dt; 555 struct property *prop; 556 557 for_each_property(node, prop) { 558 struct marker *m = prop->val.markers; 559 struct node *refnode; 560 char *path; 561 562 for_each_marker_of_type(m, REF_PATH) { 563 assert(m->offset <= prop->val.len); 564 565 refnode = get_node_by_ref(dt, m->ref); 566 if (!refnode) { 567 FAIL(c, "Reference to non-existent node or label \"%s\"\n", 568 m->ref); 569 continue; 570 } 571 572 path = refnode->fullpath; 573 prop->val = data_insert_at_marker(prop->val, m, path, 574 strlen(path) + 1); 575 } 576 } 577 } 578 ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names); 579 580 /* 581 * Semantic checks 582 */ 583 WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells"); 584 WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells"); 585 WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells"); 586 587 WARNING_IF_NOT_STRING(device_type_is_string, "device_type"); 588 WARNING_IF_NOT_STRING(model_is_string, "model"); 589 WARNING_IF_NOT_STRING(status_is_string, "status"); 590 591 static void fixup_addr_size_cells(struct check *c, struct dt_info *dti, 592 struct node *node) 593 { 594 struct property *prop; 595 596 node->addr_cells = -1; 597 node->size_cells = -1; 598 599 prop = get_property(node, "#address-cells"); 600 if (prop) 601 node->addr_cells = propval_cell(prop); 602 603 prop = get_property(node, "#size-cells"); 604 if (prop) 605 node->size_cells = propval_cell(prop); 606 } 607 WARNING(addr_size_cells, fixup_addr_size_cells, NULL, 608 &address_cells_is_cell, &size_cells_is_cell); 609 610 #define node_addr_cells(n) \ 611 (((n)->addr_cells == -1) ? 2 : (n)->addr_cells) 612 #define node_size_cells(n) \ 613 (((n)->size_cells == -1) ? 1 : (n)->size_cells) 614 615 static void check_reg_format(struct check *c, struct dt_info *dti, 616 struct node *node) 617 { 618 struct property *prop; 619 int addr_cells, size_cells, entrylen; 620 621 prop = get_property(node, "reg"); 622 if (!prop) 623 return; /* No "reg", that's fine */ 624 625 if (!node->parent) { 626 FAIL(c, "Root node has a \"reg\" property"); 627 return; 628 } 629 630 if (prop->val.len == 0) 631 FAIL(c, "\"reg\" property in %s is empty", node->fullpath); 632 633 addr_cells = node_addr_cells(node->parent); 634 size_cells = node_size_cells(node->parent); 635 entrylen = (addr_cells + size_cells) * sizeof(cell_t); 636 637 if (!entrylen || (prop->val.len % entrylen) != 0) 638 FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) " 639 "(#address-cells == %d, #size-cells == %d)", 640 node->fullpath, prop->val.len, addr_cells, size_cells); 641 } 642 WARNING(reg_format, check_reg_format, NULL, &addr_size_cells); 643 644 static void check_ranges_format(struct check *c, struct dt_info *dti, 645 struct node *node) 646 { 647 struct property *prop; 648 int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen; 649 650 prop = get_property(node, "ranges"); 651 if (!prop) 652 return; 653 654 if (!node->parent) { 655 FAIL(c, "Root node has a \"ranges\" property"); 656 return; 657 } 658 659 p_addr_cells = node_addr_cells(node->parent); 660 p_size_cells = node_size_cells(node->parent); 661 c_addr_cells = node_addr_cells(node); 662 c_size_cells = node_size_cells(node); 663 entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t); 664 665 if (prop->val.len == 0) { 666 if (p_addr_cells != c_addr_cells) 667 FAIL(c, "%s has empty \"ranges\" property but its " 668 "#address-cells (%d) differs from %s (%d)", 669 node->fullpath, c_addr_cells, node->parent->fullpath, 670 p_addr_cells); 671 if (p_size_cells != c_size_cells) 672 FAIL(c, "%s has empty \"ranges\" property but its " 673 "#size-cells (%d) differs from %s (%d)", 674 node->fullpath, c_size_cells, node->parent->fullpath, 675 p_size_cells); 676 } else if ((prop->val.len % entrylen) != 0) { 677 FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) " 678 "(parent #address-cells == %d, child #address-cells == %d, " 679 "#size-cells == %d)", node->fullpath, prop->val.len, 680 p_addr_cells, c_addr_cells, c_size_cells); 681 } 682 } 683 WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells); 684 685 /* 686 * Style checks 687 */ 688 static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti, 689 struct node *node) 690 { 691 struct property *reg, *ranges; 692 693 if (!node->parent) 694 return; /* Ignore root node */ 695 696 reg = get_property(node, "reg"); 697 ranges = get_property(node, "ranges"); 698 699 if (!reg && !ranges) 700 return; 701 702 if (node->parent->addr_cells == -1) 703 FAIL(c, "Relying on default #address-cells value for %s", 704 node->fullpath); 705 706 if (node->parent->size_cells == -1) 707 FAIL(c, "Relying on default #size-cells value for %s", 708 node->fullpath); 709 } 710 WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL, 711 &addr_size_cells); 712 713 static void check_obsolete_chosen_interrupt_controller(struct check *c, 714 struct dt_info *dti, 715 struct node *node) 716 { 717 struct node *dt = dti->dt; 718 struct node *chosen; 719 struct property *prop; 720 721 if (node != dt) 722 return; 723 724 725 chosen = get_node_by_path(dt, "/chosen"); 726 if (!chosen) 727 return; 728 729 prop = get_property(chosen, "interrupt-controller"); 730 if (prop) 731 FAIL(c, "/chosen has obsolete \"interrupt-controller\" " 732 "property"); 733 } 734 WARNING(obsolete_chosen_interrupt_controller, 735 check_obsolete_chosen_interrupt_controller, NULL); 736 737 static struct check *check_table[] = { 738 &duplicate_node_names, &duplicate_property_names, 739 &node_name_chars, &node_name_format, &property_name_chars, 740 &name_is_string, &name_properties, 741 742 &duplicate_label, 743 744 &explicit_phandles, 745 &phandle_references, &path_references, 746 747 &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell, 748 &device_type_is_string, &model_is_string, &status_is_string, 749 750 &property_name_chars_strict, 751 &node_name_chars_strict, 752 753 &addr_size_cells, ®_format, &ranges_format, 754 755 &unit_address_vs_reg, 756 757 &avoid_default_addr_size, 758 &obsolete_chosen_interrupt_controller, 759 760 &always_fail, 761 }; 762 763 static void enable_warning_error(struct check *c, bool warn, bool error) 764 { 765 int i; 766 767 /* Raising level, also raise it for prereqs */ 768 if ((warn && !c->warn) || (error && !c->error)) 769 for (i = 0; i < c->num_prereqs; i++) 770 enable_warning_error(c->prereq[i], warn, error); 771 772 c->warn = c->warn || warn; 773 c->error = c->error || error; 774 } 775 776 static void disable_warning_error(struct check *c, bool warn, bool error) 777 { 778 int i; 779 780 /* Lowering level, also lower it for things this is the prereq 781 * for */ 782 if ((warn && c->warn) || (error && c->error)) { 783 for (i = 0; i < ARRAY_SIZE(check_table); i++) { 784 struct check *cc = check_table[i]; 785 int j; 786 787 for (j = 0; j < cc->num_prereqs; j++) 788 if (cc->prereq[j] == c) 789 disable_warning_error(cc, warn, error); 790 } 791 } 792 793 c->warn = c->warn && !warn; 794 c->error = c->error && !error; 795 } 796 797 void parse_checks_option(bool warn, bool error, const char *arg) 798 { 799 int i; 800 const char *name = arg; 801 bool enable = true; 802 803 if ((strncmp(arg, "no-", 3) == 0) 804 || (strncmp(arg, "no_", 3) == 0)) { 805 name = arg + 3; 806 enable = false; 807 } 808 809 for (i = 0; i < ARRAY_SIZE(check_table); i++) { 810 struct check *c = check_table[i]; 811 812 if (streq(c->name, name)) { 813 if (enable) 814 enable_warning_error(c, warn, error); 815 else 816 disable_warning_error(c, warn, error); 817 return; 818 } 819 } 820 821 die("Unrecognized check name \"%s\"\n", name); 822 } 823 824 void process_checks(bool force, struct dt_info *dti) 825 { 826 int i; 827 int error = 0; 828 829 for (i = 0; i < ARRAY_SIZE(check_table); i++) { 830 struct check *c = check_table[i]; 831 832 if (c->warn || c->error) 833 error = error || run_check(c, dti); 834 } 835 836 if (error) { 837 if (!force) { 838 fprintf(stderr, "ERROR: Input tree has errors, aborting " 839 "(use -f to force output)\n"); 840 exit(2); 841 } else if (quiet < 3) { 842 fprintf(stderr, "Warning: Input tree has errors, " 843 "output forced\n"); 844 } 845 } 846 } 847