Commit ed95d745 authored by David Gibson's avatar David Gibson Committed by Paul Mackerras

powerpc: Update in-kernel dtc and libfdt to version 1.2.0

Some time ago, a copies of the upstream dtc and libfdt sources were
included in the kernel tree to avoid having these as external
dependencies for building the kernel.  Since then development on the
upstream dtc and libfdt has continued.  This updates the in-kernel
versions to match the recently released upstream dtc version 1.2.0.
This includes a number of bugfixes, many cleanups and a few new
features.
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 0ec27c04
......@@ -5,21 +5,5 @@
#
DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
checks.c
DTC_EXTRA = dtc.h srcpos.h
DTC_LEXFILES = dtc-lexer.l
DTC_BISONFILES = dtc-parser.y
DTC_LEX_SRCS = $(DTC_LEXFILES:%.l=%.lex.c)
DTC_BISON_SRCS = $(DTC_BISONFILES:%.y=%.tab.c)
DTC_BISON_INCLUDES = $(DTC_BISONFILES:%.y=%.tab.h)
DTC_GEN_SRCS = $(DTC_LEX_SRCS) $(DTC_BISON_SRCS)
DTC_GEN_ALL = $(DTC_GEN_SRCS) $(DTC_BISON_INCLUDES)
DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
DTC_CLEANFILES = $(DTC_GEN_ALL)
# We assume the containing Makefile system can do auto-dependencies for most
# things, but we supply the dependencies on generated header files explicitly
$(addprefix $(DTC_objdir)/,$(DTC_GEN_SRCS:%.c=%.o)): $(addprefix $(DTC_objdir)/,$(DTC_BISON_INCLUDES))
This diff is collapsed.
......@@ -32,8 +32,6 @@ void data_free(struct data d)
m = nm;
}
assert(!d.val || d.asize);
if (d.val)
free(d.val);
}
......@@ -43,9 +41,6 @@ struct data data_grow_for(struct data d, int xlen)
struct data nd;
int newsize;
/* we must start with an allocated datum */
assert(!d.val || d.asize);
if (xlen == 0)
return d;
......@@ -56,11 +51,8 @@ struct data data_grow_for(struct data d, int xlen)
while ((d.len + xlen) > newsize)
newsize *= 2;
nd.asize = newsize;
nd.val = xrealloc(d.val, newsize);
assert(nd.asize >= (d.len + xlen));
return nd;
}
......@@ -83,16 +75,11 @@ static char get_oct_char(const char *s, int *i)
long val;
x[3] = '\0';
x[0] = s[(*i)];
if (x[0]) {
x[1] = s[(*i)+1];
if (x[1])
x[2] = s[(*i)+2];
}
strncpy(x, s + *i, 3);
val = strtol(x, &endx, 8);
if ((endx - x) == 0)
fprintf(stderr, "Empty \\nnn escape\n");
assert(endx > x);
(*i) += endx - x;
return val;
......@@ -105,13 +92,11 @@ static char get_hex_char(const char *s, int *i)
long val;
x[2] = '\0';
x[0] = s[(*i)];
if (x[0])
x[1] = s[(*i)+1];
strncpy(x, s + *i, 2);
val = strtol(x, &endx, 16);
if ((endx - x) == 0)
fprintf(stderr, "Empty \\x escape\n");
if (!(endx > x))
die("\\x used with no following hex digits\n");
(*i) += endx - x;
return val;
......@@ -182,14 +167,29 @@ struct data data_copy_escape_string(const char *s, int len)
return d;
}
struct data data_copy_file(FILE *f, size_t len)
struct data data_copy_file(FILE *f, size_t maxlen)
{
struct data d;
struct data d = empty_data;
d = data_grow_for(empty_data, len);
while (!feof(f) && (d.len < maxlen)) {
size_t chunksize, ret;
d.len = len;
fread(d.val, len, 1, f);
if (maxlen == -1)
chunksize = 4096;
else
chunksize = maxlen - d.len;
d = data_grow_for(d, chunksize);
ret = fread(d.val + d.len, 1, chunksize, f);
if (ferror(f))
die("Error reading file into data: %s", strerror(errno));
if (d.len + ret < d.len)
die("Overflow reading file into data\n");
d.len += ret;
}
return d;
}
......@@ -247,7 +247,7 @@ struct data data_merge(struct data d1, struct data d2)
struct data data_append_cell(struct data d, cell_t word)
{
cell_t beword = cpu_to_be32(word);
cell_t beword = cpu_to_fdt32(word);
return data_append_data(d, &beword, sizeof(beword));
}
......@@ -256,15 +256,15 @@ struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
{
struct fdt_reserve_entry bere;
bere.address = cpu_to_be64(re->address);
bere.size = cpu_to_be64(re->size);
bere.address = cpu_to_fdt64(re->address);
bere.size = cpu_to_fdt64(re->size);
return data_append_data(d, &bere, sizeof(bere));
}
struct data data_append_addr(struct data d, u64 addr)
struct data data_append_addr(struct data d, uint64_t addr)
{
u64 beaddr = cpu_to_be64(addr);
uint64_t beaddr = cpu_to_fdt64(addr);
return data_append_data(d, &beaddr, sizeof(beaddr));
}
......
......@@ -28,6 +28,10 @@
PROPNODECHAR [a-zA-Z0-9,._+*#?@-]
PATHCHAR ({PROPNODECHAR}|[/])
LABEL [a-zA-Z_][a-zA-Z0-9_]*
STRING \"([^\\"]|\\.)*\"
WS [[:space:]]
COMMENT "/*"([^*]|\*+[^*/])*\*+"/"
LINECOMMENT "//".*\n
%{
#include "dtc.h"
......@@ -52,29 +56,26 @@ static int dts_version; /* = 0 */
DPRINT("<V1>\n"); \
BEGIN(V1); \
}
static void push_input_file(const char *filename);
static int pop_input_file(void);
%}
%%
<*>"/include/" BEGIN(INCLUDE);
<INCLUDE>\"[^"\n]*\" {
yytext[strlen(yytext) - 1] = 0;
if (!push_input_file(yytext + 1)) {
/* Some unrecoverable error.*/
exit(1);
}
BEGIN_DEFAULT();
<*>"/include/"{WS}*{STRING} {
char *name = strchr(yytext, '\"') + 1;
yytext[yyleng-1] = '\0';
push_input_file(name);
}
<*><<EOF>> {
if (!pop_input_file()) {
yyterminate();
}
}
<*>\"([^\\"]|\\.)*\" {
yylloc.filenum = srcpos_filenum;
<*>{STRING} {
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
DPRINT("String: %s\n", yytext);
yylval.data = data_copy_escape_string(yytext+1,
......@@ -84,7 +85,7 @@ static int dts_version; /* = 0 */
}
<*>"/dts-v1/" {
yylloc.filenum = srcpos_filenum;
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
DPRINT("Keyword: /dts-v1/\n");
dts_version = 1;
......@@ -93,7 +94,7 @@ static int dts_version; /* = 0 */
}
<*>"/memreserve/" {
yylloc.filenum = srcpos_filenum;
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT();
......@@ -101,7 +102,7 @@ static int dts_version; /* = 0 */
}
<*>{LABEL}: {
yylloc.filenum = srcpos_filenum;
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
DPRINT("Label: %s\n", yytext);
yylval.labelref = strdup(yytext);
......@@ -110,7 +111,7 @@ static int dts_version; /* = 0 */
}
<INITIAL>[bodh]# {
yylloc.filenum = srcpos_filenum;
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
if (*yytext == 'b')
yylval.cbase = 2;
......@@ -125,7 +126,7 @@ static int dts_version; /* = 0 */
}
<INITIAL>[0-9a-fA-F]+ {
yylloc.filenum = srcpos_filenum;
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
yylval.literal = strdup(yytext);
DPRINT("Literal: '%s'\n", yylval.literal);
......@@ -133,7 +134,7 @@ static int dts_version; /* = 0 */
}
<V1>[0-9]+|0[xX][0-9a-fA-F]+ {
yylloc.filenum = srcpos_filenum;
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
yylval.literal = strdup(yytext);
DPRINT("Literal: '%s'\n", yylval.literal);
......@@ -141,7 +142,7 @@ static int dts_version; /* = 0 */
}
\&{LABEL} { /* label reference */
yylloc.filenum = srcpos_filenum;
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = strdup(yytext+1);
......@@ -149,7 +150,7 @@ static int dts_version; /* = 0 */
}
"&{/"{PATHCHAR}+\} { /* new-style path reference */
yylloc.filenum = srcpos_filenum;
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
......@@ -158,7 +159,7 @@ static int dts_version; /* = 0 */
}
<INITIAL>"&/"{PATHCHAR}+ { /* old-style path reference */
yylloc.filenum = srcpos_filenum;
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = strdup(yytext+1);
......@@ -166,7 +167,7 @@ static int dts_version; /* = 0 */
}
<BYTESTRING>[0-9a-fA-F]{2} {
yylloc.filenum = srcpos_filenum;
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
yylval.byte = strtol(yytext, NULL, 16);
DPRINT("Byte: %02x\n", (int)yylval.byte);
......@@ -174,7 +175,7 @@ static int dts_version; /* = 0 */
}
<BYTESTRING>"]" {
yylloc.filenum = srcpos_filenum;
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
DPRINT("/BYTESTRING\n");
BEGIN_DEFAULT();
......@@ -182,7 +183,7 @@ static int dts_version; /* = 0 */
}
<PROPNODENAME>{PROPNODECHAR}+ {
yylloc.filenum = srcpos_filenum;
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
DPRINT("PropNodeName: %s\n", yytext);
yylval.propnodename = strdup(yytext);
......@@ -190,20 +191,19 @@ static int dts_version; /* = 0 */
return DT_PROPNODENAME;
}
<*>[[:space:]]+ /* eat whitespace */
<*>"/*"([^*]|\*+[^*/])*\*+"/" {
yylloc.filenum = srcpos_filenum;
"/incbin/" {
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
DPRINT("Comment: %s\n", yytext);
/* eat comments */
DPRINT("Binary Include\n");
return DT_INCBIN;
}
<*>"//".*\n /* eat line comments */
<*>{WS}+ /* eat whitespace */
<*>{COMMENT}+ /* eat C-style comments */
<*>{LINECOMMENT}+ /* eat C++-style comments */
<*>. {
yylloc.filenum = srcpos_filenum;
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
......@@ -227,14 +227,13 @@ static int dts_version; /* = 0 */
*/
struct incl_file {
int filenum;
FILE *file;
struct dtc_file *file;
YY_BUFFER_STATE yy_prev_buf;
int yy_prev_lineno;
struct incl_file *prev;
};
struct incl_file *incl_file_stack;
static struct incl_file *incl_file_stack;
/*
......@@ -245,36 +244,34 @@ struct incl_file *incl_file_stack;
static int incl_depth = 0;
int push_input_file(const char *filename)
static void push_input_file(const char *filename)
{
FILE *f;
struct incl_file *incl_file;
struct dtc_file *newfile;
struct search_path search, *searchptr = NULL;
if (!filename) {
yyerror("No include file name given.");
return 0;
}
assert(filename);
if (incl_depth++ >= MAX_INCLUDE_DEPTH) {
yyerror("Includes nested too deeply");
return 0;
if (incl_depth++ >= MAX_INCLUDE_DEPTH)
die("Includes nested too deeply");
if (srcpos_file) {
search.dir = srcpos_file->dir;
search.next = NULL;
search.prev = NULL;
searchptr = &search;
}
f = dtc_open_file(filename);
newfile = dtc_open_file(filename, searchptr);
incl_file = malloc(sizeof(struct incl_file));
if (!incl_file) {
yyerror("Can not allocate include file space.");
return 0;
}
incl_file = xmalloc(sizeof(struct incl_file));
/*
* Save current context.
*/
incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
incl_file->yy_prev_lineno = yylineno;
incl_file->filenum = srcpos_filenum;
incl_file->file = yyin;
incl_file->file = srcpos_file;
incl_file->prev = incl_file_stack;
incl_file_stack = incl_file;
......@@ -282,23 +279,21 @@ int push_input_file(const char *filename)
/*
* Establish new context.
*/
srcpos_filenum = lookup_file_name(filename, 0);
srcpos_file = newfile;
yylineno = 1;
yyin = f;
yyin = newfile->file;
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
return 1;
}
int pop_input_file(void)
static int pop_input_file(void)
{
struct incl_file *incl_file;
if (incl_file_stack == 0)
return 0;
fclose(yyin);
dtc_close_file(srcpos_file);
/*
* Pop.
......@@ -313,16 +308,13 @@ int pop_input_file(void)
yy_delete_buffer(YY_CURRENT_BUFFER);
yy_switch_to_buffer(incl_file->yy_prev_buf);
yylineno = incl_file->yy_prev_lineno;
srcpos_filenum = incl_file->filenum;
yyin = incl_file->file;
srcpos_file = incl_file->file;
yyin = incl_file->file ? incl_file->file->file : NULL;
/*
* Free old state.
*/
free(incl_file);
if (YY_CURRENT_BUFFER == 0)
return 0;
return 1;
}
......@@ -48,7 +48,8 @@
DT_BYTE = 264,
DT_STRING = 265,
DT_LABEL = 266,
DT_REF = 267
DT_REF = 267,
DT_INCBIN = 268
};
#endif
/* Tokens. */
......@@ -62,22 +63,23 @@
#define DT_STRING 265
#define DT_LABEL 266
#define DT_REF 267
#define DT_INCBIN 268
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 34 "dtc-parser.y"
#line 37 "dtc-parser.y"
{
char *propnodename;
char *literal;
char *labelref;
unsigned int cbase;
u8 byte;
uint8_t byte;
struct data data;
u64 addr;
uint64_t addr;
cell_t cell;
struct property *prop;
struct property *proplist;
......@@ -86,7 +88,7 @@ typedef union YYSTYPE
struct reserve_info *re;
}
/* Line 1489 of yacc.c. */
#line 90 "dtc-parser.tab.h"
#line 92 "dtc-parser.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
......
......@@ -21,14 +21,17 @@
%locations
%{
#include <stdio.h>
#include "dtc.h"
#include "srcpos.h"
int yylex(void);
unsigned long long eval_literal(const char *s, int base, int bits);
extern int yylex(void);
extern struct boot_info *the_boot_info;
extern int treesource_error;
static unsigned long long eval_literal(const char *s, int base, int bits);
%}
%union {
......@@ -36,10 +39,10 @@ extern struct boot_info *the_boot_info;
char *literal;
char *labelref;
unsigned int cbase;
u8 byte;
uint8_t byte;
struct data data;
u64 addr;
uint64_t addr;
cell_t cell;
struct property *prop;
struct property *proplist;
......@@ -58,6 +61,7 @@ extern struct boot_info *the_boot_info;
%token <data> DT_STRING
%token <labelref> DT_LABEL
%token <labelref> DT_REF
%token DT_INCBIN
%type <data> propdata
%type <data> propdataprefix
......@@ -84,11 +88,11 @@ extern struct boot_info *the_boot_info;
sourcefile:
DT_V1 ';' memreserves devicetree
{
the_boot_info = build_boot_info($3, $4);
the_boot_info = build_boot_info($3, $4, 0);
}
| v0_memreserves devicetree
{
the_boot_info = build_boot_info($1, $2);
the_boot_info = build_boot_info($1, $2, 0);
}
;
......@@ -196,6 +200,34 @@ propdata:
{
$$ = data_add_marker($1, REF_PATH, $2);
}
| propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
{
struct search_path path = { srcpos_file->dir, NULL, NULL };
struct dtc_file *file = dtc_open_file($4.val, &path);
struct data d = empty_data;
if ($6 != 0)
if (fseek(file->file, $6, SEEK_SET) != 0)
yyerrorf("Couldn't seek to offset %llu in \"%s\": %s",
(unsigned long long)$6,
$4.val, strerror(errno));
d = data_copy_file(file->file, $8);
$$ = data_merge($1, d);
dtc_close_file(file);
}
| propdataprefix DT_INCBIN '(' DT_STRING ')'
{
struct search_path path = { srcpos_file->dir, NULL, NULL };
struct dtc_file *file = dtc_open_file($4.val, &path);
struct data d = empty_data;
d = data_copy_file(file->file, -1);
$$ = data_merge($1, d);
dtc_close_file(file);
}
| propdata DT_LABEL
{
$$ = data_add_marker($1, LABEL, $2);
......@@ -282,7 +314,7 @@ subnodes:
}
| subnode propdef
{
yyerror("syntax error: properties must precede subnodes\n");
yyerror("syntax error: properties must precede subnodes");
YYERROR;
}
;
......@@ -307,18 +339,29 @@ label:
%%
void yyerror (char const *s)
void yyerrorf(char const *s, ...)
{
const char *fname = srcpos_filename_for_num(yylloc.filenum);
const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";
va_list va;
va_start(va, s);
if (strcmp(fname, "-") == 0)
fname = "stdin";
fprintf(stderr, "%s:%d %s\n",
fname, yylloc.first_line, s);
fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
vfprintf(stderr, s, va);
fprintf(stderr, "\n");
treesource_error = 1;
va_end(va);
}
void yyerror (char const *s)
{
yyerrorf("%s", s);
}
unsigned long long eval_literal(const char *s, int base, int bits)
static unsigned long long eval_literal(const char *s, int base, int bits)
{
unsigned long long val;
char *e;
......
......@@ -55,7 +55,7 @@ char *join_path(const char *path, const char *name)
return str;
}
void fill_fullpaths(struct node *tree, const char *prefix)
static void fill_fullpaths(struct node *tree, const char *prefix)
{
struct node *child;
const char *unit;
......@@ -106,7 +106,7 @@ static void __attribute__ ((noreturn)) usage(void)
fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
fprintf(stderr, "\t-v\n");
fprintf(stderr, "\t\tPrint DTC version and exit\n");
exit(2);
exit(3);
}
int main(int argc, char *argv[])
......@@ -118,10 +118,9 @@ int main(int argc, char *argv[])
int force = 0, check = 0;
const char *arg;
int opt;
FILE *inf = NULL;
FILE *outf = NULL;
int outversion = DEFAULT_FDT_VERSION;
int boot_cpuid_phys = 0xfeedbeef;
long long cmdline_boot_cpuid = -1;
quiet = 0;
reservenum = 0;
......@@ -161,11 +160,11 @@ int main(int argc, char *argv[])
quiet++;
break;
case 'b':
boot_cpuid_phys = strtol(optarg, NULL, 0);
cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
break;
case 'v':
printf("Version: %s\n", DTC_VERSION);
exit(0);
printf("Version: %s\n", DTC_VERSION);
exit(0);
case 'h':
default:
usage();
......@@ -180,31 +179,27 @@ int main(int argc, char *argv[])
arg = argv[optind];
/* minsize and padsize are mutually exclusive */
if ((minsize) && (padsize)) {
if (minsize && padsize)
die("Can't set both -p and -S\n");
}
fprintf(stderr, "DTC: %s->%s on file \"%s\"\n",
inform, outform, arg);
if (streq(inform, "dts")) {
if (streq(inform, "dts"))
bi = dt_from_source(arg);
} else if (streq(inform, "fs")) {
else if (streq(inform, "fs"))
bi = dt_from_fs(arg);
} else if(streq(inform, "dtb")) {
inf = dtc_open_file(arg);
bi = dt_from_blob(inf);
} else {
else if(streq(inform, "dtb"))
bi = dt_from_blob(arg);
else
die("Unknown input format \"%s\"\n", inform);
}
if (inf && (inf != stdin))
fclose(inf);
if (cmdline_boot_cpuid != -1)
bi->boot_cpuid_phys = cmdline_boot_cpuid;
if (! bi || ! bi->dt)
die("Couldn't read input tree\n");
fill_fullpaths(bi->dt, "");
process_checks(force, bi);
process_checks(force, bi, check, outversion, boot_cpuid_phys);
if (streq(outname, "-")) {
outf = stdout;
......@@ -218,9 +213,9 @@ int main(int argc, char *argv[])
if (streq(outform, "dts")) {
dt_to_source(outf, bi);
} else if (streq(outform, "dtb")) {
dt_to_blob(outf, bi, outversion, boot_cpuid_phys);
dt_to_blob(outf, bi, outversion);
} else if (streq(outform, "asm")) {
dt_to_asm(outf, bi, outversion, boot_cpuid_phys);
dt_to_asm(outf, bi, outversion);
} else if (streq(outform, "null")) {
/* do nothing */
} else {
......
......@@ -30,10 +30,8 @@
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <endian.h>
#include <byteswap.h>
#include <libfdt_env.h>
#include <fdt.h>
#define DEFAULT_FDT_VERSION 17
......@@ -75,25 +73,8 @@ static inline void *xrealloc(void *p, size_t len)
return new;
}
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef u32 cell_t;
typedef uint32_t cell_t;
#define cpu_to_be16(x) htons(x)
#define be16_to_cpu(x) ntohs(x)