mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-29 08:01:08 +00:00
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:
parent
f0a29d4331
commit
bc80295b62
1 changed files with 144 additions and 0 deletions
144
common/cmd_fdt.c
144
common/cmd_fdt.c
|
@ -47,6 +47,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
static int fdt_valid(void);
|
||||
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 is_printable_string(const void *data, int len);
|
||||
|
||||
/*
|
||||
* The working_fdt points to our working flattened device tree.
|
||||
|
@ -63,6 +64,34 @@ void set_working_fdt_addr(void *addr)
|
|||
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.
|
||||
*/
|
||||
|
@ -253,6 +282,117 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
|||
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)
|
||||
*/
|
||||
|
@ -836,6 +976,10 @@ U_BOOT_CMD(
|
|||
"fdt resize - Resize fdt to size + padding to 4k addr\n"
|
||||
"fdt print <path> [<prop>] - Recursive print 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 mknode <path> <node> - Create a new node after <path>\n"
|
||||
"fdt rm <path> [<prop>] - Delete the node or <property>\n"
|
||||
|
|
Loading…
Reference in a new issue