From: Jerry Van Baren <gvb.uboot@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot-Users] [PATCH 4/6] libfdt: Enhanced and published fdt_next_tag()
Date: Sat, 31 Mar 2007 13:36:03 -0400 [thread overview]
Message-ID: <20070331173603.GD26761@dellserver.lan> (raw)
Enhanced the formerly private function _fdt_next_tag() to allow stepping
through the tree, used to produce a human-readable dump, and made
it part of the published interface.
Also added some comments.
Signed-off-by: Gerald Van Baren <vanbaren@cideas.com>
---
include/libfdt.h | 3 +
libfdt/fdt.c | 39 ---------------
libfdt/fdt_ro.c | 116 +++++++++++++++++++++++++++++++++++++++++++--
libfdt/fdt_rw.c | 6 +-
libfdt/fdt_sw.c | 2 +-
libfdt/fdt_wip.c | 4 +-
libfdt/libfdt_internal.h | 1 -
7 files changed, 119 insertions(+), 52 deletions(-)
diff --git a/include/libfdt.h b/include/libfdt.h
index acdc72e..c4b3c24 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -81,6 +81,9 @@ struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
void *fdt_getprop(const void *fdt, int nodeoffset,
const char *name, int *lenp);
+uint32_t fdt_next_tag(const void *fdt, int offset,
+ int *nextoffset, char **namep);
+
/* Write-in-place functions */
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
const void *val, int len);
diff --git a/libfdt/fdt.c b/libfdt/fdt.c
index 772da46..4b1c8ab 100644
--- a/libfdt/fdt.c
+++ b/libfdt/fdt.c
@@ -58,45 +58,6 @@ void *fdt_offset_ptr(const void *fdt, int offset, int len)
return p;
}
-uint32_t _fdt_next_tag(const void *fdt, int offset, int *nextoffset)
-{
- const uint32_t *tagp, *lenp;
- uint32_t tag;
- const char *p;
-
- if (offset % FDT_TAGSIZE)
- return -1;
-
- tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
- if (! tagp)
- return FDT_END; /* premature end */
- tag = fdt32_to_cpu(*tagp);
- offset += FDT_TAGSIZE;
-
- switch (tag) {
- case FDT_BEGIN_NODE:
- /* skip name */
- do {
- p = fdt_offset_ptr(fdt, offset++, 1);
- } while (p && (*p != '\0'));
- if (! p)
- return FDT_END;
- break;
- case FDT_PROP:
- lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
- if (! lenp)
- return FDT_END;
- /* skip name offset, length and value */
- offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
- break;
- }
-
- if (nextoffset)
- *nextoffset = ALIGN(offset, FDT_TAGSIZE);
-
- return tag;
-}
-
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 9112c6a..f884083 100644
--- a/libfdt/fdt_ro.c
+++ b/libfdt/fdt_ro.c
@@ -48,11 +48,24 @@ static int offset_streq(const void *fdt, int offset,
return 1;
}
+/*
+ * Return a pointer to the string at the given string offset.
+ */
char *fdt_string(const void *fdt, int stroffset)
{
return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
}
+/*
+ * Return the node offset of the node specified by:
+ * parentoffset - starting place (0 to start at the root)
+ * name - name being searched for
+ * namelen - length of the name: typically strlen(name)
+ *
+ * Notes:
+ * If the start node has subnodes, the subnodes are _not_ searched for the
+ * requested name.
+ */
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
const char *name, int namelen)
{
@@ -62,13 +75,13 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
CHECK_HEADER(fdt);
- tag = _fdt_next_tag(fdt, parentoffset, &nextoffset);
+ tag = fdt_next_tag(fdt, parentoffset, &nextoffset, NULL);
if (tag != FDT_BEGIN_NODE)
return -FDT_ERR_BADOFFSET;
do {
offset = nextoffset;
- tag = _fdt_next_tag(fdt, offset, &nextoffset);
+ tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);
switch (tag) {
case FDT_END:
@@ -76,10 +89,15 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
case FDT_BEGIN_NODE:
level++;
+ /*
+ * If we are nested down levels, ignore the strings
+ * until we get back to the proper level.
+ */
if (level != 1)
continue;
+
+ /* Return the offset if this is "our" string. */
if (offset_streq(fdt, offset+FDT_TAGSIZE, name, namelen))
- /* Found it! */
return offset;
break;
@@ -99,12 +117,19 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
return -FDT_ERR_NOTFOUND;
}
+/*
+ * See fdt_subnode_offset_namelen()
+ */
int fdt_subnode_offset(const void *fdt, int parentoffset,
const char *name)
{
return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
}
+/*
+ * Searches for the node corresponding to the given path and returns the
+ * offset of that node.
+ */
int fdt_path_offset(const void *fdt, const char *path)
{
const char *end = path + strlen(path);
@@ -113,21 +138,33 @@ int fdt_path_offset(const void *fdt, const char *path)
CHECK_HEADER(fdt);
+ /* Paths must be absolute */
if (*path != '/')
return -FDT_ERR_BADPATH;
while (*p) {
const char *q;
+ /* Skip path separator(s) */
while (*p == '/')
p++;
if (! *p)
return -FDT_ERR_BADPATH;
+
+ /*
+ * Find the next path separator. The characters between
+ * p and q are the next segment of the the path to find.
+ */
q = strchr(p, '/');
if (! q)
q = end;
+ /*
+ * Find the offset corresponding to the this path segment.
+ */
offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
+
+ /* Oops, error, abort abort abort */
if (offset < 0)
return offset;
@@ -137,6 +174,10 @@ int fdt_path_offset(const void *fdt, const char *path)
return offset;
}
+/*
+ * Given the offset of a node and a name of a property in that node, return
+ * a pointer to the property struct.
+ */
struct fdt_property *fdt_get_property(const void *fdt,
int nodeoffset,
const char *name, int *lenp)
@@ -155,14 +196,14 @@ struct fdt_property *fdt_get_property(const void *fdt,
if (nodeoffset % FDT_TAGSIZE)
goto fail;
- tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset);
+ tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL);
if (tag != FDT_BEGIN_NODE)
goto fail;
do {
offset = nextoffset;
- tag = _fdt_next_tag(fdt, offset, &nextoffset);
+ tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);
switch (tag) {
case FDT_END:
err = -FDT_ERR_TRUNCATED;
@@ -177,6 +218,10 @@ struct fdt_property *fdt_get_property(const void *fdt,
break;
case FDT_PROP:
+ /*
+ * If we are nested down levels, ignore the strings
+ * until we get back to the proper level.
+ */
if (level != 0)
continue;
@@ -216,6 +261,10 @@ struct fdt_property *fdt_get_property(const void *fdt,
return NULL;
}
+/*
+ * Given the offset of a node and a name of a property in that node, return
+ * a pointer to the property data (ONLY).
+ */
void *fdt_getprop(const void *fdt, int nodeoffset,
const char *name, int *lenp)
{
@@ -225,5 +274,60 @@ void *fdt_getprop(const void *fdt, int nodeoffset,
if (! prop)
return NULL;
- return prop->data;
+ return (void *)prop->data;
+}
+
+
+uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset, char **namep)
+{
+ const uint32_t *tagp, *lenp;
+ uint32_t tag;
+ const char *p;
+
+ if (offset % FDT_TAGSIZE)
+ return -1;
+
+ tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
+ if (! tagp)
+ return FDT_END; /* premature end */
+ tag = fdt32_to_cpu(*tagp);
+ offset += FDT_TAGSIZE;
+
+ switch (tag) {
+ case FDT_BEGIN_NODE:
+ if(namep)
+ *namep = fdt_offset_ptr(fdt, offset, 1);
+
+ /* skip name */
+ do {
+ p = fdt_offset_ptr(fdt, offset++, 1);
+ } while (p && (*p != '\0'));
+ if (! p)
+ return FDT_END;
+ break;
+ case FDT_PROP:
+ lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
+ if (! lenp)
+ return FDT_END;
+ /*
+ * Get the property and set the namep to the name.
+ */
+ if(namep) {
+ struct fdt_property *prop;
+
+ prop = fdt_offset_ptr_typed(fdt, offset - FDT_TAGSIZE, prop);
+ if (! prop)
+ return -FDT_ERR_BADSTRUCTURE;
+ *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+ }
+ /* skip name offset, length and value */
+ offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
+ break;
+ }
+
+ if (nextoffset)
+ *nextoffset = ALIGN(offset, FDT_TAGSIZE);
+
+ return tag;
}
+
diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c
index 7396645..b33fbf4 100644
--- a/libfdt/fdt_rw.c
+++ b/libfdt/fdt_rw.c
@@ -145,7 +145,7 @@ static int _add_property(void *fdt, int nodeoffset, const char *name, int len,
int namestroff;
int err;
- tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset);
+ tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL);
if (tag != FDT_BEGIN_NODE)
return -FDT_ERR_BADOFFSET;
@@ -219,10 +219,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
return offset;
/* Try to place the new node after the parent's properties */
- _fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
+ fdt_next_tag(fdt, parentoffset, &nextoffset, NULL); /* skip the BEGIN_NODE */
do {
offset = nextoffset;
- tag = _fdt_next_tag(fdt, offset, &nextoffset);
+ tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);
} while (tag == FDT_PROP);
nh = _fdt_offset_ptr(fdt, offset);
diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c
index 41d4891..672f4dd 100644
--- a/libfdt/fdt_sw.c
+++ b/libfdt/fdt_sw.c
@@ -203,7 +203,7 @@ int fdt_finish(void *fdt)
/* Walk the structure, correcting string offsets */
offset = 0;
- while ((tag = _fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
+ while ((tag = fdt_next_tag(fdt, offset, &nextoffset, NULL)) != FDT_END) {
if (tag == FDT_PROP) {
struct fdt_property *prop = fdt_offset_ptr(fdt, offset,
sizeof(*prop));
diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c
index 0db7d25..261b9b0 100644
--- a/libfdt/fdt_wip.c
+++ b/libfdt/fdt_wip.c
@@ -68,12 +68,12 @@ int _fdt_node_end_offset(void *fdt, int nodeoffset)
uint32_t tag;
int offset, nextoffset;
- tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset);
+ tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL);
if (tag != FDT_BEGIN_NODE)
return -FDT_ERR_BADOFFSET;
do {
offset = nextoffset;
- tag = _fdt_next_tag(fdt, offset, &nextoffset);
+ tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);
switch (tag) {
case FDT_END:
diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h
index 124bef7..cc9633c 100644
--- a/libfdt/libfdt_internal.h
+++ b/libfdt/libfdt_internal.h
@@ -27,7 +27,6 @@
#define streq(p, q) (strcmp((p), (q)) == 0)
int _fdt_check_header(const void *fdt);
-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);
--
1.4.4.4
reply other threads:[~2007-03-31 17:36 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070331173603.GD26761@dellserver.lan \
--to=gvb.uboot@gmail.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.