From 9eaeb07a7185d852c7aa10735ecd4e9edf24fb5d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 11 Jan 2008 14:55:05 +1100 Subject: [PATCH 01/11] libfdt: Add fdt_set_name() function This patch adds an fdt_set_name() function to libfdt, mirroring fdt_get_name(). This is a r/w function which alters the name of a given device tree node. Signed-off-by: David Gibson --- include/libfdt.h | 26 ++++++++++++++++++++++++++ libfdt/fdt_rw.c | 24 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/libfdt.h b/include/libfdt.h index 6c05236858..f634a9c8df 100644 --- a/include/libfdt.h +++ b/include/libfdt.h @@ -845,6 +845,32 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); */ int fdt_del_mem_rsv(void *fdt, int n); +/** + * fdt_set_name - change the name of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * @name: name to give the node + * + * fdt_set_name() replaces the name (including unit address, if any) + * of the given node with the given string. NOTE: this function can't + * efficiently check if the new name is unique amongst the given + * node's siblings; results are undefined if this function is invoked + * with a name equal to one of the given node's siblings. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob + * to contain the new name + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_set_name(void *fdt, int nodeoffset, const char *name); + /** * fdt_setprop - create or change a property * @fdt: pointer to the device tree blob diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 6673f8ec96..a1c70ff154 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -252,6 +252,30 @@ static int _add_property(void *fdt, int nodeoffset, const char *name, int len, return 0; } +int fdt_set_name(void *fdt, int nodeoffset, const char *name) +{ + char *namep; + int oldlen, newlen; + int err; + + if ((err = rw_check_header(fdt))) + return err; + + namep = (char *)fdt_get_name(fdt, nodeoffset, &oldlen); + if (!namep) + return oldlen; + + newlen = strlen(name); + + err = _blob_splice_struct(fdt, namep, ALIGN(oldlen+1, FDT_TAGSIZE), + ALIGN(newlen+1, FDT_TAGSIZE)); + if (err) + return err; + + memcpy(namep, name, newlen+1); + return 0; +} + int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len) { From ae0b5908de3b9855f8931bc9b32c9fc4962df5a9 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 12 Feb 2008 11:58:31 +1100 Subject: [PATCH 02/11] libfdt: Add and use a node iteration helper function. This patch adds an fdt_next_node() function which can be used to iterate through nodes of the tree while keeping track of depth. This function is used to simplify the iteration code in a lot of other functions, and is also exported for use by library users. Signed-off-by: David Gibson --- include/libfdt.h | 6 ++ libfdt/fdt.c | 41 ++++++++ libfdt/fdt_ro.c | 258 +++++++++++++++-------------------------------- 3 files changed, 131 insertions(+), 174 deletions(-) diff --git a/include/libfdt.h b/include/libfdt.h index f634a9c8df..beeacb2e07 100644 --- a/include/libfdt.h +++ b/include/libfdt.h @@ -130,6 +130,12 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); +/**********************************************************************/ +/* Traversal functions */ +/**********************************************************************/ + +int fdt_next_node(const void *fdt, int offset, int *depth); + /**********************************************************************/ /* General functions */ /**********************************************************************/ diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 586a36136d..c61fb531b3 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -129,6 +129,47 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset) return tag; } +int fdt_next_node(const void *fdt, int offset, int *depth) +{ + int nextoffset = 0; + uint32_t tag; + + if (offset >= 0) { + tag = fdt_next_tag(fdt, offset, &nextoffset); + if (tag != FDT_BEGIN_NODE) + return -FDT_ERR_BADOFFSET; + } + + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_PROP: + case FDT_NOP: + break; + + case FDT_BEGIN_NODE: + if (depth) + (*depth)++; + break; + + case FDT_END_NODE: + if (depth) + (*depth)--; + break; + + case FDT_END: + return -FDT_ERR_NOTFOUND; + + default: + return -FDT_ERR_BADSTRUCTURE; + } + } while (tag != FDT_BEGIN_NODE); + + return offset; +} + const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) { int len = strlen(s) + 1; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 12a37d59f9..f08941a7ad 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -65,7 +65,7 @@ static int nodename_eq(const void *fdt, int offset, const char *s, int len) { - const char *p = fdt_offset_ptr(fdt, offset, len+1); + const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); if (! p) /* short match */ @@ -104,50 +104,24 @@ int fdt_num_mem_rsv(const void *fdt) return i; } -int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, +int fdt_subnode_offset_namelen(const void *fdt, int offset, const char *name, int namelen) { - int level = 0; - uint32_t tag; - int offset, nextoffset; + int depth; CHECK_HEADER(fdt); - tag = fdt_next_tag(fdt, parentoffset, &nextoffset); - if (tag != FDT_BEGIN_NODE) - return -FDT_ERR_BADOFFSET; + for (depth = 0; + offset >= 0; + offset = fdt_next_node(fdt, offset, &depth)) { + if (depth < 0) + return -FDT_ERR_NOTFOUND; + else if ((depth == 1) + && nodename_eq(fdt, offset, name, namelen)) + return offset; + } - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - - switch (tag) { - case FDT_END: - return -FDT_ERR_TRUNCATED; - - case FDT_BEGIN_NODE: - level++; - if (level != 1) - continue; - if (nodename_eq(fdt, offset+FDT_TAGSIZE, name, namelen)) - /* Found it! */ - return offset; - break; - - case FDT_END_NODE: - level--; - break; - - case FDT_PROP: - case FDT_NOP: - break; - - default: - return -FDT_ERR_BADSTRUCTURE; - } - } while (level >= 0); - - return -FDT_ERR_NOTFOUND; + return offset; /* error */ } int fdt_subnode_offset(const void *fdt, int parentoffset, @@ -307,76 +281,61 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) { - uint32_t tag; - int p = 0, overflow = 0; - int offset, nextoffset, namelen; + int pdepth = 0, p = 0; + int offset, depth, namelen; const char *name; CHECK_HEADER(fdt); - tag = fdt_next_tag(fdt, 0, &nextoffset); - if (tag != FDT_BEGIN_NODE) - return -FDT_ERR_BADSTRUCTURE; - if (buflen < 2) return -FDT_ERR_NOSPACE; - buf[0] = '/'; - p = 1; - while (nextoffset <= nodeoffset) { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - switch (tag) { - case FDT_END: - return -FDT_ERR_BADOFFSET; + for (offset = 0, depth = 0; + (offset >= 0) && (offset <= nodeoffset); + offset = fdt_next_node(fdt, offset, &depth)) { + if (pdepth < depth) + continue; /* overflowed buffer */ - case FDT_BEGIN_NODE: - name = fdt_get_name(fdt, offset, &namelen); - if (!name) - return namelen; - if (overflow || ((p + namelen + 1) > buflen)) { - overflow++; - break; - } + while (pdepth > depth) { + do { + p--; + } while (buf[p-1] != '/'); + pdepth--; + } + + name = fdt_get_name(fdt, offset, &namelen); + if (!name) + return namelen; + if ((p + namelen + 1) <= buflen) { memcpy(buf + p, name, namelen); p += namelen; buf[p++] = '/'; - break; + pdepth++; + } - case FDT_END_NODE: - if (overflow) { - overflow--; - break; - } - do { + if (offset == nodeoffset) { + if (pdepth < (depth + 1)) + return -FDT_ERR_NOSPACE; + + if (p > 1) /* special case so that root path is "/", not "" */ p--; - } while (buf[p-1] != '/'); - break; - - case FDT_PROP: - case FDT_NOP: - break; - - default: - return -FDT_ERR_BADSTRUCTURE; + buf[p] = '\0'; + return p; } } - if (overflow) - return -FDT_ERR_NOSPACE; + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; - if (p > 1) /* special case so that root path is "/", not "" */ - p--; - buf[p] = '\0'; - return p; + return offset; /* error from fdt_next_node() */ } int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, int supernodedepth, int *nodedepth) { - int level = -1; - uint32_t tag; - int offset, nextoffset = 0; + int offset, depth; int supernodeoffset = -FDT_ERR_INTERNAL; CHECK_HEADER(fdt); @@ -384,38 +343,29 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, if (supernodedepth < 0) return -FDT_ERR_NOTFOUND; - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - switch (tag) { - case FDT_END: - return -FDT_ERR_BADOFFSET; + for (offset = 0, depth = 0; + (offset >= 0) && (offset <= nodeoffset); + offset = fdt_next_node(fdt, offset, &depth)) { + if (depth == supernodedepth) + supernodeoffset = offset; - case FDT_BEGIN_NODE: - level++; - if (level == supernodedepth) - supernodeoffset = offset; - break; + if (offset == nodeoffset) { + if (nodedepth) + *nodedepth = depth; - case FDT_END_NODE: - level--; - break; - - case FDT_PROP: - case FDT_NOP: - break; - - default: - return -FDT_ERR_BADSTRUCTURE; + if (supernodedepth > depth) + return -FDT_ERR_NOTFOUND; + else + return supernodeoffset; } - } while (offset < nodeoffset); + } - if (nodedepth) - *nodedepth = level; + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; - if (supernodedepth > level) - return -FDT_ERR_NOTFOUND; - return supernodeoffset; + return offset; /* error from fdt_next_node() */ } int fdt_node_depth(const void *fdt, int nodeoffset) @@ -443,51 +393,27 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, const char *propname, const void *propval, int proplen) { - uint32_t tag; - int offset, nextoffset; + int offset; const void *val; int len; CHECK_HEADER(fdt); - if (startoffset >= 0) { - tag = fdt_next_tag(fdt, startoffset, &nextoffset); - if (tag != FDT_BEGIN_NODE) - return -FDT_ERR_BADOFFSET; - } else { - nextoffset = 0; - } - /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_getprop(), then if that didn't * find what we want, we scan over them again making our way * to the next node. Still it's the easiest to implement * approach; performance can come later. */ - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); + for (offset = fdt_next_node(fdt, startoffset, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + val = fdt_getprop(fdt, offset, propname, &len); + if (val && (len == proplen) + && (memcmp(val, propval, len) == 0)) + return offset; + } - switch (tag) { - case FDT_BEGIN_NODE: - val = fdt_getprop(fdt, offset, propname, &len); - if (val - && (len == proplen) - && (memcmp(val, propval, len) == 0)) - return offset; - break; - - case FDT_PROP: - case FDT_END: - case FDT_END_NODE: - case FDT_NOP: - break; - - default: - return -FDT_ERR_BADSTRUCTURE; - } - } while (tag != FDT_END); - - return -FDT_ERR_NOTFOUND; + return offset; /* error from fdt_next_node() */ } int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) @@ -553,31 +479,15 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, * that didn't find what we want, we scan over them again * making our way to the next node. Still it's the easiest to * implement approach; performance can come later. */ - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); + for (offset = fdt_next_node(fdt, startoffset, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + err = fdt_node_check_compatible(fdt, offset, compatible); + if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) + return err; + else if (err == 0) + return offset; + } - switch (tag) { - case FDT_BEGIN_NODE: - err = fdt_node_check_compatible(fdt, offset, - compatible); - if ((err < 0) - && (err != -FDT_ERR_NOTFOUND)) - return err; - else if (err == 0) - return offset; - break; - - case FDT_PROP: - case FDT_END: - case FDT_END_NODE: - case FDT_NOP: - break; - - default: - return -FDT_ERR_BADSTRUCTURE; - } - } while (tag != FDT_END); - - return -FDT_ERR_NOTFOUND; + return offset; /* error from fdt_next_node() */ } From f84d65f9b085ffbed464d1d58e8aaa8f5a2efc07 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 14 Feb 2008 16:50:34 +1100 Subject: [PATCH 03/11] libfdt: Fix NOP handling bug in fdt_add_subnode_namelen() fdt_add_subnode_namelen() has a bug if asked to add a subnode to a node which has NOP tags interspersed with its properties. In this case fdt_add_subnode_namelen() will put the new subnode before the first NOP tag, even if there are properties after it, which will result in an invalid blob. This patch fixes the bug, and adds a testcase for it. Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index a1c70ff154..ac5019560f 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -333,7 +333,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, do { offset = nextoffset; tag = fdt_next_tag(fdt, offset, &nextoffset); - } while (tag == FDT_PROP); + } while ((tag == FDT_PROP) || (tag == FDT_NOP)); nh = _fdt_offset_ptr_w(fdt, offset); nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE; From 804887e6001e2f00bea11431bf34d6d472512cda Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 15 Feb 2008 03:34:36 -0600 Subject: [PATCH 04/11] Add sub-commands to fdt fdt header - Display header info fdt bootcpu - Set boot cpuid fdt memory - Add/Update memory node fdt rsvmem print - Show current mem reserves fdt rsvmem add - Add a mem reserve fdt rsvmem delete - Delete a mem reserves Signed-off-by: Kumar Gala --- common/cmd_fdt.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 9cd22ee94a..c31560bd65 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -260,7 +260,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /******************************************************************** * Remove a property/node ********************************************************************/ - } else if (argv[1][0] == 'r') { + } else if ((argv[1][0] == 'r') && (argv[1][1] == 'm')) { int nodeoffset; /* node offset from libfdt */ int err; @@ -296,6 +296,110 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return err; } } + + /******************************************************************** + * 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)); + printf("version:\t\t%d\n", version); + printf("last_comp_version:\t%d\n", fdt_last_comp_version(fdt)); + if (version >= 2) + printf("boot_cpuid_phys:\t0x%x\n", + fdt_boot_cpuid_phys(fdt)); + if (version >= 3) + printf("size_dt_strings:\t0x%x\n", + fdt_size_dt_strings(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)); + printf("\n"); + + /******************************************************************** + * Set boot cpu id + ********************************************************************/ + } else if ((argv[1][0] == 'b') && (argv[1][1] == 'o')) { + unsigned long tmp = simple_strtoul(argv[2], NULL, 16); + fdt_set_boot_cpuid_phys(fdt, tmp); + + /******************************************************************** + * memory command + ********************************************************************/ + } else if ((argv[1][0] == 'm') && (argv[1][1] == 'e')) { + 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); + if (err < 0) + return err; + + /******************************************************************** + * mem reserve commands + ********************************************************************/ + } else if ((argv[1][0] == 'r') && (argv[1][1] == 's')) { + if (argv[2][0] == 'p') { + uint64_t addr, size; + int total = fdt_num_mem_rsv(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); + if (err < 0) { + printf("libfdt fdt_get_mem_rsv(): %s\n", + fdt_strerror(err)); + return err; + } + printf(" %x\t%08x%08x\t%08x%08x\n", j, + (u32)(addr >> 32), + (u32)(addr & 0xffffffff), + (u32)(size >> 32), + (u32)(size & 0xffffffff)); + } + } 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); + + if (err < 0) { + printf("libfdt fdt_add_mem_rsv(): %s\n", + fdt_strerror(err)); + return err; + } + } else if (argv[2][0] == 'd') { + unsigned long idx = simple_strtoul(argv[3], NULL, 16); + int err = fdt_del_mem_rsv(fdt, idx); + + if (err < 0) { + printf("libfdt fdt_del_mem_rsv(): %s\n", + fdt_strerror(err)); + return err; + } + } else { + /* Unrecognized command */ + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } } #ifdef CONFIG_OF_BOARD_SETUP /* Call the board-specific fixup routine */ @@ -689,6 +793,12 @@ U_BOOT_CMD( "fdt set [] - Set [to ]\n" "fdt mknode - Create a new node after \n" "fdt rm [] - Delete the node or \n" + "fdt header - Display header info\n" + "fdt bootcpu - Set boot cpuid\n" + "fdt memory - Add/Update memory node\n" + "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" #ifdef CONFIG_OF_HAS_UBOOT_ENV "fdt env - Add/replace the /u-boot-env branch in the tree\n" From fe30a354cdbb808b5f15366a935b151a4ccee74f Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 20 Feb 2008 14:32:36 -0600 Subject: [PATCH 05/11] Fix fdt boardsetup command parsing The introduciton of the 'fdt bootcpu' broke parsing for 'fdt boardsetup'. Signed-off-by: Kumar Gala --- common/cmd_fdt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index c31560bd65..14c3fa022e 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -324,7 +324,8 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /******************************************************************** * Set boot cpu id ********************************************************************/ - } else if ((argv[1][0] == 'b') && (argv[1][1] == 'o')) { + } else if ((argv[1][0] == 'b') && (argv[1][1] == 'o') && + (argv[1][2] == 'o')) { unsigned long tmp = simple_strtoul(argv[2], NULL, 16); fdt_set_boot_cpuid_phys(fdt, tmp); From d0ccb9b140b472039732de102fc14597eedb14df Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 18 Feb 2008 18:06:31 +1100 Subject: [PATCH 06/11] libfdt: Trivial cleanup for CHECK_HEADER) Currently the CHECK_HEADER() macro is defined local to fdt_ro.c. However, there are a handful of functions (fdt_move, rw_check_header, fdt_open_into) from other files which could also use it (currently they open-code something more-or-less identical). Therefore, this patch moves CHECK_HEADER() to libfdt_internal.h and uses it in those places. Signed-off-by: David Gibson --- libfdt/fdt.c | 5 +---- libfdt/fdt_ro.c | 7 ------- libfdt/fdt_rw.c | 8 ++------ libfdt/libfdt_internal.h | 7 +++++++ 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index c61fb531b3..bd91712378 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -184,10 +184,7 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) int fdt_move(const void *fdt, void *buf, int bufsize) { - int err = fdt_check_header(fdt); - - if (err) - return err; + CHECK_HEADER(fdt); if (fdt_totalsize(fdt) > bufsize) return -FDT_ERR_NOSPACE; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index f08941a7ad..15d5f6b585 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -55,13 +55,6 @@ #include "libfdt_internal.h" -#define CHECK_HEADER(fdt) \ - { \ - int err; \ - if ((err = fdt_check_header(fdt)) != 0) \ - return err; \ - } - static int nodename_eq(const void *fdt, int offset, const char *s, int len) { diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index ac5019560f..0df472bc5e 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -69,10 +69,8 @@ static int _blocks_misordered(const void *fdt, static int rw_check_header(void *fdt) { - int err; + CHECK_HEADER(fdt); - if ((err = fdt_check_header(fdt))) - return err; if (fdt_version(fdt) < 17) return -FDT_ERR_BADVERSION; if (_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), @@ -399,9 +397,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) int newsize; void *tmp; - err = fdt_check_header(fdt); - if (err) - return err; + CHECK_HEADER(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 1e60936beb..52e1b8d810 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -58,6 +58,13 @@ #define memeq(p, q, n) (memcmp((p), (q), (n)) == 0) #define streq(p, q) (strcmp((p), (q)) == 0) +#define CHECK_HEADER(fdt) \ + { \ + int err; \ + if ((err = fdt_check_header(fdt)) != 0) \ + return err; \ + } + uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset); const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); int _fdt_node_end_offset(void *fdt, int nodeoffset); From 11abe45c48ec3485a6c1a5168ce8d79c3288adc1 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 18 Feb 2008 18:09:04 +1100 Subject: [PATCH 07/11] libfdt: Remove no longer used code from fdt_node_offset_by_compatible() Since fdt_node_offset_by_compatible() was converted to the new fdt_next_node() iterator, a chunk of initialization code became redundant, but was not removed by oversight. This patch cleans it up. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 15d5f6b585..63fa1290be 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -453,20 +453,10 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, int fdt_node_offset_by_compatible(const void *fdt, int startoffset, const char *compatible) { - uint32_t tag; - int offset, nextoffset; - int err; + int offset, err; CHECK_HEADER(fdt); - if (startoffset >= 0) { - tag = fdt_next_tag(fdt, startoffset, &nextoffset); - if (tag != FDT_BEGIN_NODE) - return -FDT_ERR_BADOFFSET; - } else { - nextoffset = 0; - } - /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_node_check_compatible(), then if * that didn't find what we want, we scan over them again From 9a042e9ca512beaaa2cb450274313fc477141241 Mon Sep 17 00:00:00 2001 From: Jerry Van Baren Date: Sat, 8 Mar 2008 13:48:01 -0500 Subject: [PATCH 08/11] Flash programming progress countdown. Signed-off-by: Gerald Van Baren --- README | 5 +++++ drivers/mtd/cfi_flash.c | 44 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/README b/README index b230fde78a..0e37b8b084 100644 --- a/README +++ b/README @@ -1946,6 +1946,11 @@ Configuration Settings: is useful, if some of the configured banks are only optionally available. +- CONFIG_FLASH_SHOW_PROGRESS + If defined (must be an integer), print out countdown + digits and dots. Recommended value: 45 (9..1) for 80 + column displays, 15 (3..1) for 40 column displays. + - CFG_RX_ETH_BUFFER: Defines the number of ethernet receive buffers. On some ethernet controllers it is recommended to set this value diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index 439c950cf2..48286e5803 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -1179,6 +1179,22 @@ void flash_print_info (flash_info_t * info) return; } +/*----------------------------------------------------------------------- + * This is used in a few places in write_buf() to show programming + * progress. Making it a function is nasty because it needs to do side + * effect updates to digit and dots. Repeated code is nasty too, so + * we define it once here. + */ +#define FLASH_SHOW_PROGRESS(scale, dots, digit) \ + if ((scale > 0) && (dots <= 0)) { \ + if ((digit % 5) == 0) \ + printf ("%d", digit / 5); \ + else \ + putc ('.'); \ + digit--; \ + dots += scale; \ + } + /*----------------------------------------------------------------------- * Copy memory to flash, returns: * 0 - OK @@ -1192,10 +1208,23 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) int aln; cfiword_t cword; int i, rc; - #ifdef CFG_FLASH_USE_BUFFER_WRITE int buffered_size; #endif +#ifdef CONFIG_FLASH_SHOW_PROGRESS + int digit = CONFIG_FLASH_SHOW_PROGRESS; + int scale = 0; + int dots = 0; + + /* + * Suppress if there are fewer than CONFIG_FLASH_SHOW_PROGRESS writes. + */ + if (cnt >= CONFIG_FLASH_SHOW_PROGRESS) { + scale = (int)((cnt + CONFIG_FLASH_SHOW_PROGRESS - 1) / + CONFIG_FLASH_SHOW_PROGRESS); + } +#endif + /* get lower aligned address */ wp = (addr & ~(info->portwidth - 1)); @@ -1219,6 +1248,10 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) return rc; wp += i; +#ifdef CONFIG_FLASH_SHOW_PROGRESS + dots -= i; + FLASH_SHOW_PROGRESS(scale, dots, digit); +#endif } /* handle the aligned part */ @@ -1248,6 +1281,10 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) wp += i; src += i; cnt -= i; +#ifdef CONFIG_FLASH_SHOW_PROGRESS + dots -= i; + FLASH_SHOW_PROGRESS(scale, dots, digit); +#endif } #else while (cnt >= info->portwidth) { @@ -1259,8 +1296,13 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) return rc; wp += info->portwidth; cnt -= info->portwidth; +#ifdef CONFIG_FLASH_SHOW_PROGRESS + dots -= info->portwidth; + FLASH_SHOW_PROGRESS(scale, dots, digit); +#endif } #endif /* CFG_FLASH_USE_BUFFER_WRITE */ + if (cnt == 0) { return (0); } From f0105727d132f56a21fa3ed8b162309cca6cac44 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 19 Mar 2008 07:09:26 +0100 Subject: [PATCH 09/11] CFI: Small cleanup for FLASH_SHOW_PROGRESS With this patch we don't need that many #ifdef's in the code. It moves the subtraction into the macro and defines a NOP-macro when CONFIG_FLASH_SHOW_PROGRESS is not defined. Signed-off-by: Stefan Roese Acked-by: Gerald Van Baren --- drivers/mtd/cfi_flash.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index 48286e5803..f04c72d05a 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -1185,7 +1185,9 @@ void flash_print_info (flash_info_t * info) * effect updates to digit and dots. Repeated code is nasty too, so * we define it once here. */ -#define FLASH_SHOW_PROGRESS(scale, dots, digit) \ +#ifdef CONFIG_FLASH_SHOW_PROGRESS +#define FLASH_SHOW_PROGRESS(scale, dots, digit, dots_sub) \ + dots -= dots_sub; \ if ((scale > 0) && (dots <= 0)) { \ if ((digit % 5) == 0) \ printf ("%d", digit / 5); \ @@ -1194,6 +1196,9 @@ void flash_print_info (flash_info_t * info) digit--; \ dots += scale; \ } +#else +#define FLASH_SHOW_PROGRESS(scale, dots, digit, dots_sub) +#endif /*----------------------------------------------------------------------- * Copy memory to flash, returns: @@ -1248,10 +1253,7 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) return rc; wp += i; -#ifdef CONFIG_FLASH_SHOW_PROGRESS - dots -= i; - FLASH_SHOW_PROGRESS(scale, dots, digit); -#endif + FLASH_SHOW_PROGRESS(scale, dots, digit, i); } /* handle the aligned part */ @@ -1281,10 +1283,7 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) wp += i; src += i; cnt -= i; -#ifdef CONFIG_FLASH_SHOW_PROGRESS - dots -= i; - FLASH_SHOW_PROGRESS(scale, dots, digit); -#endif + FLASH_SHOW_PROGRESS(scale, dots, digit, i); } #else while (cnt >= info->portwidth) { @@ -1296,10 +1295,7 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) return rc; wp += info->portwidth; cnt -= info->portwidth; -#ifdef CONFIG_FLASH_SHOW_PROGRESS - dots -= info->portwidth; - FLASH_SHOW_PROGRESS(scale, dots, digit); -#endif + FLASH_SHOW_PROGRESS(scale, dots, digit, info->portwidth); } #endif /* CFG_FLASH_USE_BUFFER_WRITE */ From a5cc5555ccee596908a7d8cf22a104f6b993bfd5 Mon Sep 17 00:00:00 2001 From: Martin Krause Date: Wed, 19 Mar 2008 14:25:14 +0100 Subject: [PATCH 10/11] TQM5200B: update MTD partition layout - insert partition for dtb blob to TQM5200B MTD layout - set env variables dependent on the configured board (TQM5200 or TQM5200B) Signed-off-by: Martin Krause --- include/configs/TQM5200.h | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/include/configs/TQM5200.h b/include/configs/TQM5200.h index 9a0e9b84af..b36c8264da 100644 --- a/include/configs/TQM5200.h +++ b/include/configs/TQM5200.h @@ -252,12 +252,22 @@ "setup=tftp 200000 cam5200/setup.img; autoscr 200000\0" #endif +#if defined(CONFIG_TQM5200_B) +#define ENV_FLASH_LAYOUT \ + "fdt_addr=FC100000\0" \ + "kernel_addr=FC140000\0" \ + "ramdisk_addr=FC600000\0" +#else /* !CONFIG_TQM5200_B */ +#define ENV_FLASH_LAYOUT \ + "fdt_addr=FC0A0000\0" \ + "kernel_addr=FC0C0000\0" \ + "ramdisk_addr=FC300000\0" +#endif + #define CONFIG_EXTRA_ENV_SETTINGS \ "netdev=eth0\0" \ "console=ttyPSC0\0" \ - "fdt_addr=FC0A0000\0" \ - "kernel_addr=FC0C0000\0" \ - "ramdisk_addr=FC300000\0" \ + ENV_FLASH_LAYOUT \ "kernel_addr_r=400000\0" \ "fdt_addr_r=600000\0" \ "rootpath=/opt/eldk/ppc_6xx\0" \ @@ -400,8 +410,9 @@ # if defined(CONFIG_TQM5200_B) # if defined(CFG_LOWBOOT) # define MTDPARTS_DEFAULT "mtdparts=TQM5200-0:1m(firmware)," \ - "1536k(kernel)," \ - "3584k(small-fs)," \ + "256k(dtb)," \ + "2304k(kernel)," \ + "2560k(small-fs)," \ "2m(initrd)," \ "8m(misc)," \ "16m(big-fs)" From 81a0ac62ea29f8252d0a714709d0ecfdbba2a15e Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Thu, 20 Mar 2008 22:01:38 +0100 Subject: [PATCH 11/11] lwmon5 POST: remove unreachable code plus some coding style cleanup Signed-off-by: Wolfgang Denk --- post/board/lwmon5/watchdog.c | 43 ++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/post/board/lwmon5/watchdog.c b/post/board/lwmon5/watchdog.c index 8348346a18..48ff687460 100644 --- a/post/board/lwmon5/watchdog.c +++ b/post/board/lwmon5/watchdog.c @@ -24,7 +24,8 @@ #include -/* This test verifies if the reason of last reset was an abnormal voltage +/* + * This test verifies if the reason of last reset was an abnormal voltage * condition, than it performs watchdog test, measuing time required to * trigger watchdog reset. */ @@ -55,7 +56,8 @@ static void watchdog_magic_write(uint value) int sysmon1_post_test(int flags) { if (gpio_read_in_bit(CFG_GPIO_SYSMON_STATUS)) { - /* 3.1. GPIO62 is low + /* + * 3.1. GPIO62 is low * Assuming system voltage failure. */ post_log("Abnormal voltage detected (GPIO62)\n"); @@ -67,11 +69,14 @@ int sysmon1_post_test(int flags) int lwmon5_watchdog_post_test(int flags) { + ulong time; + /* On each reset scratch register 1 should be tested, * but first test GPIO62: */ if (!(flags & POST_MANUAL) && sysmon1_post_test(flags)) { - /* 3.1. GPIO62 is low + /* + * 3.1. GPIO62 is low * Assuming system voltage failure. */ /* 3.1.1. Set scratch register 1 to 0x0000xxxx */ @@ -81,12 +86,12 @@ int lwmon5_watchdog_post_test(int flags) } if (watchdog_magic_read() != CFG_WATCHDOG_MAGIC) { - /* 3.2. Scratch register 1 differs from magic value 0x1248xxxx + /* + * 3.2. Scratch register 1 differs from magic value 0x1248xxxx * Assuming PowerOn */ int ints; ulong base; - ulong time; /* 3.2.1. Set magic value to scratch register */ watchdog_magic_write(CFG_WATCHDOG_MAGIC); @@ -104,28 +109,28 @@ int lwmon5_watchdog_post_test(int flags) if (ints) enable_interrupts (); - /* 3.2.5. Reset didn't happen. - Set 0x0000xxxx + /* + * 3.2.5. Reset didn't happen. - Set 0x0000xxxx * into scratch register 1 */ watchdog_magic_write(0); /* 3.2.6. Mark test as failed. */ post_log("hw watchdog time : %u ms, failed ", time); return 2; - } else { - /* 3.3. Scratch register matches magic value 0x1248xxxx - * Assume this is watchdog-initiated reset - */ - ulong time; - /* 3.3.1. So, the test succeed, save measured time to syslog. */ - time = in_be32((void *)CFG_WATCHDOG_TIME_ADDR); - post_log("hw watchdog time : %u ms, passed ", time); - /* 3.3.2. Set scratch register 1 to 0x0000xxxx */ - watchdog_magic_write(0); - return 0; } - return -1; -} + /* + * 3.3. Scratch register matches magic value 0x1248xxxx + * Assume this is watchdog-initiated reset + */ + /* 3.3.1. So, the test succeed, save measured time to syslog. */ + time = in_be32((void *)CFG_WATCHDOG_TIME_ADDR); + post_log("hw watchdog time : %u ms, passed ", time); + /* 3.3.2. Set scratch register 1 to 0x0000xxxx */ + watchdog_magic_write(0); + + return 0; +} #endif /* CONFIG_POST & CFG_POST_WATCHDOG */ #endif /* CONFIG_POST */