checks.c 22 KB

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