fdt.c 18 KB

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