Blame view

cmd/fdt.c 27.2 KB
781e09ee6   Gerald Van Baren   Add a flattened d...
1
2
3
4
5
6
7
  /*
   * (C) Copyright 2007
   * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
   * Based on code written by:
   *   Pantelis Antoniou <pantelis.antoniou@gmail.com> and
   *   Matthew McClintock <msm@freescale.com>
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
8
   * SPDX-License-Identifier:	GPL-2.0+
781e09ee6   Gerald Van Baren   Add a flattened d...
9
10
11
12
13
14
   */
  
  #include <common.h>
  #include <command.h>
  #include <linux/ctype.h>
  #include <linux/types.h>
781e09ee6   Gerald Van Baren   Add a flattened d...
15
  #include <asm/global_data.h>
b08c8c487   Masahiro Yamada   libfdt: move head...
16
  #include <linux/libfdt.h>
64dbbd40c   Gerald Van Baren   Moved fdt command...
17
  #include <fdt_support.h>
0eb25b619   Joe Hershberger   common: Make sure...
18
  #include <mapmem.h>
a92fd6577   Simon Glass   sandbox: fdt: Sup...
19
  #include <asm/io.h>
781e09ee6   Gerald Van Baren   Add a flattened d...
20
21
  
  #define MAX_LEVEL	32		/* how deeply nested we will go */
fd61e55dd   Gerald Van Baren   Create new fdt bo...
22
  #define SCRATCHPAD	1024		/* bytes of scratchpad memory */
5d927b428   Simon Glass   Kconfig: Drop CON...
23
  #define CMD_FDT_MAX_DUMP 64
781e09ee6   Gerald Van Baren   Add a flattened d...
24
25
26
27
28
  
  /*
   * Global data (for the gd->bd)
   */
  DECLARE_GLOBAL_DATA_PTR;
d14da9130   Simon Glass   fdt: Add a parame...
29
  static int fdt_valid(struct fdt_header **blobp);
54841ab50   Wolfgang Denk   Make sure that ar...
30
  static int fdt_parse_prop(char *const*newval, int count, char *data, int *len);
dbaf07ce6   Kumar Gala   Fix warnings from...
31
  static int fdt_print(const char *pathp, char *prop, int depth);
bc80295b6   Joe Hershberger   fdt: Add get comm...
32
  static int is_printable_string(const void *data, int len);
781e09ee6   Gerald Van Baren   Add a flattened d...
33

781e09ee6   Gerald Van Baren   Add a flattened d...
34
  /*
ae9e97fa9   Gerald Van Baren   libfdt: Move the ...
35
36
37
   * The working_fdt points to our working flattened device tree.
   */
  struct fdt_header *working_fdt;
90fbee3e4   Joe Hershberger   cmd_fdt: Actually...
38
  void set_working_fdt_addr(ulong addr)
54f9c8669   Kumar Gala   bootm: Set workin...
39
  {
a92fd6577   Simon Glass   sandbox: fdt: Sup...
40
  	void *buf;
90fbee3e4   Joe Hershberger   cmd_fdt: Actually...
41
  	buf = map_sysmem(addr, 0);
a92fd6577   Simon Glass   sandbox: fdt: Sup...
42
  	working_fdt = buf;
018f53032   Simon Glass   env: Rename commo...
43
  	env_set_hex("fdtaddr", addr);
54f9c8669   Kumar Gala   bootm: Set workin...
44
  }
ae9e97fa9   Gerald Van Baren   libfdt: Move the ...
45
  /*
bc80295b6   Joe Hershberger   fdt: Add get comm...
46
47
   * Get a value from the fdt and format it to be set in the environment
   */
382bee57f   Simon Glass   env: Rename seten...
48
  static int fdt_value_env_set(const void *nodep, int len, const char *var)
bc80295b6   Joe Hershberger   fdt: Add get comm...
49
50
  {
  	if (is_printable_string(nodep, len))
382bee57f   Simon Glass   env: Rename seten...
51
  		env_set(var, (void *)nodep);
bc80295b6   Joe Hershberger   fdt: Add get comm...
52
53
  	else if (len == 4) {
  		char buf[11];
b05bf6c75   Andreas Färber   cmd/fdt: Make fdt...
54
  		sprintf(buf, "0x%08X", fdt32_to_cpu(*(fdt32_t *)nodep));
382bee57f   Simon Glass   env: Rename seten...
55
  		env_set(var, buf);
bc80295b6   Joe Hershberger   fdt: Add get comm...
56
57
58
59
60
61
62
63
  	} else if (len%4 == 0 && len <= 20) {
  		/* Needed to print things like sha1 hashes. */
  		char buf[41];
  		int i;
  
  		for (i = 0; i < len; i += sizeof(unsigned int))
  			sprintf(buf + (i * 2), "%08x",
  				*(unsigned int *)(nodep + i));
382bee57f   Simon Glass   env: Rename seten...
64
  		env_set(var, buf);
bc80295b6   Joe Hershberger   fdt: Add get comm...
65
66
67
68
69
70
71
72
73
  	} else {
  		printf("error: unprintable value
  ");
  		return 1;
  	}
  	return 0;
  }
  
  /*
781e09ee6   Gerald Van Baren   Add a flattened d...
74
75
   * Flattened Device Tree command, see the help for parameter definitions.
   */
088f1b199   Kim Phillips   common/cmd_*.c: s...
76
  static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
781e09ee6   Gerald Van Baren   Add a flattened d...
77
  {
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
78
  	if (argc < 2)
4c12eeb8b   Simon Glass   Convert cmd_usage...
79
  		return CMD_RET_USAGE;
781e09ee6   Gerald Van Baren   Add a flattened d...
80

47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
81
  	/*
781e09ee6   Gerald Van Baren   Add a flattened d...
82
  	 * Set the address of the fdt
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
83
  	 */
f0ed68e21   Maxime Ripard   cmd: fdt: Narrow ...
84
  	if (strncmp(argv[1], "ad", 2) == 0) {
54f9c8669   Kumar Gala   bootm: Set workin...
85
  		unsigned long addr;
4b5786550   Simon Glass   fdt: Allow fdt co...
86
87
  		int control = 0;
  		struct fdt_header *blob;
781e09ee6   Gerald Van Baren   Add a flattened d...
88
89
90
  		/*
  		 * Set the address [and length] of the fdt.
  		 */
4b5786550   Simon Glass   fdt: Allow fdt co...
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  		argc -= 2;
  		argv += 2;
  /* Temporary #ifdef - some archs don't have fdt_blob yet */
  #ifdef CONFIG_OF_CONTROL
  		if (argc && !strcmp(*argv, "-c")) {
  			control = 1;
  			argc--;
  			argv++;
  		}
  #endif
  		if (argc == 0) {
  			if (control)
  				blob = (struct fdt_header *)gd->fdt_blob;
  			else
  				blob = working_fdt;
  			if (!blob || !fdt_valid(&blob))
7dbc38ad9   Kumar Gala   fdt: fdt addr w/o...
107
  				return 1;
4b5786550   Simon Glass   fdt: Allow fdt co...
108
109
  			printf("The address of the fdt is %#08lx
  ",
c71a0164d   Joe Hershberger   cmd_fdt: Print th...
110
  			       control ? (ulong)map_to_sysmem(blob) :
bfebc8c96   Simon Glass   env: Rename geten...
111
  					env_get_hex("fdtaddr", 0));
7dbc38ad9   Kumar Gala   fdt: fdt addr w/o...
112
113
  			return 0;
  		}
4b5786550   Simon Glass   fdt: Allow fdt co...
114
  		addr = simple_strtoul(argv[0], NULL, 16);
a92fd6577   Simon Glass   sandbox: fdt: Sup...
115
  		blob = map_sysmem(addr, 0);
4b5786550   Simon Glass   fdt: Allow fdt co...
116
  		if (!fdt_valid(&blob))
781e09ee6   Gerald Van Baren   Add a flattened d...
117
  			return 1;
4b5786550   Simon Glass   fdt: Allow fdt co...
118
119
120
  		if (control)
  			gd->fdt_blob = blob;
  		else
90fbee3e4   Joe Hershberger   cmd_fdt: Actually...
121
  			set_working_fdt_addr(addr);
781e09ee6   Gerald Van Baren   Add a flattened d...
122

4b5786550   Simon Glass   fdt: Allow fdt co...
123
  		if (argc >= 2) {
781e09ee6   Gerald Van Baren   Add a flattened d...
124
125
126
127
128
  			int  len;
  			int  err;
  			/*
  			 * Optional new length
  			 */
4b5786550   Simon Glass   fdt: Allow fdt co...
129
130
  			len = simple_strtoul(argv[1], NULL, 16);
  			if (len < fdt_totalsize(blob)) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
131
132
133
  				printf ("New length %d < existing length %d, "
  					"ignoring.
  ",
4b5786550   Simon Glass   fdt: Allow fdt co...
134
  					len, fdt_totalsize(blob));
781e09ee6   Gerald Van Baren   Add a flattened d...
135
136
137
138
  			} else {
  				/*
  				 * Open in place with a new length.
  				 */
4b5786550   Simon Glass   fdt: Allow fdt co...
139
  				err = fdt_open_into(blob, blob, len);
781e09ee6   Gerald Van Baren   Add a flattened d...
140
  				if (err != 0) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
141
142
143
  					printf ("libfdt fdt_open_into(): %s
  ",
  						fdt_strerror(err));
781e09ee6   Gerald Van Baren   Add a flattened d...
144
145
146
  				}
  			}
  		}
e02c94587   Marek Vasut   fdt: Check if the...
147
148
149
150
151
152
153
154
155
156
157
158
159
  		return CMD_RET_SUCCESS;
  	}
  
  	if (!working_fdt) {
  		puts(
  			"No FDT memory address configured. Please configure
  "
  			"the FDT address via \"fdt addr <address>\" command.
  "
  			"Aborting!
  ");
  		return CMD_RET_FAILURE;
  	}
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
160
  	/*
e489b9c07   Kim Phillips   fdt: unshadow glo...
161
  	 * Move the working_fdt
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
162
  	 */
e02c94587   Marek Vasut   fdt: Check if the...
163
  	if (strncmp(argv[1], "mo", 2) == 0) {
781e09ee6   Gerald Van Baren   Add a flattened d...
164
165
166
  		struct fdt_header *newaddr;
  		int  len;
  		int  err;
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
167
  		if (argc < 4)
4c12eeb8b   Simon Glass   Convert cmd_usage...
168
  			return CMD_RET_USAGE;
781e09ee6   Gerald Van Baren   Add a flattened d...
169
170
171
172
  
  		/*
  		 * Set the address and length of the fdt.
  		 */
e489b9c07   Kim Phillips   fdt: unshadow glo...
173
  		working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
d14da9130   Simon Glass   fdt: Add a parame...
174
  		if (!fdt_valid(&working_fdt))
781e09ee6   Gerald Van Baren   Add a flattened d...
175
  			return 1;
781e09ee6   Gerald Van Baren   Add a flattened d...
176

addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
177
  		newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);
6be07cc1c   Gerald Van Baren   Improve fdt move ...
178
179
180
181
182
183
  
  		/*
  		 * If the user specifies a length, use that.  Otherwise use the
  		 * current length.
  		 */
  		if (argc <= 4) {
e489b9c07   Kim Phillips   fdt: unshadow glo...
184
  			len = fdt_totalsize(working_fdt);
6be07cc1c   Gerald Van Baren   Improve fdt move ...
185
186
  		} else {
  			len = simple_strtoul(argv[4], NULL, 16);
e489b9c07   Kim Phillips   fdt: unshadow glo...
187
  			if (len < fdt_totalsize(working_fdt)) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
188
189
190
  				printf ("New length 0x%X < existing length "
  					"0x%X, aborting.
  ",
e489b9c07   Kim Phillips   fdt: unshadow glo...
191
  					len, fdt_totalsize(working_fdt));
6be07cc1c   Gerald Van Baren   Improve fdt move ...
192
193
  				return 1;
  			}
781e09ee6   Gerald Van Baren   Add a flattened d...
194
195
196
197
198
  		}
  
  		/*
  		 * Copy to the new location.
  		 */
