168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass/*
268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass *
430eb201adae2132c36874c89d4c6cf3195659d71Simon Glass * Portions from U-Boot cmd_fdt.c (C) Copyright 2007
530eb201adae2132c36874c89d4c6cf3195659d71Simon Glass * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
630eb201adae2132c36874c89d4c6cf3195659d71Simon Glass * Based on code written by:
730eb201adae2132c36874c89d4c6cf3195659d71Simon Glass *   Pantelis Antoniou <pantelis.antoniou@gmail.com> and
830eb201adae2132c36874c89d4c6cf3195659d71Simon Glass *   Matthew McClintock <msm@freescale.com>
930eb201adae2132c36874c89d4c6cf3195659d71Simon Glass *
1068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * This program is free software; you can redistribute it and/or
1168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * modify it under the terms of the GNU General Public License as
1268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * published by the Free Software Foundation; either version 2 of
1368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * the License, or (at your option) any later version.
1468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass *
1568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * This program is distributed in the hope that it will be useful,
1668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * but WITHOUT ANY WARRANTY; without even the implied warranty of
1768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1868d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * GNU General Public License for more details.
1968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass *
2068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * You should have received a copy of the GNU General Public License
2168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * along with this program; if not, write to the Free Software
2268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
2368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * MA 02111-1307 USA
2468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass */
2568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
2630eb201adae2132c36874c89d4c6cf3195659d71Simon Glass#include <assert.h>
2768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass#include <ctype.h>
2868d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass#include <getopt.h>
2968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass#include <stdio.h>
3068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass#include <stdlib.h>
3168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass#include <string.h>
3268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
3368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass#include <libfdt.h>
3468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
3568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass#include "util.h"
3668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
3730eb201adae2132c36874c89d4c6cf3195659d71Simon Glassenum display_mode {
3830eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	MODE_SHOW_VALUE,	/* show values for node properties */
3930eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	MODE_LIST_PROPS,	/* list the properties for a node */
4016c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass	MODE_LIST_SUBNODES,	/* list the subnodes of a node */
4130eb201adae2132c36874c89d4c6cf3195659d71Simon Glass};
4230eb201adae2132c36874c89d4c6cf3195659d71Simon Glass
4368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass/* Holds information which controls our output and options */
4468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glassstruct display_info {
4568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	int type;		/* data type (s/i/u/x or 0 for default) */
4668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	int size;		/* data size (1/2/4) */
4730eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	enum display_mode mode;	/* display mode that we are using */
487fcbef275741793064268cf0a1bdcd59144a9a10Simon Glass	const char *default_val; /* default value if node/property not found */
4968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass};
5068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
5168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glassstatic void report_error(const char *where, int err)
5268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass{
5368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
5468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass}
5568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
5668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass/**
5768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * Displays data of a given length according to selected options
5868d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass *
5968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * If a specific data type is provided in disp, then this is used. Otherwise
6068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * we try to guess the data type / size from the contents.
6168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass *
6268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * @param disp		Display information / options
6368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * @param data		Data to display
6468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * @param len		Maximum length of buffer
6568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * @return 0 if ok, -1 if data does not match format
6668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass */
6768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glassstatic int show_data(struct display_info *disp, const char *data, int len)
6868d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass{
6968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	int i, size;
7068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	const uint8_t *p = (const uint8_t *)data;
7168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	const char *s;
7268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	int value;
7368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	int is_string;
7468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	char fmt[3];
7568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
7668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	/* no data, don't print */
7768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	if (len == 0)
7868d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		return 0;
7968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
8068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	is_string = (disp->type) == 's' ||
8168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		(!disp->type && util_is_printable_string(data, len));
8268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	if (is_string) {
8368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		if (data[len - 1] != '\0') {
8468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass			fprintf(stderr, "Unterminated string\n");
8568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass			return -1;
8668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		}
8768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		for (s = data; s - data < len; s += strlen(s) + 1) {
8868d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass			if (s != data)
8968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass				printf(" ");
9068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass			printf("%s", (const char *)s);
9168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		}
9268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		return 0;
9368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	}
9468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	size = disp->size;
9553d6ca639d1e95d0d62e84b25f3d22d721d1f4a3David Gibson	if (size == -1) {
9668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		size = (len % 4) == 0 ? 4 : 1;
9753d6ca639d1e95d0d62e84b25f3d22d721d1f4a3David Gibson	} else if (len % size) {
9868d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		fprintf(stderr, "Property length must be a multiple of "
9968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass				"selected data size\n");
10068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		return -1;
10168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	}
10268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	fmt[0] = '%';
10368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	fmt[1] = disp->type ? disp->type : 'd';
10468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	fmt[2] = '\0';
10568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	for (i = 0; i < len; i += size, p += size) {
10668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		if (i)
10768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass			printf(" ");
108bad5b28049e5e0562a8ad91797fb77953a53fa20David Gibson		value = size == 4 ? fdt32_to_cpu(*(const fdt32_t *)p) :
10968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass			size == 2 ? (*p << 8) | p[1] : *p;
11068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		printf(fmt, value);
11168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	}
11268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	return 0;
11368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass}
11468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
11568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass/**
11630eb201adae2132c36874c89d4c6cf3195659d71Simon Glass * List all properties in a node, one per line.
11730eb201adae2132c36874c89d4c6cf3195659d71Simon Glass *
11830eb201adae2132c36874c89d4c6cf3195659d71Simon Glass * @param blob		FDT blob
11930eb201adae2132c36874c89d4c6cf3195659d71Simon Glass * @param node		Node to display
12030eb201adae2132c36874c89d4c6cf3195659d71Simon Glass * @return 0 if ok, or FDT_ERR... if not.
12130eb201adae2132c36874c89d4c6cf3195659d71Simon Glass */
12230eb201adae2132c36874c89d4c6cf3195659d71Simon Glassstatic int list_properties(const void *blob, int node)
12330eb201adae2132c36874c89d4c6cf3195659d71Simon Glass{
12430eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	const struct fdt_property *data;
12530eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	const char *name;
12630eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	int prop;
12730eb201adae2132c36874c89d4c6cf3195659d71Simon Glass
12830eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	prop = fdt_first_property_offset(blob, node);
12930eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	do {
13030eb201adae2132c36874c89d4c6cf3195659d71Simon Glass		/* Stop silently when there are no more properties */
13130eb201adae2132c36874c89d4c6cf3195659d71Simon Glass		if (prop < 0)
13230eb201adae2132c36874c89d4c6cf3195659d71Simon Glass			return prop == -FDT_ERR_NOTFOUND ? 0 : prop;
13330eb201adae2132c36874c89d4c6cf3195659d71Simon Glass		data = fdt_get_property_by_offset(blob, prop, NULL);
13430eb201adae2132c36874c89d4c6cf3195659d71Simon Glass		name = fdt_string(blob, fdt32_to_cpu(data->nameoff));
13530eb201adae2132c36874c89d4c6cf3195659d71Simon Glass		if (name)
13630eb201adae2132c36874c89d4c6cf3195659d71Simon Glass			puts(name);
13730eb201adae2132c36874c89d4c6cf3195659d71Simon Glass		prop = fdt_next_property_offset(blob, prop);
13830eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	} while (1);
13930eb201adae2132c36874c89d4c6cf3195659d71Simon Glass}
14030eb201adae2132c36874c89d4c6cf3195659d71Simon Glass
14116c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass#define MAX_LEVEL	32		/* how deeply nested we will go */
14216c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass
14316c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass/**
14416c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass * List all subnodes in a node, one per line
14516c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass *
14616c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass * @param blob		FDT blob
14716c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass * @param node		Node to display
14816c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass * @return 0 if ok, or FDT_ERR... if not.
14916c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass */
15016c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glassstatic int list_subnodes(const void *blob, int node)
15116c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass{
15216c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass	int nextoffset;		/* next node offset from libfdt */
15316c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass	uint32_t tag;		/* current tag */
15416c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass	int level = 0;		/* keep track of nesting level */
15516c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass	const char *pathp;
15616c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass	int depth = 1;		/* the assumed depth of this node */
15716c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass
15816c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass	while (level >= 0) {
15916c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		tag = fdt_next_tag(blob, node, &nextoffset);
16016c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		switch (tag) {
16116c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		case FDT_BEGIN_NODE:
16216c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			pathp = fdt_get_name(blob, node, NULL);
16316c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			if (level <= depth) {
16416c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass				if (pathp == NULL)
16516c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass					pathp = "/* NULL pointer error */";
16616c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass				if (*pathp == '\0')
16716c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass					pathp = "/";	/* root is nameless */
16816c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass				if (level == 1)
16916c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass					puts(pathp);
17016c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			}
17116c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			level++;
17216c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			if (level >= MAX_LEVEL) {
17316c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass				printf("Nested too deep, aborting.\n");
17416c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass				return 1;
17516c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			}
17616c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			break;
17716c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		case FDT_END_NODE:
17816c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			level--;
17916c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			if (level == 0)
18016c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass				level = -1;		/* exit the loop */
18116c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			break;
18216c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		case FDT_END:
18316c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			return 1;
18416c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		case FDT_PROP:
18516c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			break;
18616c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		default:
18716c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			if (level <= depth)
18816c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass				printf("Unknown tag 0x%08X\n", tag);
18916c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			return 1;
19016c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		}
19116c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		node = nextoffset;
19216c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass	}
19316c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass	return 0;
19416c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass}
19516c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass
19630eb201adae2132c36874c89d4c6cf3195659d71Simon Glass/**
19768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * Show the data for a given node (and perhaps property) according to the
19868d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * display option provided.
19968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass *
20068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * @param blob		FDT blob
20168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * @param disp		Display information / options
20268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * @param node		Node to display
20368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * @param property	Name of property to display, or NULL if none
20468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * @return 0 if ok, -ve on error
20568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass */
20668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glassstatic int show_data_for_item(const void *blob, struct display_info *disp,
20768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		int node, const char *property)
20868d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass{
20968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	const void *value = NULL;
21068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	int len, err = 0;
21168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
21216c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass	switch (disp->mode) {
21316c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass	case MODE_LIST_PROPS:
21416c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		err = list_properties(blob, node);
21516c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		break;
21616c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass
21716c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass	case MODE_LIST_SUBNODES:
21816c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		err = list_subnodes(blob, node);
21916c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		break;
22030eb201adae2132c36874c89d4c6cf3195659d71Simon Glass
22116c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass	default:
22216c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		assert(property);
22316c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		value = fdt_getprop(blob, node, property, &len);
22416c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		if (value) {
22516c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			if (show_data(disp, value, len))
22616c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass				err = -1;
22716c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			else
22816c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass				printf("\n");
2297fcbef275741793064268cf0a1bdcd59144a9a10Simon Glass		} else if (disp->default_val) {
2307fcbef275741793064268cf0a1bdcd59144a9a10Simon Glass			puts(disp->default_val);
23116c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		} else {
23216c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			report_error(property, len);
23368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass			err = -1;
23416c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		}
23516c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		break;
23668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	}
23716c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass
23868d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	return err;
23968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass}
24068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
24168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass/**
24268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * Run the main fdtget operation, given a filename and valid arguments
24368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass *
24468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * @param disp		Display information / options
24568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * @param filename	Filename of blob file
24668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * @param arg		List of arguments to process
24768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass * @param arg_count	Number of arguments
248194d5caaefcb7a65f492f09f83815e200d20b3dfNicolas Iooss * @return 0 if ok, -ve on error
24968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass */
25068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glassstatic int do_fdtget(struct display_info *disp, const char *filename,
25130eb201adae2132c36874c89d4c6cf3195659d71Simon Glass		     char **arg, int arg_count, int args_per_step)
25268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass{
25368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	char *blob;
25430eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	const char *prop;
25568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	int i, node;
25668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
2575543b88d5e3047b781552eb431bc2e3bdd9ade06Jon Loeliger	blob = utilfdt_read(filename);
25868d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	if (!blob)
25968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		return -1;
26068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
26130eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	for (i = 0; i + args_per_step <= arg_count; i += args_per_step) {
262097ec97c1a35685957210adb93692c3e210bc82cSimon Glass		node = fdt_path_offset(blob, arg[i]);
26368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		if (node < 0) {
2647fcbef275741793064268cf0a1bdcd59144a9a10Simon Glass			if (disp->default_val) {
2657fcbef275741793064268cf0a1bdcd59144a9a10Simon Glass				puts(disp->default_val);
2667fcbef275741793064268cf0a1bdcd59144a9a10Simon Glass				continue;
2677fcbef275741793064268cf0a1bdcd59144a9a10Simon Glass			} else {
2687fcbef275741793064268cf0a1bdcd59144a9a10Simon Glass				report_error(arg[i], node);
269f79ddb83e18505b522700476e546591bae6a9d4fJean-Christophe Dubois				free(blob);
2707fcbef275741793064268cf0a1bdcd59144a9a10Simon Glass				return -1;
2717fcbef275741793064268cf0a1bdcd59144a9a10Simon Glass			}
27268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		}
27330eb201adae2132c36874c89d4c6cf3195659d71Simon Glass		prop = args_per_step == 1 ? NULL : arg[i + 1];
27468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
275f79ddb83e18505b522700476e546591bae6a9d4fJean-Christophe Dubois		if (show_data_for_item(blob, disp, node, prop)) {
276f79ddb83e18505b522700476e546591bae6a9d4fJean-Christophe Dubois			free(blob);
27768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass			return -1;
278f79ddb83e18505b522700476e546591bae6a9d4fJean-Christophe Dubois		}
27968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	}
280f79ddb83e18505b522700476e546591bae6a9d4fJean-Christophe Dubois
281f79ddb83e18505b522700476e546591bae6a9d4fJean-Christophe Dubois	free(blob);
282f79ddb83e18505b522700476e546591bae6a9d4fJean-Christophe Dubois
28368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	return 0;
28468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass}
28568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
28603449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger/* Usage related data. */
28703449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysingerstatic const char usage_synopsis[] =
28803449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	"read values from device tree\n"
28968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	"	fdtget <options> <dt file> [<node> <property>]...\n"
29030eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	"	fdtget -p <options> <dt file> [<node> ]...\n"
29103449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	"\n"
29203449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	"Each value is printed on a new line.\n"
29368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	USAGE_TYPE_MSG;
29403449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysingerstatic const char usage_short_opts[] = "t:pld:" USAGE_COMMON_SHORT_OPTS;
29503449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysingerstatic struct option const usage_long_opts[] = {
29603449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	{"type",              a_argument, NULL, 't'},
29703449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	{"properties",       no_argument, NULL, 'p'},
29803449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	{"list",             no_argument, NULL, 'l'},
29903449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	{"default",           a_argument, NULL, 'd'},
30003449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	USAGE_COMMON_LONG_OPTS,
30103449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger};
30203449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysingerstatic const char * const usage_opts_help[] = {
30303449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	"Type of data",
30403449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	"List properties for each node",
30503449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	"List subnodes for each node",
30603449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	"Default value to display when the property is missing",
30703449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	USAGE_COMMON_OPTS_HELP
30803449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger};
30968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
31068d057f20d7c3a93b441d2892c4749392bc83b45Simon Glassint main(int argc, char *argv[])
31168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass{
31203449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	int opt;
31368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	char *filename = NULL;
31468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	struct display_info disp;
31530eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	int args_per_step = 2;
31668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
31768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	/* set defaults */
31868d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	memset(&disp, '\0', sizeof(disp));
31968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	disp.size = -1;
32030eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	disp.mode = MODE_SHOW_VALUE;
32103449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	while ((opt = util_getopt_long()) != EOF) {
32203449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger		switch (opt) {
32303449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger		case_USAGE_COMMON_FLAGS
32468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
32568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		case 't':
32668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass			if (utilfdt_decode_type(optarg, &disp.type,
32768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass					&disp.size))
328b9e80656f2de441826ed2ff1cd9c5d43b3ae43d3Mike Frysinger				usage("invalid type string");
32968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass			break;
33030eb201adae2132c36874c89d4c6cf3195659d71Simon Glass
33130eb201adae2132c36874c89d4c6cf3195659d71Simon Glass		case 'p':
33230eb201adae2132c36874c89d4c6cf3195659d71Simon Glass			disp.mode = MODE_LIST_PROPS;
33330eb201adae2132c36874c89d4c6cf3195659d71Simon Glass			args_per_step = 1;
33430eb201adae2132c36874c89d4c6cf3195659d71Simon Glass			break;
33516c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass
33616c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass		case 'l':
33716c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			disp.mode = MODE_LIST_SUBNODES;
33816c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			args_per_step = 1;
33916c99ee8e3e60fb47b5eaa1778996fe6ef11c611Simon Glass			break;
3407fcbef275741793064268cf0a1bdcd59144a9a10Simon Glass
3417fcbef275741793064268cf0a1bdcd59144a9a10Simon Glass		case 'd':
3427fcbef275741793064268cf0a1bdcd59144a9a10Simon Glass			disp.default_val = optarg;
3437fcbef275741793064268cf0a1bdcd59144a9a10Simon Glass			break;
34468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		}
34568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	}
34668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
34768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	if (optind < argc)
34868d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		filename = argv[optind++];
34968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	if (!filename)
350b9e80656f2de441826ed2ff1cd9c5d43b3ae43d3Mike Frysinger		usage("missing filename");
35168d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
35268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	argv += optind;
35368d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	argc -= optind;
35468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
35568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	/* Allow no arguments, and silently succeed */
35668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	if (!argc)
35768d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		return 0;
35868d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
35968d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	/* Check for node, property arguments */
36030eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	if (args_per_step == 2 && (argc % 2))
361b9e80656f2de441826ed2ff1cd9c5d43b3ae43d3Mike Frysinger		usage("must have an even number of arguments");
36268d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass
36330eb201adae2132c36874c89d4c6cf3195659d71Simon Glass	if (do_fdtget(&disp, filename, argv, argc, args_per_step))
36468d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass		return 1;
36568d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass	return 0;
36668d057f20d7c3a93b441d2892c4749392bc83b45Simon Glass}
367