Commit 05f477fa301b1c8e1b48d9411c5836c314fe59ac
Committed by
guoyin.chen
1 parent
f2d295e18b
Exists in
smarc-imx_v2015.04_4.1.15_1.0.0_ga
and in
1 other branch
MLK-12483-1 common: Fix fdt command systemsetup issue
The fdt command "fdt systemsetup" can't work because the do_fdt check the start char 's' for command "fdt set". So the fdt systemsetup will also go into the "fdt set" in fault. Fix this problem by checking the whole word "set" for "fdt set" command. Signed-off-by: Ye Li <ye.li@nxp.com> (cherry picked from commit 771dab97f93e1ab07a5f2f29f1622528b9477969)
Showing 1 changed file with 1 additions and 1 deletions Inline Diff
common/cmd_fdt.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2007 | 2 | * (C) Copyright 2007 |
3 | * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com | 3 | * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com |
4 | * Based on code written by: | 4 | * Based on code written by: |
5 | * Pantelis Antoniou <pantelis.antoniou@gmail.com> and | 5 | * Pantelis Antoniou <pantelis.antoniou@gmail.com> and |
6 | * Matthew McClintock <msm@freescale.com> | 6 | * Matthew McClintock <msm@freescale.com> |
7 | * | 7 | * |
8 | * SPDX-License-Identifier: GPL-2.0+ | 8 | * SPDX-License-Identifier: GPL-2.0+ |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <common.h> | 11 | #include <common.h> |
12 | #include <command.h> | 12 | #include <command.h> |
13 | #include <linux/ctype.h> | 13 | #include <linux/ctype.h> |
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <asm/global_data.h> | 15 | #include <asm/global_data.h> |
16 | #include <libfdt.h> | 16 | #include <libfdt.h> |
17 | #include <fdt_support.h> | 17 | #include <fdt_support.h> |
18 | #include <asm/io.h> | 18 | #include <asm/io.h> |
19 | 19 | ||
20 | #define MAX_LEVEL 32 /* how deeply nested we will go */ | 20 | #define MAX_LEVEL 32 /* how deeply nested we will go */ |
21 | #define SCRATCHPAD 1024 /* bytes of scratchpad memory */ | 21 | #define SCRATCHPAD 1024 /* bytes of scratchpad memory */ |
22 | #ifndef CONFIG_CMD_FDT_MAX_DUMP | 22 | #ifndef CONFIG_CMD_FDT_MAX_DUMP |
23 | #define CONFIG_CMD_FDT_MAX_DUMP 64 | 23 | #define CONFIG_CMD_FDT_MAX_DUMP 64 |
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | /* | 26 | /* |
27 | * Global data (for the gd->bd) | 27 | * Global data (for the gd->bd) |
28 | */ | 28 | */ |
29 | DECLARE_GLOBAL_DATA_PTR; | 29 | DECLARE_GLOBAL_DATA_PTR; |
30 | 30 | ||
31 | static int fdt_valid(struct fdt_header **blobp); | 31 | static int fdt_valid(struct fdt_header **blobp); |
32 | static int fdt_parse_prop(char *const*newval, int count, char *data, int *len); | 32 | static int fdt_parse_prop(char *const*newval, int count, char *data, int *len); |
33 | static int fdt_print(const char *pathp, char *prop, int depth); | 33 | static int fdt_print(const char *pathp, char *prop, int depth); |
34 | static int is_printable_string(const void *data, int len); | 34 | static int is_printable_string(const void *data, int len); |
35 | 35 | ||
36 | /* | 36 | /* |
37 | * The working_fdt points to our working flattened device tree. | 37 | * The working_fdt points to our working flattened device tree. |
38 | */ | 38 | */ |
39 | struct fdt_header *working_fdt; | 39 | struct fdt_header *working_fdt; |
40 | 40 | ||
41 | void set_working_fdt_addr(ulong addr) | 41 | void set_working_fdt_addr(ulong addr) |
42 | { | 42 | { |
43 | void *buf; | 43 | void *buf; |
44 | 44 | ||
45 | buf = map_sysmem(addr, 0); | 45 | buf = map_sysmem(addr, 0); |
46 | working_fdt = buf; | 46 | working_fdt = buf; |
47 | setenv_ulong("fdtaddr", addr); | 47 | setenv_ulong("fdtaddr", addr); |
48 | } | 48 | } |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * Get a value from the fdt and format it to be set in the environment | 51 | * Get a value from the fdt and format it to be set in the environment |
52 | */ | 52 | */ |
53 | static int fdt_value_setenv(const void *nodep, int len, const char *var) | 53 | static int fdt_value_setenv(const void *nodep, int len, const char *var) |
54 | { | 54 | { |
55 | if (is_printable_string(nodep, len)) | 55 | if (is_printable_string(nodep, len)) |
56 | setenv(var, (void *)nodep); | 56 | setenv(var, (void *)nodep); |
57 | else if (len == 4) { | 57 | else if (len == 4) { |
58 | char buf[11]; | 58 | char buf[11]; |
59 | 59 | ||
60 | sprintf(buf, "0x%08X", *(uint32_t *)nodep); | 60 | sprintf(buf, "0x%08X", *(uint32_t *)nodep); |
61 | setenv(var, buf); | 61 | setenv(var, buf); |
62 | } else if (len%4 == 0 && len <= 20) { | 62 | } else if (len%4 == 0 && len <= 20) { |
63 | /* Needed to print things like sha1 hashes. */ | 63 | /* Needed to print things like sha1 hashes. */ |
64 | char buf[41]; | 64 | char buf[41]; |
65 | int i; | 65 | int i; |
66 | 66 | ||
67 | for (i = 0; i < len; i += sizeof(unsigned int)) | 67 | for (i = 0; i < len; i += sizeof(unsigned int)) |
68 | sprintf(buf + (i * 2), "%08x", | 68 | sprintf(buf + (i * 2), "%08x", |
69 | *(unsigned int *)(nodep + i)); | 69 | *(unsigned int *)(nodep + i)); |
70 | setenv(var, buf); | 70 | setenv(var, buf); |
71 | } else { | 71 | } else { |
72 | printf("error: unprintable value\n"); | 72 | printf("error: unprintable value\n"); |
73 | return 1; | 73 | return 1; |
74 | } | 74 | } |
75 | return 0; | 75 | return 0; |
76 | } | 76 | } |
77 | 77 | ||
78 | /* | 78 | /* |
79 | * Flattened Device Tree command, see the help for parameter definitions. | 79 | * Flattened Device Tree command, see the help for parameter definitions. |
80 | */ | 80 | */ |
81 | static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | 81 | static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
82 | { | 82 | { |
83 | if (argc < 2) | 83 | if (argc < 2) |
84 | return CMD_RET_USAGE; | 84 | return CMD_RET_USAGE; |
85 | 85 | ||
86 | /* | 86 | /* |
87 | * Set the address of the fdt | 87 | * Set the address of the fdt |
88 | */ | 88 | */ |
89 | if (argv[1][0] == 'a') { | 89 | if (argv[1][0] == 'a') { |
90 | unsigned long addr; | 90 | unsigned long addr; |
91 | int control = 0; | 91 | int control = 0; |
92 | struct fdt_header *blob; | 92 | struct fdt_header *blob; |
93 | /* | 93 | /* |
94 | * Set the address [and length] of the fdt. | 94 | * Set the address [and length] of the fdt. |
95 | */ | 95 | */ |
96 | argc -= 2; | 96 | argc -= 2; |
97 | argv += 2; | 97 | argv += 2; |
98 | /* Temporary #ifdef - some archs don't have fdt_blob yet */ | 98 | /* Temporary #ifdef - some archs don't have fdt_blob yet */ |
99 | #ifdef CONFIG_OF_CONTROL | 99 | #ifdef CONFIG_OF_CONTROL |
100 | if (argc && !strcmp(*argv, "-c")) { | 100 | if (argc && !strcmp(*argv, "-c")) { |
101 | control = 1; | 101 | control = 1; |
102 | argc--; | 102 | argc--; |
103 | argv++; | 103 | argv++; |
104 | } | 104 | } |
105 | #endif | 105 | #endif |
106 | if (argc == 0) { | 106 | if (argc == 0) { |
107 | if (control) | 107 | if (control) |
108 | blob = (struct fdt_header *)gd->fdt_blob; | 108 | blob = (struct fdt_header *)gd->fdt_blob; |
109 | else | 109 | else |
110 | blob = working_fdt; | 110 | blob = working_fdt; |
111 | if (!blob || !fdt_valid(&blob)) | 111 | if (!blob || !fdt_valid(&blob)) |
112 | return 1; | 112 | return 1; |
113 | printf("The address of the fdt is %#08lx\n", | 113 | printf("The address of the fdt is %#08lx\n", |
114 | control ? (ulong)map_to_sysmem(blob) : | 114 | control ? (ulong)map_to_sysmem(blob) : |
115 | getenv_hex("fdtaddr", 0)); | 115 | getenv_hex("fdtaddr", 0)); |
116 | return 0; | 116 | return 0; |
117 | } | 117 | } |
118 | 118 | ||
119 | addr = simple_strtoul(argv[0], NULL, 16); | 119 | addr = simple_strtoul(argv[0], NULL, 16); |
120 | blob = map_sysmem(addr, 0); | 120 | blob = map_sysmem(addr, 0); |
121 | if (!fdt_valid(&blob)) | 121 | if (!fdt_valid(&blob)) |
122 | return 1; | 122 | return 1; |
123 | if (control) | 123 | if (control) |
124 | gd->fdt_blob = blob; | 124 | gd->fdt_blob = blob; |
125 | else | 125 | else |
126 | set_working_fdt_addr(addr); | 126 | set_working_fdt_addr(addr); |
127 | 127 | ||
128 | if (argc >= 2) { | 128 | if (argc >= 2) { |
129 | int len; | 129 | int len; |
130 | int err; | 130 | int err; |
131 | /* | 131 | /* |
132 | * Optional new length | 132 | * Optional new length |
133 | */ | 133 | */ |
134 | len = simple_strtoul(argv[1], NULL, 16); | 134 | len = simple_strtoul(argv[1], NULL, 16); |
135 | if (len < fdt_totalsize(blob)) { | 135 | if (len < fdt_totalsize(blob)) { |
136 | printf ("New length %d < existing length %d, " | 136 | printf ("New length %d < existing length %d, " |
137 | "ignoring.\n", | 137 | "ignoring.\n", |
138 | len, fdt_totalsize(blob)); | 138 | len, fdt_totalsize(blob)); |
139 | } else { | 139 | } else { |
140 | /* | 140 | /* |
141 | * Open in place with a new length. | 141 | * Open in place with a new length. |
142 | */ | 142 | */ |
143 | err = fdt_open_into(blob, blob, len); | 143 | err = fdt_open_into(blob, blob, len); |
144 | if (err != 0) { | 144 | if (err != 0) { |
145 | printf ("libfdt fdt_open_into(): %s\n", | 145 | printf ("libfdt fdt_open_into(): %s\n", |
146 | fdt_strerror(err)); | 146 | fdt_strerror(err)); |
147 | } | 147 | } |
148 | } | 148 | } |
149 | } | 149 | } |
150 | 150 | ||
151 | return CMD_RET_SUCCESS; | 151 | return CMD_RET_SUCCESS; |
152 | } | 152 | } |
153 | 153 | ||
154 | if (!working_fdt) { | 154 | if (!working_fdt) { |
155 | puts( | 155 | puts( |
156 | "No FDT memory address configured. Please configure\n" | 156 | "No FDT memory address configured. Please configure\n" |
157 | "the FDT address via \"fdt addr <address>\" command.\n" | 157 | "the FDT address via \"fdt addr <address>\" command.\n" |
158 | "Aborting!\n"); | 158 | "Aborting!\n"); |
159 | return CMD_RET_FAILURE; | 159 | return CMD_RET_FAILURE; |
160 | } | 160 | } |
161 | 161 | ||
162 | /* | 162 | /* |
163 | * Move the working_fdt | 163 | * Move the working_fdt |
164 | */ | 164 | */ |
165 | if (strncmp(argv[1], "mo", 2) == 0) { | 165 | if (strncmp(argv[1], "mo", 2) == 0) { |
166 | struct fdt_header *newaddr; | 166 | struct fdt_header *newaddr; |
167 | int len; | 167 | int len; |
168 | int err; | 168 | int err; |
169 | 169 | ||
170 | if (argc < 4) | 170 | if (argc < 4) |
171 | return CMD_RET_USAGE; | 171 | return CMD_RET_USAGE; |
172 | 172 | ||
173 | /* | 173 | /* |
174 | * Set the address and length of the fdt. | 174 | * Set the address and length of the fdt. |
175 | */ | 175 | */ |
176 | working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); | 176 | working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); |
177 | if (!fdt_valid(&working_fdt)) | 177 | if (!fdt_valid(&working_fdt)) |
178 | return 1; | 178 | return 1; |
179 | 179 | ||
180 | newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16); | 180 | newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16); |
181 | 181 | ||
182 | /* | 182 | /* |
183 | * If the user specifies a length, use that. Otherwise use the | 183 | * If the user specifies a length, use that. Otherwise use the |
184 | * current length. | 184 | * current length. |
185 | */ | 185 | */ |
186 | if (argc <= 4) { | 186 | if (argc <= 4) { |
187 | len = fdt_totalsize(working_fdt); | 187 | len = fdt_totalsize(working_fdt); |
188 | } else { | 188 | } else { |
189 | len = simple_strtoul(argv[4], NULL, 16); | 189 | len = simple_strtoul(argv[4], NULL, 16); |
190 | if (len < fdt_totalsize(working_fdt)) { | 190 | if (len < fdt_totalsize(working_fdt)) { |
191 | printf ("New length 0x%X < existing length " | 191 | printf ("New length 0x%X < existing length " |
192 | "0x%X, aborting.\n", | 192 | "0x%X, aborting.\n", |
193 | len, fdt_totalsize(working_fdt)); | 193 | len, fdt_totalsize(working_fdt)); |
194 | return 1; | 194 | return 1; |
195 | } | 195 | } |
196 | } | 196 | } |
197 | 197 | ||
198 | /* | 198 | /* |
199 | * Copy to the new location. | 199 | * Copy to the new location. |
200 | */ | 200 | */ |
201 | err = fdt_open_into(working_fdt, newaddr, len); | 201 | err = fdt_open_into(working_fdt, newaddr, len); |
202 | if (err != 0) { | 202 | if (err != 0) { |
203 | printf ("libfdt fdt_open_into(): %s\n", | 203 | printf ("libfdt fdt_open_into(): %s\n", |
204 | fdt_strerror(err)); | 204 | fdt_strerror(err)); |
205 | return 1; | 205 | return 1; |
206 | } | 206 | } |
207 | working_fdt = newaddr; | 207 | working_fdt = newaddr; |
208 | 208 | ||
209 | /* | 209 | /* |
210 | * Make a new node | 210 | * Make a new node |
211 | */ | 211 | */ |
212 | } else if (strncmp(argv[1], "mk", 2) == 0) { | 212 | } else if (strncmp(argv[1], "mk", 2) == 0) { |
213 | char *pathp; /* path */ | 213 | char *pathp; /* path */ |
214 | char *nodep; /* new node to add */ | 214 | char *nodep; /* new node to add */ |
215 | int nodeoffset; /* node offset from libfdt */ | 215 | int nodeoffset; /* node offset from libfdt */ |
216 | int err; | 216 | int err; |
217 | 217 | ||
218 | /* | 218 | /* |
219 | * Parameters: Node path, new node to be appended to the path. | 219 | * Parameters: Node path, new node to be appended to the path. |
220 | */ | 220 | */ |
221 | if (argc < 4) | 221 | if (argc < 4) |
222 | return CMD_RET_USAGE; | 222 | return CMD_RET_USAGE; |
223 | 223 | ||
224 | pathp = argv[2]; | 224 | pathp = argv[2]; |
225 | nodep = argv[3]; | 225 | nodep = argv[3]; |
226 | 226 | ||
227 | nodeoffset = fdt_path_offset (working_fdt, pathp); | 227 | nodeoffset = fdt_path_offset (working_fdt, pathp); |
228 | if (nodeoffset < 0) { | 228 | if (nodeoffset < 0) { |
229 | /* | 229 | /* |
230 | * Not found or something else bad happened. | 230 | * Not found or something else bad happened. |
231 | */ | 231 | */ |
232 | printf ("libfdt fdt_path_offset() returned %s\n", | 232 | printf ("libfdt fdt_path_offset() returned %s\n", |
233 | fdt_strerror(nodeoffset)); | 233 | fdt_strerror(nodeoffset)); |
234 | return 1; | 234 | return 1; |
235 | } | 235 | } |
236 | err = fdt_add_subnode(working_fdt, nodeoffset, nodep); | 236 | err = fdt_add_subnode(working_fdt, nodeoffset, nodep); |
237 | if (err < 0) { | 237 | if (err < 0) { |
238 | printf ("libfdt fdt_add_subnode(): %s\n", | 238 | printf ("libfdt fdt_add_subnode(): %s\n", |
239 | fdt_strerror(err)); | 239 | fdt_strerror(err)); |
240 | return 1; | 240 | return 1; |
241 | } | 241 | } |
242 | 242 | ||
243 | /* | 243 | /* |
244 | * Set the value of a property in the working_fdt. | 244 | * Set the value of a property in the working_fdt. |
245 | */ | 245 | */ |
246 | } else if (argv[1][0] == 's') { | 246 | } else if (strncmp(argv[1], "set", 3) == 0) { |
247 | char *pathp; /* path */ | 247 | char *pathp; /* path */ |
248 | char *prop; /* property */ | 248 | char *prop; /* property */ |
249 | int nodeoffset; /* node offset from libfdt */ | 249 | int nodeoffset; /* node offset from libfdt */ |
250 | static char data[SCRATCHPAD]; /* storage for the property */ | 250 | static char data[SCRATCHPAD]; /* storage for the property */ |
251 | int len; /* new length of the property */ | 251 | int len; /* new length of the property */ |
252 | int ret; /* return value */ | 252 | int ret; /* return value */ |
253 | 253 | ||
254 | /* | 254 | /* |
255 | * Parameters: Node path, property, optional value. | 255 | * Parameters: Node path, property, optional value. |
256 | */ | 256 | */ |
257 | if (argc < 4) | 257 | if (argc < 4) |
258 | return CMD_RET_USAGE; | 258 | return CMD_RET_USAGE; |
259 | 259 | ||
260 | pathp = argv[2]; | 260 | pathp = argv[2]; |
261 | prop = argv[3]; | 261 | prop = argv[3]; |
262 | if (argc == 4) { | 262 | if (argc == 4) { |
263 | len = 0; | 263 | len = 0; |
264 | } else { | 264 | } else { |
265 | ret = fdt_parse_prop(&argv[4], argc - 4, data, &len); | 265 | ret = fdt_parse_prop(&argv[4], argc - 4, data, &len); |
266 | if (ret != 0) | 266 | if (ret != 0) |
267 | return ret; | 267 | return ret; |
268 | } | 268 | } |
269 | 269 | ||
270 | nodeoffset = fdt_path_offset (working_fdt, pathp); | 270 | nodeoffset = fdt_path_offset (working_fdt, pathp); |
271 | if (nodeoffset < 0) { | 271 | if (nodeoffset < 0) { |
272 | /* | 272 | /* |
273 | * Not found or something else bad happened. | 273 | * Not found or something else bad happened. |
274 | */ | 274 | */ |
275 | printf ("libfdt fdt_path_offset() returned %s\n", | 275 | printf ("libfdt fdt_path_offset() returned %s\n", |
276 | fdt_strerror(nodeoffset)); | 276 | fdt_strerror(nodeoffset)); |
277 | return 1; | 277 | return 1; |
278 | } | 278 | } |
279 | 279 | ||
280 | ret = fdt_setprop(working_fdt, nodeoffset, prop, data, len); | 280 | ret = fdt_setprop(working_fdt, nodeoffset, prop, data, len); |
281 | if (ret < 0) { | 281 | if (ret < 0) { |
282 | printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret)); | 282 | printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret)); |
283 | return 1; | 283 | return 1; |
284 | } | 284 | } |
285 | 285 | ||
286 | /******************************************************************** | 286 | /******************************************************************** |
287 | * Get the value of a property in the working_fdt. | 287 | * Get the value of a property in the working_fdt. |
288 | ********************************************************************/ | 288 | ********************************************************************/ |
289 | } else if (argv[1][0] == 'g') { | 289 | } else if (argv[1][0] == 'g') { |
290 | char *subcmd; /* sub-command */ | 290 | char *subcmd; /* sub-command */ |
291 | char *pathp; /* path */ | 291 | char *pathp; /* path */ |
292 | char *prop; /* property */ | 292 | char *prop; /* property */ |
293 | char *var; /* variable to store result */ | 293 | char *var; /* variable to store result */ |
294 | int nodeoffset; /* node offset from libfdt */ | 294 | int nodeoffset; /* node offset from libfdt */ |
295 | const void *nodep; /* property node pointer */ | 295 | const void *nodep; /* property node pointer */ |
296 | int len = 0; /* new length of the property */ | 296 | int len = 0; /* new length of the property */ |
297 | 297 | ||
298 | /* | 298 | /* |
299 | * Parameters: Node path, property, optional value. | 299 | * Parameters: Node path, property, optional value. |
300 | */ | 300 | */ |
301 | if (argc < 5) | 301 | if (argc < 5) |
302 | return CMD_RET_USAGE; | 302 | return CMD_RET_USAGE; |
303 | 303 | ||
304 | subcmd = argv[2]; | 304 | subcmd = argv[2]; |
305 | 305 | ||
306 | if (argc < 6 && subcmd[0] != 's') | 306 | if (argc < 6 && subcmd[0] != 's') |
307 | return CMD_RET_USAGE; | 307 | return CMD_RET_USAGE; |
308 | 308 | ||
309 | var = argv[3]; | 309 | var = argv[3]; |
310 | pathp = argv[4]; | 310 | pathp = argv[4]; |
311 | prop = argv[5]; | 311 | prop = argv[5]; |
312 | 312 | ||
313 | nodeoffset = fdt_path_offset(working_fdt, pathp); | 313 | nodeoffset = fdt_path_offset(working_fdt, pathp); |
314 | if (nodeoffset < 0) { | 314 | if (nodeoffset < 0) { |
315 | /* | 315 | /* |
316 | * Not found or something else bad happened. | 316 | * Not found or something else bad happened. |
317 | */ | 317 | */ |
318 | printf("libfdt fdt_path_offset() returned %s\n", | 318 | printf("libfdt fdt_path_offset() returned %s\n", |
319 | fdt_strerror(nodeoffset)); | 319 | fdt_strerror(nodeoffset)); |
320 | return 1; | 320 | return 1; |
321 | } | 321 | } |
322 | 322 | ||
323 | if (subcmd[0] == 'n' || (subcmd[0] == 's' && argc == 5)) { | 323 | if (subcmd[0] == 'n' || (subcmd[0] == 's' && argc == 5)) { |
324 | int reqIndex = -1; | 324 | int reqIndex = -1; |
325 | int startDepth = fdt_node_depth( | 325 | int startDepth = fdt_node_depth( |
326 | working_fdt, nodeoffset); | 326 | working_fdt, nodeoffset); |
327 | int curDepth = startDepth; | 327 | int curDepth = startDepth; |
328 | int curIndex = -1; | 328 | int curIndex = -1; |
329 | int nextNodeOffset = fdt_next_node( | 329 | int nextNodeOffset = fdt_next_node( |
330 | working_fdt, nodeoffset, &curDepth); | 330 | working_fdt, nodeoffset, &curDepth); |
331 | 331 | ||
332 | if (subcmd[0] == 'n') | 332 | if (subcmd[0] == 'n') |
333 | reqIndex = simple_strtoul(argv[5], NULL, 16); | 333 | reqIndex = simple_strtoul(argv[5], NULL, 16); |
334 | 334 | ||
335 | while (curDepth > startDepth) { | 335 | while (curDepth > startDepth) { |
336 | if (curDepth == startDepth + 1) | 336 | if (curDepth == startDepth + 1) |
337 | curIndex++; | 337 | curIndex++; |
338 | if (subcmd[0] == 'n' && curIndex == reqIndex) { | 338 | if (subcmd[0] == 'n' && curIndex == reqIndex) { |
339 | const char *nodeName = fdt_get_name( | 339 | const char *nodeName = fdt_get_name( |
340 | working_fdt, nextNodeOffset, NULL); | 340 | working_fdt, nextNodeOffset, NULL); |
341 | 341 | ||
342 | setenv(var, (char *)nodeName); | 342 | setenv(var, (char *)nodeName); |
343 | return 0; | 343 | return 0; |
344 | } | 344 | } |
345 | nextNodeOffset = fdt_next_node( | 345 | nextNodeOffset = fdt_next_node( |
346 | working_fdt, nextNodeOffset, &curDepth); | 346 | working_fdt, nextNodeOffset, &curDepth); |
347 | if (nextNodeOffset < 0) | 347 | if (nextNodeOffset < 0) |
348 | break; | 348 | break; |
349 | } | 349 | } |
350 | if (subcmd[0] == 's') { | 350 | if (subcmd[0] == 's') { |
351 | /* get the num nodes at this level */ | 351 | /* get the num nodes at this level */ |
352 | setenv_ulong(var, curIndex + 1); | 352 | setenv_ulong(var, curIndex + 1); |
353 | } else { | 353 | } else { |
354 | /* node index not found */ | 354 | /* node index not found */ |
355 | printf("libfdt node not found\n"); | 355 | printf("libfdt node not found\n"); |
356 | return 1; | 356 | return 1; |
357 | } | 357 | } |
358 | } else { | 358 | } else { |
359 | nodep = fdt_getprop( | 359 | nodep = fdt_getprop( |
360 | working_fdt, nodeoffset, prop, &len); | 360 | working_fdt, nodeoffset, prop, &len); |
361 | if (len == 0) { | 361 | if (len == 0) { |
362 | /* no property value */ | 362 | /* no property value */ |
363 | setenv(var, ""); | 363 | setenv(var, ""); |
364 | return 0; | 364 | return 0; |
365 | } else if (len > 0) { | 365 | } else if (len > 0) { |
366 | if (subcmd[0] == 'v') { | 366 | if (subcmd[0] == 'v') { |
367 | int ret; | 367 | int ret; |
368 | 368 | ||
369 | ret = fdt_value_setenv(nodep, len, var); | 369 | ret = fdt_value_setenv(nodep, len, var); |
370 | if (ret != 0) | 370 | if (ret != 0) |
371 | return ret; | 371 | return ret; |
372 | } else if (subcmd[0] == 'a') { | 372 | } else if (subcmd[0] == 'a') { |
373 | /* Get address */ | 373 | /* Get address */ |
374 | char buf[11]; | 374 | char buf[11]; |
375 | 375 | ||
376 | sprintf(buf, "0x%p", nodep); | 376 | sprintf(buf, "0x%p", nodep); |
377 | setenv(var, buf); | 377 | setenv(var, buf); |
378 | } else if (subcmd[0] == 's') { | 378 | } else if (subcmd[0] == 's') { |
379 | /* Get size */ | 379 | /* Get size */ |
380 | char buf[11]; | 380 | char buf[11]; |
381 | 381 | ||
382 | sprintf(buf, "0x%08X", len); | 382 | sprintf(buf, "0x%08X", len); |
383 | setenv(var, buf); | 383 | setenv(var, buf); |
384 | } else | 384 | } else |
385 | return CMD_RET_USAGE; | 385 | return CMD_RET_USAGE; |
386 | return 0; | 386 | return 0; |
387 | } else { | 387 | } else { |
388 | printf("libfdt fdt_getprop(): %s\n", | 388 | printf("libfdt fdt_getprop(): %s\n", |
389 | fdt_strerror(len)); | 389 | fdt_strerror(len)); |
390 | return 1; | 390 | return 1; |
391 | } | 391 | } |
392 | } | 392 | } |
393 | 393 | ||
394 | /* | 394 | /* |
395 | * Print (recursive) / List (single level) | 395 | * Print (recursive) / List (single level) |
396 | */ | 396 | */ |
397 | } else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) { | 397 | } else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) { |
398 | int depth = MAX_LEVEL; /* how deep to print */ | 398 | int depth = MAX_LEVEL; /* how deep to print */ |
399 | char *pathp; /* path */ | 399 | char *pathp; /* path */ |
400 | char *prop; /* property */ | 400 | char *prop; /* property */ |
401 | int ret; /* return value */ | 401 | int ret; /* return value */ |
402 | static char root[2] = "/"; | 402 | static char root[2] = "/"; |
403 | 403 | ||
404 | /* | 404 | /* |
405 | * list is an alias for print, but limited to 1 level | 405 | * list is an alias for print, but limited to 1 level |
406 | */ | 406 | */ |
407 | if (argv[1][0] == 'l') { | 407 | if (argv[1][0] == 'l') { |
408 | depth = 1; | 408 | depth = 1; |
409 | } | 409 | } |
410 | 410 | ||
411 | /* | 411 | /* |
412 | * Get the starting path. The root node is an oddball, | 412 | * Get the starting path. The root node is an oddball, |
413 | * the offset is zero and has no name. | 413 | * the offset is zero and has no name. |
414 | */ | 414 | */ |
415 | if (argc == 2) | 415 | if (argc == 2) |
416 | pathp = root; | 416 | pathp = root; |
417 | else | 417 | else |
418 | pathp = argv[2]; | 418 | pathp = argv[2]; |
419 | if (argc > 3) | 419 | if (argc > 3) |
420 | prop = argv[3]; | 420 | prop = argv[3]; |
421 | else | 421 | else |
422 | prop = NULL; | 422 | prop = NULL; |
423 | 423 | ||
424 | ret = fdt_print(pathp, prop, depth); | 424 | ret = fdt_print(pathp, prop, depth); |
425 | if (ret != 0) | 425 | if (ret != 0) |
426 | return ret; | 426 | return ret; |
427 | 427 | ||
428 | /* | 428 | /* |
429 | * Remove a property/node | 429 | * Remove a property/node |
430 | */ | 430 | */ |
431 | } else if (strncmp(argv[1], "rm", 2) == 0) { | 431 | } else if (strncmp(argv[1], "rm", 2) == 0) { |
432 | int nodeoffset; /* node offset from libfdt */ | 432 | int nodeoffset; /* node offset from libfdt */ |
433 | int err; | 433 | int err; |
434 | 434 | ||
435 | /* | 435 | /* |
436 | * Get the path. The root node is an oddball, the offset | 436 | * Get the path. The root node is an oddball, the offset |
437 | * is zero and has no name. | 437 | * is zero and has no name. |
438 | */ | 438 | */ |
439 | nodeoffset = fdt_path_offset (working_fdt, argv[2]); | 439 | nodeoffset = fdt_path_offset (working_fdt, argv[2]); |
440 | if (nodeoffset < 0) { | 440 | if (nodeoffset < 0) { |
441 | /* | 441 | /* |
442 | * Not found or something else bad happened. | 442 | * Not found or something else bad happened. |
443 | */ | 443 | */ |
444 | printf ("libfdt fdt_path_offset() returned %s\n", | 444 | printf ("libfdt fdt_path_offset() returned %s\n", |
445 | fdt_strerror(nodeoffset)); | 445 | fdt_strerror(nodeoffset)); |
446 | return 1; | 446 | return 1; |
447 | } | 447 | } |
448 | /* | 448 | /* |
449 | * Do the delete. A fourth parameter means delete a property, | 449 | * Do the delete. A fourth parameter means delete a property, |
450 | * otherwise delete the node. | 450 | * otherwise delete the node. |
451 | */ | 451 | */ |
452 | if (argc > 3) { | 452 | if (argc > 3) { |
453 | err = fdt_delprop(working_fdt, nodeoffset, argv[3]); | 453 | err = fdt_delprop(working_fdt, nodeoffset, argv[3]); |
454 | if (err < 0) { | 454 | if (err < 0) { |
455 | printf("libfdt fdt_delprop(): %s\n", | 455 | printf("libfdt fdt_delprop(): %s\n", |
456 | fdt_strerror(err)); | 456 | fdt_strerror(err)); |
457 | return err; | 457 | return err; |
458 | } | 458 | } |
459 | } else { | 459 | } else { |
460 | err = fdt_del_node(working_fdt, nodeoffset); | 460 | err = fdt_del_node(working_fdt, nodeoffset); |
461 | if (err < 0) { | 461 | if (err < 0) { |
462 | printf("libfdt fdt_del_node(): %s\n", | 462 | printf("libfdt fdt_del_node(): %s\n", |
463 | fdt_strerror(err)); | 463 | fdt_strerror(err)); |
464 | return err; | 464 | return err; |
465 | } | 465 | } |
466 | } | 466 | } |
467 | 467 | ||
468 | /* | 468 | /* |
469 | * Display header info | 469 | * Display header info |
470 | */ | 470 | */ |
471 | } else if (argv[1][0] == 'h') { | 471 | } else if (argv[1][0] == 'h') { |
472 | u32 version = fdt_version(working_fdt); | 472 | u32 version = fdt_version(working_fdt); |
473 | printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt)); | 473 | printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt)); |
474 | printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt), | 474 | printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt), |
475 | fdt_totalsize(working_fdt)); | 475 | fdt_totalsize(working_fdt)); |
476 | printf("off_dt_struct:\t\t0x%x\n", | 476 | printf("off_dt_struct:\t\t0x%x\n", |
477 | fdt_off_dt_struct(working_fdt)); | 477 | fdt_off_dt_struct(working_fdt)); |
478 | printf("off_dt_strings:\t\t0x%x\n", | 478 | printf("off_dt_strings:\t\t0x%x\n", |
479 | fdt_off_dt_strings(working_fdt)); | 479 | fdt_off_dt_strings(working_fdt)); |
480 | printf("off_mem_rsvmap:\t\t0x%x\n", | 480 | printf("off_mem_rsvmap:\t\t0x%x\n", |
481 | fdt_off_mem_rsvmap(working_fdt)); | 481 | fdt_off_mem_rsvmap(working_fdt)); |
482 | printf("version:\t\t%d\n", version); | 482 | printf("version:\t\t%d\n", version); |
483 | printf("last_comp_version:\t%d\n", | 483 | printf("last_comp_version:\t%d\n", |
484 | fdt_last_comp_version(working_fdt)); | 484 | fdt_last_comp_version(working_fdt)); |
485 | if (version >= 2) | 485 | if (version >= 2) |
486 | printf("boot_cpuid_phys:\t0x%x\n", | 486 | printf("boot_cpuid_phys:\t0x%x\n", |
487 | fdt_boot_cpuid_phys(working_fdt)); | 487 | fdt_boot_cpuid_phys(working_fdt)); |
488 | if (version >= 3) | 488 | if (version >= 3) |
489 | printf("size_dt_strings:\t0x%x\n", | 489 | printf("size_dt_strings:\t0x%x\n", |
490 | fdt_size_dt_strings(working_fdt)); | 490 | fdt_size_dt_strings(working_fdt)); |
491 | if (version >= 17) | 491 | if (version >= 17) |
492 | printf("size_dt_struct:\t\t0x%x\n", | 492 | printf("size_dt_struct:\t\t0x%x\n", |
493 | fdt_size_dt_struct(working_fdt)); | 493 | fdt_size_dt_struct(working_fdt)); |
494 | printf("number mem_rsv:\t\t0x%x\n", | 494 | printf("number mem_rsv:\t\t0x%x\n", |
495 | fdt_num_mem_rsv(working_fdt)); | 495 | fdt_num_mem_rsv(working_fdt)); |
496 | printf("\n"); | 496 | printf("\n"); |
497 | 497 | ||
498 | /* | 498 | /* |
499 | * Set boot cpu id | 499 | * Set boot cpu id |
500 | */ | 500 | */ |
501 | } else if (strncmp(argv[1], "boo", 3) == 0) { | 501 | } else if (strncmp(argv[1], "boo", 3) == 0) { |
502 | unsigned long tmp = simple_strtoul(argv[2], NULL, 16); | 502 | unsigned long tmp = simple_strtoul(argv[2], NULL, 16); |
503 | fdt_set_boot_cpuid_phys(working_fdt, tmp); | 503 | fdt_set_boot_cpuid_phys(working_fdt, tmp); |
504 | 504 | ||
505 | /* | 505 | /* |
506 | * memory command | 506 | * memory command |
507 | */ | 507 | */ |
508 | } else if (strncmp(argv[1], "me", 2) == 0) { | 508 | } else if (strncmp(argv[1], "me", 2) == 0) { |
509 | uint64_t addr, size; | 509 | uint64_t addr, size; |
510 | int err; | 510 | int err; |
511 | addr = simple_strtoull(argv[2], NULL, 16); | 511 | addr = simple_strtoull(argv[2], NULL, 16); |
512 | size = simple_strtoull(argv[3], NULL, 16); | 512 | size = simple_strtoull(argv[3], NULL, 16); |
513 | err = fdt_fixup_memory(working_fdt, addr, size); | 513 | err = fdt_fixup_memory(working_fdt, addr, size); |
514 | if (err < 0) | 514 | if (err < 0) |
515 | return err; | 515 | return err; |
516 | 516 | ||
517 | /* | 517 | /* |
518 | * mem reserve commands | 518 | * mem reserve commands |
519 | */ | 519 | */ |
520 | } else if (strncmp(argv[1], "rs", 2) == 0) { | 520 | } else if (strncmp(argv[1], "rs", 2) == 0) { |
521 | if (argv[2][0] == 'p') { | 521 | if (argv[2][0] == 'p') { |
522 | uint64_t addr, size; | 522 | uint64_t addr, size; |
523 | int total = fdt_num_mem_rsv(working_fdt); | 523 | int total = fdt_num_mem_rsv(working_fdt); |
524 | int j, err; | 524 | int j, err; |
525 | printf("index\t\t start\t\t size\n"); | 525 | printf("index\t\t start\t\t size\n"); |
526 | printf("-------------------------------" | 526 | printf("-------------------------------" |
527 | "-----------------\n"); | 527 | "-----------------\n"); |
528 | for (j = 0; j < total; j++) { | 528 | for (j = 0; j < total; j++) { |
529 | err = fdt_get_mem_rsv(working_fdt, j, &addr, &size); | 529 | err = fdt_get_mem_rsv(working_fdt, j, &addr, &size); |
530 | if (err < 0) { | 530 | if (err < 0) { |
531 | printf("libfdt fdt_get_mem_rsv(): %s\n", | 531 | printf("libfdt fdt_get_mem_rsv(): %s\n", |
532 | fdt_strerror(err)); | 532 | fdt_strerror(err)); |
533 | return err; | 533 | return err; |
534 | } | 534 | } |
535 | printf(" %x\t%08x%08x\t%08x%08x\n", j, | 535 | printf(" %x\t%08x%08x\t%08x%08x\n", j, |
536 | (u32)(addr >> 32), | 536 | (u32)(addr >> 32), |
537 | (u32)(addr & 0xffffffff), | 537 | (u32)(addr & 0xffffffff), |
538 | (u32)(size >> 32), | 538 | (u32)(size >> 32), |
539 | (u32)(size & 0xffffffff)); | 539 | (u32)(size & 0xffffffff)); |
540 | } | 540 | } |
541 | } else if (argv[2][0] == 'a') { | 541 | } else if (argv[2][0] == 'a') { |
542 | uint64_t addr, size; | 542 | uint64_t addr, size; |
543 | int err; | 543 | int err; |
544 | addr = simple_strtoull(argv[3], NULL, 16); | 544 | addr = simple_strtoull(argv[3], NULL, 16); |
545 | size = simple_strtoull(argv[4], NULL, 16); | 545 | size = simple_strtoull(argv[4], NULL, 16); |
546 | err = fdt_add_mem_rsv(working_fdt, addr, size); | 546 | err = fdt_add_mem_rsv(working_fdt, addr, size); |
547 | 547 | ||
548 | if (err < 0) { | 548 | if (err < 0) { |
549 | printf("libfdt fdt_add_mem_rsv(): %s\n", | 549 | printf("libfdt fdt_add_mem_rsv(): %s\n", |
550 | fdt_strerror(err)); | 550 | fdt_strerror(err)); |
551 | return err; | 551 | return err; |
552 | } | 552 | } |
553 | } else if (argv[2][0] == 'd') { | 553 | } else if (argv[2][0] == 'd') { |
554 | unsigned long idx = simple_strtoul(argv[3], NULL, 16); | 554 | unsigned long idx = simple_strtoul(argv[3], NULL, 16); |
555 | int err = fdt_del_mem_rsv(working_fdt, idx); | 555 | int err = fdt_del_mem_rsv(working_fdt, idx); |
556 | 556 | ||
557 | if (err < 0) { | 557 | if (err < 0) { |
558 | printf("libfdt fdt_del_mem_rsv(): %s\n", | 558 | printf("libfdt fdt_del_mem_rsv(): %s\n", |
559 | fdt_strerror(err)); | 559 | fdt_strerror(err)); |
560 | return err; | 560 | return err; |
561 | } | 561 | } |
562 | } else { | 562 | } else { |
563 | /* Unrecognized command */ | 563 | /* Unrecognized command */ |
564 | return CMD_RET_USAGE; | 564 | return CMD_RET_USAGE; |
565 | } | 565 | } |
566 | } | 566 | } |
567 | #ifdef CONFIG_OF_BOARD_SETUP | 567 | #ifdef CONFIG_OF_BOARD_SETUP |
568 | /* Call the board-specific fixup routine */ | 568 | /* Call the board-specific fixup routine */ |
569 | else if (strncmp(argv[1], "boa", 3) == 0) { | 569 | else if (strncmp(argv[1], "boa", 3) == 0) { |
570 | int err = ft_board_setup(working_fdt, gd->bd); | 570 | int err = ft_board_setup(working_fdt, gd->bd); |
571 | 571 | ||
572 | if (err) { | 572 | if (err) { |
573 | printf("Failed to update board information in FDT: %s\n", | 573 | printf("Failed to update board information in FDT: %s\n", |
574 | fdt_strerror(err)); | 574 | fdt_strerror(err)); |
575 | return CMD_RET_FAILURE; | 575 | return CMD_RET_FAILURE; |
576 | } | 576 | } |
577 | } | 577 | } |
578 | #endif | 578 | #endif |
579 | #ifdef CONFIG_OF_SYSTEM_SETUP | 579 | #ifdef CONFIG_OF_SYSTEM_SETUP |
580 | /* Call the board-specific fixup routine */ | 580 | /* Call the board-specific fixup routine */ |
581 | else if (strncmp(argv[1], "sys", 3) == 0) { | 581 | else if (strncmp(argv[1], "sys", 3) == 0) { |
582 | int err = ft_system_setup(working_fdt, gd->bd); | 582 | int err = ft_system_setup(working_fdt, gd->bd); |
583 | 583 | ||
584 | if (err) { | 584 | if (err) { |
585 | printf("Failed to add system information to FDT: %s\n", | 585 | printf("Failed to add system information to FDT: %s\n", |
586 | fdt_strerror(err)); | 586 | fdt_strerror(err)); |
587 | return CMD_RET_FAILURE; | 587 | return CMD_RET_FAILURE; |
588 | } | 588 | } |
589 | } | 589 | } |
590 | #endif | 590 | #endif |
591 | /* Create a chosen node */ | 591 | /* Create a chosen node */ |
592 | else if (strncmp(argv[1], "cho", 3) == 0) { | 592 | else if (strncmp(argv[1], "cho", 3) == 0) { |
593 | unsigned long initrd_start = 0, initrd_end = 0; | 593 | unsigned long initrd_start = 0, initrd_end = 0; |
594 | 594 | ||
595 | if ((argc != 2) && (argc != 4)) | 595 | if ((argc != 2) && (argc != 4)) |
596 | return CMD_RET_USAGE; | 596 | return CMD_RET_USAGE; |
597 | 597 | ||
598 | if (argc == 4) { | 598 | if (argc == 4) { |
599 | initrd_start = simple_strtoul(argv[2], NULL, 16); | 599 | initrd_start = simple_strtoul(argv[2], NULL, 16); |
600 | initrd_end = simple_strtoul(argv[3], NULL, 16); | 600 | initrd_end = simple_strtoul(argv[3], NULL, 16); |
601 | } | 601 | } |
602 | 602 | ||
603 | fdt_chosen(working_fdt); | 603 | fdt_chosen(working_fdt); |
604 | fdt_initrd(working_fdt, initrd_start, initrd_end); | 604 | fdt_initrd(working_fdt, initrd_start, initrd_end); |
605 | 605 | ||
606 | #if defined(CONFIG_FIT_SIGNATURE) | 606 | #if defined(CONFIG_FIT_SIGNATURE) |
607 | } else if (strncmp(argv[1], "che", 3) == 0) { | 607 | } else if (strncmp(argv[1], "che", 3) == 0) { |
608 | int cfg_noffset; | 608 | int cfg_noffset; |
609 | int ret; | 609 | int ret; |
610 | unsigned long addr; | 610 | unsigned long addr; |
611 | struct fdt_header *blob; | 611 | struct fdt_header *blob; |
612 | 612 | ||
613 | if (!working_fdt) | 613 | if (!working_fdt) |
614 | return CMD_RET_FAILURE; | 614 | return CMD_RET_FAILURE; |
615 | 615 | ||
616 | if (argc > 2) { | 616 | if (argc > 2) { |
617 | addr = simple_strtoul(argv[2], NULL, 16); | 617 | addr = simple_strtoul(argv[2], NULL, 16); |
618 | blob = map_sysmem(addr, 0); | 618 | blob = map_sysmem(addr, 0); |
619 | } else { | 619 | } else { |
620 | blob = (struct fdt_header *)gd->fdt_blob; | 620 | blob = (struct fdt_header *)gd->fdt_blob; |
621 | } | 621 | } |
622 | if (!fdt_valid(&blob)) | 622 | if (!fdt_valid(&blob)) |
623 | return 1; | 623 | return 1; |
624 | 624 | ||
625 | gd->fdt_blob = blob; | 625 | gd->fdt_blob = blob; |
626 | cfg_noffset = fit_conf_get_node(working_fdt, NULL); | 626 | cfg_noffset = fit_conf_get_node(working_fdt, NULL); |
627 | if (!cfg_noffset) { | 627 | if (!cfg_noffset) { |
628 | printf("Could not find configuration node: %s\n", | 628 | printf("Could not find configuration node: %s\n", |
629 | fdt_strerror(cfg_noffset)); | 629 | fdt_strerror(cfg_noffset)); |
630 | return CMD_RET_FAILURE; | 630 | return CMD_RET_FAILURE; |
631 | } | 631 | } |
632 | 632 | ||
633 | ret = fit_config_verify(working_fdt, cfg_noffset); | 633 | ret = fit_config_verify(working_fdt, cfg_noffset); |
634 | if (ret == 0) | 634 | if (ret == 0) |
635 | return CMD_RET_SUCCESS; | 635 | return CMD_RET_SUCCESS; |
636 | else | 636 | else |
637 | return CMD_RET_FAILURE; | 637 | return CMD_RET_FAILURE; |
638 | #endif | 638 | #endif |
639 | 639 | ||
640 | } | 640 | } |
641 | /* resize the fdt */ | 641 | /* resize the fdt */ |
642 | else if (strncmp(argv[1], "re", 2) == 0) { | 642 | else if (strncmp(argv[1], "re", 2) == 0) { |
643 | fdt_shrink_to_minimum(working_fdt); | 643 | fdt_shrink_to_minimum(working_fdt); |
644 | } | 644 | } |
645 | else { | 645 | else { |
646 | /* Unrecognized command */ | 646 | /* Unrecognized command */ |
647 | return CMD_RET_USAGE; | 647 | return CMD_RET_USAGE; |
648 | } | 648 | } |
649 | 649 | ||
650 | return 0; | 650 | return 0; |
651 | } | 651 | } |
652 | 652 | ||
653 | /****************************************************************************/ | 653 | /****************************************************************************/ |
654 | 654 | ||
655 | /** | 655 | /** |
656 | * fdt_valid() - Check if an FDT is valid. If not, change it to NULL | 656 | * fdt_valid() - Check if an FDT is valid. If not, change it to NULL |
657 | * | 657 | * |
658 | * @blobp: Pointer to FDT pointer | 658 | * @blobp: Pointer to FDT pointer |
659 | * @return 1 if OK, 0 if bad (in which case *blobp is set to NULL) | 659 | * @return 1 if OK, 0 if bad (in which case *blobp is set to NULL) |
660 | */ | 660 | */ |
661 | static int fdt_valid(struct fdt_header **blobp) | 661 | static int fdt_valid(struct fdt_header **blobp) |
662 | { | 662 | { |
663 | const void *blob = *blobp; | 663 | const void *blob = *blobp; |
664 | int err; | 664 | int err; |
665 | 665 | ||
666 | if (blob == NULL) { | 666 | if (blob == NULL) { |
667 | printf ("The address of the fdt is invalid (NULL).\n"); | 667 | printf ("The address of the fdt is invalid (NULL).\n"); |
668 | return 0; | 668 | return 0; |
669 | } | 669 | } |
670 | 670 | ||
671 | err = fdt_check_header(blob); | 671 | err = fdt_check_header(blob); |
672 | if (err == 0) | 672 | if (err == 0) |
673 | return 1; /* valid */ | 673 | return 1; /* valid */ |
674 | 674 | ||
675 | if (err < 0) { | 675 | if (err < 0) { |
676 | printf("libfdt fdt_check_header(): %s", fdt_strerror(err)); | 676 | printf("libfdt fdt_check_header(): %s", fdt_strerror(err)); |
677 | /* | 677 | /* |
678 | * Be more informative on bad version. | 678 | * Be more informative on bad version. |
679 | */ | 679 | */ |
680 | if (err == -FDT_ERR_BADVERSION) { | 680 | if (err == -FDT_ERR_BADVERSION) { |
681 | if (fdt_version(blob) < | 681 | if (fdt_version(blob) < |
682 | FDT_FIRST_SUPPORTED_VERSION) { | 682 | FDT_FIRST_SUPPORTED_VERSION) { |
683 | printf (" - too old, fdt %d < %d", | 683 | printf (" - too old, fdt %d < %d", |
684 | fdt_version(blob), | 684 | fdt_version(blob), |
685 | FDT_FIRST_SUPPORTED_VERSION); | 685 | FDT_FIRST_SUPPORTED_VERSION); |
686 | } | 686 | } |
687 | if (fdt_last_comp_version(blob) > | 687 | if (fdt_last_comp_version(blob) > |
688 | FDT_LAST_SUPPORTED_VERSION) { | 688 | FDT_LAST_SUPPORTED_VERSION) { |
689 | printf (" - too new, fdt %d > %d", | 689 | printf (" - too new, fdt %d > %d", |
690 | fdt_version(blob), | 690 | fdt_version(blob), |
691 | FDT_LAST_SUPPORTED_VERSION); | 691 | FDT_LAST_SUPPORTED_VERSION); |
692 | } | 692 | } |
693 | } | 693 | } |
694 | printf("\n"); | 694 | printf("\n"); |
695 | *blobp = NULL; | 695 | *blobp = NULL; |
696 | return 0; | 696 | return 0; |
697 | } | 697 | } |
698 | return 1; | 698 | return 1; |
699 | } | 699 | } |
700 | 700 | ||
701 | /****************************************************************************/ | 701 | /****************************************************************************/ |
702 | 702 | ||
703 | /* | 703 | /* |
704 | * Parse the user's input, partially heuristic. Valid formats: | 704 | * Parse the user's input, partially heuristic. Valid formats: |
705 | * <0x00112233 4 05> - an array of cells. Numbers follow standard | 705 | * <0x00112233 4 05> - an array of cells. Numbers follow standard |
706 | * C conventions. | 706 | * C conventions. |
707 | * [00 11 22 .. nn] - byte stream | 707 | * [00 11 22 .. nn] - byte stream |
708 | * "string" - If the the value doesn't start with "<" or "[", it is | 708 | * "string" - If the the value doesn't start with "<" or "[", it is |
709 | * treated as a string. Note that the quotes are | 709 | * treated as a string. Note that the quotes are |
710 | * stripped by the parser before we get the string. | 710 | * stripped by the parser before we get the string. |
711 | * newval: An array of strings containing the new property as specified | 711 | * newval: An array of strings containing the new property as specified |
712 | * on the command line | 712 | * on the command line |
713 | * count: The number of strings in the array | 713 | * count: The number of strings in the array |
714 | * data: A bytestream to be placed in the property | 714 | * data: A bytestream to be placed in the property |
715 | * len: The length of the resulting bytestream | 715 | * len: The length of the resulting bytestream |
716 | */ | 716 | */ |
717 | static int fdt_parse_prop(char * const *newval, int count, char *data, int *len) | 717 | static int fdt_parse_prop(char * const *newval, int count, char *data, int *len) |
718 | { | 718 | { |
719 | char *cp; /* temporary char pointer */ | 719 | char *cp; /* temporary char pointer */ |
720 | char *newp; /* temporary newval char pointer */ | 720 | char *newp; /* temporary newval char pointer */ |
721 | unsigned long tmp; /* holds converted values */ | 721 | unsigned long tmp; /* holds converted values */ |
722 | int stridx = 0; | 722 | int stridx = 0; |
723 | 723 | ||
724 | *len = 0; | 724 | *len = 0; |
725 | newp = newval[0]; | 725 | newp = newval[0]; |
726 | 726 | ||
727 | /* An array of cells */ | 727 | /* An array of cells */ |
728 | if (*newp == '<') { | 728 | if (*newp == '<') { |
729 | newp++; | 729 | newp++; |
730 | while ((*newp != '>') && (stridx < count)) { | 730 | while ((*newp != '>') && (stridx < count)) { |
731 | /* | 731 | /* |
732 | * Keep searching until we find that last ">" | 732 | * Keep searching until we find that last ">" |
733 | * That way users don't have to escape the spaces | 733 | * That way users don't have to escape the spaces |
734 | */ | 734 | */ |
735 | if (*newp == '\0') { | 735 | if (*newp == '\0') { |
736 | newp = newval[++stridx]; | 736 | newp = newval[++stridx]; |
737 | continue; | 737 | continue; |
738 | } | 738 | } |
739 | 739 | ||
740 | cp = newp; | 740 | cp = newp; |
741 | tmp = simple_strtoul(cp, &newp, 0); | 741 | tmp = simple_strtoul(cp, &newp, 0); |
742 | *(__be32 *)data = __cpu_to_be32(tmp); | 742 | *(__be32 *)data = __cpu_to_be32(tmp); |
743 | data += 4; | 743 | data += 4; |
744 | *len += 4; | 744 | *len += 4; |
745 | 745 | ||
746 | /* If the ptr didn't advance, something went wrong */ | 746 | /* If the ptr didn't advance, something went wrong */ |
747 | if ((newp - cp) <= 0) { | 747 | if ((newp - cp) <= 0) { |
748 | printf("Sorry, I could not convert \"%s\"\n", | 748 | printf("Sorry, I could not convert \"%s\"\n", |
749 | cp); | 749 | cp); |
750 | return 1; | 750 | return 1; |
751 | } | 751 | } |
752 | 752 | ||
753 | while (*newp == ' ') | 753 | while (*newp == ' ') |
754 | newp++; | 754 | newp++; |
755 | } | 755 | } |
756 | 756 | ||
757 | if (*newp != '>') { | 757 | if (*newp != '>') { |
758 | printf("Unexpected character '%c'\n", *newp); | 758 | printf("Unexpected character '%c'\n", *newp); |
759 | return 1; | 759 | return 1; |
760 | } | 760 | } |
761 | } else if (*newp == '[') { | 761 | } else if (*newp == '[') { |
762 | /* | 762 | /* |
763 | * Byte stream. Convert the values. | 763 | * Byte stream. Convert the values. |
764 | */ | 764 | */ |
765 | newp++; | 765 | newp++; |
766 | while ((stridx < count) && (*newp != ']')) { | 766 | while ((stridx < count) && (*newp != ']')) { |
767 | while (*newp == ' ') | 767 | while (*newp == ' ') |
768 | newp++; | 768 | newp++; |
769 | if (*newp == '\0') { | 769 | if (*newp == '\0') { |
770 | newp = newval[++stridx]; | 770 | newp = newval[++stridx]; |
771 | continue; | 771 | continue; |
772 | } | 772 | } |
773 | if (!isxdigit(*newp)) | 773 | if (!isxdigit(*newp)) |
774 | break; | 774 | break; |
775 | tmp = simple_strtoul(newp, &newp, 16); | 775 | tmp = simple_strtoul(newp, &newp, 16); |
776 | *data++ = tmp & 0xFF; | 776 | *data++ = tmp & 0xFF; |
777 | *len = *len + 1; | 777 | *len = *len + 1; |
778 | } | 778 | } |
779 | if (*newp != ']') { | 779 | if (*newp != ']') { |
780 | printf("Unexpected character '%c'\n", *newp); | 780 | printf("Unexpected character '%c'\n", *newp); |
781 | return 1; | 781 | return 1; |
782 | } | 782 | } |
783 | } else { | 783 | } else { |
784 | /* | 784 | /* |
785 | * Assume it is one or more strings. Copy it into our | 785 | * Assume it is one or more strings. Copy it into our |
786 | * data area for convenience (including the | 786 | * data area for convenience (including the |
787 | * terminating '\0's). | 787 | * terminating '\0's). |
788 | */ | 788 | */ |
789 | while (stridx < count) { | 789 | while (stridx < count) { |
790 | size_t length = strlen(newp) + 1; | 790 | size_t length = strlen(newp) + 1; |
791 | strcpy(data, newp); | 791 | strcpy(data, newp); |
792 | data += length; | 792 | data += length; |
793 | *len += length; | 793 | *len += length; |
794 | newp = newval[++stridx]; | 794 | newp = newval[++stridx]; |
795 | } | 795 | } |
796 | } | 796 | } |
797 | return 0; | 797 | return 0; |
798 | } | 798 | } |
799 | 799 | ||
800 | /****************************************************************************/ | 800 | /****************************************************************************/ |
801 | 801 | ||
802 | /* | 802 | /* |
803 | * Heuristic to guess if this is a string or concatenated strings. | 803 | * Heuristic to guess if this is a string or concatenated strings. |
804 | */ | 804 | */ |
805 | 805 | ||
806 | static int is_printable_string(const void *data, int len) | 806 | static int is_printable_string(const void *data, int len) |
807 | { | 807 | { |
808 | const char *s = data; | 808 | const char *s = data; |
809 | 809 | ||
810 | /* zero length is not */ | 810 | /* zero length is not */ |
811 | if (len == 0) | 811 | if (len == 0) |
812 | return 0; | 812 | return 0; |
813 | 813 | ||
814 | /* must terminate with zero or '\n' */ | 814 | /* must terminate with zero or '\n' */ |
815 | if (s[len - 1] != '\0' && s[len - 1] != '\n') | 815 | if (s[len - 1] != '\0' && s[len - 1] != '\n') |
816 | return 0; | 816 | return 0; |
817 | 817 | ||
818 | /* printable or a null byte (concatenated strings) */ | 818 | /* printable or a null byte (concatenated strings) */ |
819 | while (((*s == '\0') || isprint(*s) || isspace(*s)) && (len > 0)) { | 819 | while (((*s == '\0') || isprint(*s) || isspace(*s)) && (len > 0)) { |
820 | /* | 820 | /* |
821 | * If we see a null, there are three possibilities: | 821 | * If we see a null, there are three possibilities: |
822 | * 1) If len == 1, it is the end of the string, printable | 822 | * 1) If len == 1, it is the end of the string, printable |
823 | * 2) Next character also a null, not printable. | 823 | * 2) Next character also a null, not printable. |
824 | * 3) Next character not a null, continue to check. | 824 | * 3) Next character not a null, continue to check. |
825 | */ | 825 | */ |
826 | if (s[0] == '\0') { | 826 | if (s[0] == '\0') { |
827 | if (len == 1) | 827 | if (len == 1) |
828 | return 1; | 828 | return 1; |
829 | if (s[1] == '\0') | 829 | if (s[1] == '\0') |
830 | return 0; | 830 | return 0; |
831 | } | 831 | } |
832 | s++; | 832 | s++; |
833 | len--; | 833 | len--; |
834 | } | 834 | } |
835 | 835 | ||
836 | /* Not the null termination, or not done yet: not printable */ | 836 | /* Not the null termination, or not done yet: not printable */ |
837 | if (*s != '\0' || (len != 0)) | 837 | if (*s != '\0' || (len != 0)) |
838 | return 0; | 838 | return 0; |
839 | 839 | ||
840 | return 1; | 840 | return 1; |
841 | } | 841 | } |
842 | 842 | ||
843 | 843 | ||
844 | /* | 844 | /* |
845 | * Print the property in the best format, a heuristic guess. Print as | 845 | * Print the property in the best format, a heuristic guess. Print as |
846 | * a string, concatenated strings, a byte, word, double word, or (if all | 846 | * a string, concatenated strings, a byte, word, double word, or (if all |
847 | * else fails) it is printed as a stream of bytes. | 847 | * else fails) it is printed as a stream of bytes. |
848 | */ | 848 | */ |
849 | static void print_data(const void *data, int len) | 849 | static void print_data(const void *data, int len) |
850 | { | 850 | { |
851 | int j; | 851 | int j; |
852 | 852 | ||
853 | /* no data, don't print */ | 853 | /* no data, don't print */ |
854 | if (len == 0) | 854 | if (len == 0) |
855 | return; | 855 | return; |
856 | 856 | ||
857 | /* | 857 | /* |
858 | * It is a string, but it may have multiple strings (embedded '\0's). | 858 | * It is a string, but it may have multiple strings (embedded '\0's). |
859 | */ | 859 | */ |
860 | if (is_printable_string(data, len)) { | 860 | if (is_printable_string(data, len)) { |
861 | puts("\""); | 861 | puts("\""); |
862 | j = 0; | 862 | j = 0; |
863 | while (j < len) { | 863 | while (j < len) { |
864 | if (j > 0) | 864 | if (j > 0) |
865 | puts("\", \""); | 865 | puts("\", \""); |
866 | puts(data); | 866 | puts(data); |
867 | j += strlen(data) + 1; | 867 | j += strlen(data) + 1; |
868 | data += strlen(data) + 1; | 868 | data += strlen(data) + 1; |
869 | } | 869 | } |
870 | puts("\""); | 870 | puts("\""); |
871 | return; | 871 | return; |
872 | } | 872 | } |
873 | 873 | ||
874 | if ((len %4) == 0) { | 874 | if ((len %4) == 0) { |
875 | if (len > CONFIG_CMD_FDT_MAX_DUMP) | 875 | if (len > CONFIG_CMD_FDT_MAX_DUMP) |
876 | printf("* 0x%p [0x%08x]", data, len); | 876 | printf("* 0x%p [0x%08x]", data, len); |
877 | else { | 877 | else { |
878 | const __be32 *p; | 878 | const __be32 *p; |
879 | 879 | ||
880 | printf("<"); | 880 | printf("<"); |
881 | for (j = 0, p = data; j < len/4; j++) | 881 | for (j = 0, p = data; j < len/4; j++) |
882 | printf("0x%08x%s", fdt32_to_cpu(p[j]), | 882 | printf("0x%08x%s", fdt32_to_cpu(p[j]), |
883 | j < (len/4 - 1) ? " " : ""); | 883 | j < (len/4 - 1) ? " " : ""); |
884 | printf(">"); | 884 | printf(">"); |
885 | } | 885 | } |
886 | } else { /* anything else... hexdump */ | 886 | } else { /* anything else... hexdump */ |
887 | if (len > CONFIG_CMD_FDT_MAX_DUMP) | 887 | if (len > CONFIG_CMD_FDT_MAX_DUMP) |
888 | printf("* 0x%p [0x%08x]", data, len); | 888 | printf("* 0x%p [0x%08x]", data, len); |
889 | else { | 889 | else { |
890 | const u8 *s; | 890 | const u8 *s; |
891 | 891 | ||
892 | printf("["); | 892 | printf("["); |
893 | for (j = 0, s = data; j < len; j++) | 893 | for (j = 0, s = data; j < len; j++) |
894 | printf("%02x%s", s[j], j < len - 1 ? " " : ""); | 894 | printf("%02x%s", s[j], j < len - 1 ? " " : ""); |
895 | printf("]"); | 895 | printf("]"); |
896 | } | 896 | } |
897 | } | 897 | } |
898 | } | 898 | } |
899 | 899 | ||
900 | /****************************************************************************/ | 900 | /****************************************************************************/ |
901 | 901 | ||
902 | /* | 902 | /* |
903 | * Recursively print (a portion of) the working_fdt. The depth parameter | 903 | * Recursively print (a portion of) the working_fdt. The depth parameter |
904 | * determines how deeply nested the fdt is printed. | 904 | * determines how deeply nested the fdt is printed. |
905 | */ | 905 | */ |
906 | static int fdt_print(const char *pathp, char *prop, int depth) | 906 | static int fdt_print(const char *pathp, char *prop, int depth) |
907 | { | 907 | { |
908 | static char tabs[MAX_LEVEL+1] = | 908 | static char tabs[MAX_LEVEL+1] = |
909 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" | 909 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" |
910 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; | 910 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; |
911 | const void *nodep; /* property node pointer */ | 911 | const void *nodep; /* property node pointer */ |
912 | int nodeoffset; /* node offset from libfdt */ | 912 | int nodeoffset; /* node offset from libfdt */ |
913 | int nextoffset; /* next node offset from libfdt */ | 913 | int nextoffset; /* next node offset from libfdt */ |
914 | uint32_t tag; /* tag */ | 914 | uint32_t tag; /* tag */ |
915 | int len; /* length of the property */ | 915 | int len; /* length of the property */ |
916 | int level = 0; /* keep track of nesting level */ | 916 | int level = 0; /* keep track of nesting level */ |
917 | const struct fdt_property *fdt_prop; | 917 | const struct fdt_property *fdt_prop; |
918 | 918 | ||
919 | nodeoffset = fdt_path_offset (working_fdt, pathp); | 919 | nodeoffset = fdt_path_offset (working_fdt, pathp); |
920 | if (nodeoffset < 0) { | 920 | if (nodeoffset < 0) { |
921 | /* | 921 | /* |
922 | * Not found or something else bad happened. | 922 | * Not found or something else bad happened. |
923 | */ | 923 | */ |
924 | printf ("libfdt fdt_path_offset() returned %s\n", | 924 | printf ("libfdt fdt_path_offset() returned %s\n", |
925 | fdt_strerror(nodeoffset)); | 925 | fdt_strerror(nodeoffset)); |
926 | return 1; | 926 | return 1; |
927 | } | 927 | } |
928 | /* | 928 | /* |
929 | * The user passed in a property as well as node path. | 929 | * The user passed in a property as well as node path. |
930 | * Print only the given property and then return. | 930 | * Print only the given property and then return. |
931 | */ | 931 | */ |
932 | if (prop) { | 932 | if (prop) { |
933 | nodep = fdt_getprop (working_fdt, nodeoffset, prop, &len); | 933 | nodep = fdt_getprop (working_fdt, nodeoffset, prop, &len); |
934 | if (len == 0) { | 934 | if (len == 0) { |
935 | /* no property value */ | 935 | /* no property value */ |
936 | printf("%s %s\n", pathp, prop); | 936 | printf("%s %s\n", pathp, prop); |
937 | return 0; | 937 | return 0; |
938 | } else if (len > 0) { | 938 | } else if (len > 0) { |
939 | printf("%s = ", prop); | 939 | printf("%s = ", prop); |
940 | print_data (nodep, len); | 940 | print_data (nodep, len); |
941 | printf("\n"); | 941 | printf("\n"); |
942 | return 0; | 942 | return 0; |
943 | } else { | 943 | } else { |
944 | printf ("libfdt fdt_getprop(): %s\n", | 944 | printf ("libfdt fdt_getprop(): %s\n", |
945 | fdt_strerror(len)); | 945 | fdt_strerror(len)); |
946 | return 1; | 946 | return 1; |
947 | } | 947 | } |
948 | } | 948 | } |
949 | 949 | ||
950 | /* | 950 | /* |
951 | * The user passed in a node path and no property, | 951 | * The user passed in a node path and no property, |
952 | * print the node and all subnodes. | 952 | * print the node and all subnodes. |
953 | */ | 953 | */ |
954 | while(level >= 0) { | 954 | while(level >= 0) { |
955 | tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset); | 955 | tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset); |
956 | switch(tag) { | 956 | switch(tag) { |
957 | case FDT_BEGIN_NODE: | 957 | case FDT_BEGIN_NODE: |
958 | pathp = fdt_get_name(working_fdt, nodeoffset, NULL); | 958 | pathp = fdt_get_name(working_fdt, nodeoffset, NULL); |
959 | if (level <= depth) { | 959 | if (level <= depth) { |
960 | if (pathp == NULL) | 960 | if (pathp == NULL) |
961 | pathp = "/* NULL pointer error */"; | 961 | pathp = "/* NULL pointer error */"; |
962 | if (*pathp == '\0') | 962 | if (*pathp == '\0') |
963 | pathp = "/"; /* root is nameless */ | 963 | pathp = "/"; /* root is nameless */ |
964 | printf("%s%s {\n", | 964 | printf("%s%s {\n", |
965 | &tabs[MAX_LEVEL - level], pathp); | 965 | &tabs[MAX_LEVEL - level], pathp); |
966 | } | 966 | } |
967 | level++; | 967 | level++; |
968 | if (level >= MAX_LEVEL) { | 968 | if (level >= MAX_LEVEL) { |
969 | printf("Nested too deep, aborting.\n"); | 969 | printf("Nested too deep, aborting.\n"); |
970 | return 1; | 970 | return 1; |
971 | } | 971 | } |
972 | break; | 972 | break; |
973 | case FDT_END_NODE: | 973 | case FDT_END_NODE: |
974 | level--; | 974 | level--; |
975 | if (level <= depth) | 975 | if (level <= depth) |
976 | printf("%s};\n", &tabs[MAX_LEVEL - level]); | 976 | printf("%s};\n", &tabs[MAX_LEVEL - level]); |
977 | if (level == 0) { | 977 | if (level == 0) { |
978 | level = -1; /* exit the loop */ | 978 | level = -1; /* exit the loop */ |
979 | } | 979 | } |
980 | break; | 980 | break; |
981 | case FDT_PROP: | 981 | case FDT_PROP: |
982 | fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset, | 982 | fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset, |
983 | sizeof(*fdt_prop)); | 983 | sizeof(*fdt_prop)); |
984 | pathp = fdt_string(working_fdt, | 984 | pathp = fdt_string(working_fdt, |
985 | fdt32_to_cpu(fdt_prop->nameoff)); | 985 | fdt32_to_cpu(fdt_prop->nameoff)); |
986 | len = fdt32_to_cpu(fdt_prop->len); | 986 | len = fdt32_to_cpu(fdt_prop->len); |
987 | nodep = fdt_prop->data; | 987 | nodep = fdt_prop->data; |
988 | if (len < 0) { | 988 | if (len < 0) { |
989 | printf ("libfdt fdt_getprop(): %s\n", | 989 | printf ("libfdt fdt_getprop(): %s\n", |
990 | fdt_strerror(len)); | 990 | fdt_strerror(len)); |
991 | return 1; | 991 | return 1; |
992 | } else if (len == 0) { | 992 | } else if (len == 0) { |
993 | /* the property has no value */ | 993 | /* the property has no value */ |
994 | if (level <= depth) | 994 | if (level <= depth) |
995 | printf("%s%s;\n", | 995 | printf("%s%s;\n", |
996 | &tabs[MAX_LEVEL - level], | 996 | &tabs[MAX_LEVEL - level], |
997 | pathp); | 997 | pathp); |
998 | } else { | 998 | } else { |
999 | if (level <= depth) { | 999 | if (level <= depth) { |
1000 | printf("%s%s = ", | 1000 | printf("%s%s = ", |
1001 | &tabs[MAX_LEVEL - level], | 1001 | &tabs[MAX_LEVEL - level], |
1002 | pathp); | 1002 | pathp); |
1003 | print_data (nodep, len); | 1003 | print_data (nodep, len); |
1004 | printf(";\n"); | 1004 | printf(";\n"); |
1005 | } | 1005 | } |
1006 | } | 1006 | } |
1007 | break; | 1007 | break; |
1008 | case FDT_NOP: | 1008 | case FDT_NOP: |
1009 | printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]); | 1009 | printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]); |
1010 | break; | 1010 | break; |
1011 | case FDT_END: | 1011 | case FDT_END: |
1012 | return 1; | 1012 | return 1; |
1013 | default: | 1013 | default: |
1014 | if (level <= depth) | 1014 | if (level <= depth) |
1015 | printf("Unknown tag 0x%08X\n", tag); | 1015 | printf("Unknown tag 0x%08X\n", tag); |
1016 | return 1; | 1016 | return 1; |
1017 | } | 1017 | } |
1018 | nodeoffset = nextoffset; | 1018 | nodeoffset = nextoffset; |
1019 | } | 1019 | } |
1020 | return 0; | 1020 | return 0; |
1021 | } | 1021 | } |
1022 | 1022 | ||
1023 | /********************************************************************/ | 1023 | /********************************************************************/ |
1024 | #ifdef CONFIG_SYS_LONGHELP | 1024 | #ifdef CONFIG_SYS_LONGHELP |
1025 | static char fdt_help_text[] = | 1025 | static char fdt_help_text[] = |
1026 | "addr [-c] <addr> [<length>] - Set the [control] fdt location to <addr>\n" | 1026 | "addr [-c] <addr> [<length>] - Set the [control] fdt location to <addr>\n" |
1027 | #ifdef CONFIG_OF_BOARD_SETUP | 1027 | #ifdef CONFIG_OF_BOARD_SETUP |
1028 | "fdt boardsetup - Do board-specific set up\n" | 1028 | "fdt boardsetup - Do board-specific set up\n" |
1029 | #endif | 1029 | #endif |
1030 | #ifdef CONFIG_OF_SYSTEM_SETUP | 1030 | #ifdef CONFIG_OF_SYSTEM_SETUP |
1031 | "fdt systemsetup - Do system-specific set up\n" | 1031 | "fdt systemsetup - Do system-specific set up\n" |
1032 | #endif | 1032 | #endif |
1033 | "fdt move <fdt> <newaddr> <length> - Copy the fdt to <addr> and make it active\n" | 1033 | "fdt move <fdt> <newaddr> <length> - Copy the fdt to <addr> and make it active\n" |
1034 | "fdt resize - Resize fdt to size + padding to 4k addr\n" | 1034 | "fdt resize - Resize fdt to size + padding to 4k addr\n" |
1035 | "fdt print <path> [<prop>] - Recursive print starting at <path>\n" | 1035 | "fdt print <path> [<prop>] - Recursive print starting at <path>\n" |
1036 | "fdt list <path> [<prop>] - Print one level starting at <path>\n" | 1036 | "fdt list <path> [<prop>] - Print one level starting at <path>\n" |
1037 | "fdt get value <var> <path> <prop> - Get <property> and store in <var>\n" | 1037 | "fdt get value <var> <path> <prop> - Get <property> and store in <var>\n" |
1038 | "fdt get name <var> <path> <index> - Get name of node <index> and store in <var>\n" | 1038 | "fdt get name <var> <path> <index> - Get name of node <index> and store in <var>\n" |
1039 | "fdt get addr <var> <path> <prop> - Get start address of <property> and store in <var>\n" | 1039 | "fdt get addr <var> <path> <prop> - Get start address of <property> and store in <var>\n" |
1040 | "fdt get size <var> <path> [<prop>] - Get size of [<property>] or num nodes and store in <var>\n" | 1040 | "fdt get size <var> <path> [<prop>] - Get size of [<property>] or num nodes and store in <var>\n" |
1041 | "fdt set <path> <prop> [<val>] - Set <property> [to <val>]\n" | 1041 | "fdt set <path> <prop> [<val>] - Set <property> [to <val>]\n" |
1042 | "fdt mknode <path> <node> - Create a new node after <path>\n" | 1042 | "fdt mknode <path> <node> - Create a new node after <path>\n" |
1043 | "fdt rm <path> [<prop>] - Delete the node or <property>\n" | 1043 | "fdt rm <path> [<prop>] - Delete the node or <property>\n" |
1044 | "fdt header - Display header info\n" | 1044 | "fdt header - Display header info\n" |
1045 | "fdt bootcpu <id> - Set boot cpuid\n" | 1045 | "fdt bootcpu <id> - Set boot cpuid\n" |
1046 | "fdt memory <addr> <size> - Add/Update memory node\n" | 1046 | "fdt memory <addr> <size> - Add/Update memory node\n" |
1047 | "fdt rsvmem print - Show current mem reserves\n" | 1047 | "fdt rsvmem print - Show current mem reserves\n" |
1048 | "fdt rsvmem add <addr> <size> - Add a mem reserve\n" | 1048 | "fdt rsvmem add <addr> <size> - Add a mem reserve\n" |
1049 | "fdt rsvmem delete <index> - Delete a mem reserves\n" | 1049 | "fdt rsvmem delete <index> - Delete a mem reserves\n" |
1050 | "fdt chosen [<start> <end>] - Add/update the /chosen branch in the tree\n" | 1050 | "fdt chosen [<start> <end>] - Add/update the /chosen branch in the tree\n" |
1051 | " <start>/<end> - initrd start/end addr\n" | 1051 | " <start>/<end> - initrd start/end addr\n" |
1052 | #if defined(CONFIG_FIT_SIGNATURE) | 1052 | #if defined(CONFIG_FIT_SIGNATURE) |
1053 | "fdt checksign [<addr>] - check FIT signature\n" | 1053 | "fdt checksign [<addr>] - check FIT signature\n" |
1054 | " <start> - addr of key blob\n" | 1054 | " <start> - addr of key blob\n" |
1055 | " default gd->fdt_blob\n" | 1055 | " default gd->fdt_blob\n" |
1056 | #endif | 1056 | #endif |
1057 | "NOTE: Dereference aliases by omiting the leading '/', " | 1057 | "NOTE: Dereference aliases by omiting the leading '/', " |
1058 | "e.g. fdt print ethernet0."; | 1058 | "e.g. fdt print ethernet0."; |
1059 | #endif | 1059 | #endif |
1060 | 1060 | ||
1061 | U_BOOT_CMD( | 1061 | U_BOOT_CMD( |
1062 | fdt, 255, 0, do_fdt, | 1062 | fdt, 255, 0, do_fdt, |
1063 | "flattened device tree utility commands", fdt_help_text | 1063 | "flattened device tree utility commands", fdt_help_text |
1064 | ); | 1064 | ); |
1065 | 1065 |