From 6be07cc1ca458278c85ecdbf1a0536cff4c701ec Mon Sep 17 00:00:00 2001 From: Gerald Van Baren Date: Wed, 25 Apr 2007 22:47:15 -0400 Subject: Improve fdt move length handling. Make the length parameter optional: if not specified, do the move using the current size unchanged. Signed-off-by: Gerald Van Baren --- common/cmd_fdt.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'common/cmd_fdt.c') diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 08fe351..a119985 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -115,7 +115,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) int len; int err; - if (argc != 5) { + if (argc < 4) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } @@ -129,11 +129,20 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } newaddr = (struct fdt_header *)simple_strtoul(argv[3], NULL, 16); - len = simple_strtoul(argv[4], NULL, 16); - if (len < fdt_totalsize(fdt)) { - printf ("New length %d < existing length %d, aborting.\n", - len, fdt_totalsize(fdt)); - return 1; + + /* + * If the user specifies a length, use that. Otherwise use the + * current length. + */ + if (argc <= 4) { + len = fdt_totalsize(fdt); + } else { + len = simple_strtoul(argv[4], NULL, 16); + if (len < fdt_totalsize(fdt)) { + printf ("New length 0x%X < existing length 0x%X, aborting.\n", + len, fdt_totalsize(fdt)); + return 1; + } } /* -- cgit v1.1 From 25114033ab21788810c48ba4df103b649da1223b Mon Sep 17 00:00:00 2001 From: Gerald Van Baren Date: Sat, 12 May 2007 09:47:25 -0400 Subject: 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 --- common/cmd_fdt.c | 271 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 143 insertions(+), 128 deletions(-) (limited to 'common/cmd_fdt.c') diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index a119985..8402ca7 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -56,27 +56,38 @@ static char data[SCRATCHPAD]; static int fdt_valid(void); 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. */ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { - char op; - if (argc < 2) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } - /* - * Figure out which subcommand was given - */ - op = argv[1][0]; /******************************************************************** * Set the address of the fdt ********************************************************************/ - if (op == 'a') { + if (argv[1][0] == 'a') { /* * 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); 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 ********************************************************************/ - } else if (op == 'm') { + } else if ((argv[1][0] == 'm') && (argv[1][1] == 'o')) { struct fdt_header *newaddr; int len; 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); if (err != 0) { - printf ("libfdt: %s\n", fdt_strerror(err)); + printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); return 1; } 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 *prop; /* property */ 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]; newval = argv[4]; - if (strcmp(pathp, "/") == 0) { - 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) { + nodeoffset = findnodeoffset(pathp); + if (nodeoffset < 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; - } else { + } + /* + * Convert the new property + */ + vp = data; + if (*newval == '<') { /* - * Convert the new property + * Bigger values than bytes. */ - vp = data; - if (*newval == '<') { - /* - * Bigger values than bytes. - */ - len = 0; - newval++; - while ((*newval != '>') && (*newval != '\0')) { - cp = newval; - tmp = simple_strtoul(cp, &newval, 16); - if ((newval - cp) <= 2) { - *vp = tmp & 0xFF; - vp += 1; - len += 1; - } else if ((newval - cp) <= 4) { - *(uint16_t *)vp = __cpu_to_be16(tmp); - vp += 2; - len += 2; - } else if ((newval - cp) <= 8) { - *(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); + len = 0; + newval++; + while ((*newval != '>') && (*newval != '\0')) { + cp = newval; + tmp = simple_strtoul(cp, &newval, 16); + if ((newval - cp) <= 2) { + *vp = tmp & 0xFF; + vp += 1; + len += 1; + } else if ((newval - cp) <= 4) { + *(uint16_t *)vp = __cpu_to_be16(tmp); + vp += 2; + len += 2; + } else if ((newval - cp) <= 8) { + *(uint32_t *)vp = __cpu_to_be32(tmp); + vp += 4; + len += 4; + } else { + printf("Sorry, I could not convert \"%s\"\n", cp); 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); + while (*newval == ' ') + newval++; } - - ret = fdt_setprop(fdt, nodeoffset, prop, data, len); - if (ret < 0) { - printf ("libfdt %s\n", fdt_strerror(ret)); + 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; } + } 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) ********************************************************************/ - } else if ((op == 'p') || (op == 'l')) { + } else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) { /* * 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 */ - if (op == 'l') { + if (argv[1][0] == 'l') { depth = 1; } @@ -311,18 +338,12 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) else prop = NULL; - if (strcmp(pathp, "/") == 0) { - nodeoffset = 0; - printf("/"); - } 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; - } + nodeoffset = findnodeoffset(pathp); + if (nodeoffset < 0) { + /* + * Not found or something else bad happened. + */ + return 1; } /* * 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"); return 0; } else { - printf ("libfdt %s\n", fdt_strerror(len)); + printf ("libfdt fdt_getprop(): %s\n", fdt_strerror(len)); return 1; } } @@ -359,7 +380,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) level++; offstack[level] = nodeoffset; if (level >= MAX_LEVEL) { - printf("Aaaiii nested too deep.\n"); + printf("Aaaiii nested too deep. Aborting.\n"); return 1; } break; @@ -374,7 +395,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) case FDT_PROP: nodep = fdt_getprop (fdt, offstack[level], pathp, &len); if (len < 0) { - printf ("libfdt %s\n", fdt_strerror(len)); + printf ("libfdt fdt_getprop(): %s\n", fdt_strerror(len)); return 1; } else if (len == 0) { /* 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 ********************************************************************/ - } else if (op == 'r') { + } else if (argv[1][0] == 'r') { int nodeoffset; /* node offset from libfdt */ 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 * is zero and has no name. */ - if (strcmp(argv[2], "/") == 0) { - nodeoffset = 0; - } else { - nodeoffset = fdt_path_offset (fdt, argv[2]); - if (nodeoffset < 0) { - /* - * Not found or something else bad happened. - */ - printf ("libfdt %s\n", fdt_strerror(nodeoffset)); - return 1; - } + nodeoffset = findnodeoffset(argv[2]); + if (nodeoffset < 0) { + /* + * Not found or something else bad happened. + */ + return 1; } /* * 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) { err = fdt_delprop(fdt, nodeoffset, argv[3]); if (err < 0) { - printf("fdt_delprop libfdt: %s\n", fdt_strerror(err)); + printf("libfdt fdt_delprop(): %s\n", fdt_strerror(err)); return err; } } else { err = fdt_del_node(fdt, nodeoffset); 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; } } @@ -444,19 +460,19 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /******************************************************************** * Create a chosen node ********************************************************************/ - } else if (op == 'c') { + } else if (argv[1][0] == 'c') { fdt_chosen(fdt, 0, 0, 1); /******************************************************************** * Create a u-boot-env node ********************************************************************/ - } else if (op == 'e') { + } else if (argv[1][0] == 'e') { fdt_env(fdt); /******************************************************************** * Create a bd_t node ********************************************************************/ - } else if (op == 'b') { + } else if (argv[1][0] == 'b') { fdt_bd_t(fdt); /******************************************************************** @@ -486,7 +502,7 @@ static int fdt_valid(void) return 1; /* valid */ if (err < 0) { - printf("libfdt: %s", fdt_strerror(err)); + printf("libfdt fdt_check_header(): %s", fdt_strerror(err)); /* * 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" #endif "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" " you MUST escape it with a \\ character or quote it with \" or\n" " it will be ignored as a comment.\n" -- cgit v1.1 From addd8ce83078c25f0eca5f23adbdfc64ca50a243 Mon Sep 17 00:00:00 2001 From: Gerald Van Baren Date: Wed, 16 May 2007 22:39:59 -0400 Subject: Fix cmd_fdt line lengths, refactor code. Break lines that were greater than 80 characters in length. Move the fdt print and property parsing code to separate static functions to reduce coding clutter in the fdt_cmd handling body. Signed-off-by: Gerald Van Baren --- common/cmd_fdt.c | 426 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 239 insertions(+), 187 deletions(-) (limited to 'common/cmd_fdt.c') diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 8402ca7..7066d7d 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -45,16 +45,12 @@ DECLARE_GLOBAL_DATA_PTR; /* - * Scratchpad memory. - */ -static char data[SCRATCHPAD]; - - -/* * Function prototypes/declarations. */ static int fdt_valid(void); -static void print_data(const void *data, int len); +static int fdt_parse_prop(char *pathp, char *prop, char *newval, + char *data, int *len); +static int fdt_print(char *pathp, char *prop, int depth); static int findnodeoffset(const char *pathp) { @@ -68,7 +64,8 @@ static int findnodeoffset(const char *pathp) /* * Not found or something else bad happened. */ - printf ("findnodeoffset() libfdt: %s\n", fdt_strerror(nodeoffset)); + printf ("findnodeoffset() libfdt: %s\n", + fdt_strerror(nodeoffset)); } } return nodeoffset; @@ -105,7 +102,8 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) */ len = simple_strtoul(argv[3], NULL, 16); if (len < fdt_totalsize(fdt)) { - printf ("New length %d < existing length %d, ignoring.\n", + printf ("New length %d < existing length %d, " + "ignoring.\n", len, fdt_totalsize(fdt)); } else { /* @@ -113,7 +111,8 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) */ err = fdt_open_into(fdt, fdt, len); if (err != 0) { - printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); + printf ("libfdt fdt_open_into(): %s\n", + fdt_strerror(err)); } } } @@ -139,7 +138,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; } - newaddr = (struct fdt_header *)simple_strtoul(argv[3], NULL, 16); + newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16); /* * If the user specifies a length, use that. Otherwise use the @@ -150,7 +149,8 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } else { len = simple_strtoul(argv[4], NULL, 16); if (len < fdt_totalsize(fdt)) { - printf ("New length 0x%X < existing length 0x%X, aborting.\n", + printf ("New length 0x%X < existing length " + "0x%X, aborting.\n", len, fdt_totalsize(fdt)); return 1; } @@ -161,7 +161,8 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) */ err = fdt_open_into(fdt, newaddr, len); if (err != 0) { - printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); + printf ("libfdt fdt_open_into(): %s\n", + fdt_strerror(err)); return 1; } fdt = newaddr; @@ -195,7 +196,8 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } err = fdt_add_subnode(fdt, nodeoffset, nodep); if (err < 0) { - printf ("libfdt fdt_add_subnode(): %s\n", fdt_strerror(err)); + printf ("libfdt fdt_add_subnode(): %s\n", + fdt_strerror(err)); return 1; } @@ -204,16 +206,12 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) ********************************************************************/ } else if (argv[1][0] == 's') { char *pathp; /* path */ - char *prop; /* property */ - struct fdt_property *nodep; /* node struct pointer */ + char *prop; /* property */ char *newval; /* value from the user (as a string) */ - char *vp; /* temporary value pointer */ - char *cp; /* temporary char pointer */ int nodeoffset; /* node offset from libfdt */ - int len; /* new length of the property */ - int oldlen; /* original length of the property */ - unsigned long tmp; /* holds converted values */ - int ret; /* return value */ + static char data[SCRATCHPAD]; /* storage for the property */ + int len; /* new length of the property */ + int ret; /* return value */ /* * Parameters: Node path, property, value. @@ -234,67 +232,9 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) */ return 1; } - /* - * Convert the new property - */ - vp = data; - if (*newval == '<') { - /* - * Bigger values than bytes. - */ - len = 0; - newval++; - while ((*newval != '>') && (*newval != '\0')) { - cp = newval; - tmp = simple_strtoul(cp, &newval, 16); - if ((newval - cp) <= 2) { - *vp = tmp & 0xFF; - vp += 1; - len += 1; - } else if ((newval - cp) <= 4) { - *(uint16_t *)vp = __cpu_to_be16(tmp); - vp += 2; - len += 2; - } else if ((newval - cp) <= 8) { - *(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; - } - } 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_parse_prop(pathp, prop, newval, data, &len); + if (ret != 0) + return ret; ret = fdt_setprop(fdt, nodeoffset, prop, data, len); if (ret < 0) { @@ -306,20 +246,10 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) * Print (recursive) / List (single level) ********************************************************************/ } else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) { - /* - * Recursively print (a portion of) the fdt. - */ - static int offstack[MAX_LEVEL]; - static char tabs[MAX_LEVEL+1] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; int depth = MAX_LEVEL; /* how deep to print */ char *pathp; /* path */ - char *prop; /* property */ - void *nodep; /* property node pointer */ - int nodeoffset; /* node offset from libfdt */ - int nextoffset; /* next node offset from libfdt */ - uint32_t tag; /* tag */ - int len; /* length of the property */ - int level = 0; /* keep track of nesting level */ + char *prop; /* property */ + int ret; /* return value */ /* * list is an alias for print, but limited to 1 level @@ -338,88 +268,9 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) else prop = NULL; - nodeoffset = findnodeoffset(pathp); - if (nodeoffset < 0) { - /* - * Not found or something else bad happened. - */ - return 1; - } - /* - * The user passed in a property as well as node path. Print only - * the given property and then return. - */ - if (prop) { - nodep = fdt_getprop (fdt, nodeoffset, prop, &len); - if (len == 0) { - printf("%s %s\n", pathp, prop); /* no property value */ - return 0; - } else if (len > 0) { - printf("%s=", prop); - print_data (nodep, len); - printf("\n"); - return 0; - } else { - printf ("libfdt fdt_getprop(): %s\n", fdt_strerror(len)); - return 1; - } - } - - /* - * The user passed in a node path and no property, print the node - * and all subnodes. - */ - offstack[0] = nodeoffset; - - while(level >= 0) { - tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, &pathp); - switch(tag) { - case FDT_BEGIN_NODE: - if(level <= depth) - printf("%s%s {\n", &tabs[MAX_LEVEL - level], pathp); - level++; - offstack[level] = nodeoffset; - if (level >= MAX_LEVEL) { - printf("Aaaiii nested too deep. Aborting.\n"); - return 1; - } - break; - case FDT_END_NODE: - level--; - if(level <= depth) - printf("%s};\n", &tabs[MAX_LEVEL - level]); - if (level == 0) { - level = -1; /* exit the loop */ - } - break; - case FDT_PROP: - nodep = fdt_getprop (fdt, offstack[level], pathp, &len); - if (len < 0) { - printf ("libfdt fdt_getprop(): %s\n", fdt_strerror(len)); - return 1; - } else if (len == 0) { - /* the property has no value */ - if(level <= depth) - printf("%s%s;\n", &tabs[MAX_LEVEL - level], pathp); - } else { - if(level <= depth) { - printf("%s%s=", &tabs[MAX_LEVEL - level], pathp); - print_data (nodep, len); - printf(";\n"); - } - } - break; - case FDT_NOP: - break; - case FDT_END: - return 1; - default: - if(level <= depth) - printf("Unknown tag 0x%08X\n", tag); - return 1; - } - nodeoffset = nextoffset; - } + ret = fdt_print(pathp, prop, depth); + if (ret != 0) + return ret; /******************************************************************** * Remove a property/node @@ -446,13 +297,15 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if (argc > 3) { err = fdt_delprop(fdt, nodeoffset, argv[3]); if (err < 0) { - printf("libfdt fdt_delprop(): %s\n", fdt_strerror(err)); + printf("libfdt fdt_delprop(): %s\n", + fdt_strerror(err)); return err; } } else { err = fdt_del_node(fdt, nodeoffset); if (err < 0) { - printf("libfdt fdt_del_node(): %s\n", fdt_strerror(err)); + printf("libfdt fdt_del_node(): %s\n", + fdt_strerror(err)); return err; } } @@ -486,7 +339,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 0; } -/********************************************************************/ +/****************************************************************************/ static int fdt_valid(void) { @@ -509,12 +362,14 @@ static int fdt_valid(void) if (err == -FDT_ERR_BADVERSION) { if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) { printf (" - too old, fdt $d < %d", - fdt_version(fdt), FDT_FIRST_SUPPORTED_VERSION); + fdt_version(fdt), + FDT_FIRST_SUPPORTED_VERSION); fdt = NULL; } if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) { printf (" - too new, fdt $d > %d", - fdt_version(fdt), FDT_LAST_SUPPORTED_VERSION); + fdt_version(fdt), + FDT_LAST_SUPPORTED_VERSION); fdt = NULL; } return 0; @@ -525,13 +380,91 @@ static int fdt_valid(void) return 1; } -/********************************************************************/ +/****************************************************************************/ /* - * OF flat tree handling - * Written by: Pantelis Antoniou - * Updated by: Matthew McClintock - * Converted to libfdt by: Gerald Van Baren + * Parse the user's input, partially heuristic. Valid formats: + * <00> - hex byte + * <0011> - hex half word (16 bits) + * <00112233> - hex word (32 bits) + * - hex double words (64 bits) are not supported, must use + * a byte stream instead. + * [00 11 22 .. nn] - byte stream + * "string" - If the the value doesn't start with "<" or "[", it is + * treated as a string. Note that the quotes are + * stripped by the parser before we get the string. + */ +static int fdt_parse_prop(char *pathp, char *prop, char *newval, + char *data, int *len) +{ + char *cp; /* temporary char pointer */ + unsigned long tmp; /* holds converted values */ + + if (*newval == '<') { + /* + * Bigger values than bytes. + */ + *len = 0; + newval++; + while ((*newval != '>') && (*newval != '\0')) { + cp = newval; + tmp = simple_strtoul(cp, &newval, 16); + if ((newval - cp) <= 2) { + *data = tmp & 0xFF; + data += 1; + *len += 1; + } else if ((newval - cp) <= 4) { + *(uint16_t *)data = __cpu_to_be16(tmp); + data += 2; + *len += 2; + } else if ((newval - cp) <= 8) { + *(uint32_t *)data = __cpu_to_be32(tmp); + data += 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); + *data++ = tmp & 0xFF; + *len++; + while (*newval == ' ') + newval++; + } + if (*newval != ']') { + printf("Unexpected character '%c'\n", *newval); + 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); + } + return 0; +} + +/****************************************************************************/ + +/* + * Heuristic to guess if this is a string or concatenated strings. */ static int is_printable_string(const void *data, int len) @@ -571,6 +504,12 @@ static int is_printable_string(const void *data, int len) return 1; } + +/* + * Print the property in the best format, a heuristic guess. Print as + * a string, concatenated strings, a byte, word, double word, or (if all + * else fails) it is printed as a stream of bytes. + */ static void print_data(const void *data, int len) { int j; @@ -626,6 +565,119 @@ static void print_data(const void *data, int len) } } +/****************************************************************************/ + +/* + * Recursively print (a portion of) the fdt. The depth parameter + * determines how deeply nested the fdt is printed. + */ +static int fdt_print(char *pathp, char *prop, int depth) +{ + static int offstack[MAX_LEVEL]; + static char tabs[MAX_LEVEL+1] = + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; + void *nodep; /* property node pointer */ + int nodeoffset; /* node offset from libfdt */ + int nextoffset; /* next node offset from libfdt */ + uint32_t tag; /* tag */ + int len; /* length of the property */ + int level = 0; /* keep track of nesting level */ + + nodeoffset = findnodeoffset(pathp); + if (nodeoffset < 0) { + /* + * Not found or something else bad happened. + */ + return 1; + } + /* + * The user passed in a property as well as node path. + * Print only the given property and then return. + */ + if (prop) { + nodep = fdt_getprop (fdt, nodeoffset, prop, &len); + if (len == 0) { + /* no property value */ + printf("%s %s\n", pathp, prop); + return 0; + } else if (len > 0) { + printf("%s=", prop); + print_data (nodep, len); + printf("\n"); + return 0; + } else { + printf ("libfdt fdt_getprop(): %s\n", + fdt_strerror(len)); + return 1; + } + } + + /* + * The user passed in a node path and no property, + * print the node and all subnodes. + */ + offstack[0] = nodeoffset; + + while(level >= 0) { + tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, &pathp); + switch(tag) { + case FDT_BEGIN_NODE: + if(level <= depth) + printf("%s%s {\n", + &tabs[MAX_LEVEL - level], pathp); + level++; + offstack[level] = nodeoffset; + if (level >= MAX_LEVEL) { + printf("Aaaiii nested too deep. " + "Aborting.\n"); + return 1; + } + break; + case FDT_END_NODE: + level--; + if(level <= depth) + printf("%s};\n", &tabs[MAX_LEVEL - level]); + if (level == 0) { + level = -1; /* exit the loop */ + } + break; + case FDT_PROP: + nodep = fdt_getprop (fdt, offstack[level], pathp, &len); + if (len < 0) { + printf ("libfdt fdt_getprop(): %s\n", + fdt_strerror(len)); + return 1; + } else if (len == 0) { + /* the property has no value */ + if(level <= depth) + printf("%s%s;\n", + &tabs[MAX_LEVEL - level], + pathp); + } else { + if(level <= depth) { + printf("%s%s=", + &tabs[MAX_LEVEL - level], + pathp); + print_data (nodep, len); + printf(";\n"); + } + } + break; + case FDT_NOP: + break; + case FDT_END: + return 1; + default: + if(level <= depth) + printf("Unknown tag 0x%08X\n", tag); + return 1; + } + nodeoffset = nextoffset; + } + return 0; +} + /********************************************************************/ U_BOOT_CMD( -- cgit v1.1 From 1a861169bc3758f9de3aead62b058736c6891246 Mon Sep 17 00:00:00 2001 From: Gerald Van Baren Date: Wed, 6 Jun 2007 22:47:58 -0400 Subject: Replace fdt_node_offset() with fdt_find_node_by_path(). The new name matches more closely the kernel's name, which is also a much better description. Signed-off-by: Wolfgang Grandegger Acked-by: Gerald Van Baren --- common/cmd_fdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common/cmd_fdt.c') diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 7066d7d..65960c6 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -59,7 +59,7 @@ static int findnodeoffset(const char *pathp) if (strcmp(pathp, "/") == 0) { nodeoffset = 0; } else { - nodeoffset = fdt_path_offset (fdt, pathp); + nodeoffset = fdt_find_node_by_path (fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. -- cgit v1.1 From 06e19a07701c968f15d72c083b5872a1a11c7b01 Mon Sep 17 00:00:00 2001 From: Gerald Van Baren Date: Mon, 21 May 2007 23:27:16 -0400 Subject: For fdt_find_node_by_path(), handle the root path properly. Also removes the special case root path detection in cmd_fdt.c since it is no longer necessary. Signed-off-by: Gerald Van Baren --- common/cmd_fdt.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) (limited to 'common/cmd_fdt.c') diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 65960c6..7669676 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -52,25 +52,6 @@ static int fdt_parse_prop(char *pathp, char *prop, char *newval, char *data, int *len); static int fdt_print(char *pathp, char *prop, int depth); -static int findnodeoffset(const char *pathp) -{ - int nodeoffset; - - if (strcmp(pathp, "/") == 0) { - nodeoffset = 0; - } else { - nodeoffset = fdt_find_node_by_path (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. */ @@ -187,11 +168,13 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) pathp = argv[2]; nodep = argv[3]; - nodeoffset = findnodeoffset(pathp); + nodeoffset = fdt_find_node_by_path (fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ + printf ("libfdt fdt_find_node_by_path() returned %s\n", + fdt_strerror(nodeoffset)); return 1; } err = fdt_add_subnode(fdt, nodeoffset, nodep); @@ -225,11 +208,13 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) prop = argv[3]; newval = argv[4]; - nodeoffset = findnodeoffset(pathp); + nodeoffset = fdt_find_node_by_path (fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ + printf ("libfdt fdt_find_node_by_path() returned %s\n", + fdt_strerror(nodeoffset)); return 1; } ret = fdt_parse_prop(pathp, prop, newval, data, &len); @@ -283,11 +268,13 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) * Get the path. The root node is an oddball, the offset * is zero and has no name. */ - nodeoffset = findnodeoffset(argv[2]); + nodeoffset = fdt_find_node_by_path (fdt, argv[2]); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ + printf ("libfdt fdt_find_node_by_path() returned %s\n", + fdt_strerror(nodeoffset)); return 1; } /* @@ -584,11 +571,13 @@ static int fdt_print(char *pathp, char *prop, int depth) int len; /* length of the property */ int level = 0; /* keep track of nesting level */ - nodeoffset = findnodeoffset(pathp); + nodeoffset = fdt_find_node_by_path (fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ + printf ("libfdt fdt_find_node_by_path() returned %s\n", + fdt_strerror(nodeoffset)); return 1; } /* -- cgit v1.1 From fd61e55dd8cb52ce3ff91b3917af26e24b6b0845 Mon Sep 17 00:00:00 2001 From: Gerald Van Baren Date: Mon, 25 Jun 2007 23:25:28 -0400 Subject: Create new fdt boardsetup command, fix bug parsing [] form of set values. Previously ft_board_setup() was called by fdt_chosen() which was not really correctly structured. This splits ft_board_setup() out by creating a new fdt boardsetup command. Fix a bug when parsing fdt set command values which have the square bracket form [00 11 22 33] - the length was updated incorrectly in when parsing that form. Signed-off-by: Gerald Van Baren --- common/cmd_fdt.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'common/cmd_fdt.c') diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 7669676..824088c 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -37,7 +37,7 @@ #include #define MAX_LEVEL 32 /* how deeply nested we will go */ -#define SCRATCHPAD 1024 /* bytes of scratchpad memory */ +#define SCRATCHPAD 1024 /* bytes of scratchpad memory */ /* * Global data (for the gd->bd) @@ -47,6 +47,10 @@ DECLARE_GLOBAL_DATA_PTR; /* * Function prototypes/declarations. */ +#ifdef CONFIG_OF_BOARD_SETUP +void ft_board_setup(void *blob, bd_t *bd); +#endif + static int fdt_valid(void); static int fdt_parse_prop(char *pathp, char *prop, char *newval, char *data, int *len); @@ -297,6 +301,13 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } } +#ifdef CONFIG_OF_BOARD_SETUP + /******************************************************************** + * Call the board-specific fixup routine + ********************************************************************/ + } else if (argv[1][0] == 'b') { + ft_board_setup(fdt, gd->bd); +#endif /******************************************************************** * Create a chosen node ********************************************************************/ @@ -429,7 +440,7 @@ static int fdt_parse_prop(char *pathp, char *prop, char *newval, while ((*newval != ']') && (*newval != '\0')) { tmp = simple_strtoul(newval, &newval, 16); *data++ = tmp & 0xFF; - *len++; + *len = *len + 1; while (*newval == ' ') newval++; } @@ -673,25 +684,25 @@ U_BOOT_CMD( fdt, 5, 0, do_fdt, "fdt - flattened device tree utility commands\n", "addr [] - Set the fdt location to \n" +#ifdef CONFIG_OF_BOARD_SETUP + "fdt boardsetup - Do board-specific set up\n" +#endif "fdt move - Copy the fdt to \n" "fdt print [] - Recursive print starting at \n" "fdt list [] - Print one level starting at \n" "fdt set [] - Set [to ]\n" "fdt mknode - Create a new node after \n" "fdt rm [] - Delete the node or \n" - "fdt chosen - Add/update the \"/chosen\" branch in the tree\n" + "fdt chosen - Add/update the /chosen branch in the tree\n" #ifdef CONFIG_OF_HAS_UBOOT_ENV - "fdt env - Add/replace the \"/u-boot-env\" branch in the tree\n" + "fdt env - Add/replace the /u-boot-env branch in the tree\n" #endif #ifdef CONFIG_OF_HAS_BD_T - "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 "Hints:\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" - " it will be ignored as a comment.\n" - " * If the value has spaces in it, you MUST escape the spaces with\n" - " \\ characters or quote it with \"\"\n" + " If the property you are setting/printing has a '#' character or spaces,\n" + " you MUST escape it with a \\ character or quote it with \".\n" "Examples: fdt print / # print the whole tree\n" " fdt print /cpus \"#address-cells\"\n" " fdt set /cpus \"#address-cells\" \"[00 00 00 01]\"\n" -- cgit v1.1 From e125a2ffc209dd34794e326c7175658253beadf3 Mon Sep 17 00:00:00 2001 From: Gerald Van Baren Date: Tue, 10 Jul 2007 20:40:39 -0400 Subject: Call ft_board_setup() from the bootm command. In the patch titled "Create new fdt boardsetup command..." I removed the call to ft_board_setup() from the routine fdt_chosen(), but I forgot to add a direct call back into cmd_bootm.c This fixes the oversight by adding the direct call to the bootm command. Signed-off-by: Gerald Van Baren --- common/cmd_fdt.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'common/cmd_fdt.c') diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 824088c..9ddec47 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -44,13 +44,6 @@ */ DECLARE_GLOBAL_DATA_PTR; -/* - * Function prototypes/declarations. - */ -#ifdef CONFIG_OF_BOARD_SETUP -void ft_board_setup(void *blob, bd_t *bd); -#endif - static int fdt_valid(void); static int fdt_parse_prop(char *pathp, char *prop, char *newval, char *data, int *len); -- cgit v1.1 From 99dffca3b7590a16a00bc475c860b67b2a3f1462 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Tue, 17 Jul 2007 13:57:04 -0500 Subject: fdt: allow for builds that don't want env and bd_t nodes protect fdt_env and fdt_bd_t invocations, fix codingstyle while in the area. Signed-off-by: Kim Phillips --- common/cmd_fdt.c | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) (limited to 'common/cmd_fdt.c') diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 9ddec47..571b8f1 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -293,36 +293,28 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return err; } } - + } #ifdef CONFIG_OF_BOARD_SETUP - /******************************************************************** - * Call the board-specific fixup routine - ********************************************************************/ - } else if (argv[1][0] == 'b') { + /* Call the board-specific fixup routine */ + else if (argv[1][0] == 'b') ft_board_setup(fdt, gd->bd); #endif - /******************************************************************** - * Create a chosen node - ********************************************************************/ - } else if (argv[1][0] == 'c') { + /* Create a chosen node */ + else if (argv[1][0] == 'c') fdt_chosen(fdt, 0, 0, 1); - /******************************************************************** - * Create a u-boot-env node - ********************************************************************/ - } else if (argv[1][0] == 'e') { +#ifdef CONFIG_OF_HAS_UBOOT_ENV + /* Create a u-boot-env node */ + else if (argv[1][0] == 'e') fdt_env(fdt); - - /******************************************************************** - * Create a bd_t node - ********************************************************************/ - } else if (argv[1][0] == 'b') { +#endif +#ifdef CONFIG_OF_HAS_BD_T + /* Create a bd_t node */ + else if (argv[1][0] == 'b') fdt_bd_t(fdt); - - /******************************************************************** - * Unrecognized command - ********************************************************************/ - } else { +#endif + else { + /* Unrecognized command */ printf ("Usage:\n%s\n", cmdtp->usage); return 1; } -- cgit v1.1