summaryrefslogtreecommitdiff
path: root/libfdt/fdt_ro.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2009-02-06 14:03:24 +1100
committerGerald Van Baren <vanbaren@cideas.com>2009-04-01 19:29:31 -0400
commita22d9cfbb5bcfb3dc6ffd64d391b568e8a0ce383 (patch)
tree83dd65295d64b33daca89502df5c4e28e857112a /libfdt/fdt_ro.c
parent2c0b843e710aa1e2da25c2592e6dbe5d0b0ab7da (diff)
libfdt: Rework/cleanup fdt_next_tag()
Currently, callers of fdt_next_tag() must usually follow the call with some sort of call to fdt_offset_ptr() to verify that the blob isn't truncated in the middle of the tag data they're going to process. This is a bit silly, since fdt_next_tag() generally has to call fdt_offset_ptr() on at least some of the data following the tag for its own operation. This patch alters fdt_next_tag() to always use fdt_offset_ptr() to verify the data between its starting offset and the offset it returns in nextoffset. This simplifies fdt_get_property() which no longer has to verify itself that the property data is all present. At the same time, I neaten and clarify the error handling for fdt_next_tag(). Previously, fdt_next_tag() could return -1 instead of a tag value in some circumstances - which almost none of the callers checked for. Also, fdt_next_tag() could return FDT_END either because it encountered an FDT_END tag, or because it reached the end of the structure block - no way was provided to tell between these cases. With this patch, fdt_next_tag() always returns FDT_END with a negative value in nextoffset for an error. This means the several places which loop looking for FDT_END will still work correctly - they only need to check for errors at the end. The errors which fdt_next_tag() can report are: - -FDT_ERR_TRUNCATED if it reached the end of the structure block instead of finding a tag. - -FDT_BADSTRUCTURE if a bad tag was encountered, or if the tag data couldn't be verified with fdt_offset_ptr(). This patch also updates the callers of fdt_next_tag(), where appropriate, to make use of the new error reporting. Finally, the prototype for the long gone _fdt_next_tag() is removed from libfdt_internal.h. Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'libfdt/fdt_ro.c')
-rw-r--r--libfdt/fdt_ro.c33
1 files changed, 9 insertions, 24 deletions
diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
index d682a40c1..1e1e32209 100644
--- a/libfdt/fdt_ro.c
+++ b/libfdt/fdt_ro.c
@@ -205,7 +205,6 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
{
uint32_t tag;
const struct fdt_property *prop;
- int namestroff;
int offset, nextoffset;
int err;
@@ -220,38 +219,24 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
tag = fdt_next_tag(fdt, offset, &nextoffset);
switch (tag) {
case FDT_END:
- err = -FDT_ERR_TRUNCATED;
+ if (nextoffset < 0)
+ err = nextoffset;
+ else
+ /* FDT_END tag with unclosed nodes */
+ err = -FDT_ERR_BADSTRUCTURE;
goto fail;
- case FDT_BEGIN_NODE:
- case FDT_END_NODE:
- case FDT_NOP:
- break;
-
case FDT_PROP:
- err = -FDT_ERR_BADSTRUCTURE;
- prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
- if (! prop)
- goto fail;
- namestroff = fdt32_to_cpu(prop->nameoff);
- if (_fdt_string_eq(fdt, namestroff, name, namelen)) {
+ prop = _fdt_offset_ptr(fdt, offset);
+ if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
+ name, namelen)) {
/* Found it! */
- int len = fdt32_to_cpu(prop->len);
- prop = fdt_offset_ptr(fdt, offset,
- sizeof(*prop)+len);
- if (! prop)
- goto fail;
-
if (lenp)
- *lenp = len;
+ *lenp = fdt32_to_cpu(prop->len);
return prop;
}
break;
-
- default:
- err = -FDT_ERR_BADSTRUCTURE;
- goto fail;
}
} while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));