e489b9c07   Kim Phillips   fdt: unshadow glo...
199
  		err = fdt_open_into(working_fdt, newaddr, len);
781e09ee6   Gerald Van Baren   Add a flattened d...
200
  		if (err != 0) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
201
202
203
  			printf ("libfdt fdt_open_into(): %s
  ",
  				fdt_strerror(err));
781e09ee6   Gerald Van Baren   Add a flattened d...
204
205
  			return 1;
  		}
e489b9c07   Kim Phillips   fdt: unshadow glo...
206
  		working_fdt = newaddr;
f7f191ee4   Fabien Parent   cmd/fdt: fix unca...
207
208
209
210
  #ifdef CONFIG_OF_SYSTEM_SETUP
  	/* Call the board-specific fixup routine */
  	} else if (strncmp(argv[1], "sys", 3) == 0) {
  		int err = ft_system_setup(working_fdt, gd->bd);
781e09ee6   Gerald Van Baren   Add a flattened d...
211

f7f191ee4   Fabien Parent   cmd/fdt: fix unca...
212
213
214
215
216
217
218
  		if (err) {
  			printf("Failed to add system information to FDT: %s
  ",
  			       fdt_strerror(err));
  			return CMD_RET_FAILURE;
  		}
  #endif
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
219
  	/*
25114033a   Gerald Van Baren   FDT command impro...
220
  	 * Make a new node
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
221
  	 */
2fb698bf5   Gerald Van Baren   Use strncmp() for...
222
  	} else if (strncmp(argv[1], "mk", 2) == 0) {
25114033a   Gerald Van Baren   FDT command impro...
223
224
225
226
227
228
229
230
  		char *pathp;		/* path */
  		char *nodep;		/* new node to add */
  		int  nodeoffset;	/* node offset from libfdt */
  		int  err;
  
  		/*
  		 * Parameters: Node path, new node to be appended to the path.
  		 */
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
231
  		if (argc < 4)
4c12eeb8b   Simon Glass   Convert cmd_usage...
232
  			return CMD_RET_USAGE;
25114033a   Gerald Van Baren   FDT command impro...
233
234
235
  
  		pathp = argv[2];
  		nodep = argv[3];
e489b9c07   Kim Phillips   fdt: unshadow glo...
236
  		nodeoffset = fdt_path_offset (working_fdt, pathp);
25114033a   Gerald Van Baren   FDT command impro...
237
238
239
240
  		if (nodeoffset < 0) {
  			/*
  			 * Not found or something else bad happened.
  			 */
8d04f02f6   Kumar Gala   Update libfdt fro...
241
242
  			printf ("libfdt fdt_path_offset() returned %s
  ",
06e19a077   Gerald Van Baren   For fdt_find_node...
243
  				fdt_strerror(nodeoffset));
25114033a   Gerald Van Baren   FDT command impro...
244
245
  			return 1;
  		}
e489b9c07   Kim Phillips   fdt: unshadow glo...
246
  		err = fdt_add_subnode(working_fdt, nodeoffset, nodep);
25114033a   Gerald Van Baren   FDT command impro...
247
  		if (err < 0) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
248
249
250
  			printf ("libfdt fdt_add_subnode(): %s
  ",
  				fdt_strerror(err));
25114033a   Gerald Van Baren   FDT command impro...
251
252
  			return 1;
  		}
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
253
  	/*
e489b9c07   Kim Phillips   fdt: unshadow glo...
254
  	 * Set the value of a property in the working_fdt.
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
255
  	 */
