aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of/fdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/of/fdt.c')
-rw-r--r--drivers/of/fdt.c458
1 files changed, 197 insertions, 261 deletions
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 7a2ef7bb8022..c4cddf0cd96d 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -12,7 +12,6 @@
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/initrd.h> 13#include <linux/initrd.h>
14#include <linux/memblock.h> 14#include <linux/memblock.h>
15#include <linux/module.h>
16#include <linux/of.h> 15#include <linux/of.h>
17#include <linux/of_fdt.h> 16#include <linux/of_fdt.h>
18#include <linux/of_reserved_mem.h> 17#include <linux/of_reserved_mem.h>
@@ -20,62 +19,13 @@
20#include <linux/string.h> 19#include <linux/string.h>
21#include <linux/errno.h> 20#include <linux/errno.h>
22#include <linux/slab.h> 21#include <linux/slab.h>
22#include <linux/libfdt.h>
23#include <linux/debugfs.h>
24#include <linux/serial_core.h>
23 25
24#include <asm/setup.h> /* for COMMAND_LINE_SIZE */ 26#include <asm/setup.h> /* for COMMAND_LINE_SIZE */
25#ifdef CONFIG_PPC
26#include <asm/machdep.h>
27#endif /* CONFIG_PPC */
28
29#include <asm/page.h> 27#include <asm/page.h>
30 28
31char *of_fdt_get_string(struct boot_param_header *blob, u32 offset)
32{
33 return ((char *)blob) +
34 be32_to_cpu(blob->off_dt_strings) + offset;
35}
36
37/**
38 * of_fdt_get_property - Given a node in the given flat blob, return
39 * the property ptr
40 */
41void *of_fdt_get_property(struct boot_param_header *blob,
42 unsigned long node, const char *name,
43 unsigned long *size)
44{
45 unsigned long p = node;
46
47 do {
48 u32 tag = be32_to_cpup((__be32 *)p);
49 u32 sz, noff;
50 const char *nstr;
51
52 p += 4;
53 if (tag == OF_DT_NOP)
54 continue;
55 if (tag != OF_DT_PROP)
56 return NULL;
57
58 sz = be32_to_cpup((__be32 *)p);
59 noff = be32_to_cpup((__be32 *)(p + 4));
60 p += 8;
61 if (be32_to_cpu(blob->version) < 0x10)
62 p = ALIGN(p, sz >= 8 ? 8 : 4);
63
64 nstr = of_fdt_get_string(blob, noff);
65 if (nstr == NULL) {
66 pr_warning("Can't find property index name !\n");
67 return NULL;
68 }
69 if (strcmp(name, nstr) == 0) {
70 if (size)
71 *size = sz;
72 return (void *)p;
73 }
74 p += sz;
75 p = ALIGN(p, 4);
76 } while (1);
77}
78
79/** 29/**
80 * of_fdt_is_compatible - Return true if given node from the given blob has 30 * of_fdt_is_compatible - Return true if given node from the given blob has
81 * compat in its compatible list 31 * compat in its compatible list
@@ -86,13 +36,14 @@ void *of_fdt_get_property(struct boot_param_header *blob,
86 * On match, returns a non-zero value with smaller values returned for more 36 * On match, returns a non-zero value with smaller values returned for more
87 * specific compatible values. 37 * specific compatible values.
88 */ 38 */
89int of_fdt_is_compatible(struct boot_param_header *blob, 39int of_fdt_is_compatible(const void *blob,
90 unsigned long node, const char *compat) 40 unsigned long node, const char *compat)
91{ 41{
92 const char *cp; 42 const char *cp;
93 unsigned long cplen, l, score = 0; 43 int cplen;
44 unsigned long l, score = 0;
94 45
95 cp = of_fdt_get_property(blob, node, "compatible", &cplen); 46 cp = fdt_getprop(blob, node, "compatible", &cplen);
96 if (cp == NULL) 47 if (cp == NULL)
97 return 0; 48 return 0;
98 while (cplen > 0) { 49 while (cplen > 0) {
@@ -110,7 +61,7 @@ int of_fdt_is_compatible(struct boot_param_header *blob,
110/** 61/**
111 * of_fdt_match - Return true if node matches a list of compatible values 62 * of_fdt_match - Return true if node matches a list of compatible values
112 */ 63 */
113int of_fdt_match(struct boot_param_header *blob, unsigned long node, 64int of_fdt_match(const void *blob, unsigned long node,
114 const char *const *compat) 65 const char *const *compat)
115{ 66{
116 unsigned int tmp, score = 0; 67 unsigned int tmp, score = 0;
@@ -149,30 +100,29 @@ static void *unflatten_dt_alloc(void **mem, unsigned long size,
149 * @allnextpp: pointer to ->allnext from last allocated device_node 100 * @allnextpp: pointer to ->allnext from last allocated device_node
150 * @fpsize: Size of the node path up at the current depth. 101 * @fpsize: Size of the node path up at the current depth.
151 */ 102 */
152static void * unflatten_dt_node(struct boot_param_header *blob, 103static void * unflatten_dt_node(void *blob,
153 void *mem, 104 void *mem,
154 void **p, 105 int *poffset,
155 struct device_node *dad, 106 struct device_node *dad,
156 struct device_node ***allnextpp, 107 struct device_node ***allnextpp,
157 unsigned long fpsize) 108 unsigned long fpsize)
158{ 109{
110 const __be32 *p;
159 struct device_node *np; 111 struct device_node *np;
160 struct property *pp, **prev_pp = NULL; 112 struct property *pp, **prev_pp = NULL;
161 char *pathp; 113 const char *pathp;
162 u32 tag;
163 unsigned int l, allocl; 114 unsigned int l, allocl;
115 static int depth = 0;
116 int old_depth;
117 int offset;
164 int has_name = 0; 118 int has_name = 0;
165 int new_format = 0; 119 int new_format = 0;
166 120
167 tag = be32_to_cpup(*p); 121 pathp = fdt_get_name(blob, *poffset, &l);
168 if (tag != OF_DT_BEGIN_NODE) { 122 if (!pathp)
169 pr_err("Weird tag at start of node: %x\n", tag);
170 return mem; 123 return mem;
171 } 124
172 *p += 4; 125 allocl = l++;
173 pathp = *p;
174 l = allocl = strlen(pathp) + 1;
175 *p = PTR_ALIGN(*p + l, 4);
176 126
177 /* version 0x10 has a more compact unit name here instead of the full 127 /* version 0x10 has a more compact unit name here instead of the full
178 * path. we accumulate the full path size using "fpsize", we'll rebuild 128 * path. we accumulate the full path size using "fpsize", we'll rebuild
@@ -190,7 +140,7 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
190 fpsize = 1; 140 fpsize = 1;
191 allocl = 2; 141 allocl = 2;
192 l = 1; 142 l = 1;
193 *pathp = '\0'; 143 pathp = "";
194 } else { 144 } else {
195 /* account for '/' and path size minus terminal 0 145 /* account for '/' and path size minus terminal 0
196 * already in 'l' 146 * already in 'l'
@@ -237,32 +187,23 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
237 } 187 }
238 } 188 }
239 /* process properties */ 189 /* process properties */
240 while (1) { 190 for (offset = fdt_first_property_offset(blob, *poffset);
241 u32 sz, noff; 191 (offset >= 0);
242 char *pname; 192 (offset = fdt_next_property_offset(blob, offset))) {
243 193 const char *pname;
244 tag = be32_to_cpup(*p); 194 u32 sz;
245 if (tag == OF_DT_NOP) { 195
246 *p += 4; 196 if (!(p = fdt_getprop_by_offset(blob, offset, &pname, &sz))) {
247 continue; 197 offset = -FDT_ERR_INTERNAL;
248 }
249 if (tag != OF_DT_PROP)
250 break; 198 break;
251 *p += 4; 199 }
252 sz = be32_to_cpup(*p); 200
253 noff = be32_to_cpup(*p + 4);
254 *p += 8;
255 if (be32_to_cpu(blob->version) < 0x10)
256 *p = PTR_ALIGN(*p, sz >= 8 ? 8 : 4);
257
258 pname = of_fdt_get_string(blob, noff);
259 if (pname == NULL) { 201 if (pname == NULL) {
260 pr_info("Can't find property name in list !\n"); 202 pr_info("Can't find property name in list !\n");
261 break; 203 break;
262 } 204 }
263 if (strcmp(pname, "name") == 0) 205 if (strcmp(pname, "name") == 0)
264 has_name = 1; 206 has_name = 1;
265 l = strlen(pname) + 1;
266 pp = unflatten_dt_alloc(&mem, sizeof(struct property), 207 pp = unflatten_dt_alloc(&mem, sizeof(struct property),
267 __alignof__(struct property)); 208 __alignof__(struct property));
268 if (allnextpp) { 209 if (allnextpp) {
@@ -274,26 +215,25 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
274 if ((strcmp(pname, "phandle") == 0) || 215 if ((strcmp(pname, "phandle") == 0) ||
275 (strcmp(pname, "linux,phandle") == 0)) { 216 (strcmp(pname, "linux,phandle") == 0)) {
276 if (np->phandle == 0) 217 if (np->phandle == 0)
277 np->phandle = be32_to_cpup((__be32*)*p); 218 np->phandle = be32_to_cpup(p);
278 } 219 }
279 /* And we process the "ibm,phandle" property 220 /* And we process the "ibm,phandle" property
280 * used in pSeries dynamic device tree 221 * used in pSeries dynamic device tree
281 * stuff */ 222 * stuff */
282 if (strcmp(pname, "ibm,phandle") == 0) 223 if (strcmp(pname, "ibm,phandle") == 0)
283 np->phandle = be32_to_cpup((__be32 *)*p); 224 np->phandle = be32_to_cpup(p);
284 pp->name = pname; 225 pp->name = (char *)pname;
285 pp->length = sz; 226 pp->length = sz;
286 pp->value = *p; 227 pp->value = (__be32 *)p;
287 *prev_pp = pp; 228 *prev_pp = pp;
288 prev_pp = &pp->next; 229 prev_pp = &pp->next;
289 } 230 }
290 *p = PTR_ALIGN((*p) + sz, 4);
291 } 231 }
292 /* with version 0x10 we may not have the name property, recreate 232 /* with version 0x10 we may not have the name property, recreate
293 * it here from the unit name if absent 233 * it here from the unit name if absent
294 */ 234 */
295 if (!has_name) { 235 if (!has_name) {
296 char *p1 = pathp, *ps = pathp, *pa = NULL; 236 const char *p1 = pathp, *ps = pathp, *pa = NULL;
297 int sz; 237 int sz;
298 238
299 while (*p1) { 239 while (*p1) {
@@ -330,19 +270,18 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
330 if (!np->type) 270 if (!np->type)
331 np->type = "<NULL>"; 271 np->type = "<NULL>";
332 } 272 }
333 while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) { 273
334 if (tag == OF_DT_NOP) 274 old_depth = depth;
335 *p += 4; 275 *poffset = fdt_next_node(blob, *poffset, &depth);
336 else 276 if (depth < 0)
337 mem = unflatten_dt_node(blob, mem, p, np, allnextpp, 277 depth = 0;
338 fpsize); 278 while (*poffset > 0 && depth > old_depth)
339 tag = be32_to_cpup(*p); 279 mem = unflatten_dt_node(blob, mem, poffset, np, allnextpp,
340 } 280 fpsize);
341 if (tag != OF_DT_END_NODE) { 281
342 pr_err("Weird tag at end of node: %x\n", tag); 282 if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND)
343 return mem; 283 pr_err("unflatten: error %d processing FDT\n", *poffset);
344 } 284
345 *p += 4;
346 return mem; 285 return mem;
347} 286}
348 287
@@ -358,12 +297,13 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
358 * @dt_alloc: An allocator that provides a virtual address to memory 297 * @dt_alloc: An allocator that provides a virtual address to memory
359 * for the resulting tree 298 * for the resulting tree
360 */ 299 */
361static void __unflatten_device_tree(struct boot_param_header *blob, 300static void __unflatten_device_tree(void *blob,
362 struct device_node **mynodes, 301 struct device_node **mynodes,
363 void * (*dt_alloc)(u64 size, u64 align)) 302 void * (*dt_alloc)(u64 size, u64 align))
364{ 303{
365 unsigned long size; 304 unsigned long size;
366 void *start, *mem; 305 int start;
306 void *mem;
367 struct device_node **allnextp = mynodes; 307 struct device_node **allnextp = mynodes;
368 308
369 pr_debug(" -> unflatten_device_tree()\n"); 309 pr_debug(" -> unflatten_device_tree()\n");
@@ -374,18 +314,18 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
374 } 314 }
375 315
376 pr_debug("Unflattening device tree:\n"); 316 pr_debug("Unflattening device tree:\n");
377 pr_debug("magic: %08x\n", be32_to_cpu(blob->magic)); 317 pr_debug("magic: %08x\n", fdt_magic(blob));
378 pr_debug("size: %08x\n", be32_to_cpu(blob->totalsize)); 318 pr_debug("size: %08x\n", fdt_totalsize(blob));
379 pr_debug("version: %08x\n", be32_to_cpu(blob->version)); 319 pr_debug("version: %08x\n", fdt_version(blob));
380 320
381 if (be32_to_cpu(blob->magic) != OF_DT_HEADER) { 321 if (fdt_check_header(blob)) {
382 pr_err("Invalid device tree blob header\n"); 322 pr_err("Invalid device tree blob header\n");
383 return; 323 return;
384 } 324 }
385 325
386 /* First pass, scan for size */ 326 /* First pass, scan for size */
387 start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct); 327 start = 0;
388 size = (unsigned long)unflatten_dt_node(blob, 0, &start, NULL, NULL, 0); 328 size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL, 0);
389 size = ALIGN(size, 4); 329 size = ALIGN(size, 4);
390 330
391 pr_debug(" size is %lx, allocating...\n", size); 331 pr_debug(" size is %lx, allocating...\n", size);
@@ -399,10 +339,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
399 pr_debug(" unflattening %p...\n", mem); 339 pr_debug(" unflattening %p...\n", mem);
400 340
401 /* Second pass, do actual unflattening */ 341 /* Second pass, do actual unflattening */
402 start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct); 342 start = 0;
403 unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0); 343 unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0);
404 if (be32_to_cpup(start) != OF_DT_END)
405 pr_warning("Weird tag at end of tree: %08x\n", be32_to_cpup(start));
406 if (be32_to_cpup(mem + size) != 0xdeadbeef) 344 if (be32_to_cpup(mem + size) != 0xdeadbeef)
407 pr_warning("End of tree marker overwritten: %08x\n", 345 pr_warning("End of tree marker overwritten: %08x\n",
408 be32_to_cpup(mem + size)); 346 be32_to_cpup(mem + size));
@@ -427,9 +365,7 @@ static void *kernel_tree_alloc(u64 size, u64 align)
427void of_fdt_unflatten_tree(unsigned long *blob, 365void of_fdt_unflatten_tree(unsigned long *blob,
428 struct device_node **mynodes) 366 struct device_node **mynodes)
429{ 367{
430 struct boot_param_header *device_tree = 368 __unflatten_device_tree(blob, mynodes, &kernel_tree_alloc);
431 (struct boot_param_header *)blob;
432 __unflatten_device_tree(device_tree, mynodes, &kernel_tree_alloc);
433} 369}
434EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); 370EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
435 371
@@ -437,7 +373,7 @@ EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
437int __initdata dt_root_addr_cells; 373int __initdata dt_root_addr_cells;
438int __initdata dt_root_size_cells; 374int __initdata dt_root_size_cells;
439 375
440struct boot_param_header *initial_boot_params; 376void *initial_boot_params;
441 377
442#ifdef CONFIG_OF_EARLY_FLATTREE 378#ifdef CONFIG_OF_EARLY_FLATTREE
443 379
@@ -449,8 +385,8 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
449{ 385{
450 int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); 386 int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
451 phys_addr_t base, size; 387 phys_addr_t base, size;
452 unsigned long len; 388 int len;
453 __be32 *prop; 389 const __be32 *prop;
454 int nomap, first = 1; 390 int nomap, first = 1;
455 391
456 prop = of_get_flat_dt_prop(node, "reg", &len); 392 prop = of_get_flat_dt_prop(node, "reg", &len);
@@ -493,7 +429,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
493 */ 429 */
494static int __init __reserved_mem_check_root(unsigned long node) 430static int __init __reserved_mem_check_root(unsigned long node)
495{ 431{
496 __be32 *prop; 432 const __be32 *prop;
497 433
498 prop = of_get_flat_dt_prop(node, "#size-cells", NULL); 434 prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
499 if (!prop || be32_to_cpup(prop) != dt_root_size_cells) 435 if (!prop || be32_to_cpup(prop) != dt_root_size_cells)
@@ -557,9 +493,25 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname,
557 */ 493 */
558void __init early_init_fdt_scan_reserved_mem(void) 494void __init early_init_fdt_scan_reserved_mem(void)
559{ 495{
496 int n;
497 u64 base, size;
498
560 if (!initial_boot_params) 499 if (!initial_boot_params)
561 return; 500 return;
562 501
502 /* Reserve the dtb region */
503 early_init_dt_reserve_memory_arch(__pa(initial_boot_params),
504 fdt_totalsize(initial_boot_params),
505 0);
506
507 /* Process header /memreserve/ fields */
508 for (n = 0; ; n++) {
509 fdt_get_mem_rsv(initial_boot_params, n, &base, &size);
510 if (!size)
511 break;
512 early_init_dt_reserve_memory_arch(base, size, 0);
513 }
514
563 of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); 515 of_scan_flat_dt(__fdt_scan_reserved_mem, NULL);
564 fdt_init_reserved_mem(); 516 fdt_init_reserved_mem();
565} 517}
@@ -578,47 +530,19 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
578 void *data), 530 void *data),
579 void *data) 531 void *data)
580{ 532{
581 unsigned long p = ((unsigned long)initial_boot_params) + 533 const void *blob = initial_boot_params;
582 be32_to_cpu(initial_boot_params->off_dt_struct); 534 const char *pathp;
583 int rc = 0; 535 int offset, rc = 0, depth = -1;
584 int depth = -1; 536
585 537 for (offset = fdt_next_node(blob, -1, &depth);
586 do { 538 offset >= 0 && depth >= 0 && !rc;
587 u32 tag = be32_to_cpup((__be32 *)p); 539 offset = fdt_next_node(blob, offset, &depth)) {
588 const char *pathp; 540
589 541 pathp = fdt_get_name(blob, offset, NULL);
590 p += 4;
591 if (tag == OF_DT_END_NODE) {
592 depth--;
593 continue;
594 }
595 if (tag == OF_DT_NOP)
596 continue;
597 if (tag == OF_DT_END)
598 break;
599 if (tag == OF_DT_PROP) {
600 u32 sz = be32_to_cpup((__be32 *)p);
601 p += 8;
602 if (be32_to_cpu(initial_boot_params->version) < 0x10)
603 p = ALIGN(p, sz >= 8 ? 8 : 4);
604 p += sz;
605 p = ALIGN(p, 4);
606 continue;
607 }
608 if (tag != OF_DT_BEGIN_NODE) {
609 pr_err("Invalid tag %x in flat device tree!\n", tag);
610 return -EINVAL;
611 }
612 depth++;
613 pathp = (char *)p;
614 p = ALIGN(p + strlen(pathp) + 1, 4);
615 if (*pathp == '/') 542 if (*pathp == '/')
616 pathp = kbasename(pathp); 543 pathp = kbasename(pathp);
617 rc = it(p, pathp, depth, data); 544 rc = it(offset, pathp, depth, data);
618 if (rc != 0) 545 }
619 break;
620 } while (1);
621
622 return rc; 546 return rc;
623} 547}
624 548
@@ -627,14 +551,15 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
627 */ 551 */
628unsigned long __init of_get_flat_dt_root(void) 552unsigned long __init of_get_flat_dt_root(void)
629{ 553{
630 unsigned long p = ((unsigned long)initial_boot_params) + 554 return 0;
631 be32_to_cpu(initial_boot_params->off_dt_struct); 555}
632 556
633 while (be32_to_cpup((__be32 *)p) == OF_DT_NOP) 557/**
634 p += 4; 558 * of_get_flat_dt_size - Return the total size of the FDT
635 BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE); 559 */
636 p += 4; 560int __init of_get_flat_dt_size(void)
637 return ALIGN(p + strlen((char *)p) + 1, 4); 561{
562 return fdt_totalsize(initial_boot_params);
638} 563}
639 564
640/** 565/**
@@ -643,10 +568,10 @@ unsigned long __init of_get_flat_dt_root(void)
643 * This function can be used within scan_flattened_dt callback to get 568 * This function can be used within scan_flattened_dt callback to get
644 * access to properties 569 * access to properties
645 */ 570 */
646void *__init of_get_flat_dt_prop(unsigned long node, const char *name, 571const void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
647 unsigned long *size) 572 int *size)
648{ 573{
649 return of_fdt_get_property(initial_boot_params, node, name, size); 574 return fdt_getprop(initial_boot_params, node, name, size);
650} 575}
651 576
652/** 577/**
@@ -676,73 +601,6 @@ struct fdt_scan_status {
676 void *data; 601 void *data;
677}; 602};
678 603
679/**
680 * fdt_scan_node_by_path - iterator for of_scan_flat_dt_by_path function
681 */
682static int __init fdt_scan_node_by_path(unsigned long node, const char *uname,
683 int depth, void *data)
684{
685 struct fdt_scan_status *st = data;
686
687 /*
688 * if scan at the requested fdt node has been completed,
689 * return -ENXIO to abort further scanning
690 */
691 if (depth <= st->depth)
692 return -ENXIO;
693
694 /* requested fdt node has been found, so call iterator function */
695 if (st->found)
696 return st->iterator(node, uname, depth, st->data);
697
698 /* check if scanning automata is entering next level of fdt nodes */
699 if (depth == st->depth + 1 &&
700 strncmp(st->name, uname, st->namelen) == 0 &&
701 uname[st->namelen] == 0) {
702 st->depth += 1;
703 if (st->name[st->namelen] == 0) {
704 st->found = 1;
705 } else {
706 const char *next = st->name + st->namelen + 1;
707 st->name = next;
708 st->namelen = strcspn(next, "/");
709 }
710 return 0;
711 }
712
713 /* scan next fdt node */
714 return 0;
715}
716
717/**
718 * of_scan_flat_dt_by_path - scan flattened tree blob and call callback on each
719 * child of the given path.
720 * @path: path to start searching for children
721 * @it: callback function
722 * @data: context data pointer
723 *
724 * This function is used to scan the flattened device-tree starting from the
725 * node given by path. It is used to extract information (like reserved
726 * memory), which is required on ealy boot before we can unflatten the tree.
727 */
728int __init of_scan_flat_dt_by_path(const char *path,
729 int (*it)(unsigned long node, const char *name, int depth, void *data),
730 void *data)
731{
732 struct fdt_scan_status st = {path, 0, -1, 0, it, data};
733 int ret = 0;
734
735 if (initial_boot_params)
736 ret = of_scan_flat_dt(fdt_scan_node_by_path, &st);
737
738 if (!st.found)
739 return -ENOENT;
740 else if (ret == -ENXIO) /* scan has been completed */
741 return 0;
742 else
743 return ret;
744}
745
746const char * __init of_flat_dt_get_machine_name(void) 604const char * __init of_flat_dt_get_machine_name(void)
747{ 605{
748 const char *name; 606 const char *name;
@@ -782,7 +640,7 @@ const void * __init of_flat_dt_match_machine(const void *default_match,
782 } 640 }
783 if (!best_data) { 641 if (!best_data) {
784 const char *prop; 642 const char *prop;
785 long size; 643 int size;
786 644
787 pr_err("\n unrecognized device tree list:\n[ "); 645 pr_err("\n unrecognized device tree list:\n[ ");
788 646
@@ -811,8 +669,8 @@ const void * __init of_flat_dt_match_machine(const void *default_match,
811static void __init early_init_dt_check_for_initrd(unsigned long node) 669static void __init early_init_dt_check_for_initrd(unsigned long node)
812{ 670{
813 u64 start, end; 671 u64 start, end;
814 unsigned long len; 672 int len;
815 __be32 *prop; 673 const __be32 *prop;
816 674
817 pr_debug("Looking for initrd properties... "); 675 pr_debug("Looking for initrd properties... ");
818 676
@@ -839,13 +697,68 @@ static inline void early_init_dt_check_for_initrd(unsigned long node)
839} 697}
840#endif /* CONFIG_BLK_DEV_INITRD */ 698#endif /* CONFIG_BLK_DEV_INITRD */
841 699
700#ifdef CONFIG_SERIAL_EARLYCON
701extern struct of_device_id __earlycon_of_table[];
702
703int __init early_init_dt_scan_chosen_serial(void)
704{
705 int offset;
706 const char *p;
707 int l;
708 const struct of_device_id *match = __earlycon_of_table;
709 const void *fdt = initial_boot_params;
710
711 offset = fdt_path_offset(fdt, "/chosen");
712 if (offset < 0)
713 offset = fdt_path_offset(fdt, "/chosen@0");
714 if (offset < 0)
715 return -ENOENT;
716
717 p = fdt_getprop(fdt, offset, "stdout-path", &l);
718 if (!p)
719 p = fdt_getprop(fdt, offset, "linux,stdout-path", &l);
720 if (!p || !l)
721 return -ENOENT;
722
723 /* Get the node specified by stdout-path */
724 offset = fdt_path_offset(fdt, p);
725 if (offset < 0)
726 return -ENODEV;
727
728 while (match->compatible) {
729 unsigned long addr;
730 if (fdt_node_check_compatible(fdt, offset, match->compatible)) {
731 match++;
732 continue;
733 }
734
735 addr = fdt_translate_address(fdt, offset);
736 if (!addr)
737 return -ENXIO;
738
739 of_setup_earlycon(addr, match->data);
740 return 0;
741 }
742 return -ENODEV;
743}
744
745static int __init setup_of_earlycon(char *buf)
746{
747 if (buf)
748 return 0;
749
750 return early_init_dt_scan_chosen_serial();
751}
752early_param("earlycon", setup_of_earlycon);
753#endif
754
842/** 755/**
843 * early_init_dt_scan_root - fetch the top level address and size cells 756 * early_init_dt_scan_root - fetch the top level address and size cells
844 */ 757 */
845int __init early_init_dt_scan_root(unsigned long node, const char *uname, 758int __init early_init_dt_scan_root(unsigned long node, const char *uname,
846 int depth, void *data) 759 int depth, void *data)
847{ 760{
848 __be32 *prop; 761 const __be32 *prop;
849 762
850 if (depth != 0) 763 if (depth != 0)
851 return 0; 764 return 0;
@@ -867,9 +780,9 @@ int __init early_init_dt_scan_root(unsigned long node, const char *uname,
867 return 1; 780 return 1;
868} 781}
869 782
870u64 __init dt_mem_next_cell(int s, __be32 **cellp) 783u64 __init dt_mem_next_cell(int s, const __be32 **cellp)
871{ 784{
872 __be32 *p = *cellp; 785 const __be32 *p = *cellp;
873 786
874 *cellp = p + s; 787 *cellp = p + s;
875 return of_read_number(p, s); 788 return of_read_number(p, s);
@@ -881,9 +794,9 @@ u64 __init dt_mem_next_cell(int s, __be32 **cellp)
881int __init early_init_dt_scan_memory(unsigned long node, const char *uname, 794int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
882 int depth, void *data) 795 int depth, void *data)
883{ 796{
884 char *type = of_get_flat_dt_prop(node, "device_type", NULL); 797 const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
885 __be32 *reg, *endp; 798 const __be32 *reg, *endp;
886 unsigned long l; 799 int l;
887 800
888 /* We are scanning "memory" nodes only */ 801 /* We are scanning "memory" nodes only */
889 if (type == NULL) { 802 if (type == NULL) {
@@ -891,7 +804,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
891 * The longtrail doesn't have a device_type on the 804 * The longtrail doesn't have a device_type on the
892 * /memory node, so look for the node called /memory@0. 805 * /memory node, so look for the node called /memory@0.
893 */ 806 */
894 if (depth != 1 || strcmp(uname, "memory@0") != 0) 807 if (!IS_ENABLED(CONFIG_PPC32) || depth != 1 || strcmp(uname, "memory@0") != 0)
895 return 0; 808 return 0;
896 } else if (strcmp(type, "memory") != 0) 809 } else if (strcmp(type, "memory") != 0)
897 return 0; 810 return 0;
@@ -904,7 +817,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
904 817
905 endp = reg + (l / sizeof(__be32)); 818 endp = reg + (l / sizeof(__be32));
906 819
907 pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", 820 pr_debug("memory scan node %s, reg size %d, data: %x %x %x %x,\n",
908 uname, l, reg[0], reg[1], reg[2], reg[3]); 821 uname, l, reg[0], reg[1], reg[2], reg[3]);
909 822
910 while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { 823 while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
@@ -927,8 +840,8 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
927int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, 840int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
928 int depth, void *data) 841 int depth, void *data)
929{ 842{
930 unsigned long l; 843 int l;
931 char *p; 844 const char *p;
932 845
933 pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); 846 pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
934 847
@@ -1003,8 +916,8 @@ void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align)
1003int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, 916int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
1004 phys_addr_t size, bool nomap) 917 phys_addr_t size, bool nomap)
1005{ 918{
1006 pr_err("Reserved memory not supported, ignoring range 0x%llx - 0x%llx%s\n", 919 pr_err("Reserved memory not supported, ignoring range 0x%pa - 0x%pa%s\n",
1007 base, size, nomap ? " (nomap)" : ""); 920 &base, &size, nomap ? " (nomap)" : "");
1008 return -ENOSYS; 921 return -ENOSYS;
1009} 922}
1010#endif 923#endif
@@ -1018,7 +931,7 @@ bool __init early_init_dt_scan(void *params)
1018 initial_boot_params = params; 931 initial_boot_params = params;
1019 932
1020 /* check device tree validity */ 933 /* check device tree validity */
1021 if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) { 934 if (fdt_check_header(params)) {
1022 initial_boot_params = NULL; 935 initial_boot_params = NULL;
1023 return false; 936 return false;
1024 } 937 }
@@ -1073,9 +986,9 @@ void __init unflatten_and_copy_device_tree(void)
1073 return; 986 return;
1074 } 987 }
1075 988
1076 size = __be32_to_cpu(initial_boot_params->totalsize); 989 size = fdt_totalsize(initial_boot_params);
1077 dt = early_init_dt_alloc_memory_arch(size, 990 dt = early_init_dt_alloc_memory_arch(size,
1078 __alignof__(struct boot_param_header)); 991 roundup_pow_of_two(FDT_V17_SIZE));
1079 992
1080 if (dt) { 993 if (dt) {
1081 memcpy(dt, initial_boot_params, size); 994 memcpy(dt, initial_boot_params, size);
@@ -1084,4 +997,27 @@ void __init unflatten_and_copy_device_tree(void)
1084 unflatten_device_tree(); 997 unflatten_device_tree();
1085} 998}
1086 999
1000#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
1001static struct debugfs_blob_wrapper flat_dt_blob;
1002
1003static int __init of_flat_dt_debugfs_export_fdt(void)
1004{
1005 struct dentry *d = debugfs_create_dir("device-tree", NULL);
1006
1007 if (!d)
1008 return -ENOENT;
1009
1010 flat_dt_blob.data = initial_boot_params;
1011 flat_dt_blob.size = fdt_totalsize(initial_boot_params);
1012
1013 d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
1014 d, &flat_dt_blob);
1015 if (!d)
1016 return -ENOENT;
1017
1018 return 0;
1019}
1020module_init(of_flat_dt_debugfs_export_fdt);
1021#endif
1022
1087#endif /* CONFIG_OF_EARLY_FLATTREE */ 1023#endif /* CONFIG_OF_EARLY_FLATTREE */