summaryrefslogtreecommitdiff
path: root/libfdt/fdt_ro.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2018-03-18 00:12:12 +1100
committerDavid Gibson <david@gibson.dropbear.id.au>2018-04-11 16:49:38 +1000
commit9d9c795cd721bd11f4a8cc039e5553c83bd66fdf (patch)
tree31c7ee4f324a2bf49f8dc038a4c6474d4768577d /libfdt/fdt_ro.c
parent27a63cf0742fa75fc51eb6b906a135440a693642 (diff)
downloaddevice-tree-compiler-9d9c795cd721bd11f4a8cc039e5553c83bd66fdf.tar.gz
libfdt: Add fdt_check_full() functionsafety
This new function implements a complete and thorough check of an fdt blob's structure. Given a buffer containing an fdt, it should return 0 only if the fdt within is structurally sound in all regards. It doesn't check anything about the blob's contents (i.e. the actual values of the nodes and properties), of course. Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'libfdt/fdt_ro.c')
-rw-r--r--libfdt/fdt_ro.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
index c74b962..4ba7c93 100644
--- a/libfdt/fdt_ro.c
+++ b/libfdt/fdt_ro.c
@@ -857,3 +857,66 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
return offset; /* error from fdt_next_node() */
}
+
+int fdt_check_full(const void *fdt, size_t bufsize)
+{
+ int err;
+ int num_memrsv;
+ int offset, nextoffset = 0;
+ uint32_t tag;
+ unsigned depth = 0;
+ const void *prop;
+ const char *propname;
+
+ if (bufsize < FDT_V1_SIZE)
+ return -FDT_ERR_TRUNCATED;
+ err = fdt_check_header(fdt);
+ if (err != 0)
+ return err;
+ if (bufsize < fdt_totalsize(fdt))
+ return -FDT_ERR_TRUNCATED;
+
+ num_memrsv = fdt_num_mem_rsv(fdt);
+ if (num_memrsv < 0)
+ return num_memrsv;
+
+ while (1) {
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ if (nextoffset < 0)
+ return nextoffset;
+
+ switch (tag) {
+ case FDT_NOP:
+ break;
+
+ case FDT_END:
+ if (depth != 0)
+ return -FDT_ERR_BADSTRUCTURE;
+ return 0;
+
+ case FDT_BEGIN_NODE:
+ depth++;
+ if (depth > INT_MAX)
+ return -FDT_ERR_BADSTRUCTURE;
+ break;
+
+ case FDT_END_NODE:
+ if (depth == 0)
+ return -FDT_ERR_BADSTRUCTURE;
+ depth--;
+ break;
+
+ case FDT_PROP:
+ prop = fdt_getprop_by_offset(fdt, offset, &propname,
+ &err);
+ if (!prop)
+ return err;
+ break;
+
+ default:
+ return -FDT_ERR_INTERNAL;
+ }
+ }
+}