2 * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
4 * Portions from U-Boot cmd_fdt.c (C) Copyright 2007
5 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
6 * Based on code written by:
7 * Pantelis Antoniou <pantelis.antoniou@gmail.com> and
8 * Matthew McClintock <msm@freescale.com>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
38 MODE_SHOW_VALUE
, /* show values for node properties */
39 MODE_LIST_PROPS
, /* list the properties for a node */
40 MODE_LIST_SUBNODES
, /* list the subnodes of a node */
43 /* Holds information which controls our output and options */
45 int type
; /* data type (s/i/u/x or 0 for default) */
46 int size
; /* data size (1/2/4) */
47 enum display_mode mode
; /* display mode that we are using */
48 const char *default_val
; /* default value if node/property not found */
51 static void report_error(const char *where
, int err
)
53 fprintf(stderr
, "Error at '%s': %s\n", where
, fdt_strerror(err
));
57 * Displays data of a given length according to selected options
59 * If a specific data type is provided in disp, then this is used. Otherwise
60 * we try to guess the data type / size from the contents.
62 * @param disp Display information / options
63 * @param data Data to display
64 * @param len Maximum length of buffer
65 * @return 0 if ok, -1 if data does not match format
67 static int show_data(struct display_info
*disp
, const char *data
, int len
)
70 const uint8_t *p
= (const uint8_t *)data
;
76 /* no data, don't print */
80 is_string
= (disp
->type
) == 's' ||
81 (!disp
->type
&& util_is_printable_string(data
, len
));
83 if (data
[len
- 1] != '\0') {
84 fprintf(stderr
, "Unterminated string\n");
87 for (s
= data
; s
- data
< len
; s
+= strlen(s
) + 1) {
90 printf("%s", (const char *)s
);
96 size
= (len
% 4) == 0 ? 4 : 1;
97 } else if (len
% size
) {
98 fprintf(stderr
, "Property length must be a multiple of "
99 "selected data size\n");
103 fmt
[1] = disp
->type
? disp
->type
: 'd';
105 for (i
= 0; i
< len
; i
+= size
, p
+= size
) {
108 value
= size
== 4 ? fdt32_to_cpu(*(const uint32_t *)p
) :
109 size
== 2 ? (*p
<< 8) | p
[1] : *p
;
116 * List all properties in a node, one per line.
118 * @param blob FDT blob
119 * @param node Node to display
120 * @return 0 if ok, or FDT_ERR... if not.
122 static int list_properties(const void *blob
, int node
)
124 const struct fdt_property
*data
;
128 prop
= fdt_first_property_offset(blob
, node
);
130 /* Stop silently when there are no more properties */
132 return prop
== -FDT_ERR_NOTFOUND
? 0 : prop
;
133 data
= fdt_get_property_by_offset(blob
, prop
, NULL
);
134 name
= fdt_string(blob
, fdt32_to_cpu(data
->nameoff
));
137 prop
= fdt_next_property_offset(blob
, prop
);
141 #define MAX_LEVEL 32 /* how deeply nested we will go */
144 * List all subnodes in a node, one per line
146 * @param blob FDT blob
147 * @param node Node to display
148 * @return 0 if ok, or FDT_ERR... if not.
150 static int list_subnodes(const void *blob
, int node
)
152 int nextoffset
; /* next node offset from libfdt */
153 uint32_t tag
; /* current tag */
154 int level
= 0; /* keep track of nesting level */
156 int depth
= 1; /* the assumed depth of this node */
159 tag
= fdt_next_tag(blob
, node
, &nextoffset
);
162 pathp
= fdt_get_name(blob
, node
, NULL
);
163 if (level
<= depth
) {
165 pathp
= "/* NULL pointer error */";
167 pathp
= "/"; /* root is nameless */
172 if (level
>= MAX_LEVEL
) {
173 printf("Nested too deep, aborting.\n");
180 level
= -1; /* exit the loop */
188 printf("Unknown tag 0x%08X\n", tag
);
197 * Show the data for a given node (and perhaps property) according to the
198 * display option provided.
200 * @param blob FDT blob
201 * @param disp Display information / options
202 * @param node Node to display
203 * @param property Name of property to display, or NULL if none
204 * @return 0 if ok, -ve on error
206 static int show_data_for_item(const void *blob
, struct display_info
*disp
,
207 int node
, const char *property
)
209 const void *value
= NULL
;
212 switch (disp
->mode
) {
213 case MODE_LIST_PROPS
:
214 err
= list_properties(blob
, node
);
217 case MODE_LIST_SUBNODES
:
218 err
= list_subnodes(blob
, node
);
223 value
= fdt_getprop(blob
, node
, property
, &len
);
225 if (show_data(disp
, value
, len
))
229 } else if (disp
->default_val
) {
230 puts(disp
->default_val
);
232 report_error(property
, len
);
242 * Run the main fdtget operation, given a filename and valid arguments
244 * @param disp Display information / options
245 * @param filename Filename of blob file
246 * @param arg List of arguments to process
247 * @param arg_count Number of arguments
248 * @param return 0 if ok, -ve on error
250 static int do_fdtget(struct display_info
*disp
, const char *filename
,
251 char **arg
, int arg_count
, int args_per_step
)
257 blob
= utilfdt_read(filename
);
261 for (i
= 0; i
+ args_per_step
<= arg_count
; i
+= args_per_step
) {
262 node
= fdt_path_offset(blob
, arg
[i
]);
264 if (disp
->default_val
) {
265 puts(disp
->default_val
);
268 report_error(arg
[i
], node
);
272 prop
= args_per_step
== 1 ? NULL
: arg
[i
+ 1];
274 if (show_data_for_item(blob
, disp
, node
, prop
))
280 static const char *usage_msg
=
281 "fdtget - read values from device tree\n"
283 "Each value is printed on a new line.\n\n"
285 " fdtget <options> <dt file> [<node> <property>]...\n"
286 " fdtget -p <options> <dt file> [<node> ]...\n"
288 "\t-t <type>\tType of data\n"
289 "\t-p\t\tList properties for each node\n"
290 "\t-l\t\tList subnodes for each node\n"
291 "\t-d\t\tDefault value to display when the property is "
293 "\t-h\t\tPrint this help\n\n"
296 static void usage(const char *msg
)
299 fprintf(stderr
, "Error: %s\n\n", msg
);
301 fprintf(stderr
, "%s", usage_msg
);
305 int main(int argc
, char *argv
[])
307 char *filename
= NULL
;
308 struct display_info disp
;
309 int args_per_step
= 2;
312 memset(&disp
, '\0', sizeof(disp
));
314 disp
.mode
= MODE_SHOW_VALUE
;
316 int c
= getopt(argc
, argv
, "d:hlpt:");
326 if (utilfdt_decode_type(optarg
, &disp
.type
,
328 usage("Invalid type string");
332 disp
.mode
= MODE_LIST_PROPS
;
337 disp
.mode
= MODE_LIST_SUBNODES
;
342 disp
.default_val
= optarg
;
348 filename
= argv
[optind
++];
350 usage("Missing filename");
355 /* Allow no arguments, and silently succeed */
359 /* Check for node, property arguments */
360 if (args_per_step
== 2 && (argc
% 2))
361 usage("Must have an even number of arguments");
363 if (do_fdtget(&disp
, filename
, argv
, argc
, args_per_step
))