checks.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  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. #include "dtc.h"
  21. #ifdef TRACE_CHECKS
  22. #define TRACE(c, ...) \
  23. do { \
  24. fprintf(stderr, "=== %s: ", (c)->name); \
  25. fprintf(stderr, __VA_ARGS__); \
  26. fprintf(stderr, "\n"); \
  27. } while (0)
  28. #else
  29. #define TRACE(c, fmt, ...) do { } while (0)
  30. #endif
  31. enum checkstatus {
  32. UNCHECKED = 0,
  33. PREREQ,
  34. PASSED,
  35. FAILED,
  36. };
  37. struct check;
  38. typedef void (*tree_check_fn)(struct check *c, struct node *dt);
  39. typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node);
  40. typedef void (*prop_check_fn)(struct check *c, struct node *dt,
  41. struct node *node, struct property *prop);
  42. struct check {
  43. const char *name;
  44. tree_check_fn tree_fn;
  45. node_check_fn node_fn;
  46. prop_check_fn prop_fn;
  47. void *data;
  48. bool warn, error;
  49. enum checkstatus status;
  50. bool inprogress;
  51. int num_prereqs;
  52. struct check **prereq;
  53. };
  54. #define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...) \
  55. static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
  56. static struct check nm = { \
  57. .name = #nm, \
  58. .tree_fn = (tfn), \
  59. .node_fn = (nfn), \
  60. .prop_fn = (pfn), \
  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, tfn, nfn, pfn, d, ...) \
  69. CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
  70. #define ERROR(nm, tfn, nfn, pfn, d, ...) \
  71. CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__)
  72. #define CHECK(nm, tfn, nfn, pfn, d, ...) \
  73. CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__)
  74. #define TREE_WARNING(nm, d, ...) \
  75. WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
  76. #define TREE_ERROR(nm, d, ...) \
  77. ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
  78. #define TREE_CHECK(nm, d, ...) \
  79. CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
  80. #define NODE_WARNING(nm, d, ...) \
  81. WARNING(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
  82. #define NODE_ERROR(nm, d, ...) \
  83. ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
  84. #define NODE_CHECK(nm, d, ...) \
  85. CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
  86. #define PROP_WARNING(nm, d, ...) \
  87. WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
  88. #define PROP_ERROR(nm, d, ...) \
  89. ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
  90. #define PROP_CHECK(nm, d, ...) \
  91. CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
  92. #ifdef __GNUC__
  93. static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
  94. #endif
  95. static inline void check_msg(struct check *c, const char *fmt, ...)
  96. {
  97. va_list ap;
  98. va_start(ap, fmt);
  99. if ((c->warn && (quiet < 1))
  100. || (c->error && (quiet < 2))) {
  101. fprintf(stderr, "%s (%s): ",
  102. (c->error) ? "ERROR" : "Warning", c->name);
  103. vfprintf(stderr, fmt, ap);
  104. fprintf(stderr, "\n");
  105. }
  106. va_end(ap);
  107. }
  108. #define FAIL(c, ...) \
  109. do { \
  110. TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
  111. (c)->status = FAILED; \
  112. check_msg((c), __VA_ARGS__); \
  113. } while (0)
  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. TRACE(c, "%s", node->fullpath);
  119. if (c->node_fn)
  120. c->node_fn(c, dt, node);
  121. if (c->prop_fn)
  122. for_each_property(node, prop) {
  123. TRACE(c, "%s\t'%s'", node->fullpath, prop->name);
  124. c->prop_fn(c, dt, node, prop);
  125. }
  126. for_each_child(node, child)
  127. check_nodes_props(c, dt, child);
  128. }
  129. static bool run_check(struct check *c, struct node *dt)
  130. {
  131. bool error = false;
  132. int i;
  133. assert(!c->inprogress);
  134. if (c->status != UNCHECKED)
  135. goto out;
  136. c->inprogress = true;
  137. for (i = 0; i < c->num_prereqs; i++) {
  138. struct check *prq = c->prereq[i];
  139. error = error || run_check(prq, dt);
  140. if (prq->status != PASSED) {
  141. c->status = PREREQ;
  142. check_msg(c, "Failed prerequisite '%s'",
  143. c->prereq[i]->name);
  144. }
  145. }
  146. if (c->status != UNCHECKED)
  147. goto out;
  148. if (c->node_fn || c->prop_fn)
  149. check_nodes_props(c, dt, dt);
  150. if (c->tree_fn)
  151. c->tree_fn(c, dt);
  152. if (c->status == UNCHECKED)
  153. c->status = PASSED;
  154. TRACE(c, "\tCompleted, status %d", c->status);
  155. out:
  156. c->inprogress = false;
  157. if ((c->status != PASSED) && (c->error))
  158. error = true;
  159. return error;
  160. }
  161. /*
  162. * Utility check functions
  163. */
  164. /* A check which always fails, for testing purposes only */
  165. static inline void check_always_fail(struct check *c, struct node *dt)
  166. {
  167. FAIL(c, "always_fail check");
  168. }
  169. TREE_CHECK(always_fail, NULL);
  170. static void check_is_string(struct check *c, struct node *root,
  171. struct node *node)
  172. {
  173. struct property *prop;
  174. char *propname = c->data;
  175. prop = get_property(node, propname);
  176. if (!prop)
  177. return; /* Not present, assumed ok */
  178. if (!data_is_one_string(prop->val))
  179. FAIL(c, "\"%s\" property in %s is not a string",
  180. propname, node->fullpath);
  181. }
  182. #define WARNING_IF_NOT_STRING(nm, propname) \
  183. WARNING(nm, NULL, check_is_string, NULL, (propname))
  184. #define ERROR_IF_NOT_STRING(nm, propname) \
  185. ERROR(nm, NULL, check_is_string, NULL, (propname))
  186. static void check_is_cell(struct check *c, struct node *root,
  187. struct node *node)
  188. {
  189. struct property *prop;
  190. char *propname = c->data;
  191. prop = get_property(node, propname);
  192. if (!prop)
  193. return; /* Not present, assumed ok */
  194. if (prop->val.len != sizeof(cell_t))
  195. FAIL(c, "\"%s\" property in %s is not a single cell",
  196. propname, node->fullpath);
  197. }
  198. #define WARNING_IF_NOT_CELL(nm, propname) \
  199. WARNING(nm, NULL, check_is_cell, NULL, (propname))
  200. #define ERROR_IF_NOT_CELL(nm, propname) \
  201. ERROR(nm, NULL, check_is_cell, NULL, (propname))
  202. /*
  203. * Structural check functions
  204. */
  205. static void check_duplicate_node_names(struct check *c, struct node *dt,
  206. struct node *node)
  207. {
  208. struct node *child, *child2;
  209. for_each_child(node, child)
  210. for (child2 = child->next_sibling;
  211. child2;
  212. child2 = child2->next_sibling)
  213. if (streq(child->name, child2->name))
  214. FAIL(c, "Duplicate node name %s",
  215. child->fullpath);
  216. }
  217. NODE_ERROR(duplicate_node_names, NULL);
  218. static void check_duplicate_property_names(struct check *c, struct node *dt,
  219. struct node *node)
  220. {
  221. struct property *prop, *prop2;
  222. for_each_property(node, prop) {
  223. for (prop2 = prop->next; prop2; prop2 = prop2->next) {
  224. if (prop2->deleted)
  225. continue;
  226. if (streq(prop->name, prop2->name))
  227. FAIL(c, "Duplicate property name %s in %s",
  228. prop->name, node->fullpath);
  229. }
  230. }
  231. }
  232. NODE_ERROR(duplicate_property_names, NULL);
  233. #define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
  234. #define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  235. #define DIGITS "0123456789"
  236. #define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
  237. static void check_node_name_chars(struct check *c, struct node *dt,
  238. struct node *node)
  239. {
  240. int n = strspn(node->name, c->data);
  241. if (n < strlen(node->name))
  242. FAIL(c, "Bad character '%c' in node %s",
  243. node->name[n], node->fullpath);
  244. }
  245. NODE_ERROR(node_name_chars, PROPNODECHARS "@");
  246. static void check_node_name_format(struct check *c, struct node *dt,
  247. struct node *node)
  248. {
  249. if (strchr(get_unitname(node), '@'))
  250. FAIL(c, "Node %s has multiple '@' characters in name",
  251. node->fullpath);
  252. }
  253. NODE_ERROR(node_name_format, NULL, &node_name_chars);
  254. static void check_unit_address_vs_reg(struct check *c, struct node *dt,
  255. struct node *node)
  256. {
  257. const char *unitname = get_unitname(node);
  258. struct property *prop = get_property(node, "reg");
  259. if (!prop) {
  260. prop = get_property(node, "ranges");
  261. if (prop && !prop->val.len)
  262. prop = NULL;
  263. }
  264. if (prop) {
  265. if (!unitname[0])
  266. FAIL(c, "Node %s has a reg or ranges property, but no unit name",
  267. node->fullpath);
  268. } else {
  269. if (unitname[0])
  270. FAIL(c, "Node %s has a unit name, but no reg property",
  271. node->fullpath);
  272. }
  273. }
  274. NODE_WARNING(unit_address_vs_reg, NULL);
  275. static void check_property_name_chars(struct check *c, struct node *dt,
  276. struct node *node, struct property *prop)
  277. {
  278. int n = strspn(prop->name, c->data);
  279. if (n < strlen(prop->name))
  280. FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
  281. prop->name[n], prop->name, node->fullpath);
  282. }
  283. PROP_ERROR(property_name_chars, PROPNODECHARS);
  284. #define DESCLABEL_FMT "%s%s%s%s%s"
  285. #define DESCLABEL_ARGS(node,prop,mark) \
  286. ((mark) ? "value of " : ""), \
  287. ((prop) ? "'" : ""), \
  288. ((prop) ? (prop)->name : ""), \
  289. ((prop) ? "' in " : ""), (node)->fullpath
  290. static void check_duplicate_label(struct check *c, struct node *dt,
  291. const char *label, struct node *node,
  292. struct property *prop, struct marker *mark)
  293. {
  294. struct node *othernode = NULL;
  295. struct property *otherprop = NULL;
  296. struct marker *othermark = NULL;
  297. othernode = get_node_by_label(dt, label);
  298. if (!othernode)
  299. otherprop = get_property_by_label(dt, label, &othernode);
  300. if (!othernode)
  301. othermark = get_marker_label(dt, label, &othernode,
  302. &otherprop);
  303. if (!othernode)
  304. return;
  305. if ((othernode != node) || (otherprop != prop) || (othermark != mark))
  306. FAIL(c, "Duplicate label '%s' on " DESCLABEL_FMT
  307. " and " DESCLABEL_FMT,
  308. label, DESCLABEL_ARGS(node, prop, mark),
  309. DESCLABEL_ARGS(othernode, otherprop, othermark));
  310. }
  311. static void check_duplicate_label_node(struct check *c, struct node *dt,
  312. struct node *node)
  313. {
  314. struct label *l;
  315. for_each_label(node->labels, l)
  316. check_duplicate_label(c, dt, l->label, node, NULL, NULL);
  317. }
  318. static void check_duplicate_label_prop(struct check *c, struct node *dt,
  319. struct node *node, struct property *prop)
  320. {
  321. struct marker *m = prop->val.markers;
  322. struct label *l;
  323. for_each_label(prop->labels, l)
  324. check_duplicate_label(c, dt, l->label, node, prop, NULL);
  325. for_each_marker_of_type(m, LABEL)
  326. check_duplicate_label(c, dt, m->ref, node, prop, m);
  327. }
  328. ERROR(duplicate_label, NULL, check_duplicate_label_node,
  329. check_duplicate_label_prop, NULL);
  330. static void check_explicit_phandles(struct check *c, struct node *root,
  331. struct node *node, struct property *prop)
  332. {
  333. struct marker *m;
  334. struct node *other;
  335. cell_t phandle;
  336. if (!streq(prop->name, "phandle")
  337. && !streq(prop->name, "linux,phandle"))
  338. return;
  339. if (prop->val.len != sizeof(cell_t)) {
  340. FAIL(c, "%s has bad length (%d) %s property",
  341. node->fullpath, prop->val.len, prop->name);
  342. return;
  343. }
  344. m = prop->val.markers;
  345. for_each_marker_of_type(m, REF_PHANDLE) {
  346. assert(m->offset == 0);
  347. if (node != get_node_by_ref(root, m->ref))
  348. /* "Set this node's phandle equal to some
  349. * other node's phandle". That's nonsensical
  350. * by construction. */ {
  351. FAIL(c, "%s in %s is a reference to another node",
  352. prop->name, node->fullpath);
  353. return;
  354. }
  355. /* But setting this node's phandle equal to its own
  356. * phandle is allowed - that means allocate a unique
  357. * phandle for this node, even if it's not otherwise
  358. * referenced. The value will be filled in later, so
  359. * no further checking for now. */
  360. return;
  361. }
  362. phandle = propval_cell(prop);
  363. if ((phandle == 0) || (phandle == -1)) {
  364. FAIL(c, "%s has bad value (0x%x) in %s property",
  365. node->fullpath, phandle, prop->name);
  366. return;
  367. }
  368. if (node->phandle && (node->phandle != phandle))
  369. FAIL(c, "%s has %s property which replaces existing phandle information",
  370. node->fullpath, prop->name);
  371. other = get_node_by_phandle(root, phandle);
  372. if (other && (other != node)) {
  373. FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
  374. node->fullpath, phandle, other->fullpath);
  375. return;
  376. }
  377. node->phandle = phandle;
  378. }
  379. PROP_ERROR(explicit_phandles, NULL);
  380. static void check_name_properties(struct check *c, struct node *root,
  381. struct node *node)
  382. {
  383. struct property **pp, *prop = NULL;
  384. for (pp = &node->proplist; *pp; pp = &((*pp)->next))
  385. if (streq((*pp)->name, "name")) {
  386. prop = *pp;
  387. break;
  388. }
  389. if (!prop)
  390. return; /* No name property, that's fine */
  391. if ((prop->val.len != node->basenamelen+1)
  392. || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
  393. FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
  394. " of base node name)", node->fullpath, prop->val.val);
  395. } else {
  396. /* The name property is correct, and therefore redundant.
  397. * Delete it */
  398. *pp = prop->next;
  399. free(prop->name);
  400. data_free(prop->val);
  401. free(prop);
  402. }
  403. }
  404. ERROR_IF_NOT_STRING(name_is_string, "name");
  405. NODE_ERROR(name_properties, NULL, &name_is_string);
  406. /*
  407. * Reference fixup functions
  408. */
  409. static void fixup_phandle_references(struct check *c, struct node *dt,
  410. struct node *node, struct property *prop)
  411. {
  412. struct marker *m = prop->val.markers;
  413. struct node *refnode;
  414. cell_t phandle;
  415. for_each_marker_of_type(m, REF_PHANDLE) {
  416. assert(m->offset + sizeof(cell_t) <= prop->val.len);
  417. refnode = get_node_by_ref(dt, m->ref);
  418. if (! refnode) {
  419. FAIL(c, "Reference to non-existent node or label \"%s\"\n",
  420. m->ref);
  421. continue;
  422. }
  423. phandle = get_node_phandle(dt, refnode);
  424. *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
  425. }
  426. }
  427. ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,
  428. &duplicate_node_names, &explicit_phandles);
  429. static void fixup_path_references(struct check *c, struct node *dt,
  430. struct node *node, struct property *prop)
  431. {
  432. struct marker *m = prop->val.markers;
  433. struct node *refnode;
  434. char *path;
  435. for_each_marker_of_type(m, REF_PATH) {
  436. assert(m->offset <= prop->val.len);
  437. refnode = get_node_by_ref(dt, m->ref);
  438. if (!refnode) {
  439. FAIL(c, "Reference to non-existent node or label \"%s\"\n",
  440. m->ref);
  441. continue;
  442. }
  443. path = refnode->fullpath;
  444. prop->val = data_insert_at_marker(prop->val, m, path,
  445. strlen(path) + 1);
  446. }
  447. }
  448. ERROR(path_references, NULL, NULL, fixup_path_references, NULL,
  449. &duplicate_node_names);
  450. /*
  451. * Semantic checks
  452. */
  453. WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
  454. WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
  455. WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
  456. WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
  457. WARNING_IF_NOT_STRING(model_is_string, "model");
  458. WARNING_IF_NOT_STRING(status_is_string, "status");
  459. static void fixup_addr_size_cells(struct check *c, struct node *dt,
  460. struct node *node)
  461. {
  462. struct property *prop;
  463. node->addr_cells = -1;
  464. node->size_cells = -1;
  465. prop = get_property(node, "#address-cells");
  466. if (prop)
  467. node->addr_cells = propval_cell(prop);
  468. prop = get_property(node, "#size-cells");
  469. if (prop)
  470. node->size_cells = propval_cell(prop);
  471. }
  472. WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL,
  473. &address_cells_is_cell, &size_cells_is_cell);
  474. #define node_addr_cells(n) \
  475. (((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
  476. #define node_size_cells(n) \
  477. (((n)->size_cells == -1) ? 1 : (n)->size_cells)
  478. static void check_reg_format(struct check *c, struct node *dt,
  479. struct node *node)
  480. {
  481. struct property *prop;
  482. int addr_cells, size_cells, entrylen;
  483. prop = get_property(node, "reg");
  484. if (!prop)
  485. return; /* No "reg", that's fine */
  486. if (!node->parent) {
  487. FAIL(c, "Root node has a \"reg\" property");
  488. return;
  489. }
  490. if (prop->val.len == 0)
  491. FAIL(c, "\"reg\" property in %s is empty", node->fullpath);
  492. addr_cells = node_addr_cells(node->parent);
  493. size_cells = node_size_cells(node->parent);
  494. entrylen = (addr_cells + size_cells) * sizeof(cell_t);
  495. if (!entrylen || (prop->val.len % entrylen) != 0)
  496. FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
  497. "(#address-cells == %d, #size-cells == %d)",
  498. node->fullpath, prop->val.len, addr_cells, size_cells);
  499. }
  500. NODE_WARNING(reg_format, NULL, &addr_size_cells);
  501. static void check_ranges_format(struct check *c, struct node *dt,
  502. struct node *node)
  503. {
  504. struct property *prop;
  505. int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen;
  506. prop = get_property(node, "ranges");
  507. if (!prop)
  508. return;
  509. if (!node->parent) {
  510. FAIL(c, "Root node has a \"ranges\" property");
  511. return;
  512. }
  513. p_addr_cells = node_addr_cells(node->parent);
  514. p_size_cells = node_size_cells(node->parent);
  515. c_addr_cells = node_addr_cells(node);
  516. c_size_cells = node_size_cells(node);
  517. entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t);
  518. if (prop->val.len == 0) {
  519. if (p_addr_cells != c_addr_cells)
  520. FAIL(c, "%s has empty \"ranges\" property but its "
  521. "#address-cells (%d) differs from %s (%d)",
  522. node->fullpath, c_addr_cells, node->parent->fullpath,
  523. p_addr_cells);
  524. if (p_size_cells != c_size_cells)
  525. FAIL(c, "%s has empty \"ranges\" property but its "
  526. "#size-cells (%d) differs from %s (%d)",
  527. node->fullpath, c_size_cells, node->parent->fullpath,
  528. p_size_cells);
  529. } else if ((prop->val.len % entrylen) != 0) {
  530. FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) "
  531. "(parent #address-cells == %d, child #address-cells == %d, "
  532. "#size-cells == %d)", node->fullpath, prop->val.len,
  533. p_addr_cells, c_addr_cells, c_size_cells);
  534. }
  535. }
  536. NODE_WARNING(ranges_format, NULL, &addr_size_cells);
  537. /*
  538. * Style checks
  539. */
  540. static void check_avoid_default_addr_size(struct check *c, struct node *dt,
  541. struct node *node)
  542. {
  543. struct property *reg, *ranges;
  544. if (!node->parent)
  545. return; /* Ignore root node */
  546. reg = get_property(node, "reg");
  547. ranges = get_property(node, "ranges");
  548. if (!reg && !ranges)
  549. return;
  550. if (node->parent->addr_cells == -1)
  551. FAIL(c, "Relying on default #address-cells value for %s",
  552. node->fullpath);
  553. if (node->parent->size_cells == -1)
  554. FAIL(c, "Relying on default #size-cells value for %s",
  555. node->fullpath);
  556. }
  557. NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells);
  558. static void check_obsolete_chosen_interrupt_controller(struct check *c,
  559. struct node *dt)
  560. {
  561. struct node *chosen;
  562. struct property *prop;
  563. chosen = get_node_by_path(dt, "/chosen");
  564. if (!chosen)
  565. return;
  566. prop = get_property(chosen, "interrupt-controller");
  567. if (prop)
  568. FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
  569. "property");
  570. }
  571. TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
  572. static struct check *check_table[] = {
  573. &duplicate_node_names, &duplicate_property_names,
  574. &node_name_chars, &node_name_format, &property_name_chars,
  575. &name_is_string, &name_properties,
  576. &duplicate_label,
  577. &explicit_phandles,
  578. &phandle_references, &path_references,
  579. &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
  580. &device_type_is_string, &model_is_string, &status_is_string,
  581. &addr_size_cells, &reg_format, &ranges_format,
  582. &unit_address_vs_reg,
  583. &avoid_default_addr_size,
  584. &obsolete_chosen_interrupt_controller,
  585. &always_fail,
  586. };
  587. static void enable_warning_error(struct check *c, bool warn, bool error)
  588. {
  589. int i;
  590. /* Raising level, also raise it for prereqs */
  591. if ((warn && !c->warn) || (error && !c->error))
  592. for (i = 0; i < c->num_prereqs; i++)
  593. enable_warning_error(c->prereq[i], warn, error);
  594. c->warn = c->warn || warn;
  595. c->error = c->error || error;
  596. }
  597. static void disable_warning_error(struct check *c, bool warn, bool error)
  598. {
  599. int i;
  600. /* Lowering level, also lower it for things this is the prereq
  601. * for */
  602. if ((warn && c->warn) || (error && c->error)) {
  603. for (i = 0; i < ARRAY_SIZE(check_table); i++) {
  604. struct check *cc = check_table[i];
  605. int j;
  606. for (j = 0; j < cc->num_prereqs; j++)
  607. if (cc->prereq[j] == c)
  608. disable_warning_error(cc, warn, error);
  609. }
  610. }
  611. c->warn = c->warn && !warn;
  612. c->error = c->error && !error;
  613. }
  614. void parse_checks_option(bool warn, bool error, const char *arg)
  615. {
  616. int i;
  617. const char *name = arg;
  618. bool enable = true;
  619. if ((strncmp(arg, "no-", 3) == 0)
  620. || (strncmp(arg, "no_", 3) == 0)) {
  621. name = arg + 3;
  622. enable = false;
  623. }
  624. for (i = 0; i < ARRAY_SIZE(check_table); i++) {
  625. struct check *c = check_table[i];
  626. if (streq(c->name, name)) {
  627. if (enable)
  628. enable_warning_error(c, warn, error);
  629. else
  630. disable_warning_error(c, warn, error);
  631. return;
  632. }
  633. }
  634. die("Unrecognized check name \"%s\"\n", name);
  635. }
  636. void process_checks(bool force, struct boot_info *bi)
  637. {
  638. struct node *dt = bi->dt;
  639. int i;
  640. int error = 0;
  641. for (i = 0; i < ARRAY_SIZE(check_table); i++) {
  642. struct check *c = check_table[i];
  643. if (c->warn || c->error)
  644. error = error || run_check(c, dt);
  645. }
  646. if (error) {
  647. if (!force) {
  648. fprintf(stderr, "ERROR: Input tree has errors, aborting "
  649. "(use -f to force output)\n");
  650. exit(2);
  651. } else if (quiet < 3) {
  652. fprintf(stderr, "Warning: Input tree has errors, "
  653. "output forced\n");
  654. }
  655. }
  656. }