Blame view

cmd/fdt.c 28.1 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
781e09ee6   Gerald Van Baren   Add a flattened d...
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>
781e09ee6   Gerald Van Baren   Add a flattened d...
8
9
10
11
   */
  
  #include <common.h>
  #include <command.h>
c7694dd48   Simon Glass   env: Move env_set...
12
  #include <env.h>
781e09ee6   Gerald Van Baren   Add a flattened d...
13
14
  #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
  	} else {
  		printf("error: unprintable value
  ");
  		return 1;
  	}
  	return 0;
  }
8244127db   Heiko Schocher   cmd, fdt: add sub...
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
  static const char * const fdt_member_table[] = {
  	"magic",
  	"totalsize",
  	"off_dt_struct",
  	"off_dt_strings",
  	"off_mem_rsvmap",
  	"version",
  	"last_comp_version",
  	"boot_cpuid_phys",
  	"size_dt_strings",
  	"size_dt_struct",
  };
  
  static int fdt_get_header_value(int argc, char * const argv[])
  {
  	fdt32_t *fdtp = (fdt32_t *)working_fdt;
  	ulong val;
  	int i;
  
  	if (argv[2][0] != 'g')
  		return CMD_RET_FAILURE;
  
  	for (i = 0; i < ARRAY_SIZE(fdt_member_table); i++) {
  		if (strcmp(fdt_member_table[i], argv[4]))
  			continue;
  
  		val = fdt32_to_cpu(fdtp[i]);
  		env_set_hex(argv[3], val);
  		return CMD_RET_SUCCESS;
  	}
  
  	return CMD_RET_FAILURE;
  }
bc80295b6   Joe Hershberger   fdt: Add get comm...
105
  /*
781e09ee6   Gerald Van Baren   Add a flattened d...
106
107
   * Flattened Device Tree command, see the help for parameter definitions.
   */
088f1b199   Kim Phillips   common/cmd_*.c: s...
108
  static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
781e09ee6   Gerald Van Baren   Add a flattened d...
109
  {
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
110
  	if (argc < 2)
4c12eeb8b   Simon Glass   Convert cmd_usage...
111
  		return CMD_RET_USAGE;
781e09ee6   Gerald Van Baren   Add a flattened d...
112

47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
113
  	/*
781e09ee6   Gerald Van Baren   Add a flattened d...
114
  	 * Set the address of the fdt
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
115
  	 */
f0ed68e21   Maxime Ripard   cmd: fdt: Narrow ...
116
  	if (strncmp(argv[1], "ad", 2) == 0) {
54f9c8669   Kumar Gala   bootm: Set workin...
117
  		unsigned long addr;
4b5786550   Simon Glass   fdt: Allow fdt co...
118
119
  		int control = 0;
  		struct fdt_header *blob;
781e09ee6   Gerald Van Baren   Add a flattened d...
120
121
122
  		/*
  		 * Set the address [and length] of the fdt.
  		 */
4b5786550   Simon Glass   fdt: Allow fdt co...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  		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...
139
  				return 1;
4b5786550   Simon Glass   fdt: Allow fdt co...
140
141
  			printf("The address of the fdt is %#08lx
  ",
c71a0164d   Joe Hershberger   cmd_fdt: Print th...
142
  			       control ? (ulong)map_to_sysmem(blob) :
bfebc8c96   Simon Glass   env: Rename geten...
143
  					env_get_hex("fdtaddr", 0));
7dbc38ad9   Kumar Gala   fdt: fdt addr w/o...
144
145
  			return 0;
  		}
4b5786550   Simon Glass   fdt: Allow fdt co...
146
  		addr = simple_strtoul(argv[0], NULL, 16);
a92fd6577   Simon Glass   sandbox: fdt: Sup...
147
  		blob = map_sysmem(addr, 0);
4b5786550   Simon Glass   fdt: Allow fdt co...
148
  		if (!fdt_valid(&blob))
781e09ee6   Gerald Van Baren   Add a flattened d...
149
  			return 1;
4b5786550   Simon Glass   fdt: Allow fdt co...
150
151
152
  		if (control)
  			gd->fdt_blob = blob;
  		else
90fbee3e4   Joe Hershberger   cmd_fdt: Actually...
153
  			set_working_fdt_addr(addr);
781e09ee6   Gerald Van Baren   Add a flattened d...
154

4b5786550   Simon Glass   fdt: Allow fdt co...
155
  		if (argc >= 2) {
781e09ee6   Gerald Van Baren   Add a flattened d...
156
157
158
159
160
  			int  len;
  			int  err;
  			/*
  			 * Optional new length
  			 */
4b5786550   Simon Glass   fdt: Allow fdt co...
161
162
  			len = simple_strtoul(argv[1], NULL, 16);
  			if (len < fdt_totalsize(blob)) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
163
164
165
  				printf ("New length %d < existing length %d, "
  					"ignoring.
  ",
4b5786550   Simon Glass   fdt: Allow fdt co...
166
  					len, fdt_totalsize(blob));
781e09ee6   Gerald Van Baren   Add a flattened d...
167
168
169
170
  			} else {
  				/*
  				 * Open in place with a new length.
  				 */
4b5786550   Simon Glass   fdt: Allow fdt co...
171
  				err = fdt_open_into(blob, blob, len);
781e09ee6   Gerald Van Baren   Add a flattened d...
172
  				if (err != 0) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
173
174
175
  					printf ("libfdt fdt_open_into(): %s
  ",
  						fdt_strerror(err));
781e09ee6   Gerald Van Baren   Add a flattened d...
176
177
178
  				}
  			}
  		}
e02c94587   Marek Vasut   fdt: Check if the...
179
180
181
182
183
184
185
186
187
188
189
190
191
  		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...
