[PATCH] Add support for binary includes.

Scott Wood scottwood at freescale.com
Thu Feb 21 06:19:41 EST 2008


A property's data can be populated with a file's contents
as follows:

node {
	prop = /incbin/("path/to/data");
};

A subset of a file can be included by passing start and size parameters.
For example, to include bytes 8 through 23:

node {
	prop = /incbin/("path/to/data", 8, 16);
};

As with /include/, non-absolute paths are looked for in the directory
of the source file that includes them.

Signed-off-by: Scott Wood <scottwood at freescale.com>
---
Now that there's no imminent release tagging, can we merge this, or are
there any objections?

 Makefile     |    2 +-
 data.c       |   37 ++++++++++++++++++++++++++++++++++++-
 dtc-lexer.l  |    7 +++++++
 dtc-parser.y |   49 +++++++++++++++++++++++++++++++++++++++++++++++++
 dtc.h        |    5 +++++
 5 files changed, 98 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index 8a47c34..d4d935c 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ LOCAL_VERSION =
 CONFIG_LOCALVERSION =
 
 CPPFLAGS = -I libfdt
-CFLAGS = -Wall -g -Os
+CFLAGS = -Wall -g -Os -D_FILE_OFFSET_BITS=64
 
 BISON = bison
 LEX = flex
diff --git a/data.c b/data.c
index a94718c..f9464bf 100644
--- a/data.c
+++ b/data.c
@@ -19,6 +19,7 @@
  */
 
 #include "dtc.h"
+#include "srcpos.h"
 
 void data_free(struct data d)
 {
@@ -189,7 +190,41 @@ struct data data_copy_file(FILE *f, size_t len)
 	d = data_grow_for(empty_data, len);
 
 	d.len = len;
-	fread(d.val, len, 1, f);
+	if (fread(d.val, len, 1, f) != 1) {
+		yyerrorf("Couldn't read %zu bytes from file: %s",
+		         len, feof(f) ? "end-of-file" : strerror(errno));
+		return empty_data;
+	}
+
+	return d;
+}
+
+struct data data_copy_file_all(FILE *f)
+{
+	char buf[4096];
+	struct data d = empty_data;
+
+	while (1) {
+		size_t ret = fread(buf, 1, sizeof(buf), f);
+		if (ret == 0) {
+			if (!feof(f))
+				yyerrorf("Error reading file: %s", strerror(errno));
+
+			break;
+		}
+
+		assert(ret <= sizeof(buf));
+
+		d = data_grow_for(d, ret);
+		memcpy(d.val + d.len, buf, ret);
+
+		if (d.len + ret < d.len) {
+			yyerror("Binary include too large");
+			break;
+		}
+
+		d.len += ret;
+	}
 
 	return d;
 }
diff --git a/dtc-lexer.l b/dtc-lexer.l
index 920b87f..ee32308 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -190,6 +190,13 @@ static int dts_version; /* = 0 */
 			return DT_PROPNODENAME;
 		}
 
+"/incbin/"	{
+			yylloc.file = srcpos_file;
+			yylloc.first_line = yylineno;
+			DPRINT("Binary Include\n");
+			return DT_INCBIN;
+		}
+
 <*>[[:space:]]+	/* eat whitespace */
 
 <*>"/*"([^*]|\*+[^*/])*\*+"/"	{
diff --git a/dtc-parser.y b/dtc-parser.y
index bae3c32..3a24d14 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -21,6 +21,8 @@
 %locations
 
 %{
+#include <stdio.h>
+
 #include "dtc.h"
 #include "srcpos.h"
 
@@ -47,6 +49,7 @@ extern int treesource_error;
 	struct node *node;
 	struct node *nodelist;
 	struct reserve_info *re;
+	struct range range;
 }
 
 %token DT_V1
@@ -59,6 +62,7 @@ extern int treesource_error;
 %token <data> DT_STRING
 %token <labelref> DT_LABEL
 %token <labelref> DT_REF
+%token DT_INCBIN
 
 %type <data> propdata
 %type <data> propdataprefix
@@ -79,6 +83,7 @@ extern int treesource_error;
 %type <node> subnode
 %type <nodelist> subnodes
 %type <labelref> label
+%type <range> mayberange
 
 %%
 
@@ -197,12 +202,56 @@ propdata:
 		{
 			$$ = data_add_marker($1, REF_PATH, $2);
 		}
+	| propdataprefix DT_INCBIN '(' DT_STRING mayberange ')'
+		{
+			struct search_path path = { srcpos_file->dir, NULL, NULL };
+			struct dtc_file *file = dtc_open_file($4.val, &path);
+
+			if (!file) {
+				yyerrorf("Cannot open file \"%s\": %s",
+				         $4.val, strerror(errno));
+			} else {
+				struct data d = empty_data;
+
+				if ($5.len >= 0) {
+					if (fseek(file->file, $5.start, SEEK_SET) == 0)
+						d = data_copy_file(file->file, $5.len);
+					else
+						yyerrorf("Couldn't seek to offset %llu in \"%s\": %s",
+						         (unsigned long long)$5.start,
+						         $4.val, strerror(errno));
+				} else {
+					d = data_copy_file_all(file->file);
+				}
+
+				$$ = data_merge($1, d);
+				dtc_close_file(file);
+			}
+		}
 	| propdata DT_LABEL
 		{
 			$$ = data_add_marker($1, LABEL, $2);
 		}
 	;
 
+mayberange:
+	  /* empty */
+		{
+			$$.len = -1;
+		}
+	| ',' addr ',' addr
+		{
+			$$.start = $2;
+			$$.len = $4;
+
+			if ($$.len != $4) {
+				yyerrorf("Length %llu is too large",
+				         (unsigned long long)$4);
+				$$.len = -1;
+			}
+		}
+	;
+
 propdataprefix:
 	  /* empty */
 		{
diff --git a/dtc.h b/dtc.h
index cba9d28..509fbc9 100644
--- a/dtc.h
+++ b/dtc.h
@@ -122,6 +122,10 @@ struct data {
 	struct marker *markers;
 };
 
+struct range {
+	off_t start;
+	int len;
+};
 
 #define empty_data ((struct data){ /* all .members = 0 or NULL */ })
 
@@ -138,6 +142,7 @@ struct data data_grow_for(struct data d, int xlen);
 struct data data_copy_mem(const char *mem, int len);
 struct data data_copy_escape_string(const char *s, int len);
 struct data data_copy_file(FILE *f, size_t len);
+struct data data_copy_file_all(FILE *f);
 
 struct data data_append_data(struct data d, const void *p, int len);
 struct data data_insert_at_marker(struct data d, struct marker *m,
-- 
1.5.3



More information about the Linuxppc-dev mailing list