fdt.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. /*
  2. * Functions for working with the Flattened Device Tree data format
  3. *
  4. * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
  5. * benh@kernel.crashing.org
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * version 2 as published by the Free Software Foundation.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/lmb.h>
  13. #include <linux/initrd.h>
  14. #include <linux/of.h>
  15. #include <linux/of_fdt.h>
  16. #ifdef CONFIG_PPC
  17. #include <asm/machdep.h>
  18. #endif /* CONFIG_PPC */
  19. int __initdata dt_root_addr_cells;
  20. int __initdata dt_root_size_cells;
  21. struct boot_param_header *initial_boot_params;
  22. char *find_flat_dt_string(u32 offset)
  23. {
  24. return ((char *)initial_boot_params) +
  25. be32_to_cpu(initial_boot_params->off_dt_strings) + offset;
  26. }
  27. /**
  28. * of_scan_flat_dt - scan flattened tree blob and call callback on each.
  29. * @it: callback function
  30. * @data: context data pointer
  31. *
  32. * This function is used to scan the flattened device-tree, it is
  33. * used to extract the memory information at boot before we can
  34. * unflatten the tree
  35. */
  36. int __init of_scan_flat_dt(int (*it)(unsigned long node,
  37. const char *uname, int depth,
  38. void *data),
  39. void *data)
  40. {
  41. unsigned long p = ((unsigned long)initial_boot_params) +
  42. be32_to_cpu(initial_boot_params->off_dt_struct);
  43. int rc = 0;
  44. int depth = -1;
  45. do {
  46. u32 tag = be32_to_cpup((__be32 *)p);
  47. char *pathp;
  48. p += 4;
  49. if (tag == OF_DT_END_NODE) {
  50. depth--;
  51. continue;
  52. }
  53. if (tag == OF_DT_NOP)
  54. continue;
  55. if (tag == OF_DT_END)
  56. break;
  57. if (tag == OF_DT_PROP) {
  58. u32 sz = be32_to_cpup((__be32 *)p);
  59. p += 8;
  60. if (be32_to_cpu(initial_boot_params->version) < 0x10)
  61. p = _ALIGN(p, sz >= 8 ? 8 : 4);
  62. p += sz;
  63. p = _ALIGN(p, 4);
  64. continue;
  65. }
  66. if (tag != OF_DT_BEGIN_NODE) {
  67. pr_err("Invalid tag %x in flat device tree!\n", tag);
  68. return -EINVAL;
  69. }
  70. depth++;
  71. pathp = (char *)p;
  72. p = _ALIGN(p + strlen(pathp) + 1, 4);
  73. if ((*pathp) == '/') {
  74. char *lp, *np;
  75. for (lp = NULL, np = pathp; *np; np++)
  76. if ((*np) == '/')
  77. lp = np+1;
  78. if (lp != NULL)
  79. pathp = lp;
  80. }
  81. rc = it(p, pathp, depth, data);
  82. if (rc != 0)
  83. break;
  84. } while (1);
  85. return rc;
  86. }
  87. /**
  88. * of_get_flat_dt_root - find the root node in the flat blob
  89. */
  90. unsigned long __init of_get_flat_dt_root(void)
  91. {
  92. unsigned long p = ((unsigned long)initial_boot_params) +
  93. be32_to_cpu(initial_boot_params->off_dt_struct);
  94. while (be32_to_cpup((__be32 *)p) == OF_DT_NOP)
  95. p += 4;
  96. BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE);
  97. p += 4;
  98. return _ALIGN(p + strlen((char *)p) + 1, 4);
  99. }
  100. /**
  101. * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr
  102. *
  103. * This function can be used within scan_flattened_dt callback to get
  104. * access to properties
  105. */
  106. void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
  107. unsigned long *size)
  108. {
  109. unsigned long p = node;
  110. do {
  111. u32 tag = be32_to_cpup((__be32 *)p);
  112. u32 sz, noff;
  113. const char *nstr;
  114. p += 4;
  115. if (tag == OF_DT_NOP)
  116. continue;
  117. if (tag != OF_DT_PROP)
  118. return NULL;
  119. sz = be32_to_cpup((__be32 *)p);
  120. noff = be32_to_cpup((__be32 *)(p + 4));
  121. p += 8;
  122. if (be32_to_cpu(initial_boot_params->version) < 0x10)
  123. p = _ALIGN(p, sz >= 8 ? 8 : 4);
  124. nstr = find_flat_dt_string(noff);
  125. if (nstr == NULL) {
  126. pr_warning("Can't find property index name !\n");
  127. return NULL;
  128. }
  129. if (strcmp(name, nstr) == 0) {
  130. if (size)
  131. *size = sz;
  132. return (void *)p;
  133. }
  134. p += sz;
  135. p = _ALIGN(p, 4);
  136. } while (1);
  137. }
  138. /**
  139. * of_flat_dt_is_compatible - Return true if given node has compat in compatible list
  140. * @node: node to test
  141. * @compat: compatible string to compare with compatible list.
  142. */
  143. int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
  144. {
  145. const char *cp;
  146. unsigned long cplen, l;
  147. cp = of_get_flat_dt_prop(node, "compatible", &cplen);
  148. if (cp == NULL)
  149. return 0;
  150. while (cplen > 0) {
  151. if (strncasecmp(cp, compat, strlen(compat)) == 0)
  152. return 1;
  153. l = strlen(cp) + 1;
  154. cp += l;
  155. cplen -= l;
  156. }
  157. return 0;
  158. }
  159. static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
  160. unsigned long align)
  161. {
  162. void *res;
  163. *mem = _ALIGN(*mem, align);
  164. res = (void *)*mem;
  165. *mem += size;
  166. return res;
  167. }
  168. /**
  169. * unflatten_dt_node - Alloc and populate a device_node from the flat tree
  170. * @p: pointer to node in flat tree
  171. * @dad: Parent struct device_node
  172. * @allnextpp: pointer to ->allnext from last allocated device_node
  173. * @fpsize: Size of the node path up at the current depth.
  174. */
  175. unsigned long __init unflatten_dt_node(unsigned long mem,
  176. unsigned long *p,
  177. struct device_node *dad,
  178. struct device_node ***allnextpp,
  179. unsigned long fpsize)
  180. {
  181. struct device_node *np;
  182. struct property *pp, **prev_pp = NULL;
  183. char *pathp;
  184. u32 tag;
  185. unsigned int l, allocl;
  186. int has_name = 0;
  187. int new_format = 0;
  188. tag = be32_to_cpup((__be32 *)(*p));
  189. if (tag != OF_DT_BEGIN_NODE) {
  190. pr_err("Weird tag at start of node: %x\n", tag);
  191. return mem;
  192. }
  193. *p += 4;
  194. pathp = (char *)*p;
  195. l = allocl = strlen(pathp) + 1;
  196. *p = _ALIGN(*p + l, 4);
  197. /* version 0x10 has a more compact unit name here instead of the full
  198. * path. we accumulate the full path size using "fpsize", we'll rebuild
  199. * it later. We detect this because the first character of the name is
  200. * not '/'.
  201. */
  202. if ((*pathp) != '/') {
  203. new_format = 1;
  204. if (fpsize == 0) {
  205. /* root node: special case. fpsize accounts for path
  206. * plus terminating zero. root node only has '/', so
  207. * fpsize should be 2, but we want to avoid the first
  208. * level nodes to have two '/' so we use fpsize 1 here
  209. */
  210. fpsize = 1;
  211. allocl = 2;
  212. } else {
  213. /* account for '/' and path size minus terminal 0
  214. * already in 'l'
  215. */
  216. fpsize += l;
  217. allocl = fpsize;
  218. }
  219. }
  220. np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
  221. __alignof__(struct device_node));
  222. if (allnextpp) {
  223. memset(np, 0, sizeof(*np));
  224. np->full_name = ((char *)np) + sizeof(struct device_node);
  225. if (new_format) {
  226. char *fn = np->full_name;
  227. /* rebuild full path for new format */
  228. if (dad && dad->parent) {
  229. strcpy(fn, dad->full_name);
  230. #ifdef DEBUG
  231. if ((strlen(fn) + l + 1) != allocl) {
  232. pr_debug("%s: p: %d, l: %d, a: %d\n",
  233. pathp, (int)strlen(fn),
  234. l, allocl);
  235. }
  236. #endif
  237. fn += strlen(fn);
  238. }
  239. *(fn++) = '/';
  240. memcpy(fn, pathp, l);
  241. } else
  242. memcpy(np->full_name, pathp, l);
  243. prev_pp = &np->properties;
  244. **allnextpp = np;
  245. *allnextpp = &np->allnext;
  246. if (dad != NULL) {
  247. np->parent = dad;
  248. /* we temporarily use the next field as `last_child'*/
  249. if (dad->next == NULL)
  250. dad->child = np;
  251. else
  252. dad->next->sibling = np;
  253. dad->next = np;
  254. }
  255. kref_init(&np->kref);
  256. }
  257. while (1) {
  258. u32 sz, noff;
  259. char *pname;
  260. tag = be32_to_cpup((__be32 *)(*p));
  261. if (tag == OF_DT_NOP) {
  262. *p += 4;
  263. continue;
  264. }
  265. if (tag != OF_DT_PROP)
  266. break;
  267. *p += 4;
  268. sz = be32_to_cpup((__be32 *)(*p));
  269. noff = be32_to_cpup((__be32 *)((*p) + 4));
  270. *p += 8;
  271. if (be32_to_cpu(initial_boot_params->version) < 0x10)
  272. *p = _ALIGN(*p, sz >= 8 ? 8 : 4);
  273. pname = find_flat_dt_string(noff);
  274. if (pname == NULL) {
  275. pr_info("Can't find property name in list !\n");
  276. break;
  277. }
  278. if (strcmp(pname, "name") == 0)
  279. has_name = 1;
  280. l = strlen(pname) + 1;
  281. pp = unflatten_dt_alloc(&mem, sizeof(struct property),
  282. __alignof__(struct property));
  283. if (allnextpp) {
  284. /* We accept flattened tree phandles either in
  285. * ePAPR-style "phandle" properties, or the
  286. * legacy "linux,phandle" properties. If both
  287. * appear and have different values, things
  288. * will get weird. Don't do that. */
  289. if ((strcmp(pname, "phandle") == 0) ||
  290. (strcmp(pname, "linux,phandle") == 0)) {
  291. if (np->phandle == 0)
  292. np->phandle = *((u32 *)*p);
  293. }
  294. /* And we process the "ibm,phandle" property
  295. * used in pSeries dynamic device tree
  296. * stuff */
  297. if (strcmp(pname, "ibm,phandle") == 0)
  298. np->phandle = *((u32 *)*p);
  299. pp->name = pname;
  300. pp->length = sz;
  301. pp->value = (void *)*p;
  302. *prev_pp = pp;
  303. prev_pp = &pp->next;
  304. }
  305. *p = _ALIGN((*p) + sz, 4);
  306. }
  307. /* with version 0x10 we may not have the name property, recreate
  308. * it here from the unit name if absent
  309. */
  310. if (!has_name) {
  311. char *p1 = pathp, *ps = pathp, *pa = NULL;
  312. int sz;
  313. while (*p1) {
  314. if ((*p1) == '@')
  315. pa = p1;
  316. if ((*p1) == '/')
  317. ps = p1 + 1;
  318. p1++;
  319. }
  320. if (pa < ps)
  321. pa = p1;
  322. sz = (pa - ps) + 1;
  323. pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
  324. __alignof__(struct property));
  325. if (allnextpp) {
  326. pp->name = "name";
  327. pp->length = sz;
  328. pp->value = pp + 1;
  329. *prev_pp = pp;
  330. prev_pp = &pp->next;
  331. memcpy(pp->value, ps, sz - 1);
  332. ((char *)pp->value)[sz - 1] = 0;
  333. pr_debug("fixed up name for %s -> %s\n", pathp,
  334. (char *)pp->value);
  335. }
  336. }
  337. if (allnextpp) {
  338. *prev_pp = NULL;
  339. np->name = of_get_property(np, "name", NULL);
  340. np->type = of_get_property(np, "device_type", NULL);
  341. if (!np->name)
  342. np->name = "<NULL>";
  343. if (!np->type)
  344. np->type = "<NULL>";
  345. }
  346. while (tag == OF_DT_BEGIN_NODE) {
  347. mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
  348. tag = be32_to_cpup((__be32 *)(*p));
  349. }
  350. if (tag != OF_DT_END_NODE) {
  351. pr_err("Weird tag at end of node: %x\n", tag);
  352. return mem;
  353. }
  354. *p += 4;
  355. return mem;
  356. }
  357. #ifdef CONFIG_BLK_DEV_INITRD
  358. /**
  359. * early_init_dt_check_for_initrd - Decode initrd location from flat tree
  360. * @node: reference to node containing initrd location ('chosen')
  361. */
  362. void __init early_init_dt_check_for_initrd(unsigned long node)
  363. {
  364. unsigned long start, end, len;
  365. __be32 *prop;
  366. pr_debug("Looking for initrd properties... ");
  367. prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len);
  368. if (!prop)
  369. return;
  370. start = of_read_ulong(prop, len/4);
  371. prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len);
  372. if (!prop)
  373. return;
  374. end = of_read_ulong(prop, len/4);
  375. early_init_dt_setup_initrd_arch(start, end);
  376. pr_debug("initrd_start=0x%lx initrd_end=0x%lx\n", start, end);
  377. }
  378. #else
  379. inline void early_init_dt_check_for_initrd(unsigned long node)
  380. {
  381. }
  382. #endif /* CONFIG_BLK_DEV_INITRD */
  383. /**
  384. * early_init_dt_scan_root - fetch the top level address and size cells
  385. */
  386. int __init early_init_dt_scan_root(unsigned long node, const char *uname,
  387. int depth, void *data)
  388. {
  389. __be32 *prop;
  390. if (depth != 0)
  391. return 0;
  392. dt_root_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
  393. dt_root_addr_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
  394. prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
  395. if (prop)
  396. dt_root_size_cells = be32_to_cpup(prop);
  397. pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);
  398. prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
  399. if (prop)
  400. dt_root_addr_cells = be32_to_cpup(prop);
  401. pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
  402. /* break now */
  403. return 1;
  404. }
  405. u64 __init dt_mem_next_cell(int s, __be32 **cellp)
  406. {
  407. __be32 *p = *cellp;
  408. *cellp = p + s;
  409. return of_read_number(p, s);
  410. }
  411. /**
  412. * early_init_dt_scan_memory - Look for an parse memory nodes
  413. */
  414. int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
  415. int depth, void *data)
  416. {
  417. char *type = of_get_flat_dt_prop(node, "device_type", NULL);
  418. __be32 *reg, *endp;
  419. unsigned long l;
  420. /* We are scanning "memory" nodes only */
  421. if (type == NULL) {
  422. /*
  423. * The longtrail doesn't have a device_type on the
  424. * /memory node, so look for the node called /memory@0.
  425. */
  426. if (depth != 1 || strcmp(uname, "memory@0") != 0)
  427. return 0;
  428. } else if (strcmp(type, "memory") != 0)
  429. return 0;
  430. reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
  431. if (reg == NULL)
  432. reg = of_get_flat_dt_prop(node, "reg", &l);
  433. if (reg == NULL)
  434. return 0;
  435. endp = reg + (l / sizeof(__be32));
  436. pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
  437. uname, l, reg[0], reg[1], reg[2], reg[3]);
  438. while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
  439. u64 base, size;
  440. base = dt_mem_next_cell(dt_root_addr_cells, &reg);
  441. size = dt_mem_next_cell(dt_root_size_cells, &reg);
  442. if (size == 0)
  443. continue;
  444. pr_debug(" - %llx , %llx\n", (unsigned long long)base,
  445. (unsigned long long)size);
  446. early_init_dt_add_memory_arch(base, size);
  447. }
  448. return 0;
  449. }
  450. int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
  451. int depth, void *data)
  452. {
  453. unsigned long l;
  454. char *p;
  455. pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
  456. if (depth != 1 ||
  457. (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
  458. return 0;
  459. early_init_dt_check_for_initrd(node);
  460. /* Retreive command line */
  461. p = of_get_flat_dt_prop(node, "bootargs", &l);
  462. if (p != NULL && l > 0)
  463. strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));
  464. #ifdef CONFIG_CMDLINE
  465. #ifndef CONFIG_CMDLINE_FORCE
  466. if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
  467. #endif
  468. strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
  469. #endif /* CONFIG_CMDLINE */
  470. early_init_dt_scan_chosen_arch(node);
  471. pr_debug("Command line is: %s\n", cmd_line);
  472. /* break now */
  473. return 1;
  474. }
  475. /**
  476. * unflatten_device_tree - create tree of device_nodes from flat blob
  477. *
  478. * unflattens the device-tree passed by the firmware, creating the
  479. * tree of struct device_node. It also fills the "name" and "type"
  480. * pointers of the nodes so the normal device-tree walking functions
  481. * can be used.
  482. */
  483. void __init unflatten_device_tree(void)
  484. {
  485. unsigned long start, mem, size;
  486. struct device_node **allnextp = &allnodes;
  487. pr_debug(" -> unflatten_device_tree()\n");
  488. /* First pass, scan for size */
  489. start = ((unsigned long)initial_boot_params) +
  490. be32_to_cpu(initial_boot_params->off_dt_struct);
  491. size = unflatten_dt_node(0, &start, NULL, NULL, 0);
  492. size = (size | 3) + 1;
  493. pr_debug(" size is %lx, allocating...\n", size);
  494. /* Allocate memory for the expanded device tree */
  495. mem = lmb_alloc(size + 4, __alignof__(struct device_node));
  496. mem = (unsigned long) __va(mem);
  497. ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);
  498. pr_debug(" unflattening %lx...\n", mem);
  499. /* Second pass, do actual unflattening */
  500. start = ((unsigned long)initial_boot_params) +
  501. be32_to_cpu(initial_boot_params->off_dt_struct);
  502. unflatten_dt_node(mem, &start, NULL, &allnextp, 0);
  503. if (be32_to_cpup((__be32 *)start) != OF_DT_END)
  504. pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start));
  505. if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef)
  506. pr_warning("End of tree marker overwritten: %08x\n",
  507. be32_to_cpu(((__be32 *)mem)[size / 4]));
  508. *allnextp = NULL;
  509. /* Get pointer to OF "/chosen" node for use everywhere */
  510. of_chosen = of_find_node_by_path("/chosen");
  511. if (of_chosen == NULL)
  512. of_chosen = of_find_node_by_path("/chosen@0");
  513. pr_debug(" <- unflatten_device_tree()\n");
  514. }