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