checks.c 20 KB

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