FDT command improvements.

Fix "fdt set" so that it will create a non-existing property.
Add "fdt mknode" to create nodes.

Signed-off-by: Gerald Van Baren <vanbaren@cideas.com>
master
Gerald Van Baren 17 years ago
parent 38eb508e8e
commit 25114033ab
  1. 271
      common/cmd_fdt.c

@ -56,27 +56,38 @@ static char data[SCRATCHPAD];
static int fdt_valid(void); static int fdt_valid(void);
static void print_data(const void *data, int len); static void print_data(const void *data, int len);
static int findnodeoffset(const char *pathp)
{
int nodeoffset;
if (strcmp(pathp, "/") == 0) {
nodeoffset = 0;
} else {
nodeoffset = fdt_path_offset (fdt, pathp);
if (nodeoffset < 0) {
/*
* Not found or something else bad happened.
*/
printf ("findnodeoffset() libfdt: %s\n", fdt_strerror(nodeoffset));
}
}
return nodeoffset;
}
/* /*
* Flattened Device Tree command, see the help for parameter definitions. * Flattened Device Tree command, see the help for parameter definitions.
*/ */
int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{ {
char op;
if (argc < 2) { if (argc < 2) {
printf ("Usage:\n%s\n", cmdtp->usage); printf ("Usage:\n%s\n", cmdtp->usage);
return 1; return 1;
} }
/*
* Figure out which subcommand was given
*/
op = argv[1][0];
/******************************************************************** /********************************************************************
* Set the address of the fdt * Set the address of the fdt
********************************************************************/ ********************************************************************/
if (op == 'a') { if (argv[1][0] == 'a') {
/* /*
* Set the address [and length] of the fdt. * Set the address [and length] of the fdt.
*/ */
@ -102,7 +113,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
*/ */
err = fdt_open_into(fdt, fdt, len); err = fdt_open_into(fdt, fdt, len);
if (err != 0) { if (err != 0) {
printf ("libfdt: %s\n", fdt_strerror(err)); printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err));
} }
} }
} }
@ -110,7 +121,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
/******************************************************************** /********************************************************************
* Move the fdt * Move the fdt
********************************************************************/ ********************************************************************/
} else if (op == 'm') { } else if ((argv[1][0] == 'm') && (argv[1][1] == 'o')) {
struct fdt_header *newaddr; struct fdt_header *newaddr;
int len; int len;
int err; int err;
@ -150,15 +161,48 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
*/ */
err = fdt_open_into(fdt, newaddr, len); err = fdt_open_into(fdt, newaddr, len);
if (err != 0) { if (err != 0) {
printf ("libfdt: %s\n", fdt_strerror(err)); printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err));
return 1; return 1;
} }
fdt = newaddr; fdt = newaddr;
/******************************************************************** /********************************************************************
* Set the value of a node in the fdt. * Make a new node
********************************************************************/
} else if ((argv[1][0] == 'm') && (argv[1][1] == 'k')) {
char *pathp; /* path */
char *nodep; /* new node to add */
int nodeoffset; /* node offset from libfdt */
int err;
/*
* Parameters: Node path, new node to be appended to the path.
*/
if (argc < 4) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
pathp = argv[2];
nodep = argv[3];
nodeoffset = findnodeoffset(pathp);
if (nodeoffset < 0) {
/*
* Not found or something else bad happened.
*/
return 1;
}
err = fdt_add_subnode(fdt, nodeoffset, nodep);
if (err < 0) {
printf ("libfdt fdt_add_subnode(): %s\n", fdt_strerror(err));
return 1;
}
/********************************************************************
* Set the value of a property in the fdt.
********************************************************************/ ********************************************************************/
} else if (op == 's') { } else if (argv[1][0] == 's') {
char *pathp; /* path */ char *pathp; /* path */
char *prop; /* property */ char *prop; /* property */
struct fdt_property *nodep; /* node struct pointer */ struct fdt_property *nodep; /* node struct pointer */
@ -183,102 +227,85 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
prop = argv[3]; prop = argv[3];
newval = argv[4]; newval = argv[4];
if (strcmp(pathp, "/") == 0) { nodeoffset = findnodeoffset(pathp);
nodeoffset = 0; if (nodeoffset < 0) {
} else {
nodeoffset = fdt_path_offset (fdt, pathp);
if (nodeoffset < 0) {
/*
* Not found or something else bad happened.
*/
printf ("libfdt: %s\n", fdt_strerror(nodeoffset));
return 1;
}
}
nodep = fdt_getprop (fdt, nodeoffset, prop, &oldlen);
if (oldlen < 0) {
printf ("libfdt %s\n", fdt_strerror(oldlen));
return 1;
} else if (oldlen == 0) {
/* /*
* The specified property has no value * Not found or something else bad happened.
*/ */
printf("%s has no value, cannot set one (yet).\n", prop);
return 1; return 1;
} else { }
/*
* Convert the new property
*/
vp = data;
if (*newval == '<') {
/* /*
* Convert the new property * Bigger values than bytes.
*/ */
vp = data; len = 0;
if (*newval == '<') { newval++;
/* while ((*newval != '>') && (*newval != '\0')) {
* Bigger values than bytes. cp = newval;
*/ tmp = simple_strtoul(cp, &newval, 16);
len = 0; if ((newval - cp) <= 2) {
newval++; *vp = tmp & 0xFF;
while ((*newval != '>') && (*newval != '\0')) { vp += 1;
cp = newval; len += 1;
tmp = simple_strtoul(cp, &newval, 16); } else if ((newval - cp) <= 4) {
if ((newval - cp) <= 2) { *(uint16_t *)vp = __cpu_to_be16(tmp);
*vp = tmp & 0xFF; vp += 2;
vp += 1; len += 2;
len += 1; } else if ((newval - cp) <= 8) {
} else if ((newval - cp) <= 4) { *(uint32_t *)vp = __cpu_to_be32(tmp);
*(uint16_t *)vp = __cpu_to_be16(tmp); vp += 4;
vp += 2; len += 4;
len += 2; } else {
} else if ((newval - cp) <= 8) { printf("Sorry, I could not convert \"%s\"\n", cp);
*(uint32_t *)vp = __cpu_to_be32(tmp);
vp += 4;
len += 4;
} else {
printf("Sorry, I could not convert \"%s\"\n", cp);
return 1;
}
while (*newval == ' ')
newval++;
}
if (*newval != '>') {
printf("Unexpected character '%c'\n", *newval);
return 1;
}
} else if (*newval == '[') {
/*
* Byte stream. Convert the values.
*/
len = 0;
newval++;
while ((*newval != ']') && (*newval != '\0')) {
tmp = simple_strtoul(newval, &newval, 16);
*vp++ = tmp & 0xFF;
len++;
while (*newval == ' ')
newval++;
}
if (*newval != ']') {
printf("Unexpected character '%c'\n", *newval);
return 1; return 1;
} }
} else { while (*newval == ' ')
/* newval++;
* Assume it is a string. Copy it into our data area for
* convenience (including the terminating '\0').
*/
len = strlen(newval) + 1;
strcpy(data, newval);
} }
if (*newval != '>') {
ret = fdt_setprop(fdt, nodeoffset, prop, data, len); printf("Unexpected character '%c'\n", *newval);
if (ret < 0) { return 1;
printf ("libfdt %s\n", fdt_strerror(ret)); }
} else if (*newval == '[') {
/*
* Byte stream. Convert the values.
*/
len = 0;
newval++;
while ((*newval != ']') && (*newval != '\0')) {
tmp = simple_strtoul(newval, &newval, 16);
*vp++ = tmp & 0xFF;
len++;
while (*newval == ' ')
newval++;
}
if (*newval != ']') {
printf("Unexpected character '%c'\n", *newval);
return 1; return 1;
} }
} else {
/*
* Assume it is a string. Copy it into our data area for
* convenience (including the terminating '\0').
*/
len = strlen(newval) + 1;
strcpy(data, newval);
}
ret = fdt_setprop(fdt, nodeoffset, prop, data, len);
if (ret < 0) {
printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret));
return 1;
} }
/******************************************************************** /********************************************************************
* Print (recursive) / List (single level) * Print (recursive) / List (single level)
********************************************************************/ ********************************************************************/
} else if ((op == 'p') || (op == 'l')) { } else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) {
/* /*
* Recursively print (a portion of) the fdt. * Recursively print (a portion of) the fdt.
*/ */
@ -297,7 +324,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
/* /*
* list is an alias for print, but limited to 1 level * list is an alias for print, but limited to 1 level
*/ */
if (op == 'l') { if (argv[1][0] == 'l') {
depth = 1; depth = 1;
} }
@ -311,18 +338,12 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
else else
prop = NULL; prop = NULL;
if (strcmp(pathp, "/") == 0) { nodeoffset = findnodeoffset(pathp);
nodeoffset = 0; if (nodeoffset < 0) {
printf("/"); /*
} else { * Not found or something else bad happened.
nodeoffset = fdt_path_offset (fdt, pathp); */
if (nodeoffset < 0) { return 1;
/*
* Not found or something else bad happened.
*/
printf ("libfdt %s\n", fdt_strerror(nodeoffset));
return 1;
}
} }
/* /*
* The user passed in a property as well as node path. Print only * The user passed in a property as well as node path. Print only
@ -339,7 +360,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
printf("\n"); printf("\n");
return 0; return 0;
} else { } else {
printf ("libfdt %s\n", fdt_strerror(len)); printf ("libfdt fdt_getprop(): %s\n", fdt_strerror(len));
return 1; return 1;
} }
} }
@ -359,7 +380,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
level++; level++;
offstack[level] = nodeoffset; offstack[level] = nodeoffset;
if (level >= MAX_LEVEL) { if (level >= MAX_LEVEL) {
printf("Aaaiii <splat> nested too deep.\n"); printf("Aaaiii <splat> nested too deep. Aborting.\n");
return 1; return 1;
} }
break; break;
@ -374,7 +395,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
case FDT_PROP: case FDT_PROP:
nodep = fdt_getprop (fdt, offstack[level], pathp, &len); nodep = fdt_getprop (fdt, offstack[level], pathp, &len);
if (len < 0) { if (len < 0) {
printf ("libfdt %s\n", fdt_strerror(len)); printf ("libfdt fdt_getprop(): %s\n", fdt_strerror(len));
return 1; return 1;
} else if (len == 0) { } else if (len == 0) {
/* the property has no value */ /* the property has no value */
@ -403,7 +424,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
/******************************************************************** /********************************************************************
* Remove a property/node * Remove a property/node
********************************************************************/ ********************************************************************/
} else if (op == 'r') { } else if (argv[1][0] == 'r') {
int nodeoffset; /* node offset from libfdt */ int nodeoffset; /* node offset from libfdt */
int err; int err;
@ -411,17 +432,12 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
* Get the path. The root node is an oddball, the offset * Get the path. The root node is an oddball, the offset
* is zero and has no name. * is zero and has no name.
*/ */
if (strcmp(argv[2], "/") == 0) { nodeoffset = findnodeoffset(argv[2]);
nodeoffset = 0; if (nodeoffset < 0) {
} else { /*
nodeoffset = fdt_path_offset (fdt, argv[2]); * Not found or something else bad happened.
if (nodeoffset < 0) { */
/* return 1;
* Not found or something else bad happened.
*/
printf ("libfdt %s\n", fdt_strerror(nodeoffset));
return 1;
}
} }
/* /*
* Do the delete. A fourth parameter means delete a property, * Do the delete. A fourth parameter means delete a property,
@ -430,13 +446,13 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
if (argc > 3) { if (argc > 3) {
err = fdt_delprop(fdt, nodeoffset, argv[3]); err = fdt_delprop(fdt, nodeoffset, argv[3]);
if (err < 0) { if (err < 0) {
printf("fdt_delprop libfdt: %s\n", fdt_strerror(err)); printf("libfdt fdt_delprop(): %s\n", fdt_strerror(err));
return err; return err;
} }
} else { } else {
err = fdt_del_node(fdt, nodeoffset); err = fdt_del_node(fdt, nodeoffset);
if (err < 0) { if (err < 0) {
printf("fdt_del_node libfdt: %s\n", fdt_strerror(err)); printf("libfdt fdt_del_node(): %s\n", fdt_strerror(err));
return err; return err;
} }
} }
@ -444,19 +460,19 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
/******************************************************************** /********************************************************************
* Create a chosen node * Create a chosen node
********************************************************************/ ********************************************************************/
} else if (op == 'c') { } else if (argv[1][0] == 'c') {
fdt_chosen(fdt, 0, 0, 1); fdt_chosen(fdt, 0, 0, 1);
/******************************************************************** /********************************************************************
* Create a u-boot-env node * Create a u-boot-env node
********************************************************************/ ********************************************************************/
} else if (op == 'e') { } else if (argv[1][0] == 'e') {
fdt_env(fdt); fdt_env(fdt);
/******************************************************************** /********************************************************************
* Create a bd_t node * Create a bd_t node
********************************************************************/ ********************************************************************/
} else if (op == 'b') { } else if (argv[1][0] == 'b') {
fdt_bd_t(fdt); fdt_bd_t(fdt);
/******************************************************************** /********************************************************************
@ -486,7 +502,7 @@ static int fdt_valid(void)
return 1; /* valid */ return 1; /* valid */
if (err < 0) { if (err < 0) {
printf("libfdt: %s", fdt_strerror(err)); printf("libfdt fdt_check_header(): %s", fdt_strerror(err));
/* /*
* Be more informative on bad version. * Be more informative on bad version.
*/ */
@ -630,7 +646,6 @@ U_BOOT_CMD(
"fdt bd_t - Add/replace the \"/bd_t\" branch in the tree\n" "fdt bd_t - Add/replace the \"/bd_t\" branch in the tree\n"
#endif #endif
"Hints:\n" "Hints:\n"
" * Set a larger length with the fdt addr command to add to the blob.\n"
" * If the property you are setting/printing has a '#' character,\n" " * If the property you are setting/printing has a '#' character,\n"
" you MUST escape it with a \\ character or quote it with \" or\n" " you MUST escape it with a \\ character or quote it with \" or\n"
" it will be ignored as a comment.\n" " it will be ignored as a comment.\n"

Loading…
Cancel
Save