25114033a   Gerald Van Baren   FDT command impro...
256
  	} else if (argv[1][0] == 's') {
781e09ee6   Gerald Van Baren   Add a flattened d...
257
  		char *pathp;		/* path */
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
258
  		char *prop;		/* property */
781e09ee6   Gerald Van Baren   Add a flattened d...
259
  		int  nodeoffset;	/* node offset from libfdt */
6dfd65f81   Bernhard Messerklinger   cmd/fdt.c align d...
260
  		static char data[SCRATCHPAD] __aligned(4);/* property storage */
9620d8725   Hannes Schmelzer   cmd/fdt: support ...
261
  		const void *ptmp;
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
262
263
  		int  len;		/* new length of the property */
  		int  ret;		/* return value */
781e09ee6   Gerald Van Baren   Add a flattened d...
264
265
  
  		/*
ea6d8be15   Gerald Van Baren   Support setting F...
266
  		 * Parameters: Node path, property, optional value.
781e09ee6   Gerald Van Baren   Add a flattened d...
267
  		 */
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
268
  		if (argc < 4)
4c12eeb8b   Simon Glass   Convert cmd_usage...
269
  			return CMD_RET_USAGE;
781e09ee6   Gerald Van Baren   Add a flattened d...
270
271
272
  
  		pathp  = argv[2];
  		prop   = argv[3];
781e09ee6   Gerald Van Baren   Add a flattened d...
273

e489b9c07   Kim Phillips   fdt: unshadow glo...
274
  		nodeoffset = fdt_path_offset (working_fdt, pathp);
25114033a   Gerald Van Baren   FDT command impro...
275
  		if (nodeoffset < 0) {
781e09ee6   Gerald Van Baren   Add a flattened d...
276
  			/*
25114033a   Gerald Van Baren   FDT command impro...
277
  			 * Not found or something else bad happened.
781e09ee6   Gerald Van Baren   Add a flattened d...
278
  			 */
8d04f02f6   Kumar Gala   Update libfdt fro...
279
280
  			printf ("libfdt fdt_path_offset() returned %s
  ",
06e19a077   Gerald Van Baren   For fdt_find_node...
281
  				fdt_strerror(nodeoffset));
781e09ee6   Gerald Van Baren   Add a flattened d...
282
  			return 1;
25114033a   Gerald Van Baren   FDT command impro...
283
  		}
25114033a   Gerald Van Baren   FDT command impro...
284

9620d8725   Hannes Schmelzer   cmd/fdt: support ...
285
286
287
288
289
290
291
292
293
294
  		if (argc == 4) {
  			len = 0;
  		} else {
  			ptmp = fdt_getprop(working_fdt, nodeoffset, prop, &len);
  			if (len > SCRATCHPAD) {
  				printf("prop (%d) doesn't fit in scratchpad!
  ",
  				       len);
  				return 1;
  			}
cee8c35d1   Hannes Schmelzer   fdt: fix 'prop (....
295
296
  			if (ptmp != NULL)
  				memcpy(data, ptmp, len);
9620d8725   Hannes Schmelzer   cmd/fdt: support ...
297
298
299
300
  			ret = fdt_parse_prop(&argv[4], argc - 4, data, &len);
  			if (ret != 0)
  				return ret;
  		}
e489b9c07   Kim Phillips   fdt: unshadow glo...
301
  		ret = fdt_setprop(working_fdt, nodeoffset, prop, data, len);
25114033a   Gerald Van Baren   FDT command impro...
302
303
304
305
  		if (ret < 0) {
  			printf ("libfdt fdt_setprop(): %s
  ", fdt_strerror(ret));
  			return 1;
781e09ee6   Gerald Van Baren   Add a flattened d...
306
  		}
bc80295b6   Joe Hershberger   fdt: Add get comm...
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  	/********************************************************************
  	 * Get the value of a property in the working_fdt.
  	 ********************************************************************/
  	} else if (argv[1][0] == 'g') {
  		char *subcmd;		/* sub-command */
  		char *pathp;		/* path */
  		char *prop;		/* property */
  		char *var;		/* variable to store result */
  		int  nodeoffset;	/* node offset from libfdt */
  		const void *nodep;	/* property node pointer */
  		int  len = 0;		/* new length of the property */
  
  		/*
  		 * Parameters: Node path, property, optional value.
  		 */
  		if (argc < 5)
  			return CMD_RET_USAGE;
  
  		subcmd = argv[2];
  
  		if (argc < 6 && subcmd[0] != 's')
  			return CMD_RET_USAGE;
  
  		var    = argv[3];
  		pathp  = argv[4];
  		prop   = argv[5];
  
  		nodeoffset = fdt_path_offset(working_fdt, pathp);
  		if (nodeoffset < 0) {
  			/*
  			 * Not found or something else bad happened.
  			 */
  			printf("libfdt fdt_path_offset() returned %s
  ",
  				fdt_strerror(nodeoffset));
  			return 1;
  		}
  
  		if (subcmd[0] == 'n' || (subcmd[0] == 's' && argc == 5)) {
  			int reqIndex = -1;
  			int startDepth = fdt_node_depth(
  				working_fdt, nodeoffset);
  			int curDepth = startDepth;
  			int curIndex = -1;
  			int nextNodeOffset = fdt_next_node(
  				working_fdt, nodeoffset, &curDepth);
  
  			if (subcmd[0] == 'n')
  				reqIndex = simple_strtoul(argv[5], NULL, 16);
  
  			while (curDepth > startDepth) {
  				if (curDepth == startDepth + 1)
  					curIndex++;
  				if (subcmd[0] == 'n' && curIndex == reqIndex) {
382bee57f   Simon Glass   env: Rename seten...
361
  					const char *node_name;
bc80295b6   Joe Hershberger   fdt: Add get comm...
362

382bee57f   Simon Glass   env: Rename seten...
363
364
365
366
  					node_name = fdt_get_name(working_fdt,
  								 nextNodeOffset,
  								 NULL);
  					env_set(var, node_name);
bc80295b6   Joe Hershberger   fdt: Add get comm...
367
368
369
370
371
372
373
374
375
  					return 0;
  				}
  				nextNodeOffset = fdt_next_node(
  					working_fdt, nextNodeOffset, &curDepth);
  				if (nextNodeOffset < 0)
  					break;
  			}
  			if (subcmd[0] == 's') {
  				/* get the num nodes at this level */
018f53032   Simon Glass   env: Rename commo...
376
  				env_set_ulong(var, curIndex + 1);
bc80295b6   Joe Hershberger   fdt: Add get comm...
377
378
379
380
381
382
383
384
385
386
387
  			} else {
  				/* node index not found */
  				printf("libfdt node not found
  ");
  				return 1;
  			}
  		} else {
  			nodep = fdt_getprop(
  				working_fdt, nodeoffset, prop, &len);
  			if (len == 0) {
  				/* no property value */
382bee57f   Simon Glass   env: Rename seten...
388
  				env_set(var, "");
bc80295b6   Joe Hershberger   fdt: Add get comm...
389
  				return 0;
72c98ed1a   Simon Glass   fdt: Add a check ...
390
  			} else if (nodep && len > 0) {
bc80295b6   Joe Hershberger   fdt: Add get comm...
391
392
  				if (subcmd[0] == 'v') {
  					int ret;
382bee57f   Simon Glass   env: Rename seten...
393
394
  					ret = fdt_value_env_set(nodep, len,
  								var);
bc80295b6   Joe Hershberger   fdt: Add get comm...
395
396
397
398
399
  					if (ret != 0)
  						return ret;
  				} else if (subcmd[0] == 'a') {
  					/* Get address */
  					char buf[11];
085b9c3a1   Tom Rini   cmd_fdt.c: Use %p...
400
  					sprintf(buf, "0x%p", nodep);
382bee57f   Simon Glass   env: Rename seten...
401
  					env_set(var, buf);
bc80295b6   Joe Hershberger   fdt: Add get comm...
402
403
404
405
406
  				} else if (subcmd[0] == 's') {
  					/* Get size */
  					char buf[11];
  
  					sprintf(buf, "0x%08X", len);
382bee57f   Simon Glass   env: Rename seten...
407
  					env_set(var, buf);
bc80295b6   Joe Hershberger   fdt: Add get comm...
408
409
410
411
412
413
414
415
416
417
  				} else
  					return CMD_RET_USAGE;
  				return 0;
  			} else {
  				printf("libfdt fdt_getprop(): %s
  ",
  					fdt_strerror(len));
  				return 1;
  			}
  		}
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
418
  	/*
781e09ee6   Gerald Van Baren   Add a flattened d...
419
  	 * Print (recursive) / List (single level)
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
420
  	 */
25114033a   Gerald Van Baren   FDT command impro...
421
  	} else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) {
781e09ee6   Gerald Van Baren   Add a flattened d...
422
423
  		int depth = MAX_LEVEL;	/* how deep to print */
  		char *pathp;		/* path */
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
424
425
  		char *prop;		/* property */
  		int  ret;		/* return value */
f738b4a75   Kumar Gala   Make no options t...
426
  		static char root[2] = "/";
781e09ee6   Gerald Van Baren   Add a flattened d...
427
428
429
430
  
  		/*
  		 * list is an alias for print, but limited to 1 level
  		 */
25114033a   Gerald Van Baren   FDT command impro...
431
  		if (argv[1][0] == 'l') {
781e09ee6   Gerald Van Baren   Add a flattened d...
432
433
434
435
436
437
438
  			depth = 1;
  		}
  
  		/*
  		 * Get the starting path.  The root node is an oddball,
  		 * the offset is zero and has no name.
  		 */
f738b4a75   Kumar Gala   Make no options t...
439
440
441
442
  		if (argc == 2)
  			pathp = root;
  		else
  			pathp = argv[2];
781e09ee6   Gerald Van Baren   Add a flattened d...
443
444
445
446
  		if (argc > 3)
  			prop = argv[3];
  		else
  			prop = NULL;
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
447
448
449
  		ret = fdt_print(pathp, prop, depth);
  		if (ret != 0)
  			return ret;
781e09ee6   Gerald Van Baren   Add a flattened d...
450

47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
451
  	/*
781e09ee6   Gerald Van Baren   Add a flattened d...
452
  	 * Remove a property/node
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
453
  	 */
2fb698bf5   Gerald Van Baren   Use strncmp() for...
454
  	} else if (strncmp(argv[1], "rm", 2) == 0) {
781e09ee6   Gerald Van Baren   Add a flattened d...
455
456
457
458
459
460
461
  		int  nodeoffset;	/* node offset from libfdt */
  		int  err;
  
  		/*
  		 * Get the path.  The root node is an oddball, the offset
  		 * is zero and has no name.
  		 */
e489b9c07   Kim Phillips   fdt: unshadow glo...
462
  		nodeoffset = fdt_path_offset (working_fdt, argv[2]);
25114033a   Gerald Van Baren   FDT command impro...
463
464
465
466
  		if (nodeoffset < 0) {
  			/*
  			 * Not found or something else bad happened.
  			 */
8d04f02f6   Kumar Gala   Update libfdt fro...
467
468
  			printf ("libfdt fdt_path_offset() returned %s
  ",
06e19a077   Gerald Van Baren   For fdt_find_node...
469
  				fdt_strerror(nodeoffset));
25114033a   Gerald Van Baren   FDT command impro...
470
  			return 1;
781e09ee6   Gerald Van Baren   Add a flattened d...
471
472
473
474
475
476
  		}
  		/*
  		 * Do the delete.  A fourth parameter means delete a property,
  		 * otherwise delete the node.
  		 */
  		if (argc > 3) {
e489b9c07   Kim Phillips   fdt: unshadow glo...
477
  			err = fdt_delprop(working_fdt, nodeoffset, argv[3]);
781e09ee6   Gerald Van Baren   Add a flattened d...
478
  			if (err < 0) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
479
480
481
  				printf("libfdt fdt_delprop():  %s
  ",
  					fdt_strerror(err));
781e09ee6   Gerald Van Baren   Add a flattened d...
482
483
484
  				return err;
  			}
  		} else {
e489b9c07   Kim Phillips   fdt: unshadow glo...
485
  			err = fdt_del_node(working_fdt, nodeoffset);
781e09ee6   Gerald Van Baren   Add a flattened d...
486
  			if (err < 0) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
487
488
489
  				printf("libfdt fdt_del_node():  %s
  ",
  					fdt_strerror(err));
781e09ee6   Gerald Van Baren   Add a flattened d...
490
491
492
  				return err;
  			}
  		}
