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 <[EMAIL PROTECTED]> --- 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 6e07862..578d8c1 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 bfb996e..7670aca 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 da7f6f5..f50f2f0 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 _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev