diff options
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/Kconfig | 1 | ||||
-rw-r--r-- | drivers/of/Makefile | 2 | ||||
-rw-r--r-- | drivers/of/fdt.c | 398 | ||||
-rw-r--r-- | drivers/of/of_reserved_mem.c | 4 |
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 | |||
20 | config OF_FLATTREE | 20 | config OF_FLATTREE |
21 | bool | 21 | bool |
22 | select DTC | 22 | select DTC |
23 | select LIBFDT | ||
23 | 24 | ||
24 | config OF_EARLY_FLATTREE | 25 | config 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 | |||
10 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o | 10 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o |
11 | obj-$(CONFIG_OF_MTD) += of_mtd.o | 11 | obj-$(CONFIG_OF_MTD) += of_mtd.o |
12 | obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o | 12 | obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o |
13 | |||
14 | CFLAGS_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 | ||
31 | char *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 | */ | ||
41 | void *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 | */ |
89 | int of_fdt_is_compatible(struct boot_param_header *blob, | 38 | int 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 | */ |
113 | int of_fdt_match(struct boot_param_header *blob, unsigned long node, | 63 | int 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 | */ |
152 | static void * unflatten_dt_node(struct boot_param_header *blob, | 102 | static 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 | */ |
361 | static void __unflatten_device_tree(struct boot_param_header *blob, | 299 | static 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) | |||
427 | void of_fdt_unflatten_tree(unsigned long *blob, | 364 | void 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 | } |
434 | EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); | 369 | EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); |
435 | 370 | ||
@@ -437,7 +372,7 @@ EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); | |||
437 | int __initdata dt_root_addr_cells; | 372 | int __initdata dt_root_addr_cells; |
438 | int __initdata dt_root_size_cells; | 373 | int __initdata dt_root_size_cells; |
439 | 374 | ||
440 | struct boot_param_header *initial_boot_params; | 375 | void *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 | */ |
494 | static int __init __reserved_mem_check_root(unsigned long node) | 429 | static 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 | */ |
558 | void __init early_init_fdt_scan_reserved_mem(void) | 493 | void __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 | */ |
628 | unsigned long __init of_get_flat_dt_root(void) | 551 | unsigned 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; | 559 | int __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 | */ |
646 | void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | 570 | const 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 | */ | ||
682 | static 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 | */ | ||
728 | int __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 | |||
746 | const char * __init of_flat_dt_get_machine_name(void) | 603 | const 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, | |||
811 | static void __init early_init_dt_check_for_initrd(unsigned long node) | 668 | static 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) | |||
845 | int __init early_init_dt_scan_root(unsigned long node, const char *uname, | 702 | int __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 | ||
870 | u64 __init dt_mem_next_cell(int s, __be32 **cellp) | 727 | u64 __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) | |||
881 | int __init early_init_dt_scan_memory(unsigned long node, const char *uname, | 738 | int __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, | |||
927 | int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | 784 | int __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) | |||
1003 | int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, | 860 | int __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) | ||
945 | static struct debugfs_blob_wrapper flat_dt_blob; | ||
946 | |||
947 | static 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 | } | ||
964 | module_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 | ||