aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/of')
-rw-r--r--drivers/of/Kconfig1
-rw-r--r--drivers/of/Makefile2
-rw-r--r--drivers/of/fdt.c398
-rw-r--r--drivers/of/of_reserved_mem.c4
4 files changed, 144 insertions, 261 deletions
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 889005fa4d04..2dcb0541012d 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -20,6 +20,7 @@ config OF_SELFTEST
20config OF_FLATTREE 20config OF_FLATTREE
21 bool 21 bool
22 select DTC 22 select DTC
23 select LIBFDT
23 24
24config OF_EARLY_FLATTREE 25config OF_EARLY_FLATTREE
25 bool 26 bool
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index ed9660adad77..9891232f999e 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -10,3 +10,5 @@ obj-$(CONFIG_OF_PCI) += of_pci.o
10obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o 10obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
11obj-$(CONFIG_OF_MTD) += of_mtd.o 11obj-$(CONFIG_OF_MTD) += of_mtd.o
12obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o 12obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
13
14CFLAGS_fdt.o = -I$(src)/../../scripts/dtc/libfdt
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 7a2ef7bb8022..a6f83ea107ae 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,12 @@
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>
23 24
24#include <asm/setup.h> /* for COMMAND_LINE_SIZE */ 25#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> 26#include <asm/page.h>
30 27
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/** 28/**
80 * of_fdt_is_compatible - Return true if given node from the given blob has 29 * of_fdt_is_compatible - Return true if given node from the given blob has
81 * compat in its compatible list 30 * compat in its compatible list
@@ -86,13 +35,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 35 * On match, returns a non-zero value with smaller values returned for more
87 * specific compatible values. 36 * specific compatible values.
88 */ 37 */
89int of_fdt_is_compatible(struct boot_param_header *blob, 38int of_fdt_is_compatible(const void *blob,
90 unsigned long node, const char *compat) 39 unsigned long node, const char *compat)
91{ 40{
92 const char *cp; 41 const char *cp;
93 unsigned long cplen, l, score = 0; 42 int cplen;
43 unsigned long l, score = 0;
94 44
95 cp = of_fdt_get_property(blob, node, "compatible", &cplen); 45 cp = fdt_getprop(blob, node, "compatible", &cplen);
96 if (cp == NULL) 46 if (cp == NULL)
97 return 0; 47 return 0;
98 while (cplen > 0) { 48 while (cplen > 0) {
@@ -110,7 +60,7 @@ int of_fdt_is_compatible(struct boot_param_header *blob,
110/** 60/**
111 * of_fdt_match - Return true if node matches a list of compatible values 61 * of_fdt_match - Return true if node matches a list of compatible values
112 */ 62 */
113int of_fdt_match(struct boot_param_header *blob, unsigned long node, 63int of_fdt_match(const void *blob, unsigned long node,
114 const char *const *compat) 64 const char *const *compat)
115{ 65{
116 unsigned int tmp, score = 0; 66 unsigned int tmp, score = 0;
@@ -149,30 +99,29 @@ static void *unflatten_dt_alloc(void **mem, unsigned long size,
149 * @allnextpp: pointer to ->allnext from last allocated device_node 99 * @allnextpp: pointer to ->allnext from last allocated device_node
150 * @fpsize: Size of the node path up at the current depth. 100 * @fpsize: Size of the node path up at the current depth.
151 */ 101 */
152static void * unflatten_dt_node(struct boot_param_header *blob, 102static void * unflatten_dt_node(void *blob,
153 void *mem, 103 void *mem,
154 void **p, 104 int *poffset,
155 struct device_node *dad, 105 struct device_node *dad,
156 struct device_node ***allnextpp, 106 struct device_node ***allnextpp,
157 unsigned long fpsize) 107 unsigned long fpsize)
158{ 108{
109 const __be32 *p;
159 struct device_node *np; 110 struct device_node *np;
160 struct property *pp, **prev_pp = NULL; 111 struct property *pp, **prev_pp = NULL;
161 char *pathp; 112 const char *pathp;
162 u32 tag;
163 unsigned int l, allocl; 113 unsigned int l, allocl;
114 static int depth = 0;
115 int old_depth;
116 int offset;
164 int has_name = 0; 117 int has_name = 0;
165 int new_format = 0; 118 int new_format = 0;
166 119
167 tag = be32_to_cpup(*p); 120 pathp = fdt_get_name(blob, *poffset, &l);
168 if (tag != OF_DT_BEGIN_NODE) { 121 if (!pathp)
169 pr_err("Weird tag at start of node: %x\n", tag);
170 return mem; 122 return mem;
171 } 123
172 *p += 4; 124 allocl = l++;
173 pathp = *p;
174 l = allocl = strlen(pathp) + 1;
175 *p = PTR_ALIGN(*p + l, 4);
176 125
177 /* version 0x10 has a more compact unit name here instead of the full 126 /* 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 127 * path. we accumulate the full path size using "fpsize", we'll rebuild
@@ -190,7 +139,7 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
190 fpsize = 1; 139 fpsize = 1;
191 allocl = 2; 140 allocl = 2;
192 l = 1; 141 l = 1;
193 *pathp = '\0'; 142 pathp = "";
194 } else { 143 } else {
195 /* account for '/' and path size minus terminal 0 144 /* account for '/' and path size minus terminal 0
196 * already in 'l' 145 * already in 'l'
@@ -237,32 +186,23 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
237 } 186 }
238 } 187 }
239 /* process properties */ 188 /* process properties */
240 while (1) { 189 for (offset = fdt_first_property_offset(blob, *poffset);
241 u32 sz, noff; 190 (offset >= 0);
242 char *pname; 191 (offset = fdt_next_property_offset(blob, offset))) {
243 192 const char *pname;
244 tag = be32_to_cpup(*p); 193 u32 sz;
245 if (tag == OF_DT_NOP) { 194
246 *p += 4; 195 if (!(p = fdt_getprop_by_offset(blob, offset, &pname, &sz))) {
247 continue; 196 offset = -FDT_ERR_INTERNAL;
248 }
249 if (tag != OF_DT_PROP)
250 break; 197 break;
251 *p += 4; 198 }
252 sz = be32_to_cpup(*p); 199
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) { 200 if (pname == NULL) {
260 pr_info("Can't find property name in list !\n"); 201 pr_info("Can't find property name in list !\n");
261 break; 202 break;
262 } 203 }
263 if (strcmp(pname, "name") == 0) 204 if (strcmp(pname, "name") == 0)
264 has_name = 1; 205 has_name = 1;
265 l = strlen(pname) + 1;
266 pp = unflatten_dt_alloc(&mem, sizeof(struct property), 206 pp = unflatten_dt_alloc(&mem, sizeof(struct property),
267 __alignof__(struct property)); 207 __alignof__(struct property));
268 if (allnextpp) { 208 if (allnextpp) {
@@ -274,26 +214,25 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
274 if ((strcmp(pname, "phandle") == 0) || 214 if ((strcmp(pname, "phandle") == 0) ||
275 (strcmp(pname, "linux,phandle") == 0)) { 215 (strcmp(pname, "linux,phandle") == 0)) {
276 if (np->phandle == 0) 216 if (np->phandle == 0)
277 np->phandle = be32_to_cpup((__be32*)*p); 217 np->phandle = be32_to_cpup(p);
278 } 218 }
279 /* And we process the "ibm,phandle" property 219 /* And we process the "ibm,phandle" property
280 * used in pSeries dynamic device tree 220 * used in pSeries dynamic device tree
281 * stuff */ 221 * stuff */
282 if (strcmp(pname, "ibm,phandle") == 0) 222 if (strcmp(pname, "ibm,phandle") == 0)
283 np->phandle = be32_to_cpup((__be32 *)*p); 223 np->phandle = be32_to_cpup(p);
284 pp->name = pname; 224 pp->name = (char *)pname;
285 pp->length = sz; 225 pp->length = sz;
286 pp->value = *p; 226 pp->value = (__be32 *)p;
287 *prev_pp = pp; 227 *prev_pp = pp;
288 prev_pp = &pp->next; 228 prev_pp = &pp->next;
289 } 229 }
290 *p = PTR_ALIGN((*p) + sz, 4);
291 } 230 }
292 /* with version 0x10 we may not have the name property, recreate 231 /* with version 0x10 we may not have the name property, recreate
293 * it here from the unit name if absent 232 * it here from the unit name if absent
294 */ 233 */
295 if (!has_name) { 234 if (!has_name) {
296 char *p1 = pathp, *ps = pathp, *pa = NULL; 235 const char *p1 = pathp, *ps = pathp, *pa = NULL;
297 int sz; 236 int sz;
298 237
299 while (*p1) { 238 while (*p1) {
@@ -330,19 +269,18 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
330 if (!np->type) 269 if (!np->type)
331 np->type = "<NULL>"; 270 np->type = "<NULL>";
332 } 271 }
333 while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) { 272
334 if (tag == OF_DT_NOP) 273 old_depth = depth;
335 *p += 4; 274 *poffset = fdt_next_node(blob, *poffset, &depth);
336 else 275 if (depth < 0)
337 mem = unflatten_dt_node(blob, mem, p, np, allnextpp, 276 depth = 0;
338 fpsize); 277 while (*poffset > 0 && depth > old_depth)
339 tag = be32_to_cpup(*p); 278 mem = unflatten_dt_node(blob, mem, poffset, np, allnextpp,
340 } 279 fpsize);
341 if (tag != OF_DT_END_NODE) { 280
342 pr_err("Weird tag at end of node: %x\n", tag); 281 if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND)
343 return mem; 282 pr_err("unflatten: error %d processing FDT\n", *poffset);
344 } 283
345 *p += 4;
346 return mem; 284 return mem;
347} 285}
348 286
@@ -358,12 +296,13 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
358 * @dt_alloc: An allocator that provides a virtual address to memory 296 * @dt_alloc: An allocator that provides a virtual address to memory
359 * for the resulting tree 297 * for the resulting tree
360 */ 298 */
361static void __unflatten_device_tree(struct boot_param_header *blob, 299static void __unflatten_device_tree(void *blob,
362 struct device_node **mynodes, 300 struct device_node **mynodes,
363 void * (*dt_alloc)(u64 size, u64 align)) 301 void * (*dt_alloc)(u64 size, u64 align))
364{ 302{
365 unsigned long size; 303 unsigned long size;
366 void *start, *mem; 304 int start;
305 void *mem;
367 struct device_node **allnextp = mynodes; 306 struct device_node **allnextp = mynodes;
368 307
369 pr_debug(" -> unflatten_device_tree()\n"); 308 pr_debug(" -> unflatten_device_tree()\n");
@@ -374,17 +313,17 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
374 } 313 }
375 314
376 pr_debug("Unflattening device tree:\n"); 315 pr_debug("Unflattening device tree:\n");
377 pr_debug("magic: %08x\n", be32_to_cpu(blob->magic)); 316 pr_debug("magic: %08x\n", fdt_magic(blob));
378 pr_debug("size: %08x\n", be32_to_cpu(blob->totalsize)); 317 pr_debug("size: %08x\n", fdt_totalsize(blob));
379 pr_debug("version: %08x\n", be32_to_cpu(blob->version)); 318 pr_debug("version: %08x\n", fdt_version(blob));
380 319
381 if (be32_to_cpu(blob->magic) != OF_DT_HEADER) { 320 if (fdt_check_header(blob)) {
382 pr_err("Invalid device tree blob header\n"); 321 pr_err("Invalid device tree blob header\n");
383 return; 322 return;
384 } 323 }
385 324
386 /* First pass, scan for size */ 325 /* First pass, scan for size */
387 start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct); 326 start = 0;
388 size = (unsigned long)unflatten_dt_node(blob, 0, &start, NULL, NULL, 0); 327 size = (unsigned long)unflatten_dt_node(blob, 0, &start, NULL, NULL, 0);
389 size = ALIGN(size, 4); 328 size = ALIGN(size, 4);
390 329
@@ -399,10 +338,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
399 pr_debug(" unflattening %p...\n", mem); 338 pr_debug(" unflattening %p...\n", mem);
400 339
401 /* Second pass, do actual unflattening */ 340 /* Second pass, do actual unflattening */
402 start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct); 341 start = 0;
403 unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0); 342 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) 343 if (be32_to_cpup(mem + size) != 0xdeadbeef)
407 pr_warning("End of tree marker overwritten: %08x\n", 344 pr_warning("End of tree marker overwritten: %08x\n",
408 be32_to_cpup(mem + size)); 345 be32_to_cpup(mem + size));
@@ -427,9 +364,7 @@ static void *kernel_tree_alloc(u64 size, u64 align)
427void of_fdt_unflatten_tree(unsigned long *blob, 364void of_fdt_unflatten_tree(unsigned long *blob,
428 struct device_node **mynodes) 365 struct device_node **mynodes)
429{ 366{
430 struct boot_param_header *device_tree = 367 __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} 368}
434EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); 369EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
435 370
@@ -437,7 +372,7 @@ EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
437int __initdata dt_root_addr_cells; 372int __initdata dt_root_addr_cells;
438int __initdata dt_root_size_cells; 373int __initdata dt_root_size_cells;
439 374
440struct boot_param_header *initial_boot_params; 375void *initial_boot_params;
441 376
442#ifdef CONFIG_OF_EARLY_FLATTREE 377#ifdef CONFIG_OF_EARLY_FLATTREE
443 378
@@ -449,8 +384,8 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
449{ 384{
450 int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); 385 int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
451 phys_addr_t base, size; 386 phys_addr_t base, size;
452 unsigned long len; 387 int len;
453 __be32 *prop; 388 const __be32 *prop;
454 int nomap, first = 1; 389 int nomap, first = 1;
455 390
456 prop = of_get_flat_dt_prop(node, "reg", &len); 391 prop = of_get_flat_dt_prop(node, "reg", &len);
@@ -493,7 +428,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
493 */ 428 */
494static int __init __reserved_mem_check_root(unsigned long node) 429static int __init __reserved_mem_check_root(unsigned long node)
495{ 430{
496 __be32 *prop; 431 const __be32 *prop;
497 432
498 prop = of_get_flat_dt_prop(node, "#size-cells", NULL); 433 prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
499 if (!prop || be32_to_cpup(prop) != dt_root_size_cells) 434 if (!prop || be32_to_cpup(prop) != dt_root_size_cells)
@@ -557,9 +492,25 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname,
557 */ 492 */
558void __init early_init_fdt_scan_reserved_mem(void) 493void __init early_init_fdt_scan_reserved_mem(void)
559{ 494{
495 int n;
496 u64 base, size;
497
560 if (!initial_boot_params) 498 if (!initial_boot_params)
561 return; 499 return;
562 500
501 /* Reserve the dtb region */
502 early_init_dt_reserve_memory_arch(__pa(initial_boot_params),
503 fdt_totalsize(initial_boot_params),
504 0);
505
506 /* Process header /memreserve/ fields */
507 for (n = 0; ; n++) {
508 fdt_get_mem_rsv(initial_boot_params, n, &base, &size);
509 if (!size)
510 break;
511 early_init_dt_reserve_memory_arch(base, size, 0);
512 }
513
563 of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); 514 of_scan_flat_dt(__fdt_scan_reserved_mem, NULL);
564 fdt_init_reserved_mem(); 515 fdt_init_reserved_mem();
565} 516}
@@ -578,47 +529,19 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
578 void *data), 529 void *data),
579 void *data) 530 void *data)
580{ 531{
581 unsigned long p = ((unsigned long)initial_boot_params) + 532 const void *blob = initial_boot_params;
582 be32_to_cpu(initial_boot_params->off_dt_struct); 533 const char *pathp;
583 int rc = 0; 534 int offset, rc = 0, depth = -1;
584 int depth = -1; 535
585 536 for (offset = fdt_next_node(blob, -1, &depth);
586 do { 537 offset >= 0 && depth >= 0 && !rc;
587 u32 tag = be32_to_cpup((__be32 *)p); 538 offset = fdt_next_node(blob, offset, &depth)) {
588 const char *pathp; 539
589 540 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 == '/') 541 if (*pathp == '/')
616 pathp = kbasename(pathp); 542 pathp = kbasename(pathp);
617 rc = it(p, pathp, depth, data); 543 rc = it(offset, pathp, depth, data);
618 if (rc != 0) 544 }
619 break;
620 } while (1);
621
622 return rc; 545 return rc;
623} 546}
624 547
@@ -627,14 +550,15 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
627 */ 550 */
628unsigned long __init of_get_flat_dt_root(void) 551unsigned long __init of_get_flat_dt_root(void)
629{ 552{
630 unsigned long p = ((unsigned long)initial_boot_params) + 553 return 0;
631 be32_to_cpu(initial_boot_params->off_dt_struct); 554}
632 555
633 while (be32_to_cpup((__be32 *)p) == OF_DT_NOP) 556/**
634 p += 4; 557 * of_get_flat_dt_size - Return the total size of the FDT
635 BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE); 558 */
636 p += 4; 559int __init of_get_flat_dt_size(void)
637 return ALIGN(p + strlen((char *)p) + 1, 4); 560{
561 return fdt_totalsize(initial_boot_params);
638} 562}
639 563
640/** 564/**
@@ -643,10 +567,10 @@ unsigned long __init of_get_flat_dt_root(void)
643 * This function can be used within scan_flattened_dt callback to get 567 * This function can be used within scan_flattened_dt callback to get
644 * access to properties 568 * access to properties
645 */ 569 */
646void *__init of_get_flat_dt_prop(unsigned long node, const char *name, 570const void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
647 unsigned long *size) 571 int *size)
648{ 572{
649 return of_fdt_get_property(initial_boot_params, node, name, size); 573 return fdt_getprop(initial_boot_params, node, name, size);
650} 574}
651 575
652/** 576/**
@@ -676,73 +600,6 @@ struct fdt_scan_status {
676 void *data; 600 void *data;
677}; 601};
678 602
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) 603const char * __init of_flat_dt_get_machine_name(void)
747{ 604{
748 const char *name; 605 const char *name;
@@ -782,7 +639,7 @@ const void * __init of_flat_dt_match_machine(const void *default_match,
782 } 639 }
783 if (!best_data) { 640 if (!best_data) {
784 const char *prop; 641 const char *prop;
785 long size; 642 int size;
786 643
787 pr_err("\n unrecognized device tree list:\n[ "); 644 pr_err("\n unrecognized device tree list:\n[ ");
788 645
@@ -811,8 +668,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) 668static void __init early_init_dt_check_for_initrd(unsigned long node)
812{ 669{
813 u64 start, end; 670 u64 start, end;
814 unsigned long len; 671 int len;
815 __be32 *prop; 672 const __be32 *prop;
816 673
817 pr_debug("Looking for initrd properties... "); 674 pr_debug("Looking for initrd properties... ");
818 675
@@ -845,7 +702,7 @@ static inline void early_init_dt_check_for_initrd(unsigned long node)
845int __init early_init_dt_scan_root(unsigned long node, const char *uname, 702int __init early_init_dt_scan_root(unsigned long node, const char *uname,
846 int depth, void *data) 703 int depth, void *data)
847{ 704{
848 __be32 *prop; 705 const __be32 *prop;
849 706
850 if (depth != 0) 707 if (depth != 0)
851 return 0; 708 return 0;
@@ -867,9 +724,9 @@ int __init early_init_dt_scan_root(unsigned long node, const char *uname,
867 return 1; 724 return 1;
868} 725}
869 726
870u64 __init dt_mem_next_cell(int s, __be32 **cellp) 727u64 __init dt_mem_next_cell(int s, const __be32 **cellp)
871{ 728{
872 __be32 *p = *cellp; 729 const __be32 *p = *cellp;
873 730
874 *cellp = p + s; 731 *cellp = p + s;
875 return of_read_number(p, s); 732 return of_read_number(p, s);
@@ -881,9 +738,9 @@ u64 __init dt_mem_next_cell(int s, __be32 **cellp)
881int __init early_init_dt_scan_memory(unsigned long node, const char *uname, 738int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
882 int depth, void *data) 739 int depth, void *data)
883{ 740{
884 char *type = of_get_flat_dt_prop(node, "device_type", NULL); 741 const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
885 __be32 *reg, *endp; 742 const __be32 *reg, *endp;
886 unsigned long l; 743 int l;
887 744
888 /* We are scanning "memory" nodes only */ 745 /* We are scanning "memory" nodes only */
889 if (type == NULL) { 746 if (type == NULL) {
@@ -904,7 +761,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
904 761
905 endp = reg + (l / sizeof(__be32)); 762 endp = reg + (l / sizeof(__be32));
906 763
907 pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", 764 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]); 765 uname, l, reg[0], reg[1], reg[2], reg[3]);
909 766
910 while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { 767 while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
@@ -927,8 +784,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, 784int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
928 int depth, void *data) 785 int depth, void *data)
929{ 786{
930 unsigned long l; 787 int l;
931 char *p; 788 const char *p;
932 789
933 pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); 790 pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
934 791
@@ -1003,8 +860,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, 860int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
1004 phys_addr_t size, bool nomap) 861 phys_addr_t size, bool nomap)
1005{ 862{
1006 pr_err("Reserved memory not supported, ignoring range 0x%llx - 0x%llx%s\n", 863 pr_err("Reserved memory not supported, ignoring range 0x%pa - 0x%pa%s\n",
1007 base, size, nomap ? " (nomap)" : ""); 864 &base, &size, nomap ? " (nomap)" : "");
1008 return -ENOSYS; 865 return -ENOSYS;
1009} 866}
1010#endif 867#endif
@@ -1018,7 +875,7 @@ bool __init early_init_dt_scan(void *params)
1018 initial_boot_params = params; 875 initial_boot_params = params;
1019 876
1020 /* check device tree validity */ 877 /* check device tree validity */
1021 if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) { 878 if (fdt_check_header(params)) {
1022 initial_boot_params = NULL; 879 initial_boot_params = NULL;
1023 return false; 880 return false;
1024 } 881 }
@@ -1073,9 +930,9 @@ void __init unflatten_and_copy_device_tree(void)
1073 return; 930 return;
1074 } 931 }
1075 932
1076 size = __be32_to_cpu(initial_boot_params->totalsize); 933 size = fdt_totalsize(initial_boot_params);
1077 dt = early_init_dt_alloc_memory_arch(size, 934 dt = early_init_dt_alloc_memory_arch(size,
1078 __alignof__(struct boot_param_header)); 935 roundup_pow_of_two(FDT_V17_SIZE));
1079 936
1080 if (dt) { 937 if (dt) {
1081 memcpy(dt, initial_boot_params, size); 938 memcpy(dt, initial_boot_params, size);
@@ -1084,4 +941,27 @@ void __init unflatten_and_copy_device_tree(void)
1084 unflatten_device_tree(); 941 unflatten_device_tree();
1085} 942}
1086 943
944#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
945static struct debugfs_blob_wrapper flat_dt_blob;
946
947static int __init of_flat_dt_debugfs_export_fdt(void)
948{
949 struct dentry *d = debugfs_create_dir("device-tree", NULL);
950
951 if (!d)
952 return -ENOENT;
953
954 flat_dt_blob.data = initial_boot_params;
955 flat_dt_blob.size = fdt_totalsize(initial_boot_params);
956
957 d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
958 d, &flat_dt_blob);
959 if (!d)
960 return -ENOENT;
961
962 return 0;
963}
964module_init(of_flat_dt_debugfs_export_fdt);
965#endif
966
1087#endif /* CONFIG_OF_EARLY_FLATTREE */ 967#endif /* CONFIG_OF_EARLY_FLATTREE */
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index daaaf935911d..e420eb52e5c9 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -95,8 +95,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node,
95 int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); 95 int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
96 phys_addr_t start = 0, end = 0; 96 phys_addr_t start = 0, end = 0;
97 phys_addr_t base = 0, align = 0, size; 97 phys_addr_t base = 0, align = 0, size;
98 unsigned long len; 98 int len;
99 __be32 *prop; 99 const __be32 *prop;
100 int nomap; 100 int nomap;
101 int ret; 101 int ret;
102 102