192
  	/*
e489b9c07   Kim Phillips   fdt: unshadow glo...
193
  	 * Move the working_fdt
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
194
  	 */
e02c94587   Marek Vasut   fdt: Check if the...
195
  	if (strncmp(argv[1], "mo", 2) == 0) {
781e09ee6   Gerald Van Baren   Add a flattened d...
196
197
198
  		struct fdt_header *newaddr;
  		int  len;
  		int  err;
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
199
  		if (argc < 4)
4c12eeb8b   Simon Glass   Convert cmd_usage...
200
  			return CMD_RET_USAGE;
781e09ee6   Gerald Van Baren   Add a flattened d...
201
202
203
204
  
  		/*
  		 * Set the address and length of the fdt.
  		 */
e489b9c07   Kim Phillips   fdt: unshadow glo...
205
  		working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
d14da9130   Simon Glass   fdt: Add a parame...
206
  		if (!fdt_valid(&working_fdt))
781e09ee6   Gerald Van Baren   Add a flattened d...
207
  			return 1;
781e09ee6   Gerald Van Baren   Add a flattened d...
208

addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
209
  		newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);
6be07cc1c   Gerald Van Baren   Improve fdt move ...
210
211
212
213
214
215
  
  		/*
  		 * If the user specifies a length, use that.  Otherwise use the
  		 * current length.
  		 */
  		if (argc <= 4) {
e489b9c07   Kim Phillips   fdt: unshadow glo...
216
  			len = fdt_totalsize(working_fdt);
6be07cc1c   Gerald Van Baren   Improve fdt move ...
217
218
  		} else {
  			len = simple_strtoul(argv[4], NULL, 16);
e489b9c07   Kim Phillips   fdt: unshadow glo...
219
  			if (len < fdt_totalsize(working_fdt)) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
220
221
222
  				printf ("New length 0x%X < existing length "
  					"0x%X, aborting.
  ",
e489b9c07   Kim Phillips   fdt: unshadow glo...
223
  					len, fdt_totalsize(working_fdt));
6be07cc1c   Gerald Van Baren   Improve fdt move ...
224
225
  				return 1;
  			}
781e09ee6   Gerald Van Baren   Add a flattened d...
226
227
228
229
230
  		}
  
  		/*
  		 * Copy to the new location.
  		 */
e489b9c07   Kim Phillips   fdt: unshadow glo...
231
  		err = fdt_open_into(working_fdt, newaddr, len);
781e09ee6   Gerald Van Baren   Add a flattened d...
232
  		if (err != 0) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
233
234
235
  			printf ("libfdt fdt_open_into(): %s
  ",
  				fdt_strerror(err));
781e09ee6   Gerald Van Baren   Add a flattened d...
236
237
  			return 1;
  		}
b1a7e7994   Hiroyuki Yokoyama   cmd: fdt: Fix fdt...
238
  		set_working_fdt_addr((ulong)newaddr);
f7f191ee4   Fabien Parent   cmd/fdt: fix unca...
239
240
241
242
  #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...
243

f7f191ee4   Fabien Parent   cmd/fdt: fix unca...
244
245
246
247
248
249
250
  		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...
251
  	/*
25114033a   Gerald Van Baren   FDT command impro...
252
  	 * Make a new node
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
253
  	 */
2fb698bf5   Gerald Van Baren   Use strncmp() for...
254
  	} else if (strncmp(argv[1], "mk", 2) == 0) {
25114033a   Gerald Van Baren   FDT command impro...
255
256
257
258
259
260
261
262
  		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...
263
  		if (argc < 4)
4c12eeb8b   Simon Glass   Convert cmd_usage...
264
  			return CMD_RET_USAGE;
25114033a   Gerald Van Baren   FDT command impro...
265
266
267
  
  		pathp = argv[2];
  		nodep = argv[3];
e489b9c07   Kim Phillips   fdt: unshadow glo...
268
  		nodeoffset = fdt_path_offset (working_fdt, pathp);
25114033a   Gerald Van Baren   FDT command impro...
269
270
271
272
  		if (nodeoffset < 0) {
  			/*
  			 * Not found or something else bad happened.
  			 */
8d04f02f6   Kumar Gala   Update libfdt fro...
273
274
  			printf ("libfdt fdt_path_offset() returned %s
  ",
06e19a077   Gerald Van Baren   For fdt_find_node...
275
  				fdt_strerror(nodeoffset));
25114033a   Gerald Van Baren   FDT command impro...
276
277
  			return 1;
  		}
e489b9c07   Kim Phillips   fdt: unshadow glo...
278
  		err = fdt_add_subnode(working_fdt, nodeoffset, nodep);
25114033a   Gerald Van Baren   FDT command impro...
279
  		if (err < 0) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
280
281
282
  			printf ("libfdt fdt_add_subnode(): %s
  ",
  				fdt_strerror(err));
25114033a   Gerald Van Baren   FDT command impro...
283
284
  			return 1;
  		}
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
285
  	/*
e489b9c07   Kim Phillips   fdt: unshadow glo...
286
  	 * Set the value of a property in the working_fdt.
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
287
  	 */