804887e60   Kumar Gala   Add sub-commands ...
493

47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
494
  	/*
804887e60   Kumar Gala   Add sub-commands ...
495
  	 * Display header info
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
496
  	 */
804887e60   Kumar Gala   Add sub-commands ...
497
  	} else if (argv[1][0] == 'h') {
e489b9c07   Kim Phillips   fdt: unshadow glo...
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
  		u32 version = fdt_version(working_fdt);
  		printf("magic:\t\t\t0x%x
  ", fdt_magic(working_fdt));
  		printf("totalsize:\t\t0x%x (%d)
  ", fdt_totalsize(working_fdt),
  		       fdt_totalsize(working_fdt));
  		printf("off_dt_struct:\t\t0x%x
  ",
  		       fdt_off_dt_struct(working_fdt));
  		printf("off_dt_strings:\t\t0x%x
  ",
  		       fdt_off_dt_strings(working_fdt));
  		printf("off_mem_rsvmap:\t\t0x%x
  ",
  		       fdt_off_mem_rsvmap(working_fdt));
804887e60   Kumar Gala   Add sub-commands ...
513
514
  		printf("version:\t\t%d
  ", version);
e489b9c07   Kim Phillips   fdt: unshadow glo...
515
516
517
  		printf("last_comp_version:\t%d
  ",
  		       fdt_last_comp_version(working_fdt));
804887e60   Kumar Gala   Add sub-commands ...
518
519
520
  		if (version >= 2)
  			printf("boot_cpuid_phys:\t0x%x
  ",
e489b9c07   Kim Phillips   fdt: unshadow glo...
521
  				fdt_boot_cpuid_phys(working_fdt));
804887e60   Kumar Gala   Add sub-commands ...
522
523
524
  		if (version >= 3)
  			printf("size_dt_strings:\t0x%x
  ",
e489b9c07   Kim Phillips   fdt: unshadow glo...
525
  				fdt_size_dt_strings(working_fdt));
804887e60   Kumar Gala   Add sub-commands ...
526
527
528
  		if (version >= 17)
  			printf("size_dt_struct:\t\t0x%x
  ",
e489b9c07   Kim Phillips   fdt: unshadow glo...
529
530
531
532
  				fdt_size_dt_struct(working_fdt));
  		printf("number mem_rsv:\t\t0x%x
  ",
  		       fdt_num_mem_rsv(working_fdt));
804887e60   Kumar Gala   Add sub-commands ...
533
534
  		printf("
  ");
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
535
  	/*
804887e60   Kumar Gala   Add sub-commands ...
536
  	 * Set boot cpu id
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
537
  	 */
2fb698bf5   Gerald Van Baren   Use strncmp() for...
538
  	} else if (strncmp(argv[1], "boo", 3) == 0) {
804887e60   Kumar Gala   Add sub-commands ...
539
  		unsigned long tmp = simple_strtoul(argv[2], NULL, 16);
e489b9c07   Kim Phillips   fdt: unshadow glo...
540
  		fdt_set_boot_cpuid_phys(working_fdt, tmp);
804887e60   Kumar Gala   Add sub-commands ...
541

47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
542
  	/*
804887e60   Kumar Gala   Add sub-commands ...
543
  	 * memory command
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
544
  	 */
2fb698bf5   Gerald Van Baren   Use strncmp() for...
545
  	} else if (strncmp(argv[1], "me", 2) == 0) {
804887e60   Kumar Gala   Add sub-commands ...
546
547
  		uint64_t addr, size;
  		int err;
4b142febf   Heiko Schocher   common: delete CO...
548
549
  		addr = simple_strtoull(argv[2], NULL, 16);
  		size = simple_strtoull(argv[3], NULL, 16);
e489b9c07   Kim Phillips   fdt: unshadow glo...
550
  		err = fdt_fixup_memory(working_fdt, addr, size);
804887e60   Kumar Gala   Add sub-commands ...
551
552
  		if (err < 0)
  			return err;
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
553
  	/*
804887e60   Kumar Gala   Add sub-commands ...
554
  	 * mem reserve commands
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
555
  	 */
2fb698bf5   Gerald Van Baren   Use strncmp() for...
556
  	} else if (strncmp(argv[1], "rs", 2) == 0) {
804887e60   Kumar Gala   Add sub-commands ...
557
558
  		if (argv[2][0] == 'p') {
  			uint64_t addr, size;
e489b9c07   Kim Phillips   fdt: unshadow glo...
559
  			int total = fdt_num_mem_rsv(working_fdt);
804887e60   Kumar Gala   Add sub-commands ...
560
561
562
563
564
565
566
  			int j, err;
  			printf("index\t\t   start\t\t    size
  ");
  			printf("-------------------------------"
  				"-----------------
  ");
  			for (j = 0; j < total; j++) {
e489b9c07   Kim Phillips   fdt: unshadow glo...
567
  				err = fdt_get_mem_rsv(working_fdt, j, &addr, &size);
804887e60   Kumar Gala   Add sub-commands ...
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
  				if (err < 0) {
  					printf("libfdt fdt_get_mem_rsv():  %s
  ",
  							fdt_strerror(err));
  					return err;
  				}
  				printf("    %x\t%08x%08x\t%08x%08x
  ", j,
  					(u32)(addr >> 32),
  					(u32)(addr & 0xffffffff),
  					(u32)(size >> 32),
  					(u32)(size & 0xffffffff));
  			}
  		} else if (argv[2][0] == 'a') {
  			uint64_t addr, size;
  			int err;
804887e60   Kumar Gala   Add sub-commands ...
584
585
  			addr = simple_strtoull(argv[3], NULL, 16);
  			size = simple_strtoull(argv[4], NULL, 16);
e489b9c07   Kim Phillips   fdt: unshadow glo...
586
  			err = fdt_add_mem_rsv(working_fdt, addr, size);
804887e60   Kumar Gala   Add sub-commands ...
587
588
589
590
591
592
593
594
595
  
  			if (err < 0) {
  				printf("libfdt fdt_add_mem_rsv():  %s
  ",
  					fdt_strerror(err));
  				return err;
  			}
  		} else if (argv[2][0] == 'd') {
  			unsigned long idx = simple_strtoul(argv[3], NULL, 16);
e489b9c07   Kim Phillips   fdt: unshadow glo...
596
  			int err = fdt_del_mem_rsv(working_fdt, idx);
804887e60   Kumar Gala   Add sub-commands ...
597
598
599
600
601
602
603
604
605
  
  			if (err < 0) {
  				printf("libfdt fdt_del_mem_rsv():  %s
  ",
  					fdt_strerror(err));
  				return err;
  			}
  		} else {
  			/* Unrecognized command */
4c12eeb8b   Simon Glass   Convert cmd_usage...
606
  			return CMD_RET_USAGE;
804887e60   Kumar Gala   Add sub-commands ...
607
  		}
99dffca3b   Kim Phillips   fdt: allow for bu...
608
  	}
fd61e55dd   Gerald Van Baren   Create new fdt bo...
609
  #ifdef CONFIG_OF_BOARD_SETUP
99dffca3b   Kim Phillips   fdt: allow for bu...
610
  	/* Call the board-specific fixup routine */
4ba98dc26   Simon Glass   fdt: Report failu...
611
612
613
614
615
616
617
618
619
620
  	else if (strncmp(argv[1], "boa", 3) == 0) {
  		int err = ft_board_setup(working_fdt, gd->bd);
  
  		if (err) {
  			printf("Failed to update board information in FDT: %s
  ",
  			       fdt_strerror(err));
  			return CMD_RET_FAILURE;
  		}
  	}
fd61e55dd   Gerald Van Baren   Create new fdt bo...
621
  #endif
99dffca3b   Kim Phillips   fdt: allow for bu...
622
  	/* Create a chosen node */
097dd3e0a   Heiko Schocher   fdt: add "fdt che...
623
  	else if (strncmp(argv[1], "cho", 3) == 0) {
f953d99fd   Kumar Gala   fdt: added the ab...
624
  		unsigned long initrd_start = 0, initrd_end = 0;
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
625
  		if ((argc != 2) && (argc != 4))
4c12eeb8b   Simon Glass   Convert cmd_usage...
626
  			return CMD_RET_USAGE;
f953d99fd   Kumar Gala   fdt: added the ab...
627
628
629
630
631
  
  		if (argc == 4) {
  			initrd_start = simple_strtoul(argv[2], NULL, 16);
  			initrd_end = simple_strtoul(argv[3], NULL, 16);
  		}
bc6ed0f9d   Masahiro Yamada   fdt_support: dele...
632
  		fdt_chosen(working_fdt);
dbe963ae5   Masahiro Yamada   fdt_support: dele...
633
  		fdt_initrd(working_fdt, initrd_start, initrd_end);
097dd3e0a   Heiko Schocher   fdt: add "fdt che...
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
  
  #if defined(CONFIG_FIT_SIGNATURE)
  	} else if (strncmp(argv[1], "che", 3) == 0) {
  		int cfg_noffset;
  		int ret;
  		unsigned long addr;
  		struct fdt_header *blob;
  
  		if (!working_fdt)
  			return CMD_RET_FAILURE;
  
  		if (argc > 2) {
  			addr = simple_strtoul(argv[2], NULL, 16);
  			blob = map_sysmem(addr, 0);
  		} else {
  			blob = (struct fdt_header *)gd->fdt_blob;
  		}
  		if (!fdt_valid(&blob))
  			return 1;
  
  		gd->fdt_blob = blob;
  		cfg_noffset = fit_conf_get_node(working_fdt, NULL);
  		if (!cfg_noffset) {
  			printf("Could not find configuration node: %s
  ",
  			       fdt_strerror(cfg_noffset));
  			return CMD_RET_FAILURE;
  		}
  
  		ret = fit_config_verify(working_fdt, cfg_noffset);
12df2abe3   Simon Glass   Reverse the meani...
664
  		if (ret == 0)
097dd3e0a   Heiko Schocher   fdt: add "fdt che...
665
666
667
668
  			return CMD_RET_SUCCESS;
  		else
  			return CMD_RET_FAILURE;
  #endif
40afac22a   Kumar Gala   fdt: Added resize...
669
  	}
e6628ad7b   Maxime Ripard   cmd: fdt: add fdt...
670
671
672
673
674
  #ifdef CONFIG_OF_LIBFDT_OVERLAY
  	/* apply an overlay */
  	else if (strncmp(argv[1], "ap", 2) == 0) {
  		unsigned long addr;
  		struct fdt_header *blob;
082b1414e   Stefan Agner   cmd: fdt: Print e...
675
  		int ret;
e6628ad7b   Maxime Ripard   cmd: fdt: add fdt...
676
677
678
679
680
681
682
683
684
685
686
  
  		if (argc != 3)
  			return CMD_RET_USAGE;
  
  		if (!working_fdt)
  			return CMD_RET_FAILURE;
  
  		addr = simple_strtoul(argv[2], NULL, 16);
  		blob = map_sysmem(addr, 0);
  		if (!fdt_valid(&blob))
  			return CMD_RET_FAILURE;
81ecc5d92   Pantelis Antoniou   fdt: Switch to us...
687
688
689
  		/* apply method prints messages on error */
  		ret = fdt_overlay_apply_verbose(working_fdt, blob);
  		if (ret)
e6628ad7b   Maxime Ripard   cmd: fdt: add fdt...
690
691
692
  			return CMD_RET_FAILURE;
  	}
  #endif
40afac22a   Kumar Gala   fdt: Added resize...
693
694
  	/* resize the fdt */
  	else if (strncmp(argv[1], "re", 2) == 0) {
ef4768364   Hannes Schmelzer   cmd/fdt: add poss...
695
696
697
698
699
700
  		uint extrasize;
  		if (argc > 2)
  			extrasize = simple_strtoul(argv[2], NULL, 16);
  		else
  			extrasize = 0;
  		fdt_shrink_to_minimum(working_fdt, extrasize);
40afac22a   Kumar Gala   fdt: Added resize...
701
702
  	}
  	else {
99dffca3b   Kim Phillips   fdt: allow for bu...
703
  		/* Unrecognized command */
4c12eeb8b   Simon Glass   Convert cmd_usage...
704
  		return CMD_RET_USAGE;
781e09ee6   Gerald Van Baren   Add a flattened d...
705
706
707
708
  	}
  
  	return 0;
  }
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
709
  /****************************************************************************/
781e09ee6   Gerald Van Baren   Add a flattened d...
710

d14da9130   Simon Glass   fdt: Add a parame...
711
712
713
714
715
716
717
  /**
   * fdt_valid() - Check if an FDT is valid. If not, change it to NULL
   *
   * @blobp: Pointer to FDT pointer
   * @return 1 if OK, 0 if bad (in which case *blobp is set to NULL)
   */
  static int fdt_valid(struct fdt_header **blobp)
781e09ee6   Gerald Van Baren   Add a flattened d...
718
  {
d14da9130   Simon Glass   fdt: Add a parame...
719
720
  	const void *blob = *blobp;
  	int err;
64dbbd40c   Gerald Van Baren   Moved fdt command...
721

d14da9130   Simon Glass   fdt: Add a parame...
722
  	if (blob == NULL) {
64dbbd40c   Gerald Van Baren   Moved fdt command...
723
724
  		printf ("The address of the fdt is invalid (NULL).
  ");
781e09ee6   Gerald Van Baren   Add a flattened d...
725
726
  		return 0;
  	}
64dbbd40c   Gerald Van Baren   Moved fdt command...
727

d14da9130   Simon Glass   fdt: Add a parame...
728
  	err = fdt_check_header(blob);
64dbbd40c   Gerald Van Baren   Moved fdt command...
729
730
731
732
  	if (err == 0)
  		return 1;	/* valid */
  
  	if (err < 0) {
25114033a   Gerald Van Baren   FDT command impro...
733
  		printf("libfdt fdt_check_header(): %s", fdt_strerror(err));
64dbbd40c   Gerald Van Baren   Moved fdt command...
734
735
736
737
  		/*
  		 * Be more informative on bad version.
  		 */
  		if (err == -FDT_ERR_BADVERSION) {
d14da9130   Simon Glass   fdt: Add a parame...
738
  			if (fdt_version(blob) <
e489b9c07   Kim Phillips   fdt: unshadow glo...
739
  			    FDT_FIRST_SUPPORTED_VERSION) {
dc4b0b38d   Andrew Klossner   Fix printf errors.
740
  				printf (" - too old, fdt %d < %d",
d14da9130   Simon Glass   fdt: Add a parame...
741
  					fdt_version(blob),
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
742
  					FDT_FIRST_SUPPORTED_VERSION);
64dbbd40c   Gerald Van Baren   Moved fdt command...
743
  			}
d14da9130   Simon Glass   fdt: Add a parame...
744
  			if (fdt_last_comp_version(blob) >
e489b9c07   Kim Phillips   fdt: unshadow glo...
745
  			    FDT_LAST_SUPPORTED_VERSION) {
dc4b0b38d   Andrew Klossner   Fix printf errors.
746
  				printf (" - too new, fdt %d > %d",
d14da9130   Simon Glass   fdt: Add a parame...
747
  					fdt_version(blob),
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
748
  					FDT_LAST_SUPPORTED_VERSION);
64dbbd40c   Gerald Van Baren   Moved fdt command...
749
  			}
64dbbd40c   Gerald Van Baren   Moved fdt command...
750
751
752
  		}
  		printf("
  ");
d14da9130   Simon Glass   fdt: Add a parame...
753
  		*blobp = NULL;
781e09ee6   Gerald Van Baren   Add a flattened d...
754
755
756
757
  		return 0;
  	}
  	return 1;
  }
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
758
  /****************************************************************************/
781e09ee6   Gerald Van Baren   Add a flattened d...
759
760
  
  /*
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
761
   * Parse the user's input, partially heuristic.  Valid formats:
4abd844d8   Andy Fleming   Fix fdt set comma...
762
   * <0x00112233 4 05>	- an array of cells.  Numbers follow standard
53677ef18   Wolfgang Denk   Big white-space c...
763
   *			C conventions.
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
764
765
766
767
   * [00 11 22 .. nn] - byte stream
   * "string"	- If the the value doesn't start with "<" or "[", it is
   *			treated as a string.  Note that the quotes are
   *			stripped by the parser before we get the string.
4abd844d8   Andy Fleming   Fix fdt set comma...
768
   * newval: An array of strings containing the new property as specified
53677ef18   Wolfgang Denk   Big white-space c...
769
   *	on the command line
4abd844d8   Andy Fleming   Fix fdt set comma...
770
771
772
   * count: The number of strings in the array
   * data: A bytestream to be placed in the property
   * len: The length of the resulting bytestream
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
773
   */
54841ab50   Wolfgang Denk   Make sure that ar...
774
  static int fdt_parse_prop(char * const *newval, int count, char *data, int *len)
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
775
776
  {
  	char *cp;		/* temporary char pointer */
4abd844d8   Andy Fleming   Fix fdt set comma...
777
  	char *newp;		/* temporary newval char pointer */
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
778
  	unsigned long tmp;	/* holds converted values */
4abd844d8   Andy Fleming   Fix fdt set comma...
779
  	int stridx = 0;
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
780

4abd844d8   Andy Fleming   Fix fdt set comma...
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
  	*len = 0;
  	newp = newval[0];
  
  	/* An array of cells */
  	if (*newp == '<') {
  		newp++;
  		while ((*newp != '>') && (stridx < count)) {
  			/*
  			 * Keep searching until we find that last ">"
  			 * That way users don't have to escape the spaces
  			 */
  			if (*newp == '\0') {
  				newp = newval[++stridx];
  				continue;
  			}
  
  			cp = newp;
  			tmp = simple_strtoul(cp, &newp, 0);
9620d8725   Hannes Schmelzer   cmd/fdt: support ...
799
800
801
802
  			if (*cp != '?')
  				*(fdt32_t *)data = cpu_to_fdt32(tmp);
  			else
  				newp++;
4abd844d8   Andy Fleming   Fix fdt set comma...
803
804
805
806
807
  			data  += 4;
  			*len += 4;
  
  			/* If the ptr didn't advance, something went wrong */
  			if ((newp - cp) <= 0) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
808
809
810
811
812
  				printf("Sorry, I could not convert \"%s\"
  ",
  					cp);
  				return 1;
  			}
4abd844d8   Andy Fleming   Fix fdt set comma...
813
814
815
  
  			while (*newp == ' ')
  				newp++;
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
816
  		}
4abd844d8   Andy Fleming   Fix fdt set comma...
817
818
819
820
  
  		if (*newp != '>') {
  			printf("Unexpected character '%c'
  ", *newp);
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
821
822
  			return 1;
  		}
4abd844d8   Andy Fleming   Fix fdt set comma...
823
  	} else if (*newp == '[') {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
824
825
826
  		/*
  		 * Byte stream.  Convert the values.
  		 */
4abd844d8   Andy Fleming   Fix fdt set comma...
827
  		newp++;
6e748ea00   Ken MacLeod   cmd_fdt.c: fix pa...
828
  		while ((stridx < count) && (*newp != ']')) {
4abd844d8   Andy Fleming   Fix fdt set comma...
829
830
  			while (*newp == ' ')
  				newp++;
6e748ea00   Ken MacLeod   cmd_fdt.c: fix pa...
831
  			if (*newp == '\0') {
4abd844d8   Andy Fleming   Fix fdt set comma...
832
  				newp = newval[++stridx];
6e748ea00   Ken MacLeod   cmd_fdt.c: fix pa...
833
834
835
836
837
838
839
  				continue;
  			}
  			if (!isxdigit(*newp))
  				break;
  			tmp = simple_strtoul(newp, &newp, 16);
  			*data++ = tmp & 0xFF;
  			*len    = *len + 1;
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
840
  		}
4abd844d8   Andy Fleming   Fix fdt set comma...
841
  		if (*newp != ']') {
dc4b0b38d   Andrew Klossner   Fix printf errors.
842
843
  			printf("Unexpected character '%c'
  ", *newp);
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
844
845
846
847
  			return 1;
  		}
  	} else {
  		/*
6e748ea00   Ken MacLeod   cmd_fdt.c: fix pa...
848
849
850
  		 * Assume it is one or more strings.  Copy it into our
  		 * data area for convenience (including the
  		 * terminating '\0's).
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
851
  		 */
4abd844d8   Andy Fleming   Fix fdt set comma...
852
  		while (stridx < count) {
6e748ea00   Ken MacLeod   cmd_fdt.c: fix pa...
853
  			size_t length = strlen(newp) + 1;
4abd844d8   Andy Fleming   Fix fdt set comma...
854
  			strcpy(data, newp);
6e748ea00   Ken MacLeod   cmd_fdt.c: fix pa...
855
856
  			data += length;
  			*len += length;
4abd844d8   Andy Fleming   Fix fdt set comma...
857
858
  			newp = newval[++stridx];
  		}
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
859
860
861
862
863
864
865
866
  	}
  	return 0;
  }
  
  /****************************************************************************/
  
  /*
   * Heuristic to guess if this is a string or concatenated strings.
781e09ee6   Gerald Van Baren   Add a flattened d...
867
868
869
870
871
872
873
874
875
   */
  
  static int is_printable_string(const void *data, int len)
  {
  	const char *s = data;
  
  	/* zero length is not */
  	if (len == 0)
  		return 0;
8805beec8   Joe Hershberger   fdt: Identify scr...
876
877
878
879
  	/* must terminate with zero or '
  ' */
  	if (s[len - 1] != '\0' && s[len - 1] != '
  ')
781e09ee6   Gerald Van Baren   Add a flattened d...
880
881
882
  		return 0;
  
  	/* printable or a null byte (concatenated strings) */
8805beec8   Joe Hershberger   fdt: Identify scr...
883
  	while (((*s == '\0') || isprint(*s) || isspace(*s)) && (len > 0)) {
781e09ee6   Gerald Van Baren   Add a flattened d...
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
  		/*
  		 * If we see a null, there are three possibilities:
  		 * 1) If len == 1, it is the end of the string, printable
  		 * 2) Next character also a null, not printable.
  		 * 3) Next character not a null, continue to check.
  		 */
  		if (s[0] == '\0') {
  			if (len == 1)
  				return 1;
  			if (s[1] == '\0')
  				return 0;
  		}
  		s++;
  		len--;
  	}
  
  	/* Not the null termination, or not done yet: not printable */
  	if (*s != '\0' || (len != 0))
  		return 0;
  
  	return 1;
  }
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
906
907
908
909
910
911
  
  /*
   * Print the property in the best format, a heuristic guess.  Print as
   * a string, concatenated strings, a byte, word, double word, or (if all
   * else fails) it is printed as a stream of bytes.
   */
781e09ee6   Gerald Van Baren   Add a flattened d...
912
913
914
  static void print_data(const void *data, int len)
  {
  	int j;
781e09ee6   Gerald Van Baren   Add a flattened d...
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
  
  	/* no data, don't print */
  	if (len == 0)
  		return;
  
  	/*
  	 * It is a string, but it may have multiple strings (embedded '\0's).
  	 */
  	if (is_printable_string(data, len)) {
  		puts("\"");
  		j = 0;
  		while (j < len) {
  			if (j > 0)
  				puts("\", \"");
  			puts(data);
  			j    += strlen(data) + 1;
  			data += strlen(data) + 1;
  		}
  		puts("\"");
  		return;
  	}
4abd844d8   Andy Fleming   Fix fdt set comma...
936
  	if ((len %4) == 0) {
5d927b428   Simon Glass   Kconfig: Drop CON...
937
  		if (len > CMD_FDT_MAX_DUMP)
085b9c3a1   Tom Rini   cmd_fdt.c: Use %p...
938
  			printf("* 0x%p [0x%08x]", data, len);
f0a29d433   Joe Hershberger   fdt: Limit printe...
939
  		else {
088f1b199   Kim Phillips   common/cmd_*.c: s...
940
  			const __be32 *p;
f0a29d433   Joe Hershberger   fdt: Limit printe...
941
942
943
944
945
946
947
  
  			printf("<");
  			for (j = 0, p = data; j < len/4; j++)
  				printf("0x%08x%s", fdt32_to_cpu(p[j]),
  					j < (len/4 - 1) ? " " : "");
  			printf(">");
  		}
4abd844d8   Andy Fleming   Fix fdt set comma...
948
  	} else { /* anything else... hexdump */
5d927b428   Simon Glass   Kconfig: Drop CON...
949
  		if (len > CMD_FDT_MAX_DUMP)
085b9c3a1   Tom Rini   cmd_fdt.c: Use %p...
950
  			printf("* 0x%p [0x%08x]", data, len);
f0a29d433   Joe Hershberger   fdt: Limit printe...
951
952
953
954
955
956
957
958
  		else {
  			const u8 *s;
  
  			printf("[");
  			for (j = 0, s = data; j < len; j++)
  				printf("%02x%s", s[j], j < len - 1 ? " " : "");
  			printf("]");
  		}
781e09ee6   Gerald Van Baren   Add a flattened d...
959
960
  	}
  }
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
961
962
963
  /****************************************************************************/
  
  /*
e489b9c07   Kim Phillips   fdt: unshadow glo...
964
   * Recursively print (a portion of) the working_fdt.  The depth parameter
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
965
966
   * determines how deeply nested the fdt is printed.
   */
dbaf07ce6   Kumar Gala   Fix warnings from...
967
  static int fdt_print(const char *pathp, char *prop, int depth)
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
968
  {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
969
970
971
  	static char tabs[MAX_LEVEL+1] =
  		"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
  		"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
dbaf07ce6   Kumar Gala   Fix warnings from...
972
  	const void *nodep;	/* property node pointer */
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
973
974
975
976
977
  	int  nodeoffset;	/* node offset from libfdt */
  	int  nextoffset;	/* next node offset from libfdt */
  	uint32_t tag;		/* tag */
  	int  len;		/* length of the property */
  	int  level = 0;		/* keep track of nesting level */
916235281   Gerald Van Baren   Fix fdt printing ...
978
  	const struct fdt_property *fdt_prop;
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
979

e489b9c07   Kim Phillips   fdt: unshadow glo...
980
  	nodeoffset = fdt_path_offset (working_fdt, pathp);
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
981
982
983
984
  	if (nodeoffset < 0) {
  		/*
  		 * Not found or something else bad happened.
  		 */
8d04f02f6   Kumar Gala   Update libfdt fro...
985
986
  		printf ("libfdt fdt_path_offset() returned %s
  ",
06e19a077   Gerald Van Baren   For fdt_find_node...
987
  			fdt_strerror(nodeoffset));
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
988
989
990
991
992
993
994
  		return 1;
  	}
  	/*
  	 * The user passed in a property as well as node path.
  	 * Print only the given property and then return.
  	 */
  	if (prop) {
e489b9c07   Kim Phillips   fdt: unshadow glo...
995
  		nodep = fdt_getprop (working_fdt, nodeoffset, prop, &len);
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
996
997
998
999
1000
  		if (len == 0) {
  			/* no property value */
  			printf("%s %s
  ", pathp, prop);
  			return 0;
9f9526727   Simon Glass   fdt: Add a check ...
1001
  		} else if (nodep && len > 0) {
28f384b17   Gerald Van Baren   Add spaces around...
1002
  			printf("%s = ", prop);
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
  			print_data (nodep, len);
  			printf("
  ");
  			return 0;
  		} else {
  			printf ("libfdt fdt_getprop(): %s
  ",
  				fdt_strerror(len));
  			return 1;
  		}
  	}
  
  	/*
  	 * The user passed in a node path and no property,
  	 * print the node and all subnodes.
  	 */
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1019
  	while(level >= 0) {
e489b9c07   Kim Phillips   fdt: unshadow glo...
1020
  		tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset);
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1021
1022
  		switch(tag) {
  		case FDT_BEGIN_NODE:
e489b9c07   Kim Phillips   fdt: unshadow glo...
1023
  			pathp = fdt_get_name(working_fdt, nodeoffset, NULL);
916235281   Gerald Van Baren   Fix fdt printing ...
1024
1025
1026
1027
1028
  			if (level <= depth) {
  				if (pathp == NULL)
  					pathp = "/* NULL pointer error */";
  				if (*pathp == '\0')
  					pathp = "/";	/* root is nameless */
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1029
1030
1031
  				printf("%s%s {
  ",
  					&tabs[MAX_LEVEL - level], pathp);
916235281   Gerald Van Baren   Fix fdt printing ...
1032
  			}
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1033
  			level++;
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1034
  			if (level >= MAX_LEVEL) {
916235281   Gerald Van Baren   Fix fdt printing ...
1035
1036
  				printf("Nested too deep, aborting.
  ");
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1037
1038
1039
1040
1041
  				return 1;
  			}
  			break;
  		case FDT_END_NODE:
  			level--;
916235281   Gerald Van Baren   Fix fdt printing ...
1042
  			if (level <= depth)
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1043
1044
1045
1046
1047
1048
1049
  				printf("%s};
  ", &tabs[MAX_LEVEL - level]);
  			if (level == 0) {
  				level = -1;		/* exit the loop */
  			}
  			break;
  		case FDT_PROP:
e489b9c07   Kim Phillips   fdt: unshadow glo...
1050
  			fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset,
916235281   Gerald Van Baren   Fix fdt printing ...
1051
  					sizeof(*fdt_prop));
e489b9c07   Kim Phillips   fdt: unshadow glo...
1052
  			pathp    = fdt_string(working_fdt,
916235281   Gerald Van Baren   Fix fdt printing ...
1053
1054
1055
  					fdt32_to_cpu(fdt_prop->nameoff));
  			len      = fdt32_to_cpu(fdt_prop->len);
  			nodep    = fdt_prop->data;
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1056
1057
1058
1059
1060
1061
1062
  			if (len < 0) {
  				printf ("libfdt fdt_getprop(): %s
  ",
  					fdt_strerror(len));
  				return 1;
  			} else if (len == 0) {
  				/* the property has no value */
916235281   Gerald Van Baren   Fix fdt printing ...
1063
  				if (level <= depth)
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1064
1065
1066
1067
1068
  					printf("%s%s;
  ",
  						&tabs[MAX_LEVEL - level],
  						pathp);
  			} else {
916235281   Gerald Van Baren   Fix fdt printing ...
1069
  				if (level <= depth) {
28f384b17   Gerald Van Baren   Add spaces around...
1070
  					printf("%s%s = ",
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1071
1072
1073
1074
1075
1076
1077
1078
1079
  						&tabs[MAX_LEVEL - level],
  						pathp);
  					print_data (nodep, len);
  					printf(";
  ");
  				}
  			}
  			break;
  		case FDT_NOP:
dc4b0b38d   Andrew Klossner   Fix printf errors.
1080
1081
  			printf("%s/* NOP */
  ", &tabs[MAX_LEVEL - level]);
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1082
1083
1084
1085
  			break;
  		case FDT_END:
  			return 1;
  		default:
916235281   Gerald Van Baren   Fix fdt printing ...
1086
  			if (level <= depth)
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1087
1088
1089
1090
1091
1092
1093
1094
  				printf("Unknown tag 0x%08X
  ", tag);
  			return 1;
  		}
  		nodeoffset = nextoffset;
  	}
  	return 0;
  }
781e09ee6   Gerald Van Baren   Add a flattened d...
1095
  /********************************************************************/
088f1b199   Kim Phillips   common/cmd_*.c: s...
1096
1097
  #ifdef CONFIG_SYS_LONGHELP
  static char fdt_help_text[] =
4b5786550   Simon Glass   fdt: Allow fdt co...
1098
1099
  	"addr [-c]  <addr> [<length>]   - Set the [control] fdt location to <addr>
  "
e6628ad7b   Maxime Ripard   cmd: fdt: add fdt...
1100
1101
1102
1103
  #ifdef CONFIG_OF_LIBFDT_OVERLAY
  	"fdt apply <addr>                    - Apply overlay to the DT
  "
  #endif
fd61e55dd   Gerald Van Baren   Create new fdt bo...
1104
1105
1106
1107
  #ifdef CONFIG_OF_BOARD_SETUP
  	"fdt boardsetup                      - Do board-specific set up
  "
  #endif
c654b5172   Simon Glass   fdt: Add ft_syste...
1108
1109
1110
1111
  #ifdef CONFIG_OF_SYSTEM_SETUP
  	"fdt systemsetup                     - Do system-specific set up
  "
  #endif
238cb7a42   Gerald Van Baren   Improve the FDT h...
1112
1113
  	"fdt move   <fdt> <newaddr> <length> - Copy the fdt to <addr> and make it active
  "
ef4768364   Hannes Schmelzer   cmd/fdt: add poss...
1114
1115
  	"fdt resize [<extrasize>]            - Resize fdt to size + padding to 4k addr + some optional <extrasize> if needed
  "
781e09ee6   Gerald Van Baren   Add a flattened d...
1116
1117
1118
1119
  	"fdt print  <path> [<prop>]          - Recursive print starting at <path>
  "
  	"fdt list   <path> [<prop>]          - Print one level starting at <path>
  "
bc80295b6   Joe Hershberger   fdt: Add get comm...
1120
1121
1122
1123
1124
1125
1126
1127
  	"fdt get value <var> <path> <prop>   - Get <property> and store in <var>
  "
  	"fdt get name <var> <path> <index>   - Get name of node <index> and store in <var>
  "
  	"fdt get addr <var> <path> <prop>    - Get start address of <property> and store in <var>
  "
  	"fdt get size <var> <path> [<prop>]  - Get size of [<property>] or num nodes and store in <var>
  "
781e09ee6   Gerald Van Baren   Add a flattened d...
1128
1129
1130
1131
1132
1133
  	"fdt set    <path> <prop> [<val>]    - Set <property> [to <val>]
  "
  	"fdt mknode <path> <node>            - Create a new node after <path>
  "
  	"fdt rm     <path> [<prop>]          - Delete the node or <property>
  "
804887e60   Kumar Gala   Add sub-commands ...
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
  	"fdt header                          - Display header info
  "
  	"fdt bootcpu <id>                    - Set boot cpuid
  "
  	"fdt memory <addr> <size>            - Add/Update memory node
  "
  	"fdt rsvmem print                    - Show current mem reserves
  "
  	"fdt rsvmem add <addr> <size>        - Add a mem reserve
  "
  	"fdt rsvmem delete <index>           - Delete a mem reserves
  "
f953d99fd   Kumar Gala   fdt: added the ab...
1146
1147
1148
1149
  	"fdt chosen [<start> <end>]          - Add/update the /chosen branch in the tree
  "
  	"                                        <start>/<end> - initrd start/end addr
  "
097dd3e0a   Heiko Schocher   fdt: add "fdt che...
1150
1151
1152
1153
1154
1155
1156
1157
  #if defined(CONFIG_FIT_SIGNATURE)
  	"fdt checksign [<addr>]              - check FIT signature
  "
  	"                                        <start> - addr of key blob
  "
  	"                                                  default gd->fdt_blob
  "
  #endif
1cc0a9f49   Robert P. J. Day   Fix various typos...
1158
  	"NOTE: Dereference aliases by omitting the leading '/', "
088f1b199   Kim Phillips   common/cmd_*.c: s...
1159
1160
1161
1162
1163
1164
  		"e.g. fdt print ethernet0.";
  #endif
  
  U_BOOT_CMD(
  	fdt,	255,	0,	do_fdt,
  	"flattened device tree utility commands", fdt_help_text
781e09ee6   Gerald Van Baren   Add a flattened d...
1165
  );