summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libfdt.h2
-rw-r--r--libfdt/fdt.c50
-rw-r--r--libfdt/fdt_ro.c53
-rw-r--r--libfdt/fdt_rw.c2
-rw-r--r--libfdt/fdt_sw.c11
-rw-r--r--libfdt/fdt_wip.c41
-rw-r--r--libfdt/libfdt_internal.h1
7 files changed, 63 insertions, 97 deletions
diff --git a/include/libfdt.h b/include/libfdt.h
index ce374fd..d23d40e 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -156,7 +156,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth);
#define __fdt_set_hdr(name) \
static inline void fdt_set_##name(void *fdt, uint32_t val) \
{ \
- struct fdt_header *fdth = fdt; \
+ struct fdt_header *fdth = (struct fdt_header*)fdt; \
fdth->name = cpu_to_fdt32(val); \
}
__fdt_set_hdr(magic);
diff --git a/libfdt/fdt.c b/libfdt/fdt.c
index a59a518..b09ea6f 100644
--- a/libfdt/fdt.c
+++ b/libfdt/fdt.c
@@ -94,42 +94,53 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
return p;
}
-uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
+uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
const uint32_t *tagp, *lenp;
uint32_t tag;
+ int offset = startoffset;
const char *p;
- if (offset % FDT_TAGSIZE)
- return -1;
-
+ *nextoffset = -FDT_ERR_TRUNCATED;
tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
- if (! tagp)
+ if (!tagp)
return FDT_END; /* premature end */
tag = fdt32_to_cpu(*tagp);
offset += FDT_TAGSIZE;
+ *nextoffset = -FDT_ERR_BADSTRUCTURE;
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;
+ if (!p)
+ return FDT_END; /* premature 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);
+ if (!lenp)
+ return FDT_END; /* premature end */
+ /* skip-name offset, length and value */
+ offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ + fdt32_to_cpu(*lenp);
+ break;
+
+ case FDT_END:
+ case FDT_END_NODE:
+ case FDT_NOP:
break;
+
+ default:
+ return FDT_END;
}
- if (nextoffset)
- *nextoffset = FDT_TAGALIGN(offset);
+ if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
+ return FDT_END; /* premature end */
+ *nextoffset = FDT_TAGALIGN(offset);
return tag;
}
@@ -166,15 +177,16 @@ 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:
- return -FDT_ERR_NOTFOUND;
-
- default:
- return -FDT_ERR_BADSTRUCTURE;
+ if ((nextoffset >= 0)
+ || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth))
+ return -FDT_ERR_NOTFOUND;
+ else
+ return nextoffset;
}
} while (tag != FDT_BEGIN_NODE);
diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
index fdc9c29..1e1e322 100644
--- a/libfdt/fdt_ro.c
+++ b/libfdt/fdt_ro.c
@@ -112,24 +112,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,
@@ -209,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;
@@ -224,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));
diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c
index cd06178..5c27a67 100644
--- a/libfdt/fdt_rw.c
+++ b/libfdt/fdt_rw.c
@@ -410,6 +410,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
struct_size = 0;
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
;
+ if (struct_size < 0)
+ return struct_size;
}
if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c
index 698329e..55ebebf 100644
--- a/libfdt/fdt_sw.c
+++ b/libfdt/fdt_sw.c
@@ -70,7 +70,7 @@ static int _fdt_sw_check_header(void *fdt)
return err; \
}
-static void *_fdt_grab_space(void *fdt, int len)
+static void *_fdt_grab_space(void *fdt, size_t len)
{
int offset = fdt_size_dt_struct(fdt);
int spaceleft;
@@ -82,7 +82,7 @@ static void *_fdt_grab_space(void *fdt, int len)
return NULL;
fdt_set_size_dt_struct(fdt, offset + len);
- return fdt_offset_ptr_w(fdt, offset, len);
+ return _fdt_offset_ptr_w(fdt, offset);
}
int fdt_create(void *buf, int bufsize)
@@ -237,18 +237,17 @@ int fdt_finish(void *fdt)
while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
if (tag == FDT_PROP) {
struct fdt_property *prop =
- fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
+ _fdt_offset_ptr_w(fdt, offset);
int nameoff;
- if (! prop)
- return -FDT_ERR_BADSTRUCTURE;
-
nameoff = fdt32_to_cpu(prop->nameoff);
nameoff += fdt_size_dt_strings(fdt);
prop->nameoff = cpu_to_fdt32(nameoff);
}
offset = nextoffset;
}
+ if (nextoffset < 0)
+ return nextoffset;
/* Finally, adjust the header */
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c
index e30c81d..e373677 100644
--- a/libfdt/fdt_wip.c
+++ b/libfdt/fdt_wip.c
@@ -98,41 +98,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)
diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h
index 46eb93e..d2dcbd6 100644
--- a/libfdt/libfdt_internal.h
+++ b/libfdt/libfdt_internal.h
@@ -62,7 +62,6 @@
return err; \
}
-uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
int _fdt_check_node_offset(const void *fdt, int offset);
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
int _fdt_node_end_offset(void *fdt, int nodeoffset);