提交 ed95d745 编写于 作者: D David Gibson 提交者: 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: NDavid Gibson <david@gibson.dropbear.id.au>
Signed-off-by: NPaul Mackerras <paulus@samba.org>
上级 0ec27c04
...@@ -5,21 +5,5 @@ ...@@ -5,21 +5,5 @@
# #
DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \ DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
checks.c checks.c
DTC_EXTRA = dtc.h srcpos.h DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
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_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o) 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, ...@@ -242,6 +242,42 @@ static void check_duplicate_property_names(struct check *c, struct node *dt,
} }
NODE_CHECK(duplicate_property_names, NULL, ERROR); 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, static void check_explicit_phandles(struct check *c, struct node *root,
struct node *node) struct node *node)
{ {
...@@ -280,16 +316,29 @@ NODE_CHECK(explicit_phandles, NULL, ERROR); ...@@ -280,16 +316,29 @@ NODE_CHECK(explicit_phandles, NULL, ERROR);
static void check_name_properties(struct check *c, struct node *root, static void check_name_properties(struct check *c, struct node *root,
struct node *node) 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) if (!prop)
return; /* No name property, that's fine */ return; /* No name property, that's fine */
if ((prop->val.len != node->basenamelen+1) 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" FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
" of base node name)", node->fullpath, prop->val.val); " 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); CHECK_IS_STRING(name_is_string, "name", ERROR);
NODE_CHECK(name_properties, NULL, ERROR, &name_is_string); NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
...@@ -301,23 +350,23 @@ NODE_CHECK(name_properties, NULL, ERROR, &name_is_string); ...@@ -301,23 +350,23 @@ NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
static void fixup_phandle_references(struct check *c, struct node *dt, static void fixup_phandle_references(struct check *c, struct node *dt,
struct node *node, struct property *prop) struct node *node, struct property *prop)
{ {
struct marker *m = prop->val.markers; struct marker *m = prop->val.markers;
struct node *refnode; struct node *refnode;
cell_t phandle; cell_t phandle;
for_each_marker_of_type(m, REF_PHANDLE) { for_each_marker_of_type(m, REF_PHANDLE) {
assert(m->offset + sizeof(cell_t) <= prop->val.len); assert(m->offset + sizeof(cell_t) <= prop->val.len);
refnode = get_node_by_ref(dt, m->ref); refnode = get_node_by_ref(dt, m->ref);
if (! refnode) { if (! refnode) {
FAIL(c, "Reference to non-existent node or label \"%s\"\n", FAIL(c, "Reference to non-existent node or label \"%s\"\n",
m->ref); m->ref);
continue; continue;
} }
phandle = get_node_phandle(dt, refnode); 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, CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
&duplicate_node_names, &explicit_phandles); &duplicate_node_names, &explicit_phandles);
...@@ -498,6 +547,7 @@ TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN); ...@@ -498,6 +547,7 @@ TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
static struct check *check_table[] = { static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names, &duplicate_node_names, &duplicate_property_names,
&node_name_chars, &node_name_format, &property_name_chars,
&name_is_string, &name_properties, &name_is_string, &name_properties,
&explicit_phandles, &explicit_phandles,
&phandle_references, &path_references, &phandle_references, &path_references,
...@@ -511,10 +561,7 @@ static struct check *check_table[] = { ...@@ -511,10 +561,7 @@ static struct check *check_table[] = {
&obsolete_chosen_interrupt_controller, &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)
void process_checks(int force, struct boot_info *bi,
int checkflag, int outversion, int boot_cpuid_phys)
{ {
struct node *dt = bi->dt; struct node *dt = bi->dt;
int i; int i;
...@@ -537,214 +584,4 @@ void process_checks(int force, struct boot_info *bi, ...@@ -537,214 +584,4 @@ void process_checks(int force, struct boot_info *bi,
"output forced\n"); "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) ...@@ -32,8 +32,6 @@ void data_free(struct data d)
m = nm; m = nm;
} }
assert(!d.val || d.asize);
if (d.val) if (d.val)
free(d.val); free(d.val);
} }
...@@ -43,9 +41,6 @@ struct data data_grow_for(struct data d, int xlen) ...@@ -43,9 +41,6 @@ struct data data_grow_for(struct data d, int xlen)
struct data nd; struct data nd;
int newsize; int newsize;
/* we must start with an allocated datum */
assert(!d.val || d.asize);
if (xlen == 0) if (xlen == 0)
return d; return d;
...@@ -56,11 +51,8 @@ struct data data_grow_for(struct data d, int xlen) ...@@ -56,11 +51,8 @@ struct data data_grow_for(struct data d, int xlen)
while ((d.len + xlen) > newsize) while ((d.len + xlen) > newsize)
newsize *= 2; newsize *= 2;
nd.asize = newsize;
nd.val = xrealloc(d.val, newsize); nd.val = xrealloc(d.val, newsize);
assert(nd.asize >= (d.len + xlen));
return nd; return nd;
} }
...@@ -83,16 +75,11 @@ static char get_oct_char(const char *s, int *i) ...@@ -83,16 +75,11 @@ static char get_oct_char(const char *s, int *i)
long val; long val;
x[3] = '\0'; x[3] = '\0';
x[0] = s[(*i)]; strncpy(x, s + *i, 3);
if (x[0]) {
x[1] = s[(*i)+1];
if (x[1])
x[2] = s[(*i)+2];
}
val = strtol(x, &endx, 8); val = strtol(x, &endx, 8);
if ((endx - x) == 0)
fprintf(stderr, "Empty \\nnn escape\n"); assert(endx > x);
(*i) += endx - x; (*i) += endx - x;
return val; return val;
...@@ -105,13 +92,11 @@ static char get_hex_char(const char *s, int *i) ...@@ -105,13 +92,11 @@ static char get_hex_char(const char *s, int *i)
long val; long val;
x[2] = '\0'; x[2] = '\0';
x[0] = s[(*i)]; strncpy(x, s + *i, 2);
if (x[0])
x[1] = s[(*i)+1];
val = strtol(x, &endx, 16); val = strtol(x, &endx, 16);
if ((endx - x) == 0) if (!(endx > x))
fprintf(stderr, "Empty \\x escape\n"); die("\\x used with no following hex digits\n");
(*i) += endx - x; (*i) += endx - x;
return val; return val;
...@@ -182,14 +167,29 @@ struct data data_copy_escape_string(const char *s, int len) ...@@ -182,14 +167,29 @@ struct data data_copy_escape_string(const char *s, int len)
return d; 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; if (maxlen == -1)
fread(d.val, len, 1, f); 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; return d;
} }
...@@ -247,7 +247,7 @@ struct data data_merge(struct data d1, struct data d2) ...@@ -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) 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)); 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) ...@@ -256,15 +256,15 @@ struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
{ {
struct fdt_reserve_entry bere; struct fdt_reserve_entry bere;
bere.address = cpu_to_be64(re->address); bere.address = cpu_to_fdt64(re->address);
bere.size = cpu_to_be64(re->size); bere.size = cpu_to_fdt64(re->size);
return data_append_data(d, &bere, sizeof(bere)); 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)); return data_append_data(d, &beaddr, sizeof(beaddr));
} }
......
...@@ -28,6 +28,10 @@ ...@@ -28,6 +28,10 @@
PROPNODECHAR [a-zA-Z0-9,._+*#?@-] PROPNODECHAR [a-zA-Z0-9,._+*#?@-]
PATHCHAR ({PROPNODECHAR}|[/]) PATHCHAR ({PROPNODECHAR}|[/])
LABEL [a-zA-Z_][a-zA-Z0-9_]* LABEL [a-zA-Z_][a-zA-Z0-9_]*
STRING \"([^\\"]|\\.)*\"
WS [[:space:]]
COMMENT "/*"([^*]|\*+[^*/])*\*+"/"
LINECOMMENT "//".*\n
%{ %{
#include "dtc.h" #include "dtc.h"
...@@ -52,29 +56,26 @@ static int dts_version; /* = 0 */ ...@@ -52,29 +56,26 @@ static int dts_version; /* = 0 */
DPRINT("<V1>\n"); \ DPRINT("<V1>\n"); \
BEGIN(V1); \ BEGIN(V1); \
} }
static void push_input_file(const char *filename);
static int pop_input_file(void);
%} %}
%% %%
<*>"/include/" BEGIN(INCLUDE); <*>"/include/"{WS}*{STRING} {
char *name = strchr(yytext, '\"') + 1;
<INCLUDE>\"[^"\n]*\" { yytext[yyleng-1] = '\0';
yytext[strlen(yytext) - 1] = 0; push_input_file(name);
if (!push_input_file(yytext + 1)) {
/* Some unrecoverable error.*/
exit(1);
}
BEGIN_DEFAULT();
} }
<*><<EOF>> { <*><<EOF>> {
if (!pop_input_file()) { if (!pop_input_file()) {
yyterminate(); yyterminate();
} }
} }
<*>\"([^\\"]|\\.)*\" { <*>{STRING} {
yylloc.filenum = srcpos_filenum; yylloc.file = srcpos_file;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("String: %s\n", yytext); DPRINT("String: %s\n", yytext);
yylval.data = data_copy_escape_string(yytext+1, yylval.data = data_copy_escape_string(yytext+1,
...@@ -84,7 +85,7 @@ static int dts_version; /* = 0 */ ...@@ -84,7 +85,7 @@ static int dts_version; /* = 0 */
} }
<*>"/dts-v1/" { <*>"/dts-v1/" {
yylloc.filenum = srcpos_filenum; yylloc.file = srcpos_file;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("Keyword: /dts-v1/\n"); DPRINT("Keyword: /dts-v1/\n");
dts_version = 1; dts_version = 1;
...@@ -93,7 +94,7 @@ static int dts_version; /* = 0 */ ...@@ -93,7 +94,7 @@ static int dts_version; /* = 0 */
} }
<*>"/memreserve/" { <*>"/memreserve/" {
yylloc.filenum = srcpos_filenum; yylloc.file = srcpos_file;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("Keyword: /memreserve/\n"); DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT(); BEGIN_DEFAULT();
...@@ -101,7 +102,7 @@ static int dts_version; /* = 0 */ ...@@ -101,7 +102,7 @@ static int dts_version; /* = 0 */
} }
<*>{LABEL}: { <*>{LABEL}: {
yylloc.filenum = srcpos_filenum; yylloc.file = srcpos_file;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("Label: %s\n", yytext); DPRINT("Label: %s\n", yytext);
yylval.labelref = strdup(yytext); yylval.labelref = strdup(yytext);
...@@ -110,7 +111,7 @@ static int dts_version; /* = 0 */ ...@@ -110,7 +111,7 @@ static int dts_version; /* = 0 */
} }
<INITIAL>[bodh]# { <INITIAL>[bodh]# {
yylloc.filenum = srcpos_filenum; yylloc.file = srcpos_file;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
if (*yytext == 'b') if (*yytext == 'b')
yylval.cbase = 2; yylval.cbase = 2;
...@@ -125,7 +126,7 @@ static int dts_version; /* = 0 */ ...@@ -125,7 +126,7 @@ static int dts_version; /* = 0 */
} }
<INITIAL>[0-9a-fA-F]+ { <INITIAL>[0-9a-fA-F]+ {
yylloc.filenum = srcpos_filenum; yylloc.file = srcpos_file;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
yylval.literal = strdup(yytext); yylval.literal = strdup(yytext);
DPRINT("Literal: '%s'\n", yylval.literal); DPRINT("Literal: '%s'\n", yylval.literal);
...@@ -133,7 +134,7 @@ static int dts_version; /* = 0 */ ...@@ -133,7 +134,7 @@ static int dts_version; /* = 0 */
} }
<V1>[0-9]+|0[xX][0-9a-fA-F]+ { <V1>[0-9]+|0[xX][0-9a-fA-F]+ {
yylloc.filenum = srcpos_filenum; yylloc.file = srcpos_file;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
yylval.literal = strdup(yytext); yylval.literal = strdup(yytext);
DPRINT("Literal: '%s'\n", yylval.literal); DPRINT("Literal: '%s'\n", yylval.literal);
...@@ -141,7 +142,7 @@ static int dts_version; /* = 0 */ ...@@ -141,7 +142,7 @@ static int dts_version; /* = 0 */
} }
\&{LABEL} { /* label reference */ \&{LABEL} { /* label reference */
yylloc.filenum = srcpos_filenum; yylloc.file = srcpos_file;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("Ref: %s\n", yytext+1); DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = strdup(yytext+1); yylval.labelref = strdup(yytext+1);
...@@ -149,7 +150,7 @@ static int dts_version; /* = 0 */ ...@@ -149,7 +150,7 @@ static int dts_version; /* = 0 */
} }
"&{/"{PATHCHAR}+\} { /* new-style path reference */ "&{/"{PATHCHAR}+\} { /* new-style path reference */
yylloc.filenum = srcpos_filenum; yylloc.file = srcpos_file;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
yytext[yyleng-1] = '\0'; yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2); DPRINT("Ref: %s\n", yytext+2);
...@@ -158,7 +159,7 @@ static int dts_version; /* = 0 */ ...@@ -158,7 +159,7 @@ static int dts_version; /* = 0 */
} }
<INITIAL>"&/"{PATHCHAR}+ { /* old-style path reference */ <INITIAL>"&/"{PATHCHAR}+ { /* old-style path reference */
yylloc.filenum = srcpos_filenum; yylloc.file = srcpos_file;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("Ref: %s\n", yytext+1); DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = strdup(yytext+1); yylval.labelref = strdup(yytext+1);
...@@ -166,7 +167,7 @@ static int dts_version; /* = 0 */ ...@@ -166,7 +167,7 @@ static int dts_version; /* = 0 */
} }
<BYTESTRING>[0-9a-fA-F]{2} { <BYTESTRING>[0-9a-fA-F]{2} {
yylloc.filenum = srcpos_filenum; yylloc.file = srcpos_file;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
yylval.byte = strtol(yytext, NULL, 16); yylval.byte = strtol(yytext, NULL, 16);
DPRINT("Byte: %02x\n", (int)yylval.byte); DPRINT("Byte: %02x\n", (int)yylval.byte);
...@@ -174,7 +175,7 @@ static int dts_version; /* = 0 */ ...@@ -174,7 +175,7 @@ static int dts_version; /* = 0 */
} }
<BYTESTRING>"]" { <BYTESTRING>"]" {
yylloc.filenum = srcpos_filenum; yylloc.file = srcpos_file;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("/BYTESTRING\n"); DPRINT("/BYTESTRING\n");
BEGIN_DEFAULT(); BEGIN_DEFAULT();
...@@ -182,7 +183,7 @@ static int dts_version; /* = 0 */ ...@@ -182,7 +183,7 @@ static int dts_version; /* = 0 */
} }
<PROPNODENAME>{PROPNODECHAR}+ { <PROPNODENAME>{PROPNODECHAR}+ {
yylloc.filenum = srcpos_filenum; yylloc.file = srcpos_file;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("PropNodeName: %s\n", yytext); DPRINT("PropNodeName: %s\n", yytext);
yylval.propnodename = strdup(yytext); yylval.propnodename = strdup(yytext);
...@@ -190,20 +191,19 @@ static int dts_version; /* = 0 */ ...@@ -190,20 +191,19 @@ static int dts_version; /* = 0 */
return DT_PROPNODENAME; return DT_PROPNODENAME;
} }
"/incbin/" {
<*>[[:space:]]+ /* eat whitespace */ yylloc.file = srcpos_file;
<*>"/*"([^*]|\*+[^*/])*\*+"/" {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("Comment: %s\n", yytext); DPRINT("Binary Include\n");
/* eat comments */ 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; yylloc.first_line = yylineno;
DPRINT("Char: %c (\\x%02x)\n", yytext[0], DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]); (unsigned)yytext[0]);
...@@ -227,14 +227,13 @@ static int dts_version; /* = 0 */ ...@@ -227,14 +227,13 @@ static int dts_version; /* = 0 */
*/ */
struct incl_file { struct incl_file {
int filenum; struct dtc_file *file;
FILE *file;
YY_BUFFER_STATE yy_prev_buf; YY_BUFFER_STATE yy_prev_buf;
int yy_prev_lineno; int yy_prev_lineno;
struct incl_file *prev; 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; ...@@ -245,36 +244,34 @@ struct incl_file *incl_file_stack;
static int incl_depth = 0; 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 incl_file *incl_file;
struct dtc_file *newfile;
struct search_path search, *searchptr = NULL;
if (!filename) { assert(filename);
yyerror("No include file name given.");
return 0;
}
if (incl_depth++ >= MAX_INCLUDE_DEPTH) { if (incl_depth++ >= MAX_INCLUDE_DEPTH)
yyerror("Includes nested too deeply"); die("Includes nested too deeply");
return 0;
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)); incl_file = xmalloc(sizeof(struct incl_file));
if (!incl_file) {
yyerror("Can not allocate include file space.");
return 0;
}
/* /*
* Save current context. * Save current context.
*/ */
incl_file->yy_prev_buf = YY_CURRENT_BUFFER; incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
incl_file->yy_prev_lineno = yylineno; incl_file->yy_prev_lineno = yylineno;
incl_file->filenum = srcpos_filenum; incl_file->file = srcpos_file;
incl_file->file = yyin;
incl_file->prev = incl_file_stack; incl_file->prev = incl_file_stack;
incl_file_stack = incl_file; incl_file_stack = incl_file;
...@@ -282,23 +279,21 @@ int push_input_file(const char *filename) ...@@ -282,23 +279,21 @@ int push_input_file(const char *filename)
/* /*
* Establish new context. * Establish new context.
*/ */
srcpos_filenum = lookup_file_name(filename, 0); srcpos_file = newfile;
yylineno = 1; yylineno = 1;
yyin = f; yyin = newfile->file;
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); 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; struct incl_file *incl_file;
if (incl_file_stack == 0) if (incl_file_stack == 0)
return 0; return 0;
fclose(yyin); dtc_close_file(srcpos_file);
/* /*
* Pop. * Pop.
...@@ -313,16 +308,13 @@ int pop_input_file(void) ...@@ -313,16 +308,13 @@ int pop_input_file(void)
yy_delete_buffer(YY_CURRENT_BUFFER); yy_delete_buffer(YY_CURRENT_BUFFER);
yy_switch_to_buffer(incl_file->yy_prev_buf); yy_switch_to_buffer(incl_file->yy_prev_buf);
yylineno = incl_file->yy_prev_lineno; yylineno = incl_file->yy_prev_lineno;
srcpos_filenum = incl_file->filenum; srcpos_file = incl_file->file;
yyin = incl_file->file; yyin = incl_file->file ? incl_file->file->file : NULL;
/* /*
* Free old state. * Free old state.
*/ */
free(incl_file); free(incl_file);
if (YY_CURRENT_BUFFER == 0)
return 0;
return 1; return 1;
} }
...@@ -48,7 +48,8 @@ ...@@ -48,7 +48,8 @@
DT_BYTE = 264, DT_BYTE = 264,
DT_STRING = 265, DT_STRING = 265,
DT_LABEL = 266, DT_LABEL = 266,
DT_REF = 267 DT_REF = 267,
DT_INCBIN = 268
}; };
#endif #endif
/* Tokens. */ /* Tokens. */
...@@ -62,22 +63,23 @@ ...@@ -62,22 +63,23 @@
#define DT_STRING 265 #define DT_STRING 265
#define DT_LABEL 266 #define DT_LABEL 266
#define DT_REF 267 #define DT_REF 267
#define DT_INCBIN 268
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE typedef union YYSTYPE
#line 34 "dtc-parser.y" #line 37 "dtc-parser.y"
{ {
char *propnodename; char *propnodename;
char *literal; char *literal;
char *labelref; char *labelref;
unsigned int cbase; unsigned int cbase;
u8 byte; uint8_t byte;
struct data data; struct data data;
u64 addr; uint64_t addr;
cell_t cell; cell_t cell;
struct property *prop; struct property *prop;
struct property *proplist; struct property *proplist;
...@@ -86,7 +88,7 @@ typedef union YYSTYPE ...@@ -86,7 +88,7 @@ typedef union YYSTYPE
struct reserve_info *re; struct reserve_info *re;
} }
/* Line 1489 of yacc.c. */ /* Line 1489 of yacc.c. */
#line 90 "dtc-parser.tab.h" #line 92 "dtc-parser.tab.h"
YYSTYPE; YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_DECLARED 1
......
...@@ -21,14 +21,17 @@ ...@@ -21,14 +21,17 @@
%locations %locations
%{ %{
#include <stdio.h>
#include "dtc.h" #include "dtc.h"
#include "srcpos.h" #include "srcpos.h"
int yylex(void); extern int yylex(void);
unsigned long long eval_literal(const char *s, int base, int bits);
extern struct boot_info *the_boot_info; 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 { %union {
...@@ -36,10 +39,10 @@ extern struct boot_info *the_boot_info; ...@@ -36,10 +39,10 @@ extern struct boot_info *the_boot_info;
char *literal; char *literal;
char *labelref; char *labelref;
unsigned int cbase; unsigned int cbase;
u8 byte; uint8_t byte;
struct data data; struct data data;
u64 addr; uint64_t addr;
cell_t cell; cell_t cell;
struct property *prop; struct property *prop;
struct property *proplist; struct property *proplist;
...@@ -58,6 +61,7 @@ extern struct boot_info *the_boot_info; ...@@ -58,6 +61,7 @@ extern struct boot_info *the_boot_info;
%token <data> DT_STRING %token <data> DT_STRING
%token <labelref> DT_LABEL %token <labelref> DT_LABEL
%token <labelref> DT_REF %token <labelref> DT_REF
%token DT_INCBIN
%type <data> propdata %type <data> propdata
%type <data> propdataprefix %type <data> propdataprefix
...@@ -84,11 +88,11 @@ extern struct boot_info *the_boot_info; ...@@ -84,11 +88,11 @@ extern struct boot_info *the_boot_info;
sourcefile: sourcefile:
DT_V1 ';' memreserves devicetree DT_V1 ';' memreserves devicetree
{ {
the_boot_info = build_boot_info($3, $4); the_boot_info = build_boot_info($3, $4, 0);
} }
| v0_memreserves devicetree | 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: ...@@ -196,6 +200,34 @@ propdata:
{ {
$$ = data_add_marker($1, REF_PATH, $2); $$ = 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 | propdata DT_LABEL
{ {
$$ = data_add_marker($1, LABEL, $2); $$ = data_add_marker($1, LABEL, $2);
...@@ -282,7 +314,7 @@ subnodes: ...@@ -282,7 +314,7 @@ subnodes:
} }
| subnode propdef | subnode propdef
{ {
yyerror("syntax error: properties must precede subnodes\n"); yyerror("syntax error: properties must precede subnodes");
YYERROR; YYERROR;
} }
; ;
...@@ -307,18 +339,29 @@ label: ...@@ -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) if (strcmp(fname, "-") == 0)
fname = "stdin"; fname = "stdin";
fprintf(stderr, "%s:%d %s\n", fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
fname, yylloc.first_line, s); 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; unsigned long long val;
char *e; char *e;
......
...@@ -55,7 +55,7 @@ char *join_path(const char *path, const char *name) ...@@ -55,7 +55,7 @@ char *join_path(const char *path, const char *name)
return str; return str;
} }
void fill_fullpaths(struct node *tree, const char *prefix) static void fill_fullpaths(struct node *tree, const char *prefix)
{ {
struct node *child; struct node *child;
const char *unit; const char *unit;
...@@ -106,7 +106,7 @@ static void __attribute__ ((noreturn)) usage(void) ...@@ -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\tForce - try to produce output even if the input tree has errors\n");
fprintf(stderr, "\t-v\n"); fprintf(stderr, "\t-v\n");
fprintf(stderr, "\t\tPrint DTC version and exit\n"); fprintf(stderr, "\t\tPrint DTC version and exit\n");
exit(2); exit(3);
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
...@@ -118,10 +118,9 @@ int main(int argc, char *argv[]) ...@@ -118,10 +118,9 @@ int main(int argc, char *argv[])
int force = 0, check = 0; int force = 0, check = 0;
const char *arg; const char *arg;
int opt; int opt;
FILE *inf = NULL;
FILE *outf = NULL; FILE *outf = NULL;
int outversion = DEFAULT_FDT_VERSION; int outversion = DEFAULT_FDT_VERSION;
int boot_cpuid_phys = 0xfeedbeef; long long cmdline_boot_cpuid = -1;
quiet = 0; quiet = 0;
reservenum = 0; reservenum = 0;
...@@ -161,11 +160,11 @@ int main(int argc, char *argv[]) ...@@ -161,11 +160,11 @@ int main(int argc, char *argv[])
quiet++; quiet++;
break; break;
case 'b': case 'b':
boot_cpuid_phys = strtol(optarg, NULL, 0); cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
break; break;
case 'v': case 'v':
printf("Version: %s\n", DTC_VERSION); printf("Version: %s\n", DTC_VERSION);
exit(0); exit(0);
case 'h': case 'h':
default: default:
usage(); usage();
...@@ -180,31 +179,27 @@ int main(int argc, char *argv[]) ...@@ -180,31 +179,27 @@ int main(int argc, char *argv[])
arg = argv[optind]; arg = argv[optind];
/* minsize and padsize are mutually exclusive */ /* minsize and padsize are mutually exclusive */
if ((minsize) && (padsize)) { if (minsize && padsize)
die("Can't set both -p and -S\n"); die("Can't set both -p and -S\n");
}
fprintf(stderr, "DTC: %s->%s on file \"%s\"\n", fprintf(stderr, "DTC: %s->%s on file \"%s\"\n",
inform, outform, arg); inform, outform, arg);
if (streq(inform, "dts")) { if (streq(inform, "dts"))
bi = dt_from_source(arg); bi = dt_from_source(arg);
} else if (streq(inform, "fs")) { else if (streq(inform, "fs"))
bi = dt_from_fs(arg); bi = dt_from_fs(arg);
} else if(streq(inform, "dtb")) { else if(streq(inform, "dtb"))
inf = dtc_open_file(arg); bi = dt_from_blob(arg);
bi = dt_from_blob(inf); else
} else {
die("Unknown input format \"%s\"\n", inform); die("Unknown input format \"%s\"\n", inform);
}
if (inf && (inf != stdin)) if (cmdline_boot_cpuid != -1)
fclose(inf); bi->boot_cpuid_phys = cmdline_boot_cpuid;
if (! bi || ! bi->dt) fill_fullpaths(bi->dt, "");
die("Couldn't read input tree\n"); process_checks(force, bi);
process_checks(force, bi, check, outversion, boot_cpuid_phys);
if (streq(outname, "-")) { if (streq(outname, "-")) {
outf = stdout; outf = stdout;
...@@ -218,9 +213,9 @@ int main(int argc, char *argv[]) ...@@ -218,9 +213,9 @@ int main(int argc, char *argv[])
if (streq(outform, "dts")) { if (streq(outform, "dts")) {
dt_to_source(outf, bi); dt_to_source(outf, bi);
} else if (streq(outform, "dtb")) { } 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")) { } 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")) { } else if (streq(outform, "null")) {
/* do nothing */ /* do nothing */
} else { } else {
......
...@@ -30,10 +30,8 @@ ...@@ -30,10 +30,8 @@
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <netinet/in.h>
#include <endian.h>
#include <byteswap.h>
#include <libfdt_env.h>
#include <fdt.h> #include <fdt.h>
#define DEFAULT_FDT_VERSION 17 #define DEFAULT_FDT_VERSION 17
...@@ -75,25 +73,8 @@ static inline void *xrealloc(void *p, size_t len) ...@@ -75,25 +73,8 @@ static inline void *xrealloc(void *p, size_t len)
return new; return new;
} }
typedef uint8_t u8; typedef uint32_t cell_t;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef u32 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 streq(a, b) (strcmp((a), (b)) == 0)
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) #define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
...@@ -118,7 +99,6 @@ struct marker { ...@@ -118,7 +99,6 @@ struct marker {
struct data { struct data {
int len; int len;
char *val; char *val;
int asize;
struct marker *markers; struct marker *markers;
}; };
...@@ -145,7 +125,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m, ...@@ -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_merge(struct data d1, struct data d2);
struct data data_append_cell(struct data d, cell_t word); 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_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_byte(struct data d, uint8_t byte);
struct data data_append_zeroes(struct data d, int len); struct data data_append_zeroes(struct data d, int len);
struct data data_append_align(struct data d, int align); struct data data_append_align(struct data d, int align);
...@@ -223,7 +203,7 @@ struct reserve_info { ...@@ -223,7 +203,7 @@ struct reserve_info {
char *label; 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 *chain_reserve_entry(struct reserve_info *first,
struct reserve_info *list); struct reserve_info *list);
struct reserve_info *add_reserve_entry(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, ...@@ -233,24 +213,22 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
struct boot_info { struct boot_info {
struct reserve_info *reservelist; struct reserve_info *reservelist;
struct node *dt; /* the device tree */ struct node *dt; /* the device tree */
uint32_t boot_cpuid_phys;
}; };
struct boot_info *build_boot_info(struct reserve_info *reservelist, struct boot_info *build_boot_info(struct reserve_info *reservelist,
struct node *tree); struct node *tree, uint32_t boot_cpuid_phys);
/* Checks */ /* Checks */
void process_checks(int force, struct boot_info *bi, void process_checks(int force, struct boot_info *bi);
int checkflag, int outversion, int boot_cpuid_phys);
/* Flattened trees */ /* Flattened trees */
void dt_to_blob(FILE *f, struct boot_info *bi, int version, 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);
void dt_to_asm(FILE *f, struct boot_info *bi, int version,
int boot_cpuid_phys);
struct boot_info *dt_from_blob(FILE *f); struct boot_info *dt_from_blob(const char *fname);
/* Tree source */ /* Tree source */
...@@ -264,6 +242,5 @@ struct boot_info *dt_from_fs(const char *dirname); ...@@ -264,6 +242,5 @@ struct boot_info *dt_from_fs(const char *dirname);
/* misc */ /* misc */
char *join_path(const char *path, const char *name); char *join_path(const char *path, const char *name);
void fill_fullpaths(struct node *tree, const char *prefix);
#endif /* _DTC_H */ #endif /* _DTC_H */
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
*/ */
#include "dtc.h" #include "dtc.h"
#include "srcpos.h"
#define FTF_FULLPATH 0x1 #define FTF_FULLPATH 0x1
#define FTF_VARALIGN 0x2 #define FTF_VARALIGN 0x2
...@@ -162,28 +163,18 @@ static void asm_emit_data(void *e, struct data d) ...@@ -162,28 +163,18 @@ static void asm_emit_data(void *e, struct data d)
{ {
FILE *f = e; FILE *f = e;
int off = 0; int off = 0;
struct marker *m; struct marker *m = d.markers;
m = d.markers; for_each_marker_of_type(m, LABEL)
while (m) { emit_offset_label(f, m->ref, m->offset);
if (m->type == LABEL)
emit_offset_label(f, m->ref, m->offset);
m = m->next;
}
while ((d.len - off) >= sizeof(u32)) { while ((d.len - off) >= sizeof(uint32_t)) {
fprintf(f, "\t.long\t0x%x\n", fprintf(f, "\t.long\t0x%x\n",
be32_to_cpu(*((u32 *)(d.val+off)))); fdt32_to_cpu(*((uint32_t *)(d.val+off))));
off += sizeof(u32); off += sizeof(uint32_t);
}
if ((d.len - off) >= sizeof(u16)) {
fprintf(f, "\t.short\t0x%hx\n",
be16_to_cpu(*((u16 *)(d.val+off))));
off += sizeof(u16);
} }
if ((d.len - off) >= 1) { while ((d.len - off) >= 1) {
fprintf(f, "\t.byte\t0x%hhx\n", d.val[off]); fprintf(f, "\t.byte\t0x%hhx\n", d.val[off]);
off += 1; off += 1;
} }
...@@ -336,29 +327,28 @@ static void make_fdt_header(struct fdt_header *fdt, ...@@ -336,29 +327,28 @@ static void make_fdt_header(struct fdt_header *fdt,
memset(fdt, 0xff, sizeof(*fdt)); memset(fdt, 0xff, sizeof(*fdt));
fdt->magic = cpu_to_be32(FDT_MAGIC); fdt->magic = cpu_to_fdt32(FDT_MAGIC);
fdt->version = cpu_to_be32(vi->version); fdt->version = cpu_to_fdt32(vi->version);
fdt->last_comp_version = cpu_to_be32(vi->last_comp_version); fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version);
/* Reserve map should be doubleword aligned */ /* Reserve map should be doubleword aligned */
reserve_off = ALIGN(vi->hdr_size, 8); reserve_off = ALIGN(vi->hdr_size, 8);
fdt->off_mem_rsvmap = cpu_to_be32(reserve_off); fdt->off_mem_rsvmap = cpu_to_fdt32(reserve_off);
fdt->off_dt_struct = cpu_to_be32(reserve_off + reservesize); fdt->off_dt_struct = cpu_to_fdt32(reserve_off + reservesize);
fdt->off_dt_strings = cpu_to_be32(reserve_off + reservesize fdt->off_dt_strings = cpu_to_fdt32(reserve_off + reservesize
+ dtsize); + dtsize);
fdt->totalsize = cpu_to_be32(reserve_off + reservesize + dtsize + strsize); fdt->totalsize = cpu_to_fdt32(reserve_off + reservesize + dtsize + strsize);
if (vi->flags & FTF_BOOTCPUID) if (vi->flags & FTF_BOOTCPUID)
fdt->boot_cpuid_phys = cpu_to_be32(boot_cpuid_phys); fdt->boot_cpuid_phys = cpu_to_fdt32(boot_cpuid_phys);
if (vi->flags & FTF_STRTABSIZE) if (vi->flags & FTF_STRTABSIZE)
fdt->size_dt_strings = cpu_to_be32(strsize); fdt->size_dt_strings = cpu_to_fdt32(strsize);
if (vi->flags & FTF_STRUCTSIZE) if (vi->flags & FTF_STRUCTSIZE)
fdt->size_dt_struct = cpu_to_be32(dtsize); fdt->size_dt_struct = cpu_to_fdt32(dtsize);
} }
void dt_to_blob(FILE *f, struct boot_info *bi, int version, void dt_to_blob(FILE *f, struct boot_info *bi, int version)
int boot_cpuid_phys)
{ {
struct version_info *vi = NULL; struct version_info *vi = NULL;
int i; int i;
...@@ -383,26 +373,26 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, ...@@ -383,26 +373,26 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version,
/* Make header */ /* Make header */
make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len, make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
boot_cpuid_phys); bi->boot_cpuid_phys);
/* /*
* If the user asked for more space than is used, adjust the totalsize. * If the user asked for more space than is used, adjust the totalsize.
*/ */
if (minsize > 0) { if (minsize > 0) {
padlen = minsize - be32_to_cpu(fdt.totalsize); padlen = minsize - fdt32_to_cpu(fdt.totalsize);
if ((padlen < 0) && (quiet < 1)) if ((padlen < 0) && (quiet < 1))
fprintf(stderr, fprintf(stderr,
"Warning: blob size %d >= minimum size %d\n", "Warning: blob size %d >= minimum size %d\n",
be32_to_cpu(fdt.totalsize), minsize); fdt32_to_cpu(fdt.totalsize), minsize);
} }
if (padsize > 0) if (padsize > 0)
padlen = padsize; padlen = padsize;
if (padlen > 0) { if (padlen > 0) {
int tsize = be32_to_cpu(fdt.totalsize); int tsize = fdt32_to_cpu(fdt.totalsize);
tsize += padlen; tsize += padlen;
fdt.totalsize = cpu_to_be32(tsize); fdt.totalsize = cpu_to_fdt32(tsize);
} }
/* /*
...@@ -410,7 +400,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, ...@@ -410,7 +400,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version,
* the reserve buffer, add the reserve map terminating zeroes, * the reserve buffer, add the reserve map terminating zeroes,
* the device tree itself, and finally the strings. * the device tree itself, and finally the strings.
*/ */
blob = data_append_data(blob, &fdt, sizeof(fdt)); blob = data_append_data(blob, &fdt, vi->hdr_size);
blob = data_append_align(blob, 8); blob = data_append_align(blob, 8);
blob = data_merge(blob, reservebuf); blob = data_merge(blob, reservebuf);
blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry)); blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry));
...@@ -449,7 +439,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf) ...@@ -449,7 +439,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
} }
} }
void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) void dt_to_asm(FILE *f, struct boot_info *bi, int version)
{ {
struct version_info *vi = NULL; struct version_info *vi = NULL;
int i; int i;
...@@ -489,7 +479,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) ...@@ -489,7 +479,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys)
if (vi->flags & FTF_BOOTCPUID) if (vi->flags & FTF_BOOTCPUID)
fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n", fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n",
boot_cpuid_phys); bi->boot_cpuid_phys);
if (vi->flags & FTF_STRTABSIZE) if (vi->flags & FTF_STRTABSIZE)
fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n", fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n",
...@@ -579,15 +569,15 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len) ...@@ -579,15 +569,15 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len)
inb->ptr += len; inb->ptr += len;
} }
static u32 flat_read_word(struct inbuf *inb) static uint32_t flat_read_word(struct inbuf *inb)
{ {
u32 val; uint32_t val;
assert(((inb->ptr - inb->base) % sizeof(val)) == 0); assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
flat_read_chunk(inb, &val, sizeof(val)); flat_read_chunk(inb, &val, sizeof(val));
return be32_to_cpu(val); return fdt32_to_cpu(val);
} }
static void flat_realign(struct inbuf *inb, int align) static void flat_realign(struct inbuf *inb, int align)
...@@ -615,7 +605,7 @@ static char *flat_read_string(struct inbuf *inb) ...@@ -615,7 +605,7 @@ static char *flat_read_string(struct inbuf *inb)
inb->ptr += len; inb->ptr += len;
flat_realign(inb, sizeof(u32)); flat_realign(inb, sizeof(uint32_t));
return str; return str;
} }
...@@ -632,7 +622,7 @@ static struct data flat_read_data(struct inbuf *inb, int len) ...@@ -632,7 +622,7 @@ static struct data flat_read_data(struct inbuf *inb, int len)
flat_read_chunk(inb, d.val, len); flat_read_chunk(inb, d.val, len);
flat_realign(inb, sizeof(u32)); flat_realign(inb, sizeof(uint32_t));
return d; return d;
} }
...@@ -659,7 +649,7 @@ static char *flat_read_stringtable(struct inbuf *inb, int offset) ...@@ -659,7 +649,7 @@ static char *flat_read_stringtable(struct inbuf *inb, int offset)
static struct property *flat_read_property(struct inbuf *dtbuf, static struct property *flat_read_property(struct inbuf *dtbuf,
struct inbuf *strbuf, int flags) struct inbuf *strbuf, int flags)
{ {
u32 proplen, stroff; uint32_t proplen, stroff;
char *name; char *name;
struct data val; struct data val;
...@@ -693,8 +683,8 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) ...@@ -693,8 +683,8 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
p = inb->ptr; p = inb->ptr;
while (1) { while (1) {
flat_read_chunk(inb, &re, sizeof(re)); flat_read_chunk(inb, &re, sizeof(re));
re.address = be64_to_cpu(re.address); re.address = fdt64_to_cpu(re.address);
re.size = be64_to_cpu(re.size); re.size = fdt64_to_cpu(re.size);
if (re.size == 0) if (re.size == 0)
break; break;
...@@ -708,77 +698,37 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) ...@@ -708,77 +698,37 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
static char *nodename_from_path(const char *ppath, const char *cpath) static char *nodename_from_path(const char *ppath, const char *cpath)
{ {
const char *lslash;
int plen; int plen;
lslash = strrchr(cpath, '/'); plen = strlen(ppath);
if (! lslash)
return NULL;
plen = lslash - cpath;
if (streq(cpath, "/") && streq(ppath, ""))
return "";
if ((plen == 0) && streq(ppath, "/"))
return strdup(lslash+1);
if (! strneq(ppath, cpath, plen))
return NULL;
return strdup(lslash+1);
}
static const char PROPCHAR[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,._+*#?-";
static const char UNITCHAR[] = "0123456789abcdef,";
static int check_node_name(const char *name)
{
const char *atpos;
int basenamelen;
atpos = strrchr(name, '@'); if (!strneq(ppath, cpath, plen))
die("Path \"%s\" is not valid as a child of \"%s\"\n",
cpath, ppath);
if (atpos) /* root node is a special case */
basenamelen = atpos - name; if (!streq(ppath, "/"))
else plen++;
basenamelen = strlen(name);
if (strspn(name, PROPCHAR) < basenamelen)
return -1;
if (atpos return strdup(cpath + plen);
&& ((basenamelen + 1 + strspn(atpos+1, UNITCHAR)) < strlen(name)))
return -1;
return basenamelen;
} }
static struct node *unflatten_tree(struct inbuf *dtbuf, static struct node *unflatten_tree(struct inbuf *dtbuf,
struct inbuf *strbuf, struct inbuf *strbuf,
const char *parent_path, int flags) const char *parent_flatname, int flags)
{ {
struct node *node; struct node *node;
u32 val; char *flatname;
uint32_t val;
node = build_node(NULL, NULL); node = build_node(NULL, NULL);
if (flags & FTF_FULLPATH) { flatname = flat_read_string(dtbuf);
node->fullpath = flat_read_string(dtbuf);
node->name = nodename_from_path(parent_path, node->fullpath);
if (! node->name)
die("Path \"%s\" is not valid as a child of \"%s\"\n",
node->fullpath, parent_path);
} else {
node->name = flat_read_string(dtbuf);
node->fullpath = join_path(parent_path, node->name);
}
node->basenamelen = check_node_name(node->name); if (flags & FTF_FULLPATH)
if (node->basenamelen < 0) { node->name = nodename_from_path(parent_flatname, flatname);
fprintf(stderr, "Warning \"%s\" has incorrect format\n", node->name); else
} node->name = flatname;
do { do {
struct property *prop; struct property *prop;
...@@ -795,8 +745,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, ...@@ -795,8 +745,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
break; break;
case FDT_BEGIN_NODE: case FDT_BEGIN_NODE:
child = unflatten_tree(dtbuf,strbuf, node->fullpath, child = unflatten_tree(dtbuf,strbuf, flatname, flags);
flags);
add_child(node, child); add_child(node, child);
break; break;
...@@ -825,10 +774,11 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, ...@@ -825,10 +774,11 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
} }
struct boot_info *dt_from_blob(FILE *f) struct boot_info *dt_from_blob(const char *fname)
{ {
u32 magic, totalsize, version, size_str, size_dt; struct dtc_file *dtcf;
u32 off_dt, off_str, off_mem_rsvmap; uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
uint32_t off_dt, off_str, off_mem_rsvmap;
int rc; int rc;
char *blob; char *blob;
struct fdt_header *fdt; struct fdt_header *fdt;
...@@ -838,54 +788,56 @@ struct boot_info *dt_from_blob(FILE *f) ...@@ -838,54 +788,56 @@ struct boot_info *dt_from_blob(FILE *f)
int sizeleft; int sizeleft;
struct reserve_info *reservelist; struct reserve_info *reservelist;
struct node *tree; struct node *tree;
u32 val; uint32_t val;
int flags = 0; int flags = 0;
rc = fread(&magic, sizeof(magic), 1, f); dtcf = dtc_open_file(fname, NULL);
if (ferror(f))
rc = fread(&magic, sizeof(magic), 1, dtcf->file);
if (ferror(dtcf->file))
die("Error reading DT blob magic number: %s\n", die("Error reading DT blob magic number: %s\n",
strerror(errno)); strerror(errno));
if (rc < 1) { if (rc < 1) {
if (feof(f)) if (feof(dtcf->file))
die("EOF reading DT blob magic number\n"); die("EOF reading DT blob magic number\n");
else else
die("Mysterious short read reading magic number\n"); die("Mysterious short read reading magic number\n");
} }
magic = be32_to_cpu(magic); magic = fdt32_to_cpu(magic);
if (magic != FDT_MAGIC) if (magic != FDT_MAGIC)
die("Blob has incorrect magic number\n"); die("Blob has incorrect magic number\n");
rc = fread(&totalsize, sizeof(totalsize), 1, f); rc = fread(&totalsize, sizeof(totalsize), 1, dtcf->file);
if (ferror(f)) if (ferror(dtcf->file))
die("Error reading DT blob size: %s\n", strerror(errno)); die("Error reading DT blob size: %s\n", strerror(errno));
if (rc < 1) { if (rc < 1) {
if (feof(f)) if (feof(dtcf->file))
die("EOF reading DT blob size\n"); die("EOF reading DT blob size\n");
else else
die("Mysterious short read reading blob size\n"); die("Mysterious short read reading blob size\n");
} }
totalsize = be32_to_cpu(totalsize); totalsize = fdt32_to_cpu(totalsize);
if (totalsize < FDT_V1_SIZE) if (totalsize < FDT_V1_SIZE)
die("DT blob size (%d) is too small\n", totalsize); die("DT blob size (%d) is too small\n", totalsize);
blob = xmalloc(totalsize); blob = xmalloc(totalsize);
fdt = (struct fdt_header *)blob; fdt = (struct fdt_header *)blob;
fdt->magic = cpu_to_be32(magic); fdt->magic = cpu_to_fdt32(magic);
fdt->totalsize = cpu_to_be32(totalsize); fdt->totalsize = cpu_to_fdt32(totalsize);
sizeleft = totalsize - sizeof(magic) - sizeof(totalsize); sizeleft = totalsize - sizeof(magic) - sizeof(totalsize);
p = blob + sizeof(magic) + sizeof(totalsize); p = blob + sizeof(magic) + sizeof(totalsize);
while (sizeleft) { while (sizeleft) {
if (feof(f)) if (feof(dtcf->file))
die("EOF before reading %d bytes of DT blob\n", die("EOF before reading %d bytes of DT blob\n",
totalsize); totalsize);
rc = fread(p, 1, sizeleft, f); rc = fread(p, 1, sizeleft, dtcf->file);
if (ferror(f)) if (ferror(dtcf->file))
die("Error reading DT blob: %s\n", die("Error reading DT blob: %s\n",
strerror(errno)); strerror(errno));
...@@ -893,19 +845,11 @@ struct boot_info *dt_from_blob(FILE *f) ...@@ -893,19 +845,11 @@ struct boot_info *dt_from_blob(FILE *f)
p += rc; p += rc;
} }
off_dt = be32_to_cpu(fdt->off_dt_struct); off_dt = fdt32_to_cpu(fdt->off_dt_struct);
off_str = be32_to_cpu(fdt->off_dt_strings); off_str = fdt32_to_cpu(fdt->off_dt_strings);
off_mem_rsvmap = be32_to_cpu(fdt->off_mem_rsvmap); off_mem_rsvmap = fdt32_to_cpu(fdt->off_mem_rsvmap);
version = be32_to_cpu(fdt->version); version = fdt32_to_cpu(fdt->version);
boot_cpuid_phys = fdt32_to_cpu(fdt->boot_cpuid_phys);
fprintf(stderr, "\tmagic:\t\t\t0x%x\n", magic);
fprintf(stderr, "\ttotalsize:\t\t%d\n", totalsize);
fprintf(stderr, "\toff_dt_struct:\t\t0x%x\n", off_dt);
fprintf(stderr, "\toff_dt_strings:\t\t0x%x\n", off_str);
fprintf(stderr, "\toff_mem_rsvmap:\t\t0x%x\n", off_mem_rsvmap);
fprintf(stderr, "\tversion:\t\t0x%x\n", version );
fprintf(stderr, "\tlast_comp_version:\t0x%x\n",
be32_to_cpu(fdt->last_comp_version));
if (off_mem_rsvmap >= totalsize) if (off_mem_rsvmap >= totalsize)
die("Mem Reserve structure offset exceeds total size\n"); die("Mem Reserve structure offset exceeds total size\n");
...@@ -916,21 +860,17 @@ struct boot_info *dt_from_blob(FILE *f) ...@@ -916,21 +860,17 @@ struct boot_info *dt_from_blob(FILE *f)
if (off_str > totalsize) if (off_str > totalsize)
die("String table offset exceeds total size\n"); die("String table offset exceeds total size\n");
if (version >= 2)
fprintf(stderr, "\tboot_cpuid_phys:\t0x%x\n",
be32_to_cpu(fdt->boot_cpuid_phys));
size_str = -1;
if (version >= 3) { if (version >= 3) {
size_str = be32_to_cpu(fdt->size_dt_strings); uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings);
fprintf(stderr, "\tsize_dt_strings:\t%d\n", size_str);
if (off_str+size_str > totalsize) if (off_str+size_str > totalsize)
die("String table extends past total size\n"); die("String table extends past total size\n");
inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
} else {
inbuf_init(&strbuf, blob + off_str, blob + totalsize);
} }
if (version >= 17) { if (version >= 17) {
size_dt = be32_to_cpu(fdt->size_dt_struct); size_dt = fdt32_to_cpu(fdt->size_dt_struct);
fprintf(stderr, "\tsize_dt_struct:\t\t%d\n", size_dt);
if (off_dt+size_dt > totalsize) if (off_dt+size_dt > totalsize)
die("Structure block extends past total size\n"); die("Structure block extends past total size\n");
} }
...@@ -944,10 +884,6 @@ struct boot_info *dt_from_blob(FILE *f) ...@@ -944,10 +884,6 @@ struct boot_info *dt_from_blob(FILE *f)
inbuf_init(&memresvbuf, inbuf_init(&memresvbuf,
blob + off_mem_rsvmap, blob + totalsize); blob + off_mem_rsvmap, blob + totalsize);
inbuf_init(&dtbuf, blob + off_dt, blob + totalsize); inbuf_init(&dtbuf, blob + off_dt, blob + totalsize);
if (size_str >= 0)
inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
else
inbuf_init(&strbuf, blob + off_str, blob + totalsize);
reservelist = flat_read_mem_reserve(&memresvbuf); reservelist = flat_read_mem_reserve(&memresvbuf);
...@@ -964,5 +900,7 @@ struct boot_info *dt_from_blob(FILE *f) ...@@ -964,5 +900,7 @@ struct boot_info *dt_from_blob(FILE *f)
free(blob); free(blob);
return build_boot_info(reservelist, tree); dtc_close_file(dtcf);
return build_boot_info(reservelist, tree, boot_cpuid_phys);
} }
...@@ -31,8 +31,8 @@ static struct node *read_fstree(const char *dirname) ...@@ -31,8 +31,8 @@ static struct node *read_fstree(const char *dirname)
struct node *tree; struct node *tree;
d = opendir(dirname); d = opendir(dirname);
if (! d) if (!d)
die("opendir(): %s\n", strerror(errno)); die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno));
tree = build_node(NULL, NULL); tree = build_node(NULL, NULL);
...@@ -87,8 +87,6 @@ struct boot_info *dt_from_fs(const char *dirname) ...@@ -87,8 +87,6 @@ struct boot_info *dt_from_fs(const char *dirname)
tree = read_fstree(dirname); tree = read_fstree(dirname);
tree = name_node(tree, "", NULL); tree = name_node(tree, "", NULL);
fill_fullpaths(tree, ""); return build_boot_info(NULL, tree, 0);
return build_boot_info(NULL, tree);
} }
#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) ...@@ -115,6 +115,7 @@ void add_child(struct node *parent, struct node *child)
struct node **p; struct node **p;
child->next_sibling = NULL; child->next_sibling = NULL;
child->parent = parent;
p = &parent->children; p = &parent->children;
while (*p) while (*p)
...@@ -123,7 +124,8 @@ void add_child(struct node *parent, struct node *child) ...@@ -123,7 +124,8 @@ void add_child(struct node *parent, struct node *child)
*p = 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)); struct reserve_info *new = xmalloc(sizeof(*new));
...@@ -165,13 +167,14 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list, ...@@ -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 boot_info *build_boot_info(struct reserve_info *reservelist,
struct node *tree) struct node *tree, uint32_t boot_cpuid_phys)
{ {
struct boot_info *bi; struct boot_info *bi;
bi = xmalloc(sizeof(*bi)); bi = xmalloc(sizeof(*bi));
bi->reservelist = reservelist; bi->reservelist = reservelist;
bi->dt = tree; bi->dt = tree;
bi->boot_cpuid_phys = boot_cpuid_phys;
return bi; return bi;
} }
...@@ -202,7 +205,7 @@ struct property *get_property(struct node *node, const char *propname) ...@@ -202,7 +205,7 @@ struct property *get_property(struct node *node, const char *propname)
cell_t propval_cell(struct property *prop) cell_t propval_cell(struct property *prop)
{ {
assert(prop->val.len == sizeof(cell_t)); 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) struct node *get_subnode(struct node *node, const char *nodename)
......
...@@ -20,86 +20,97 @@ ...@@ -20,86 +20,97 @@
#include "dtc.h" #include "dtc.h"
#include "srcpos.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. * Like yylineno, this is the current open file pos.
*/ */
int srcpos_filenum = -1; struct dtc_file *srcpos_file;
static int dtc_open_one(struct dtc_file *file,
FILE *dtc_open_file(const char *fname) const char *search,
const char *fname)
{ {
FILE *f; char *fullname;
if (lookup_file_name(fname, 1) < 0) if (search) {
die("Too many files opened\n"); fullname = xmalloc(strlen(search) + strlen(fname) + 2);
if (streq(fname, "-")) strcpy(fullname, search);
f = stdin; strcat(fullname, "/");
else strcat(fullname, fname);
f = fopen(fname, "r"); } else {
fullname = strdup(fname);
}
if (! f) file->file = fopen(fullname, "r");
die("Couldn't open \"%s\": %s\n", fname, strerror(errno)); 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 };
/* struct dtc_file *file;
* Locate and optionally add filename fname in the file_names[] array. const char *slash;
*
* 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
*/
int lookup_file_name(const char *fname, int add_it) file = xmalloc(sizeof(struct dtc_file));
{
int i;
for (i = 0; i < n_file_names; i++) { slash = strrchr(fname, '/');
if (strcmp(file_names[i], fname) == 0) if (slash) {
return i; char *dir = xmalloc(slash - fname + 1);
memcpy(dir, fname, slash - fname);
dir[slash - fname] = 0;
file->dir = dir;
} else {
file->dir = NULL;
} }
if (add_it) { if (streq(fname, "-")) {
if (n_file_names < MAX_N_FILE_NAMES) { file->name = "stdin";
file_names[n_file_names] = strdup(fname); file->file = stdin;
return n_file_names++; return file;
}
} }
return -1; if (fname[0] == '/') {
} file->file = fopen(fname, "r");
if (!file->file)
goto fail;
file->name = strdup(fname);
return file;
}
if (!search)
search = &default_search;
const char *srcpos_filename_for_num(int filenum) while (search) {
{ if (dtc_open_one(file, search->dir, fname))
if (0 <= filenum && filenum < n_file_names) { return file;
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));
} }
void dtc_close_file(struct dtc_file *file)
const char *srcpos_get_filename(void)
{ {
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 @@ ...@@ -22,13 +22,21 @@
* array of all opened filenames. * 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) #if ! defined(YYLTYPE) && ! defined(YYLTYPE_IS_DECLARED)
typedef struct YYLTYPE { typedef struct YYLTYPE {
int first_line; int first_line;
int first_column; int first_column;
int last_line; int last_line;
int last_column; int last_column;
int filenum; struct dtc_file *file;
} YYLTYPE; } YYLTYPE;
#define YYLTYPE_IS_DECLARED 1 #define YYLTYPE_IS_DECLARED 1
...@@ -48,7 +56,7 @@ typedef struct YYLTYPE { ...@@ -48,7 +56,7 @@ typedef struct YYLTYPE {
(Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
(Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
(Current).last_column = YYRHSLOC (Rhs, N).last_column; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
(Current).filenum = YYRHSLOC (Rhs, N).filenum; \ (Current).file = YYRHSLOC (Rhs, N).file; \
} \ } \
else \ else \
{ \ { \
...@@ -56,20 +64,22 @@ typedef struct YYLTYPE { ...@@ -56,20 +64,22 @@ typedef struct YYLTYPE {
YYRHSLOC (Rhs, 0).last_line; \ YYRHSLOC (Rhs, 0).last_line; \
(Current).first_column = (Current).last_column = \ (Current).first_column = (Current).last_column = \
YYRHSLOC (Rhs, 0).last_column; \ YYRHSLOC (Rhs, 0).last_column; \
(Current).filenum = YYRHSLOC (Rhs, 0).filenum; \ (Current).file = YYRHSLOC (Rhs, 0).file; \
} \ } \
while (YYID (0)) while (YYID (0))
extern void yyerror(char const *); 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); struct search_path {
extern int pop_input_file(void); const char *dir; /* NULL for current directory */
struct search_path *prev, *next;
};
extern FILE *dtc_open_file(const char *fname); extern struct dtc_file *dtc_open_file(const char *fname,
extern int lookup_file_name(const char *fname, int add_it); const struct search_path *search);
extern const char *srcpos_filename_for_num(int filenum); extern void dtc_close_file(struct dtc_file *file);
const char *srcpos_get_filename(void);
...@@ -23,20 +23,23 @@ ...@@ -23,20 +23,23 @@
extern FILE *yyin; extern FILE *yyin;
extern int yyparse(void); extern int yyparse(void);
extern void yyerror(char const *);
struct boot_info *the_boot_info; struct boot_info *the_boot_info;
int treesource_error;
struct boot_info *dt_from_source(const char *fname) struct boot_info *dt_from_source(const char *fname)
{ {
the_boot_info = NULL; 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) 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; return the_boot_info;
} }
...@@ -144,7 +147,7 @@ static void write_propval_cells(FILE *f, struct data val) ...@@ -144,7 +147,7 @@ static void write_propval_cells(FILE *f, struct data val)
m = m->next; m = m->next;
} }
fprintf(f, "0x%x", be32_to_cpu(*cp++)); fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
if ((void *)cp >= propend) if ((void *)cp >= propend)
break; break;
fprintf(f, " "); fprintf(f, " ");
...@@ -173,7 +176,7 @@ static void write_propval_bytes(FILE *f, struct data val) ...@@ -173,7 +176,7 @@ static void write_propval_bytes(FILE *f, struct data val)
} }
fprintf(f, "%02hhx", *bp++); fprintf(f, "%02hhx", *bp++);
if ((void *)bp >= propend) if ((const void *)bp >= propend)
break; break;
fprintf(f, " "); fprintf(f, " ");
} }
......
#define DTC_VERSION "DTC 1.0.0-gd6f9b62f" #define DTC_VERSION "DTC 1.2.0"
...@@ -3,12 +3,6 @@ ...@@ -3,12 +3,6 @@
# This is not a complete Makefile of itself. Instead, it is designed to # This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles. # 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_INCLUDES = fdt.h libfdt.h
LIBFDT_EXTRA = libfdt_internal.h LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
LIBFDT_LIB = libfdt/libfdt.a
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) 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) ...@@ -63,7 +63,7 @@ int fdt_check_header(const void *fdt)
return -FDT_ERR_BADVERSION; return -FDT_ERR_BADVERSION;
if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
return -FDT_ERR_BADVERSION; return -FDT_ERR_BADVERSION;
} else if (fdt_magic(fdt) == SW_MAGIC) { } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
/* Unfinished sequential-write blob */ /* Unfinished sequential-write blob */
if (fdt_size_dt_struct(fdt) == 0) if (fdt_size_dt_struct(fdt) == 0)
return -FDT_ERR_BADSTATE; return -FDT_ERR_BADSTATE;
...@@ -76,7 +76,7 @@ int fdt_check_header(const void *fdt) ...@@ -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 *fdt_offset_ptr(const void *fdt, int offset, int len)
{ {
const void *p; const char *p;
if (fdt_version(fdt) >= 0x11) if (fdt_version(fdt) >= 0x11)
if (((offset + len) < offset) if (((offset + len) < offset)
...@@ -124,11 +124,59 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset) ...@@ -124,11 +124,59 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
} }
if (nextoffset) if (nextoffset)
*nextoffset = ALIGN(offset, FDT_TAGSIZE); *nextoffset = FDT_TAGALIGN(offset);
return tag; 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) const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
{ {
int len = strlen(s) + 1; int len = strlen(s) + 1;
...@@ -136,17 +184,14 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) ...@@ -136,17 +184,14 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
const char *p; const char *p;
for (p = strtab; p <= last; p++) for (p = strtab; p <= last; p++)
if (memeq(p, s, len)) if (memcmp(p, s, len) == 0)
return p; return p;
return NULL; return NULL;
} }
int fdt_move(const void *fdt, void *buf, int bufsize) int fdt_move(const void *fdt, void *buf, int bufsize)
{ {
int err = fdt_check_header(fdt); FDT_CHECK_HEADER(fdt);
if (err)
return err;
if (fdt_totalsize(fdt) > bufsize) if (fdt_totalsize(fdt) > bufsize)
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
......
...@@ -55,17 +55,10 @@ ...@@ -55,17 +55,10 @@
#include "libfdt_internal.h" #include "libfdt_internal.h"
#define CHECK_HEADER(fdt) \ static int _fdt_nodename_eq(const void *fdt, int offset,
{ \ const char *s, int len)
int err; \
if ((err = fdt_check_header(fdt)) != 0) \
return err; \
}
static int nodename_eq(const void *fdt, int offset,
const char *s, int len)
{ {
const char *p = fdt_offset_ptr(fdt, offset, len+1); const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
if (! p) if (! p)
/* short match */ /* short match */
...@@ -84,12 +77,12 @@ static int nodename_eq(const void *fdt, int offset, ...@@ -84,12 +77,12 @@ static int nodename_eq(const void *fdt, int offset,
const char *fdt_string(const void *fdt, int stroffset) const char *fdt_string(const void *fdt, int stroffset)
{ {
return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset; return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
} }
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{ {
CHECK_HEADER(fdt); FDT_CHECK_HEADER(fdt);
*address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
*size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
return 0; return 0;
...@@ -104,50 +97,24 @@ int fdt_num_mem_rsv(const void *fdt) ...@@ -104,50 +97,24 @@ int fdt_num_mem_rsv(const void *fdt)
return i; return i;
} }
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, int fdt_subnode_offset_namelen(const void *fdt, int offset,
const char *name, int namelen) const char *name, int namelen)
{ {
int level = 0; int depth;
uint32_t tag;
int offset, nextoffset;
CHECK_HEADER(fdt);
tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
if (tag != FDT_BEGIN_NODE)
return -FDT_ERR_BADOFFSET;
do {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);
switch (tag) {
case FDT_END:
return -FDT_ERR_TRUNCATED;
case FDT_BEGIN_NODE:
level++;
if (level != 1)
continue;
if (nodename_eq(fdt, offset+FDT_TAGSIZE, name, namelen))
/* Found it! */
return offset;
break;
case FDT_END_NODE:
level--;
break;
case FDT_PROP: FDT_CHECK_HEADER(fdt);
case FDT_NOP:
break;
default: for (depth = 0;
return -FDT_ERR_BADSTRUCTURE; offset >= 0;
} offset = fdt_next_node(fdt, offset, &depth)) {
} while (level >= 0); if (depth < 0)
return -FDT_ERR_NOTFOUND;
else if ((depth == 1)
&& _fdt_nodename_eq(fdt, offset, name, namelen))
return offset;
}
return -FDT_ERR_NOTFOUND; return offset; /* error */
} }
int fdt_subnode_offset(const void *fdt, int parentoffset, int fdt_subnode_offset(const void *fdt, int parentoffset,
...@@ -162,7 +129,7 @@ int fdt_path_offset(const void *fdt, const char *path) ...@@ -162,7 +129,7 @@ int fdt_path_offset(const void *fdt, const char *path)
const char *p = path; const char *p = path;
int offset = 0; int offset = 0;
CHECK_HEADER(fdt); FDT_CHECK_HEADER(fdt);
if (*path != '/') if (*path != '/')
return -FDT_ERR_BADPATH; return -FDT_ERR_BADPATH;
...@@ -190,16 +157,12 @@ int fdt_path_offset(const void *fdt, const char *path) ...@@ -190,16 +157,12 @@ int fdt_path_offset(const void *fdt, const char *path)
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
{ {
const struct fdt_node_header *nh; const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
int err; int err;
if ((err = fdt_check_header(fdt)) != 0) if (((err = fdt_check_header(fdt)) != 0)
goto fail; || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
goto fail;
err = -FDT_ERR_BADOFFSET;
nh = fdt_offset_ptr(fdt, nodeoffset, sizeof(*nh));
if (!nh || (fdt32_to_cpu(nh->tag) != FDT_BEGIN_NODE))
goto fail;
if (len) if (len)
*len = strlen(nh->name); *len = strlen(nh->name);
...@@ -222,17 +185,11 @@ const struct fdt_property *fdt_get_property(const void *fdt, ...@@ -222,17 +185,11 @@ const struct fdt_property *fdt_get_property(const void *fdt,
int offset, nextoffset; int offset, nextoffset;
int err; int err;
if ((err = fdt_check_header(fdt)) != 0) if (((err = fdt_check_header(fdt)) != 0)
goto fail; || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
goto fail;
err = -FDT_ERR_BADOFFSET;
if (nodeoffset % FDT_TAGSIZE)
goto fail;
tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
if (tag != FDT_BEGIN_NODE)
goto fail;
nextoffset = err;
do { do {
offset = nextoffset; offset = nextoffset;
...@@ -253,7 +210,7 @@ const struct fdt_property *fdt_get_property(const void *fdt, ...@@ -253,7 +210,7 @@ const struct fdt_property *fdt_get_property(const void *fdt,
if (! prop) if (! prop)
goto fail; goto fail;
namestroff = fdt32_to_cpu(prop->nameoff); namestroff = fdt32_to_cpu(prop->nameoff);
if (streq(fdt_string(fdt, namestroff), name)) { if (strcmp(fdt_string(fdt, namestroff), name) == 0) {
/* Found it! */ /* Found it! */
int len = fdt32_to_cpu(prop->len); int len = fdt32_to_cpu(prop->len);
prop = fdt_offset_ptr(fdt, offset, prop = fdt_offset_ptr(fdt, offset,
...@@ -307,115 +264,91 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) ...@@ -307,115 +264,91 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
{ {
uint32_t tag; int pdepth = 0, p = 0;
int p = 0, overflow = 0; int offset, depth, namelen;
int offset, nextoffset, namelen;
const char *name; const char *name;
CHECK_HEADER(fdt); FDT_CHECK_HEADER(fdt);
tag = fdt_next_tag(fdt, 0, &nextoffset);
if (tag != FDT_BEGIN_NODE)
return -FDT_ERR_BADSTRUCTURE;
if (buflen < 2) if (buflen < 2)
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
buf[0] = '/';
p = 1;
while (nextoffset <= nodeoffset) { for (offset = 0, depth = 0;
offset = nextoffset; (offset >= 0) && (offset <= nodeoffset);
tag = fdt_next_tag(fdt, offset, &nextoffset); offset = fdt_next_node(fdt, offset, &depth)) {
switch (tag) { if (pdepth < depth)
case FDT_END: continue; /* overflowed buffer */
return -FDT_ERR_BADOFFSET;
case FDT_BEGIN_NODE: while (pdepth > depth) {
name = fdt_get_name(fdt, offset, &namelen); do {
if (!name) p--;
return namelen; } while (buf[p-1] != '/');
if (overflow || ((p + namelen + 1) > buflen)) { pdepth--;
overflow++; }
break;
} name = fdt_get_name(fdt, offset, &namelen);
if (!name)
return namelen;
if ((p + namelen + 1) <= buflen) {
memcpy(buf + p, name, namelen); memcpy(buf + p, name, namelen);
p += namelen; p += namelen;
buf[p++] = '/'; buf[p++] = '/';
break; pdepth++;
}
case FDT_END_NODE:
if (overflow) {
overflow--;
break;
}
do {
p--;
} while (buf[p-1] != '/');
break;
case FDT_PROP: if (offset == nodeoffset) {
case FDT_NOP: if (pdepth < (depth + 1))
break; return -FDT_ERR_NOSPACE;
default: if (p > 1) /* special case so that root path is "/", not "" */
return -FDT_ERR_BADSTRUCTURE; p--;
buf[p] = '\0';
return p;
} }
} }
if (overflow) if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
return -FDT_ERR_NOSPACE; return -FDT_ERR_BADOFFSET;
else if (offset == -FDT_ERR_BADOFFSET)
return -FDT_ERR_BADSTRUCTURE;
if (p > 1) /* special case so that root path is "/", not "" */ return offset; /* error from fdt_next_node() */
p--;
buf[p] = '\0';
return p;
} }
int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
int supernodedepth, int *nodedepth) int supernodedepth, int *nodedepth)
{ {
int level = -1; int offset, depth;
uint32_t tag;
int offset, nextoffset = 0;
int supernodeoffset = -FDT_ERR_INTERNAL; int supernodeoffset = -FDT_ERR_INTERNAL;
CHECK_HEADER(fdt); FDT_CHECK_HEADER(fdt);
if (supernodedepth < 0) if (supernodedepth < 0)
return -FDT_ERR_NOTFOUND; return -FDT_ERR_NOTFOUND;
do { for (offset = 0, depth = 0;
offset = nextoffset; (offset >= 0) && (offset <= nodeoffset);
tag = fdt_next_tag(fdt, offset, &nextoffset); offset = fdt_next_node(fdt, offset, &depth)) {
switch (tag) { if (depth == supernodedepth)
case FDT_END: supernodeoffset = offset;
return -FDT_ERR_BADOFFSET;
case FDT_BEGIN_NODE:
level++;
if (level == supernodedepth)
supernodeoffset = offset;
break;
case FDT_END_NODE:
level--;
break;
case FDT_PROP: if (offset == nodeoffset) {
case FDT_NOP: if (nodedepth)
break; *nodedepth = depth;
default: if (supernodedepth > depth)
return -FDT_ERR_BADSTRUCTURE; return -FDT_ERR_NOTFOUND;
else
return supernodeoffset;
} }
} while (offset < nodeoffset); }
if (nodedepth) if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
*nodedepth = level; return -FDT_ERR_BADOFFSET;
else if (offset == -FDT_ERR_BADOFFSET)
return -FDT_ERR_BADSTRUCTURE;
if (supernodedepth > level) return offset; /* error from fdt_next_node() */
return -FDT_ERR_NOTFOUND;
return supernodeoffset;
} }
int fdt_node_depth(const void *fdt, int nodeoffset) int fdt_node_depth(const void *fdt, int nodeoffset)
...@@ -443,51 +376,27 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, ...@@ -443,51 +376,27 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
const char *propname, const char *propname,
const void *propval, int proplen) const void *propval, int proplen)
{ {
uint32_t tag; int offset;
int offset, nextoffset;
const void *val; const void *val;
int len; int len;
CHECK_HEADER(fdt); FDT_CHECK_HEADER(fdt);
if (startoffset >= 0) {
tag = fdt_next_tag(fdt, startoffset, &nextoffset);
if (tag != FDT_BEGIN_NODE)
return -FDT_ERR_BADOFFSET;
} else {
nextoffset = 0;
}
/* FIXME: The algorithm here is pretty horrible: we scan each /* FIXME: The algorithm here is pretty horrible: we scan each
* property of a node in fdt_getprop(), then if that didn't * property of a node in fdt_getprop(), then if that didn't
* find what we want, we scan over them again making our way * find what we want, we scan over them again making our way
* to the next node. Still it's the easiest to implement * to the next node. Still it's the easiest to implement
* approach; performance can come later. */ * approach; performance can come later. */
do { for (offset = fdt_next_node(fdt, startoffset, NULL);
offset = nextoffset; offset >= 0;
tag = fdt_next_tag(fdt, offset, &nextoffset); offset = fdt_next_node(fdt, offset, NULL)) {
val = fdt_getprop(fdt, offset, propname, &len);
switch (tag) { if (val && (len == proplen)
case FDT_BEGIN_NODE: && (memcmp(val, propval, len) == 0))
val = fdt_getprop(fdt, offset, propname, &len); return offset;
if (val }
&& (len == proplen)
&& (memcmp(val, propval, len) == 0))
return offset;
break;
case FDT_PROP:
case FDT_END:
case FDT_END_NODE:
case FDT_NOP:
break;
default:
return -FDT_ERR_BADSTRUCTURE;
}
} while (tag != FDT_END);
return -FDT_ERR_NOTFOUND; return offset; /* error from fdt_next_node() */
} }
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
...@@ -499,10 +408,10 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) ...@@ -499,10 +408,10 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
&phandle, sizeof(phandle)); &phandle, sizeof(phandle));
} }
int _stringlist_contains(const void *strlist, int listlen, const char *str) int _stringlist_contains(const char *strlist, int listlen, const char *str)
{ {
int len = strlen(str); int len = strlen(str);
const void *p; const char *p;
while (listlen >= len) { while (listlen >= len) {
if (memcmp(str, strlist, len+1) == 0) if (memcmp(str, strlist, len+1) == 0)
...@@ -534,50 +443,24 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, ...@@ -534,50 +443,24 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
int fdt_node_offset_by_compatible(const void *fdt, int startoffset, int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
const char *compatible) const char *compatible)
{ {
uint32_t tag; int offset, err;
int offset, nextoffset;
int err;
CHECK_HEADER(fdt);
if (startoffset >= 0) { FDT_CHECK_HEADER(fdt);
tag = fdt_next_tag(fdt, startoffset, &nextoffset);
if (tag != FDT_BEGIN_NODE)
return -FDT_ERR_BADOFFSET;
} else {
nextoffset = 0;
}
/* FIXME: The algorithm here is pretty horrible: we scan each /* FIXME: The algorithm here is pretty horrible: we scan each
* property of a node in fdt_node_check_compatible(), then if * property of a node in fdt_node_check_compatible(), then if
* that didn't find what we want, we scan over them again * that didn't find what we want, we scan over them again
* making our way to the next node. Still it's the easiest to * making our way to the next node. Still it's the easiest to
* implement approach; performance can come later. */ * implement approach; performance can come later. */
do { for (offset = fdt_next_node(fdt, startoffset, NULL);
offset = nextoffset; offset >= 0;
tag = fdt_next_tag(fdt, offset, &nextoffset); offset = fdt_next_node(fdt, offset, NULL)) {
err = fdt_node_check_compatible(fdt, offset, compatible);
switch (tag) { if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
case FDT_BEGIN_NODE: return err;
err = fdt_node_check_compatible(fdt, offset, else if (err == 0)
compatible); return offset;
if ((err < 0) }
&& (err != -FDT_ERR_NOTFOUND))
return err;
else if (err == 0)
return offset;
break;
case FDT_PROP:
case FDT_END:
case FDT_END_NODE:
case FDT_NOP:
break;
default:
return -FDT_ERR_BADSTRUCTURE;
}
} while (tag != FDT_END);
return -FDT_ERR_NOTFOUND; return offset; /* error from fdt_next_node() */
} }
...@@ -55,10 +55,10 @@ ...@@ -55,10 +55,10 @@
#include "libfdt_internal.h" #include "libfdt_internal.h"
static int _blocks_misordered(const void *fdt, static int _fdt_blocks_misordered(const void *fdt,
int mem_rsv_size, int struct_size) int mem_rsv_size, int struct_size)
{ {
return (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8)) return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
|| (fdt_off_dt_struct(fdt) < || (fdt_off_dt_struct(fdt) <
(fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
|| (fdt_off_dt_strings(fdt) < || (fdt_off_dt_strings(fdt) <
...@@ -67,16 +67,14 @@ static int _blocks_misordered(const void *fdt, ...@@ -67,16 +67,14 @@ static int _blocks_misordered(const void *fdt,
(fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
} }
static int rw_check_header(void *fdt) static int _fdt_rw_check_header(void *fdt)
{ {
int err; FDT_CHECK_HEADER(fdt);
if ((err = fdt_check_header(fdt)))
return err;
if (fdt_version(fdt) < 17) if (fdt_version(fdt) < 17)
return -FDT_ERR_BADVERSION; return -FDT_ERR_BADVERSION;
if (_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
fdt_size_dt_struct(fdt))) fdt_size_dt_struct(fdt)))
return -FDT_ERR_BADLAYOUT; return -FDT_ERR_BADLAYOUT;
if (fdt_version(fdt) > 17) if (fdt_version(fdt) > 17)
fdt_set_version(fdt, 17); fdt_set_version(fdt, 17);
...@@ -84,36 +82,37 @@ static int rw_check_header(void *fdt) ...@@ -84,36 +82,37 @@ static int rw_check_header(void *fdt)
return 0; return 0;
} }
#define RW_CHECK_HEADER(fdt) \ #define FDT_RW_CHECK_HEADER(fdt) \
{ \ { \
int err; \ int err; \
if ((err = rw_check_header(fdt)) != 0) \ if ((err = _fdt_rw_check_header(fdt)) != 0) \
return err; \ return err; \
} }
static inline int _blob_data_size(void *fdt) static inline int _fdt_data_size(void *fdt)
{ {
return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
} }
static int _blob_splice(void *fdt, void *p, int oldlen, int newlen) static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
{ {
void *end = fdt + _blob_data_size(fdt); char *p = splicepoint;
char *end = (char *)fdt + _fdt_data_size(fdt);
if (((p + oldlen) < p) || ((p + oldlen) > end)) if (((p + oldlen) < p) || ((p + oldlen) > end))
return -FDT_ERR_BADOFFSET; return -FDT_ERR_BADOFFSET;
if ((end - oldlen + newlen) > (fdt + fdt_totalsize(fdt))) if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
memmove(p + newlen, p + oldlen, end - p - oldlen); memmove(p + newlen, p + oldlen, end - p - oldlen);
return 0; return 0;
} }
static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
int oldn, int newn) int oldn, int newn)
{ {
int delta = (newn - oldn) * sizeof(*p); int delta = (newn - oldn) * sizeof(*p);
int err; int err;
err = _blob_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
if (err) if (err)
return err; return err;
fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
...@@ -121,13 +120,13 @@ static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, ...@@ -121,13 +120,13 @@ static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
return 0; return 0;
} }
static int _blob_splice_struct(void *fdt, void *p, static int _fdt_splice_struct(void *fdt, void *p,
int oldlen, int newlen) int oldlen, int newlen)
{ {
int delta = newlen - oldlen; int delta = newlen - oldlen;
int err; int err;
if ((err = _blob_splice(fdt, p, oldlen, newlen))) if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
return err; return err;
fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
...@@ -135,19 +134,20 @@ static int _blob_splice_struct(void *fdt, void *p, ...@@ -135,19 +134,20 @@ static int _blob_splice_struct(void *fdt, void *p,
return 0; return 0;
} }
static int _blob_splice_string(void *fdt, int newlen) static int _fdt_splice_string(void *fdt, int newlen)
{ {
void *p = fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); void *p = (char *)fdt
+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
int err; int err;
if ((err = _blob_splice(fdt, p, 0, newlen))) if ((err = _fdt_splice(fdt, p, 0, newlen)))
return err; return err;
fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
return 0; 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_off_dt_strings(fdt); char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
const char *p; const char *p;
...@@ -161,7 +161,7 @@ static int _find_add_string(void *fdt, const char *s) ...@@ -161,7 +161,7 @@ static int _find_add_string(void *fdt, const char *s)
return (p - strtab); return (p - strtab);
new = strtab + fdt_size_dt_strings(fdt); new = strtab + fdt_size_dt_strings(fdt);
err = _blob_splice_string(fdt, len); err = _fdt_splice_string(fdt, len);
if (err) if (err)
return err; return err;
...@@ -174,11 +174,10 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) ...@@ -174,11 +174,10 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
struct fdt_reserve_entry *re; struct fdt_reserve_entry *re;
int err; int err;
if ((err = rw_check_header(fdt))) FDT_RW_CHECK_HEADER(fdt);
return err;
re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
err = _blob_splice_mem_rsv(fdt, re, 0, 1); err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
if (err) if (err)
return err; return err;
...@@ -192,19 +191,19 @@ int fdt_del_mem_rsv(void *fdt, int n) ...@@ -192,19 +191,19 @@ int fdt_del_mem_rsv(void *fdt, int n)
struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
int err; int err;
if ((err = rw_check_header(fdt))) FDT_RW_CHECK_HEADER(fdt);
return err;
if (n >= fdt_num_mem_rsv(fdt)) if (n >= fdt_num_mem_rsv(fdt))
return -FDT_ERR_NOTFOUND; return -FDT_ERR_NOTFOUND;
err = _blob_splice_mem_rsv(fdt, re, 1, 0); err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
if (err) if (err)
return err; return err;
return 0; return 0;
} }
static int _resize_property(void *fdt, int nodeoffset, const char *name, int len, static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
struct fdt_property **prop) int len, struct fdt_property **prop)
{ {
int oldlen; int oldlen;
int err; int err;
...@@ -213,36 +212,33 @@ static int _resize_property(void *fdt, int nodeoffset, const char *name, int len ...@@ -213,36 +212,33 @@ static int _resize_property(void *fdt, int nodeoffset, const char *name, int len
if (! (*prop)) if (! (*prop))
return oldlen; return oldlen;
if ((err = _blob_splice_struct(fdt, (*prop)->data, if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
ALIGN(oldlen, FDT_TAGSIZE), FDT_TAGALIGN(len))))
ALIGN(len, FDT_TAGSIZE))))
return err; return err;
(*prop)->len = cpu_to_fdt32(len); (*prop)->len = cpu_to_fdt32(len);
return 0; return 0;
} }
static int _add_property(void *fdt, int nodeoffset, const char *name, int len, static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
struct fdt_property **prop) int len, struct fdt_property **prop)
{ {
uint32_t tag;
int proplen; int proplen;
int nextoffset; int nextoffset;
int namestroff; int namestroff;
int err; int err;
tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
if (tag != FDT_BEGIN_NODE) return nextoffset;
return -FDT_ERR_BADOFFSET;
namestroff = _find_add_string(fdt, name); namestroff = _fdt_find_add_string(fdt, name);
if (namestroff < 0) if (namestroff < 0)
return namestroff; return namestroff;
*prop = _fdt_offset_ptr_w(fdt, nextoffset); *prop = _fdt_offset_ptr_w(fdt, nextoffset);
proplen = sizeof(**prop) + ALIGN(len, FDT_TAGSIZE); proplen = sizeof(**prop) + FDT_TAGALIGN(len);
err = _blob_splice_struct(fdt, *prop, 0, proplen); err = _fdt_splice_struct(fdt, *prop, 0, proplen);
if (err) if (err)
return err; return err;
...@@ -252,18 +248,40 @@ static int _add_property(void *fdt, int nodeoffset, const char *name, int len, ...@@ -252,18 +248,40 @@ static int _add_property(void *fdt, int nodeoffset, const char *name, int len,
return 0; return 0;
} }
int fdt_set_name(void *fdt, int nodeoffset, const char *name)
{
char *namep;
int oldlen, newlen;
int err;
FDT_RW_CHECK_HEADER(fdt);
namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
if (!namep)
return oldlen;
newlen = strlen(name);
err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
FDT_TAGALIGN(newlen+1));
if (err)
return err;
memcpy(namep, name, newlen+1);
return 0;
}
int fdt_setprop(void *fdt, int nodeoffset, const char *name, int fdt_setprop(void *fdt, int nodeoffset, const char *name,
const void *val, int len) const void *val, int len)
{ {
struct fdt_property *prop; struct fdt_property *prop;
int err; int err;
if ((err = rw_check_header(fdt))) FDT_RW_CHECK_HEADER(fdt);
return err;
err = _resize_property(fdt, nodeoffset, name, len, &prop); err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
if (err == -FDT_ERR_NOTFOUND) if (err == -FDT_ERR_NOTFOUND)
err = _add_property(fdt, nodeoffset, name, len, &prop); err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
if (err) if (err)
return err; return err;
...@@ -276,14 +294,14 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name) ...@@ -276,14 +294,14 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
struct fdt_property *prop; struct fdt_property *prop;
int len, proplen; int len, proplen;
RW_CHECK_HEADER(fdt); FDT_RW_CHECK_HEADER(fdt);
prop = fdt_get_property_w(fdt, nodeoffset, name, &len); prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
if (! prop) if (! prop)
return len; return len;
proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE); proplen = sizeof(*prop) + FDT_TAGALIGN(len);
return _blob_splice_struct(fdt, prop, proplen, 0); return _fdt_splice_struct(fdt, prop, proplen, 0);
} }
int fdt_add_subnode_namelen(void *fdt, int parentoffset, int fdt_add_subnode_namelen(void *fdt, int parentoffset,
...@@ -296,7 +314,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, ...@@ -296,7 +314,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
uint32_t tag; uint32_t tag;
uint32_t *endtag; uint32_t *endtag;
RW_CHECK_HEADER(fdt); FDT_RW_CHECK_HEADER(fdt);
offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
if (offset >= 0) if (offset >= 0)
...@@ -309,19 +327,19 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, ...@@ -309,19 +327,19 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
do { do {
offset = nextoffset; offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset); tag = fdt_next_tag(fdt, offset, &nextoffset);
} while (tag == FDT_PROP); } while ((tag == FDT_PROP) || (tag == FDT_NOP));
nh = _fdt_offset_ptr_w(fdt, offset); nh = _fdt_offset_ptr_w(fdt, offset);
nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE; nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
err = _blob_splice_struct(fdt, nh, 0, nodelen); err = _fdt_splice_struct(fdt, nh, 0, nodelen);
if (err) if (err)
return err; return err;
nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
memset(nh->name, 0, ALIGN(namelen+1, FDT_TAGSIZE)); memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
memcpy(nh->name, name, namelen); memcpy(nh->name, name, namelen);
endtag = (uint32_t *)((void *)nh + nodelen - FDT_TAGSIZE); endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
*endtag = cpu_to_fdt32(FDT_END_NODE); *endtag = cpu_to_fdt32(FDT_END_NODE);
return offset; return offset;
...@@ -336,36 +354,36 @@ int fdt_del_node(void *fdt, int nodeoffset) ...@@ -336,36 +354,36 @@ int fdt_del_node(void *fdt, int nodeoffset)
{ {
int endoffset; int endoffset;
RW_CHECK_HEADER(fdt); FDT_RW_CHECK_HEADER(fdt);
endoffset = _fdt_node_end_offset(fdt, nodeoffset); endoffset = _fdt_node_end_offset(fdt, nodeoffset);
if (endoffset < 0) if (endoffset < 0)
return endoffset; return endoffset;
return _blob_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
endoffset - nodeoffset, 0); endoffset - nodeoffset, 0);
} }
static void _packblocks(const void *fdt, void *buf, static void _fdt_packblocks(const char *old, char *new,
int mem_rsv_size, int struct_size) int mem_rsv_size, int struct_size)
{ {
int mem_rsv_off, struct_off, strings_off; int mem_rsv_off, struct_off, strings_off;
mem_rsv_off = ALIGN(sizeof(struct fdt_header), 8); mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
struct_off = mem_rsv_off + mem_rsv_size; struct_off = mem_rsv_off + mem_rsv_size;
strings_off = struct_off + struct_size; strings_off = struct_off + struct_size;
memmove(buf + mem_rsv_off, fdt + fdt_off_mem_rsvmap(fdt), mem_rsv_size); memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size);
fdt_set_off_mem_rsvmap(buf, mem_rsv_off); fdt_set_off_mem_rsvmap(new, mem_rsv_off);
memmove(buf + struct_off, fdt + fdt_off_dt_struct(fdt), struct_size); memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size);
fdt_set_off_dt_struct(buf, struct_off); fdt_set_off_dt_struct(new, struct_off);
fdt_set_size_dt_struct(buf, struct_size); fdt_set_size_dt_struct(new, struct_size);
memmove(buf + strings_off, fdt + fdt_off_dt_strings(fdt), memmove(new + strings_off, old + fdt_off_dt_strings(old),
fdt_size_dt_strings(fdt)); fdt_size_dt_strings(old));
fdt_set_off_dt_strings(buf, strings_off); fdt_set_off_dt_strings(new, strings_off);
fdt_set_size_dt_strings(buf, fdt_size_dt_strings(fdt)); fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
} }
int fdt_open_into(const void *fdt, void *buf, int bufsize) int fdt_open_into(const void *fdt, void *buf, int bufsize)
...@@ -373,11 +391,11 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) ...@@ -373,11 +391,11 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
int err; int err;
int mem_rsv_size, struct_size; int mem_rsv_size, struct_size;
int newsize; int newsize;
void *tmp; const char *fdtstart = fdt;
const char *fdtend = fdtstart + fdt_totalsize(fdt);
char *tmp;
err = fdt_check_header(fdt); FDT_CHECK_HEADER(fdt);
if (err)
return err;
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry); * sizeof(struct fdt_reserve_entry);
...@@ -390,7 +408,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) ...@@ -390,7 +408,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
; ;
} }
if (!_blocks_misordered(fdt, mem_rsv_size, struct_size)) { if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
/* no further work necessary */ /* no further work necessary */
err = fdt_move(fdt, buf, bufsize); err = fdt_move(fdt, buf, bufsize);
if (err) if (err)
...@@ -402,22 +420,23 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) ...@@ -402,22 +420,23 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
} }
/* Need to reorder */ /* Need to reorder */
newsize = ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
+ struct_size + fdt_size_dt_strings(fdt); + struct_size + fdt_size_dt_strings(fdt);
if (bufsize < newsize) if (bufsize < newsize)
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
if (((buf + newsize) <= fdt) /* First attempt to build converted tree at beginning of buffer */
|| (buf >= (fdt + fdt_totalsize(fdt)))) { tmp = buf;
tmp = buf; /* But if that overlaps with the old tree... */
} else { if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) {
tmp = (void *)fdt + fdt_totalsize(fdt); /* Try right after the old tree instead */
if ((tmp + newsize) > (buf + bufsize)) tmp = (char *)(uintptr_t)fdtend;
if ((tmp + newsize) > ((char *)buf + bufsize))
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
} }
_packblocks(fdt, tmp, mem_rsv_size, struct_size); _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
memmove(buf, tmp, newsize); memmove(buf, tmp, newsize);
fdt_set_magic(buf, FDT_MAGIC); fdt_set_magic(buf, FDT_MAGIC);
...@@ -432,16 +451,13 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) ...@@ -432,16 +451,13 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
int fdt_pack(void *fdt) int fdt_pack(void *fdt)
{ {
int mem_rsv_size; int mem_rsv_size;
int err;
err = rw_check_header(fdt); FDT_RW_CHECK_HEADER(fdt);
if (err)
return err;
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry); * sizeof(struct fdt_reserve_entry);
_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
fdt_set_totalsize(fdt, _blob_data_size(fdt)); fdt_set_totalsize(fdt, _fdt_data_size(fdt));
return 0; return 0;
} }
...@@ -55,29 +55,29 @@ ...@@ -55,29 +55,29 @@
#include "libfdt_internal.h" #include "libfdt_internal.h"
struct errtabent { struct fdt_errtabent {
const char *str; const char *str;
}; };
#define ERRTABENT(val) \ #define FDT_ERRTABENT(val) \
[(val)] = { .str = #val, } [(val)] = { .str = #val, }
static struct errtabent errtable[] = { static struct fdt_errtabent fdt_errtable[] = {
ERRTABENT(FDT_ERR_NOTFOUND), FDT_ERRTABENT(FDT_ERR_NOTFOUND),
ERRTABENT(FDT_ERR_EXISTS), FDT_ERRTABENT(FDT_ERR_EXISTS),
ERRTABENT(FDT_ERR_NOSPACE), FDT_ERRTABENT(FDT_ERR_NOSPACE),
ERRTABENT(FDT_ERR_BADOFFSET), FDT_ERRTABENT(FDT_ERR_BADOFFSET),
ERRTABENT(FDT_ERR_BADPATH), FDT_ERRTABENT(FDT_ERR_BADPATH),
ERRTABENT(FDT_ERR_BADSTATE), FDT_ERRTABENT(FDT_ERR_BADSTATE),
ERRTABENT(FDT_ERR_TRUNCATED), FDT_ERRTABENT(FDT_ERR_TRUNCATED),
ERRTABENT(FDT_ERR_BADMAGIC), FDT_ERRTABENT(FDT_ERR_BADMAGIC),
ERRTABENT(FDT_ERR_BADVERSION), FDT_ERRTABENT(FDT_ERR_BADVERSION),
ERRTABENT(FDT_ERR_BADSTRUCTURE), FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
ERRTABENT(FDT_ERR_BADLAYOUT), 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) const char *fdt_strerror(int errval)
{ {
...@@ -85,8 +85,8 @@ const char *fdt_strerror(int errval) ...@@ -85,8 +85,8 @@ const char *fdt_strerror(int errval)
return "<valid offset/length>"; return "<valid offset/length>";
else if (errval == 0) else if (errval == 0)
return "<no error>"; return "<no error>";
else if (errval > -ERRTABSIZE) { else if (errval > -FDT_ERRTABSIZE) {
const char *s = errtable[-errval].str; const char *s = fdt_errtable[-errval].str;
if (s) if (s)
return s; return s;
......
...@@ -55,14 +55,22 @@ ...@@ -55,14 +55,22 @@
#include "libfdt_internal.h" #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; return -FDT_ERR_BADMAGIC;
/* FIXME: should check more details about the header state */
return 0; 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 offset = fdt_size_dt_struct(fdt);
int spaceleft; int spaceleft;
...@@ -86,13 +94,13 @@ int fdt_create(void *buf, int bufsize) ...@@ -86,13 +94,13 @@ int fdt_create(void *buf, int bufsize)
memset(buf, 0, 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_version(fdt, FDT_LAST_SUPPORTED_VERSION);
fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
fdt_set_totalsize(fdt, bufsize); 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))); sizeof(struct fdt_reserve_entry)));
fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
fdt_set_off_dt_strings(fdt, bufsize); fdt_set_off_dt_strings(fdt, bufsize);
...@@ -102,11 +110,10 @@ int fdt_create(void *buf, int 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) int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
{ {
struct fdt_reserve_entry *re; struct fdt_reserve_entry *re;
int err = check_header_sw(fdt);
int offset; int offset;
if (err) FDT_SW_CHECK_HEADER(fdt);
return err;
if (fdt_size_dt_struct(fdt)) if (fdt_size_dt_struct(fdt))
return -FDT_ERR_BADSTATE; return -FDT_ERR_BADSTATE;
...@@ -114,7 +121,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) ...@@ -114,7 +121,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
return -FDT_ERR_NOSPACE; 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->address = cpu_to_fdt64(addr);
re->size = cpu_to_fdt64(size); re->size = cpu_to_fdt64(size);
...@@ -131,13 +138,11 @@ int fdt_finish_reservemap(void *fdt) ...@@ -131,13 +138,11 @@ int fdt_finish_reservemap(void *fdt)
int fdt_begin_node(void *fdt, const char *name) int fdt_begin_node(void *fdt, const char *name)
{ {
struct fdt_node_header *nh; struct fdt_node_header *nh;
int err = check_header_sw(fdt);
int namelen = strlen(name) + 1; int namelen = strlen(name) + 1;
if (err) FDT_SW_CHECK_HEADER(fdt);
return err;
nh = grab_space(fdt, sizeof(*nh) + ALIGN(namelen, FDT_TAGSIZE)); nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
if (! nh) if (! nh)
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
...@@ -149,12 +154,10 @@ int fdt_begin_node(void *fdt, const char *name) ...@@ -149,12 +154,10 @@ int fdt_begin_node(void *fdt, const char *name)
int fdt_end_node(void *fdt) int fdt_end_node(void *fdt)
{ {
uint32_t *en; uint32_t *en;
int err = check_header_sw(fdt);
if (err) FDT_SW_CHECK_HEADER(fdt);
return err;
en = grab_space(fdt, FDT_TAGSIZE); en = _fdt_grab_space(fdt, FDT_TAGSIZE);
if (! en) if (! en)
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
...@@ -162,7 +165,7 @@ int fdt_end_node(void *fdt) ...@@ -162,7 +165,7 @@ int fdt_end_node(void *fdt)
return 0; 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); char *strtab = (char *)fdt + fdt_totalsize(fdt);
const char *p; const char *p;
...@@ -188,17 +191,15 @@ static int find_add_string(void *fdt, const char *s) ...@@ -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) int fdt_property(void *fdt, const char *name, const void *val, int len)
{ {
struct fdt_property *prop; struct fdt_property *prop;
int err = check_header_sw(fdt);
int nameoff; int nameoff;
if (err) FDT_SW_CHECK_HEADER(fdt);
return err;
nameoff = find_add_string(fdt, name); nameoff = _fdt_find_add_string(fdt, name);
if (nameoff == 0) if (nameoff == 0)
return -FDT_ERR_NOSPACE; 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) if (! prop)
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
...@@ -211,18 +212,16 @@ int fdt_property(void *fdt, const char *name, const void *val, int len) ...@@ -211,18 +212,16 @@ int fdt_property(void *fdt, const char *name, const void *val, int len)
int fdt_finish(void *fdt) int fdt_finish(void *fdt)
{ {
int err = check_header_sw(fdt);
char *p = (char *)fdt; char *p = (char *)fdt;
uint32_t *end; uint32_t *end;
int oldstroffset, newstroffset; int oldstroffset, newstroffset;
uint32_t tag; uint32_t tag;
int offset, nextoffset; int offset, nextoffset;
if (err) FDT_SW_CHECK_HEADER(fdt);
return err;
/* Add terminator */ /* Add terminator */
end = grab_space(fdt, sizeof(*end)); end = _fdt_grab_space(fdt, sizeof(*end));
if (! end) if (! end)
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
*end = cpu_to_fdt32(FDT_END); *end = cpu_to_fdt32(FDT_END);
......
...@@ -72,11 +72,11 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, ...@@ -72,11 +72,11 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
return 0; return 0;
} }
static void nop_region(void *start, int len) static void _fdt_nop_region(void *start, int len)
{ {
uint32_t *p; 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); *p = cpu_to_fdt32(FDT_NOP);
} }
...@@ -89,7 +89,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name) ...@@ -89,7 +89,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
if (! prop) if (! prop)
return len; return len;
nop_region(prop, len + sizeof(*prop)); _fdt_nop_region(prop, len + sizeof(*prop));
return 0; return 0;
} }
...@@ -139,6 +139,7 @@ int fdt_nop_node(void *fdt, int nodeoffset) ...@@ -139,6 +139,7 @@ int fdt_nop_node(void *fdt, int nodeoffset)
if (endoffset < 0) if (endoffset < 0)
return endoffset; 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; return 0;
} }
此差异已折叠。
...@@ -52,38 +52,44 @@ ...@@ -52,38 +52,44 @@
*/ */
#include <fdt.h> #include <fdt.h>
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define PALIGN(p, a) ((void *)ALIGN((unsigned long)(p), (a))) #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
#define memeq(p, q, n) (memcmp((p), (q), (n)) == 0) #define FDT_CHECK_HEADER(fdt) \
#define streq(p, q) (strcmp((p), (q)) == 0) { \
int err; \
if ((err = fdt_check_header(fdt)) != 0) \
return err; \
}
uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset); 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); const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
int _fdt_node_end_offset(void *fdt, int nodeoffset); int _fdt_node_end_offset(void *fdt, int nodeoffset);
static inline const void *_fdt_offset_ptr(const void *fdt, int offset) 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) 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) static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
{ {
const struct fdt_reserve_entry *rsv_table = 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; return rsv_table + n;
} }
static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int 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 */ #endif /* _LIBFDT_INTERNAL_H */
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
typedef u32 uint32_t; typedef u32 uint32_t;
typedef u64 uint64_t; typedef u64 uint64_t;
typedef unsigned long uintptr_t;
#define fdt16_to_cpu(x) (x) #define fdt16_to_cpu(x) (x)
#define cpu_to_fdt16(x) (x) #define cpu_to_fdt16(x) (x)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册