fdt: Add get commands to fdt

Add commands to access data in the fdt.  This allows data from a dtb
or itb to be accessed from the shell scripts.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
This commit is contained in:
Joe Hershberger 2012-08-17 10:34:37 +00:00 committed by Gerald Van Baren
parent f0a29d4331
commit bc80295b62

View File

@ -47,6 +47,7 @@ DECLARE_GLOBAL_DATA_PTR;
static int fdt_valid(void); static int fdt_valid(void);
static int fdt_parse_prop(char *const*newval, int count, char *data, int *len); static int fdt_parse_prop(char *const*newval, int count, char *data, int *len);
static int fdt_print(const char *pathp, char *prop, int depth); static int fdt_print(const char *pathp, char *prop, int depth);
static int is_printable_string(const void *data, int len);
/* /*
* The working_fdt points to our working flattened device tree. * The working_fdt points to our working flattened device tree.
@ -63,6 +64,34 @@ void set_working_fdt_addr(void *addr)
setenv("fdtaddr", buf); setenv("fdtaddr", buf);
} }
/*
* Get a value from the fdt and format it to be set in the environment
*/
static int fdt_value_setenv(const void *nodep, int len, const char *var)
{
if (is_printable_string(nodep, len))
setenv(var, (void *)nodep);
else if (len == 4) {
char buf[11];
sprintf(buf, "0x%08X", *(uint32_t *)nodep);
setenv(var, buf);
} 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));
setenv(var, buf);
} else {
printf("error: unprintable value\n");
return 1;
}
return 0;
}
/* /*
* Flattened Device Tree command, see the help for parameter definitions. * Flattened Device Tree command, see the help for parameter definitions.
*/ */
@ -253,6 +282,117 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
return 1; return 1;
} }
/********************************************************************
* 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\n",
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) {
const char *nodeName = fdt_get_name(
working_fdt, nextNodeOffset, NULL);
setenv(var, (char *)nodeName);
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 */
char buf[11];
sprintf(buf, "%d", curIndex + 1);
setenv(var, buf);
} else {
/* node index not found */
printf("libfdt node not found\n");
return 1;
}
} else {
nodep = fdt_getprop(
working_fdt, nodeoffset, prop, &len);
if (len == 0) {
/* no property value */
setenv(var, "");
return 0;
} else if (len > 0) {
if (subcmd[0] == 'v') {
int ret;
ret = fdt_value_setenv(nodep, len, var);
if (ret != 0)
return ret;
} else if (subcmd[0] == 'a') {
/* Get address */
char buf[11];
sprintf(buf, "0x%08X", (uint32_t)nodep);
setenv(var, buf);
} else if (subcmd[0] == 's') {
/* Get size */
char buf[11];
sprintf(buf, "0x%08X", len);
setenv(var, buf);
} else
return CMD_RET_USAGE;
return 0;
} else {
printf("libfdt fdt_getprop(): %s\n",
fdt_strerror(len));
return 1;
}
}
/* /*
* Print (recursive) / List (single level) * Print (recursive) / List (single level)
*/ */
@ -836,6 +976,10 @@ U_BOOT_CMD(
"fdt resize - Resize fdt to size + padding to 4k addr\n" "fdt resize - Resize fdt to size + padding to 4k addr\n"
"fdt print <path> [<prop>] - Recursive print starting at <path>\n" "fdt print <path> [<prop>] - Recursive print starting at <path>\n"
"fdt list <path> [<prop>] - Print one level starting at <path>\n" "fdt list <path> [<prop>] - Print one level starting at <path>\n"
"fdt get value <var> <path> <prop> - Get <property> and store in <var>\n"
"fdt get name <var> <path> <index> - Get name of node <index> and store in <var>\n"
"fdt get addr <var> <path> <prop> - Get start address of <property> and store in <var>\n"
"fdt get size <var> <path> [<prop>] - Get size of [<property>] or num nodes and store in <var>\n"
"fdt set <path> <prop> [<val>] - Set <property> [to <val>]\n" "fdt set <path> <prop> [<val>] - Set <property> [to <val>]\n"
"fdt mknode <path> <node> - Create a new node after <path>\n" "fdt mknode <path> <node> - Create a new node after <path>\n"
"fdt rm <path> [<prop>] - Delete the node or <property>\n" "fdt rm <path> [<prop>] - Delete the node or <property>\n"