summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2009-02-06 14:01:56 +1100
committerJon Loeliger <jdl@example.com>2009-02-06 11:19:10 -0600
commitce4d9c0f746b21119bc2b5aa5571bb08799a82bd (patch)
tree20f6735160b99f51092c81d89b34a47b57161fea
parentbae93e8992fef3cfaff681fe85b26fd35e432e31 (diff)
downloaddtc-ce4d9c0f746b21119bc2b5aa5571bb08799a82bd.tar.gz
libfdt: Rework fdt_next_node()
Currently fdt_next_node() will find the next node in the blob regardless of whether it is above, below or at the same level in the tree as the starting node - the depth parameter is updated to indicate which is the case. When a depth parameter is supplied, this patch makes it instead terminate immediately when it finds the END_NODE tag for a node at depth 0. In this case it returns the offset immediately past the END_NODE tag. This has a couple of advantages. First, this slightly simplifies fdt_subnode_offset(), which no longer needs to explicitly check that fdt_next_node()'s iteration hasn't left the starting node. Second, this allows fdt_next_node() to be used to implement _fdt_node_end_offset() considerably simplifying the latter function. The other users of fdt_next_node() either don't need to iterate out of the starting node, or don't pass a depth parameter at all. Any callers that really need to iterate out of the starting node, but keep tracking depth can do so by biasing the initial depth value. This is a semantic change, but I think it's very unlikely to break any existing library users. Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
-rw-r--r--libfdt/fdt.c4
-rw-r--r--libfdt/fdt_ro.c20
-rw-r--r--libfdt/fdt_wip.c41
3 files changed, 17 insertions, 48 deletions
diff --git a/libfdt/fdt.c b/libfdt/fdt.c
index 37085c1..2546b5c 100644
--- a/libfdt/fdt.c
+++ b/libfdt/fdt.c
@@ -162,8 +162,8 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
break;
case FDT_END_NODE:
- if (depth)
- (*depth)--;
+ if (depth && ((--(*depth)) < 0))
+ return nextoffset;
break;
case FDT_END:
diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
index d12c7ee..7a79bb8 100644
--- a/libfdt/fdt_ro.c
+++ b/libfdt/fdt_ro.c
@@ -108,24 +108,20 @@ int fdt_num_mem_rsv(const void *fdt)
int fdt_subnode_offset_namelen(const void *fdt, int offset,
const char *name, int namelen)
{
- int depth = 0;
+ int depth;
FDT_CHECK_HEADER(fdt);
- for (depth = 0, offset = fdt_next_node(fdt, offset, &depth);
- (offset >= 0) && (depth > 0);
- offset = fdt_next_node(fdt, offset, &depth)) {
- if (depth < 0)
- return -FDT_ERR_NOTFOUND;
- else if ((depth == 1)
- && _fdt_nodename_eq(fdt, offset, name, namelen))
+ for (depth = 0;
+ (offset >= 0) && (depth >= 0);
+ offset = fdt_next_node(fdt, offset, &depth))
+ if ((depth == 1)
+ && _fdt_nodename_eq(fdt, offset, name, namelen))
return offset;
- }
- if (offset < 0)
- return offset; /* error */
- else
+ if (depth < 0)
return -FDT_ERR_NOTFOUND;
+ return offset; /* error */
}
int fdt_subnode_offset(const void *fdt, int parentoffset,
diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c
index a4652c6..6025fa1 100644
--- a/libfdt/fdt_wip.c
+++ b/libfdt/fdt_wip.c
@@ -94,41 +94,14 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
return 0;
}
-int _fdt_node_end_offset(void *fdt, int nodeoffset)
+int _fdt_node_end_offset(void *fdt, int offset)
{
- int level = 0;
- uint32_t tag;
- int offset, nextoffset;
-
- tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
- if (tag != FDT_BEGIN_NODE)
- return -FDT_ERR_BADOFFSET;
- do {
- offset = nextoffset;
- tag = fdt_next_tag(fdt, offset, &nextoffset);
-
- switch (tag) {
- case FDT_END:
- return offset;
-
- case FDT_BEGIN_NODE:
- level++;
- break;
-
- case FDT_END_NODE:
- level--;
- break;
-
- case FDT_PROP:
- case FDT_NOP:
- break;
-
- default:
- return -FDT_ERR_BADSTRUCTURE;
- }
- } while (level >= 0);
-
- return nextoffset;
+ int depth = 0;
+
+ while ((offset >= 0) && (depth >= 0))
+ offset = fdt_next_node(fdt, offset, &depth);
+
+ return offset;
}
int fdt_nop_node(void *fdt, int nodeoffset)