symbian-qemu-0.9.1-12/dtc-trunk/checks.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * (C) Copyright David Gibson <dwg@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 checklevel {
       
    35 	IGNORE = 0,
       
    36 	WARN = 1,
       
    37 	ERROR = 2,
       
    38 };
       
    39 
       
    40 enum checkstatus {
       
    41 	UNCHECKED = 0,
       
    42 	PREREQ,
       
    43 	PASSED,
       
    44 	FAILED,
       
    45 };
       
    46 
       
    47 struct check;
       
    48 
       
    49 typedef void (*tree_check_fn)(struct check *c, struct node *dt);
       
    50 typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node);
       
    51 typedef void (*prop_check_fn)(struct check *c, struct node *dt,
       
    52 			      struct node *node, struct property *prop);
       
    53 
       
    54 struct check {
       
    55 	const char *name;
       
    56 	tree_check_fn tree_fn;
       
    57 	node_check_fn node_fn;
       
    58 	prop_check_fn prop_fn;
       
    59 	void *data;
       
    60 	enum checklevel level;
       
    61 	enum checkstatus status;
       
    62 	int inprogress;
       
    63 	int num_prereqs;
       
    64 	struct check **prereq;
       
    65 };
       
    66 
       
    67 #define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \
       
    68 	static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
       
    69 	static struct check nm = { \
       
    70 		.name = #nm, \
       
    71 		.tree_fn = (tfn), \
       
    72 		.node_fn = (nfn), \
       
    73 		.prop_fn = (pfn), \
       
    74 		.data = (d), \
       
    75 		.level = (lvl), \
       
    76 		.status = UNCHECKED, \
       
    77 		.num_prereqs = ARRAY_SIZE(nm##_prereqs), \
       
    78 		.prereq = nm##_prereqs, \
       
    79 	};
       
    80 
       
    81 #define TREE_CHECK(nm, d, lvl, ...) \
       
    82 	CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__)
       
    83 #define NODE_CHECK(nm, d, lvl, ...) \
       
    84 	CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__)
       
    85 #define PROP_CHECK(nm, d, lvl, ...) \
       
    86 	CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__)
       
    87 #define BATCH_CHECK(nm, lvl, ...) \
       
    88 	CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__)
       
    89 
       
    90 #ifdef __GNUC__
       
    91 static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
       
    92 #endif
       
    93 static inline void check_msg(struct check *c, const char *fmt, ...)
       
    94 {
       
    95 	va_list ap;
       
    96 	va_start(ap, fmt);
       
    97 
       
    98 	if ((c->level < WARN) || (c->level <= quiet))
       
    99 		return; /* Suppress message */
       
   100 
       
   101 	fprintf(stderr, "%s (%s): ",
       
   102 		(c->level == ERROR) ? "ERROR" : "Warning", c->name);
       
   103 	vfprintf(stderr, fmt, ap);
       
   104 	fprintf(stderr, "\n");
       
   105 }
       
   106 
       
   107 #define FAIL(c, ...) \
       
   108 	do { \
       
   109 		TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
       
   110 		(c)->status = FAILED; \
       
   111 		check_msg((c), __VA_ARGS__); \
       
   112 	} while (0)
       
   113 
       
   114 static void check_nodes_props(struct check *c, struct node *dt, struct node *node)
       
   115 {
       
   116 	struct node *child;
       
   117 	struct property *prop;
       
   118 
       
   119 	TRACE(c, "%s", node->fullpath);
       
   120 	if (c->node_fn)
       
   121 		c->node_fn(c, dt, node);
       
   122 
       
   123 	if (c->prop_fn)
       
   124 		for_each_property(node, prop) {
       
   125 			TRACE(c, "%s\t'%s'", node->fullpath, prop->name);
       
   126 			c->prop_fn(c, dt, node, prop);
       
   127 		}
       
   128 
       
   129 	for_each_child(node, child)
       
   130 		check_nodes_props(c, dt, child);
       
   131 }
       
   132 
       
   133 static int run_check(struct check *c, struct node *dt)
       
   134 {
       
   135 	int error = 0;
       
   136 	int i;
       
   137 
       
   138 	assert(!c->inprogress);
       
   139 
       
   140 	if (c->status != UNCHECKED)
       
   141 		goto out;
       
   142 
       
   143 	c->inprogress = 1;
       
   144 
       
   145 	for (i = 0; i < c->num_prereqs; i++) {
       
   146 		struct check *prq = c->prereq[i];
       
   147 		error |= run_check(prq, dt);
       
   148 		if (prq->status != PASSED) {
       
   149 			c->status = PREREQ;
       
   150 			check_msg(c, "Failed prerequisite '%s'",
       
   151 				  c->prereq[i]->name);
       
   152 		}
       
   153 	}
       
   154 
       
   155 	if (c->status != UNCHECKED)
       
   156 		goto out;
       
   157 
       
   158 	if (c->node_fn || c->prop_fn)
       
   159 		check_nodes_props(c, dt, dt);
       
   160 
       
   161 	if (c->tree_fn)
       
   162 		c->tree_fn(c, dt);
       
   163 	if (c->status == UNCHECKED)
       
   164 		c->status = PASSED;
       
   165 
       
   166 	TRACE(c, "\tCompleted, status %d", c->status);
       
   167 
       
   168 out:
       
   169 	c->inprogress = 0;
       
   170 	if ((c->status != PASSED) && (c->level == ERROR))
       
   171 		error = 1;
       
   172 	return error;
       
   173 }
       
   174 
       
   175 /*
       
   176  * Utility check functions
       
   177  */
       
   178 
       
   179 static void check_is_string(struct check *c, struct node *root,
       
   180 			    struct node *node)
       
   181 {
       
   182 	struct property *prop;
       
   183 	char *propname = c->data;
       
   184 
       
   185 	prop = get_property(node, propname);
       
   186 	if (!prop)
       
   187 		return; /* Not present, assumed ok */
       
   188 
       
   189 	if (!data_is_one_string(prop->val))
       
   190 		FAIL(c, "\"%s\" property in %s is not a string",
       
   191 		     propname, node->fullpath);
       
   192 }
       
   193 #define CHECK_IS_STRING(nm, propname, lvl) \
       
   194 	CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl))
       
   195 
       
   196 static void check_is_cell(struct check *c, struct node *root,
       
   197 			  struct node *node)
       
   198 {
       
   199 	struct property *prop;
       
   200 	char *propname = c->data;
       
   201 
       
   202 	prop = get_property(node, propname);
       
   203 	if (!prop)
       
   204 		return; /* Not present, assumed ok */
       
   205 
       
   206 	if (prop->val.len != sizeof(cell_t))
       
   207 		FAIL(c, "\"%s\" property in %s is not a single cell",
       
   208 		     propname, node->fullpath);
       
   209 }
       
   210 #define CHECK_IS_CELL(nm, propname, lvl) \
       
   211 	CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl))
       
   212 
       
   213 /*
       
   214  * Structural check functions
       
   215  */
       
   216 
       
   217 static void check_duplicate_node_names(struct check *c, struct node *dt,
       
   218 				       struct node *node)
       
   219 {
       
   220 	struct node *child, *child2;
       
   221 
       
   222 	for_each_child(node, child)
       
   223 		for (child2 = child->next_sibling;
       
   224 		     child2;
       
   225 		     child2 = child2->next_sibling)
       
   226 			if (streq(child->name, child2->name))
       
   227 				FAIL(c, "Duplicate node name %s",
       
   228 				     child->fullpath);
       
   229 }
       
   230 NODE_CHECK(duplicate_node_names, NULL, ERROR);
       
   231 
       
   232 static void check_duplicate_property_names(struct check *c, struct node *dt,
       
   233 					   struct node *node)
       
   234 {
       
   235 	struct property *prop, *prop2;
       
   236 
       
   237 	for_each_property(node, prop)
       
   238 		for (prop2 = prop->next; prop2; prop2 = prop2->next)
       
   239 			if (streq(prop->name, prop2->name))
       
   240 				FAIL(c, "Duplicate property name %s in %s",
       
   241 				     prop->name, node->fullpath);
       
   242 }
       
   243 NODE_CHECK(duplicate_property_names, NULL, ERROR);
       
   244 
       
   245 #define LOWERCASE	"abcdefghijklmnopqrstuvwxyz"
       
   246 #define UPPERCASE	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
       
   247 #define DIGITS		"0123456789"
       
   248 #define PROPNODECHARS	LOWERCASE UPPERCASE DIGITS ",._+*#?-"
       
   249 
       
   250 static void check_node_name_chars(struct check *c, struct node *dt,
       
   251 				  struct node *node)
       
   252 {
       
   253 	int n = strspn(node->name, c->data);
       
   254 
       
   255 	if (n < strlen(node->name))
       
   256 		FAIL(c, "Bad character '%c' in node %s",
       
   257 		     node->name[n], node->fullpath);
       
   258 }
       
   259 NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);
       
   260 
       
   261 static void check_node_name_format(struct check *c, struct node *dt,
       
   262 				   struct node *node)
       
   263 {
       
   264 	if (strchr(get_unitname(node), '@'))
       
   265 		FAIL(c, "Node %s has multiple '@' characters in name",
       
   266 		     node->fullpath);
       
   267 }
       
   268 NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);
       
   269 
       
   270 static void check_property_name_chars(struct check *c, struct node *dt,
       
   271 				      struct node *node, struct property *prop)
       
   272 {
       
   273 	int n = strspn(prop->name, c->data);
       
   274 
       
   275 	if (n < strlen(prop->name))
       
   276 		FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
       
   277 		     prop->name[n], prop->name, node->fullpath);
       
   278 }
       
   279 PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);
       
   280 
       
   281 static void check_explicit_phandles(struct check *c, struct node *root,
       
   282 					  struct node *node)
       
   283 {
       
   284 	struct property *prop;
       
   285 	struct node *other;
       
   286 	cell_t phandle;
       
   287 
       
   288 	prop = get_property(node, "linux,phandle");
       
   289 	if (! prop)
       
   290 		return; /* No phandle, that's fine */
       
   291 
       
   292 	if (prop->val.len != sizeof(cell_t)) {
       
   293 		FAIL(c, "%s has bad length (%d) linux,phandle property",
       
   294 		     node->fullpath, prop->val.len);
       
   295 		return;
       
   296 	}
       
   297 
       
   298 	phandle = propval_cell(prop);
       
   299 	if ((phandle == 0) || (phandle == -1)) {
       
   300 		FAIL(c, "%s has invalid linux,phandle value 0x%x",
       
   301 		     node->fullpath, phandle);
       
   302 		return;
       
   303 	}
       
   304 
       
   305 	other = get_node_by_phandle(root, phandle);
       
   306 	if (other) {
       
   307 		FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
       
   308 		     node->fullpath, phandle, other->fullpath);
       
   309 		return;
       
   310 	}
       
   311 
       
   312 	node->phandle = phandle;
       
   313 }
       
   314 NODE_CHECK(explicit_phandles, NULL, ERROR);
       
   315 
       
   316 static void check_name_properties(struct check *c, struct node *root,
       
   317 				  struct node *node)
       
   318 {
       
   319 	struct property **pp, *prop = NULL;
       
   320 
       
   321 	for (pp = &node->proplist; *pp; pp = &((*pp)->next))
       
   322 		if (streq((*pp)->name, "name")) {
       
   323 			prop = *pp;
       
   324 			break;
       
   325 		}
       
   326 
       
   327 	if (!prop)
       
   328 		return; /* No name property, that's fine */
       
   329 
       
   330 	if ((prop->val.len != node->basenamelen+1)
       
   331 	    || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
       
   332 		FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
       
   333 		     " of base node name)", node->fullpath, prop->val.val);
       
   334 	} else {
       
   335 		/* The name property is correct, and therefore redundant.
       
   336 		 * Delete it */
       
   337 		*pp = prop->next;
       
   338 		free(prop->name);
       
   339 		data_free(prop->val);
       
   340 		free(prop);
       
   341 	}
       
   342 }
       
   343 CHECK_IS_STRING(name_is_string, "name", ERROR);
       
   344 NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
       
   345 
       
   346 /*
       
   347  * Reference fixup functions
       
   348  */
       
   349 
       
   350 static void fixup_phandle_references(struct check *c, struct node *dt,
       
   351 				     struct node *node, struct property *prop)
       
   352 {
       
   353 	struct marker *m = prop->val.markers;
       
   354 	struct node *refnode;
       
   355 	cell_t phandle;
       
   356 
       
   357 	for_each_marker_of_type(m, REF_PHANDLE) {
       
   358 		assert(m->offset + sizeof(cell_t) <= prop->val.len);
       
   359 
       
   360 		refnode = get_node_by_ref(dt, m->ref);
       
   361 		if (! refnode) {
       
   362 			FAIL(c, "Reference to non-existent node or label \"%s\"\n",
       
   363 			     m->ref);
       
   364 			continue;
       
   365 		}
       
   366 
       
   367 		phandle = get_node_phandle(dt, refnode);
       
   368 		*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
       
   369 	}
       
   370 }
       
   371 CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
       
   372       &duplicate_node_names, &explicit_phandles);
       
   373 
       
   374 static void fixup_path_references(struct check *c, struct node *dt,
       
   375 				  struct node *node, struct property *prop)
       
   376 {
       
   377 	struct marker *m = prop->val.markers;
       
   378 	struct node *refnode;
       
   379 	char *path;
       
   380 
       
   381 	for_each_marker_of_type(m, REF_PATH) {
       
   382 		assert(m->offset <= prop->val.len);
       
   383 
       
   384 		refnode = get_node_by_ref(dt, m->ref);
       
   385 		if (!refnode) {
       
   386 			FAIL(c, "Reference to non-existent node or label \"%s\"\n",
       
   387 			     m->ref);
       
   388 			continue;
       
   389 		}
       
   390 
       
   391 		path = refnode->fullpath;
       
   392 		prop->val = data_insert_at_marker(prop->val, m, path,
       
   393 						  strlen(path) + 1);
       
   394 	}
       
   395 }
       
   396 CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR,
       
   397       &duplicate_node_names);
       
   398 
       
   399 /*
       
   400  * Semantic checks
       
   401  */
       
   402 CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN);
       
   403 CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
       
   404 CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
       
   405 
       
   406 CHECK_IS_STRING(device_type_is_string, "device_type", WARN);
       
   407 CHECK_IS_STRING(model_is_string, "model", WARN);
       
   408 CHECK_IS_STRING(status_is_string, "status", WARN);
       
   409 
       
   410 static void fixup_addr_size_cells(struct check *c, struct node *dt,
       
   411 				  struct node *node)
       
   412 {
       
   413 	struct property *prop;
       
   414 
       
   415 	node->addr_cells = -1;
       
   416 	node->size_cells = -1;
       
   417 
       
   418 	prop = get_property(node, "#address-cells");
       
   419 	if (prop)
       
   420 		node->addr_cells = propval_cell(prop);
       
   421 
       
   422 	prop = get_property(node, "#size-cells");
       
   423 	if (prop)
       
   424 		node->size_cells = propval_cell(prop);
       
   425 }
       
   426 CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN,
       
   427       &address_cells_is_cell, &size_cells_is_cell);
       
   428 
       
   429 #define node_addr_cells(n) \
       
   430 	(((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
       
   431 #define node_size_cells(n) \
       
   432 	(((n)->size_cells == -1) ? 1 : (n)->size_cells)
       
   433 
       
   434 static void check_reg_format(struct check *c, struct node *dt,
       
   435 			     struct node *node)
       
   436 {
       
   437 	struct property *prop;
       
   438 	int addr_cells, size_cells, entrylen;
       
   439 
       
   440 	prop = get_property(node, "reg");
       
   441 	if (!prop)
       
   442 		return; /* No "reg", that's fine */
       
   443 
       
   444 	if (!node->parent) {
       
   445 		FAIL(c, "Root node has a \"reg\" property");
       
   446 		return;
       
   447 	}
       
   448 
       
   449 	if (prop->val.len == 0)
       
   450 		FAIL(c, "\"reg\" property in %s is empty", node->fullpath);
       
   451 
       
   452 	addr_cells = node_addr_cells(node->parent);
       
   453 	size_cells = node_size_cells(node->parent);
       
   454 	entrylen = (addr_cells + size_cells) * sizeof(cell_t);
       
   455 
       
   456 	if ((prop->val.len % entrylen) != 0)
       
   457 		FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
       
   458 		     "(#address-cells == %d, #size-cells == %d)",
       
   459 		     node->fullpath, prop->val.len, addr_cells, size_cells);
       
   460 }
       
   461 NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells);
       
   462 
       
   463 static void check_ranges_format(struct check *c, struct node *dt,
       
   464 				struct node *node)
       
   465 {
       
   466 	struct property *prop;
       
   467 	int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen;
       
   468 
       
   469 	prop = get_property(node, "ranges");
       
   470 	if (!prop)
       
   471 		return;
       
   472 
       
   473 	if (!node->parent) {
       
   474 		FAIL(c, "Root node has a \"ranges\" property");
       
   475 		return;
       
   476 	}
       
   477 
       
   478 	p_addr_cells = node_addr_cells(node->parent);
       
   479 	p_size_cells = node_size_cells(node->parent);
       
   480 	c_addr_cells = node_addr_cells(node);
       
   481 	c_size_cells = node_size_cells(node);
       
   482 	entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t);
       
   483 
       
   484 	if (prop->val.len == 0) {
       
   485 		if (p_addr_cells != c_addr_cells)
       
   486 			FAIL(c, "%s has empty \"ranges\" property but its "
       
   487 			     "#address-cells (%d) differs from %s (%d)",
       
   488 			     node->fullpath, c_addr_cells, node->parent->fullpath,
       
   489 			     p_addr_cells);
       
   490 		if (p_size_cells != c_size_cells)
       
   491 			FAIL(c, "%s has empty \"ranges\" property but its "
       
   492 			     "#size-cells (%d) differs from %s (%d)",
       
   493 			     node->fullpath, c_size_cells, node->parent->fullpath,
       
   494 			     p_size_cells);
       
   495 	} else if ((prop->val.len % entrylen) != 0) {
       
   496 		FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) "
       
   497 		     "(parent #address-cells == %d, child #address-cells == %d, "
       
   498 		     "#size-cells == %d)", node->fullpath, prop->val.len,
       
   499 		     p_addr_cells, c_addr_cells, c_size_cells);
       
   500 	}
       
   501 }
       
   502 NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells);
       
   503 
       
   504 /*
       
   505  * Style checks
       
   506  */
       
   507 static void check_avoid_default_addr_size(struct check *c, struct node *dt,
       
   508 					  struct node *node)
       
   509 {
       
   510 	struct property *reg, *ranges;
       
   511 
       
   512 	if (!node->parent)
       
   513 		return; /* Ignore root node */
       
   514 
       
   515 	reg = get_property(node, "reg");
       
   516 	ranges = get_property(node, "ranges");
       
   517 
       
   518 	if (!reg && !ranges)
       
   519 		return;
       
   520 
       
   521 	if ((node->parent->addr_cells == -1))
       
   522 		FAIL(c, "Relying on default #address-cells value for %s",
       
   523 		     node->fullpath);
       
   524 
       
   525 	if ((node->parent->size_cells == -1))
       
   526 		FAIL(c, "Relying on default #size-cells value for %s",
       
   527 		     node->fullpath);
       
   528 }
       
   529 NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells);
       
   530 
       
   531 static void check_obsolete_chosen_interrupt_controller(struct check *c,
       
   532 						       struct node *dt)
       
   533 {
       
   534 	struct node *chosen;
       
   535 	struct property *prop;
       
   536 
       
   537 	chosen = get_node_by_path(dt, "/chosen");
       
   538 	if (!chosen)
       
   539 		return;
       
   540 
       
   541 	prop = get_property(chosen, "interrupt-controller");
       
   542 	if (prop)
       
   543 		FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
       
   544 		     "property");
       
   545 }
       
   546 TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
       
   547 
       
   548 static struct check *check_table[] = {
       
   549 	&duplicate_node_names, &duplicate_property_names,
       
   550 	&node_name_chars, &node_name_format, &property_name_chars,
       
   551 	&name_is_string, &name_properties,
       
   552 	&explicit_phandles,
       
   553 	&phandle_references, &path_references,
       
   554 
       
   555 	&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
       
   556 	&device_type_is_string, &model_is_string, &status_is_string,
       
   557 
       
   558 	&addr_size_cells, &reg_format, &ranges_format,
       
   559 
       
   560 	&avoid_default_addr_size,
       
   561 	&obsolete_chosen_interrupt_controller,
       
   562 };
       
   563 
       
   564 void process_checks(int force, struct boot_info *bi)
       
   565 {
       
   566 	struct node *dt = bi->dt;
       
   567 	int i;
       
   568 	int error = 0;
       
   569 
       
   570 	for (i = 0; i < ARRAY_SIZE(check_table); i++) {
       
   571 		struct check *c = check_table[i];
       
   572 
       
   573 		if (c->level != IGNORE)
       
   574 			error = error || run_check(c, dt);
       
   575 	}
       
   576 
       
   577 	if (error) {
       
   578 		if (!force) {
       
   579 			fprintf(stderr, "ERROR: Input tree has errors, aborting "
       
   580 				"(use -f to force output)\n");
       
   581 			exit(2);
       
   582 		} else if (quiet < 3) {
       
   583 			fprintf(stderr, "Warning: Input tree has errors, "
       
   584 				"output forced\n");
       
   585 		}
       
   586 	}
       
   587 }