Home | History | Annotate | Download | only in dtc
      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, &reg_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