25114033a   Gerald Van Baren   FDT command impro...
288
  	} else if (argv[1][0] == 's') {
781e09ee6   Gerald Van Baren   Add a flattened d...
289
  		char *pathp;		/* path */
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
290
  		char *prop;		/* property */
781e09ee6   Gerald Van Baren   Add a flattened d...
291
  		int  nodeoffset;	/* node offset from libfdt */
6dfd65f81   Bernhard Messerklinger   cmd/fdt.c align d...
292
  		static char data[SCRATCHPAD] __aligned(4);/* property storage */
9620d8725   Hannes Schmelzer   cmd/fdt: support ...
293
  		const void *ptmp;
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
294
295
  		int  len;		/* new length of the property */
  		int  ret;		/* return value */
781e09ee6   Gerald Van Baren   Add a flattened d...
296
297
  
  		/*
ea6d8be15   Gerald Van Baren   Support setting F...
298
  		 * Parameters: Node path, property, optional value.
781e09ee6   Gerald Van Baren   Add a flattened d...
299
  		 */
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
300
  		if (argc < 4)
4c12eeb8b   Simon Glass   Convert cmd_usage...
301
  			return CMD_RET_USAGE;
781e09ee6   Gerald Van Baren   Add a flattened d...
302
303
304
  
  		pathp  = argv[2];
  		prop   = argv[3];
781e09ee6   Gerald Van Baren   Add a flattened d...
305

e489b9c07   Kim Phillips   fdt: unshadow glo...
306
  		nodeoffset = fdt_path_offset (working_fdt, pathp);
25114033a   Gerald Van Baren   FDT command impro...
307
  		if (nodeoffset < 0) {
781e09ee6   Gerald Van Baren   Add a flattened d...
308
  			/*
25114033a   Gerald Van Baren   FDT command impro...
309
  			 * Not found or something else bad happened.
781e09ee6   Gerald Van Baren   Add a flattened d...
310
  			 */
8d04f02f6   Kumar Gala   Update libfdt fro...
311
312
  			printf ("libfdt fdt_path_offset() returned %s
  ",
06e19a077   Gerald Van Baren   For fdt_find_node...
313
  				fdt_strerror(nodeoffset));
781e09ee6   Gerald Van Baren   Add a flattened d...
314
  			return 1;
25114033a   Gerald Van Baren   FDT command impro...
315
  		}
25114033a   Gerald Van Baren   FDT command impro...
316

9620d8725   Hannes Schmelzer   cmd/fdt: support ...
317
318
319
320
321
322
323
324
325
326
  		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 (....
327
328
  			if (ptmp != NULL)
  				memcpy(data, ptmp, len);
9620d8725   Hannes Schmelzer   cmd/fdt: support ...
329
330
331
332
  			ret = fdt_parse_prop(&argv[4], argc - 4, data, &len);
  			if (ret != 0)
  				return ret;
  		}
e489b9c07   Kim Phillips   fdt: unshadow glo...
333
  		ret = fdt_setprop(working_fdt, nodeoffset, prop, data, len);
25114033a   Gerald Van Baren   FDT command impro...
334
335
336
337
  		if (ret < 0) {
  			printf ("libfdt fdt_setprop(): %s
  ", fdt_strerror(ret));
  			return 1;
781e09ee6   Gerald Van Baren   Add a flattened d...
338
  		}
bc80295b6   Joe Hershberger   fdt: Add get comm...
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
  	/********************************************************************
  	 * 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...
393
  					const char *node_name;
bc80295b6   Joe Hershberger   fdt: Add get comm...
394

382bee57f   Simon Glass   env: Rename seten...
395
396
397
398
  					node_name = fdt_get_name(working_fdt,
  								 nextNodeOffset,
  								 NULL);
  					env_set(var, node_name);
bc80295b6   Joe Hershberger   fdt: Add get comm...
399
400
401
402
403
404
405
406
407
  					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...
408
  				env_set_ulong(var, curIndex + 1);
bc80295b6   Joe Hershberger   fdt: Add get comm...
409
410
411
412
413
414
415
416
417
418
419
  			} 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...
420
  				env_set(var, "");
bc80295b6   Joe Hershberger   fdt: Add get comm...
421
  				return 0;
72c98ed1a   Simon Glass   fdt: Add a check ...
422
  			} else if (nodep && len > 0) {
bc80295b6   Joe Hershberger   fdt: Add get comm...
423
424
  				if (subcmd[0] == 'v') {
  					int ret;
382bee57f   Simon Glass   env: Rename seten...
425
426
  					ret = fdt_value_env_set(nodep, len,
  								var);
bc80295b6   Joe Hershberger   fdt: Add get comm...
427
428
429
430
431
  					if (ret != 0)
  						return ret;
  				} else if (subcmd[0] == 'a') {
  					/* Get address */
  					char buf[11];
085b9c3a1   Tom Rini   cmd_fdt.c: Use %p...
432
  					sprintf(buf, "0x%p", nodep);
382bee57f   Simon Glass   env: Rename seten...
433
  					env_set(var, buf);
bc80295b6   Joe Hershberger   fdt: Add get comm...
434
435
436
437
438
  				} else if (subcmd[0] == 's') {
  					/* Get size */
  					char buf[11];
  
  					sprintf(buf, "0x%08X", len);
382bee57f   Simon Glass   env: Rename seten...
439
  					env_set(var, buf);
bc80295b6   Joe Hershberger   fdt: Add get comm...
440
441
442
443
444
445
446
447
448
449
  				} else
  					return CMD_RET_USAGE;
  				return 0;
  			} else {
  				printf("libfdt fdt_getprop(): %s
  ",
  					fdt_strerror(len));
  				return 1;
  			}
  		}
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
450
  	/*
781e09ee6   Gerald Van Baren   Add a flattened d...
451
  	 * Print (recursive) / List (single level)
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
452
  	 */
