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))
......@@ -242,6 +242,42 @@ static void check_duplicate_property_names(struct check *c, struct node *dt,
}
NODE_CHECK(duplicate_property_names, NULL, ERROR);
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define DIGITS "0123456789"
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
static void check_node_name_chars(struct check *c, struct node *dt,
struct node *node)
{
int n = strspn(node->name, c->data);
if (n < strlen(node->name))
FAIL(c, "Bad character '%c' in node %s",
node->name[n], node->fullpath);
}
NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);
static void check_node_name_format(struct check *c, struct node *dt,
struct node *node)
{
if (strchr(get_unitname(node), '@'))
FAIL(c, "Node %s has multiple '@' characters in name",
node->fullpath);
}
NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);
static void check_property_name_chars(struct check *c, struct node *dt,
struct node *node, struct property *prop)
{
int n = strspn(prop->name, c->data);
if (n < strlen(prop->name))
FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
prop->name[n], prop->name, node->fullpath);
}
PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);
static void check_explicit_phandles(struct check *c, struct node *root,
struct node *node)
{
......@@ -280,16 +316,29 @@ NODE_CHECK(explicit_phandles, NULL, ERROR);
static void check_name_properties(struct check *c, struct node *root,
struct node *node)
{
struct property *prop;
struct property **pp, *prop = NULL;
for (pp = &node->proplist; *pp; pp = &((*pp)->next))
if (streq((*pp)->name, "name")) {
prop = *pp;
break;
}
prop = get_property(node, "name");
if (!prop)
return; /* No name property, that's fine */
if ((prop->val.len != node->basenamelen+1)
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0))
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
" of base node name)", node->fullpath, prop->val.val);
} else {
/* The name property is correct, and therefore redundant.
* Delete it */
*pp = prop->next;
free(prop->name);
data_free(prop->val);
free(prop);
}
}
CHECK_IS_STRING(name_is_string, "name", ERROR);
NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
......@@ -316,7 +365,7 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
}
phandle = get_node_phandle(dt, refnode);
*((cell_t *)(prop->val.val + m->offset)) = cpu_to_be32(phandle);
*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
}
}
CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
......@@ -498,6 +547,7 @@ TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
&node_name_chars, &node_name_format, &property_name_chars,
&name_is_string, &name_properties,
&explicit_phandles,
&phandle_references, &path_references,
......@@ -511,10 +561,7 @@ static struct check *check_table[] = {
&obsolete_chosen_interrupt_controller,
};
int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys);
void process_checks(int force, struct boot_info *bi,
int checkflag, int outversion, int boot_cpuid_phys)
void process_checks(int force, struct boot_info *bi)
{
struct node *dt = bi->dt;
int i;
......@@ -537,214 +584,4 @@ void process_checks(int force, struct boot_info *bi,
"output forced\n");
}
}
if (checkflag) {
if (error) {
fprintf(stderr, "Warning: Skipping semantic checks due to structural errors\n");
} else {
if (!check_semantics(bi->dt, outversion,
boot_cpuid_phys))
fprintf(stderr, "Warning: Input tree has semantic errors\n");
}
}
}
/*
* Semantic check functions
*/
#define ERRMSG(...) if (quiet < 2) fprintf(stderr, "ERROR: " __VA_ARGS__)
#define WARNMSG(...) if (quiet < 1) fprintf(stderr, "Warning: " __VA_ARGS__)
#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0)
#define CHECK_HAVE(node, propname) \
do { \
if (! (prop = get_property((node), (propname)))) \
DO_ERR("Missing \"%s\" property in %s\n", (propname), \
(node)->fullpath); \
} while (0);
#define CHECK_HAVE_WARN(node, propname) \
do { \
if (! (prop = get_property((node), (propname)))) \
WARNMSG("%s has no \"%s\" property\n", \
(node)->fullpath, (propname)); \
} while (0)
#define CHECK_HAVE_STRING(node, propname) \
do { \
CHECK_HAVE((node), (propname)); \
if (prop && !data_is_one_string(prop->val)) \
DO_ERR("\"%s\" property in %s is not a string\n", \
(propname), (node)->fullpath); \
} while (0)
#define CHECK_HAVE_STREQ(node, propname, value) \
do { \
CHECK_HAVE_STRING((node), (propname)); \
if (prop && !streq(prop->val.val, (value))) \
DO_ERR("%s has wrong %s, %s (should be %s\n", \
(node)->fullpath, (propname), \
prop->val.val, (value)); \
} while (0)
#define CHECK_HAVE_ONECELL(node, propname) \
do { \
CHECK_HAVE((node), (propname)); \
if (prop && (prop->val.len != sizeof(cell_t))) \
DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \
} while (0)
#define CHECK_HAVE_WARN_ONECELL(node, propname) \
do { \
CHECK_HAVE_WARN((node), (propname)); \
if (prop && (prop->val.len != sizeof(cell_t))) \
DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \
} while (0)
#define CHECK_HAVE_WARN_PHANDLE(xnode, propname, root) \
do { \
struct node *ref; \
CHECK_HAVE_WARN_ONECELL((xnode), (propname)); \
if (prop) {\
cell_t phandle = propval_cell(prop); \
if ((phandle == 0) || (phandle == -1)) { \
DO_ERR("\"%s\" property in %s contains an invalid phandle %x\n", (propname), (xnode)->fullpath, phandle); \
} else { \
ref = get_node_by_phandle((root), propval_cell(prop)); \
if (! ref) \
DO_ERR("\"%s\" property in %s refers to non-existant phandle %x\n", (propname), (xnode)->fullpath, propval_cell(prop)); \
} \
} \
} while (0)
#define CHECK_HAVE_WARN_STRING(node, propname) \
do { \
CHECK_HAVE_WARN((node), (propname)); \
if (prop && !data_is_one_string(prop->val)) \
DO_ERR("\"%s\" property in %s is not a string\n", \
(propname), (node)->fullpath); \
} while (0)
static int check_root(struct node *root)
{
struct property *prop;
int ok = 1;
CHECK_HAVE_STRING(root, "model");
CHECK_HAVE_WARN(root, "compatible");
return ok;
}
static int check_cpus(struct node *root, int outversion, int boot_cpuid_phys)
{
struct node *cpus, *cpu;
struct property *prop;
struct node *bootcpu = NULL;
int ok = 1;
cpus = get_subnode(root, "cpus");
if (! cpus) {
ERRMSG("Missing /cpus node\n");
return 0;
}
if (cpus->addr_cells != 1)
DO_ERR("%s has bad #address-cells value %d (should be 1)\n",
cpus->fullpath, cpus->addr_cells);
if (cpus->size_cells != 0)
DO_ERR("%s has bad #size-cells value %d (should be 0)\n",
cpus->fullpath, cpus->size_cells);
for_each_child(cpus, cpu) {
CHECK_HAVE_STREQ(cpu, "device_type", "cpu");
CHECK_HAVE_ONECELL(cpu, "reg");
if (prop) {
cell_t unitnum;
char *eptr;
unitnum = strtol(get_unitname(cpu), &eptr, 16);
if (*eptr) {
WARNMSG("%s has bad format unit name %s (should be CPU number\n",
cpu->fullpath, get_unitname(cpu));
} else if (unitnum != propval_cell(prop)) {
WARNMSG("%s unit name \"%s\" does not match \"reg\" property <%x>\n",
cpu->fullpath, get_unitname(cpu),
propval_cell(prop));
}
}
/* CHECK_HAVE_ONECELL(cpu, "d-cache-line-size"); */
/* CHECK_HAVE_ONECELL(cpu, "i-cache-line-size"); */
CHECK_HAVE_ONECELL(cpu, "d-cache-size");
CHECK_HAVE_ONECELL(cpu, "i-cache-size");
CHECK_HAVE_WARN_ONECELL(cpu, "clock-frequency");
CHECK_HAVE_WARN_ONECELL(cpu, "timebase-frequency");
prop = get_property(cpu, "linux,boot-cpu");
if (prop) {
if (prop->val.len)
WARNMSG("\"linux,boot-cpu\" property in %s is non-empty\n",
cpu->fullpath);
if (bootcpu)
DO_ERR("Multiple boot cpus (%s and %s)\n",
bootcpu->fullpath, cpu->fullpath);
else
bootcpu = cpu;
}
}
if (outversion < 2) {
if (! bootcpu)
WARNMSG("No cpu has \"linux,boot-cpu\" property\n");
} else {
if (bootcpu)
WARNMSG("\"linux,boot-cpu\" property is deprecated in blob version 2 or higher\n");
if (boot_cpuid_phys == 0xfeedbeef)
WARNMSG("physical boot CPU not set. Use -b option to set\n");
}
return ok;
}
static int check_memory(struct node *root)
{
struct node *mem;
struct property *prop;
int nnodes = 0;
int ok = 1;
for_each_child(root, mem) {
if (! strneq(mem->name, "memory", mem->basenamelen))
continue;
nnodes++;
CHECK_HAVE_STREQ(mem, "device_type", "memory");
CHECK_HAVE(mem, "reg");
}
if (nnodes == 0) {
ERRMSG("No memory nodes\n");
return 0;
}
return ok;
}
int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys)
{
int ok = 1;
ok = ok && check_root(dt);
ok = ok && check_cpus(dt, outversion, boot_cpuid_phys);
ok = ok && check_memory(dt);
if (! ok)
return 0;
return 1;
}
......@@ -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,7 +160,7 @@ 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);
......@@ -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)
#define cpu_to_be32(x) htonl(x)
#define be32_to_cpu(x) ntohl(x)
#if __BYTE_ORDER == __BIG_ENDIAN
#define cpu_to_be64(x) (x)
#define be64_to_cpu(x) (x)
#else
#define cpu_to_be64(x) bswap_64(x)
#define be64_to_cpu(x) bswap_64(x)
#endif
#define streq(a, b) (strcmp((a), (b)) == 0)
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
......@@ -118,7 +99,6 @@ struct marker {
struct data {
int len;
char *val;
int asize;
struct marker *markers;
};
......@@ -145,7 +125,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m,
struct data data_merge(struct data d1, struct data d2);
struct data data_append_cell(struct data d, cell_t word);
struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
struct data data_append_addr(struct data d, u64 addr);
struct data data_append_addr(struct data d, uint64_t addr);
struct data data_append_byte(struct data d, uint8_t byte);
struct data data_append_zeroes(struct data d, int len);
struct data data_append_align(struct data d, int align);
......@@ -223,7 +203,7 @@ struct reserve_info {
char *label;
};
struct reserve_info *build_reserve_entry(u64 start, u64 len, char *label);
struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len, char *label);
struct reserve_info *chain_reserve_entry(struct reserve_info *first,
struct reserve_info *list);
struct reserve_info *add_reserve_entry(struct reserve_info *list,
......@@ -233,24 +213,22 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
struct boot_info {
struct reserve_info *reservelist;
struct node *dt; /* the device tree */
uint32_t boot_cpuid_phys;
};
struct boot_info *build_boot_info(struct reserve_info *reservelist,
struct node *tree);
struct node *tree, uint32_t boot_cpuid_phys);
/* Checks */
void process_checks(int force, struct boot_info *bi,
int checkflag, int outversion, int boot_cpuid_phys);
void process_checks(int force, struct boot_info *bi);
/* Flattened trees */
void dt_to_blob(FILE *f, struct boot_info *bi, int version,
int boot_cpuid_phys);
void dt_to_asm(FILE *f, struct boot_info *bi, int version,
int boot_cpuid_phys);
void dt_to_blob(FILE *f, struct boot_info *bi, int version);
void dt_to_asm(FILE *f, struct boot_info *bi, int version);
struct boot_info *dt_from_blob(FILE *f);
struct boot_info *dt_from_blob(const char *fname);
/* Tree source */
......@@ -264,6 +242,5 @@ struct boot_info *dt_from_fs(const char *dirname);
/* misc */
char *join_path(const char *path, const char *name);
void fill_fullpaths(struct node *tree, const char *prefix);
#endif /* _DTC_H */
This diff is collapsed.
......@@ -31,8 +31,8 @@ static struct node *read_fstree(const char *dirname)
struct node *tree;
d = opendir(dirname);
if (! d)
die("opendir(): %s\n", strerror(errno));
if (!d)
die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno));
tree = build_node(NULL, NULL);
......@@ -87,8 +87,6 @@ struct boot_info *dt_from_fs(const char *dirname)
tree = read_fstree(dirname);
tree = name_node(tree, "", NULL);
fill_fullpaths(tree, "");
return build_boot_info(NULL, tree);
return build_boot_info(NULL, tree, 0);
}
#ifndef _LIBFDT_ENV_H
#define _LIBFDT_ENV_H
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#define _B(n) ((unsigned long long)((uint8_t *)&x)[n])
static inline uint32_t fdt32_to_cpu(uint32_t x)
{
return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3);
}
#define cpu_to_fdt32(x) fdt32_to_cpu(x)
static inline uint64_t fdt64_to_cpu(uint64_t x)
{
return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32)
| (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7);
}
#define cpu_to_fdt64(x) fdt64_to_cpu(x)
#undef _B
#endif /* _LIBFDT_ENV_H */
......@@ -115,6 +115,7 @@ void add_child(struct node *parent, struct node *child)
struct node **p;
child->next_sibling = NULL;
child->parent = parent;
p = &parent->children;
while (*p)
......@@ -123,7 +124,8 @@ void add_child(struct node *parent, struct node *child)
*p = child;
}
struct reserve_info *build_reserve_entry(u64 address, u64 size, char *label)
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size,
char *label)
{
struct reserve_info *new = xmalloc(sizeof(*new));
......@@ -165,13 +167,14 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
}
struct boot_info *build_boot_info(struct reserve_info *reservelist,
struct node *tree)
struct node *tree, uint32_t boot_cpuid_phys)
{
struct boot_info *bi;
bi = xmalloc(sizeof(*bi));
bi->reservelist = reservelist;
bi->dt = tree;
bi->boot_cpuid_phys = boot_cpuid_phys;
return bi;
}
......@@ -202,7 +205,7 @@ struct property *get_property(struct node *node, const char *propname)
cell_t propval_cell(struct property *prop)
{
assert(prop->val.len == sizeof(cell_t));
return be32_to_cpu(*((cell_t *)prop->val.val));
return fdt32_to_cpu(*((cell_t *)prop->val.val));
}
struct node *get_subnode(struct node *node, const char *nodename)
......
......@@ -20,86 +20,97 @@
#include "dtc.h"
#include "srcpos.h"
/*
* Record the complete unique set of opened file names.
* Primarily used to cache source position file names.
*/
#define MAX_N_FILE_NAMES (100)
const char *file_names[MAX_N_FILE_NAMES];
static int n_file_names = 0;
/*
* Like yylineno, this is the current open file pos.
*/
int srcpos_filenum = -1;
struct dtc_file *srcpos_file;
FILE *dtc_open_file(const char *fname)
static int dtc_open_one(struct dtc_file *file,
const char *search,
const char *fname)
{
FILE *f;
char *fullname;
if (lookup_file_name(fname, 1) < 0)
die("Too many files opened\n");
if (search) {
fullname = xmalloc(strlen(search) + strlen(fname) + 2);
if (streq(fname, "-"))
f = stdin;
else
f = fopen(fname, "r");
strcpy(fullname, search);
strcat(fullname, "/");
strcat(fullname, fname);
} else {
fullname = strdup(fname);
}
if (! f)
die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
file->file = fopen(fullname, "r");
if (!file->file) {
free(fullname);
return 0;
}
return f;
file->name = fullname;
return 1;
}
struct dtc_file *dtc_open_file(const char *fname,
const struct search_path *search)
{
static const struct search_path default_search = { NULL, NULL, NULL };
/*
* Locate and optionally add filename fname in the file_names[] array.
*
* If the filename is currently not in the array and the boolean
* add_it is non-zero, an attempt to add the filename will be made.
*
* Returns;
* Index [0..MAX_N_FILE_NAMES) where the filename is kept
* -1 if the name can not be recorded
*/
struct dtc_file *file;
const char *slash;
int lookup_file_name(const char *fname, int add_it)
{
int i;
file = xmalloc(sizeof(struct dtc_file));
slash = strrchr(fname, '/');
if (slash) {
char *dir = xmalloc(slash - fname + 1);
for (i = 0; i < n_file_names; i++) {
if (strcmp(file_names[i], fname) == 0)
return i;
memcpy(dir, fname, slash - fname);
dir[slash - fname] = 0;
file->dir = dir;
} else {
file->dir = NULL;
}
if (add_it) {
if (n_file_names < MAX_N_FILE_NAMES) {
file_names[n_file_names] = strdup(fname);
return n_file_names++;
if (streq(fname, "-")) {
file->name = "stdin";
file->file = stdin;
return file;
}
if (fname[0] == '/') {
file->file = fopen(fname, "r");
if (!file->file)
goto fail;
file->name = strdup(fname);
return file;
}
return -1;
}
if (!search)
search = &default_search;
while (search) {
if (dtc_open_one(file, search->dir, fname))
return file;
const char *srcpos_filename_for_num(int filenum)
{
if (0 <= filenum && filenum < n_file_names) {
return file_names[filenum];
if (errno != ENOENT)
goto fail;
search = search->next;
}
return 0;
fail:
die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
}
const char *srcpos_get_filename(void)
void dtc_close_file(struct dtc_file *file)
{
return srcpos_filename_for_num(srcpos_filenum);
if (fclose(file->file))
die("Error closing \"%s\": %s\n", file->name, strerror(errno));
free(file->dir);
free(file);
}
......@@ -22,13 +22,21 @@
* array of all opened filenames.
*/
#include <stdio.h>
struct dtc_file {
char *dir;
const char *name;
FILE *file;
};
#if ! defined(YYLTYPE) && ! defined(YYLTYPE_IS_DECLARED)
typedef struct YYLTYPE {
int first_line;
int first_column;
int last_line;
int last_column;
int filenum;
struct dtc_file *file;
} YYLTYPE;
#define YYLTYPE_IS_DECLARED 1
......@@ -48,7 +56,7 @@ typedef struct YYLTYPE {
(Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
(Current).last_line = YYRHSLOC (Rhs, N).last_line; \
(Current).last_column = YYRHSLOC (Rhs, N).last_column; \
(Current).filenum = YYRHSLOC (Rhs, N).filenum; \
(Current).file = YYRHSLOC (Rhs, N).file; \
} \
else \
{ \
......@@ -56,20 +64,22 @@ typedef struct YYLTYPE {
YYRHSLOC (Rhs, 0).last_line; \
(Current).first_column = (Current).last_column = \
YYRHSLOC (Rhs, 0).last_column; \
(Current).filenum = YYRHSLOC (Rhs, 0).filenum; \
(Current).file = YYRHSLOC (Rhs, 0).file; \
} \
while (YYID (0))
extern void yyerror(char const *);
extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2)));
extern int srcpos_filenum;
extern struct dtc_file *srcpos_file;
extern int push_input_file(const char *filename);
extern int pop_input_file(void);
struct search_path {
const char *dir; /* NULL for current directory */
struct search_path *prev, *next;
};
extern FILE *dtc_open_file(const char *fname);
extern int lookup_file_name(const char *fname, int add_it);
extern const char *srcpos_filename_for_num(int filenum);
const char *srcpos_get_filename(void);
extern struct dtc_file *dtc_open_file(const char *fname,
const struct search_path *search);
extern void dtc_close_file(struct dtc_file *file);
......@@ -23,20 +23,23 @@
extern FILE *yyin;
extern int yyparse(void);
extern void yyerror(char const *);
struct boot_info *the_boot_info;
int treesource_error;
struct boot_info *dt_from_source(const char *fname)
{
the_boot_info = NULL;
treesource_error = 0;
push_input_file(fname);
srcpos_file = dtc_open_file(fname, NULL);
yyin = srcpos_file->file;
if (yyparse() != 0)
return NULL;
die("Unable to parse input tree\n");
fill_fullpaths(the_boot_info->dt, "");
if (treesource_error)
die("Syntax error parsing input tree\n");
return the_boot_info;
}
......@@ -144,7 +147,7 @@ static void write_propval_cells(FILE *f, struct data val)
m = m->next;
}
fprintf(f, "0x%x", be32_to_cpu(*cp++));
fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
if ((void *)cp >= propend)
break;
fprintf(f, " ");
......@@ -173,7 +176,7 @@ static void write_propval_bytes(FILE *f, struct data val)
}
fprintf(f, "%02hhx", *bp++);
if ((void *)bp >= propend)
if ((const void *)bp >= propend)
break;
fprintf(f, " ");
}
......
#define DTC_VERSION "DTC 1.0.0-gd6f9b62f"
#define DTC_VERSION "DTC 1.2.0"
......@@ -3,12 +3,6 @@
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.
#
LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
LIBFDT_INCLUDES = fdt.h libfdt.h
LIBFDT_EXTRA = libfdt_internal.h
LIBFDT_LIB = libfdt/libfdt.a
LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
$(LIBFDT_objdir)/$(LIBFDT_LIB): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
......@@ -63,7 +63,7 @@ int fdt_check_header(const void *fdt)
return -FDT_ERR_BADVERSION;
if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
return -FDT_ERR_BADVERSION;
} else if (fdt_magic(fdt) == SW_MAGIC) {
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
/* Unfinished sequential-write blob */
if (fdt_size_dt_struct(fdt) == 0)
return -FDT_ERR_BADSTATE;
......@@ -76,7 +76,7 @@ int fdt_check_header(const void *fdt)
const void *fdt_offset_ptr(const void *fdt, int offset, int len)
{
const void *p;
const char *p;
if (fdt_version(fdt) >= 0x11)
if (((offset + len) < offset)
......@@ -124,11 +124,59 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
}
if (nextoffset)
*nextoffset = ALIGN(offset, FDT_TAGSIZE);
*nextoffset = FDT_TAGALIGN(offset);
return tag;
}
int _fdt_check_node_offset(const void *fdt, int offset)
{
if ((offset < 0) || (offset % FDT_TAGSIZE)
|| (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
return -FDT_ERR_BADOFFSET;
return offset;
}
int fdt_next_node(const void *fdt, int offset, int *depth)
{
int nextoffset = 0;
uint32_t tag;
if (offset >= 0)
if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
return nextoffset;
do {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);
switch (tag) {
case FDT_PROP:
case FDT_NOP:
break;
case FDT_BEGIN_NODE:
if (depth)
(*depth)++;
break;
case FDT_END_NODE:
if (depth)
(*depth)--;
break;
case FDT_END:
return -FDT_ERR_NOTFOUND;
default:
return -FDT_ERR_BADSTRUCTURE;
}
} while (tag != FDT_BEGIN_NODE);
return offset;
}
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
{
int len = strlen(s) + 1;
......@@ -136,17 +184,14 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
const char *p;
for (p = strtab; p <= last; p++)
if (memeq(p, s, len))
if (memcmp(p, s, len) == 0)
return p;
return NULL;
}
int fdt_move(const void *fdt, void *buf, int bufsize)
{
int err = fdt_check_header(fdt);
if (err)
return err;
FDT_CHECK_HEADER(fdt);
if (fdt_totalsize(fdt) > bufsize)
return -FDT_ERR_NOSPACE;
......
This diff is collapsed.
This diff is collapsed.
......@@ -55,29 +55,29 @@
#include "libfdt_internal.h"
struct errtabent {
struct fdt_errtabent {
const char *str;
};
#define ERRTABENT(val) \
#define FDT_ERRTABENT(val) \
[(val)] = { .str = #val, }
static struct errtabent errtable[] = {
ERRTABENT(FDT_ERR_NOTFOUND),
ERRTABENT(FDT_ERR_EXISTS),
ERRTABENT(FDT_ERR_NOSPACE),
static struct fdt_errtabent fdt_errtable[] = {
FDT_ERRTABENT(FDT_ERR_NOTFOUND),
FDT_ERRTABENT(FDT_ERR_EXISTS),
FDT_ERRTABENT(FDT_ERR_NOSPACE),
ERRTABENT(FDT_ERR_BADOFFSET),
ERRTABENT(FDT_ERR_BADPATH),
ERRTABENT(FDT_ERR_BADSTATE),
FDT_ERRTABENT(FDT_ERR_BADOFFSET),
FDT_ERRTABENT(FDT_ERR_BADPATH),
FDT_ERRTABENT(FDT_ERR_BADSTATE),
ERRTABENT(FDT_ERR_TRUNCATED),
ERRTABENT(FDT_ERR_BADMAGIC),
ERRTABENT(FDT_ERR_BADVERSION),
ERRTABENT(FDT_ERR_BADSTRUCTURE),
ERRTABENT(FDT_ERR_BADLAYOUT),
FDT_ERRTABENT(FDT_ERR_TRUNCATED),
FDT_ERRTABENT(FDT_ERR_BADMAGIC),
FDT_ERRTABENT(FDT_ERR_BADVERSION),
FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
};
#define ERRTABSIZE (sizeof(errtable) / sizeof(errtable[0]))
#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
const char *fdt_strerror(int errval)
{
......@@ -85,8 +85,8 @@ const char *fdt_strerror(int errval)
return "<valid offset/length>";
else if (errval == 0)
return "<no error>";
else if (errval > -ERRTABSIZE) {
const char *s = errtable[-errval].str;
else if (errval > -FDT_ERRTABSIZE) {
const char *s = fdt_errtable[-errval].str;
if (s)
return s;
......
......@@ -55,14 +55,22 @@
#include "libfdt_internal.h"
static int check_header_sw(void *fdt)
static int _fdt_sw_check_header(void *fdt)
{
if (fdt_magic(fdt) != SW_MAGIC)
if (fdt_magic(fdt) != FDT_SW_MAGIC)
return -FDT_ERR_BADMAGIC;
/* FIXME: should check more details about the header state */
return 0;
}
static void *grab_space(void *fdt, int len)
#define FDT_SW_CHECK_HEADER(fdt) \
{ \
int err; \
if ((err = _fdt_sw_check_header(fdt)) != 0) \
return err; \
}
static void *_fdt_grab_space(void *fdt, int len)
{
int offset = fdt_size_dt_struct(fdt);
int spaceleft;
......@@ -86,12 +94,12 @@ int fdt_create(void *buf, int bufsize)
memset(buf, 0, bufsize);
fdt_set_magic(fdt, SW_MAGIC);
fdt_set_magic(fdt, FDT_SW_MAGIC);
fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
fdt_set_totalsize(fdt, bufsize);
fdt_set_off_mem_rsvmap(fdt, ALIGN(sizeof(struct fdt_header),
fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
sizeof(struct fdt_reserve_entry)));
fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
fdt_set_off_dt_strings(fdt, bufsize);
......@@ -102,11 +110,10 @@ int fdt_create(void *buf, int bufsize)
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
{
struct fdt_reserve_entry *re;
int err = check_header_sw(fdt);
int offset;
if (err)
return err;
FDT_SW_CHECK_HEADER(fdt);
if (fdt_size_dt_struct(fdt))
return -FDT_ERR_BADSTATE;
......@@ -114,7 +121,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
return -FDT_ERR_NOSPACE;
re = (struct fdt_reserve_entry *)(fdt + offset);
re = (struct fdt_reserve_entry *)((char *)fdt + offset);
re->address = cpu_to_fdt64(addr);
re->size = cpu_to_fdt64(size);
......@@ -131,13 +138,11 @@ int fdt_finish_reservemap(void *fdt)
int fdt_begin_node(void *fdt, const char *name)
{
struct fdt_node_header *nh;
int err = check_header_sw(fdt);
int namelen = strlen(name) + 1;
if (err)
return err;
FDT_SW_CHECK_HEADER(fdt);
nh = grab_space(fdt, sizeof(*nh) + ALIGN(namelen, FDT_TAGSIZE));
nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
if (! nh)
return -FDT_ERR_NOSPACE;
......@@ -149,12 +154,10 @@ int fdt_begin_node(void *fdt, const char *name)
int fdt_end_node(void *fdt)
{
uint32_t *en;
int err = check_header_sw(fdt);
if (err)
return err;
FDT_SW_CHECK_HEADER(fdt);
en = grab_space(fdt, FDT_TAGSIZE);
en = _fdt_grab_space(fdt, FDT_TAGSIZE);
if (! en)
return -FDT_ERR_NOSPACE;
......@@ -162,7 +165,7 @@ int fdt_end_node(void *fdt)
return 0;
}
static int find_add_string(void *fdt, const char *s)
static int _fdt_find_add_string(void *fdt, const char *s)
{
char *strtab = (char *)fdt + fdt_totalsize(fdt);
const char *p;
......@@ -188,17 +191,15 @@ static int find_add_string(void *fdt, const char *s)
int fdt_property(void *fdt, const char *name, const void *val, int len)
{
struct fdt_property *prop;
int err = check_header_sw(fdt);
int nameoff;
if (err)
return err;
FDT_SW_CHECK_HEADER(fdt);
nameoff = find_add_string(fdt, name);
nameoff = _fdt_find_add_string(fdt, name);
if (nameoff == 0)
return -FDT_ERR_NOSPACE;
prop = grab_space(fdt, sizeof(*prop) + ALIGN(len, FDT_TAGSIZE));
prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
if (! prop)
return -FDT_ERR_NOSPACE;
......@@ -211,18 +212,16 @@ int fdt_property(void *fdt, const char *name, const void *val, int len)
int fdt_finish(void *fdt)
{
int err = check_header_sw(fdt);
char *p = (char *)fdt;
uint32_t *end;
int oldstroffset, newstroffset;
uint32_t tag;
int offset, nextoffset;
if (err)
return err;
FDT_SW_CHECK_HEADER(fdt);
/* Add terminator */
end = grab_space(fdt, sizeof(*end));
end = _fdt_grab_space(fdt, sizeof(*end));
if (! end)
return -FDT_ERR_NOSPACE;
*end = cpu_to_fdt32(FDT_END);
......
......@@ -72,11 +72,11 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
return 0;
}
static void nop_region(void *start, int len)
static void _fdt_nop_region(void *start, int len)
{
uint32_t *p;
for (p = start; (void *)p < (start + len); p++)
for (p = start; (char *)p < ((char *)start + len); p++)
*p = cpu_to_fdt32(FDT_NOP);
}
......@@ -89,7 +89,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
if (! prop)
return len;
nop_region(prop, len + sizeof(*prop));
_fdt_nop_region(prop, len + sizeof(*prop));
return 0;
}
......@@ -139,6 +139,7 @@ int fdt_nop_node(void *fdt, int nodeoffset)
if (endoffset < 0)
return endoffset;
nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), endoffset - nodeoffset);
_fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
endoffset - nodeoffset);
return 0;
}
This diff is collapsed.
......@@ -52,38 +52,44 @@
*/
#include <fdt.h>
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define PALIGN(p, a) ((void *)ALIGN((unsigned long)(p), (a)))
#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
#define memeq(p, q, n) (memcmp((p), (q), (n)) == 0)
#define streq(p, q) (strcmp((p), (q)) == 0)
#define FDT_CHECK_HEADER(fdt) \
{ \
int err; \
if ((err = fdt_check_header(fdt)) != 0) \
return err; \
}
uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
int _fdt_check_node_offset(const void *fdt, int offset);
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
int _fdt_node_end_offset(void *fdt, int nodeoffset);
static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
{
return fdt + fdt_off_dt_struct(fdt) + offset;
return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
}
static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
{
return (void *)_fdt_offset_ptr(fdt, offset);
return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
}
static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
{
const struct fdt_reserve_entry *rsv_table =
fdt + fdt_off_mem_rsvmap(fdt);
(const struct fdt_reserve_entry *)
((const char *)fdt + fdt_off_mem_rsvmap(fdt));
return rsv_table + n;
}
static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
{
return (void *)_fdt_mem_rsv(fdt, n);
return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
}
#define SW_MAGIC (~FDT_MAGIC)
#define FDT_SW_MAGIC (~FDT_MAGIC)
#endif /* _LIBFDT_INTERNAL_H */
......@@ -6,6 +6,7 @@
typedef u32 uint32_t;
typedef u64 uint64_t;
typedef unsigned long uintptr_t;
#define fdt16_to_cpu(x) (x)
#define cpu_to_fdt16(x) (x)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment