livetree.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. /*
  2. * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
  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. /*
  22. * Tree building functions
  23. */
  24. void add_label(struct label **labels, char *label)
  25. {
  26. struct label *new;
  27. /* Make sure the label isn't already there */
  28. for_each_label(*labels, new)
  29. if (streq(new->label, label))
  30. return;
  31. new = xmalloc(sizeof(*new));
  32. new->label = label;
  33. new->next = *labels;
  34. *labels = new;
  35. }
  36. struct property *build_property(char *name, struct data val)
  37. {
  38. struct property *new = xmalloc(sizeof(*new));
  39. memset(new, 0, sizeof(*new));
  40. new->name = name;
  41. new->val = val;
  42. return new;
  43. }
  44. struct property *chain_property(struct property *first, struct property *list)
  45. {
  46. assert(first->next == NULL);
  47. first->next = list;
  48. return first;
  49. }
  50. struct property *reverse_properties(struct property *first)
  51. {
  52. struct property *p = first;
  53. struct property *head = NULL;
  54. struct property *next;
  55. while (p) {
  56. next = p->next;
  57. p->next = head;
  58. head = p;
  59. p = next;
  60. }
  61. return head;
  62. }
  63. struct node *build_node(struct property *proplist, struct node *children)
  64. {
  65. struct node *new = xmalloc(sizeof(*new));
  66. struct node *child;
  67. memset(new, 0, sizeof(*new));
  68. new->proplist = reverse_properties(proplist);
  69. new->children = children;
  70. for_each_child(new, child) {
  71. child->parent = new;
  72. }
  73. return new;
  74. }
  75. struct node *name_node(struct node *node, char *name)
  76. {
  77. assert(node->name == NULL);
  78. node->name = name;
  79. return node;
  80. }
  81. struct node *merge_nodes(struct node *old_node, struct node *new_node)
  82. {
  83. struct property *new_prop, *old_prop;
  84. struct node *new_child, *old_child;
  85. struct label *l;
  86. /* Add new node labels to old node */
  87. for_each_label(new_node->labels, l)
  88. add_label(&old_node->labels, l->label);
  89. /* Move properties from the new node to the old node. If there
  90. * is a collision, replace the old value with the new */
  91. while (new_node->proplist) {
  92. /* Pop the property off the list */
  93. new_prop = new_node->proplist;
  94. new_node->proplist = new_prop->next;
  95. new_prop->next = NULL;
  96. /* Look for a collision, set new value if there is */
  97. for_each_property(old_node, old_prop) {
  98. if (streq(old_prop->name, new_prop->name)) {
  99. /* Add new labels to old property */
  100. for_each_label(new_prop->labels, l)
  101. add_label(&old_prop->labels, l->label);
  102. old_prop->val = new_prop->val;
  103. free(new_prop);
  104. new_prop = NULL;
  105. break;
  106. }
  107. }
  108. /* if no collision occurred, add property to the old node. */
  109. if (new_prop)
  110. add_property(old_node, new_prop);
  111. }
  112. /* Move the override child nodes into the primary node. If
  113. * there is a collision, then merge the nodes. */
  114. while (new_node->children) {
  115. /* Pop the child node off the list */
  116. new_child = new_node->children;
  117. new_node->children = new_child->next_sibling;
  118. new_child->parent = NULL;
  119. new_child->next_sibling = NULL;
  120. /* Search for a collision. Merge if there is */
  121. for_each_child(old_node, old_child) {
  122. if (streq(old_child->name, new_child->name)) {
  123. merge_nodes(old_child, new_child);
  124. new_child = NULL;
  125. break;
  126. }
  127. }
  128. /* if no collision occurred, add child to the old node. */
  129. if (new_child)
  130. add_child(old_node, new_child);
  131. }
  132. /* The new node contents are now merged into the old node. Free
  133. * the new node. */
  134. free(new_node);
  135. return old_node;
  136. }
  137. struct node *chain_node(struct node *first, struct node *list)
  138. {
  139. assert(first->next_sibling == NULL);
  140. first->next_sibling = list;
  141. return first;
  142. }
  143. void add_property(struct node *node, struct property *prop)
  144. {
  145. struct property **p;
  146. prop->next = NULL;
  147. p = &node->proplist;
  148. while (*p)
  149. p = &((*p)->next);
  150. *p = prop;
  151. }
  152. void add_child(struct node *parent, struct node *child)
  153. {
  154. struct node **p;
  155. child->next_sibling = NULL;
  156. child->parent = parent;
  157. p = &parent->children;
  158. while (*p)
  159. p = &((*p)->next_sibling);
  160. *p = child;
  161. }
  162. struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
  163. {
  164. struct reserve_info *new = xmalloc(sizeof(*new));
  165. memset(new, 0, sizeof(*new));
  166. new->re.address = address;
  167. new->re.size = size;
  168. return new;
  169. }
  170. struct reserve_info *chain_reserve_entry(struct reserve_info *first,
  171. struct reserve_info *list)
  172. {
  173. assert(first->next == NULL);
  174. first->next = list;
  175. return first;
  176. }
  177. struct reserve_info *add_reserve_entry(struct reserve_info *list,
  178. struct reserve_info *new)
  179. {
  180. struct reserve_info *last;
  181. new->next = NULL;
  182. if (! list)
  183. return new;
  184. for (last = list; last->next; last = last->next)
  185. ;
  186. last->next = new;
  187. return list;
  188. }
  189. struct boot_info *build_boot_info(struct reserve_info *reservelist,
  190. struct node *tree, uint32_t boot_cpuid_phys)
  191. {
  192. struct boot_info *bi;
  193. bi = xmalloc(sizeof(*bi));
  194. bi->reservelist = reservelist;
  195. bi->dt = tree;
  196. bi->boot_cpuid_phys = boot_cpuid_phys;
  197. return bi;
  198. }
  199. /*
  200. * Tree accessor functions
  201. */
  202. const char *get_unitname(struct node *node)
  203. {
  204. if (node->name[node->basenamelen] == '\0')
  205. return "";
  206. else
  207. return node->name + node->basenamelen + 1;
  208. }
  209. struct property *get_property(struct node *node, const char *propname)
  210. {
  211. struct property *prop;
  212. for_each_property(node, prop)
  213. if (streq(prop->name, propname))
  214. return prop;
  215. return NULL;
  216. }
  217. cell_t propval_cell(struct property *prop)
  218. {
  219. assert(prop->val.len == sizeof(cell_t));
  220. return fdt32_to_cpu(*((cell_t *)prop->val.val));
  221. }
  222. struct property *get_property_by_label(struct node *tree, const char *label,
  223. struct node **node)
  224. {
  225. struct property *prop;
  226. struct node *c;
  227. *node = tree;
  228. for_each_property(tree, prop) {
  229. struct label *l;
  230. for_each_label(prop->labels, l)
  231. if (streq(l->label, label))
  232. return prop;
  233. }
  234. for_each_child(tree, c) {
  235. prop = get_property_by_label(c, label, node);
  236. if (prop)
  237. return prop;
  238. }
  239. *node = NULL;
  240. return NULL;
  241. }
  242. struct marker *get_marker_label(struct node *tree, const char *label,
  243. struct node **node, struct property **prop)
  244. {
  245. struct marker *m;
  246. struct property *p;
  247. struct node *c;
  248. *node = tree;
  249. for_each_property(tree, p) {
  250. *prop = p;
  251. m = p->val.markers;
  252. for_each_marker_of_type(m, LABEL)
  253. if (streq(m->ref, label))
  254. return m;
  255. }
  256. for_each_child(tree, c) {
  257. m = get_marker_label(c, label, node, prop);
  258. if (m)
  259. return m;
  260. }
  261. *prop = NULL;
  262. *node = NULL;
  263. return NULL;
  264. }
  265. struct node *get_subnode(struct node *node, const char *nodename)
  266. {
  267. struct node *child;
  268. for_each_child(node, child)
  269. if (streq(child->name, nodename))
  270. return child;
  271. return NULL;
  272. }
  273. struct node *get_node_by_path(struct node *tree, const char *path)
  274. {
  275. const char *p;
  276. struct node *child;
  277. if (!path || ! (*path))
  278. return tree;
  279. while (path[0] == '/')
  280. path++;
  281. p = strchr(path, '/');
  282. for_each_child(tree, child) {
  283. if (p && strneq(path, child->name, p-path))
  284. return get_node_by_path(child, p+1);
  285. else if (!p && streq(path, child->name))
  286. return child;
  287. }
  288. return NULL;
  289. }
  290. struct node *get_node_by_label(struct node *tree, const char *label)
  291. {
  292. struct node *child, *node;
  293. struct label *l;
  294. assert(label && (strlen(label) > 0));
  295. for_each_label(tree->labels, l)
  296. if (streq(l->label, label))
  297. return tree;
  298. for_each_child(tree, child) {
  299. node = get_node_by_label(child, label);
  300. if (node)
  301. return node;
  302. }
  303. return NULL;
  304. }
  305. struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
  306. {
  307. struct node *child, *node;
  308. assert((phandle != 0) && (phandle != -1));
  309. if (tree->phandle == phandle)
  310. return tree;
  311. for_each_child(tree, child) {
  312. node = get_node_by_phandle(child, phandle);
  313. if (node)
  314. return node;
  315. }
  316. return NULL;
  317. }
  318. struct node *get_node_by_ref(struct node *tree, const char *ref)
  319. {
  320. if (ref[0] == '/')
  321. return get_node_by_path(tree, ref);
  322. else
  323. return get_node_by_label(tree, ref);
  324. }
  325. cell_t get_node_phandle(struct node *root, struct node *node)
  326. {
  327. static cell_t phandle = 1; /* FIXME: ick, static local */
  328. if ((node->phandle != 0) && (node->phandle != -1))
  329. return node->phandle;
  330. while (get_node_by_phandle(root, phandle))
  331. phandle++;
  332. node->phandle = phandle;
  333. if (!get_property(node, "linux,phandle")
  334. && (phandle_format & PHANDLE_LEGACY))
  335. add_property(node,
  336. build_property("linux,phandle",
  337. data_append_cell(empty_data, phandle)));
  338. if (!get_property(node, "phandle")
  339. && (phandle_format & PHANDLE_EPAPR))
  340. add_property(node,
  341. build_property("phandle",
  342. data_append_cell(empty_data, phandle)));
  343. /* If the node *does* have a phandle property, we must
  344. * be dealing with a self-referencing phandle, which will be
  345. * fixed up momentarily in the caller */
  346. return node->phandle;
  347. }
  348. uint32_t guess_boot_cpuid(struct node *tree)
  349. {
  350. struct node *cpus, *bootcpu;
  351. struct property *reg;
  352. cpus = get_node_by_path(tree, "/cpus");
  353. if (!cpus)
  354. return 0;
  355. bootcpu = cpus->children;
  356. if (!bootcpu)
  357. return 0;
  358. reg = get_property(bootcpu, "reg");
  359. if (!reg || (reg->val.len != sizeof(uint32_t)))
  360. return 0;
  361. /* FIXME: Sanity check node? */
  362. return propval_cell(reg);
  363. }
  364. static int cmp_reserve_info(const void *ax, const void *bx)
  365. {
  366. const struct reserve_info *a, *b;
  367. a = *((const struct reserve_info * const *)ax);
  368. b = *((const struct reserve_info * const *)bx);
  369. if (a->re.address < b->re.address)
  370. return -1;
  371. else if (a->re.address > b->re.address)
  372. return 1;
  373. else if (a->re.size < b->re.size)
  374. return -1;
  375. else if (a->re.size > b->re.size)
  376. return 1;
  377. else
  378. return 0;
  379. }
  380. static void sort_reserve_entries(struct boot_info *bi)
  381. {
  382. struct reserve_info *ri, **tbl;
  383. int n = 0, i = 0;
  384. for (ri = bi->reservelist;
  385. ri;
  386. ri = ri->next)
  387. n++;
  388. if (n == 0)
  389. return;
  390. tbl = xmalloc(n * sizeof(*tbl));
  391. for (ri = bi->reservelist;
  392. ri;
  393. ri = ri->next)
  394. tbl[i++] = ri;
  395. qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
  396. bi->reservelist = tbl[0];
  397. for (i = 0; i < (n-1); i++)
  398. tbl[i]->next = tbl[i+1];
  399. tbl[n-1]->next = NULL;
  400. free(tbl);
  401. }
  402. static int cmp_prop(const void *ax, const void *bx)
  403. {
  404. const struct property *a, *b;
  405. a = *((const struct property * const *)ax);
  406. b = *((const struct property * const *)bx);
  407. return strcmp(a->name, b->name);
  408. }
  409. static void sort_properties(struct node *node)
  410. {
  411. int n = 0, i = 0;
  412. struct property *prop, **tbl;
  413. for_each_property(node, prop)
  414. n++;
  415. if (n == 0)
  416. return;
  417. tbl = xmalloc(n * sizeof(*tbl));
  418. for_each_property(node, prop)
  419. tbl[i++] = prop;
  420. qsort(tbl, n, sizeof(*tbl), cmp_prop);
  421. node->proplist = tbl[0];
  422. for (i = 0; i < (n-1); i++)
  423. tbl[i]->next = tbl[i+1];
  424. tbl[n-1]->next = NULL;
  425. free(tbl);
  426. }
  427. static int cmp_subnode(const void *ax, const void *bx)
  428. {
  429. const struct node *a, *b;
  430. a = *((const struct node * const *)ax);
  431. b = *((const struct node * const *)bx);
  432. return strcmp(a->name, b->name);
  433. }
  434. static void sort_subnodes(struct node *node)
  435. {
  436. int n = 0, i = 0;
  437. struct node *subnode, **tbl;
  438. for_each_child(node, subnode)
  439. n++;
  440. if (n == 0)
  441. return;
  442. tbl = xmalloc(n * sizeof(*tbl));
  443. for_each_child(node, subnode)
  444. tbl[i++] = subnode;
  445. qsort(tbl, n, sizeof(*tbl), cmp_subnode);
  446. node->children = tbl[0];
  447. for (i = 0; i < (n-1); i++)
  448. tbl[i]->next_sibling = tbl[i+1];
  449. tbl[n-1]->next_sibling = NULL;
  450. free(tbl);
  451. }
  452. static void sort_node(struct node *node)
  453. {
  454. struct node *c;
  455. sort_properties(node);
  456. sort_subnodes(node);
  457. for_each_child(node, c)
  458. sort_node(c);
  459. }
  460. void sort_tree(struct boot_info *bi)
  461. {
  462. sort_reserve_entries(bi);
  463. sort_node(bi->dt);
  464. }