25114033a   Gerald Van Baren   FDT command impro...
453
  	} else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) {
781e09ee6   Gerald Van Baren   Add a flattened d...
454
455
  		int depth = MAX_LEVEL;	/* how deep to print */
  		char *pathp;		/* path */
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
456
457
  		char *prop;		/* property */
  		int  ret;		/* return value */
f738b4a75   Kumar Gala   Make no options t...
458
  		static char root[2] = "/";
781e09ee6   Gerald Van Baren   Add a flattened d...
459
460
461
462
  
  		/*
  		 * list is an alias for print, but limited to 1 level
  		 */
25114033a   Gerald Van Baren   FDT command impro...
463
  		if (argv[1][0] == 'l') {
781e09ee6   Gerald Van Baren   Add a flattened d...
464
465
466
467
468
469
470
  			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...
471
472
473
474
  		if (argc == 2)
  			pathp = root;
  		else
  			pathp = argv[2];
781e09ee6   Gerald Van Baren   Add a flattened d...
475
476
477
478
  		if (argc > 3)
  			prop = argv[3];
  		else
  			prop = NULL;
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
479
480
481
  		ret = fdt_print(pathp, prop, depth);
  		if (ret != 0)
  			return ret;
781e09ee6   Gerald Van Baren   Add a flattened d...
482

47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
483
  	/*
781e09ee6   Gerald Van Baren   Add a flattened d...
484
  	 * Remove a property/node
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
485
  	 */
2fb698bf5   Gerald Van Baren   Use strncmp() for...
486
  	} else if (strncmp(argv[1], "rm", 2) == 0) {
781e09ee6   Gerald Van Baren   Add a flattened d...
487
488
489
490
491
492
493
  		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...
494
  		nodeoffset = fdt_path_offset (working_fdt, argv[2]);
25114033a   Gerald Van Baren   FDT command impro...
495
496
497
498
  		if (nodeoffset < 0) {
  			/*
  			 * Not found or something else bad happened.
  			 */
8d04f02f6   Kumar Gala   Update libfdt fro...
499
500
  			printf ("libfdt fdt_path_offset() returned %s
  ",
06e19a077   Gerald Van Baren   For fdt_find_node...
501
  				fdt_strerror(nodeoffset));
25114033a   Gerald Van Baren   FDT command impro...
502
  			return 1;
781e09ee6   Gerald Van Baren   Add a flattened d...
503
504
505
506
507
508
  		}
  		/*
  		 * Do the delete.  A fourth parameter means delete a property,
  		 * otherwise delete the node.
  		 */
  		if (argc > 3) {
e489b9c07   Kim Phillips   fdt: unshadow glo...
509
  			err = fdt_delprop(working_fdt, nodeoffset, argv[3]);
781e09ee6   Gerald Van Baren   Add a flattened d...
510
  			if (err < 0) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
511
512
513
  				printf("libfdt fdt_delprop():  %s
  ",
  					fdt_strerror(err));
781e09ee6   Gerald Van Baren   Add a flattened d...
514
515
516
  				return err;
  			}
  		} else {
e489b9c07   Kim Phillips   fdt: unshadow glo...
517
  			err = fdt_del_node(working_fdt, nodeoffset);
781e09ee6   Gerald Van Baren   Add a flattened d...
518
  			if (err < 0) {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
519
520
521
  				printf("libfdt fdt_del_node():  %s
  ",
  					fdt_strerror(err));
781e09ee6   Gerald Van Baren   Add a flattened d...
522
523
524
  				return err;
  			}
  		}
804887e60   Kumar Gala   Add sub-commands ...
525

47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
526
  	/*
804887e60   Kumar Gala   Add sub-commands ...
527
  	 * Display header info
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
528
  	 */
804887e60   Kumar Gala   Add sub-commands ...
529
  	} else if (argv[1][0] == 'h') {
8244127db   Heiko Schocher   cmd, fdt: add sub...
530
531
  		if (argc == 5)
  			return fdt_get_header_value(argc, argv);
e489b9c07   Kim Phillips   fdt: unshadow glo...
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
  		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 ...
547
548
  		printf("version:\t\t%d
  ", version);
e489b9c07   Kim Phillips   fdt: unshadow glo...
549
550
551
  		printf("last_comp_version:\t%d
  ",
  		       fdt_last_comp_version(working_fdt));
804887e60   Kumar Gala   Add sub-commands ...
552
553
554
  		if (version >= 2)
  			printf("boot_cpuid_phys:\t0x%x
  ",
e489b9c07   Kim Phillips   fdt: unshadow glo...
555
  				fdt_boot_cpuid_phys(working_fdt));
804887e60   Kumar Gala   Add sub-commands ...
556
557
558
  		if (version >= 3)
  			printf("size_dt_strings:\t0x%x
  ",
e489b9c07   Kim Phillips   fdt: unshadow glo...
559
  				fdt_size_dt_strings(working_fdt));
804887e60   Kumar Gala   Add sub-commands ...
560
561
562
  		if (version >= 17)
  			printf("size_dt_struct:\t\t0x%x
  ",
e489b9c07   Kim Phillips   fdt: unshadow glo...
563
564
565
566
  				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 ...
567
568
  		printf("
  ");
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
569
  	/*
804887e60   Kumar Gala   Add sub-commands ...
570
  	 * Set boot cpu id
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
571
  	 */
2fb698bf5   Gerald Van Baren   Use strncmp() for...
572
  	} else if (strncmp(argv[1], "boo", 3) == 0) {
804887e60   Kumar Gala   Add sub-commands ...
573
  		unsigned long tmp = simple_strtoul(argv[2], NULL, 16);
e489b9c07   Kim Phillips   fdt: unshadow glo...
574
  		fdt_set_boot_cpuid_phys(working_fdt, tmp);
804887e60   Kumar Gala   Add sub-commands ...
575

47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
576
  	/*
804887e60   Kumar Gala   Add sub-commands ...
577
  	 * memory command
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
578
  	 */
2fb698bf5   Gerald Van Baren   Use strncmp() for...
579
  	} else if (strncmp(argv[1], "me", 2) == 0) {
804887e60   Kumar Gala   Add sub-commands ...
580
581
  		uint64_t addr, size;
  		int err;
4b142febf   Heiko Schocher   common: delete CO...
582
583
  		addr = simple_strtoull(argv[2], NULL, 16);
  		size = simple_strtoull(argv[3], NULL, 16);
e489b9c07   Kim Phillips   fdt: unshadow glo...
584
  		err = fdt_fixup_memory(working_fdt, addr, size);
804887e60   Kumar Gala   Add sub-commands ...
585
586
  		if (err < 0)
  			return err;
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
587
  	/*
804887e60   Kumar Gala   Add sub-commands ...
588
  	 * mem reserve commands
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
589
  	 */
2fb698bf5   Gerald Van Baren   Use strncmp() for...
590
  	} else if (strncmp(argv[1], "rs", 2) == 0) {
804887e60   Kumar Gala   Add sub-commands ...
591
592
  		if (argv[2][0] == 'p') {
  			uint64_t addr, size;
e489b9c07   Kim Phillips   fdt: unshadow glo...
593
  			int total = fdt_num_mem_rsv(working_fdt);
804887e60   Kumar Gala   Add sub-commands ...
594
595
596
597
598
599
600
  			int j, err;
  			printf("index\t\t   start\t\t    size
  ");
  			printf("-------------------------------"
  				"-----------------
  ");
  			for (j = 0; j < total; j++) {
e489b9c07   Kim Phillips   fdt: unshadow glo...
601
  				err = fdt_get_mem_rsv(working_fdt, j, &addr, &size);
804887e60   Kumar Gala   Add sub-commands ...
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
  				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 ...
618
619
  			addr = simple_strtoull(argv[3], NULL, 16);
  			size = simple_strtoull(argv[4], NULL, 16);
e489b9c07   Kim Phillips   fdt: unshadow glo...
620
  			err = fdt_add_mem_rsv(working_fdt, addr, size);
804887e60   Kumar Gala   Add sub-commands ...
621
622
623
624
625
626
627
628
629
  
  			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...
630
  			int err = fdt_del_mem_rsv(working_fdt, idx);
804887e60   Kumar Gala   Add sub-commands ...
631
632
633
634
635
636
637
638
639
  
  			if (err < 0) {
  				printf("libfdt fdt_del_mem_rsv():  %s
  ",
  					fdt_strerror(err));
  				return err;
  			}
  		} else {
  			/* Unrecognized command */
4c12eeb8b   Simon Glass   Convert cmd_usage...
640
  			return CMD_RET_USAGE;
804887e60   Kumar Gala   Add sub-commands ...
641
  		}
99dffca3b   Kim Phillips   fdt: allow for bu...
642
  	}
fd61e55dd   Gerald Van Baren   Create new fdt bo...
643
  #ifdef CONFIG_OF_BOARD_SETUP
99dffca3b   Kim Phillips   fdt: allow for bu...
644
  	/* Call the board-specific fixup routine */
4ba98dc26   Simon Glass   fdt: Report failu...
645
646
647
648
649
650
651
652
653
  	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;
  		}
2c76d311a   Nicholas Faustini   fdt: add call to ...
654
655
656
  #ifdef CONFIG_SOC_KEYSTONE
  		ft_board_setup_ex(working_fdt, gd->bd);
  #endif
4ba98dc26   Simon Glass   fdt: Report failu...
657
  	}
fd61e55dd   Gerald Van Baren   Create new fdt bo...
658
  #endif
99dffca3b   Kim Phillips   fdt: allow for bu...
659
  	/* Create a chosen node */
097dd3e0a   Heiko Schocher   fdt: add "fdt che...
660
  	else if (strncmp(argv[1], "cho", 3) == 0) {
f953d99fd   Kumar Gala   fdt: added the ab...
661
  		unsigned long initrd_start = 0, initrd_end = 0;
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
662
  		if ((argc != 2) && (argc != 4))
4c12eeb8b   Simon Glass   Convert cmd_usage...
663
  			return CMD_RET_USAGE;
f953d99fd   Kumar Gala   fdt: added the ab...
664
665
666
667
668
  
  		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...
669
  		fdt_chosen(working_fdt);
dbe963ae5   Masahiro Yamada   fdt_support: dele...
670
  		fdt_initrd(working_fdt, initrd_start, initrd_end);
097dd3e0a   Heiko Schocher   fdt: add "fdt che...
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
  
  #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...
701
  		if (ret == 0)
097dd3e0a   Heiko Schocher   fdt: add "fdt che...
702
703
704
705
  			return CMD_RET_SUCCESS;
  		else
  			return CMD_RET_FAILURE;
  #endif
40afac22a   Kumar Gala   fdt: Added resize...
706
  	}
e6628ad7b   Maxime Ripard   cmd: fdt: add fdt...
707
708
709
710
711
  #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...
712
  		int ret;
e6628ad7b   Maxime Ripard   cmd: fdt: add fdt...
713
714
715
716
717
718
719
720
721
722
723
  
  		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...
724
725
726
  		/* apply method prints messages on error */
  		ret = fdt_overlay_apply_verbose(working_fdt, blob);
  		if (ret)
e6628ad7b   Maxime Ripard   cmd: fdt: add fdt...
727
728
729
  			return CMD_RET_FAILURE;
  	}
  #endif
40afac22a   Kumar Gala   fdt: Added resize...
730
731
  	/* resize the fdt */
  	else if (strncmp(argv[1], "re", 2) == 0) {
ef4768364   Hannes Schmelzer   cmd/fdt: add poss...
732
733
734
735
736
737
  		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...
738
739
  	}
  	else {
99dffca3b   Kim Phillips   fdt: allow for bu...
740
  		/* Unrecognized command */
4c12eeb8b   Simon Glass   Convert cmd_usage...
741
  		return CMD_RET_USAGE;
781e09ee6   Gerald Van Baren   Add a flattened d...
742
743
744
745
  	}
  
  	return 0;
  }
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
746
  /****************************************************************************/
781e09ee6   Gerald Van Baren   Add a flattened d...
747

d14da9130   Simon Glass   fdt: Add a parame...
748
749
750
751
752
753
754
  /**
   * 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...
755
  {
d14da9130   Simon Glass   fdt: Add a parame...
756
757
  	const void *blob = *blobp;
  	int err;
64dbbd40c   Gerald Van Baren   Moved fdt command...
758

d14da9130   Simon Glass   fdt: Add a parame...
759
  	if (blob == NULL) {
64dbbd40c   Gerald Van Baren   Moved fdt command...
760
761
  		printf ("The address of the fdt is invalid (NULL).
  ");
781e09ee6   Gerald Van Baren   Add a flattened d...
762
763
  		return 0;
  	}
64dbbd40c   Gerald Van Baren   Moved fdt command...
764

d14da9130   Simon Glass   fdt: Add a parame...
765
  	err = fdt_check_header(blob);
64dbbd40c   Gerald Van Baren   Moved fdt command...
766
767
768
769
  	if (err == 0)
  		return 1;	/* valid */
  
  	if (err < 0) {
25114033a   Gerald Van Baren   FDT command impro...
770
  		printf("libfdt fdt_check_header(): %s", fdt_strerror(err));
64dbbd40c   Gerald Van Baren   Moved fdt command...
771
772
773
774
  		/*
  		 * Be more informative on bad version.
  		 */
  		if (err == -FDT_ERR_BADVERSION) {
d14da9130   Simon Glass   fdt: Add a parame...
775
  			if (fdt_version(blob) <
e489b9c07   Kim Phillips   fdt: unshadow glo...
776
  			    FDT_FIRST_SUPPORTED_VERSION) {
dc4b0b38d   Andrew Klossner   Fix printf errors.
777
  				printf (" - too old, fdt %d < %d",
d14da9130   Simon Glass   fdt: Add a parame...
778
  					fdt_version(blob),
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
779
  					FDT_FIRST_SUPPORTED_VERSION);
64dbbd40c   Gerald Van Baren   Moved fdt command...
780
  			}
d14da9130   Simon Glass   fdt: Add a parame...
781
  			if (fdt_last_comp_version(blob) >
e489b9c07   Kim Phillips   fdt: unshadow glo...
782
  			    FDT_LAST_SUPPORTED_VERSION) {
dc4b0b38d   Andrew Klossner   Fix printf errors.
783
  				printf (" - too new, fdt %d > %d",
d14da9130   Simon Glass   fdt: Add a parame...
784
  					fdt_version(blob),
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
785
  					FDT_LAST_SUPPORTED_VERSION);
64dbbd40c   Gerald Van Baren   Moved fdt command...
786
  			}
64dbbd40c   Gerald Van Baren   Moved fdt command...
787
788
789
  		}
  		printf("
  ");
d14da9130   Simon Glass   fdt: Add a parame...
790
  		*blobp = NULL;
781e09ee6   Gerald Van Baren   Add a flattened d...
791
792
793
794
  		return 0;
  	}
  	return 1;
  }
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
795
  /****************************************************************************/
781e09ee6   Gerald Van Baren   Add a flattened d...
796
797
  
  /*
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
798
   * Parse the user's input, partially heuristic.  Valid formats:
4abd844d8   Andy Fleming   Fix fdt set comma...
799
   * <0x00112233 4 05>	- an array of cells.  Numbers follow standard
53677ef18   Wolfgang Denk   Big white-space c...
800
   *			C conventions.
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
801
802
803
804
   * [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...
805
   * newval: An array of strings containing the new property as specified
53677ef18   Wolfgang Denk   Big white-space c...
806
   *	on the command line
4abd844d8   Andy Fleming   Fix fdt set comma...
807
808
809
   * 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 ...
810
   */
54841ab50   Wolfgang Denk   Make sure that ar...
811
  static int fdt_parse_prop(char * const *newval, int count, char *data, int *len)
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
812
813
  {
  	char *cp;		/* temporary char pointer */
4abd844d8   Andy Fleming   Fix fdt set comma...
814
  	char *newp;		/* temporary newval char pointer */
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
815
  	unsigned long tmp;	/* holds converted values */
4abd844d8   Andy Fleming   Fix fdt set comma...
816
  	int stridx = 0;
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
817

4abd844d8   Andy Fleming   Fix fdt set comma...
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
  	*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 ...
836
837
838
839
  			if (*cp != '?')
  				*(fdt32_t *)data = cpu_to_fdt32(tmp);
  			else
  				newp++;
4abd844d8   Andy Fleming   Fix fdt set comma...
840
841
842
843
844
  			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 ...
845
846
847
848
849
  				printf("Sorry, I could not convert \"%s\"
  ",
  					cp);
  				return 1;
  			}
4abd844d8   Andy Fleming   Fix fdt set comma...
850
851
852
  
  			while (*newp == ' ')
  				newp++;
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
853
  		}
4abd844d8   Andy Fleming   Fix fdt set comma...
854
855
856
857
  
  		if (*newp != '>') {
  			printf("Unexpected character '%c'
  ", *newp);
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
858
859
  			return 1;
  		}
4abd844d8   Andy Fleming   Fix fdt set comma...
860
  	} else if (*newp == '[') {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
861
862
863
  		/*
  		 * Byte stream.  Convert the values.
  		 */
4abd844d8   Andy Fleming   Fix fdt set comma...
864
  		newp++;
6e748ea00   Ken MacLeod   cmd_fdt.c: fix pa...
865
  		while ((stridx < count) && (*newp != ']')) {
4abd844d8   Andy Fleming   Fix fdt set comma...
866
867
  			while (*newp == ' ')
  				newp++;
6e748ea00   Ken MacLeod   cmd_fdt.c: fix pa...
868
  			if (*newp == '\0') {
4abd844d8   Andy Fleming   Fix fdt set comma...
869
  				newp = newval[++stridx];
6e748ea00   Ken MacLeod   cmd_fdt.c: fix pa...
870
871
872
873
874
875
876
  				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 ...
877
  		}
4abd844d8   Andy Fleming   Fix fdt set comma...
878
  		if (*newp != ']') {
dc4b0b38d   Andrew Klossner   Fix printf errors.
879
880
  			printf("Unexpected character '%c'
  ", *newp);
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
881
882
883
884
  			return 1;
  		}
  	} else {
  		/*
6e748ea00   Ken MacLeod   cmd_fdt.c: fix pa...
885
886
887
  		 * 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 ...
888
  		 */
4abd844d8   Andy Fleming   Fix fdt set comma...
889
  		while (stridx < count) {
6e748ea00   Ken MacLeod   cmd_fdt.c: fix pa...
890
  			size_t length = strlen(newp) + 1;
4abd844d8   Andy Fleming   Fix fdt set comma...
891
  			strcpy(data, newp);
6e748ea00   Ken MacLeod   cmd_fdt.c: fix pa...
892
893
  			data += length;
  			*len += length;
4abd844d8   Andy Fleming   Fix fdt set comma...
894
895
  			newp = newval[++stridx];
  		}
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
896
897
898
899
900
901
902
903
  	}
  	return 0;
  }
  
  /****************************************************************************/
  
  /*
   * Heuristic to guess if this is a string or concatenated strings.
781e09ee6   Gerald Van Baren   Add a flattened d...
904
905
906
907
908
909
910
911
912
   */
  
  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...
913
914
915
916
  	/* must terminate with zero or '
  ' */
  	if (s[len - 1] != '\0' && s[len - 1] != '
  ')
781e09ee6   Gerald Van Baren   Add a flattened d...
917
918
919
  		return 0;
  
  	/* printable or a null byte (concatenated strings) */
8805beec8   Joe Hershberger   fdt: Identify scr...
920
  	while (((*s == '\0') || isprint(*s) || isspace(*s)) && (len > 0)) {
781e09ee6   Gerald Van Baren   Add a flattened d...
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
  		/*
  		 * 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 ...
943
944
945
946
947
948
  
  /*
   * 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...
949
950
951
  static void print_data(const void *data, int len)
  {
  	int j;
781e09ee6   Gerald Van Baren   Add a flattened d...
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
  
  	/* 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...
973
  	if ((len %4) == 0) {
5d927b428   Simon Glass   Kconfig: Drop CON...
974
  		if (len > CMD_FDT_MAX_DUMP)
085b9c3a1   Tom Rini   cmd_fdt.c: Use %p...
975
  			printf("* 0x%p [0x%08x]", data, len);
f0a29d433   Joe Hershberger   fdt: Limit printe...
976
  		else {
088f1b199   Kim Phillips   common/cmd_*.c: s...
977
  			const __be32 *p;
f0a29d433   Joe Hershberger   fdt: Limit printe...
978
979
980
981
982
983
984
  
  			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...
985
  	} else { /* anything else... hexdump */
5d927b428   Simon Glass   Kconfig: Drop CON...
986
  		if (len > CMD_FDT_MAX_DUMP)
085b9c3a1   Tom Rini   cmd_fdt.c: Use %p...
987
  			printf("* 0x%p [0x%08x]", data, len);
f0a29d433   Joe Hershberger   fdt: Limit printe...
988
989
990
991
992
993
994
995
  		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...
996
997
  	}
  }
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
998
999
1000
  /****************************************************************************/
  
  /*
e489b9c07   Kim Phillips   fdt: unshadow glo...
1001
   * Recursively print (a portion of) the working_fdt.  The depth parameter
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1002
1003
   * determines how deeply nested the fdt is printed.
   */
dbaf07ce6   Kumar Gala   Fix warnings from...
1004
  static int fdt_print(const char *pathp, char *prop, int depth)
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1005
  {
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1006
1007
1008
  	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...
1009
  	const void *nodep;	/* property node pointer */
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1010
1011
1012
1013
1014
  	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 ...
1015
  	const struct fdt_property *fdt_prop;
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1016

e489b9c07   Kim Phillips   fdt: unshadow glo...
1017
  	nodeoffset = fdt_path_offset (working_fdt, pathp);
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1018
1019
1020
1021
  	if (nodeoffset < 0) {
  		/*
  		 * Not found or something else bad happened.
  		 */
8d04f02f6   Kumar Gala   Update libfdt fro...
1022
1023
  		printf ("libfdt fdt_path_offset() returned %s
  ",
06e19a077   Gerald Van Baren   For fdt_find_node...
1024
  			fdt_strerror(nodeoffset));
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1025
1026
1027
1028
1029
1030
1031
  		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...
1032
  		nodep = fdt_getprop (working_fdt, nodeoffset, prop, &len);
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1033
1034
1035
1036
1037
  		if (len == 0) {
  			/* no property value */
  			printf("%s %s
  ", pathp, prop);
  			return 0;
9f9526727   Simon Glass   fdt: Add a check ...
1038
  		} else if (nodep && len > 0) {
28f384b17   Gerald Van Baren   Add spaces around...
1039
  			printf("%s = ", prop);
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
  			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 ...
1056
  	while(level >= 0) {
e489b9c07   Kim Phillips   fdt: unshadow glo...
1057
  		tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset);
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1058
1059
  		switch(tag) {
  		case FDT_BEGIN_NODE:
e489b9c07   Kim Phillips   fdt: unshadow glo...
1060
  			pathp = fdt_get_name(working_fdt, nodeoffset, NULL);
916235281   Gerald Van Baren   Fix fdt printing ...
1061
1062
1063
1064
1065
  			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 ...
1066
1067
1068
  				printf("%s%s {
  ",
  					&tabs[MAX_LEVEL - level], pathp);
916235281   Gerald Van Baren   Fix fdt printing ...
1069
  			}
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1070
  			level++;
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1071
  			if (level >= MAX_LEVEL) {
916235281   Gerald Van Baren   Fix fdt printing ...
1072
1073
  				printf("Nested too deep, aborting.
  ");
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1074
1075
1076
1077
1078
  				return 1;
  			}
  			break;
  		case FDT_END_NODE:
  			level--;
916235281   Gerald Van Baren   Fix fdt printing ...
1079
  			if (level <= depth)
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1080
1081
1082
1083
1084
1085
1086
  				printf("%s};
  ", &tabs[MAX_LEVEL - level]);
  			if (level == 0) {
  				level = -1;		/* exit the loop */
  			}
  			break;
  		case FDT_PROP:
e489b9c07   Kim Phillips   fdt: unshadow glo...
1087
  			fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset,
916235281   Gerald Van Baren   Fix fdt printing ...
1088
  					sizeof(*fdt_prop));
e489b9c07   Kim Phillips   fdt: unshadow glo...
1089
  			pathp    = fdt_string(working_fdt,
916235281   Gerald Van Baren   Fix fdt printing ...
1090
1091
1092
  					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 ...
1093
1094
1095
1096
1097
1098
1099
  			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 ...
1100
  				if (level <= depth)
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1101
1102
1103
1104
1105
  					printf("%s%s;
  ",
  						&tabs[MAX_LEVEL - level],
  						pathp);
  			} else {
916235281   Gerald Van Baren   Fix fdt printing ...
1106
  				if (level <= depth) {
28f384b17   Gerald Van Baren   Add spaces around...
1107
  					printf("%s%s = ",
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1108
1109
1110
1111
1112
1113
1114
1115
1116
  						&tabs[MAX_LEVEL - level],
  						pathp);
  					print_data (nodep, len);
  					printf(";
  ");
  				}
  			}
  			break;
  		case FDT_NOP:
dc4b0b38d   Andrew Klossner   Fix printf errors.
1117
1118
  			printf("%s/* NOP */
  ", &tabs[MAX_LEVEL - level]);
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1119
1120
1121
1122
  			break;
  		case FDT_END:
  			return 1;
  		default:
916235281   Gerald Van Baren   Fix fdt printing ...
1123
  			if (level <= depth)
addd8ce83   Gerald Van Baren   Fix cmd_fdt line ...
1124
1125
1126
1127
1128
1129
1130
1131
  				printf("Unknown tag 0x%08X
  ", tag);
  			return 1;
  		}
  		nodeoffset = nextoffset;
  	}
  	return 0;
  }
781e09ee6   Gerald Van Baren   Add a flattened d...
1132
  /********************************************************************/
088f1b199   Kim Phillips   common/cmd_*.c: s...
1133
1134
  #ifdef CONFIG_SYS_LONGHELP
  static char fdt_help_text[] =
4b5786550   Simon Glass   fdt: Allow fdt co...
1135
1136
  	"addr [-c]  <addr> [<length>]   - Set the [control] fdt location to <addr>
  "
e6628ad7b   Maxime Ripard   cmd: fdt: add fdt...
1137
1138
1139
1140
  #ifdef CONFIG_OF_LIBFDT_OVERLAY
  	"fdt apply <addr>                    - Apply overlay to the DT
  "
  #endif
fd61e55dd   Gerald Van Baren   Create new fdt bo...
1141
1142
1143
1144
  #ifdef CONFIG_OF_BOARD_SETUP
  	"fdt boardsetup                      - Do board-specific set up
  "
  #endif
c654b5172   Simon Glass   fdt: Add ft_syste...
1145
1146
1147
1148
  #ifdef CONFIG_OF_SYSTEM_SETUP
  	"fdt systemsetup                     - Do system-specific set up
  "
  #endif
238cb7a42   Gerald Van Baren   Improve the FDT h...
1149
1150
  	"fdt move   <fdt> <newaddr> <length> - Copy the fdt to <addr> and make it active
  "
ef4768364   Hannes Schmelzer   cmd/fdt: add poss...
1151
1152
  	"fdt resize [<extrasize>]            - Resize fdt to size + padding to 4k addr + some optional <extrasize> if needed
  "
781e09ee6   Gerald Van Baren   Add a flattened d...
1153
1154
1155
1156
  	"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...
1157
1158
1159
1160
1161
1162
1163
1164
  	"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...
1165
1166
1167
1168
1169
1170
  	"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>
  "
8244127db   Heiko Schocher   cmd, fdt: add sub...
1171
1172
1173
1174
  	"fdt header [get <var> <member>]     - Display header info
  "
  	"                                      get - get header member <member> and store it in <var>
  "
804887e60   Kumar Gala   Add sub-commands ...
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
  	"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...
1185
1186
1187
1188
  	"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...
1189
1190
1191
1192
1193
1194
1195
1196
  #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...
1197
  	"NOTE: Dereference aliases by omitting the leading '/', "
088f1b199   Kim Phillips   common/cmd_*.c: s...
1198
1199
1200
1201
1202
1203
  		"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...
1204
  );