diff options
Diffstat (limited to 'drivers/of/fdt.c')
-rw-r--r-- | drivers/of/fdt.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 9faa9a5cbdf0..dd9057cb7aa7 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -19,3 +19,67 @@ char *find_flat_dt_string(u32 offset) | |||
19 | return ((char *)initial_boot_params) + | 19 | return ((char *)initial_boot_params) + |
20 | initial_boot_params->off_dt_strings + offset; | 20 | initial_boot_params->off_dt_strings + offset; |
21 | } | 21 | } |
22 | |||
23 | /** | ||
24 | * of_scan_flat_dt - scan flattened tree blob and call callback on each. | ||
25 | * @it: callback function | ||
26 | * @data: context data pointer | ||
27 | * | ||
28 | * This function is used to scan the flattened device-tree, it is | ||
29 | * used to extract the memory information at boot before we can | ||
30 | * unflatten the tree | ||
31 | */ | ||
32 | int __init of_scan_flat_dt(int (*it)(unsigned long node, | ||
33 | const char *uname, int depth, | ||
34 | void *data), | ||
35 | void *data) | ||
36 | { | ||
37 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
38 | initial_boot_params->off_dt_struct; | ||
39 | int rc = 0; | ||
40 | int depth = -1; | ||
41 | |||
42 | do { | ||
43 | u32 tag = *((u32 *)p); | ||
44 | char *pathp; | ||
45 | |||
46 | p += 4; | ||
47 | if (tag == OF_DT_END_NODE) { | ||
48 | depth--; | ||
49 | continue; | ||
50 | } | ||
51 | if (tag == OF_DT_NOP) | ||
52 | continue; | ||
53 | if (tag == OF_DT_END) | ||
54 | break; | ||
55 | if (tag == OF_DT_PROP) { | ||
56 | u32 sz = *((u32 *)p); | ||
57 | p += 8; | ||
58 | if (initial_boot_params->version < 0x10) | ||
59 | p = _ALIGN(p, sz >= 8 ? 8 : 4); | ||
60 | p += sz; | ||
61 | p = _ALIGN(p, 4); | ||
62 | continue; | ||
63 | } | ||
64 | if (tag != OF_DT_BEGIN_NODE) { | ||
65 | pr_err("Invalid tag %x in flat device tree!\n", tag); | ||
66 | return -EINVAL; | ||
67 | } | ||
68 | depth++; | ||
69 | pathp = (char *)p; | ||
70 | p = _ALIGN(p + strlen(pathp) + 1, 4); | ||
71 | if ((*pathp) == '/') { | ||
72 | char *lp, *np; | ||
73 | for (lp = NULL, np = pathp; *np; np++) | ||
74 | if ((*np) == '/') | ||
75 | lp = np+1; | ||
76 | if (lp != NULL) | ||
77 | pathp = lp; | ||
78 | } | ||
79 | rc = it(p, pathp, depth, data); | ||
80 | if (rc != 0) | ||
81 | break; | ||
82 | } while (1); | ||
83 | |||
84 | return rc; | ||
85 | } | ||