X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=common%2Fcmd_fdt.c;h=3d0c2b772c95cfed8f95196d0d6c511f60a7c57b;hb=0abddf82d54c704cf066524235b6414333e8d087;hp=ede65ae75a2c55cd1d58d3773ed8786198a6da9e;hpb=10a3367955bc2033b288915f8f10d0e507fe2fa1;p=u-boot diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index ede65ae75a..3d0c2b772c 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -42,27 +42,50 @@ DECLARE_GLOBAL_DATA_PTR; static int fdt_valid(void); -static int fdt_parse_prop(char **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); +/* + * The working_fdt points to our working flattened device tree. + */ +struct fdt_header *working_fdt; + +void set_working_fdt_addr(void *addr) +{ + char buf[17]; + + working_fdt = addr; + + sprintf(buf, "%lx", (unsigned long)addr); + setenv("fdtaddr", buf); +} + /* * 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 * const argv[]) { - if (argc < 2) { - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; - } + if (argc < 2) + return cmd_usage(cmdtp); - /******************************************************************** + /* * Set the address of the fdt - ********************************************************************/ + */ if (argv[1][0] == 'a') { + unsigned long addr; /* * Set the address [and length] of the fdt. */ - fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); + if (argc == 2) { + if (!fdt_valid()) { + return 1; + } + printf("The address of the fdt is %p\n", working_fdt); + return 0; + } + + addr = simple_strtoul(argv[2], NULL, 16); + set_working_fdt_addr((void *)addr); if (!fdt_valid()) { return 1; @@ -75,15 +98,15 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) * Optional new length */ len = simple_strtoul(argv[3], NULL, 16); - if (len < fdt_totalsize(fdt)) { + if (len < fdt_totalsize(working_fdt)) { printf ("New length %d < existing length %d, " "ignoring.\n", - len, fdt_totalsize(fdt)); + len, fdt_totalsize(working_fdt)); } else { /* * Open in place with a new length. */ - err = fdt_open_into(fdt, fdt, len); + err = fdt_open_into(working_fdt, working_fdt, len); if (err != 0) { printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); @@ -91,23 +114,21 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } } - /******************************************************************** - * Move the fdt - ********************************************************************/ - } else if ((argv[1][0] == 'm') && (argv[1][1] == 'o')) { + /* + * Move the working_fdt + */ + } else if (strncmp(argv[1], "mo", 2) == 0) { struct fdt_header *newaddr; int len; int err; - if (argc < 4) { - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; - } + if (argc < 4) + return cmd_usage(cmdtp); /* * Set the address and length of the fdt. */ - fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); + working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); if (!fdt_valid()) { return 1; } @@ -119,13 +140,13 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) * current length. */ if (argc <= 4) { - len = fdt_totalsize(fdt); + len = fdt_totalsize(working_fdt); } else { len = simple_strtoul(argv[4], NULL, 16); - if (len < fdt_totalsize(fdt)) { + if (len < fdt_totalsize(working_fdt)) { printf ("New length 0x%X < existing length " "0x%X, aborting.\n", - len, fdt_totalsize(fdt)); + len, fdt_totalsize(working_fdt)); return 1; } } @@ -133,18 +154,18 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /* * Copy to the new location. */ - err = fdt_open_into(fdt, newaddr, len); + err = fdt_open_into(working_fdt, newaddr, len); if (err != 0) { printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); return 1; } - fdt = newaddr; + working_fdt = newaddr; - /******************************************************************** + /* * Make a new node - ********************************************************************/ - } else if ((argv[1][0] == 'm') && (argv[1][1] == 'k')) { + */ + } else if (strncmp(argv[1], "mk", 2) == 0) { char *pathp; /* path */ char *nodep; /* new node to add */ int nodeoffset; /* node offset from libfdt */ @@ -153,15 +174,13 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /* * Parameters: Node path, new node to be appended to the path. */ - if (argc < 4) { - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; - } + if (argc < 4) + return cmd_usage(cmdtp); pathp = argv[2]; nodep = argv[3]; - nodeoffset = fdt_path_offset (fdt, pathp); + nodeoffset = fdt_path_offset (working_fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. @@ -170,16 +189,16 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) fdt_strerror(nodeoffset)); return 1; } - err = fdt_add_subnode(fdt, nodeoffset, nodep); + err = fdt_add_subnode(working_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. - ********************************************************************/ + /* + * Set the value of a property in the working_fdt. + */ } else if (argv[1][0] == 's') { char *pathp; /* path */ char *prop; /* property */ @@ -191,10 +210,8 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /* * Parameters: Node path, property, optional value. */ - if (argc < 4) { - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; - } + if (argc < 4) + return cmd_usage(cmdtp); pathp = argv[2]; prop = argv[3]; @@ -206,7 +223,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return ret; } - nodeoffset = fdt_path_offset (fdt, pathp); + nodeoffset = fdt_path_offset (working_fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. @@ -216,15 +233,15 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; } - ret = fdt_setprop(fdt, nodeoffset, prop, data, len); + ret = fdt_setprop(working_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 ((argv[1][0] == 'p') || (argv[1][0] == 'l')) { int depth = MAX_LEVEL; /* how deep to print */ char *pathp; /* path */ @@ -256,10 +273,10 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if (ret != 0) return ret; - /******************************************************************** + /* * Remove a property/node - ********************************************************************/ - } else if ((argv[1][0] == 'r') && (argv[1][1] == 'm')) { + */ + } else if (strncmp(argv[1], "rm", 2) == 0) { int nodeoffset; /* node offset from libfdt */ int err; @@ -267,7 +284,7 @@ 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 = fdt_path_offset (fdt, argv[2]); + nodeoffset = fdt_path_offset (working_fdt, argv[2]); if (nodeoffset < 0) { /* * Not found or something else bad happened. @@ -281,14 +298,14 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) * otherwise delete the node. */ if (argc > 3) { - err = fdt_delprop(fdt, nodeoffset, argv[3]); + err = fdt_delprop(working_fdt, nodeoffset, argv[3]); if (err < 0) { printf("libfdt fdt_delprop(): %s\n", fdt_strerror(err)); return err; } } else { - err = fdt_del_node(fdt, nodeoffset); + err = fdt_del_node(working_fdt, nodeoffset); if (err < 0) { printf("libfdt fdt_del_node(): %s\n", fdt_strerror(err)); @@ -296,68 +313,68 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } } - /******************************************************************** + /* * Display header info - ********************************************************************/ + */ } else if (argv[1][0] == 'h') { - u32 version = fdt_version(fdt); - printf("magic:\t\t\t0x%x\n", fdt_magic(fdt)); - printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(fdt), fdt_totalsize(fdt)); - printf("off_dt_struct:\t\t0x%x\n", fdt_off_dt_struct(fdt)); - printf("off_dt_strings:\t\t0x%x\n", fdt_off_dt_strings(fdt)); - printf("off_mem_rsvmap:\t\t0x%x\n", fdt_off_mem_rsvmap(fdt)); + u32 version = fdt_version(working_fdt); + printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt)); + printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt), + fdt_totalsize(working_fdt)); + printf("off_dt_struct:\t\t0x%x\n", + fdt_off_dt_struct(working_fdt)); + printf("off_dt_strings:\t\t0x%x\n", + fdt_off_dt_strings(working_fdt)); + printf("off_mem_rsvmap:\t\t0x%x\n", + fdt_off_mem_rsvmap(working_fdt)); printf("version:\t\t%d\n", version); - printf("last_comp_version:\t%d\n", fdt_last_comp_version(fdt)); + printf("last_comp_version:\t%d\n", + fdt_last_comp_version(working_fdt)); if (version >= 2) printf("boot_cpuid_phys:\t0x%x\n", - fdt_boot_cpuid_phys(fdt)); + fdt_boot_cpuid_phys(working_fdt)); if (version >= 3) printf("size_dt_strings:\t0x%x\n", - fdt_size_dt_strings(fdt)); + fdt_size_dt_strings(working_fdt)); if (version >= 17) printf("size_dt_struct:\t\t0x%x\n", - fdt_size_dt_struct(fdt)); - printf("number mem_rsv:\t\t0x%x\n", fdt_num_mem_rsv(fdt)); + fdt_size_dt_struct(working_fdt)); + printf("number mem_rsv:\t\t0x%x\n", + fdt_num_mem_rsv(working_fdt)); printf("\n"); - /******************************************************************** + /* * Set boot cpu id - ********************************************************************/ - } else if ((argv[1][0] == 'b') && (argv[1][1] == 'o') && - (argv[1][2] == 'o')) { + */ + } else if (strncmp(argv[1], "boo", 3) == 0) { unsigned long tmp = simple_strtoul(argv[2], NULL, 16); - fdt_set_boot_cpuid_phys(fdt, tmp); + fdt_set_boot_cpuid_phys(working_fdt, tmp); - /******************************************************************** + /* * memory command - ********************************************************************/ - } else if ((argv[1][0] == 'm') && (argv[1][1] == 'e')) { + */ + } else if (strncmp(argv[1], "me", 2) == 0) { uint64_t addr, size; int err; -#ifdef CFG_64BIT_STRTOUL - addr = simple_strtoull(argv[2], NULL, 16); - size = simple_strtoull(argv[3], NULL, 16); -#else - addr = simple_strtoul(argv[2], NULL, 16); - size = simple_strtoul(argv[3], NULL, 16); -#endif - err = fdt_fixup_memory(fdt, addr, size); + addr = simple_strtoull(argv[2], NULL, 16); + size = simple_strtoull(argv[3], NULL, 16); + err = fdt_fixup_memory(working_fdt, addr, size); if (err < 0) return err; - /******************************************************************** + /* * mem reserve commands - ********************************************************************/ - } else if ((argv[1][0] == 'r') && (argv[1][1] == 's')) { + */ + } else if (strncmp(argv[1], "rs", 2) == 0) { if (argv[2][0] == 'p') { uint64_t addr, size; - int total = fdt_num_mem_rsv(fdt); + int total = fdt_num_mem_rsv(working_fdt); int j, err; printf("index\t\t start\t\t size\n"); printf("-------------------------------" "-----------------\n"); for (j = 0; j < total; j++) { - err = fdt_get_mem_rsv(fdt, j, &addr, &size); + err = fdt_get_mem_rsv(working_fdt, j, &addr, &size); if (err < 0) { printf("libfdt fdt_get_mem_rsv(): %s\n", fdt_strerror(err)); @@ -372,14 +389,9 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } else if (argv[2][0] == 'a') { uint64_t addr, size; int err; -#ifdef CFG_64BIT_STRTOUL addr = simple_strtoull(argv[3], NULL, 16); size = simple_strtoull(argv[4], NULL, 16); -#else - addr = simple_strtoul(argv[3], NULL, 16); - size = simple_strtoul(argv[4], NULL, 16); -#endif - err = fdt_add_mem_rsv(fdt, addr, size); + err = fdt_add_mem_rsv(working_fdt, addr, size); if (err < 0) { printf("libfdt fdt_add_mem_rsv(): %s\n", @@ -388,7 +400,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } } else if (argv[2][0] == 'd') { unsigned long idx = simple_strtoul(argv[3], NULL, 16); - int err = fdt_del_mem_rsv(fdt, idx); + int err = fdt_del_mem_rsv(working_fdt, idx); if (err < 0) { printf("libfdt fdt_del_mem_rsv(): %s\n", @@ -397,22 +409,36 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } } else { /* Unrecognized command */ - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; + return cmd_usage(cmdtp); } } #ifdef CONFIG_OF_BOARD_SETUP /* Call the board-specific fixup routine */ - else if (argv[1][0] == 'b') - ft_board_setup(fdt, gd->bd); + else if (strncmp(argv[1], "boa", 3) == 0) + ft_board_setup(working_fdt, gd->bd); #endif /* Create a chosen node */ - else if (argv[1][0] == 'c') - fdt_chosen(fdt, 0, 0, 1); + else if (argv[1][0] == 'c') { + unsigned long initrd_start = 0, initrd_end = 0; + + if ((argc != 2) && (argc != 4)) + return cmd_usage(cmdtp); + + if (argc == 4) { + initrd_start = simple_strtoul(argv[2], NULL, 16); + initrd_end = simple_strtoul(argv[3], NULL, 16); + } + + fdt_chosen(working_fdt, 1); + fdt_initrd(working_fdt, initrd_start, initrd_end, 1); + } + /* resize the fdt */ + else if (strncmp(argv[1], "re", 2) == 0) { + fdt_resize(working_fdt); + } else { /* Unrecognized command */ - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; + return cmd_usage(cmdtp); } return 0; @@ -424,12 +450,12 @@ static int fdt_valid(void) { int err; - if (fdt == NULL) { + if (working_fdt == NULL) { printf ("The address of the fdt is invalid (NULL).\n"); return 0; } - err = fdt_check_header(fdt); + err = fdt_check_header(working_fdt); if (err == 0) return 1; /* valid */ @@ -439,17 +465,19 @@ static int fdt_valid(void) * Be more informative on bad version. */ if (err == -FDT_ERR_BADVERSION) { - if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) { - printf (" - too old, fdt $d < %d", - fdt_version(fdt), + if (fdt_version(working_fdt) < + FDT_FIRST_SUPPORTED_VERSION) { + printf (" - too old, fdt %d < %d", + fdt_version(working_fdt), FDT_FIRST_SUPPORTED_VERSION); - fdt = NULL; + working_fdt = NULL; } - if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) { - printf (" - too new, fdt $d > %d", - fdt_version(fdt), + if (fdt_last_comp_version(working_fdt) > + FDT_LAST_SUPPORTED_VERSION) { + printf (" - too new, fdt %d > %d", + fdt_version(working_fdt), FDT_LAST_SUPPORTED_VERSION); - fdt = NULL; + working_fdt = NULL; } return 0; } @@ -475,7 +503,7 @@ static int fdt_valid(void) * data: A bytestream to be placed in the property * len: The length of the resulting bytestream */ -static int fdt_parse_prop(char **newval, int count, char *data, int *len) +static int fdt_parse_prop(char * const *newval, int count, char *data, int *len) { char *cp; /* temporary char pointer */ char *newp; /* temporary newval char pointer */ @@ -524,27 +552,34 @@ static int fdt_parse_prop(char **newval, int count, char *data, int *len) * Byte stream. Convert the values. */ newp++; - while ((*newp != ']') && (stridx < count)) { - tmp = simple_strtoul(newp, &newp, 16); - *data++ = tmp & 0xFF; - *len = *len + 1; + while ((stridx < count) && (*newp != ']')) { while (*newp == ' ') newp++; - if (*newp != '\0') + if (*newp == '\0') { newp = newval[++stridx]; + continue; + } + if (!isxdigit(*newp)) + break; + tmp = simple_strtoul(newp, &newp, 16); + *data++ = tmp & 0xFF; + *len = *len + 1; } if (*newp != ']') { - printf("Unexpected character '%c'\n", *newval); + printf("Unexpected character '%c'\n", *newp); return 1; } } else { /* - * Assume it is a string. Copy it into our data area for - * convenience (including the terminating '\0'). + * Assume it is one or more strings. Copy it into our + * data area for convenience (including the + * terminating '\0's). */ while (stridx < count) { - *len = strlen(newp) + 1; + size_t length = strlen(newp) + 1; strcpy(data, newp); + data += length; + *len += length; newp = newval[++stridx]; } } @@ -645,7 +680,7 @@ static void print_data(const void *data, int len) /****************************************************************************/ /* - * Recursively print (a portion of) the fdt. The depth parameter + * Recursively print (a portion of) the working_fdt. The depth parameter * determines how deeply nested the fdt is printed. */ static int fdt_print(const char *pathp, char *prop, int depth) @@ -661,7 +696,7 @@ static int fdt_print(const char *pathp, char *prop, int depth) int level = 0; /* keep track of nesting level */ const struct fdt_property *fdt_prop; - nodeoffset = fdt_path_offset (fdt, pathp); + nodeoffset = fdt_path_offset (working_fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. @@ -675,7 +710,7 @@ static int fdt_print(const char *pathp, char *prop, int depth) * Print only the given property and then return. */ if (prop) { - nodep = fdt_getprop (fdt, nodeoffset, prop, &len); + nodep = fdt_getprop (working_fdt, nodeoffset, prop, &len); if (len == 0) { /* no property value */ printf("%s %s\n", pathp, prop); @@ -697,10 +732,10 @@ static int fdt_print(const char *pathp, char *prop, int depth) * print the node and all subnodes. */ while(level >= 0) { - tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); + tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset); switch(tag) { case FDT_BEGIN_NODE: - pathp = fdt_get_name(fdt, nodeoffset, NULL); + pathp = fdt_get_name(working_fdt, nodeoffset, NULL); if (level <= depth) { if (pathp == NULL) pathp = "/* NULL pointer error */"; @@ -724,9 +759,9 @@ static int fdt_print(const char *pathp, char *prop, int depth) } break; case FDT_PROP: - fdt_prop = fdt_offset_ptr(fdt, nodeoffset, + fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset, sizeof(*fdt_prop)); - pathp = fdt_string(fdt, + pathp = fdt_string(working_fdt, fdt32_to_cpu(fdt_prop->nameoff)); len = fdt32_to_cpu(fdt_prop->len); nodep = fdt_prop->data; @@ -751,7 +786,7 @@ static int fdt_print(const char *pathp, char *prop, int depth) } break; case FDT_NOP: - printf("/* NOP */\n", &tabs[MAX_LEVEL - level]); + printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]); break; case FDT_END: return 1; @@ -769,12 +804,13 @@ static int fdt_print(const char *pathp, char *prop, int depth) U_BOOT_CMD( fdt, 255, 0, do_fdt, - "fdt - flattened device tree utility commands\n", + "flattened device tree utility commands", "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 and make it active\n" + "fdt resize - Resize fdt to size + padding to 4k addr\n" "fdt print [] - Recursive print starting at \n" "fdt list [] - Print one level starting at \n" "fdt set [] - Set [to ]\n" @@ -786,7 +822,8 @@ U_BOOT_CMD( "fdt rsvmem print - Show current mem reserves\n" "fdt rsvmem add - Add a mem reserve\n" "fdt rsvmem delete - Delete a mem reserves\n" - "fdt chosen - Add/update the /chosen branch in the tree\n" - "NOTE: If the path or property you are setting/printing has a '#' character\n" - " or spaces, you MUST escape it with a \\ character or quote it with \".\n" + "fdt chosen [ ] - Add/update the /chosen branch in the tree\n" + " / - initrd start/end addr\n" + "NOTE: Dereference aliases by omiting the leading '/', " + "e.g. fdt print ethernet0." );