[PATCH 06/10] fdtdump: add a --scan option

Mike Frysinger vapier at gentoo.org
Thu Apr 11 04:29:11 EST 2013


Often times, fdts get embedded in other larger files.  Rather than force
people to `dd` the blob out themselves, make the fdtdump file smarter.

It can now scan the blob looking for the fdt magic.  Once locate, it does
a little validation on the main struct to make sure we didn't hit random
binary data.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 fdtdump.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/fdtdump.c b/fdtdump.c
index b685ed1..7b967aa 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -2,12 +2,14 @@
  * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
  */
 
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 
+#include <libfdt.h>
 #include <libfdt_env.h>
 #include <fdt.h>
 
@@ -119,11 +121,13 @@ static void dump_blob(void *blob)
 
 /* Usage related data. */
 static const char usage_synopsis[] = "fdtdump [options] <file>";
-static const char usage_short_opts[] = USAGE_COMMON_SHORT_OPTS;
+static const char usage_short_opts[] = "s" USAGE_COMMON_SHORT_OPTS;
 static struct option const usage_long_opts[] = {
+	{"scan",             no_argument, NULL, 's'},
 	USAGE_COMMON_LONG_OPTS
 };
 static const char * const usage_opts_help[] = {
+	"Scan for an embedded fdt in file",
 	USAGE_COMMON_OPTS_HELP
 };
 
@@ -132,20 +136,58 @@ int main(int argc, char *argv[])
 	int opt;
 	const char *file;
 	char *buf;
+	bool scan = false;
+	off_t len;
 
 	while ((opt = util_getopt_long()) != EOF) {
 		switch (opt) {
 		case_USAGE_COMMON_FLAGS
+
+		case 's':
+			scan = true;
+			break;
 		}
 	}
 	if (optind != argc - 1)
 		long_usage("missing input filename");
 	file = argv[optind];
 
-	buf = utilfdt_read(file, NULL);
+	buf = utilfdt_read(file, &len);
 	if (!buf)
 		die("could not read: %s\n", file);
 
+	/* try and locate an embedded fdt in a bigger blob */
+	if (scan) {
+		unsigned char smagic[4];
+		char *p = buf;
+		char *endp = buf + len;
+
+		fdt_set_magic(smagic, FDT_MAGIC);
+
+		/* poor man's memmem */
+		while (true) {
+			p = memchr(p, smagic[0], endp - p - 4);
+			if (!p)
+				break;
+			if (fdt_magic(p) == FDT_MAGIC) {
+				/* try and validate the main struct */
+				off_t this_len = endp - p;
+				fdt32_t max_version = 17;
+				if (fdt_version(p) <= max_version &&
+				    fdt_last_comp_version(p) < max_version &&
+				    fdt_totalsize(p) < this_len &&
+				    fdt_off_dt_struct(p) < this_len &&
+					fdt_off_dt_strings(p) < this_len)
+					break;
+			}
+			++p;
+		}
+		if (!p)
+			die("%s: could not locate fdt magic\n", file);
+		printf("%s: found fdt at offset %#zx\n", file, p - buf);
+		buf = p;
+	}
+
 	dump_blob(buf);
 
 	return 0;
-- 
1.8.1.2



More information about the devicetree-discuss mailing list