summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/manual.txt38
-rw-r--r--Makefile96
-rw-r--r--Makefile.convert-dtsv013
-rw-r--r--Makefile.dtc13
-rw-r--r--Makefile.ftdump12
-rw-r--r--checks.c46
-rw-r--r--convert-dtsv0-lexer.l25
-rw-r--r--data.c2
-rw-r--r--dtc-lexer.l82
-rw-r--r--dtc-parser.y75
-rw-r--r--dtc.c23
-rw-r--r--dtc.h43
-rw-r--r--flattree.c111
-rw-r--r--fstree.c4
-rw-r--r--ftdump.c47
-rw-r--r--libfdt/Makefile.libfdt1
-rw-r--r--libfdt/fdt.c52
-rw-r--r--libfdt/fdt_ro.c175
-rw-r--r--libfdt/fdt_rw.c2
-rw-r--r--libfdt/fdt_sw.c11
-rw-r--r--libfdt/fdt_wip.c41
-rw-r--r--libfdt/libfdt.h60
-rw-r--r--libfdt/libfdt_internal.h1
-rw-r--r--libfdt/version.lds54
-rw-r--r--livetree.c24
-rw-r--r--srcpos.c146
-rw-r--r--srcpos.h23
-rw-r--r--tests/Makefile.tests25
-rw-r--r--tests/aliases.dts21
-rw-r--r--tests/asm_tree_dump.c62
-rw-r--r--tests/base01.dts24
-rw-r--r--tests/data.S3
-rw-r--r--tests/dtbs_equal_ordered.c4
-rw-r--r--tests/empty.dts2
-rw-r--r--tests/escapes.dts2
-rw-r--r--tests/extra-terminating-null.c59
-rw-r--r--tests/extra-terminating-null.dts11
-rw-r--r--tests/get_alias.c58
-rw-r--r--tests/get_name.c2
-rw-r--r--tests/get_path.c14
-rw-r--r--tests/get_phandle.c2
-rw-r--r--tests/incbin.c2
-rw-r--r--tests/include1.dts5
-rw-r--r--tests/include7.dts3
-rw-r--r--tests/label01.dts38
-rw-r--r--tests/mangle-layout.c6
-rw-r--r--tests/node_check_compatible.c3
-rw-r--r--tests/node_offset_by_compatible.c2
-rw-r--r--tests/node_offset_by_phandle.c2
-rw-r--r--tests/node_offset_by_prop_value.c7
-rw-r--r--tests/nopulate.c2
-rw-r--r--tests/notfound.c2
-rw-r--r--tests/parent_offset.c4
-rw-r--r--tests/path-references.c2
-rw-r--r--tests/path_offset.c2
-rw-r--r--tests/path_offset_aliases.c59
-rw-r--r--tests/phandle_format.c78
-rw-r--r--tests/references.c15
-rw-r--r--tests/references.dts13
-rw-r--r--tests/references_dts0.dts15
-rwxr-xr-xtests/run_tests.sh79
-rw-r--r--tests/rw_tree1.c18
-rw-r--r--tests/set_name.c2
-rw-r--r--tests/subnode_offset.c13
-rw-r--r--tests/supernode_atdepth_offset.c10
-rw-r--r--tests/sw_tree1.c7
-rw-r--r--tests/test01.dts38
-rw-r--r--tests/test_tree1.dts8
-rw-r--r--tests/test_tree1_dts0.dts24
-rw-r--r--tests/tests.h1
-rw-r--r--tests/trees.S13
-rw-r--r--tests/value-labels.c128
-rw-r--r--tests/value-labels.dts8
-rw-r--r--treesource.c31
-rw-r--r--util.c30
-rw-r--r--util.h55
76 files changed, 1626 insertions, 608 deletions
diff --git a/Documentation/manual.txt b/Documentation/manual.txt
index b957662..f8a8a7b 100644
--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -19,6 +19,10 @@ II - The DT block format
III - libfdt
+IV - Utility Tools
+ 1) convert-dtsv0 -- Conversion to Version 1
+ 1) ftdump
+
I - "dtc", the device tree compiler
===================================
@@ -28,7 +32,7 @@ I - "dtc", the device tree compiler
Source code for the Device Tree Compiler can be found at jdl.com.
The gitweb interface is:
- http://www.jdl.com/git_repos/
+ http://git.jdl.com/gitweb/
The repository is here:
@@ -37,7 +41,7 @@ The repository is here:
Tarballs of the 1.0.0 and latest releases are here:
- http://www.jdl.com/software/dtc-1.0.0.tgz
+ http://www.jdl.com/software/dtc-v1.2.0.tgz
http://www.jdl.com/software/dtc-latest.tgz
@@ -613,6 +617,36 @@ strings block.
III - libfdt
+============
This library should be merged into dtc proper.
This library should likely be worked into U-Boot and the kernel.
+
+
+IV - Utility Tools
+==================
+
+1) convert-dtsv0 -- Conversion to Version 1
+
+convert-dtsv0 is a small utility program which converts (DTS)
+Device Tree Source from the obsolete version 0 to version 1.
+
+Version 1 DTS files are marked by line "/dts-v1/;" at the top of the file.
+
+The syntax of the convert-dtsv0 command line is:
+
+ convert-dtsv0 [<input_filename ... >]
+
+Each file passed will be converted to the new /dts-v1/ version by creating
+a new file with a "v1" appended the filename.
+
+Comments, empty lines, etc. are preserved.
+
+
+2) ftdump -- Flat Tree dumping utility
+
+The ftdump program prints a readable version of a flat device tree file.
+
+The syntax of the ftdump command line is:
+
+ ftdump <DTB-file-name>
diff --git a/Makefile b/Makefile
index 5ad0189..d7549b2 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ LOCAL_VERSION =
CONFIG_LOCALVERSION =
CPPFLAGS = -I libfdt
-CFLAGS = -Wall -g -Os -Wpointer-arith -Wcast-qual
+CFLAGS = -Wall -g -Os -fPIC -Wpointer-arith -Wcast-qual
BISON = bison
LEX = flex
@@ -28,6 +28,17 @@ BINDIR = $(PREFIX)/bin
LIBDIR = $(PREFIX)/lib
INCLUDEDIR = $(PREFIX)/include
+HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
+ sed -e 's/\(cygwin\).*/cygwin/')
+
+ifeq ($(HOSTOS),darwin)
+SHAREDLIB_EXT=dylib
+SHAREDLIB_LINK_OPTIONS=-dynamiclib -Wl,-install_name -Wl,
+else
+SHAREDLIB_EXT=so
+SHAREDLIB_LINK_OPTIONS=-shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,
+endif
+
#
# Overall rules
#
@@ -46,17 +57,6 @@ else
DEPTARGETS = $(filter-out $(NODEPTARGETS),$(MAKECMDGOALS))
endif
-all: dtc ftdump convert-dtsv0 libfdt
-
-install: all
- @$(VECHO) INSTALL
- $(INSTALL) -d $(DESTDIR)$(BINDIR)
- $(INSTALL) -m 755 dtc $(DESTDIR)$(BINDIR)
- $(INSTALL) -d $(DESTDIR)$(LIBDIR)
- $(INSTALL) -m 644 $(LIBFDT_lib) $(DESTDIR)$(LIBDIR)
- $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR)
- $(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR)
-
#
# Rules for versioning
#
@@ -100,63 +100,82 @@ define filechk
fi;
endef
-$(VERSION_FILE): Makefile FORCE
- $(call filechk,version)
-#
-# Rules for dtc proper
-#
+include Makefile.convert-dtsv0
include Makefile.dtc
+include Makefile.ftdump
+BIN += convert-dtsv0
BIN += dtc
+BIN += ftdump
-# This stops make from generating the lex and bison output during
-# auto-dependency computation, but throwing them away as an
-# intermediate target and building them again "for real"
-.SECONDARY: $(DTC_GEN_SRCS)
-dtc: $(DTC_OBJS)
+all: $(BIN) libfdt
+
ifneq ($(DEPTARGETS),)
-include $(DTC_OBJS:%.o=%.d)
+-include $(CONVERT_OBJS:%.o=%.d)
+-include $(FTDUMP_OBJS:%.o=%.d)
endif
-#
-# Rules for ftdump & convert-dtsv0
-#
-BIN += ftdump convert-dtsv0
-ftdump: ftdump.o
-convert-dtsv0: convert-dtsv0-lexer.lex.o srcpos.o
- @$(VECHO) LD $@
- $(LINK.c) -o $@ $^
-ifneq ($(DEPTARGETS),)
--include ftdump.d
-endif
#
# Rules for libfdt
#
LIBFDT_objdir = libfdt
LIBFDT_srcdir = libfdt
-LIBFDT_lib = $(LIBFDT_objdir)/libfdt.a
+LIBFDT_archive = $(LIBFDT_objdir)/libfdt.a
+LIBFDT_lib = $(LIBFDT_objdir)/libfdt.$(SHAREDLIB_EXT)
LIBFDT_include = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES))
+LIBFDT_version = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_VERSION))
include $(LIBFDT_srcdir)/Makefile.libfdt
.PHONY: libfdt
-libfdt: $(LIBFDT_lib)
+libfdt: $(LIBFDT_archive) $(LIBFDT_lib)
+$(LIBFDT_archive): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
$(LIBFDT_lib): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
libfdt_clean:
@$(VECHO) CLEAN "(libfdt)"
rm -f $(addprefix $(LIBFDT_objdir)/,$(STD_CLEANFILES))
+ rm -f $(LIBFDT_objdir)/*.so
ifneq ($(DEPTARGETS),)
-include $(LIBFDT_OBJS:%.o=$(LIBFDT_objdir)/%.d)
endif
+# This stops make from generating the lex and bison output during
+# auto-dependency computation, but throwing them away as an
+# intermediate target and building them again "for real"
+.SECONDARY: $(DTC_GEN_SRCS) $(CONVERT_GEN_SRCS)
+
+install: all
+ @$(VECHO) INSTALL
+ $(INSTALL) -d $(DESTDIR)$(BINDIR)
+ $(INSTALL) $(BIN) $(DESTDIR)$(BINDIR)
+ $(INSTALL) -d $(DESTDIR)$(LIBDIR)
+ $(INSTALL) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR)
+ $(INSTALL) -m 644 $(LIBFDT_archive) $(DESTDIR)$(LIBDIR)
+ $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR)
+ $(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR)
+
+$(VERSION_FILE): Makefile FORCE
+ $(call filechk,version)
+
+
+dtc: $(DTC_OBJS)
+
+convert-dtsv0: $(CONVERT_OBJS)
+ @$(VECHO) LD $@
+ $(LINK.c) -o $@ $^
+
+ftdump: $(FTDUMP_OBJS)
+
+
#
# Testsuite rules
#
@@ -166,7 +185,7 @@ include tests/Makefile.tests
#
# Clean rules
#
-STD_CLEANFILES = *~ *.o *.d *.a *.i *.s core a.out vgcore.* \
+STD_CLEANFILES = *~ *.o *.so *.d *.a *.i *.s core a.out vgcore.* \
*.tab.[ch] *.lex.c *.output
clean: libfdt_clean tests_clean
@@ -210,6 +229,11 @@ clean: libfdt_clean tests_clean
@$(VECHO) AR $@
$(AR) $(ARFLAGS) $@ $^
+$(LIBFDT_lib):
+ @$(VECHO) LD $@
+ $(CC) $(LDFLAGS) -fPIC $(SHAREDLIB_LINK_OPTIONS)$(notdir $@) -o $(LIBFDT_objdir)/libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) $^
+ ln -sf libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) $(LIBFDT_objdir)/libfdt.$(SHAREDLIB_EXT)
+
%.lex.c: %.l
@$(VECHO) LEX $@
$(LEX) -o$@ $<
diff --git a/Makefile.convert-dtsv0 b/Makefile.convert-dtsv0
new file mode 100644
index 0000000..08ea40a
--- /dev/null
+++ b/Makefile.convert-dtsv0
@@ -0,0 +1,13 @@
+#
+# This is not a complete Makefile of itself.
+# Instead, it is designed to be easily embeddable
+# into other systems of Makefiles.
+#
+
+CONVERT_SRCS = \
+ srcpos.c \
+ util.c
+
+CONVERT_GEN_SRCS = convert-dtsv0-lexer.lex.c
+
+CONVERT_OBJS = $(CONVERT_SRCS:%.c=%.o) $(CONVERT_GEN_SRCS:%.c=%.o)
diff --git a/Makefile.dtc b/Makefile.dtc
index 6ddf9ec..bece49b 100644
--- a/Makefile.dtc
+++ b/Makefile.dtc
@@ -3,7 +3,16 @@
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.
#
-DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
- checks.c
+DTC_SRCS = \
+ checks.c \
+ data.c \
+ dtc.c \
+ flattree.c \
+ fstree.c \
+ livetree.c \
+ srcpos.c \
+ treesource.c \
+ util.c
+
DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
diff --git a/Makefile.ftdump b/Makefile.ftdump
new file mode 100644
index 0000000..b70905a
--- /dev/null
+++ b/Makefile.ftdump
@@ -0,0 +1,12 @@
+#
+# This is not a complete Makefile of itself.
+# Instead, it is designed to be easily embeddable
+# into other systems of Makefiles.
+#
+
+FTDUMP_SRCS = \
+ ftdump.c
+
+FTDUMP_GEN_SRCS =
+
+FTDUMP_OBJS = $(FTDUMP_SRCS:%.c=%.o) $(FTDUMP_GEN_SRCS:%.c=%.o)
diff --git a/checks.c b/checks.c
index 9548579..031cc59 100644
--- a/checks.c
+++ b/checks.c
@@ -279,31 +279,55 @@ static void check_property_name_chars(struct check *c, struct node *dt,
PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);
static void check_explicit_phandles(struct check *c, struct node *root,
- struct node *node)
+ struct node *node, struct property *prop)
{
- struct property *prop;
+ struct marker *m;
struct node *other;
cell_t phandle;
- prop = get_property(node, "linux,phandle");
- if (! prop)
- return; /* No phandle, that's fine */
+ if (!streq(prop->name, "phandle")
+ && !streq(prop->name, "linux,phandle"))
+ return;
if (prop->val.len != sizeof(cell_t)) {
- FAIL(c, "%s has bad length (%d) linux,phandle property",
- node->fullpath, prop->val.len);
+ FAIL(c, "%s has bad length (%d) %s property",
+ node->fullpath, prop->val.len, prop->name);
+ return;
+ }
+
+ m = prop->val.markers;
+ for_each_marker_of_type(m, REF_PHANDLE) {
+ assert(m->offset == 0);
+ if (node != get_node_by_ref(root, m->ref))
+ /* "Set this node's phandle equal to some
+ * other node's phandle". That's nonsensical
+ * by construction. */ {
+ FAIL(c, "%s in %s is a reference to another node",
+ prop->name, node->fullpath);
+ return;
+ }
+ /* But setting this node's phandle equal to its own
+ * phandle is allowed - that means allocate a unique
+ * phandle for this node, even if it's not otherwise
+ * referenced. The value will be filled in later, so
+ * no further checking for now. */
return;
}
phandle = propval_cell(prop);
+
if ((phandle == 0) || (phandle == -1)) {
- FAIL(c, "%s has invalid linux,phandle value 0x%x",
- node->fullpath, phandle);
+ FAIL(c, "%s has bad value (0x%x) in %s property",
+ node->fullpath, phandle, prop->name);
return;
}
+ if (node->phandle && (node->phandle != phandle))
+ FAIL(c, "%s has %s property which replaces existing phandle information",
+ node->fullpath, prop->name);
+
other = get_node_by_phandle(root, phandle);
- if (other) {
+ if (other && (other != node)) {
FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
node->fullpath, phandle, other->fullpath);
return;
@@ -311,7 +335,7 @@ static void check_explicit_phandles(struct check *c, struct node *root,
node->phandle = phandle;
}
-NODE_CHECK(explicit_phandles, NULL, ERROR);
+PROP_CHECK(explicit_phandles, NULL, ERROR);
static void check_name_properties(struct check *c, struct node *root,
struct node *node)
diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l
index 12b45ea..59137f1 100644
--- a/convert-dtsv0-lexer.l
+++ b/convert-dtsv0-lexer.l
@@ -17,7 +17,7 @@
* USA
*/
-%option noyywrap nounput
+%option noyywrap nounput noinput
%x INCLUDE
%x BYTESTRING
@@ -42,6 +42,7 @@ GAP ({WS}|{COMMENT}|{LINECOMMENT})*
#include <fnmatch.h>
#include "srcpos.h"
+#include "util.h"
static int v1_tagged; /* = 0 */
static int cbase = 16;
@@ -51,26 +52,6 @@ static char *last_name; /* = NULL */
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-static inline void __attribute__((noreturn)) die(char * str, ...)
-{
- va_list ap;
-
- va_start(ap, str);
- fprintf(stderr, "FATAL ERROR: ");
- vfprintf(stderr, str, ap);
- exit(1);
-}
-
-static inline void *xmalloc(size_t len)
-{
- void *new = malloc(len);
-
- if (! new)
- die("malloc() failed\n");
-
- return new;
-}
-
const struct {
const char *pattern;
int obase, width;
@@ -185,7 +166,7 @@ const struct {
<PROPNODENAME>{PROPNODECHAR}+ {
ECHO;
- last_name = strdup(yytext);
+ last_name = xstrdup(yytext);
BEGIN(INITIAL);
}
diff --git a/data.c b/data.c
index dd2e3d3..fe555e8 100644
--- a/data.c
+++ b/data.c
@@ -217,7 +217,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m,
return d;
}
-struct data data_append_markers(struct data d, struct marker *m)
+static struct data data_append_markers(struct data d, struct marker *m)
{
struct marker **mp = &d.markers;
diff --git a/dtc-lexer.l b/dtc-lexer.l
index 44dbfd3..d142de5 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -18,7 +18,7 @@
* USA
*/
-%option noyywrap nounput yylineno
+%option noyywrap nounput noinput yylineno
%x INCLUDE
%x BYTESTRING
@@ -38,6 +38,11 @@ LINECOMMENT "//".*\n
#include "srcpos.h"
#include "dtc-parser.tab.h"
+#define YY_USER_ACTION \
+ { \
+ yylloc.file = srcpos_file; \
+ yylloc.first_line = yylineno; \
+ }
/*#define LEXDEBUG 1*/
@@ -47,15 +52,10 @@ LINECOMMENT "//".*\n
#define DPRINT(fmt, ...) do { } while (0)
#endif
-static int dts_version; /* = 0 */
+static int dts_version = 1;
-#define BEGIN_DEFAULT() if (dts_version == 0) { \
- DPRINT("<INITIAL>\n"); \
- BEGIN(INITIAL); \
- } else { \
- DPRINT("<V1>\n"); \
+#define BEGIN_DEFAULT() DPRINT("<V1>\n"); \
BEGIN(V1); \
- }
static void push_input_file(const char *filename);
static int pop_input_file(void);
@@ -75,18 +75,13 @@ static int pop_input_file(void);
}
<*>{STRING} {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
DPRINT("String: %s\n", yytext);
yylval.data = data_copy_escape_string(yytext+1,
yyleng-2);
- yylloc.first_line = yylineno;
return DT_STRING;
}
<*>"/dts-v1/" {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
DPRINT("Keyword: /dts-v1/\n");
dts_version = 1;
BEGIN_DEFAULT();
@@ -94,106 +89,57 @@ static int pop_input_file(void);
}
<*>"/memreserve/" {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT();
return DT_MEMRESERVE;
}
<*>{LABEL}: {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
DPRINT("Label: %s\n", yytext);
- yylval.labelref = strdup(yytext);
+ yylval.labelref = xstrdup(yytext);
yylval.labelref[yyleng-1] = '\0';
return DT_LABEL;
}
-<INITIAL>[bodh]# {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- if (*yytext == 'b')
- yylval.cbase = 2;
- else if (*yytext == 'o')
- yylval.cbase = 8;
- else if (*yytext == 'd')
- yylval.cbase = 10;
- else
- yylval.cbase = 16;
- DPRINT("Base: %d\n", yylval.cbase);
- return DT_BASE;
- }
-
-<INITIAL>[0-9a-fA-F]+ {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- yylval.literal = strdup(yytext);
- DPRINT("Literal: '%s'\n", yylval.literal);
- return DT_LEGACYLITERAL;
- }
-
<V1>[0-9]+|0[xX][0-9a-fA-F]+ {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- yylval.literal = strdup(yytext);
+ yylval.literal = xstrdup(yytext);
DPRINT("Literal: '%s'\n", yylval.literal);
return DT_LITERAL;
}
\&{LABEL} { /* label reference */
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
DPRINT("Ref: %s\n", yytext+1);
- yylval.labelref = strdup(yytext+1);
+ yylval.labelref = xstrdup(yytext+1);
return DT_REF;
}
"&{/"{PATHCHAR}+\} { /* new-style path reference */
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
- yylval.labelref = strdup(yytext+2);
- return DT_REF;
- }
-
-<INITIAL>"&/"{PATHCHAR}+ { /* old-style path reference */
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Ref: %s\n", yytext+1);
- yylval.labelref = strdup(yytext+1);
+ yylval.labelref = xstrdup(yytext+2);
return DT_REF;
}
<BYTESTRING>[0-9a-fA-F]{2} {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
yylval.byte = strtol(yytext, NULL, 16);
DPRINT("Byte: %02x\n", (int)yylval.byte);
return DT_BYTE;
}
<BYTESTRING>"]" {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
DPRINT("/BYTESTRING\n");
BEGIN_DEFAULT();
return ']';
}
<PROPNODENAME>{PROPNODECHAR}+ {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
DPRINT("PropNodeName: %s\n", yytext);
- yylval.propnodename = strdup(yytext);
+ yylval.propnodename = xstrdup(yytext);
BEGIN_DEFAULT();
return DT_PROPNODENAME;
}
"/incbin/" {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
DPRINT("Binary Include\n");
return DT_INCBIN;
}
@@ -203,8 +149,6 @@ static int pop_input_file(void);
<*>{LINECOMMENT}+ /* eat C++-style comments */
<*>. {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
if (yytext[0] == '[') {
diff --git a/dtc-parser.y b/dtc-parser.y
index b2ab562..31c14d7 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -27,6 +27,7 @@
#include "srcpos.h"
extern int yylex(void);
+extern void yyerror(char const *s);
extern struct boot_info *the_boot_info;
extern int treesource_error;
@@ -55,7 +56,6 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
%token DT_MEMRESERVE
%token <propnodename> DT_PROPNODENAME
%token <literal> DT_LITERAL
-%token <literal> DT_LEGACYLITERAL
%token <cbase> DT_BASE
%token <byte> DT_BYTE
%token <data> DT_STRING
@@ -67,11 +67,8 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
%type <data> propdataprefix
%type <re> memreserve
%type <re> memreserves
-%type <re> v0_memreserve
-%type <re> v0_memreserves
%type <addr> addr
%type <data> celllist
-%type <cbase> cellbase
%type <cell> cellval
%type <data> bytestring
%type <prop> propdef
@@ -90,10 +87,6 @@ sourcefile:
{
the_boot_info = build_boot_info($3, $4, 0);
}
- | v0_memreserves devicetree
- {
- the_boot_info = build_boot_info($1, $2, 0);
- }
;
memreserves:
@@ -114,37 +107,11 @@ memreserve:
}
;
-v0_memreserves:
- /* empty */
- {
- $$ = NULL;
- }
- | v0_memreserve v0_memreserves
- {
- $$ = chain_reserve_entry($1, $2);
- };
- ;
-
-v0_memreserve:
- memreserve
- {
- $$ = $1;
- }
- | label DT_MEMRESERVE addr '-' addr ';'
- {
- $$ = build_reserve_entry($3, $5 - $3 + 1, $1);
- }
- ;
-
addr:
DT_LITERAL
{
$$ = eval_literal($1, 0, 64);
}
- | DT_LEGACYLITERAL
- {
- $$ = eval_literal($1, 16, 64);
- }
;
devicetree:
@@ -208,9 +175,11 @@ propdata:
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));
+ srcpos_error(&yylloc,
+ "Couldn't seek to offset %llu in \"%s\": %s",
+ (unsigned long long)$6,
+ $4.val,
+ strerror(errno));
d = data_copy_file(file->file, $8);
@@ -269,23 +238,11 @@ celllist:
}
;
-cellbase:
- /* empty */
- {
- $$ = 16;
- }
- | DT_BASE
- ;
-
cellval:
DT_LITERAL
{
$$ = eval_literal($1, 0, 32);
}
- | cellbase DT_LEGACYLITERAL
- {
- $$ = eval_literal($2, $1, 32);
- }
;
bytestring:
@@ -339,26 +296,10 @@ label:
%%
-void yyerrorf(char const *s, ...)
+void yyerror(char const *s)
{
- const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";
- va_list va;
- va_start(va, s);
-
- if (strcmp(fname, "-") == 0)
- fname = "stdin";
-
- fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
- vfprintf(stderr, s, va);
- fprintf(stderr, "\n");
-
+ srcpos_error(&yylloc, "%s", s);
treesource_error = 1;
- va_end(va);
-}
-
-void yyerror (char const *s)
-{
- yyerrorf("%s", s);
}
static unsigned long long eval_literal(const char *s, int base, int bits)
diff --git a/dtc.c b/dtc.c
index d8fd43b4..800664c 100644
--- a/dtc.c
+++ b/dtc.c
@@ -30,6 +30,7 @@ int quiet; /* Level of quietness */
int reservenum; /* Number of memory reservation slots */
int minsize; /* Minimum blob size */
int padsize; /* Additional padding to blob */
+int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
char *join_path(const char *path, const char *name)
{
@@ -106,6 +107,11 @@ static void __attribute__ ((noreturn)) usage(void)
fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
fprintf(stderr, "\t-v\n");
fprintf(stderr, "\t\tPrint DTC version and exit\n");
+ fprintf(stderr, "\t-H <phandle format>\n");
+ fprintf(stderr, "\t\tphandle formats are:\n");
+ fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n");
+ fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n");
+ fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n");
exit(3);
}
@@ -127,7 +133,7 @@ int main(int argc, char *argv[])
minsize = 0;
padsize = 0;
- while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:v")) != EOF) {
+ while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:vH:")) != EOF) {
switch (opt) {
case 'I':
inform = optarg;
@@ -165,6 +171,18 @@ int main(int argc, char *argv[])
case 'v':
printf("Version: %s\n", DTC_VERSION);
exit(0);
+ case 'H':
+ if (streq(optarg, "legacy"))
+ phandle_format = PHANDLE_LEGACY;
+ else if (streq(optarg, "epapr"))
+ phandle_format = PHANDLE_EPAPR;
+ else if (streq(optarg, "both"))
+ phandle_format = PHANDLE_BOTH;
+ else
+ die("Invalid argument \"%s\" to -H option\n",
+ optarg);
+ break;
+
case 'h':
default:
usage();
@@ -182,6 +200,9 @@ int main(int argc, char *argv[])
if (minsize && padsize)
die("Can't set both -p and -S\n");
+ if (minsize)
+ fprintf(stderr, "DTC: Use of \"-S\" is deprecated; it will be removed soon, use \"-p\" instead\n");
+
fprintf(stderr, "DTC: %s->%s on file \"%s\"\n",
inform, outform, arg);
diff --git a/dtc.h b/dtc.h
index 08d54c8..0d7f0ed 100644
--- a/dtc.h
+++ b/dtc.h
@@ -34,7 +34,17 @@
#include <libfdt_env.h>
#include <fdt.h>
+#include "util.h"
+
+#ifdef DEBUG
+#define debug(fmt,args...) printf(fmt, ##args)
+#else
+#define debug(fmt,args...)
+#endif
+
+
#define DEFAULT_FDT_VERSION 17
+
/*
* Command line options
*/
@@ -42,36 +52,11 @@ extern int quiet; /* Level of quietness */
extern int reservenum; /* Number of memory reservation slots */
extern int minsize; /* Minimum blob size */
extern int padsize; /* Additional padding to blob */
+extern int phandle_format; /* Use linux,phandle or phandle properties */
-static inline void __attribute__((noreturn)) die(char * str, ...)
-{
- va_list ap;
-
- va_start(ap, str);
- fprintf(stderr, "FATAL ERROR: ");
- vfprintf(stderr, str, ap);
- exit(1);
-}
-
-static inline void *xmalloc(size_t len)
-{
- void *new = malloc(len);
-
- if (! new)
- die("malloc() failed\n");
-
- return new;
-}
-
-static inline void *xrealloc(void *p, size_t len)
-{
- void *new = realloc(p, len);
-
- if (! new)
- die("realloc() failed (len=%d)\n", len);
-
- return new;
-}
+#define PHANDLE_LEGACY 0x1
+#define PHANDLE_EPAPR 0x2
+#define PHANDLE_BOTH 0x3
typedef uint32_t cell_t;
diff --git a/flattree.c b/flattree.c
index 76acd28..3eb0201 100644
--- a/flattree.c
+++ b/flattree.c
@@ -127,11 +127,21 @@ static void emit_offset_label(FILE *f, const char *label, int offset)
fprintf(f, "%s\t= . + %d\n", label, offset);
}
+#define ASM_EMIT_BELONG(f, fmt, ...) \
+ { \
+ fprintf((f), "\t.byte\t((" fmt ") >> 24) & 0xff\n", __VA_ARGS__); \
+ fprintf((f), "\t.byte\t((" fmt ") >> 16) & 0xff\n", __VA_ARGS__); \
+ fprintf((f), "\t.byte\t((" fmt ") >> 8) & 0xff\n", __VA_ARGS__); \
+ fprintf((f), "\t.byte\t(" fmt ") & 0xff\n", __VA_ARGS__); \
+ }
+
static void asm_emit_cell(void *e, cell_t val)
{
FILE *f = e;
- fprintf(f, "\t.long\t0x%x\n", val);
+ fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n",
+ (val >> 24) & 0xff, (val >> 16) & 0xff,
+ (val >> 8) & 0xff, val & 0xff);
}
static void asm_emit_string(void *e, char *str, int len)
@@ -156,7 +166,7 @@ static void asm_emit_align(void *e, int a)
{
FILE *f = e;
- fprintf(f, "\t.balign\t%d\n", a);
+ fprintf(f, "\t.balign\t%d, 0\n", a);
}
static void asm_emit_data(void *e, struct data d)
@@ -169,8 +179,7 @@ static void asm_emit_data(void *e, struct data d)
emit_offset_label(f, m->ref, m->offset);
while ((d.len - off) >= sizeof(uint32_t)) {
- fprintf(f, "\t.long\t0x%x\n",
- fdt32_to_cpu(*((uint32_t *)(d.val+off))));
+ asm_emit_cell(e, fdt32_to_cpu(*((uint32_t *)(d.val+off))));
off += sizeof(uint32_t);
}
@@ -190,14 +199,16 @@ static void asm_emit_beginnode(void *e, const char *label)
fprintf(f, "\t.globl\t%s\n", label);
fprintf(f, "%s:\n", label);
}
- fprintf(f, "\t.long\tFDT_BEGIN_NODE\n");
+ fprintf(f, "\t/* FDT_BEGIN_NODE */\n");
+ asm_emit_cell(e, FDT_BEGIN_NODE);
}
static void asm_emit_endnode(void *e, const char *label)
{
FILE *f = e;
- fprintf(f, "\t.long\tFDT_END_NODE\n");
+ fprintf(f, "\t/* FDT_END_NODE */\n");
+ asm_emit_cell(e, FDT_END_NODE);
if (label) {
fprintf(f, "\t.globl\t%s_end\n", label);
fprintf(f, "%s_end:\n", label);
@@ -212,7 +223,8 @@ static void asm_emit_property(void *e, const char *label)
fprintf(f, "\t.globl\t%s\n", label);
fprintf(f, "%s:\n", label);
}
- fprintf(f, "\t.long\tFDT_PROP\n");
+ fprintf(f, "\t/* FDT_PROP */\n");
+ asm_emit_cell(e, FDT_PROP);
}
static struct emitter asm_emitter = {
@@ -413,10 +425,13 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version)
if (padlen > 0)
blob = data_append_zeroes(blob, padlen);
- fwrite(blob.val, blob.len, 1, f);
-
- if (ferror(f))
- die("Error writing device tree blob: %s\n", strerror(errno));
+ if (fwrite(blob.val, blob.len, 1, f) != 1) {
+ if (ferror(f))
+ die("Error writing device tree blob: %s\n",
+ strerror(errno));
+ else
+ die("Short write on device tree blob\n");
+ }
/*
* data_merge() frees the right-hand element so only the blob
@@ -455,39 +470,44 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
die("Unknown device tree blob version %d\n", version);
fprintf(f, "/* autogenerated by dtc, do not edit */\n\n");
- fprintf(f, "#define FDT_MAGIC 0x%x\n", FDT_MAGIC);
- fprintf(f, "#define FDT_BEGIN_NODE 0x%x\n", FDT_BEGIN_NODE);
- fprintf(f, "#define FDT_END_NODE 0x%x\n", FDT_END_NODE);
- fprintf(f, "#define FDT_PROP 0x%x\n", FDT_PROP);
- fprintf(f, "#define FDT_END 0x%x\n", FDT_END);
- fprintf(f, "\n");
emit_label(f, symprefix, "blob_start");
emit_label(f, symprefix, "header");
- fprintf(f, "\t.long\tFDT_MAGIC\t\t\t\t/* magic */\n");
- fprintf(f, "\t.long\t_%s_blob_abs_end - _%s_blob_start\t/* totalsize */\n",
- symprefix, symprefix);
- fprintf(f, "\t.long\t_%s_struct_start - _%s_blob_start\t/* off_dt_struct */\n",
+ fprintf(f, "\t/* magic */\n");
+ asm_emit_cell(f, FDT_MAGIC);
+ fprintf(f, "\t/* totalsize */\n");
+ ASM_EMIT_BELONG(f, "_%s_blob_abs_end - _%s_blob_start",
+ symprefix, symprefix);
+ fprintf(f, "\t/* off_dt_struct */\n");
+ ASM_EMIT_BELONG(f, "_%s_struct_start - _%s_blob_start",
symprefix, symprefix);
- fprintf(f, "\t.long\t_%s_strings_start - _%s_blob_start\t/* off_dt_strings */\n",
+ fprintf(f, "\t/* off_dt_strings */\n");
+ ASM_EMIT_BELONG(f, "_%s_strings_start - _%s_blob_start",
symprefix, symprefix);
- fprintf(f, "\t.long\t_%s_reserve_map - _%s_blob_start\t/* off_dt_strings */\n",
+ fprintf(f, "\t/* off_mem_rsvmap */\n");
+ ASM_EMIT_BELONG(f, "_%s_reserve_map - _%s_blob_start",
symprefix, symprefix);
- fprintf(f, "\t.long\t%d\t\t\t\t\t/* version */\n", vi->version);
- fprintf(f, "\t.long\t%d\t\t\t\t\t/* last_comp_version */\n",
- vi->last_comp_version);
-
- if (vi->flags & FTF_BOOTCPUID)
- fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n",
- bi->boot_cpuid_phys);
+ fprintf(f, "\t/* version */\n");
+ asm_emit_cell(f, vi->version);
+ fprintf(f, "\t/* last_comp_version */\n");
+ asm_emit_cell(f, vi->last_comp_version);
+
+ if (vi->flags & FTF_BOOTCPUID) {
+ fprintf(f, "\t/* boot_cpuid_phys */\n");
+ asm_emit_cell(f, bi->boot_cpuid_phys);
+ }
- if (vi->flags & FTF_STRTABSIZE)
- fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n",
- symprefix, symprefix);
+ if (vi->flags & FTF_STRTABSIZE) {
+ fprintf(f, "\t/* size_dt_strings */\n");
+ ASM_EMIT_BELONG(f, "_%s_strings_end - _%s_strings_start",
+ symprefix, symprefix);
+ }
- if (vi->flags & FTF_STRUCTSIZE)
- fprintf(f, "\t.long\t_%s_struct_end - _%s_struct_start\t/* size_dt_struct */\n",
+ if (vi->flags & FTF_STRUCTSIZE) {
+ fprintf(f, "\t/* size_dt_struct */\n");
+ ASM_EMIT_BELONG(f, "_%s_struct_end - _%s_struct_start",
symprefix, symprefix);
+ }
/*
* Reserve map entries.
@@ -509,12 +529,11 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
fprintf(f, "\t.globl\t%s\n", re->label);
fprintf(f, "%s:\n", re->label);
}
- fprintf(f, "\t.long\t0x%08x, 0x%08x\n",
- (unsigned int)(re->re.address >> 32),
- (unsigned int)(re->re.address & 0xffffffff));
- fprintf(f, "\t.long\t0x%08x, 0x%08x\n",
- (unsigned int)(re->re.size >> 32),
- (unsigned int)(re->re.size & 0xffffffff));
+ ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32));
+ ASM_EMIT_BELONG(f, "0x%08x",
+ (unsigned int)(re->re.address & 0xffffffff));
+ ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32));
+ ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff));
}
for (i = 0; i < reservenum; i++) {
fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
@@ -524,7 +543,9 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
emit_label(f, symprefix, "struct_start");
flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi);
- fprintf(f, "\t.long\tFDT_END\n");
+
+ fprintf(f, "\t/* FDT_END */\n");
+ asm_emit_cell(f, FDT_END);
emit_label(f, symprefix, "struct_end");
emit_label(f, symprefix, "strings_start");
@@ -601,7 +622,7 @@ static char *flat_read_string(struct inbuf *inb)
len++;
} while ((*p++) != '\0');
- str = strdup(inb->ptr);
+ str = xstrdup(inb->ptr);
inb->ptr += len;
@@ -643,7 +664,7 @@ static char *flat_read_stringtable(struct inbuf *inb, int offset)
p++;
}
- return strdup(inb->base + offset);
+ return xstrdup(inb->base + offset);
}
static struct property *flat_read_property(struct inbuf *dtbuf,
@@ -710,7 +731,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath)
if (!streq(ppath, "/"))
plen++;
- return strdup(cpath + plen);
+ return xstrdup(cpath + plen);
}
static struct node *unflatten_tree(struct inbuf *dtbuf,
diff --git a/fstree.c b/fstree.c
index 766b269..7aee982 100644
--- a/fstree.c
+++ b/fstree.c
@@ -58,7 +58,7 @@ static struct node *read_fstree(const char *dirname)
"WARNING: Cannot open %s: %s\n",
tmpnam, strerror(errno));
} else {
- prop = build_property(strdup(de->d_name),
+ prop = build_property(xstrdup(de->d_name),
data_copy_file(pfile,
st.st_size),
NULL);
@@ -69,7 +69,7 @@ static struct node *read_fstree(const char *dirname)
struct node *newchild;
newchild = read_fstree(tmpnam);
- newchild = name_node(newchild, strdup(de->d_name),
+ newchild = name_node(newchild, xstrdup(de->d_name),
NULL);
add_child(tree, newchild);
}
diff --git a/ftdump.c b/ftdump.c
index 01e61a4..bce6535 100644
--- a/ftdump.c
+++ b/ftdump.c
@@ -4,15 +4,18 @@
#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <fdt.h>
#include <libfdt_env.h>
+#define FTDUMP_BUF_SIZE 65536
+
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
-#define GET_CELL(p) (p += 4, *((uint32_t *)(p-4)))
+#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4)))
static int is_printable_string(const void *data, int len)
{
@@ -38,10 +41,10 @@ static int is_printable_string(const void *data, int len)
return 1;
}
-static void print_data(const void *data, int len)
+static void print_data(const char *data, int len)
{
int i;
- const uint8_t *s;
+ const char *p = data;
/* no data, don't print */
if (len == 0)
@@ -52,13 +55,13 @@ static void print_data(const void *data, int len)
} else if ((len % 4) == 0) {
printf(" = <");
for (i = 0; i < len; i += 4)
- printf("%08x%s", *((const uint32_t *)data + i),
+ printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)),
i < (len - 4) ? " " : "");
printf(">");
} else {
printf(" = [");
- for (i = 0, s = data; i < len; i++)
- printf("%02x%s", s[i], i < len - 1 ? " " : "");
+ for (i = 0; i < len; i++)
+ printf("%02x%s", *p++, i < len - 1 ? " " : "");
printf("]");
}
}
@@ -71,13 +74,12 @@ static void dump_blob(void *blob)
uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings);
struct fdt_reserve_entry *p_rsvmap =
(struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap);
- char *p_struct = (char *)blob + off_dt;
- char *p_strings = (char *)blob + off_str;
+ const char *p_struct = (const char *)blob + off_dt;
+ const char *p_strings = (const char *)blob + off_str;
uint32_t version = fdt32_to_cpu(bph->version);
uint32_t totalsize = fdt32_to_cpu(bph->totalsize);
uint32_t tag;
- char *p;
- char *s, *t;
+ const char *p, *s, *t;
int depth, sz, shift;
int i;
uint64_t addr, size;
@@ -85,6 +87,7 @@ static void dump_blob(void *blob)
depth = 0;
shift = 4;
+ printf("/dts-v1/;\n");
printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
printf("// off_dt_struct:\t0x%x\n", off_dt);
@@ -167,7 +170,7 @@ static void dump_blob(void *blob)
int main(int argc, char *argv[])
{
FILE *fp;
- char buf[16384]; /* 16k max */
+ char *buf;
int size;
if (argc < 2) {
@@ -175,15 +178,25 @@ int main(int argc, char *argv[])
return 5;
}
- fp = fopen(argv[1], "rb");
- if (fp == NULL) {
- fprintf(stderr, "unable to open %s\n", argv[1]);
+ if (strcmp(argv[1], "-") == 0) {
+ fp = stdin;
+ } else {
+ fp = fopen(argv[1], "rb");
+ if (fp == NULL) {
+ fprintf(stderr, "unable to open %s\n", argv[1]);
+ return 10;
+ }
+ }
+
+ buf = malloc(FTDUMP_BUF_SIZE);
+ if (!buf) {
+ fprintf(stderr, "Couldn't allocate %d byte buffer\n", FTDUMP_BUF_SIZE);
return 10;
}
- size = fread(buf, 1, sizeof(buf), fp);
- if (size == sizeof(buf)) { /* too large */
- fprintf(stderr, "file too large\n");
+ size = fread(buf, 1, FTDUMP_BUF_SIZE, fp);
+ if (size == FTDUMP_BUF_SIZE) {
+ fprintf(stderr, "file too large (maximum is %d bytes)\n", FTDUMP_BUF_SIZE);
return 10;
}
diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt
index 6c42acf..341c803 100644
--- a/libfdt/Makefile.libfdt
+++ b/libfdt/Makefile.libfdt
@@ -4,5 +4,6 @@
# be easily embeddable into other systems of Makefiles.
#
LIBFDT_INCLUDES = fdt.h libfdt.h
+LIBFDT_VERSION = version.lds
LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
diff --git a/libfdt/fdt.c b/libfdt/fdt.c
index 2acaec5..b1130c2 100644
--- a/libfdt/fdt.c
+++ b/libfdt/fdt.c
@@ -74,7 +74,7 @@ int fdt_check_header(const void *fdt)
return 0;
}
-const void *fdt_offset_ptr(const void *fdt, int offset, int len)
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
const char *p;
@@ -90,42 +90,53 @@ const void *fdt_offset_ptr(const void *fdt, int offset, int len)
return p;
}
-uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
+uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
const uint32_t *tagp, *lenp;
uint32_t tag;
+ int offset = startoffset;
const char *p;
- if (offset % FDT_TAGSIZE)
- return -1;
-
+ *nextoffset = -FDT_ERR_TRUNCATED;
tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
- if (! tagp)
+ if (!tagp)
return FDT_END; /* premature end */
tag = fdt32_to_cpu(*tagp);
offset += FDT_TAGSIZE;
+ *nextoffset = -FDT_ERR_BADSTRUCTURE;
switch (tag) {
case FDT_BEGIN_NODE:
/* skip name */
do {
p = fdt_offset_ptr(fdt, offset++, 1);
} while (p && (*p != '\0'));
- if (! p)
- return FDT_END;
+ if (!p)
+ return FDT_END; /* premature end */
break;
+
case FDT_PROP:
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
- if (! lenp)
- return FDT_END;
- /* skip name offset, length and value */
- offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
+ if (!lenp)
+ return FDT_END; /* premature end */
+ /* skip-name offset, length and value */
+ offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ + fdt32_to_cpu(*lenp);
+ break;
+
+ case FDT_END:
+ case FDT_END_NODE:
+ case FDT_NOP:
break;
+
+ default:
+ return FDT_END;
}
- if (nextoffset)
- *nextoffset = FDT_TAGALIGN(offset);
+ if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
+ return FDT_END; /* premature end */
+ *nextoffset = FDT_TAGALIGN(offset);
return tag;
}
@@ -162,15 +173,16 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
break;
case FDT_END_NODE:
- if (depth)
- (*depth)--;
+ if (depth && ((--(*depth)) < 0))
+ return nextoffset;
break;
case FDT_END:
- return -FDT_ERR_NOTFOUND;
-
- default:
- return -FDT_ERR_BADSTRUCTURE;
+ if ((nextoffset >= 0)
+ || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth))
+ return -FDT_ERR_NOTFOUND;
+ else
+ return nextoffset;
}
} while (tag != FDT_BEGIN_NODE);
diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
index 129b532..951cc74 100644
--- a/libfdt/fdt_ro.c
+++ b/libfdt/fdt_ro.c
@@ -80,6 +80,14 @@ const char *fdt_string(const void *fdt, int stroffset)
return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
}
+static int _fdt_string_eq(const void *fdt, int stroffset,
+ const char *s, int len)
+{
+ const char *p = fdt_string(fdt, stroffset);
+
+ return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+}
+
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{
FDT_CHECK_HEADER(fdt);
@@ -105,15 +113,14 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
FDT_CHECK_HEADER(fdt);
for (depth = 0;
- offset >= 0;
- offset = fdt_next_node(fdt, offset, &depth)) {
- if (depth < 0)
- return -FDT_ERR_NOTFOUND;
- else if ((depth == 1)
- && _fdt_nodename_eq(fdt, offset, name, namelen))
+ (offset >= 0) && (depth >= 0);
+ offset = fdt_next_node(fdt, offset, &depth))
+ if ((depth == 1)
+ && _fdt_nodename_eq(fdt, offset, name, namelen))
return offset;
- }
+ if (depth < 0)
+ return -FDT_ERR_NOTFOUND;
return offset; /* error */
}
@@ -131,8 +138,20 @@ int fdt_path_offset(const void *fdt, const char *path)
FDT_CHECK_HEADER(fdt);
- if (*path != '/')
- return -FDT_ERR_BADPATH;
+ /* see if we have an alias */
+ if (*path != '/') {
+ const char *q = strchr(path, '/');
+
+ if (!q)
+ q = end;
+
+ p = fdt_get_alias_namelen(fdt, p, q - p);
+ if (!p)
+ return -FDT_ERR_BADPATH;
+ offset = fdt_path_offset(fdt, p);
+
+ p = q;
+ }
while (*p) {
const char *q;
@@ -175,13 +194,13 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
return NULL;
}
-const struct fdt_property *fdt_get_property(const void *fdt,
- int nodeoffset,
- const char *name, int *lenp)
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+ int nodeoffset,
+ const char *name,
+ int namelen, int *lenp)
{
uint32_t tag;
const struct fdt_property *prop;
- int namestroff;
int offset, nextoffset;
int err;
@@ -196,38 +215,24 @@ const struct fdt_property *fdt_get_property(const void *fdt,
tag = fdt_next_tag(fdt, offset, &nextoffset);
switch (tag) {
case FDT_END:
- err = -FDT_ERR_TRUNCATED;
+ if (nextoffset < 0)
+ err = nextoffset;
+ else
+ /* FDT_END tag with unclosed nodes */
+ err = -FDT_ERR_BADSTRUCTURE;
goto fail;
- case FDT_BEGIN_NODE:
- case FDT_END_NODE:
- case FDT_NOP:
- break;
-
case FDT_PROP:
- err = -FDT_ERR_BADSTRUCTURE;
- prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
- if (! prop)
- goto fail;
- namestroff = fdt32_to_cpu(prop->nameoff);
- if (strcmp(fdt_string(fdt, namestroff), name) == 0) {
+ prop = _fdt_offset_ptr(fdt, offset);
+ if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
+ name, namelen)) {
/* Found it! */
- int len = fdt32_to_cpu(prop->len);
- prop = fdt_offset_ptr(fdt, offset,
- sizeof(*prop)+len);
- if (! prop)
- goto fail;
-
if (lenp)
- *lenp = len;
+ *lenp = fdt32_to_cpu(prop->len);
return prop;
}
break;
-
- default:
- err = -FDT_ERR_BADSTRUCTURE;
- goto fail;
}
} while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
@@ -238,30 +243,66 @@ const struct fdt_property *fdt_get_property(const void *fdt,
return NULL;
}
-const void *fdt_getprop(const void *fdt, int nodeoffset,
- const char *name, int *lenp)
+const struct fdt_property *fdt_get_property(const void *fdt,
+ int nodeoffset,
+ const char *name, int *lenp)
+{
+ return fdt_get_property_namelen(fdt, nodeoffset, name,
+ strlen(name), lenp);
+}
+
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+ const char *name, int namelen, int *lenp)
{
const struct fdt_property *prop;
- prop = fdt_get_property(fdt, nodeoffset, name, lenp);
+ prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
if (! prop)
return NULL;
return prop->data;
}
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+ const char *name, int *lenp)
+{
+ return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
+}
+
uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
{
const uint32_t *php;
int len;
- php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
- if (!php || (len != sizeof(*php)))
- return 0;
+ /* FIXME: This is a bit sub-optimal, since we potentially scan
+ * over all the properties twice. */
+ php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
+ if (!php || (len != sizeof(*php))) {
+ php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
+ if (!php || (len != sizeof(*php)))
+ return 0;
+ }
return fdt32_to_cpu(*php);
}
+const char *fdt_get_alias_namelen(const void *fdt,
+ const char *name, int namelen)
+{
+ int aliasoffset;
+
+ aliasoffset = fdt_path_offset(fdt, "/aliases");
+ if (aliasoffset < 0)
+ return NULL;
+
+ return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
+}
+
+const char *fdt_get_alias(const void *fdt, const char *name)
+{
+ return fdt_get_alias_namelen(fdt, name, strlen(name));
+}
+
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
{
int pdepth = 0, p = 0;
@@ -276,9 +317,6 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
for (offset = 0, depth = 0;
(offset >= 0) && (offset <= nodeoffset);
offset = fdt_next_node(fdt, offset, &depth)) {
- if (pdepth < depth)
- continue; /* overflowed buffer */
-
while (pdepth > depth) {
do {
p--;
@@ -286,14 +324,16 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
pdepth--;
}
- name = fdt_get_name(fdt, offset, &namelen);
- if (!name)
- return namelen;
- if ((p + namelen + 1) <= buflen) {
- memcpy(buf + p, name, namelen);
- p += namelen;
- buf[p++] = '/';
- pdepth++;
+ if (pdepth >= depth) {
+ name = fdt_get_name(fdt, offset, &namelen);
+ if (!name)
+ return namelen;
+ if ((p + namelen + 1) <= buflen) {
+ memcpy(buf + p, name, namelen);
+ p += namelen;
+ buf[p++] = '/';
+ pdepth++;
+ }
}
if (offset == nodeoffset) {
@@ -303,7 +343,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
if (p > 1) /* special case so that root path is "/", not "" */
p--;
buf[p] = '\0';
- return p;
+ return 0;
}
}
@@ -401,14 +441,31 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
{
+ int offset;
+
if ((phandle == 0) || (phandle == -1))
return -FDT_ERR_BADPHANDLE;
- phandle = cpu_to_fdt32(phandle);
- return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
- &phandle, sizeof(phandle));
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we
+ * potentially scan each property of a node in
+ * fdt_get_phandle(), then if 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 implement approach;
+ * performance can come later. */
+ for (offset = fdt_next_node(fdt, -1, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ if (fdt_get_phandle(fdt, offset) == phandle)
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
}
-int _stringlist_contains(const char *strlist, int listlen, const char *str)
+static int _fdt_stringlist_contains(const char *strlist, int listlen,
+ const char *str)
{
int len = strlen(str);
const char *p;
@@ -434,7 +491,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
if (!prop)
return len;
- if (_stringlist_contains(prop, len, compatible))
+ if (_fdt_stringlist_contains(prop, len, compatible))
return 0;
else
return 1;
diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c
index 8e7ec4c..994037b 100644
--- a/libfdt/fdt_rw.c
+++ b/libfdt/fdt_rw.c
@@ -406,6 +406,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
struct_size = 0;
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
;
+ if (struct_size < 0)
+ return struct_size;
}
if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c
index 698329e..55ebebf 100644
--- a/libfdt/fdt_sw.c
+++ b/libfdt/fdt_sw.c
@@ -70,7 +70,7 @@ static int _fdt_sw_check_header(void *fdt)
return err; \
}
-static void *_fdt_grab_space(void *fdt, int len)
+static void *_fdt_grab_space(void *fdt, size_t len)
{
int offset = fdt_size_dt_struct(fdt);
int spaceleft;
@@ -82,7 +82,7 @@ static void *_fdt_grab_space(void *fdt, int len)
return NULL;
fdt_set_size_dt_struct(fdt, offset + len);
- return fdt_offset_ptr_w(fdt, offset, len);
+ return _fdt_offset_ptr_w(fdt, offset);
}
int fdt_create(void *buf, int bufsize)
@@ -237,18 +237,17 @@ int fdt_finish(void *fdt)
while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
if (tag == FDT_PROP) {
struct fdt_property *prop =
- fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
+ _fdt_offset_ptr_w(fdt, offset);
int nameoff;
- if (! prop)
- return -FDT_ERR_BADSTRUCTURE;
-
nameoff = fdt32_to_cpu(prop->nameoff);
nameoff += fdt_size_dt_strings(fdt);
prop->nameoff = cpu_to_fdt32(nameoff);
}
offset = nextoffset;
}
+ if (nextoffset < 0)
+ return nextoffset;
/* Finally, adjust the header */
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c
index a4652c6..6025fa1 100644
--- a/libfdt/fdt_wip.c
+++ b/libfdt/fdt_wip.c
@@ -94,41 +94,14 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
return 0;
}
-int _fdt_node_end_offset(void *fdt, int nodeoffset)
+int _fdt_node_end_offset(void *fdt, int offset)
{
- int level = 0;
- uint32_t tag;
- int offset, nextoffset;
-
- tag = fdt_next_tag(fdt, nodeoffset, &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 offset;
-
- case FDT_BEGIN_NODE:
- level++;
- break;
-
- case FDT_END_NODE:
- level--;
- break;
-
- case FDT_PROP:
- case FDT_NOP:
- break;
-
- default:
- return -FDT_ERR_BADSTRUCTURE;
- }
- } while (level >= 0);
-
- return nextoffset;
+ int depth = 0;
+
+ while ((offset >= 0) && (depth >= 0))
+ offset = fdt_next_node(fdt, offset, &depth);
+
+ return offset;
}
int fdt_nop_node(void *fdt, int nodeoffset)
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
index ce80e4f..18de52b 100644
--- a/libfdt/libfdt.h
+++ b/libfdt/libfdt.h
@@ -122,7 +122,7 @@
/* Low-level functions (you probably don't need these) */
/**********************************************************************/
-const void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
{
return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
@@ -156,7 +156,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth);
#define __fdt_set_hdr(name) \
static inline void fdt_set_##name(void *fdt, uint32_t val) \
{ \
- struct fdt_header *fdth = fdt; \
+ struct fdt_header *fdth = (struct fdt_header*)fdt; \
fdth->name = cpu_to_fdt32(val); \
}
__fdt_set_hdr(magic);
@@ -343,6 +343,22 @@ int fdt_path_offset(const void *fdt, const char *path);
const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
/**
+ * fdt_get_property_namelen - find a property based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_get_property_namelen(), but only examine the first
+ * namelen characters of name for matching the property name.
+ */
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+ int nodeoffset,
+ const char *name,
+ int namelen, int *lenp);
+
+/**
* fdt_get_property - find a given property in a given node
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to find
@@ -380,6 +396,20 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
}
/**
+ * fdt_getprop_namelen - get property value based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_getprop(), but only examine the first namelen
+ * characters of name for matching the property name.
+ */
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+ const char *name, int namelen, int *lenp);
+
+/**
* fdt_getprop - retrieve the value of a given property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to find
@@ -429,6 +459,32 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
/**
+ * fdt_get_alias_namelen - get alias based on substring
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_get_alias(), but only examine the first namelen
+ * characters of name for matching the alias name.
+ */
+const char *fdt_get_alias_namelen(const void *fdt,
+ const char *name, int namelen);
+
+/**
+ * fdt_get_alias - retreive the path referenced by a given alias
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ *
+ * fdt_get_alias() retrieves the value of a given alias. That is, the
+ * value of the property named 'name' in the node /aliases.
+ *
+ * returns:
+ * a pointer to the expansion of the alias named 'name', of it exists
+ * NULL, if the given alias or the /aliases node does not exist
+ */
+const char *fdt_get_alias(const void *fdt, const char *name);
+
+/**
* fdt_get_path - determine the full path of a node
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose path to find
diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h
index 46eb93e..d2dcbd6 100644
--- a/libfdt/libfdt_internal.h
+++ b/libfdt/libfdt_internal.h
@@ -62,7 +62,6 @@
return err; \
}
-uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
int _fdt_check_node_offset(const void *fdt, int offset);
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
int _fdt_node_end_offset(void *fdt, int nodeoffset);
diff --git a/libfdt/version.lds b/libfdt/version.lds
new file mode 100644
index 0000000..3c3994e
--- /dev/null
+++ b/libfdt/version.lds
@@ -0,0 +1,54 @@
+LIBFDT_1.2 {
+ global:
+ fdt_next_node;
+ fdt_check_header;
+ fdt_move;
+ fdt_string;
+ fdt_num_mem_rsv;
+ fdt_get_mem_rsv;
+ fdt_subnode_offset_namelen;
+ fdt_subnode_offset;
+ fdt_path_offset;
+ fdt_get_name;
+ fdt_get_property_namelen;
+ fdt_get_property;
+ fdt_getprop_namelen;
+ fdt_getprop;
+ fdt_get_phandle;
+ fdt_get_alias_namelen;
+ fdt_get_alias;
+ fdt_get_path;
+ fdt_supernode_atdepth_offset;
+ fdt_node_depth;
+ fdt_parent_offset;
+ fdt_node_offset_by_prop_value;
+ fdt_node_offset_by_phandle;
+ fdt_node_check_compatible;
+ fdt_node_offset_by_compatible;
+ fdt_setprop_inplace;
+ fdt_nop_property;
+ fdt_nop_node;
+ fdt_create;
+ fdt_add_reservemap_entry;
+ fdt_finish_reservemap;
+ fdt_begin_node;
+ fdt_property;
+ fdt_end_node;
+ fdt_finish;
+ fdt_open_into;
+ fdt_pack;
+ fdt_add_mem_rsv;
+ fdt_del_mem_rsv;
+ fdt_set_name;
+ fdt_setprop;
+ fdt_delprop;
+ fdt_add_subnode_namelen;
+ fdt_add_subnode;
+ fdt_del_node;
+ fdt_strerror;
+ fdt_offset_ptr;
+ fdt_next_tag;
+
+ local:
+ *;
+};
diff --git a/livetree.c b/livetree.c
index 0ca3de5..9a482a8 100644
--- a/livetree.c
+++ b/livetree.c
@@ -293,16 +293,28 @@ cell_t get_node_phandle(struct node *root, struct node *node)
if ((node->phandle != 0) && (node->phandle != -1))
return node->phandle;
- assert(! get_property(node, "linux,phandle"));
-
while (get_node_by_phandle(root, phandle))
phandle++;
node->phandle = phandle;
- add_property(node,
- build_property("linux,phandle",
- data_append_cell(empty_data, phandle),
- NULL));
+
+ if (!get_property(node, "linux,phandle")
+ && (phandle_format & PHANDLE_LEGACY))
+ add_property(node,
+ build_property("linux,phandle",
+ data_append_cell(empty_data, phandle),
+ NULL));
+
+ if (!get_property(node, "phandle")
+ && (phandle_format & PHANDLE_EPAPR))
+ add_property(node,
+ build_property("phandle",
+ data_append_cell(empty_data, phandle),
+ NULL));
+
+ /* If the node *does* have a phandle property, we must
+ * be dealing with a self-referencing phandle, which will be
+ * fixed up momentarily in the caller */
return node->phandle;
}
diff --git a/srcpos.c b/srcpos.c
index 9641b76..8bb0c02 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -17,18 +17,40 @@
* USA
*/
+#define _GNU_SOURCE
+
+#include <stdio.h>
+
#include "dtc.h"
#include "srcpos.h"
+
/*
* Like yylineno, this is the current open file pos.
*/
-
struct dtc_file *srcpos_file;
-static int dtc_open_one(struct dtc_file *file,
- const char *search,
- const char *fname)
+/*
+ * The empty source position.
+ */
+
+struct dtc_file dtc_empty_file = {
+ .dir = NULL,
+ .name = "<no file>",
+ .file = NULL
+};
+
+srcpos srcpos_empty = {
+ .first_line = 0,
+ .first_column = 0,
+ .last_line = 0,
+ .last_column = 0,
+ .file = &dtc_empty_file
+};
+
+
+static int
+dtc_open_one(struct dtc_file *file, const char *search, const char *fname)
{
char *fullname;
@@ -39,7 +61,7 @@ static int dtc_open_one(struct dtc_file *file,
strcat(fullname, "/");
strcat(fullname, fname);
} else {
- fullname = strdup(fname);
+ fullname = xstrdup(fname);
}
file->file = fopen(fullname, "r");
@@ -53,8 +75,8 @@ static int dtc_open_one(struct dtc_file *file,
}
-struct dtc_file *dtc_open_file(const char *fname,
- const struct search_path *search)
+struct dtc_file *
+dtc_open_file(const char *fname, const struct search_path *search)
{
static const struct search_path default_search = { NULL, NULL, NULL };
@@ -85,7 +107,7 @@ struct dtc_file *dtc_open_file(const char *fname,
if (!file->file)
goto fail;
- file->name = strdup(fname);
+ file->name = xstrdup(fname);
return file;
}
@@ -106,11 +128,113 @@ fail:
die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
}
-void dtc_close_file(struct dtc_file *file)
+
+void
+dtc_close_file(struct dtc_file *file)
{
if (fclose(file->file))
die("Error closing \"%s\": %s\n", file->name, strerror(errno));
+}
+
+
+srcpos *
+srcpos_copy(srcpos *pos)
+{
+ srcpos *pos_new;
+
+ pos_new = xmalloc(sizeof(srcpos));
+ memcpy(pos_new, pos, sizeof(srcpos));
+
+ return pos_new;
+}
+
+
+
+void
+srcpos_dump(srcpos *pos)
+{
+ printf("file : \"%s\"\n",
+ pos->file ? (char *) pos->file : "<no file>");
+ printf("first_line : %d\n", pos->first_line);
+ printf("first_column: %d\n", pos->first_column);
+ printf("last_line : %d\n", pos->last_line);
+ printf("last_column : %d\n", pos->last_column);
+ printf("file : %s\n", pos->file->name);
+}
+
+
+char *
+srcpos_string(srcpos *pos)
+{
+ const char *fname;
+ char col_buf[100];
+ char *pos_str;
+
+ if (!pos) {
+ fname = "<no-file>";
+ } else if (pos->file->name) {
+ fname = pos->file->name;
+ if (strcmp(fname, "-") == 0)
+ fname = "stdin";
+ } else {
+ fname = "<no-file>";
+ }
+
+ if (pos->first_line == pos->last_line) {
+ if (pos->first_column == pos->last_column) {
+ snprintf(col_buf, sizeof(col_buf),
+ "%d:%d",
+ pos->first_line, pos->first_column);
+ } else {
+ snprintf(col_buf, sizeof(col_buf),
+ "%d:%d-%d",
+ pos->first_line,
+ pos->first_column, pos->last_column);
+ }
+
+ } else {
+ snprintf(col_buf, sizeof(col_buf),
+ "%d:%d - %d:%d",
+ pos->first_line, pos->first_column,
+ pos->last_line, pos->last_column);
+ }
+
+ if (asprintf(&pos_str, "%s %s", fname, col_buf) == -1)
+ return "<unknown source position?";
+
+ return pos_str;
+}
+
+
+void
+srcpos_error(srcpos *pos, char const *fmt, ...)
+{
+ const char *srcstr;
+ va_list va;
+ va_start(va, fmt);
+
+ srcstr = srcpos_string(pos);
+
+ fprintf(stderr, "Error: %s ", srcstr);
+ vfprintf(stderr, fmt, va);
+ fprintf(stderr, "\n");
+
+ va_end(va);
+}
+
+
+void
+srcpos_warn(srcpos *pos, char const *fmt, ...)
+{
+ const char *srcstr;
+ va_list va;
+ va_start(va, fmt);
+
+ srcstr = srcpos_string(pos);
+
+ fprintf(stderr, "Warning: %s ", srcstr);
+ vfprintf(stderr, fmt, va);
+ fprintf(stderr, "\n");
- free(file->dir);
- free(file);
+ va_end(va);
}
diff --git a/srcpos.h b/srcpos.h
index e17c7c0..a6d0077 100644
--- a/srcpos.h
+++ b/srcpos.h
@@ -17,6 +17,9 @@
* USA
*/
+#ifndef _SRCPOS_H_
+#define _SRCPOS_H_
+
/*
* Augment the standard YYLTYPE with a filenum index into an
* array of all opened filenames.
@@ -69,9 +72,14 @@ typedef struct YYLTYPE {
while (YYID (0))
+typedef YYLTYPE srcpos;
-extern void yyerror(char const *);
-extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2)));
+/*
+ * Fictional source position used for IR nodes that are
+ * created without otherwise knowing a true source position.
+ * For example,constant definitions from the command line.
+ */
+extern srcpos srcpos_empty;
extern struct dtc_file *srcpos_file;
@@ -83,3 +91,14 @@ struct search_path {
extern struct dtc_file *dtc_open_file(const char *fname,
const struct search_path *search);
extern void dtc_close_file(struct dtc_file *file);
+
+extern srcpos *srcpos_copy(srcpos *pos);
+extern char *srcpos_string(srcpos *pos);
+extern void srcpos_dump(srcpos *pos);
+
+extern void srcpos_error(srcpos *pos, char const *, ...)
+ __attribute__((format(printf, 2, 3)));
+extern void srcpos_warn(srcpos *pos, char const *, ...)
+ __attribute__((format(printf, 2, 3)));
+
+#endif /* _SRCPOS_H_ */
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index 704c95d..ac21ade 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -4,20 +4,26 @@ LIB_TESTS_L = get_mem_rsv \
get_path supernode_atdepth_offset parent_offset \
node_offset_by_prop_value node_offset_by_phandle \
node_check_compatible node_offset_by_compatible \
+ get_alias \
notfound \
setprop_inplace nop_property nop_node \
sw_tree1 \
move_and_save mangle-layout nopulate \
open_pack rw_tree1 set_name setprop del_property del_node \
- string_escapes references path-references boot-cpuid incbin \
+ string_escapes references path-references phandle_format \
+ boot-cpuid incbin \
+ extra-terminating-null \
dtbs_equal_ordered \
- add_subnode_with_nops
+ add_subnode_with_nops path_offset_aliases
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
LIBTREE_TESTS_L = truncated_property
LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%)
-TESTS = $(LIB_TESTS) $(LIBTREE_TESTS)
+DL_LIB_TESTS_L = asm_tree_dump value-labels
+DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%)
+
+TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS)
TESTS_TREES_L = test_tree1.dtb
TESTS_TREES = $(TESTS_TREES_L:%=$(TESTS_PREFIX)%)
@@ -28,16 +34,19 @@ TESTS_DEPFILES = $(TESTS:%=%.d) \
$(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d)
TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts *.dtsv1 tmp.*
-TESTS_CLEANFILES = $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%)
-
-BIN += $(TESTS) $(TESTS_PREFIX)dumptrees
+TESTS_CLEANFILES_L += dumptrees
+TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%)
.PHONY: tests
tests: $(TESTS) $(TESTS_TREES)
-$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_lib)
+$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_archive)
+
+$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o $(LIBFDT_archive)
+ @$(VECHO) LD [libdl] $@
+ $(LINK.c) -o $@ $^ -ldl
-$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o $(LIBFDT_lib)
+$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o $(LIBFDT_archive)
$(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o
diff --git a/tests/aliases.dts b/tests/aliases.dts
new file mode 100644
index 0000000..39d88ff
--- /dev/null
+++ b/tests/aliases.dts
@@ -0,0 +1,21 @@
+/dts-v1/;
+
+/ {
+ aliases {
+ s1 = &sub1;
+ ss1 = &subsub1;
+ sss1 = &subsubsub1;
+ };
+
+ sub1: subnode@1 {
+ compatible = "subnode1";
+
+ subsub1: subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+
+ subsubsub1: subsubsubnode {
+ compatible = "subsubsubnode1", "subsubsubnode";
+ };
+ };
+ };
+};
diff --git a/tests/asm_tree_dump.c b/tests/asm_tree_dump.c
new file mode 100644
index 0000000..5ff5087
--- /dev/null
+++ b/tests/asm_tree_dump.c
@@ -0,0 +1,62 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Tests if an asm tree built into a shared object matches a given dtb
+ * Copyright (C) 2008 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include <dlfcn.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *sohandle;
+ void *fdt;
+ int err;
+
+ test_init(argc, argv);
+ if (argc != 3)
+ CONFIG("Usage: %s <so file> <dtb file>", argv[0]);
+
+ sohandle = dlopen(argv[1], RTLD_NOW);
+ if (!sohandle)
+ FAIL("Couldn't dlopen() %s", argv[1]);
+
+ fdt = dlsym(sohandle, "dt_blob_start");
+ if (!fdt)
+ FAIL("Couldn't locate \"dt_blob_start\" symbol in %s",
+ argv[1]);
+
+ err = fdt_check_header(fdt);
+ if (err != 0)
+ FAIL("%s contains invalid tree: %s", argv[1],
+ fdt_strerror(err));
+
+ save_blob(argv[2], fdt);
+
+ PASS();
+}
diff --git a/tests/base01.dts b/tests/base01.dts
index f84bc49..97a5dd5 100644
--- a/tests/base01.dts
+++ b/tests/base01.dts
@@ -1,3 +1,5 @@
+/dts-v1/;
+
/ {
model = "SomeModel";
compatible = "Nothing";
@@ -6,26 +8,26 @@
memory@0 {
device_type = "memory";
- reg = <00000000 00000000 00000000 20000000>;
+ reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
- d10 = <d# 10>; // hex: 0xa
- d23 = <d# 23>; // hex: 0x17
- b101 = <b# 101>; // hex: 0x5
- o17 = <o# 17>; // hex: 0xf
- hd00d = <h# d00d>; // hex: 0xd00d
+ d10 = < 10>; // hex: 0xa
+ d23 = < 23>; // hex: 0x17
+ b101 = < 0x5>; // hex: 0x5
+ o17 = < 017>; // hex: 0xf
+ hd00d = < 0xd00d>; // hex: 0xd00d
// hex: 0x4d2 0x163e 0x2334 0xd80
- stuff = <d# 1234 d# 5678 d# 9012 d# 3456>;
+ stuff = < 1234 5678 9012 3456>;
- bad-d-1 = <d# abc123>; // Hrm. 0
- bad-d-2 = <d# 123456789012345>;
- bad-o-1 = <o# 891>;
- bad-o-2 = <o# 123456123456>;
+ bad-d-1 = < 0>; // Hrm. 0
+ bad-d-2 = < 123456789012345>;
+ bad-o-1 = < 00>;
+ bad-o-2 = < 0123456123456>;
};
};
diff --git a/tests/data.S b/tests/data.S
new file mode 100644
index 0000000..86ad539
--- /dev/null
+++ b/tests/data.S
@@ -0,0 +1,3 @@
+/* Used in combination with dtc -Oasm output to embed
+ * a device tree in the data section of a .o */
+ .data
diff --git a/tests/dtbs_equal_ordered.c b/tests/dtbs_equal_ordered.c
index a0b42ae..ed9278c 100644
--- a/tests/dtbs_equal_ordered.c
+++ b/tests/dtbs_equal_ordered.c
@@ -29,7 +29,7 @@
#include "tests.h"
#include "testdata.h"
-void compare_mem_rsv(const void *fdt1, const void *fdt2)
+static void compare_mem_rsv(const void *fdt1, const void *fdt2)
{
int i;
uint64_t addr1, size1, addr2, size2;
@@ -56,7 +56,7 @@ void compare_mem_rsv(const void *fdt1, const void *fdt2)
}
}
-void compare_structure(const void *fdt1, const void *fdt2)
+static void compare_structure(const void *fdt1, const void *fdt2)
{
int nextoffset1 = 0, nextoffset2 = 0;
int offset1, offset2;
diff --git a/tests/empty.dts b/tests/empty.dts
index 336d7a2..e160dad 100644
--- a/tests/empty.dts
+++ b/tests/empty.dts
@@ -1,2 +1,4 @@
+/dts-v1/;
+
/ {
};
diff --git a/tests/escapes.dts b/tests/escapes.dts
index f1b8dbc..e05ab46 100644
--- a/tests/escapes.dts
+++ b/tests/escapes.dts
@@ -1,3 +1,5 @@
+/dts-v1/;
+
/ {
compatible = "test_string_escapes";
escape-str = "nastystring: \a\b\t\n\v\f\r\\\"";
diff --git a/tests/extra-terminating-null.c b/tests/extra-terminating-null.c
new file mode 100644
index 0000000..bb71b1a
--- /dev/null
+++ b/tests/extra-terminating-null.c
@@ -0,0 +1,59 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for properties with more than one terminating null
+ * Copyright (C) 2009 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+void check_extranull(void *fdt, const char *prop, const char *str, int numnulls)
+{
+ int len = strlen(str);
+ char checkbuf[len+numnulls];
+
+ memset(checkbuf, 0, sizeof(checkbuf));
+ memcpy(checkbuf, TEST_STRING_1, len);
+
+ check_getprop(fdt, 0, prop, len+numnulls, checkbuf);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+
+ fdt = load_blob_arg(argc, argv);
+
+ check_extranull(fdt, "extranull0", TEST_STRING_1, 1);
+ check_extranull(fdt, "extranull1,1", TEST_STRING_1, 2);
+ check_extranull(fdt, "extranull1,2", TEST_STRING_1, 2);
+ check_extranull(fdt, "extranull2,1", TEST_STRING_1, 3);
+ check_extranull(fdt, "extranull2,2", TEST_STRING_1, 3);
+ check_extranull(fdt, "extranull2,3", TEST_STRING_1, 3);
+ check_extranull(fdt, "extranull2,4", TEST_STRING_1, 3);
+
+ PASS();
+}
diff --git a/tests/extra-terminating-null.dts b/tests/extra-terminating-null.dts
new file mode 100644
index 0000000..b6cc19c
--- /dev/null
+++ b/tests/extra-terminating-null.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/ {
+ extranull0 = "hello world";
+ extranull1,1 = "hello world\0";
+ extranull1,2 = "hello world", "";
+ extranull2,1 = "hello world\0\0";
+ extranull2,2 = "hello world", "", "";
+ extranull2,3 = "hello world\0", "";
+ extranull2,4 = "hello world", "\0";
+};
diff --git a/tests/get_alias.c b/tests/get_alias.c
new file mode 100644
index 0000000..8eeaee4
--- /dev/null
+++ b/tests/get_alias.c
@@ -0,0 +1,58 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_get_alias()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+void check_alias(void *fdt, const char *path, const char *alias)
+{
+ const char *aliaspath;
+
+ aliaspath = fdt_get_alias(fdt, alias);
+
+ if (path && !aliaspath)
+ FAIL("fdt_get_alias(%s) failed\n", alias);
+
+ if (strcmp(aliaspath, path) != 0)
+ FAIL("fdt_get_alias(%s) returned %s instead of %s\n",
+ alias, aliaspath, path);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_alias(fdt, "/subnode@1", "s1");
+ check_alias(fdt, "/subnode@1/subsubnode", "ss1");
+ check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "sss1");
+
+ PASS();
+}
diff --git a/tests/get_name.c b/tests/get_name.c
index 22003b4..0262a12 100644
--- a/tests/get_name.c
+++ b/tests/get_name.c
@@ -28,7 +28,7 @@
#include "tests.h"
#include "testdata.h"
-void check_name(void *fdt, const char *path)
+static void check_name(void *fdt, const char *path)
{
int offset;
const char *getname, *getname2, *checkname;
diff --git a/tests/get_path.c b/tests/get_path.c
index 0d208bb..1e05f7c 100644
--- a/tests/get_path.c
+++ b/tests/get_path.c
@@ -30,7 +30,7 @@
#define POISON ('\xff')
-void check_path_buf(void *fdt, const char *path, int pathlen, int buflen)
+static void check_path_buf(void *fdt, const char *path, int pathlen, int buflen)
{
int offset;
char buf[buflen+1];
@@ -43,6 +43,8 @@ void check_path_buf(void *fdt, const char *path, int pathlen, int buflen)
memset(buf, POISON, sizeof(buf)); /* poison the buffer */
len = fdt_get_path(fdt, offset, buf, buflen);
+ verbose_printf("get_path() %s -> %d -> %s\n", path, offset, buf);
+
if (buflen <= pathlen) {
if (len != -FDT_ERR_NOSPACE)
FAIL("fdt_get_path([%d bytes]) returns %d with "
@@ -51,9 +53,9 @@ void check_path_buf(void *fdt, const char *path, int pathlen, int buflen)
if (len < 0)
FAIL("fdt_get_path([%d bytes]): %s", buflen,
fdt_strerror(len));
- if (len != pathlen)
- FAIL("fdt_get_path([%d bytes]) reports length %d "
- "instead of %d", buflen, len, pathlen);
+ if (len != 0)
+ FAIL("fdt_get_path([%d bytes]) returns %d "
+ "instead of 0", buflen, len);
if (strcmp(buf, path) != 0)
FAIL("fdt_get_path([%d bytes]) returns \"%s\" "
"instead of \"%s\"", buflen, buf, path);
@@ -63,13 +65,15 @@ void check_path_buf(void *fdt, const char *path, int pathlen, int buflen)
FAIL("fdt_get_path([%d bytes]) overran buffer", buflen);
}
-void check_path(void *fdt, const char *path)
+static void check_path(void *fdt, const char *path)
{
int pathlen = strlen(path);
check_path_buf(fdt, path, pathlen, 1024);
check_path_buf(fdt, path, pathlen, pathlen+1);
check_path_buf(fdt, path, pathlen, pathlen);
+ check_path_buf(fdt, path, pathlen, 0);
+ check_path_buf(fdt, path, pathlen, 2);
}
int main(int argc, char *argv[])
diff --git a/tests/get_phandle.c b/tests/get_phandle.c
index f7650b8..5735733 100644
--- a/tests/get_phandle.c
+++ b/tests/get_phandle.c
@@ -28,7 +28,7 @@
#include "tests.h"
#include "testdata.h"
-void check_phandle(void *fdt, const char *path, uint32_t checkhandle)
+static void check_phandle(void *fdt, const char *path, uint32_t checkhandle)
{
int offset;
uint32_t phandle;
diff --git a/tests/incbin.c b/tests/incbin.c
index 5ab3508..76d8626 100644
--- a/tests/incbin.c
+++ b/tests/incbin.c
@@ -31,7 +31,7 @@
#define CHUNKSIZE 1024
-char *load_file(const char *name, int *len)
+static char *load_file(const char *name, int *len)
{
FILE *f;
char *buf = NULL;
diff --git a/tests/include1.dts b/tests/include1.dts
index 0c7f42e..5d59d83 100644
--- a/tests/include1.dts
+++ b/tests/include1.dts
@@ -15,9 +15,12 @@
prop-int = <123456789>;
/include/ "include8.dts"
- linux,phandle = <0x2001>;
+ phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};
+
+ ss2 {
+ };
};
};
diff --git a/tests/include7.dts b/tests/include7.dts
index fa726f9..dba5e47 100644
--- a/tests/include7.dts
+++ b/tests/include7.dts
@@ -6,4 +6,7 @@
compatible = "subsubnode1", "subsubnode";
prop-int = <0xdeadbeef>;
};
+
+ ss1 {
+ };
};
diff --git a/tests/label01.dts b/tests/label01.dts
index 372b17a..a895803 100644
--- a/tests/label01.dts
+++ b/tests/label01.dts
@@ -1,6 +1,8 @@
-/memreserve/ 1000000000000000 0000000002000000;
-memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff;
-/memreserve/ 0-13;
+/dts-v1/;
+
+/memreserve/ 0x1000000000000000 0x0000000002000000;
+memrsv2: /memreserve/ 0x2000000000000000 0x0100000000000000;
+/memreserve/ 0x0000000000000000 0x0000000000000014;
/ {
model = "MyBoardName";
@@ -9,28 +11,28 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff;
#size-cells = <2>;
cpus {
- linux,phandle = <1>;
+ linux,phandle = <0x1>;
#address-cells = <1>;
#size-cells = <0>;
PowerPC,970@0 {
name = "PowerPC,970";
device_type = "cpu";
- reg = <0>;
- clock-frequency = <5f5e1000>;
- timebase-frequency = <1FCA055>;
+ reg = <0x00000000>;
+ clock-frequency = <1600000000>;
+ timebase-frequency = <33333333>;
linux,boot-cpu;
- i-cache-size = <10000>;
- d-cache-size = <8000>;
+ i-cache-size = <65536>;
+ d-cache-size = <32768>;
};
PowerPC,970@1 {
name = "PowerPC,970";
device_type = "cpu";
- reg = <1>;
- clock-frequency = <5f5e1000>;
- timebase-frequency = <1FCA055>;
- i-cache-size = <10000>;
- d-cache-size = <8000>;
+ reg = <0x00000001>;
+ clock-frequency = <1600000000>;
+ timebase-frequency = <33333333>;
+ i-cache-size = <65536>;
+ d-cache-size = <32768>;
};
};
@@ -38,8 +40,8 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff;
node: randomnode {
prop: string = str: "foo", str_mid: "stuffstuff\t\t\t\n\n\n" str_end: ;
blob = [byte: 0a 0b 0c 0d byte_mid: de ea ad be ef byte_end: ];
- ref = < cell: &/memory@0 0 cell_mid: ffffffff cell_end: >;
- mixed = "abc", pre: [1234] post: , gap: < aligned: a b c>;
+ ref = < cell: &{/memory@0} 0x0 cell_mid: 0xffffffff cell_end: >;
+ mixed = "abc", pre: [1234] post: , gap: < aligned: 0xa 0xb 0xc>;
tricky1 = [61 lt1: 62 63 00];
subnode: child {
};
@@ -49,12 +51,12 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff;
memory@0 {
device_type = "memory";
- memreg: reg = <00000000 00000000 00000000 20000000>;
+ memreg: reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
};
chosen {
bootargs = "root=/dev/sda2";
- linux,platform = <00000600>;
+ linux,platform = <0x600>;
};
};
diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c
index bd6ac40..5be28b9 100644
--- a/tests/mangle-layout.c
+++ b/tests/mangle-layout.c
@@ -35,7 +35,7 @@ struct bufstate {
int size;
};
-void expand_buf(struct bufstate *buf, int newsize)
+static void expand_buf(struct bufstate *buf, int newsize)
{
buf->buf = realloc(buf->buf, newsize);
if (!buf->buf)
@@ -43,7 +43,7 @@ void expand_buf(struct bufstate *buf, int newsize)
buf->size = newsize;
}
-void new_header(struct bufstate *buf, int version, const void *fdt)
+static void new_header(struct bufstate *buf, int version, const void *fdt)
{
int hdrsize;
@@ -63,7 +63,7 @@ void new_header(struct bufstate *buf, int version, const void *fdt)
fdt_set_boot_cpuid_phys(buf->buf, fdt_boot_cpuid_phys(fdt));
}
-void add_block(struct bufstate *buf, int version, char block, const void *fdt)
+static void add_block(struct bufstate *buf, int version, char block, const void *fdt)
{
int align, size;
const void *src;
diff --git a/tests/node_check_compatible.c b/tests/node_check_compatible.c
index 04b6b40..23abbf5 100644
--- a/tests/node_check_compatible.c
+++ b/tests/node_check_compatible.c
@@ -29,7 +29,8 @@
#include "tests.h"
#include "testdata.h"
-void check_compatible(const void *fdt, const char *path, const char *compat)
+static void check_compatible(const void *fdt, const char *path,
+ const char *compat)
{
int offset, err;
diff --git a/tests/node_offset_by_compatible.c b/tests/node_offset_by_compatible.c
index 02e9874..2317930 100644
--- a/tests/node_offset_by_compatible.c
+++ b/tests/node_offset_by_compatible.c
@@ -29,7 +29,7 @@
#include "tests.h"
#include "testdata.h"
-void check_search(void *fdt, const char *compat, ...)
+static void check_search(void *fdt, const char *compat, ...)
{
va_list ap;
int offset = -1, target;
diff --git a/tests/node_offset_by_phandle.c b/tests/node_offset_by_phandle.c
index e9fd939..a8442f1 100644
--- a/tests/node_offset_by_phandle.c
+++ b/tests/node_offset_by_phandle.c
@@ -29,7 +29,7 @@
#include "tests.h"
#include "testdata.h"
-void check_search(void *fdt, uint32_t phandle, int target)
+static void check_search(void *fdt, uint32_t phandle, int target)
{
int offset;
diff --git a/tests/node_offset_by_prop_value.c b/tests/node_offset_by_prop_value.c
index c55110a..0f2a345 100644
--- a/tests/node_offset_by_prop_value.c
+++ b/tests/node_offset_by_prop_value.c
@@ -29,7 +29,7 @@
#include "tests.h"
#include "testdata.h"
-void vcheck_search(void *fdt, const char *propname, const void *propval,
+static void vcheck_search(void *fdt, const char *propname, const void *propval,
int proplen, va_list ap)
{
int offset = -1, target;
@@ -48,7 +48,7 @@ void vcheck_search(void *fdt, const char *propname, const void *propval,
} while (target >= 0);
}
-void check_search(void *fdt, const char *propname, const void *propval,
+static void check_search(void *fdt, const char *propname, const void *propval,
int proplen, ...)
{
va_list ap;
@@ -58,7 +58,8 @@ void check_search(void *fdt, const char *propname, const void *propval,
va_end(ap);
}
-void check_search_str(void *fdt, const char *propname, const char *propval, ...)
+static void check_search_str(void *fdt, const char *propname,
+ const char *propval, ...)
{
va_list ap;
diff --git a/tests/nopulate.c b/tests/nopulate.c
index e56839a..3cbbe21 100644
--- a/tests/nopulate.c
+++ b/tests/nopulate.c
@@ -30,7 +30,7 @@
#include "tests.h"
#include "testdata.h"
-int nopulate_struct(char *buf, const char *fdt)
+static int nopulate_struct(char *buf, const char *fdt)
{
int offset, nextoffset = 0;
uint32_t tag;
diff --git a/tests/notfound.c b/tests/notfound.c
index ae28c44..38918ad 100644
--- a/tests/notfound.c
+++ b/tests/notfound.c
@@ -28,7 +28,7 @@
#include "tests.h"
#include "testdata.h"
-void check_error(const char *s, int err)
+static void check_error(const char *s, int err)
{
if (err != -FDT_ERR_NOTFOUND)
FAIL("%s return error %s instead of -FDT_ERR_NOTFOUND", s,
diff --git a/tests/parent_offset.c b/tests/parent_offset.c
index 8336c72..e7affcc 100644
--- a/tests/parent_offset.c
+++ b/tests/parent_offset.c
@@ -28,7 +28,7 @@
#include "tests.h"
#include "testdata.h"
-int path_parent_len(const char *path)
+static int path_parent_len(const char *path)
{
const char *p = strrchr(path, '/');
@@ -40,7 +40,7 @@ int path_parent_len(const char *path)
return p - path;
}
-void check_path(struct fdt_header *fdt, const char *path)
+static void check_path(struct fdt_header *fdt, const char *path)
{
char *parentpath;
int nodeoffset, parentoffset, parentpathoffset, pathparentlen;
diff --git a/tests/path-references.c b/tests/path-references.c
index b96c5b2..9f363b3 100644
--- a/tests/path-references.c
+++ b/tests/path-references.c
@@ -28,7 +28,7 @@
#include "tests.h"
#include "testdata.h"
-void check_ref(const void *fdt, int node, const char *checkpath)
+static void check_ref(const void *fdt, int node, const char *checkpath)
{
const char *p;
int len;
diff --git a/tests/path_offset.c b/tests/path_offset.c
index 4b014ac..bb092f1 100644
--- a/tests/path_offset.c
+++ b/tests/path_offset.c
@@ -28,7 +28,7 @@
#include "tests.h"
#include "testdata.h"
-int check_subnode(void *fdt, int parent, const char *name)
+static int check_subnode(void *fdt, int parent, const char *name)
{
int offset;
const struct fdt_node_header *nh;
diff --git a/tests/path_offset_aliases.c b/tests/path_offset_aliases.c
new file mode 100644
index 0000000..191edd2
--- /dev/null
+++ b/tests/path_offset_aliases.c
@@ -0,0 +1,59 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_path_offset()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright 2008 Kumar Gala, Freescale Semiconductor, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+void check_alias(void *fdt, const char *full_path, const char *alias_path)
+{
+ int offset, offset_a;
+
+ offset = fdt_path_offset(fdt, full_path);
+ offset_a = fdt_path_offset(fdt, alias_path);
+
+ if (offset != offset_a)
+ FAIL("Mismatch between %s path_offset (%d) and %s path_offset alias (%d)",
+ full_path, offset, alias_path, offset_a);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_alias(fdt, "/subnode@1", "s1");
+ check_alias(fdt, "/subnode@1/subsubnode", "ss1");
+ check_alias(fdt, "/subnode@1/subsubnode", "s1/subsubnode");
+ check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "sss1");
+ check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "ss1/subsubsubnode");
+ check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "s1/subsubnode/subsubsubnode");
+
+ PASS();
+}
diff --git a/tests/phandle_format.c b/tests/phandle_format.c
new file mode 100644
index 0000000..7e4d816
--- /dev/null
+++ b/tests/phandle_format.c
@@ -0,0 +1,78 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for phandle format options
+ * Copyright (C) 2009 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define PHANDLE_LEGACY 0x1
+#define PHANDLE_EPAPR 0x2
+#define PHANDLE_BOTH 0x3
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int phandle_format;
+ int n4;
+ uint32_t h4;
+
+ if (argc != 3)
+ CONFIG("Usage: %s <dtb file> <legacy|epapr|both>\n", argv[0]);
+
+ test_init(argc, argv);
+ fdt = load_blob(argv[1]);
+
+ if (streq(argv[2], "legacy"))
+ phandle_format = PHANDLE_LEGACY;
+ else if (streq(argv[2], "epapr"))
+ phandle_format = PHANDLE_EPAPR;
+ else if (streq(argv[2], "both"))
+ phandle_format = PHANDLE_BOTH;
+ else
+ CONFIG("Usage: %s <dtb file> <legacy|epapr|both>\n", argv[0]);
+
+ n4 = fdt_path_offset(fdt, "/node4");
+ if (n4 < 0)
+ FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4));
+
+ h4 = fdt_get_phandle(fdt, n4);
+ if ((h4 == 0) || (h4 == -1))
+ FAIL("/node4 has bad phandle 0x%x\n", h4);
+
+ if (phandle_format & PHANDLE_LEGACY)
+ check_getprop_cell(fdt, n4, "linux,phandle", h4);
+ else
+ if (fdt_getprop(fdt, n4, "linux,phandle", NULL))
+ FAIL("linux,phandle property present in non-legacy mode");
+
+ if (phandle_format & PHANDLE_EPAPR)
+ check_getprop_cell(fdt, n4, "phandle", h4);
+ else
+ if (fdt_getprop(fdt, n4, "phandle", NULL))
+ FAIL("phandle property present in legacy-only mode");
+
+ PASS();
+}
diff --git a/tests/references.c b/tests/references.c
index e98d450..b20f21f 100644
--- a/tests/references.c
+++ b/tests/references.c
@@ -28,7 +28,7 @@
#include "tests.h"
#include "testdata.h"
-void check_ref(const void *fdt, int node, uint32_t checkref)
+static void check_ref(const void *fdt, int node, uint32_t checkref)
{
const uint32_t *p;
uint32_t ref;
@@ -60,8 +60,8 @@ void check_ref(const void *fdt, int node, uint32_t checkref)
int main(int argc, char *argv[])
{
void *fdt;
- int n1, n2, n3, n4;
- uint32_t h1, h2, h4;
+ int n1, n2, n3, n4, n5;
+ uint32_t h1, h2, h4, h5;
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
@@ -78,10 +78,14 @@ int main(int argc, char *argv[])
n4 = fdt_path_offset(fdt, "/node4");
if (n4 < 0)
FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4));
+ n5 = fdt_path_offset(fdt, "/node5");
+ if (n5 < 0)
+ FAIL("fdt_path_offset(/node5): %s", fdt_strerror(n5));
h1 = fdt_get_phandle(fdt, n1);
h2 = fdt_get_phandle(fdt, n2);
h4 = fdt_get_phandle(fdt, n4);
+ h5 = fdt_get_phandle(fdt, n5);
if (h1 != 0x2000)
FAIL("/node1 has wrong phandle, 0x%x instead of 0x%x",
@@ -92,6 +96,11 @@ int main(int argc, char *argv[])
if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0))
FAIL("/node4 has bad phandle, 0x%x", h4);
+ if ((h5 == 0) || (h5 == -1))
+ FAIL("/node5 has bad phandle, 0x%x", h5);
+ if ((h5 == h4) || (h5 == h2) || (h5 == h1))
+ FAIL("/node5 has duplicate phandle, 0x%x", h5);
+
check_ref(fdt, n1, h2);
check_ref(fdt, n2, h1);
check_ref(fdt, n3, h4);
diff --git a/tests/references.dts b/tests/references.dts
index 36b6f51..640c931 100644
--- a/tests/references.dts
+++ b/tests/references.dts
@@ -8,7 +8,7 @@
lref = <&n2>;
};
n2: node2 {
- linux,phandle = <0x1>;
+ phandle = <0x1>;
ref = <&{/node1}>; /* reference after target */
lref = <&n1>;
};
@@ -20,4 +20,15 @@
};
n4: node4 {
};
+
+ /* Explicit phandle with implicit value */
+ /* This self-reference is the standard way to tag a node as requiring
+ * a phandle (perhaps for reference by nodes that will be dynamically
+ * added) without explicitly allocating it a phandle.
+ * The self-reference requires some special internal handling, though
+ * so check it actually works */
+ n5: node5 {
+ linux,phandle = <&n5>;
+ phandle = <&n5>;
+ };
};
diff --git a/tests/references_dts0.dts b/tests/references_dts0.dts
index df82c23..d34dbb2 100644
--- a/tests/references_dts0.dts
+++ b/tests/references_dts0.dts
@@ -1,21 +1,26 @@
+/dts-v1/;
+
/ {
/* Explicit phandles */
n1: node1 {
- linux,phandle = <2000>;
- ref = <&/node2>; /* reference precedes target */
+ linux,phandle = <0x2000>;
+ ref = <&{/node2}>; /* reference precedes target */
lref = <&n2>;
};
n2: node2 {
- linux,phandle = <1>;
- ref = <&/node1>; /* reference after target */
+ linux,phandle = <0x1>;
+ ref = <&{/node1}>; /* reference after target */
lref = <&n1>;
};
/* Implicit phandles */
n3: node3 {
- ref = <&/node4>;
+ ref = <&{/node4}>;
lref = <&n4>;
};
n4: node4 {
};
+ n5: node5 {
+ linux,phandle = <&n5>;
+ };
};
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 7bfc399..c532030 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -2,6 +2,10 @@
. ./tests.sh
+if [ -z "$CC" ]; then
+ CC=gcc
+fi
+
export QUIET_TEST=1
export VALGRIND=
@@ -71,11 +75,12 @@ run_dtc_test () {
base_run_test wrap_test $VALGRIND $DTC "$@"
}
-CONVERT=../convert-dtsv0
+asm_to_so () {
+ $CC -shared -o $1.test.so data.S $1.test.s
+}
-run_convert_test () {
- echo -n "convert-dtsv0 $@: "
- base_run_test wrap_test $VALGRIND $CONVERT "$@"
+asm_to_so_test () {
+ run_wrap_test asm_to_so "$@"
}
tree1_tests () {
@@ -201,6 +206,9 @@ dtc_tests () {
run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts
run_test string_escapes dtc_escapes.test.dtb
+ run_dtc_test -I dts -O dtb -o dtc_extra-terminating-null.test.dtb extra-terminating-null.dts
+ run_test extra-terminating-null dtc_extra-terminating-null.test.dtb
+
run_dtc_test -I dts -O dtb -o dtc_references.test.dtb references.dts
run_test references dtc_references.test.dtb
@@ -210,10 +218,21 @@ dtc_tests () {
run_dtc_test -I dts -O dtb -o dtc_path-references.test.dtb path-references.dts
run_test path-references dtc_path-references.test.dtb
+ run_test phandle_format dtc_references.test.dtb both
+ for f in legacy epapr both; do
+ run_dtc_test -I dts -O dtb -H $f -o dtc_references.test.$f.dtb references.dts
+ run_test phandle_format dtc_references.test.$f.dtb $f
+ done
+
run_dtc_test -I dts -O dtb -o dtc_comments.test.dtb comments.dts
run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts
run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb
+ # Check aliases support in fdt_path_offset
+ run_dtc_test -I dts -O dtb -o aliases.dtb aliases.dts
+ run_test get_alias aliases.dtb
+ run_test path_offset_aliases aliases.dtb
+
# Check /include/ directive
run_dtc_test -I dts -O dtb -o includes.test.dtb include0.dts
run_test dtbs_equal_ordered includes.test.dtb test_tree1.dtb
@@ -230,8 +249,22 @@ dtc_tests () {
run_dtc_test -I dtb -O dtb -o boot_cpuid_preserved_test_tree1.test.dtb boot_cpuid_test_tree1.test.dtb
run_test dtbs_equal_ordered boot_cpuid_preserved_test_tree1.test.dtb boot_cpuid_test_tree1.test.dtb
+ # Check -Oasm mode
+ for tree in test_tree1.dts escapes.dts references.dts path-references.dts \
+ comments.dts aliases.dts include0.dts incbin.dts \
+ value-labels.dts ; do
+ run_dtc_test -I dts -O asm -o oasm_$tree.test.s $tree
+ asm_to_so_test oasm_$tree
+ run_dtc_test -I dts -O dtb -o $tree.test.dtb $tree
+ run_test asm_tree_dump ./oasm_$tree.test.so oasm_$tree.test.dtb
+ run_wrap_test cmp oasm_$tree.test.dtb $tree.test.dtb
+ done
+
+ run_test value-labels ./oasm_value-labels.dts.test.so
+
# Check -Odts mode preserve all dtb information
- for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb ; do
+ for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb \
+ dtc_extra-terminating-null.test.dtb dtc_references.test.dtb; do
run_dtc_test -I dtb -O dts -o odts_$tree.test.dts $tree
run_dtc_test -I dts -O dtb -o odts_$tree.test.dtb odts_$tree.test.dts
run_test dtbs_equal_ordered $tree odts_$tree.test.dtb
@@ -283,21 +316,6 @@ dtc_tests () {
run_sh_test dtc-fatal.sh -I fs -O dtb nosuchfile
}
-convert_tests () {
- V0_DTS="test_tree1_dts0.dts references_dts0.dts empty.dts escapes.dts \
- test01.dts label01.dts"
- for dts in $V0_DTS; do
- run_dtc_test -I dts -O dtb -o cvtraw_$dts.test.dtb $dts
- run_dtc_test -I dts -O dts -o cvtdtc_$dts.test.dts $dts
- run_dtc_test -I dts -O dtb -o cvtdtc_$dts.test.dtb cvtdtc_$dts.test.dts
- run_convert_test $dts
- run_dtc_test -I dts -O dtb -o cvtcvt_$dts.test.dtb ${dts}v1
-
- run_wrap_test cmp cvtraw_$dts.test.dtb cvtdtc_$dts.test.dtb
- run_wrap_test cmp cvtraw_$dts.test.dtb cvtcvt_$dts.test.dtb
- done
-}
-
while getopts "vt:m" ARG ; do
case $ARG in
"v")
@@ -313,7 +331,7 @@ while getopts "vt:m" ARG ; do
done
if [ -z "$TESTSETS" ]; then
- TESTSETS="libfdt dtc convert"
+ TESTSETS="libfdt dtc"
fi
# Make sure we don't have stale blobs lying around
@@ -327,20 +345,17 @@ for set in $TESTSETS; do
"dtc")
dtc_tests
;;
- "convert")
- convert_tests
- ;;
esac
done
-echo -e "********** TEST SUMMARY"
-echo -e "* Total testcases: $tot_tests"
-echo -e "* PASS: $tot_pass"
-echo -e "* FAIL: $tot_fail"
-echo -e "* Bad configuration: $tot_config"
+echo "********** TEST SUMMARY"
+echo "* Total testcases: $tot_tests"
+echo "* PASS: $tot_pass"
+echo "* FAIL: $tot_fail"
+echo "* Bad configuration: $tot_config"
if [ -n "$VALGRIND" ]; then
- echo -e "* valgrind errors: $tot_vg"
+ echo "* valgrind errors: $tot_vg"
fi
-echo -e "* Strange test result: $tot_strange"
-echo -e "**********"
+echo "* Strange test result: $tot_strange"
+echo "**********"
diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c
index 8f335c9..f0bce88 100644
--- a/tests/rw_tree1.c
+++ b/tests/rw_tree1.c
@@ -50,7 +50,7 @@ int main(int argc, char *argv[])
{
void *fdt;
int err;
- int offset;
+ int offset, s1, s2;
test_init(argc, argv);
@@ -77,21 +77,25 @@ int main(int argc, char *argv[])
CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1));
OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@1"));
- CHECK(fdt_setprop_string(fdt, offset, "compatible", "subnode1"));
- CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_1));
- OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "subsubnode"));
+ s1 = offset;
+ CHECK(fdt_setprop_string(fdt, s1, "compatible", "subnode1"));
+ CHECK(fdt_setprop_cell(fdt, s1, "prop-int", TEST_VALUE_1));
+ OFF_CHECK(offset, fdt_add_subnode(fdt, s1, "subsubnode"));
CHECK(fdt_setprop(fdt, offset, "compatible",
"subsubnode1\0subsubnode", 23));
CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_1));
+ OFF_CHECK(offset, fdt_add_subnode(fdt, s1, "ss1"));
OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@2"));
- CHECK(fdt_setprop_cell(fdt, offset, "linux,phandle", PHANDLE_1));
- CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_2));
- OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "subsubnode@0"));
+ s2 = offset;
+ CHECK(fdt_setprop_cell(fdt, s2, "linux,phandle", PHANDLE_1));
+ CHECK(fdt_setprop_cell(fdt, s2, "prop-int", TEST_VALUE_2));
+ OFF_CHECK(offset, fdt_add_subnode(fdt, s2, "subsubnode@0"));
CHECK(fdt_setprop_cell(fdt, offset, "linux,phandle", PHANDLE_2));
CHECK(fdt_setprop(fdt, offset, "compatible",
"subsubnode2\0subsubnode", 23));
CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_2));
+ OFF_CHECK(offset, fdt_add_subnode(fdt, s2, "ss2"));
CHECK(fdt_pack(fdt));
diff --git a/tests/set_name.c b/tests/set_name.c
index 49817a9..5d1149e 100644
--- a/tests/set_name.c
+++ b/tests/set_name.c
@@ -28,7 +28,7 @@
#include "tests.h"
#include "testdata.h"
-void check_set_name(void *fdt, const char *path, const char *newname)
+static void check_set_name(void *fdt, const char *path, const char *newname)
{
int offset;
const char *getname, *oldname;
diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c
index ac2f32e..b961070 100644
--- a/tests/subnode_offset.c
+++ b/tests/subnode_offset.c
@@ -28,7 +28,7 @@
#include "tests.h"
#include "testdata.h"
-int check_subnode(struct fdt_header *fdt, int parent, const char *name)
+static int check_subnode(struct fdt_header *fdt, int parent, const char *name)
{
int offset;
const struct fdt_node_header *nh;
@@ -60,6 +60,7 @@ int main(int argc, char *argv[])
void *fdt;
int subnode1_offset, subnode2_offset;
int subsubnode1_offset, subsubnode2_offset, subsubnode2_offset2;
+ int ss11_off, ss12_off, ss21_off, ss22_off;
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
@@ -84,5 +85,15 @@ int main(int argc, char *argv[])
if (subsubnode2_offset != subsubnode2_offset2)
FAIL("Different offsets with and without unit address");
+ ss11_off = check_subnode(fdt, subnode1_offset, "ss1");
+ ss21_off = fdt_subnode_offset(fdt, subnode2_offset, "ss1");
+ if (ss21_off != -FDT_ERR_NOTFOUND)
+ FAIL("Incorrectly found ss1 in subnode2");
+
+ ss12_off = fdt_subnode_offset(fdt, subnode1_offset, "ss2");
+ if (ss12_off != -FDT_ERR_NOTFOUND)
+ FAIL("Incorrectly found ss2 in subnode1");
+ ss22_off = check_subnode(fdt, subnode2_offset, "ss2");
+
PASS();
}
diff --git a/tests/supernode_atdepth_offset.c b/tests/supernode_atdepth_offset.c
index 1245813..73f41ae 100644
--- a/tests/supernode_atdepth_offset.c
+++ b/tests/supernode_atdepth_offset.c
@@ -28,7 +28,7 @@
#include "tests.h"
#include "testdata.h"
-int path_depth(const char *path)
+static int path_depth(const char *path)
{
const char *p;
int depth = 0;
@@ -49,7 +49,7 @@ int path_depth(const char *path)
return depth;
}
-int path_prefix(const char *path, int depth)
+static int path_prefix(const char *path, int depth)
{
const char *p;
int i;
@@ -67,7 +67,7 @@ int path_prefix(const char *path, int depth)
return p - path;
}
-void check_supernode_atdepth(struct fdt_header *fdt, const char *path,
+static void check_supernode_atdepth(struct fdt_header *fdt, const char *path,
int depth)
{
int pdepth = path_depth(path);
@@ -106,7 +106,7 @@ void check_supernode_atdepth(struct fdt_header *fdt, const char *path,
"instead of %d", nodedepth, pdepth);
}
-void check_supernode_overdepth(struct fdt_header *fdt, const char *path)
+static void check_supernode_overdepth(struct fdt_header *fdt, const char *path)
{
int pdepth = path_depth(path);
int nodeoffset, err;
@@ -121,7 +121,7 @@ void check_supernode_overdepth(struct fdt_header *fdt, const char *path)
"of FDT_ERR_NOTFOUND", path, pdepth+1, err);
}
-void check_path(struct fdt_header *fdt, const char *path)
+static void check_path(struct fdt_header *fdt, const char *path)
{
int i;
diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c
index 2a94b63..f2c430a 100644
--- a/tests/sw_tree1.c
+++ b/tests/sw_tree1.c
@@ -66,17 +66,22 @@ int main(int argc, char *argv[])
23));
CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1));
CHECK(fdt_end_node(fdt));
+ CHECK(fdt_begin_node(fdt, "ss1"));
+ CHECK(fdt_end_node(fdt));
CHECK(fdt_end_node(fdt));
CHECK(fdt_begin_node(fdt, "subnode@2"));
CHECK(fdt_property_cell(fdt, "linux,phandle", PHANDLE_1));
CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2));
CHECK(fdt_begin_node(fdt, "subsubnode@0"));
- CHECK(fdt_property_cell(fdt, "linux,phandle", PHANDLE_2));
+ CHECK(fdt_property_cell(fdt, "phandle", PHANDLE_2));
CHECK(fdt_property(fdt, "compatible", "subsubnode2\0subsubnode",
23));
CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2));
CHECK(fdt_end_node(fdt));
+ CHECK(fdt_begin_node(fdt, "ss2"));
+ CHECK(fdt_end_node(fdt));
+
CHECK(fdt_end_node(fdt));
CHECK(fdt_end_node(fdt));
diff --git a/tests/test01.dts b/tests/test01.dts
index ed2b178..f9fd165 100644
--- a/tests/test01.dts
+++ b/tests/test01.dts
@@ -1,6 +1,8 @@
-/memreserve/ 1000000000000000 0000000002000000;
-/memreserve/ 2000000000000000-20ffffffffffffff;
-/memreserve/ 0-13;
+/dts-v1/;
+
+/memreserve/ 0x1000000000000000 0x0000000002000000;
+/memreserve/ 0x2000000000000000 0x0100000000000000;
+/memreserve/ 0x0000000000000000 0x0000000000000014;
/ {
model = "MyBoardName";
@@ -9,28 +11,28 @@
#size-cells = <2>;
cpus {
- linux,phandle = <1>;
+ linux,phandle = <0x1>;
#address-cells = <1>;
#size-cells = <0>;
PowerPC,970@0 {
name = "PowerPC,970";
device_type = "cpu";
- reg = <0>;
- clock-frequency = <5f5e1000>;
- timebase-frequency = <1FCA055>;
+ reg = <0x00000000>;
+ clock-frequency = <1600000000>;
+ timebase-frequency = <33333333>;
linux,boot-cpu;
- i-cache-size = <10000>;
- d-cache-size = <8000>;
+ i-cache-size = <65536>;
+ d-cache-size = <32768>;
};
PowerPC,970@1 {
name = "PowerPC,970";
device_type = "cpu";
- reg = <1>;
- clock-frequency = <5f5e1000>;
- timebase-frequency = <1FCA055>;
- i-cache-size = <10000>;
- d-cache-size = <8000>;
+ reg = <0x00000001>;
+ clock-frequency = <1600000000>;
+ timebase-frequency = <33333333>;
+ i-cache-size = <65536>;
+ d-cache-size = <32768>;
};
};
@@ -38,18 +40,18 @@
randomnode {
string = "\xff\0stuffstuff\t\t\t\n\n\n";
blob = [0a 0b 0c 0d de ea ad be ef];
- ref = < &/memory@0 >;
- mixed = "abc", [1234], <a b c>;
+ ref = < &{/memory@0} >;
+ mixed = "abc", [1234], <0xa 0xb 0xc>;
};
memory@0 {
device_type = "memory";
- memreg: reg = <00000000 00000000 00000000 20000000>;
+ memreg: reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
};
chosen {
bootargs = "root=/dev/sda2";
- linux,platform = <00000600>;
+ linux,platform = <0x600>;
};
};
diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts
index 27602af..218c382 100644
--- a/tests/test_tree1.dts
+++ b/tests/test_tree1.dts
@@ -16,6 +16,9 @@
compatible = "subsubnode1", "subsubnode";
prop-int = <0xdeadbeef>;
};
+
+ ss1 {
+ };
};
subnode@2 {
@@ -23,9 +26,12 @@
prop-int = <123456789>;
subsubnode@0 {
- linux,phandle = <0x2001>;
+ phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};
+
+ ss2 {
+ };
};
};
diff --git a/tests/test_tree1_dts0.dts b/tests/test_tree1_dts0.dts
index bc65819..032d540 100644
--- a/tests/test_tree1_dts0.dts
+++ b/tests/test_tree1_dts0.dts
@@ -1,9 +1,11 @@
-/memreserve/ deadbeef00000000-deadbeef000fffff;
-/memreserve/ 75bcd15 1000;
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x0000000000100000;
+/memreserve/ 0x00000000075bcd15 0x0000000000001000;
/ {
compatible = "test_tree1";
- prop-int = <deadbeef>;
+ prop-int = <0xdeadbeef>;
prop-str = "hello world";
subnode@1 {
@@ -12,18 +14,24 @@
subsubnode {
compatible = "subsubnode1", "subsubnode";
- prop-int = <h# deadbeef>;
+ prop-int = < 0xdeadbeef>;
+ };
+
+ ss1 {
};
};
subnode@2 {
- linux,phandle = <2000>;
- prop-int = <d# 123456789>;
+ linux,phandle = <0x2000>;
+ prop-int = < 123456789>;
subsubnode@0 {
- linux,phandle = <2001>;
+ linux,phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
- prop-int = <o# 0726746425>;
+ prop-int = < 0726746425>;
+ };
+
+ ss2 {
};
};
};
diff --git a/tests/tests.h b/tests/tests.h
index c273f3c..fcb2b2a 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -34,6 +34,7 @@ void test_init(int argc, char *argv[]);
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define PALIGN(p, a) ((void *)ALIGN((unsigned long)(p), (a)))
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define streq(s1, s2) (strcmp((s1),(s2)) == 0)
diff --git a/tests/trees.S b/tests/trees.S
index cedf5f9..66adf3f 100644
--- a/tests/trees.S
+++ b/tests/trees.S
@@ -96,10 +96,14 @@ test_tree1_struct:
PROP_STR(test_tree1, compatible, "subsubnode1\0subsubnode")
PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
END_NODE
+
+ BEGIN_NODE("ss1")
+ END_NODE
+
END_NODE
BEGIN_NODE("subnode@2")
- PROP_INT(test_tree1, phandle, PHANDLE_1)
+ PROP_INT(test_tree1, linux_phandle, PHANDLE_1)
PROP_INT(test_tree1, prop_int, TEST_VALUE_2)
BEGIN_NODE("subsubnode@0")
@@ -107,6 +111,10 @@ test_tree1_struct:
PROP_STR(test_tree1, compatible, "subsubnode2\0subsubnode")
PROP_INT(test_tree1, prop_int, TEST_VALUE_2)
END_NODE
+
+ BEGIN_NODE("ss2")
+ END_NODE
+
END_NODE
END_NODE
@@ -117,7 +125,8 @@ test_tree1_strings:
STRING(test_tree1, compatible, "compatible")
STRING(test_tree1, prop_int, "prop-int")
STRING(test_tree1, prop_str, "prop-str")
- STRING(test_tree1, phandle, "linux,phandle")
+ STRING(test_tree1, linux_phandle, "linux,phandle")
+ STRING(test_tree1, phandle, "phandle")
test_tree1_strings_end:
test_tree1_end:
diff --git a/tests/value-labels.c b/tests/value-labels.c
new file mode 100644
index 0000000..c5aea8f
--- /dev/null
+++ b/tests/value-labels.c
@@ -0,0 +1,128 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Test labels within values
+ * Copyright (C) 2008 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include <dlfcn.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+struct val_label {
+ const char *labelname;
+ int propoff;
+};
+
+struct val_label labels1[] = {
+ { "start1", 0 },
+ { "mid1", 2 },
+ { "end1", -1 },
+};
+
+struct val_label labels2[] = {
+ { "start2", 0 },
+ { "innerstart2", 0 },
+ { "innermid2", 4 },
+ { "innerend2", -1 },
+ { "end2", -1 },
+};
+
+struct val_label labels3[] = {
+ { "start3", 0 },
+ { "innerstart3", 0 },
+ { "innermid3", 1 },
+ { "innerend3", -1 },
+ { "end3", -1 },
+};
+
+void check_prop_labels(void *sohandle, void *fdt, const char *name,
+ const struct val_label* labels, int n)
+{
+ const struct fdt_property *prop;
+ const char *p;
+ int len;
+ int i;
+
+ prop = fdt_get_property(fdt, 0, name, &len);
+ if (!prop)
+ FAIL("Couldn't locate property \"%s\"", name);
+
+ p = dlsym(sohandle, name);
+ if (!p)
+ FAIL("Couldn't locate label symbol \"%s\"", name);
+
+ if (p != (const char *)prop)
+ FAIL("Label \"%s\" does not point to correct property", name);
+
+ for (i = 0; i < n; i++) {
+ int off = labels[i].propoff;
+
+ if (off == -1)
+ off = len;
+
+ p = dlsym(sohandle, labels[i].labelname);
+ if (!p)
+ FAIL("Couldn't locate label symbol \"%s\"", name);
+
+ if ((p - prop->data) != off)
+ FAIL("Label \"%s\" points to offset %ld instead of %d"
+ "in property \"%s\"", labels[i].labelname,
+ (long)(p - prop->data), off, name);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ void *sohandle;
+ void *fdt;
+ int err;
+
+ test_init(argc, argv);
+ if (argc != 2)
+ CONFIG("Usage: %s <so file>", argv[0]);
+
+ sohandle = dlopen(argv[1], RTLD_NOW);
+ if (!sohandle)
+ FAIL("Couldn't dlopen() %s", argv[1]);
+
+ fdt = dlsym(sohandle, "dt_blob_start");
+ if (!fdt)
+ FAIL("Couldn't locate \"dt_blob_start\" symbol in %s",
+ argv[1]);
+
+ err = fdt_check_header(fdt);
+ if (err != 0)
+ FAIL("%s contains invalid tree: %s", argv[1],
+ fdt_strerror(err));
+
+
+ check_prop_labels(sohandle, fdt, "prop1", labels1, ARRAY_SIZE(labels1));
+ check_prop_labels(sohandle, fdt, "prop2", labels2, ARRAY_SIZE(labels2));
+ check_prop_labels(sohandle, fdt, "prop3", labels3, ARRAY_SIZE(labels3));
+
+ PASS();
+}
diff --git a/tests/value-labels.dts b/tests/value-labels.dts
new file mode 100644
index 0000000..490c609
--- /dev/null
+++ b/tests/value-labels.dts
@@ -0,0 +1,8 @@
+/dts-v1/;
+
+/ {
+ prop1: prop1 = start1: "a", mid1: "b" end1:;
+ prop2: prop2 = start2: < innerstart2: 0xdeadbeef innermid2: 0xabcd1234 innerend2: > end2:;
+ prop3: prop3 = start3: [ innerstart3: ab innermid3: cd innerend3: ] end3:;
+};
+
diff --git a/treesource.c b/treesource.c
index ebeb6eb..cc1751d 100644
--- a/treesource.c
+++ b/treesource.c
@@ -52,7 +52,7 @@ static void write_prefix(FILE *f, int level)
fputc('\t', f);
}
-int isstring(char c)
+static int isstring(char c)
{
return (isprint(c)
|| (c == '\0')
@@ -63,26 +63,20 @@ static void write_propval_string(FILE *f, struct data val)
{
const char *str = val.val;
int i;
- int newchunk = 1;
struct marker *m = val.markers;
assert(str[val.len-1] == '\0');
+ while (m && (m->offset == 0)) {
+ if (m->type == LABEL)
+ fprintf(f, "%s: ", m->ref);
+ m = m->next;
+ }
+ fprintf(f, "\"");
+
for (i = 0; i < (val.len-1); i++) {
char c = str[i];
- if (newchunk) {
- while (m && (m->offset <= i)) {
- if (m->type == LABEL) {
- assert(m->offset == i);
- fprintf(f, "%s: ", m->ref);
- }
- m = m->next;
- }
- fprintf(f, "\"");
- newchunk = 0;
- }
-
switch (c) {
case '\a':
fprintf(f, "\\a");
@@ -113,7 +107,14 @@ static void write_propval_string(FILE *f, struct data val)
break;
case '\0':
fprintf(f, "\", ");
- newchunk = 1;
+ while (m && (m->offset < i)) {
+ if (m->type == LABEL) {
+ assert(m->offset == (i+1));
+ fprintf(f, "%s: ", m->ref);
+ }
+ m = m->next;
+ }
+ fprintf(f, "\"");
break;
default:
if (isprint(c))
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..33631ce
--- /dev/null
+++ b/util.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include "dtc.h"
+
+char *xstrdup(const char *s)
+{
+ int len = strlen(s) + 1;
+ char *dup = xmalloc(len);
+
+ memcpy(dup, s, len);
+
+ return dup;
+}
diff --git a/util.h b/util.h
new file mode 100644
index 0000000..0fb60fe
--- /dev/null
+++ b/util.h
@@ -0,0 +1,55 @@
+#ifndef _UTIL_H
+#define _UTIL_H
+
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+static inline void __attribute__((noreturn)) die(char * str, ...)
+{
+ va_list ap;
+
+ va_start(ap, str);
+ fprintf(stderr, "FATAL ERROR: ");
+ vfprintf(stderr, str, ap);
+ exit(1);
+}
+
+static inline void *xmalloc(size_t len)
+{
+ void *new = malloc(len);
+
+ if (!new)
+ die("malloc() failed\n");
+
+ return new;
+}
+
+static inline void *xrealloc(void *p, size_t len)
+{
+ void *new = realloc(p, len);
+
+ if (!new)
+ die("realloc() failed (len=%d)\n", len);
+
+ return new;
+}
+
+extern char *xstrdup(const char *s);
+
+#endif /* _UTIL_H */
OpenPOWER on IntegriCloud