Commit 05f477fa301b1c8e1b48d9411c5836c314fe59ac

Authored by Ye Li
Committed by guoyin.chen
1 parent f2d295e18b

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

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