checks.c revision 204433
1204431Sraj/* 2204431Sraj * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2007. 3204431Sraj * 4204431Sraj * 5204431Sraj * This program is free software; you can redistribute it and/or 6204431Sraj * modify it under the terms of the GNU General Public License as 7204431Sraj * published by the Free Software Foundation; either version 2 of the 8204431Sraj * License, or (at your option) any later version. 9204431Sraj * 10204431Sraj * This program is distributed in the hope that it will be useful, 11204431Sraj * but WITHOUT ANY WARRANTY; without even the implied warranty of 12204431Sraj * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13204431Sraj * General Public License for more details. 14204431Sraj * 15204431Sraj * You should have received a copy of the GNU General Public License 16204431Sraj * along with this program; if not, write to the Free Software 17204431Sraj * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 18204431Sraj * USA 19204431Sraj */ 20204431Sraj 21204431Sraj#include "dtc.h" 22204431Sraj 23204431Sraj#ifdef TRACE_CHECKS 24204431Sraj#define TRACE(c, ...) \ 25204431Sraj do { \ 26204431Sraj fprintf(stderr, "=== %s: ", (c)->name); \ 27204431Sraj fprintf(stderr, __VA_ARGS__); \ 28204431Sraj fprintf(stderr, "\n"); \ 29204431Sraj } while (0) 30204431Sraj#else 31204431Sraj#define TRACE(c, fmt, ...) do { } while (0) 32204431Sraj#endif 33204431Sraj 34204431Srajenum checklevel { 35204431Sraj IGNORE = 0, 36204431Sraj WARN = 1, 37204431Sraj ERROR = 2, 38204431Sraj}; 39204431Sraj 40204431Srajenum checkstatus { 41204431Sraj UNCHECKED = 0, 42204431Sraj PREREQ, 43204431Sraj PASSED, 44204431Sraj FAILED, 45204431Sraj}; 46204431Sraj 47204431Srajstruct check; 48204431Sraj 49204431Srajtypedef void (*tree_check_fn)(struct check *c, struct node *dt); 50204431Srajtypedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node); 51204431Srajtypedef void (*prop_check_fn)(struct check *c, struct node *dt, 52204431Sraj struct node *node, struct property *prop); 53204431Sraj 54204431Srajstruct check { 55204431Sraj const char *name; 56204431Sraj tree_check_fn tree_fn; 57204431Sraj node_check_fn node_fn; 58204431Sraj prop_check_fn prop_fn; 59204431Sraj void *data; 60204431Sraj enum checklevel level; 61204431Sraj enum checkstatus status; 62204431Sraj int inprogress; 63204431Sraj int num_prereqs; 64204431Sraj struct check **prereq; 65204431Sraj}; 66204431Sraj 67204431Sraj#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \ 68204431Sraj static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \ 69204431Sraj static struct check nm = { \ 70204431Sraj .name = #nm, \ 71204431Sraj .tree_fn = (tfn), \ 72204431Sraj .node_fn = (nfn), \ 73204431Sraj .prop_fn = (pfn), \ 74204431Sraj .data = (d), \ 75204431Sraj .level = (lvl), \ 76204431Sraj .status = UNCHECKED, \ 77204431Sraj .num_prereqs = ARRAY_SIZE(nm##_prereqs), \ 78204431Sraj .prereq = nm##_prereqs, \ 79204431Sraj }; 80204431Sraj 81204431Sraj#define TREE_CHECK(nm, d, lvl, ...) \ 82204431Sraj CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__) 83204431Sraj#define NODE_CHECK(nm, d, lvl, ...) \ 84204431Sraj CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__) 85204431Sraj#define PROP_CHECK(nm, d, lvl, ...) \ 86204431Sraj CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__) 87204431Sraj#define BATCH_CHECK(nm, lvl, ...) \ 88204431Sraj CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__) 89204431Sraj 90204431Sraj#ifdef __GNUC__ 91204431Srajstatic inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); 92204431Sraj#endif 93204431Srajstatic inline void check_msg(struct check *c, const char *fmt, ...) 94204431Sraj{ 95204431Sraj va_list ap; 96204431Sraj va_start(ap, fmt); 97204431Sraj 98204431Sraj if ((c->level < WARN) || (c->level <= quiet)) 99204431Sraj return; /* Suppress message */ 100204431Sraj 101204431Sraj fprintf(stderr, "%s (%s): ", 102204431Sraj (c->level == ERROR) ? "ERROR" : "Warning", c->name); 103204431Sraj vfprintf(stderr, fmt, ap); 104204431Sraj fprintf(stderr, "\n"); 105204431Sraj} 106204431Sraj 107204431Sraj#define FAIL(c, ...) \ 108204431Sraj do { \ 109204431Sraj TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \ 110204431Sraj (c)->status = FAILED; \ 111204431Sraj check_msg((c), __VA_ARGS__); \ 112204431Sraj } while (0) 113204431Sraj 114204431Srajstatic void check_nodes_props(struct check *c, struct node *dt, struct node *node) 115204431Sraj{ 116204431Sraj struct node *child; 117204431Sraj struct property *prop; 118204431Sraj 119204431Sraj TRACE(c, "%s", node->fullpath); 120204431Sraj if (c->node_fn) 121204431Sraj c->node_fn(c, dt, node); 122204431Sraj 123204431Sraj if (c->prop_fn) 124204431Sraj for_each_property(node, prop) { 125204431Sraj TRACE(c, "%s\t'%s'", node->fullpath, prop->name); 126204431Sraj c->prop_fn(c, dt, node, prop); 127204431Sraj } 128204431Sraj 129204431Sraj for_each_child(node, child) 130204431Sraj check_nodes_props(c, dt, child); 131204431Sraj} 132204431Sraj 133204431Srajstatic int run_check(struct check *c, struct node *dt) 134204431Sraj{ 135204431Sraj int error = 0; 136204431Sraj int i; 137204431Sraj 138204431Sraj assert(!c->inprogress); 139204431Sraj 140204431Sraj if (c->status != UNCHECKED) 141204431Sraj goto out; 142204431Sraj 143204431Sraj c->inprogress = 1; 144204431Sraj 145204431Sraj for (i = 0; i < c->num_prereqs; i++) { 146204431Sraj struct check *prq = c->prereq[i]; 147204431Sraj error |= run_check(prq, dt); 148204431Sraj if (prq->status != PASSED) { 149204431Sraj c->status = PREREQ; 150204431Sraj check_msg(c, "Failed prerequisite '%s'", 151204431Sraj c->prereq[i]->name); 152204431Sraj } 153204431Sraj } 154204431Sraj 155204431Sraj if (c->status != UNCHECKED) 156204431Sraj goto out; 157204431Sraj 158204431Sraj if (c->node_fn || c->prop_fn) 159204431Sraj check_nodes_props(c, dt, dt); 160204431Sraj 161204431Sraj if (c->tree_fn) 162204431Sraj c->tree_fn(c, dt); 163204431Sraj if (c->status == UNCHECKED) 164204431Sraj c->status = PASSED; 165204431Sraj 166204431Sraj TRACE(c, "\tCompleted, status %d", c->status); 167204431Sraj 168204431Srajout: 169204431Sraj c->inprogress = 0; 170204431Sraj if ((c->status != PASSED) && (c->level == ERROR)) 171204431Sraj error = 1; 172204431Sraj return error; 173204431Sraj} 174204431Sraj 175204431Sraj/* 176204431Sraj * Utility check functions 177204431Sraj */ 178204431Sraj 179204431Srajstatic void check_is_string(struct check *c, struct node *root, 180204431Sraj struct node *node) 181204431Sraj{ 182204431Sraj struct property *prop; 183204431Sraj char *propname = c->data; 184204431Sraj 185204431Sraj prop = get_property(node, propname); 186204431Sraj if (!prop) 187204431Sraj return; /* Not present, assumed ok */ 188204431Sraj 189204431Sraj if (!data_is_one_string(prop->val)) 190204431Sraj FAIL(c, "\"%s\" property in %s is not a string", 191204431Sraj propname, node->fullpath); 192204431Sraj} 193204431Sraj#define CHECK_IS_STRING(nm, propname, lvl) \ 194204431Sraj CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl)) 195204431Sraj 196204431Srajstatic void check_is_cell(struct check *c, struct node *root, 197204431Sraj struct node *node) 198204431Sraj{ 199204431Sraj struct property *prop; 200204431Sraj char *propname = c->data; 201204431Sraj 202204431Sraj prop = get_property(node, propname); 203204431Sraj if (!prop) 204204431Sraj return; /* Not present, assumed ok */ 205204431Sraj 206204431Sraj if (prop->val.len != sizeof(cell_t)) 207204431Sraj FAIL(c, "\"%s\" property in %s is not a single cell", 208204431Sraj propname, node->fullpath); 209204431Sraj} 210204431Sraj#define CHECK_IS_CELL(nm, propname, lvl) \ 211204431Sraj CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl)) 212204431Sraj 213204431Sraj/* 214204431Sraj * Structural check functions 215204431Sraj */ 216204431Sraj 217204431Srajstatic void check_duplicate_node_names(struct check *c, struct node *dt, 218204431Sraj struct node *node) 219204431Sraj{ 220204431Sraj struct node *child, *child2; 221204431Sraj 222204431Sraj for_each_child(node, child) 223204431Sraj for (child2 = child->next_sibling; 224204431Sraj child2; 225204431Sraj child2 = child2->next_sibling) 226204431Sraj if (streq(child->name, child2->name)) 227204431Sraj FAIL(c, "Duplicate node name %s", 228204431Sraj child->fullpath); 229204431Sraj} 230204431SrajNODE_CHECK(duplicate_node_names, NULL, ERROR); 231204431Sraj 232204431Srajstatic void check_duplicate_property_names(struct check *c, struct node *dt, 233204431Sraj struct node *node) 234204431Sraj{ 235204431Sraj struct property *prop, *prop2; 236204431Sraj 237204431Sraj for_each_property(node, prop) 238204431Sraj for (prop2 = prop->next; prop2; prop2 = prop2->next) 239204431Sraj if (streq(prop->name, prop2->name)) 240204431Sraj FAIL(c, "Duplicate property name %s in %s", 241204431Sraj prop->name, node->fullpath); 242204431Sraj} 243204431SrajNODE_CHECK(duplicate_property_names, NULL, ERROR); 244204431Sraj 245204431Sraj#define LOWERCASE "abcdefghijklmnopqrstuvwxyz" 246204431Sraj#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 247204431Sraj#define DIGITS "0123456789" 248204431Sraj#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-" 249204431Sraj 250204431Srajstatic void check_node_name_chars(struct check *c, struct node *dt, 251204431Sraj struct node *node) 252204431Sraj{ 253204431Sraj int n = strspn(node->name, c->data); 254204431Sraj 255204431Sraj if (n < strlen(node->name)) 256204431Sraj FAIL(c, "Bad character '%c' in node %s", 257204431Sraj node->name[n], node->fullpath); 258204431Sraj} 259204431SrajNODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR); 260204431Sraj 261204431Srajstatic void check_node_name_format(struct check *c, struct node *dt, 262204431Sraj struct node *node) 263204431Sraj{ 264204431Sraj if (strchr(get_unitname(node), '@')) 265204431Sraj FAIL(c, "Node %s has multiple '@' characters in name", 266204431Sraj node->fullpath); 267204431Sraj} 268204431SrajNODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars); 269204431Sraj 270204431Srajstatic void check_property_name_chars(struct check *c, struct node *dt, 271204431Sraj struct node *node, struct property *prop) 272204431Sraj{ 273204431Sraj int n = strspn(prop->name, c->data); 274204431Sraj 275204431Sraj if (n < strlen(prop->name)) 276204431Sraj FAIL(c, "Bad character '%c' in property name \"%s\", node %s", 277204431Sraj prop->name[n], prop->name, node->fullpath); 278204431Sraj} 279204431SrajPROP_CHECK(property_name_chars, PROPNODECHARS, ERROR); 280204431Sraj 281204431Srajstatic void check_explicit_phandles(struct check *c, struct node *root, 282204433Sraj struct node *node, struct property *prop) 283204431Sraj{ 284204433Sraj struct marker *m; 285204431Sraj struct node *other; 286204431Sraj cell_t phandle; 287204431Sraj 288204433Sraj if (!streq(prop->name, "phandle") 289204433Sraj && !streq(prop->name, "linux,phandle")) 290204433Sraj return; 291204431Sraj 292204431Sraj if (prop->val.len != sizeof(cell_t)) { 293204433Sraj FAIL(c, "%s has bad length (%d) %s property", 294204433Sraj node->fullpath, prop->val.len, prop->name); 295204431Sraj return; 296204431Sraj } 297204431Sraj 298204433Sraj m = prop->val.markers; 299204433Sraj for_each_marker_of_type(m, REF_PHANDLE) { 300204433Sraj assert(m->offset == 0); 301204433Sraj if (node != get_node_by_ref(root, m->ref)) 302204433Sraj /* "Set this node's phandle equal to some 303204433Sraj * other node's phandle". That's nonsensical 304204433Sraj * by construction. */ { 305204433Sraj FAIL(c, "%s in %s is a reference to another node", 306204433Sraj prop->name, node->fullpath); 307204433Sraj return; 308204433Sraj } 309204433Sraj /* But setting this node's phandle equal to its own 310204433Sraj * phandle is allowed - that means allocate a unique 311204433Sraj * phandle for this node, even if it's not otherwise 312204433Sraj * referenced. The value will be filled in later, so 313204433Sraj * no further checking for now. */ 314204433Sraj return; 315204433Sraj } 316204433Sraj 317204431Sraj phandle = propval_cell(prop); 318204433Sraj 319204431Sraj if ((phandle == 0) || (phandle == -1)) { 320204433Sraj FAIL(c, "%s has bad value (0x%x) in %s property", 321204433Sraj node->fullpath, phandle, prop->name); 322204431Sraj return; 323204431Sraj } 324204431Sraj 325204433Sraj if (node->phandle && (node->phandle != phandle)) 326204433Sraj FAIL(c, "%s has %s property which replaces existing phandle information", 327204433Sraj node->fullpath, prop->name); 328204433Sraj 329204431Sraj other = get_node_by_phandle(root, phandle); 330204433Sraj if (other && (other != node)) { 331204431Sraj FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)", 332204431Sraj node->fullpath, phandle, other->fullpath); 333204431Sraj return; 334204431Sraj } 335204431Sraj 336204431Sraj node->phandle = phandle; 337204431Sraj} 338204433SrajPROP_CHECK(explicit_phandles, NULL, ERROR); 339204431Sraj 340204431Srajstatic void check_name_properties(struct check *c, struct node *root, 341204431Sraj struct node *node) 342204431Sraj{ 343204431Sraj struct property **pp, *prop = NULL; 344204431Sraj 345204431Sraj for (pp = &node->proplist; *pp; pp = &((*pp)->next)) 346204431Sraj if (streq((*pp)->name, "name")) { 347204431Sraj prop = *pp; 348204431Sraj break; 349204431Sraj } 350204431Sraj 351204431Sraj if (!prop) 352204431Sraj return; /* No name property, that's fine */ 353204431Sraj 354204431Sraj if ((prop->val.len != node->basenamelen+1) 355204431Sraj || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) { 356204431Sraj FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead" 357204431Sraj " of base node name)", node->fullpath, prop->val.val); 358204431Sraj } else { 359204431Sraj /* The name property is correct, and therefore redundant. 360204431Sraj * Delete it */ 361204431Sraj *pp = prop->next; 362204431Sraj free(prop->name); 363204431Sraj data_free(prop->val); 364204431Sraj free(prop); 365204431Sraj } 366204431Sraj} 367204431SrajCHECK_IS_STRING(name_is_string, "name", ERROR); 368204431SrajNODE_CHECK(name_properties, NULL, ERROR, &name_is_string); 369204431Sraj 370204431Sraj/* 371204431Sraj * Reference fixup functions 372204431Sraj */ 373204431Sraj 374204431Srajstatic void fixup_phandle_references(struct check *c, struct node *dt, 375204431Sraj struct node *node, struct property *prop) 376204431Sraj{ 377204431Sraj struct marker *m = prop->val.markers; 378204431Sraj struct node *refnode; 379204431Sraj cell_t phandle; 380204431Sraj 381204431Sraj for_each_marker_of_type(m, REF_PHANDLE) { 382204431Sraj assert(m->offset + sizeof(cell_t) <= prop->val.len); 383204431Sraj 384204431Sraj refnode = get_node_by_ref(dt, m->ref); 385204431Sraj if (! refnode) { 386204431Sraj FAIL(c, "Reference to non-existent node or label \"%s\"\n", 387204431Sraj m->ref); 388204431Sraj continue; 389204431Sraj } 390204431Sraj 391204431Sraj phandle = get_node_phandle(dt, refnode); 392204431Sraj *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); 393204431Sraj } 394204431Sraj} 395204431SrajCHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR, 396204431Sraj &duplicate_node_names, &explicit_phandles); 397204431Sraj 398204431Srajstatic void fixup_path_references(struct check *c, struct node *dt, 399204431Sraj struct node *node, struct property *prop) 400204431Sraj{ 401204431Sraj struct marker *m = prop->val.markers; 402204431Sraj struct node *refnode; 403204431Sraj char *path; 404204431Sraj 405204431Sraj for_each_marker_of_type(m, REF_PATH) { 406204431Sraj assert(m->offset <= prop->val.len); 407204431Sraj 408204431Sraj refnode = get_node_by_ref(dt, m->ref); 409204431Sraj if (!refnode) { 410204431Sraj FAIL(c, "Reference to non-existent node or label \"%s\"\n", 411204431Sraj m->ref); 412204431Sraj continue; 413204431Sraj } 414204431Sraj 415204431Sraj path = refnode->fullpath; 416204431Sraj prop->val = data_insert_at_marker(prop->val, m, path, 417204431Sraj strlen(path) + 1); 418204431Sraj } 419204431Sraj} 420204431SrajCHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR, 421204431Sraj &duplicate_node_names); 422204431Sraj 423204431Sraj/* 424204431Sraj * Semantic checks 425204431Sraj */ 426204431SrajCHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN); 427204431SrajCHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN); 428204431SrajCHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN); 429204431Sraj 430204431SrajCHECK_IS_STRING(device_type_is_string, "device_type", WARN); 431204431SrajCHECK_IS_STRING(model_is_string, "model", WARN); 432204431SrajCHECK_IS_STRING(status_is_string, "status", WARN); 433204431Sraj 434204431Srajstatic void fixup_addr_size_cells(struct check *c, struct node *dt, 435204431Sraj struct node *node) 436204431Sraj{ 437204431Sraj struct property *prop; 438204431Sraj 439204431Sraj node->addr_cells = -1; 440204431Sraj node->size_cells = -1; 441204431Sraj 442204431Sraj prop = get_property(node, "#address-cells"); 443204431Sraj if (prop) 444204431Sraj node->addr_cells = propval_cell(prop); 445204431Sraj 446204431Sraj prop = get_property(node, "#size-cells"); 447204431Sraj if (prop) 448204431Sraj node->size_cells = propval_cell(prop); 449204431Sraj} 450204431SrajCHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN, 451204431Sraj &address_cells_is_cell, &size_cells_is_cell); 452204431Sraj 453204431Sraj#define node_addr_cells(n) \ 454204431Sraj (((n)->addr_cells == -1) ? 2 : (n)->addr_cells) 455204431Sraj#define node_size_cells(n) \ 456204431Sraj (((n)->size_cells == -1) ? 1 : (n)->size_cells) 457204431Sraj 458204431Srajstatic void check_reg_format(struct check *c, struct node *dt, 459204431Sraj struct node *node) 460204431Sraj{ 461204431Sraj struct property *prop; 462204431Sraj int addr_cells, size_cells, entrylen; 463204431Sraj 464204431Sraj prop = get_property(node, "reg"); 465204431Sraj if (!prop) 466204431Sraj return; /* No "reg", that's fine */ 467204431Sraj 468204431Sraj if (!node->parent) { 469204431Sraj FAIL(c, "Root node has a \"reg\" property"); 470204431Sraj return; 471204431Sraj } 472204431Sraj 473204431Sraj if (prop->val.len == 0) 474204431Sraj FAIL(c, "\"reg\" property in %s is empty", node->fullpath); 475204431Sraj 476204431Sraj addr_cells = node_addr_cells(node->parent); 477204431Sraj size_cells = node_size_cells(node->parent); 478204431Sraj entrylen = (addr_cells + size_cells) * sizeof(cell_t); 479204431Sraj 480204431Sraj if ((prop->val.len % entrylen) != 0) 481204431Sraj FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) " 482204431Sraj "(#address-cells == %d, #size-cells == %d)", 483204431Sraj node->fullpath, prop->val.len, addr_cells, size_cells); 484204431Sraj} 485204431SrajNODE_CHECK(reg_format, NULL, WARN, &addr_size_cells); 486204431Sraj 487204431Srajstatic void check_ranges_format(struct check *c, struct node *dt, 488204431Sraj struct node *node) 489204431Sraj{ 490204431Sraj struct property *prop; 491204431Sraj int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen; 492204431Sraj 493204431Sraj prop = get_property(node, "ranges"); 494204431Sraj if (!prop) 495204431Sraj return; 496204431Sraj 497204431Sraj if (!node->parent) { 498204431Sraj FAIL(c, "Root node has a \"ranges\" property"); 499204431Sraj return; 500204431Sraj } 501204431Sraj 502204431Sraj p_addr_cells = node_addr_cells(node->parent); 503204431Sraj p_size_cells = node_size_cells(node->parent); 504204431Sraj c_addr_cells = node_addr_cells(node); 505204431Sraj c_size_cells = node_size_cells(node); 506204431Sraj entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t); 507204431Sraj 508204431Sraj if (prop->val.len == 0) { 509204431Sraj if (p_addr_cells != c_addr_cells) 510204431Sraj FAIL(c, "%s has empty \"ranges\" property but its " 511204431Sraj "#address-cells (%d) differs from %s (%d)", 512204431Sraj node->fullpath, c_addr_cells, node->parent->fullpath, 513204431Sraj p_addr_cells); 514204431Sraj if (p_size_cells != c_size_cells) 515204431Sraj FAIL(c, "%s has empty \"ranges\" property but its " 516204431Sraj "#size-cells (%d) differs from %s (%d)", 517204431Sraj node->fullpath, c_size_cells, node->parent->fullpath, 518204431Sraj p_size_cells); 519204431Sraj } else if ((prop->val.len % entrylen) != 0) { 520204431Sraj FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) " 521204431Sraj "(parent #address-cells == %d, child #address-cells == %d, " 522204431Sraj "#size-cells == %d)", node->fullpath, prop->val.len, 523204431Sraj p_addr_cells, c_addr_cells, c_size_cells); 524204431Sraj } 525204431Sraj} 526204431SrajNODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells); 527204431Sraj 528204431Sraj/* 529204431Sraj * Style checks 530204431Sraj */ 531204431Srajstatic void check_avoid_default_addr_size(struct check *c, struct node *dt, 532204431Sraj struct node *node) 533204431Sraj{ 534204431Sraj struct property *reg, *ranges; 535204431Sraj 536204431Sraj if (!node->parent) 537204431Sraj return; /* Ignore root node */ 538204431Sraj 539204431Sraj reg = get_property(node, "reg"); 540204431Sraj ranges = get_property(node, "ranges"); 541204431Sraj 542204431Sraj if (!reg && !ranges) 543204431Sraj return; 544204431Sraj 545204431Sraj if ((node->parent->addr_cells == -1)) 546204431Sraj FAIL(c, "Relying on default #address-cells value for %s", 547204431Sraj node->fullpath); 548204431Sraj 549204431Sraj if ((node->parent->size_cells == -1)) 550204431Sraj FAIL(c, "Relying on default #size-cells value for %s", 551204431Sraj node->fullpath); 552204431Sraj} 553204431SrajNODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells); 554204431Sraj 555204431Srajstatic void check_obsolete_chosen_interrupt_controller(struct check *c, 556204431Sraj struct node *dt) 557204431Sraj{ 558204431Sraj struct node *chosen; 559204431Sraj struct property *prop; 560204431Sraj 561204431Sraj chosen = get_node_by_path(dt, "/chosen"); 562204431Sraj if (!chosen) 563204431Sraj return; 564204431Sraj 565204431Sraj prop = get_property(chosen, "interrupt-controller"); 566204431Sraj if (prop) 567204431Sraj FAIL(c, "/chosen has obsolete \"interrupt-controller\" " 568204431Sraj "property"); 569204431Sraj} 570204431SrajTREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN); 571204431Sraj 572204431Srajstatic struct check *check_table[] = { 573204431Sraj &duplicate_node_names, &duplicate_property_names, 574204431Sraj &node_name_chars, &node_name_format, &property_name_chars, 575204431Sraj &name_is_string, &name_properties, 576204431Sraj &explicit_phandles, 577204431Sraj &phandle_references, &path_references, 578204431Sraj 579204431Sraj &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell, 580204431Sraj &device_type_is_string, &model_is_string, &status_is_string, 581204431Sraj 582204431Sraj &addr_size_cells, ®_format, &ranges_format, 583204431Sraj 584204431Sraj &avoid_default_addr_size, 585204431Sraj &obsolete_chosen_interrupt_controller, 586204431Sraj}; 587204431Sraj 588204431Srajvoid process_checks(int force, struct boot_info *bi) 589204431Sraj{ 590204431Sraj struct node *dt = bi->dt; 591204431Sraj int i; 592204431Sraj int error = 0; 593204431Sraj 594204431Sraj for (i = 0; i < ARRAY_SIZE(check_table); i++) { 595204431Sraj struct check *c = check_table[i]; 596204431Sraj 597204431Sraj if (c->level != IGNORE) 598204431Sraj error = error || run_check(c, dt); 599204431Sraj } 600204431Sraj 601204431Sraj if (error) { 602204431Sraj if (!force) { 603204431Sraj fprintf(stderr, "ERROR: Input tree has errors, aborting " 604204431Sraj "(use -f to force output)\n"); 605204431Sraj exit(2); 606204431Sraj } else if (quiet < 3) { 607204431Sraj fprintf(stderr, "Warning: Input tree has errors, " 608204431Sraj "output forced\n"); 609204431Sraj } 610204431Sraj } 611204431Sraj} 612