diff options
Diffstat (limited to 'drivers/of/fdt.c')
-rw-r--r-- | drivers/of/fdt.c | 438 |
1 files changed, 273 insertions, 165 deletions
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 65da5aec7552..65200af29c52 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -11,10 +11,12 @@ | |||
11 | 11 | ||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/initrd.h> | 13 | #include <linux/initrd.h> |
14 | #include <linux/module.h> | ||
14 | #include <linux/of.h> | 15 | #include <linux/of.h> |
15 | #include <linux/of_fdt.h> | 16 | #include <linux/of_fdt.h> |
16 | #include <linux/string.h> | 17 | #include <linux/string.h> |
17 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
19 | #include <linux/slab.h> | ||
18 | 20 | ||
19 | #ifdef CONFIG_PPC | 21 | #ifdef CONFIG_PPC |
20 | #include <asm/machdep.h> | 22 | #include <asm/machdep.h> |
@@ -22,104 +24,19 @@ | |||
22 | 24 | ||
23 | #include <asm/page.h> | 25 | #include <asm/page.h> |
24 | 26 | ||
25 | int __initdata dt_root_addr_cells; | 27 | char *of_fdt_get_string(struct boot_param_header *blob, u32 offset) |
26 | int __initdata dt_root_size_cells; | ||
27 | |||
28 | struct boot_param_header *initial_boot_params; | ||
29 | |||
30 | char *find_flat_dt_string(u32 offset) | ||
31 | { | 28 | { |
32 | return ((char *)initial_boot_params) + | 29 | return ((char *)blob) + |
33 | be32_to_cpu(initial_boot_params->off_dt_strings) + offset; | 30 | be32_to_cpu(blob->off_dt_strings) + offset; |
34 | } | ||
35 | |||
36 | /** | ||
37 | * of_scan_flat_dt - scan flattened tree blob and call callback on each. | ||
38 | * @it: callback function | ||
39 | * @data: context data pointer | ||
40 | * | ||
41 | * This function is used to scan the flattened device-tree, it is | ||
42 | * used to extract the memory information at boot before we can | ||
43 | * unflatten the tree | ||
44 | */ | ||
45 | int __init of_scan_flat_dt(int (*it)(unsigned long node, | ||
46 | const char *uname, int depth, | ||
47 | void *data), | ||
48 | void *data) | ||
49 | { | ||
50 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
51 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
52 | int rc = 0; | ||
53 | int depth = -1; | ||
54 | |||
55 | do { | ||
56 | u32 tag = be32_to_cpup((__be32 *)p); | ||
57 | char *pathp; | ||
58 | |||
59 | p += 4; | ||
60 | if (tag == OF_DT_END_NODE) { | ||
61 | depth--; | ||
62 | continue; | ||
63 | } | ||
64 | if (tag == OF_DT_NOP) | ||
65 | continue; | ||
66 | if (tag == OF_DT_END) | ||
67 | break; | ||
68 | if (tag == OF_DT_PROP) { | ||
69 | u32 sz = be32_to_cpup((__be32 *)p); | ||
70 | p += 8; | ||
71 | if (be32_to_cpu(initial_boot_params->version) < 0x10) | ||
72 | p = ALIGN(p, sz >= 8 ? 8 : 4); | ||
73 | p += sz; | ||
74 | p = ALIGN(p, 4); | ||
75 | continue; | ||
76 | } | ||
77 | if (tag != OF_DT_BEGIN_NODE) { | ||
78 | pr_err("Invalid tag %x in flat device tree!\n", tag); | ||
79 | return -EINVAL; | ||
80 | } | ||
81 | depth++; | ||
82 | pathp = (char *)p; | ||
83 | p = ALIGN(p + strlen(pathp) + 1, 4); | ||
84 | if ((*pathp) == '/') { | ||
85 | char *lp, *np; | ||
86 | for (lp = NULL, np = pathp; *np; np++) | ||
87 | if ((*np) == '/') | ||
88 | lp = np+1; | ||
89 | if (lp != NULL) | ||
90 | pathp = lp; | ||
91 | } | ||
92 | rc = it(p, pathp, depth, data); | ||
93 | if (rc != 0) | ||
94 | break; | ||
95 | } while (1); | ||
96 | |||
97 | return rc; | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * of_get_flat_dt_root - find the root node in the flat blob | ||
102 | */ | ||
103 | unsigned long __init of_get_flat_dt_root(void) | ||
104 | { | ||
105 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
106 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
107 | |||
108 | while (be32_to_cpup((__be32 *)p) == OF_DT_NOP) | ||
109 | p += 4; | ||
110 | BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE); | ||
111 | p += 4; | ||
112 | return ALIGN(p + strlen((char *)p) + 1, 4); | ||
113 | } | 31 | } |
114 | 32 | ||
115 | /** | 33 | /** |
116 | * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr | 34 | * of_fdt_get_property - Given a node in the given flat blob, return |
117 | * | 35 | * the property ptr |
118 | * This function can be used within scan_flattened_dt callback to get | ||
119 | * access to properties | ||
120 | */ | 36 | */ |
121 | void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | 37 | void *of_fdt_get_property(struct boot_param_header *blob, |
122 | unsigned long *size) | 38 | unsigned long node, const char *name, |
39 | unsigned long *size) | ||
123 | { | 40 | { |
124 | unsigned long p = node; | 41 | unsigned long p = node; |
125 | 42 | ||
@@ -137,10 +54,10 @@ void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | |||
137 | sz = be32_to_cpup((__be32 *)p); | 54 | sz = be32_to_cpup((__be32 *)p); |
138 | noff = be32_to_cpup((__be32 *)(p + 4)); | 55 | noff = be32_to_cpup((__be32 *)(p + 4)); |
139 | p += 8; | 56 | p += 8; |
140 | if (be32_to_cpu(initial_boot_params->version) < 0x10) | 57 | if (be32_to_cpu(blob->version) < 0x10) |
141 | p = ALIGN(p, sz >= 8 ? 8 : 4); | 58 | p = ALIGN(p, sz >= 8 ? 8 : 4); |
142 | 59 | ||
143 | nstr = find_flat_dt_string(noff); | 60 | nstr = of_fdt_get_string(blob, noff); |
144 | if (nstr == NULL) { | 61 | if (nstr == NULL) { |
145 | pr_warning("Can't find property index name !\n"); | 62 | pr_warning("Can't find property index name !\n"); |
146 | return NULL; | 63 | return NULL; |
@@ -156,21 +73,28 @@ void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | |||
156 | } | 73 | } |
157 | 74 | ||
158 | /** | 75 | /** |
159 | * of_flat_dt_is_compatible - Return true if given node has compat in compatible list | 76 | * of_fdt_is_compatible - Return true if given node from the given blob has |
77 | * compat in its compatible list | ||
78 | * @blob: A device tree blob | ||
160 | * @node: node to test | 79 | * @node: node to test |
161 | * @compat: compatible string to compare with compatible list. | 80 | * @compat: compatible string to compare with compatible list. |
81 | * | ||
82 | * On match, returns a non-zero value with smaller values returned for more | ||
83 | * specific compatible values. | ||
162 | */ | 84 | */ |
163 | int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) | 85 | int of_fdt_is_compatible(struct boot_param_header *blob, |
86 | unsigned long node, const char *compat) | ||
164 | { | 87 | { |
165 | const char *cp; | 88 | const char *cp; |
166 | unsigned long cplen, l; | 89 | unsigned long cplen, l, score = 0; |
167 | 90 | ||
168 | cp = of_get_flat_dt_prop(node, "compatible", &cplen); | 91 | cp = of_fdt_get_property(blob, node, "compatible", &cplen); |
169 | if (cp == NULL) | 92 | if (cp == NULL) |
170 | return 0; | 93 | return 0; |
171 | while (cplen > 0) { | 94 | while (cplen > 0) { |
95 | score++; | ||
172 | if (of_compat_cmp(cp, compat, strlen(compat)) == 0) | 96 | if (of_compat_cmp(cp, compat, strlen(compat)) == 0) |
173 | return 1; | 97 | return score; |
174 | l = strlen(cp) + 1; | 98 | l = strlen(cp) + 1; |
175 | cp += l; | 99 | cp += l; |
176 | cplen -= l; | 100 | cplen -= l; |
@@ -179,7 +103,28 @@ int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) | |||
179 | return 0; | 103 | return 0; |
180 | } | 104 | } |
181 | 105 | ||
182 | static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, | 106 | /** |
107 | * of_fdt_match - Return true if node matches a list of compatible values | ||
108 | */ | ||
109 | int of_fdt_match(struct boot_param_header *blob, unsigned long node, | ||
110 | const char **compat) | ||
111 | { | ||
112 | unsigned int tmp, score = 0; | ||
113 | |||
114 | if (!compat) | ||
115 | return 0; | ||
116 | |||
117 | while (*compat) { | ||
118 | tmp = of_fdt_is_compatible(blob, node, *compat); | ||
119 | if (tmp && (score == 0 || (tmp < score))) | ||
120 | score = tmp; | ||
121 | compat++; | ||
122 | } | ||
123 | |||
124 | return score; | ||
125 | } | ||
126 | |||
127 | static void *unflatten_dt_alloc(unsigned long *mem, unsigned long size, | ||
183 | unsigned long align) | 128 | unsigned long align) |
184 | { | 129 | { |
185 | void *res; | 130 | void *res; |
@@ -193,16 +138,19 @@ static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, | |||
193 | 138 | ||
194 | /** | 139 | /** |
195 | * unflatten_dt_node - Alloc and populate a device_node from the flat tree | 140 | * unflatten_dt_node - Alloc and populate a device_node from the flat tree |
141 | * @blob: The parent device tree blob | ||
142 | * @mem: Memory chunk to use for allocating device nodes and properties | ||
196 | * @p: pointer to node in flat tree | 143 | * @p: pointer to node in flat tree |
197 | * @dad: Parent struct device_node | 144 | * @dad: Parent struct device_node |
198 | * @allnextpp: pointer to ->allnext from last allocated device_node | 145 | * @allnextpp: pointer to ->allnext from last allocated device_node |
199 | * @fpsize: Size of the node path up at the current depth. | 146 | * @fpsize: Size of the node path up at the current depth. |
200 | */ | 147 | */ |
201 | unsigned long __init unflatten_dt_node(unsigned long mem, | 148 | static unsigned long unflatten_dt_node(struct boot_param_header *blob, |
202 | unsigned long *p, | 149 | unsigned long mem, |
203 | struct device_node *dad, | 150 | unsigned long *p, |
204 | struct device_node ***allnextpp, | 151 | struct device_node *dad, |
205 | unsigned long fpsize) | 152 | struct device_node ***allnextpp, |
153 | unsigned long fpsize) | ||
206 | { | 154 | { |
207 | struct device_node *np; | 155 | struct device_node *np; |
208 | struct property *pp, **prev_pp = NULL; | 156 | struct property *pp, **prev_pp = NULL; |
@@ -283,6 +231,7 @@ unsigned long __init unflatten_dt_node(unsigned long mem, | |||
283 | } | 231 | } |
284 | kref_init(&np->kref); | 232 | kref_init(&np->kref); |
285 | } | 233 | } |
234 | /* process properties */ | ||
286 | while (1) { | 235 | while (1) { |
287 | u32 sz, noff; | 236 | u32 sz, noff; |
288 | char *pname; | 237 | char *pname; |
@@ -298,10 +247,10 @@ unsigned long __init unflatten_dt_node(unsigned long mem, | |||
298 | sz = be32_to_cpup((__be32 *)(*p)); | 247 | sz = be32_to_cpup((__be32 *)(*p)); |
299 | noff = be32_to_cpup((__be32 *)((*p) + 4)); | 248 | noff = be32_to_cpup((__be32 *)((*p) + 4)); |
300 | *p += 8; | 249 | *p += 8; |
301 | if (be32_to_cpu(initial_boot_params->version) < 0x10) | 250 | if (be32_to_cpu(blob->version) < 0x10) |
302 | *p = ALIGN(*p, sz >= 8 ? 8 : 4); | 251 | *p = ALIGN(*p, sz >= 8 ? 8 : 4); |
303 | 252 | ||
304 | pname = find_flat_dt_string(noff); | 253 | pname = of_fdt_get_string(blob, noff); |
305 | if (pname == NULL) { | 254 | if (pname == NULL) { |
306 | pr_info("Can't find property name in list !\n"); | 255 | pr_info("Can't find property name in list !\n"); |
307 | break; | 256 | break; |
@@ -380,7 +329,8 @@ unsigned long __init unflatten_dt_node(unsigned long mem, | |||
380 | if (tag == OF_DT_NOP) | 329 | if (tag == OF_DT_NOP) |
381 | *p += 4; | 330 | *p += 4; |
382 | else | 331 | else |
383 | mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); | 332 | mem = unflatten_dt_node(blob, mem, p, np, allnextpp, |
333 | fpsize); | ||
384 | tag = be32_to_cpup((__be32 *)(*p)); | 334 | tag = be32_to_cpup((__be32 *)(*p)); |
385 | } | 335 | } |
386 | if (tag != OF_DT_END_NODE) { | 336 | if (tag != OF_DT_END_NODE) { |
@@ -391,6 +341,211 @@ unsigned long __init unflatten_dt_node(unsigned long mem, | |||
391 | return mem; | 341 | return mem; |
392 | } | 342 | } |
393 | 343 | ||
344 | /** | ||
345 | * __unflatten_device_tree - create tree of device_nodes from flat blob | ||
346 | * | ||
347 | * unflattens a device-tree, creating the | ||
348 | * tree of struct device_node. It also fills the "name" and "type" | ||
349 | * pointers of the nodes so the normal device-tree walking functions | ||
350 | * can be used. | ||
351 | * @blob: The blob to expand | ||
352 | * @mynodes: The device_node tree created by the call | ||
353 | * @dt_alloc: An allocator that provides a virtual address to memory | ||
354 | * for the resulting tree | ||
355 | */ | ||
356 | static void __unflatten_device_tree(struct boot_param_header *blob, | ||
357 | struct device_node **mynodes, | ||
358 | void * (*dt_alloc)(u64 size, u64 align)) | ||
359 | { | ||
360 | unsigned long start, mem, size; | ||
361 | struct device_node **allnextp = mynodes; | ||
362 | |||
363 | pr_debug(" -> unflatten_device_tree()\n"); | ||
364 | |||
365 | if (!blob) { | ||
366 | pr_debug("No device tree pointer\n"); | ||
367 | return; | ||
368 | } | ||
369 | |||
370 | pr_debug("Unflattening device tree:\n"); | ||
371 | pr_debug("magic: %08x\n", be32_to_cpu(blob->magic)); | ||
372 | pr_debug("size: %08x\n", be32_to_cpu(blob->totalsize)); | ||
373 | pr_debug("version: %08x\n", be32_to_cpu(blob->version)); | ||
374 | |||
375 | if (be32_to_cpu(blob->magic) != OF_DT_HEADER) { | ||
376 | pr_err("Invalid device tree blob header\n"); | ||
377 | return; | ||
378 | } | ||
379 | |||
380 | /* First pass, scan for size */ | ||
381 | start = ((unsigned long)blob) + | ||
382 | be32_to_cpu(blob->off_dt_struct); | ||
383 | size = unflatten_dt_node(blob, 0, &start, NULL, NULL, 0); | ||
384 | size = (size | 3) + 1; | ||
385 | |||
386 | pr_debug(" size is %lx, allocating...\n", size); | ||
387 | |||
388 | /* Allocate memory for the expanded device tree */ | ||
389 | mem = (unsigned long) | ||
390 | dt_alloc(size + 4, __alignof__(struct device_node)); | ||
391 | |||
392 | ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef); | ||
393 | |||
394 | pr_debug(" unflattening %lx...\n", mem); | ||
395 | |||
396 | /* Second pass, do actual unflattening */ | ||
397 | start = ((unsigned long)blob) + | ||
398 | be32_to_cpu(blob->off_dt_struct); | ||
399 | unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0); | ||
400 | if (be32_to_cpup((__be32 *)start) != OF_DT_END) | ||
401 | pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start)); | ||
402 | if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef) | ||
403 | pr_warning("End of tree marker overwritten: %08x\n", | ||
404 | be32_to_cpu(((__be32 *)mem)[size / 4])); | ||
405 | *allnextp = NULL; | ||
406 | |||
407 | pr_debug(" <- unflatten_device_tree()\n"); | ||
408 | } | ||
409 | |||
410 | static void *kernel_tree_alloc(u64 size, u64 align) | ||
411 | { | ||
412 | return kzalloc(size, GFP_KERNEL); | ||
413 | } | ||
414 | |||
415 | /** | ||
416 | * of_fdt_unflatten_tree - create tree of device_nodes from flat blob | ||
417 | * | ||
418 | * unflattens the device-tree passed by the firmware, creating the | ||
419 | * tree of struct device_node. It also fills the "name" and "type" | ||
420 | * pointers of the nodes so the normal device-tree walking functions | ||
421 | * can be used. | ||
422 | */ | ||
423 | void of_fdt_unflatten_tree(unsigned long *blob, | ||
424 | struct device_node **mynodes) | ||
425 | { | ||
426 | struct boot_param_header *device_tree = | ||
427 | (struct boot_param_header *)blob; | ||
428 | __unflatten_device_tree(device_tree, mynodes, &kernel_tree_alloc); | ||
429 | } | ||
430 | EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); | ||
431 | |||
432 | /* Everything below here references initial_boot_params directly. */ | ||
433 | int __initdata dt_root_addr_cells; | ||
434 | int __initdata dt_root_size_cells; | ||
435 | |||
436 | struct boot_param_header *initial_boot_params; | ||
437 | |||
438 | #ifdef CONFIG_OF_EARLY_FLATTREE | ||
439 | |||
440 | /** | ||
441 | * of_scan_flat_dt - scan flattened tree blob and call callback on each. | ||
442 | * @it: callback function | ||
443 | * @data: context data pointer | ||
444 | * | ||
445 | * This function is used to scan the flattened device-tree, it is | ||
446 | * used to extract the memory information at boot before we can | ||
447 | * unflatten the tree | ||
448 | */ | ||
449 | int __init of_scan_flat_dt(int (*it)(unsigned long node, | ||
450 | const char *uname, int depth, | ||
451 | void *data), | ||
452 | void *data) | ||
453 | { | ||
454 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
455 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
456 | int rc = 0; | ||
457 | int depth = -1; | ||
458 | |||
459 | do { | ||
460 | u32 tag = be32_to_cpup((__be32 *)p); | ||
461 | char *pathp; | ||
462 | |||
463 | p += 4; | ||
464 | if (tag == OF_DT_END_NODE) { | ||
465 | depth--; | ||
466 | continue; | ||
467 | } | ||
468 | if (tag == OF_DT_NOP) | ||
469 | continue; | ||
470 | if (tag == OF_DT_END) | ||
471 | break; | ||
472 | if (tag == OF_DT_PROP) { | ||
473 | u32 sz = be32_to_cpup((__be32 *)p); | ||
474 | p += 8; | ||
475 | if (be32_to_cpu(initial_boot_params->version) < 0x10) | ||
476 | p = ALIGN(p, sz >= 8 ? 8 : 4); | ||
477 | p += sz; | ||
478 | p = ALIGN(p, 4); | ||
479 | continue; | ||
480 | } | ||
481 | if (tag != OF_DT_BEGIN_NODE) { | ||
482 | pr_err("Invalid tag %x in flat device tree!\n", tag); | ||
483 | return -EINVAL; | ||
484 | } | ||
485 | depth++; | ||
486 | pathp = (char *)p; | ||
487 | p = ALIGN(p + strlen(pathp) + 1, 4); | ||
488 | if ((*pathp) == '/') { | ||
489 | char *lp, *np; | ||
490 | for (lp = NULL, np = pathp; *np; np++) | ||
491 | if ((*np) == '/') | ||
492 | lp = np+1; | ||
493 | if (lp != NULL) | ||
494 | pathp = lp; | ||
495 | } | ||
496 | rc = it(p, pathp, depth, data); | ||
497 | if (rc != 0) | ||
498 | break; | ||
499 | } while (1); | ||
500 | |||
501 | return rc; | ||
502 | } | ||
503 | |||
504 | /** | ||
505 | * of_get_flat_dt_root - find the root node in the flat blob | ||
506 | */ | ||
507 | unsigned long __init of_get_flat_dt_root(void) | ||
508 | { | ||
509 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
510 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
511 | |||
512 | while (be32_to_cpup((__be32 *)p) == OF_DT_NOP) | ||
513 | p += 4; | ||
514 | BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE); | ||
515 | p += 4; | ||
516 | return ALIGN(p + strlen((char *)p) + 1, 4); | ||
517 | } | ||
518 | |||
519 | /** | ||
520 | * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr | ||
521 | * | ||
522 | * This function can be used within scan_flattened_dt callback to get | ||
523 | * access to properties | ||
524 | */ | ||
525 | void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | ||
526 | unsigned long *size) | ||
527 | { | ||
528 | return of_fdt_get_property(initial_boot_params, node, name, size); | ||
529 | } | ||
530 | |||
531 | /** | ||
532 | * of_flat_dt_is_compatible - Return true if given node has compat in compatible list | ||
533 | * @node: node to test | ||
534 | * @compat: compatible string to compare with compatible list. | ||
535 | */ | ||
536 | int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) | ||
537 | { | ||
538 | return of_fdt_is_compatible(initial_boot_params, node, compat); | ||
539 | } | ||
540 | |||
541 | /** | ||
542 | * of_flat_dt_match - Return true if node matches a list of compatible values | ||
543 | */ | ||
544 | int __init of_flat_dt_match(unsigned long node, const char **compat) | ||
545 | { | ||
546 | return of_fdt_match(initial_boot_params, node, compat); | ||
547 | } | ||
548 | |||
394 | #ifdef CONFIG_BLK_DEV_INITRD | 549 | #ifdef CONFIG_BLK_DEV_INITRD |
395 | /** | 550 | /** |
396 | * early_init_dt_check_for_initrd - Decode initrd location from flat tree | 551 | * early_init_dt_check_for_initrd - Decode initrd location from flat tree |
@@ -515,27 +670,25 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | |||
515 | 670 | ||
516 | pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); | 671 | pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); |
517 | 672 | ||
518 | if (depth != 1 || | 673 | if (depth != 1 || !data || |
519 | (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) | 674 | (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) |
520 | return 0; | 675 | return 0; |
521 | 676 | ||
522 | early_init_dt_check_for_initrd(node); | 677 | early_init_dt_check_for_initrd(node); |
523 | 678 | ||
524 | /* Retreive command line */ | 679 | /* Retrieve command line */ |
525 | p = of_get_flat_dt_prop(node, "bootargs", &l); | 680 | p = of_get_flat_dt_prop(node, "bootargs", &l); |
526 | if (p != NULL && l > 0) | 681 | if (p != NULL && l > 0) |
527 | strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); | 682 | strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); |
528 | 683 | ||
529 | #ifdef CONFIG_CMDLINE | 684 | #ifdef CONFIG_CMDLINE |
530 | #ifndef CONFIG_CMDLINE_FORCE | 685 | #ifndef CONFIG_CMDLINE_FORCE |
531 | if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) | 686 | if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) |
532 | #endif | 687 | #endif |
533 | strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); | 688 | strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); |
534 | #endif /* CONFIG_CMDLINE */ | 689 | #endif /* CONFIG_CMDLINE */ |
535 | 690 | ||
536 | early_init_dt_scan_chosen_arch(node); | 691 | pr_debug("Command line is: %s\n", (char*)data); |
537 | |||
538 | pr_debug("Command line is: %s\n", cmd_line); | ||
539 | 692 | ||
540 | /* break now */ | 693 | /* break now */ |
541 | return 1; | 694 | return 1; |
@@ -551,58 +704,13 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | |||
551 | */ | 704 | */ |
552 | void __init unflatten_device_tree(void) | 705 | void __init unflatten_device_tree(void) |
553 | { | 706 | { |
554 | unsigned long start, mem, size; | 707 | __unflatten_device_tree(initial_boot_params, &allnodes, |
555 | struct device_node **allnextp = &allnodes; | 708 | early_init_dt_alloc_memory_arch); |
556 | |||
557 | pr_debug(" -> unflatten_device_tree()\n"); | ||
558 | |||
559 | if (!initial_boot_params) { | ||
560 | pr_debug("No device tree pointer\n"); | ||
561 | return; | ||
562 | } | ||
563 | |||
564 | pr_debug("Unflattening device tree:\n"); | ||
565 | pr_debug("magic: %08x\n", be32_to_cpu(initial_boot_params->magic)); | ||
566 | pr_debug("size: %08x\n", be32_to_cpu(initial_boot_params->totalsize)); | ||
567 | pr_debug("version: %08x\n", be32_to_cpu(initial_boot_params->version)); | ||
568 | |||
569 | if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) { | ||
570 | pr_err("Invalid device tree blob header\n"); | ||
571 | return; | ||
572 | } | ||
573 | |||
574 | /* First pass, scan for size */ | ||
575 | start = ((unsigned long)initial_boot_params) + | ||
576 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
577 | size = unflatten_dt_node(0, &start, NULL, NULL, 0); | ||
578 | size = (size | 3) + 1; | ||
579 | |||
580 | pr_debug(" size is %lx, allocating...\n", size); | ||
581 | |||
582 | /* Allocate memory for the expanded device tree */ | ||
583 | mem = early_init_dt_alloc_memory_arch(size + 4, | ||
584 | __alignof__(struct device_node)); | ||
585 | mem = (unsigned long) __va(mem); | ||
586 | |||
587 | ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef); | ||
588 | |||
589 | pr_debug(" unflattening %lx...\n", mem); | ||
590 | |||
591 | /* Second pass, do actual unflattening */ | ||
592 | start = ((unsigned long)initial_boot_params) + | ||
593 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
594 | unflatten_dt_node(mem, &start, NULL, &allnextp, 0); | ||
595 | if (be32_to_cpup((__be32 *)start) != OF_DT_END) | ||
596 | pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start)); | ||
597 | if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef) | ||
598 | pr_warning("End of tree marker overwritten: %08x\n", | ||
599 | be32_to_cpu(((__be32 *)mem)[size / 4])); | ||
600 | *allnextp = NULL; | ||
601 | 709 | ||
602 | /* Get pointer to OF "/chosen" node for use everywhere */ | 710 | /* Get pointer to OF "/chosen" node for use everywhere */ |
603 | of_chosen = of_find_node_by_path("/chosen"); | 711 | of_chosen = of_find_node_by_path("/chosen"); |
604 | if (of_chosen == NULL) | 712 | if (of_chosen == NULL) |
605 | of_chosen = of_find_node_by_path("/chosen@0"); | 713 | of_chosen = of_find_node_by_path("/chosen@0"); |
606 | |||
607 | pr_debug(" <- unflatten_device_tree()\n"); | ||
608 | } | 714 | } |
715 | |||
716 | #endif /* CONFIG_OF_EARLY_FLATTREE */ | ||