aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2014-01-27 06:20:36 +0000
committerWarner Losh <imp@FreeBSD.org>2014-01-27 06:20:36 +0000
commit939bdb9f6a0dad490702c3009bb8714579e1e765 (patch)
tree4405597d1484d0e28336fa7f4f113d502f37469f
parentab1c86b34d2455fbd8cf2a9a404b0d7fd4ad28b1 (diff)
downloadsrc-939bdb9f6a0dad490702c3009bb8714579e1e765.tar.gz
src-939bdb9f6a0dad490702c3009bb8714579e1e765.zip
Import dtc git at 6a15eb2350426d285130e4c9d84c0bdb6575547a (last rev before bison became required)
Notes
Notes: svn path=/vendor/dtc/dist/; revision=261202
-rw-r--r--Documentation/manual.txt5
-rw-r--r--Makefile14
-rw-r--r--checks.c24
-rw-r--r--convert-dtsv0-lexer.l24
-rw-r--r--data.c10
-rw-r--r--dtc-lexer.l98
-rw-r--r--dtc-parser.y110
-rw-r--r--dtc.c125
-rw-r--r--dtc.h33
-rw-r--r--fdtdump.c133
-rw-r--r--fdtget.c60
-rw-r--r--fdtput.c135
-rw-r--r--flattree.c7
-rw-r--r--libfdt/Makefile.libfdt2
-rw-r--r--libfdt/fdt.c30
-rw-r--r--libfdt/fdt.h93
-rw-r--r--libfdt/fdt_ro.c7
-rw-r--r--libfdt/fdt_rw.c4
-rw-r--r--libfdt/fdt_sw.c36
-rw-r--r--libfdt/fdt_wip.c2
-rw-r--r--libfdt/libfdt.h71
-rw-r--r--libfdt/libfdt_env.h104
-rw-r--r--libfdt/version.lds6
-rw-r--r--livetree.c126
-rw-r--r--srcpos.c43
-rw-r--r--srcpos.h17
-rw-r--r--tests/Makefile.tests5
-rw-r--r--tests/add_subnode_with_nops.c1
-rw-r--r--tests/aliases.dts4
-rw-r--r--tests/appendprop1.c1
-rw-r--r--tests/appendprop2.c1
-rw-r--r--tests/asm_tree_dump.c1
-rw-r--r--tests/boot-cpuid.c1
-rw-r--r--tests/char_literal.c1
-rw-r--r--tests/del_node.c1
-rw-r--r--tests/del_property.c1
-rw-r--r--tests/dtb_reverse.c1
-rw-r--r--tests/dtbs_equal_ordered.c1
-rw-r--r--tests/dtbs_equal_unordered.c1
-rw-r--r--tests/dumptrees.c2
-rw-r--r--tests/extra-terminating-null.c1
-rwxr-xr-xtests/fdtget-runtest.sh2
-rw-r--r--tests/find_property.c1
-rw-r--r--tests/get_alias.c1
-rw-r--r--tests/get_mem_rsv.c1
-rw-r--r--tests/get_name.c1
-rw-r--r--tests/get_path.c1
-rw-r--r--tests/get_phandle.c1
-rw-r--r--tests/getprop.c1
-rw-r--r--tests/incbin.c1
-rw-r--r--tests/include1.dts5
-rw-r--r--tests/include7.dts1
-rw-r--r--tests/include8.dts3
-rw-r--r--tests/integer-expressions.c1
-rw-r--r--tests/mangle-layout.c1
-rw-r--r--tests/move_and_save.c1
-rw-r--r--tests/node_check_compatible.c1
-rw-r--r--tests/node_offset_by_compatible.c1
-rw-r--r--tests/node_offset_by_phandle.c1
-rw-r--r--tests/node_offset_by_prop_value.c1
-rw-r--r--tests/nop_node.c1
-rw-r--r--tests/nop_property.c1
-rw-r--r--tests/nopulate.c1
-rw-r--r--tests/notfound.c1
-rw-r--r--tests/open_pack.c1
-rw-r--r--tests/parent_offset.c1
-rw-r--r--tests/path-references.c1
-rw-r--r--tests/path_offset.c1
-rw-r--r--tests/path_offset_aliases.c1
-rw-r--r--tests/phandle_format.c1
-rw-r--r--tests/references.c1
-rw-r--r--tests/root_node.c1
-rwxr-xr-xtests/run_tests.sh45
-rw-r--r--tests/rw_tree1.c1
-rw-r--r--tests/set_name.c1
-rw-r--r--tests/setprop.c1
-rw-r--r--tests/setprop_inplace.c1
-rw-r--r--tests/sized_cells.c1
-rw-r--r--tests/string_escapes.c1
-rw-r--r--tests/subnode_offset.c1
-rw-r--r--tests/supernode_atdepth_offset.c1
-rw-r--r--tests/sw_tree1.c92
-rw-r--r--tests/test_tree1.dts37
-rw-r--r--tests/test_tree1_merge.dts7
-rw-r--r--tests/test_tree1_merge_labelled.dts7
-rw-r--r--tests/test_tree1_merge_path.dts7
-rw-r--r--tests/test_tree1_wrong1.dts7
-rw-r--r--tests/test_tree1_wrong2.dts7
-rw-r--r--tests/test_tree1_wrong3.dts7
-rw-r--r--tests/test_tree1_wrong4.dts7
-rw-r--r--tests/test_tree1_wrong5.dts7
-rw-r--r--tests/test_tree1_wrong6.dts7
-rw-r--r--tests/test_tree1_wrong7.dts7
-rw-r--r--tests/test_tree1_wrong8.dts7
-rw-r--r--tests/test_tree1_wrong9.dts7
-rw-r--r--tests/trees.S10
-rw-r--r--tests/truncated_property.c1
-rw-r--r--tests/utilfdt_test.c1
-rw-r--r--tests/value-labels.c1
-rw-r--r--treesource.c10
-rw-r--r--util.c143
-rw-r--r--util.h110
102 files changed, 1390 insertions, 532 deletions
diff --git a/Documentation/manual.txt b/Documentation/manual.txt
index 989c5892e442..65c8540be71b 100644
--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -3,6 +3,7 @@ Device Tree Compiler Manual
I - "dtc", the device tree compiler
1) Obtaining Sources
+ 1.1) Submitting Patches
2) Description
3) Command Line
4) Source File
@@ -44,6 +45,10 @@ Tarballs of the 1.0.0 and latest releases are here:
http://www.jdl.com/software/dtc-v1.2.0.tgz
http://www.jdl.com/software/dtc-latest.tgz
+1.1) Submitting Patches
+
+Patches should be sent to jdl@jdl.com, and CC'ed to
+devicetree-discuss@lists.ozlabs.org.
2) Description
diff --git a/Makefile b/Makefile
index 1169e6c02dc9..70abf05d874f 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@
# CONFIG_LOCALVERSION from some future config system.
#
VERSION = 1
-PATCHLEVEL = 3
+PATCHLEVEL = 4
SUBLEVEL = 0
EXTRAVERSION =
LOCAL_VERSION =
@@ -160,18 +160,26 @@ endif
# intermediate target and building them again "for real"
.SECONDARY: $(DTC_GEN_SRCS) $(CONVERT_GEN_SRCS)
-install: all $(SCRIPTS)
- @$(VECHO) INSTALL
+install-bin: all $(SCRIPTS)
+ @$(VECHO) INSTALL-BIN
$(INSTALL) -d $(DESTDIR)$(BINDIR)
$(INSTALL) $(BIN) $(SCRIPTS) $(DESTDIR)$(BINDIR)
+
+install-lib: all
+ @$(VECHO) INSTALL-LIB
$(INSTALL) -d $(DESTDIR)$(LIBDIR)
$(INSTALL) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR)
ln -sf $(notdir $(LIBFDT_lib)) $(DESTDIR)$(LIBDIR)/$(LIBFDT_soname)
ln -sf $(LIBFDT_soname) $(DESTDIR)$(LIBDIR)/libfdt.$(SHAREDLIB_EXT)
$(INSTALL) -m 644 $(LIBFDT_archive) $(DESTDIR)$(LIBDIR)
+
+install-includes:
+ @$(VECHO) INSTALL-INC
$(INSTALL) -d $(DESTDIR)$(INCLUDEDIR)
$(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR)
+install: install-bin install-lib install-includes
+
$(VERSION_FILE): Makefile FORCE
$(call filechk,version)
diff --git a/checks.c b/checks.c
index 9061237f1cce..11a40861e401 100644
--- a/checks.c
+++ b/checks.c
@@ -53,7 +53,7 @@ struct check {
void *data;
bool warn, error;
enum checkstatus status;
- int inprogress;
+ bool inprogress;
int num_prereqs;
struct check **prereq;
};
@@ -141,9 +141,9 @@ static void check_nodes_props(struct check *c, struct node *dt, struct node *nod
check_nodes_props(c, dt, child);
}
-static int run_check(struct check *c, struct node *dt)
+static bool run_check(struct check *c, struct node *dt)
{
- int error = 0;
+ bool error = false;
int i;
assert(!c->inprogress);
@@ -151,11 +151,11 @@ static int run_check(struct check *c, struct node *dt)
if (c->status != UNCHECKED)
goto out;
- c->inprogress = 1;
+ c->inprogress = true;
for (i = 0; i < c->num_prereqs; i++) {
struct check *prq = c->prereq[i];
- error |= run_check(prq, dt);
+ error = error || run_check(prq, dt);
if (prq->status != PASSED) {
c->status = PREREQ;
check_msg(c, "Failed prerequisite '%s'",
@@ -177,9 +177,9 @@ static int run_check(struct check *c, struct node *dt)
TRACE(c, "\tCompleted, status %d", c->status);
out:
- c->inprogress = 0;
+ c->inprogress = false;
if ((c->status != PASSED) && (c->error))
- error = 1;
+ error = true;
return error;
}
@@ -256,11 +256,15 @@ static void check_duplicate_property_names(struct check *c, struct node *dt,
{
struct property *prop, *prop2;
- for_each_property(node, prop)
- for (prop2 = prop->next; prop2; prop2 = prop2->next)
+ for_each_property(node, prop) {
+ for (prop2 = prop->next; prop2; prop2 = prop2->next) {
+ if (prop2->deleted)
+ continue;
if (streq(prop->name, prop2->name))
FAIL(c, "Duplicate property name %s in %s",
prop->name, node->fullpath);
+ }
+ }
}
NODE_ERROR(duplicate_property_names, NULL);
@@ -729,7 +733,7 @@ void parse_checks_option(bool warn, bool error, const char *optarg)
die("Unrecognized check name \"%s\"\n", name);
}
-void process_checks(int force, struct boot_info *bi)
+void process_checks(bool force, struct boot_info *bi)
{
struct node *dt = bi->dt;
int i;
diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l
index 89d540a7f23e..548e7199a0c4 100644
--- a/convert-dtsv0-lexer.l
+++ b/convert-dtsv0-lexer.l
@@ -50,8 +50,6 @@ static int saw_hyphen; /* = 0 */
static unsigned long long last_val;
static char *last_name; /* = NULL */
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
const struct {
const char *pattern;
int obase, width;
@@ -194,11 +192,15 @@ const struct {
}
%%
-static void usage(void)
-{
- fprintf(stderr, "convert-dtsv0 <v0 dts file>...\n");
- exit(3);
-}
+/* Usage related data. */
+static const char usage_synopsis[] = "convert-dtsv0 [options] <v0 dts file>...";
+static const char usage_short_opts[] = "" USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+ USAGE_COMMON_LONG_OPTS
+};
+static const char * const usage_opts_help[] = {
+ USAGE_COMMON_OPTS_HELP
+};
static void convert_file(const char *fname)
{
@@ -226,10 +228,16 @@ static void convert_file(const char *fname)
int main(int argc, char *argv[])
{
+ int opt;
int i;
+ while ((opt = util_getopt_long()) != EOF) {
+ switch (opt) {
+ case_USAGE_COMMON_FLAGS
+ }
+ }
if (argc < 2)
- usage();
+ usage("missing filename");
for (i = 1; i < argc; i++) {
fprintf(stderr, "Converting %s from dts v0 to dts v1\n", argv[i]);
diff --git a/data.c b/data.c
index 4a40c5b92474..4c50b1259556 100644
--- a/data.c
+++ b/data.c
@@ -250,20 +250,20 @@ struct data data_add_marker(struct data d, enum markertype type, char *ref)
return data_append_markers(d, m);
}
-int data_is_one_string(struct data d)
+bool data_is_one_string(struct data d)
{
int i;
int len = d.len;
if (len == 0)
- return 0;
+ return false;
for (i = 0; i < len-1; i++)
if (d.val[i] == '\0')
- return 0;
+ return false;
if (d.val[len-1] != '\0')
- return 0;
+ return false;
- return 1;
+ return true;
}
diff --git a/dtc-lexer.l b/dtc-lexer.l
index 4715f31544a7..0821bde31249 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -40,6 +40,7 @@ LINECOMMENT "//".*\n
#include "dtc-parser.tab.h"
YYLTYPE yylloc;
+extern bool treesource_error;
/* CAUTION: this will stop working if we ever use yyless() or yyunput() */
#define YY_USER_ACTION \
@@ -61,7 +62,8 @@ static int dts_version = 1;
BEGIN(V1); \
static void push_input_file(const char *filename);
-static int pop_input_file(void);
+static bool pop_input_file(void);
+static void lexical_error(const char *fmt, ...);
%}
%%
@@ -71,6 +73,27 @@ static int pop_input_file(void);
push_input_file(name);
}
+<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
+ char *line, *tmp, *fn;
+ /* skip text before line # */
+ line = yytext;
+ while (!isdigit((unsigned char)*line))
+ line++;
+ /* skip digits in line # */
+ tmp = line;
+ while (!isspace((unsigned char)*tmp))
+ tmp++;
+ /* "NULL"-terminate line # */
+ *tmp = '\0';
+ /* start of filename */
+ fn = strchr(tmp + 1, '"') + 1;
+ /* strip trailing " from filename */
+ tmp = strchr(fn, '"');
+ *tmp = 0;
+ /* -1 since #line is the number of the next line */
+ srcpos_set_line(xstrdup(fn), atoi(line) - 1);
+ }
+
<*><<EOF>> {
if (!pop_input_file()) {
yyterminate();
@@ -103,6 +126,20 @@ static int pop_input_file(void);
return DT_BITS;
}
+<*>"/delete-property/" {
+ DPRINT("Keyword: /delete-property/\n");
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ return DT_DEL_PROP;
+ }
+
+<*>"/delete-node/" {
+ DPRINT("Keyword: /delete-node/\n");
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ return DT_DEL_NODE;
+ }
+
<*>{LABEL}: {
DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext);
@@ -111,15 +148,42 @@ static int pop_input_file(void);
}
<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
- yylval.literal = xstrdup(yytext);
- DPRINT("Literal: '%s'\n", yylval.literal);
+ char *e;
+ DPRINT("Integer Literal: '%s'\n", yytext);
+
+ errno = 0;
+ yylval.integer = strtoull(yytext, &e, 0);
+
+ assert(!(*e) || !e[strspn(e, "UL")]);
+
+ if (errno == ERANGE)
+ lexical_error("Integer literal '%s' out of range",
+ yytext);
+ else
+ /* ERANGE is the only strtoull error triggerable
+ * by strings matching the pattern */
+ assert(errno == 0);
return DT_LITERAL;
}
<*>{CHAR_LITERAL} {
- yytext[yyleng-1] = '\0';
- yylval.literal = xstrdup(yytext+1);
- DPRINT("Character literal: %s\n", yylval.literal);
+ struct data d;
+ DPRINT("Character literal: %s\n", yytext);
+
+ d = data_copy_escape_string(yytext+1, yyleng-2);
+ if (d.len == 1) {
+ lexical_error("Empty character literal");
+ yylval.integer = 0;
+ return DT_CHAR_LITERAL;
+ }
+
+ yylval.integer = (unsigned char)d.val[0];
+
+ if (d.len > 2)
+ lexical_error("Character literal has %d"
+ " characters instead of 1",
+ d.len - 1);
+
return DT_CHAR_LITERAL;
}
@@ -148,9 +212,10 @@ static int pop_input_file(void);
return ']';
}
-<PROPNODENAME>{PROPNODECHAR}+ {
+<PROPNODENAME>\\?{PROPNODECHAR}+ {
DPRINT("PropNodeName: %s\n", yytext);
- yylval.propnodename = xstrdup(yytext);
+ yylval.propnodename = xstrdup((yytext[0] == '\\') ?
+ yytext + 1 : yytext);
BEGIN_DEFAULT();
return DT_PROPNODENAME;
}
@@ -202,13 +267,24 @@ static void push_input_file(const char *filename)
}
-static int pop_input_file(void)
+static bool pop_input_file(void)
{
if (srcfile_pop() == 0)
- return 0;
+ return false;
yypop_buffer_state();
yyin = current_srcfile->f;
- return 1;
+ return true;
+}
+
+static void lexical_error(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ srcpos_verror(&yylloc, "Lexical error", fmt, ap);
+ va_end(ap);
+
+ treesource_error = true;
}
diff --git a/dtc-parser.y b/dtc-parser.y
index 6d5c2c2de6ca..bed857e72793 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -31,15 +31,11 @@ extern void print_error(char const *fmt, ...);
extern void yyerror(char const *s);
extern struct boot_info *the_boot_info;
-extern int treesource_error;
-
-static unsigned long long eval_literal(const char *s, int base, int bits);
-static unsigned char eval_char_literal(const char *s);
+extern bool treesource_error;
%}
%union {
char *propnodename;
- char *literal;
char *labelref;
unsigned int cbase;
uint8_t byte;
@@ -62,9 +58,11 @@ static unsigned char eval_char_literal(const char *s);
%token DT_MEMRESERVE
%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
%token DT_BITS
+%token DT_DEL_PROP
+%token DT_DEL_NODE
%token <propnodename> DT_PROPNODENAME
-%token <literal> DT_LITERAL
-%token <literal> DT_CHAR_LITERAL
+%token <integer> DT_LITERAL
+%token <integer> DT_CHAR_LITERAL
%token <cbase> DT_BASE
%token <byte> DT_BYTE
%token <data> DT_STRING
@@ -153,6 +151,17 @@ devicetree:
print_error("label or path, '%s', not found", $2);
$$ = $1;
}
+ | devicetree DT_DEL_NODE DT_REF ';'
+ {
+ struct node *target = get_node_by_ref($1, $3);
+
+ if (!target)
+ print_error("label or path, '%s', not found", $3);
+ else
+ delete_node(target);
+
+ $$ = $1;
+ }
;
nodedef:
@@ -182,6 +191,10 @@ propdef:
{
$$ = build_property($1, empty_data);
}
+ | DT_DEL_PROP DT_PROPNODENAME ';'
+ {
+ $$ = build_property_delete($2);
+ }
| DT_LABEL propdef
{
add_label(&$2->labels, $1);
@@ -213,10 +226,9 @@ propdata:
if ($6 != 0)
if (fseek(f, $6, SEEK_SET) != 0)
- print_error("Couldn't seek to offset %llu in \"%s\": %s",
- (unsigned long long)$6,
- $4.val,
- strerror(errno));
+ die("Couldn't seek to offset %llu in \"%s\": %s",
+ (unsigned long long)$6, $4.val,
+ strerror(errno));
d = data_copy_file(f, $8);
@@ -257,18 +269,20 @@ propdataprefix:
arrayprefix:
DT_BITS DT_LITERAL '<'
{
- $$.data = empty_data;
- $$.bits = eval_literal($2, 0, 7);
+ unsigned long long bits;
- if (($$.bits != 8) &&
- ($$.bits != 16) &&
- ($$.bits != 32) &&
- ($$.bits != 64))
+ bits = $2;
+
+ if ((bits != 8) && (bits != 16) &&
+ (bits != 32) && (bits != 64))
{
print_error("Only 8, 16, 32 and 64-bit elements"
" are currently supported");
- $$.bits = 32;
+ bits = 32;
}
+
+ $$.data = empty_data;
+ $$.bits = bits;
}
| '<'
{
@@ -317,13 +331,7 @@ arrayprefix:
integer_prim:
DT_LITERAL
- {
- $$ = eval_literal($1, 0, 64);
- }
| DT_CHAR_LITERAL
- {
- $$ = eval_char_literal($1);
- }
| '(' integer_expr ')'
{
$$ = $2;
@@ -440,6 +448,10 @@ subnode:
{
$$ = name_node($2, $1);
}
+ | DT_DEL_NODE DT_PROPNODENAME ';'
+ {
+ $$ = name_node(build_node_delete(), $2);
+ }
| DT_LABEL subnode
{
add_label(&$2->labels, $1);
@@ -454,58 +466,12 @@ void print_error(char const *fmt, ...)
va_list va;
va_start(va, fmt);
- srcpos_verror(&yylloc, fmt, va);
+ srcpos_verror(&yylloc, "Error", fmt, va);
va_end(va);
- treesource_error = 1;
+ treesource_error = true;
}
void yyerror(char const *s) {
print_error("%s", s);
}
-
-static unsigned long long eval_literal(const char *s, int base, int bits)
-{
- unsigned long long val;
- char *e;
-
- errno = 0;
- val = strtoull(s, &e, base);
- if (*e) {
- size_t uls = strspn(e, "UL");
- if (e[uls])
- print_error("bad characters in literal");
- }
- if ((errno == ERANGE)
- || ((bits < 64) && (val >= (1ULL << bits))))
- print_error("literal out of range");
- else if (errno != 0)
- print_error("bad literal");
- return val;
-}
-
-static unsigned char eval_char_literal(const char *s)
-{
- int i = 1;
- char c = s[0];
-
- if (c == '\0')
- {
- print_error("empty character literal");
- return 0;
- }
-
- /*
- * If the first character in the character literal is a \ then process
- * the remaining characters as an escape encoding. If the first
- * character is neither an escape or a terminator it should be the only
- * character in the literal and will be returned.
- */
- if (c == '\\')
- c = get_escape_char(s, &i);
-
- if (s[i] != '\0')
- print_error("malformed character literal");
-
- return c;
-}
diff --git a/dtc.c b/dtc.c
index a375683c1534..d36ccdc2176f 100644
--- a/dtc.c
+++ b/dtc.c
@@ -21,8 +21,6 @@
#include "dtc.h"
#include "srcpos.h"
-#include "version_gen.h"
-
/*
* Command line options
*/
@@ -49,55 +47,60 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
fill_fullpaths(child, tree->fullpath);
}
-static void __attribute__ ((noreturn)) usage(void)
-{
- fprintf(stderr, "Usage:\n");
- fprintf(stderr, "\tdtc [options] <input file>\n");
- fprintf(stderr, "\nOptions:\n");
- fprintf(stderr, "\t-h\n");
- fprintf(stderr, "\t\tThis help text\n");
- fprintf(stderr, "\t-q\n");
- fprintf(stderr, "\t\tQuiet: -q suppress warnings, -qq errors, -qqq all\n");
- fprintf(stderr, "\t-I <input format>\n");
- fprintf(stderr, "\t\tInput formats are:\n");
- fprintf(stderr, "\t\t\tdts - device tree source text\n");
- fprintf(stderr, "\t\t\tdtb - device tree blob\n");
- fprintf(stderr, "\t\t\tfs - /proc/device-tree style directory\n");
- fprintf(stderr, "\t-o <output file>\n");
- fprintf(stderr, "\t-O <output format>\n");
- fprintf(stderr, "\t\tOutput formats are:\n");
- fprintf(stderr, "\t\t\tdts - device tree source text\n");
- fprintf(stderr, "\t\t\tdtb - device tree blob\n");
- fprintf(stderr, "\t\t\tasm - assembler source\n");
- fprintf(stderr, "\t-V <output version>\n");
- fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION);
- fprintf(stderr, "\t-d <output dependency file>\n");
- fprintf(stderr, "\t-R <number>\n");
- fprintf(stderr, "\t\tMake space for <number> reserve map entries (relevant for \n\t\tdtb and asm output only)\n");
- fprintf(stderr, "\t-S <bytes>\n");
- fprintf(stderr, "\t\tMake the blob at least <bytes> long (extra space)\n");
- fprintf(stderr, "\t-p <bytes>\n");
- fprintf(stderr, "\t\tAdd padding to the blob of <bytes> long (extra space)\n");
- fprintf(stderr, "\t-b <number>\n");
- fprintf(stderr, "\t\tSet the physical boot cpu\n");
- fprintf(stderr, "\t-f\n");
- fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
- fprintf(stderr, "\t-i\n");
- fprintf(stderr, "\t\tAdd a path to search for include files\n");
- fprintf(stderr, "\t-s\n");
- fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\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");
- fprintf(stderr, "\t-W [no-]<checkname>\n");
- fprintf(stderr, "\t-E [no-]<checkname>\n");
- fprintf(stderr, "\t\t\tenable or disable warnings and errors\n");
- exit(3);
-}
+/* Usage related data. */
+static const char usage_synopsis[] = "dtc [options] <input file>";
+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
+static struct option const usage_long_opts[] = {
+ {"quiet", no_argument, NULL, 'q'},
+ {"in-format", a_argument, NULL, 'I'},
+ {"out", a_argument, NULL, 'o'},
+ {"out-format", a_argument, NULL, 'O'},
+ {"out-version", a_argument, NULL, 'V'},
+ {"out-dependency", a_argument, NULL, 'd'},
+ {"reserve", a_argument, NULL, 'R'},
+ {"space", a_argument, NULL, 'S'},
+ {"pad", a_argument, NULL, 'p'},
+ {"boot-cpu", a_argument, NULL, 'b'},
+ {"force", no_argument, NULL, 'f'},
+ {"include", a_argument, NULL, 'i'},
+ {"sort", no_argument, NULL, 's'},
+ {"phandle", a_argument, NULL, 'H'},
+ {"warning", a_argument, NULL, 'W'},
+ {"error", a_argument, NULL, 'E'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'v'},
+ {NULL, no_argument, NULL, 0x0},
+};
+static const char * const usage_opts_help[] = {
+ "\n\tQuiet: -q suppress warnings, -qq errors, -qqq all",
+ "\n\tInput formats are:\n"
+ "\t\tdts - device tree source text\n"
+ "\t\tdtb - device tree blob\n"
+ "\t\tfs - /proc/device-tree style directory",
+ "\n\tOutput file",
+ "\n\tOutput formats are:\n"
+ "\t\tdts - device tree source text\n"
+ "\t\tdtb - device tree blob\n"
+ "\t\tasm - assembler source",
+ "\n\tBlob version to produce, defaults to %d (for dtb and asm output)", //, DEFAULT_FDT_VERSION);
+ "\n\tOutput dependency file",
+ "\n\ttMake space for <number> reserve map entries (for dtb and asm output)",
+ "\n\tMake the blob at least <bytes> long (extra space)",
+ "\n\tAdd padding to the blob of <bytes> long (extra space)",
+ "\n\tSet the physical boot cpu",
+ "\n\tTry to produce output even if the input tree has errors",
+ "\n\tAdd a path to search for include files",
+ "\n\tSort nodes and properties before outputting (useful for comparing trees)",
+ "\n\tValid phandle formats are:\n"
+ "\t\tlegacy - \"linux,phandle\" properties only\n"
+ "\t\tepapr - \"phandle\" properties only\n"
+ "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties",
+ "\n\tEnable/disable warnings (prefix with \"no-\")",
+ "\n\tEnable/disable errors (prefix with \"no-\")",
+ "\n\tPrint this help and exit",
+ "\n\tPrint version and exit",
+ NULL,
+};
int main(int argc, char *argv[])
{
@@ -106,7 +109,7 @@ int main(int argc, char *argv[])
const char *outform = "dts";
const char *outname = "-";
const char *depname = NULL;
- int force = 0, sort = 0;
+ bool force = false, sort = false;
const char *arg;
int opt;
FILE *outf = NULL;
@@ -118,8 +121,7 @@ int main(int argc, char *argv[])
minsize = 0;
padsize = 0;
- while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:"))
- != EOF) {
+ while ((opt = util_getopt_long()) != EOF) {
switch (opt) {
case 'I':
inform = optarg;
@@ -146,7 +148,7 @@ int main(int argc, char *argv[])
padsize = strtol(optarg, NULL, 0);
break;
case 'f':
- force = 1;
+ force = true;
break;
case 'q':
quiet++;
@@ -158,8 +160,7 @@ int main(int argc, char *argv[])
srcfile_add_search_path(optarg);
break;
case 'v':
- printf("Version: %s\n", DTC_VERSION);
- exit(0);
+ util_version();
case 'H':
if (streq(optarg, "legacy"))
phandle_format = PHANDLE_LEGACY;
@@ -173,7 +174,7 @@ int main(int argc, char *argv[])
break;
case 's':
- sort = 1;
+ sort = true;
break;
case 'W':
@@ -185,13 +186,14 @@ int main(int argc, char *argv[])
break;
case 'h':
+ usage(NULL);
default:
- usage();
+ usage("unknown option");
}
}
if (argc > (optind+1))
- usage();
+ usage("missing files");
else if (argc < (optind+1))
arg = "-";
else
@@ -201,9 +203,6 @@ 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");
-
if (depname) {
depfile = fopen(depname, "w");
if (!depfile)
diff --git a/dtc.h b/dtc.h
index 7ee2d544b67e..20e4d5620cb5 100644
--- a/dtc.h
+++ b/dtc.h
@@ -66,7 +66,6 @@ typedef uint32_t cell_t;
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
/* Data blobs */
enum markertype {
@@ -119,7 +118,7 @@ struct data data_append_align(struct data d, int align);
struct data data_add_marker(struct data d, enum markertype type, char *ref);
-int data_is_one_string(struct data d);
+bool data_is_one_string(struct data d);
/* DT constraints */
@@ -128,11 +127,13 @@ int data_is_one_string(struct data d);
/* Live trees */
struct label {
+ bool deleted;
char *label;
struct label *next;
};
struct property {
+ bool deleted;
char *name;
struct data val;
@@ -142,6 +143,7 @@ struct property {
};
struct node {
+ bool deleted;
char *name;
struct property *proplist;
struct node *children;
@@ -158,28 +160,47 @@ struct node {
struct label *labels;
};
-#define for_each_label(l0, l) \
+#define for_each_label_withdel(l0, l) \
for ((l) = (l0); (l); (l) = (l)->next)
-#define for_each_property(n, p) \
+#define for_each_label(l0, l) \
+ for_each_label_withdel(l0, l) \
+ if (!(l)->deleted)
+
+#define for_each_property_withdel(n, p) \
for ((p) = (n)->proplist; (p); (p) = (p)->next)
-#define for_each_child(n, c) \
+#define for_each_property(n, p) \
+ for_each_property_withdel(n, p) \
+ if (!(p)->deleted)
+
+#define for_each_child_withdel(n, c) \
for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
+#define for_each_child(n, c) \
+ for_each_child_withdel(n, c) \
+ if (!(c)->deleted)
+
void add_label(struct label **labels, char *label);
+void delete_labels(struct label **labels);
struct property *build_property(char *name, struct data val);
+struct property *build_property_delete(char *name);
struct property *chain_property(struct property *first, struct property *list);
struct property *reverse_properties(struct property *first);
struct node *build_node(struct property *proplist, struct node *children);
+struct node *build_node_delete(void);
struct node *name_node(struct node *node, char *name);
struct node *chain_node(struct node *first, struct node *list);
struct node *merge_nodes(struct node *old_node, struct node *new_node);
void add_property(struct node *node, struct property *prop);
+void delete_property_by_name(struct node *node, char *name);
+void delete_property(struct property *prop);
void add_child(struct node *parent, struct node *child);
+void delete_node_by_name(struct node *parent, char *name);
+void delete_node(struct node *node);
const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname);
@@ -227,7 +248,7 @@ void sort_tree(struct boot_info *bi);
/* Checks */
void parse_checks_option(bool warn, bool error, const char *optarg);
-void process_checks(int force, struct boot_info *bi);
+void process_checks(bool force, struct boot_info *bi);
/* Flattened trees */
diff --git a/fdtdump.c b/fdtdump.c
index 207a46d64864..723770d6d337 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -2,14 +2,16 @@
* fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
*/
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#include <fdt.h>
+#include <libfdt.h>
#include <libfdt_env.h>
+#include <fdt.h>
#include "util.h"
@@ -17,33 +19,29 @@
#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4)))
-static void print_data(const char *data, int len)
+static const char *tagname(uint32_t tag)
{
- int i;
- const char *p = data;
-
- /* no data, don't print */
- if (len == 0)
- return;
-
- if (util_is_printable_string(data, len)) {
- printf(" = \"%s\"", (const char *)data);
- } else if ((len % 4) == 0) {
- printf(" = <");
- for (i = 0; i < len; i += 4)
- printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)),
- i < (len - 4) ? " " : "");
- printf(">");
- } else {
- printf(" = [");
- for (i = 0; i < len; i++)
- printf("%02x%s", *p++, i < len - 1 ? " " : "");
- printf("]");
- }
+ static const char * const names[] = {
+#define TN(t) [t] #t
+ TN(FDT_BEGIN_NODE),
+ TN(FDT_END_NODE),
+ TN(FDT_PROP),
+ TN(FDT_NOP),
+ TN(FDT_END),
+#undef TN
+ };
+ if (tag < ARRAY_SIZE(names))
+ if (names[tag])
+ return names[tag];
+ return "FDT_???";
}
-static void dump_blob(void *blob)
+#define dumpf(fmt, args...) \
+ do { if (debug) printf("// " fmt, ## args); } while (0)
+
+static void dump_blob(void *blob, bool debug)
{
+ uintptr_t blob_off = (uintptr_t)blob;
struct fdt_header *bph = blob;
uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
@@ -97,7 +95,8 @@ static void dump_blob(void *blob)
p = p_struct;
while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
- /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
+ dumpf("%04zx: tag: 0x%08x (%s)\n",
+ (uintptr_t)p - blob_off - 4, tag, tagname(tag));
if (tag == FDT_BEGIN_NODE) {
s = p;
@@ -136,27 +135,93 @@ static void dump_blob(void *blob)
p = PALIGN(p + sz, 4);
+ dumpf("%04zx: string: %s\n", (uintptr_t)s - blob_off, s);
+ dumpf("%04zx: value\n", (uintptr_t)t - blob_off);
printf("%*s%s", depth * shift, "", s);
- print_data(t, sz);
+ utilfdt_print_data(t, sz);
printf(";\n");
}
}
+/* Usage related data. */
+static const char usage_synopsis[] = "fdtdump [options] <file>";
+static const char usage_short_opts[] = "ds" USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+ {"debug", no_argument, NULL, 'd'},
+ {"scan", no_argument, NULL, 's'},
+ USAGE_COMMON_LONG_OPTS
+};
+static const char * const usage_opts_help[] = {
+ "Dump debug information while decoding the file",
+ "Scan for an embedded fdt in file",
+ USAGE_COMMON_OPTS_HELP
+};
int main(int argc, char *argv[])
{
+ int opt;
+ const char *file;
char *buf;
+ bool debug = false;
+ bool scan = false;
+ off_t len;
+
+ while ((opt = util_getopt_long()) != EOF) {
+ switch (opt) {
+ case_USAGE_COMMON_FLAGS
- if (argc < 2) {
- fprintf(stderr, "supply input filename\n");
- return 5;
+ case 'd':
+ debug = true;
+ break;
+ case 's':
+ scan = true;
+ break;
+ }
+ }
+ if (optind != argc - 1)
+ usage("missing input filename");
+ file = argv[optind];
+
+ buf = utilfdt_read_len(file, &len);
+ if (!buf)
+ die("could not read: %s\n", file);
+
+ /* try and locate an embedded fdt in a bigger blob */
+ if (scan) {
+ unsigned char smagic[4];
+ char *p = buf;
+ char *endp = buf + len;
+
+ fdt_set_magic(smagic, FDT_MAGIC);
+
+ /* poor man's memmem */
+ while (true) {
+ p = memchr(p, smagic[0], endp - p - 4);
+ if (!p)
+ break;
+ if (fdt_magic(p) == FDT_MAGIC) {
+ /* try and validate the main struct */
+ off_t this_len = endp - p;
+ fdt32_t max_version = 17;
+ if (fdt_version(p) <= max_version &&
+ fdt_last_comp_version(p) < max_version &&
+ fdt_totalsize(p) < this_len &&
+ fdt_off_dt_struct(p) < this_len &&
+ fdt_off_dt_strings(p) < this_len)
+ break;
+ if (debug)
+ printf("%s: skipping fdt magic at offset %#zx\n",
+ file, p - buf);
+ }
+ ++p;
+ }
+ if (!p)
+ die("%s: could not locate fdt magic\n", file);
+ printf("%s: found fdt at offset %#zx\n", file, p - buf);
+ buf = p;
}
- buf = utilfdt_read(argv[1]);
- if (buf)
- dump_blob(buf);
- else
- return 10;
+ dump_blob(buf, debug);
return 0;
}
diff --git a/fdtget.c b/fdtget.c
index c2fbab2a5476..43774192241f 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -277,33 +277,33 @@ static int do_fdtget(struct display_info *disp, const char *filename,
return 0;
}
-static const char *usage_msg =
- "fdtget - read values from device tree\n"
- "\n"
- "Each value is printed on a new line.\n\n"
- "Usage:\n"
+/* Usage related data. */
+static const char usage_synopsis[] =
+ "read values from device tree\n"
" fdtget <options> <dt file> [<node> <property>]...\n"
" fdtget -p <options> <dt file> [<node> ]...\n"
- "Options:\n"
- "\t-t <type>\tType of data\n"
- "\t-p\t\tList properties for each node\n"
- "\t-l\t\tList subnodes for each node\n"
- "\t-d\t\tDefault value to display when the property is "
- "missing\n"
- "\t-h\t\tPrint this help\n\n"
+ "\n"
+ "Each value is printed on a new line.\n"
USAGE_TYPE_MSG;
-
-static void usage(const char *msg)
-{
- if (msg)
- fprintf(stderr, "Error: %s\n\n", msg);
-
- fprintf(stderr, "%s", usage_msg);
- exit(2);
-}
+static const char usage_short_opts[] = "t:pld:" USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+ {"type", a_argument, NULL, 't'},
+ {"properties", no_argument, NULL, 'p'},
+ {"list", no_argument, NULL, 'l'},
+ {"default", a_argument, NULL, 'd'},
+ USAGE_COMMON_LONG_OPTS,
+};
+static const char * const usage_opts_help[] = {
+ "Type of data",
+ "List properties for each node",
+ "List subnodes for each node",
+ "Default value to display when the property is missing",
+ USAGE_COMMON_OPTS_HELP
+};
int main(int argc, char *argv[])
{
+ int opt;
char *filename = NULL;
struct display_info disp;
int args_per_step = 2;
@@ -312,20 +312,14 @@ int main(int argc, char *argv[])
memset(&disp, '\0', sizeof(disp));
disp.size = -1;
disp.mode = MODE_SHOW_VALUE;
- for (;;) {
- int c = getopt(argc, argv, "d:hlpt:");
- if (c == -1)
- break;
-
- switch (c) {
- case 'h':
- case '?':
- usage(NULL);
+ while ((opt = util_getopt_long()) != EOF) {
+ switch (opt) {
+ case_USAGE_COMMON_FLAGS
case 't':
if (utilfdt_decode_type(optarg, &disp.type,
&disp.size))
- usage("Invalid type string");
+ usage("invalid type string");
break;
case 'p':
@@ -347,7 +341,7 @@ int main(int argc, char *argv[])
if (optind < argc)
filename = argv[optind++];
if (!filename)
- usage("Missing filename");
+ usage("missing filename");
argv += optind;
argc -= optind;
@@ -358,7 +352,7 @@ int main(int argc, char *argv[])
/* Check for node, property arguments */
if (args_per_step == 2 && (argc % 2))
- usage("Must have an even number of arguments");
+ usage("must have an even number of arguments");
if (do_fdtget(&disp, filename, argv, argc, args_per_step))
return 1;
diff --git a/fdtput.c b/fdtput.c
index f2197f51930b..5226a4efd546 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -131,19 +131,59 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
return 0;
}
-static int store_key_value(void *blob, const char *node_name,
+#define ALIGN(x) (((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1))
+
+static char *_realloc_fdt(char *fdt, int delta)
+{
+ int new_sz = fdt_totalsize(fdt) + delta;
+ fdt = xrealloc(fdt, new_sz);
+ fdt_open_into(fdt, fdt, new_sz);
+ return fdt;
+}
+
+static char *realloc_node(char *fdt, const char *name)
+{
+ int delta;
+ /* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */
+ delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1)
+ + FDT_TAGSIZE;
+ return _realloc_fdt(fdt, delta);
+}
+
+static char *realloc_property(char *fdt, int nodeoffset,
+ const char *name, int newlen)
+{
+ int delta = 0;
+ int oldlen = 0;
+
+ if (!fdt_get_property(fdt, nodeoffset, name, &oldlen))
+ /* strings + property header */
+ delta = sizeof(struct fdt_property) + strlen(name) + 1;
+
+ if (newlen > oldlen)
+ /* actual value in off_struct */
+ delta += ALIGN(newlen) - ALIGN(oldlen);
+
+ return _realloc_fdt(fdt, delta);
+}
+
+static int store_key_value(char **blob, const char *node_name,
const char *property, const char *buf, int len)
{
int node;
int err;
- node = fdt_path_offset(blob, node_name);
+ node = fdt_path_offset(*blob, node_name);
if (node < 0) {
report_error(node_name, -1, node);
return -1;
}
- err = fdt_setprop(blob, node, property, buf, len);
+ err = fdt_setprop(*blob, node, property, buf, len);
+ if (err == -FDT_ERR_NOSPACE) {
+ *blob = realloc_property(*blob, node, property, len);
+ err = fdt_setprop(*blob, node, property, buf, len);
+ }
if (err) {
report_error(property, -1, err);
return -1;
@@ -161,7 +201,7 @@ static int store_key_value(void *blob, const char *node_name,
* @param in_path Path to process
* @return 0 if ok, -1 on error
*/
-static int create_paths(void *blob, const char *in_path)
+static int create_paths(char **blob, const char *in_path)
{
const char *path = in_path;
const char *sep;
@@ -177,10 +217,11 @@ static int create_paths(void *blob, const char *in_path)
if (!sep)
sep = path + strlen(path);
- node = fdt_subnode_offset_namelen(blob, offset, path,
+ node = fdt_subnode_offset_namelen(*blob, offset, path,
sep - path);
if (node == -FDT_ERR_NOTFOUND) {
- node = fdt_add_subnode_namelen(blob, offset, path,
+ *blob = realloc_node(*blob, path);
+ node = fdt_add_subnode_namelen(*blob, offset, path,
sep - path);
}
if (node < 0) {
@@ -203,7 +244,7 @@ static int create_paths(void *blob, const char *in_path)
* @param node_name Name of node to create
* @return new node offset if found, or -1 on failure
*/
-static int create_node(void *blob, const char *node_name)
+static int create_node(char **blob, const char *node_name)
{
int node = 0;
char *p;
@@ -215,15 +256,17 @@ static int create_node(void *blob, const char *node_name)
}
*p = '\0';
+ *blob = realloc_node(*blob, p + 1);
+
if (p > node_name) {
- node = fdt_path_offset(blob, node_name);
+ node = fdt_path_offset(*blob, node_name);
if (node < 0) {
report_error(node_name, -1, node);
return -1;
}
}
- node = fdt_add_subnode(blob, node, p + 1);
+ node = fdt_add_subnode(*blob, node, p + 1);
if (node < 0) {
report_error(p + 1, -1, node);
return -1;
@@ -250,66 +293,64 @@ static int do_fdtput(struct display_info *disp, const char *filename,
* store them into the property.
*/
assert(arg_count >= 2);
- if (disp->auto_path && create_paths(blob, *arg))
+ if (disp->auto_path && create_paths(&blob, *arg))
return -1;
if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
- store_key_value(blob, *arg, arg[1], value, len))
+ store_key_value(&blob, *arg, arg[1], value, len))
ret = -1;
break;
case OPER_CREATE_NODE:
for (; ret >= 0 && arg_count--; arg++) {
if (disp->auto_path)
- ret = create_paths(blob, *arg);
+ ret = create_paths(&blob, *arg);
else
- ret = create_node(blob, *arg);
+ ret = create_node(&blob, *arg);
}
break;
}
- if (ret >= 0)
+ if (ret >= 0) {
+ fdt_pack(blob);
ret = utilfdt_write(filename, blob);
+ }
free(blob);
return ret;
}
-static const char *usage_msg =
- "fdtput - write a property value to a device tree\n"
- "\n"
- "The command line arguments are joined together into a single value.\n"
- "\n"
- "Usage:\n"
+/* Usage related data. */
+static const char usage_synopsis[] =
+ "write a property value to a device tree\n"
" fdtput <options> <dt file> <node> <property> [<value>...]\n"
" fdtput -c <options> <dt file> [<node>...]\n"
- "Options:\n"
- "\t-c\t\tCreate nodes if they don't already exist\n"
- "\t-p\t\tAutomatically create nodes as needed for the node path\n"
- "\t-t <type>\tType of data\n"
- "\t-v\t\tVerbose: display each value decoded from command line\n"
- "\t-h\t\tPrint this help\n\n"
+ "\n"
+ "The command line arguments are joined together into a single value.\n"
USAGE_TYPE_MSG;
-
-static void usage(const char *msg)
-{
- if (msg)
- fprintf(stderr, "Error: %s\n\n", msg);
-
- fprintf(stderr, "%s", usage_msg);
- exit(2);
-}
+static const char usage_short_opts[] = "cpt:v" USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+ {"create", no_argument, NULL, 'c'},
+ {"auto-path", no_argument, NULL, 'p'},
+ {"type", a_argument, NULL, 't'},
+ {"verbose", no_argument, NULL, 'v'},
+ USAGE_COMMON_LONG_OPTS,
+};
+static const char * const usage_opts_help[] = {
+ "Create nodes if they don't already exist",
+ "Automatically create nodes as needed for the node path",
+ "Type of data",
+ "Display each value decoded from command line",
+ USAGE_COMMON_OPTS_HELP
+};
int main(int argc, char *argv[])
{
+ int opt;
struct display_info disp;
char *filename = NULL;
memset(&disp, '\0', sizeof(disp));
disp.size = -1;
disp.oper = OPER_WRITE_PROP;
- for (;;) {
- int c = getopt(argc, argv, "chpt:v");
- if (c == -1)
- break;
-
+ while ((opt = util_getopt_long()) != EOF) {
/*
* TODO: add options to:
* - delete property
@@ -317,15 +358,13 @@ int main(int argc, char *argv[])
* - rename node
* - pack fdt before writing
* - set amount of free space when writing
- * - expand fdt if value doesn't fit
*/
- switch (c) {
+ switch (opt) {
+ case_USAGE_COMMON_FLAGS
+
case 'c':
disp.oper = OPER_CREATE_NODE;
break;
- case 'h':
- case '?':
- usage(NULL);
case 'p':
disp.auto_path = 1;
break;
@@ -344,16 +383,16 @@ int main(int argc, char *argv[])
if (optind < argc)
filename = argv[optind++];
if (!filename)
- usage("Missing filename");
+ usage("missing filename");
argv += optind;
argc -= optind;
if (disp.oper == OPER_WRITE_PROP) {
if (argc < 1)
- usage("Missing node");
+ usage("missing node");
if (argc < 2)
- usage("Missing property");
+ usage("missing property");
}
if (do_fdtput(&disp, filename, argv, argc))
diff --git a/flattree.c b/flattree.c
index 28d0b2381df6..bd99fa2d33b8 100644
--- a/flattree.c
+++ b/flattree.c
@@ -261,7 +261,10 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
{
struct property *prop;
struct node *child;
- int seen_name_prop = 0;
+ bool seen_name_prop = false;
+
+ if (tree->deleted)
+ return;
emit->beginnode(etarget, tree->labels);
@@ -276,7 +279,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
int nameoff;
if (streq(prop->name, "name"))
- seen_name_prop = 1;
+ seen_name_prop = true;
nameoff = stringtable_insert(strbuf, prop->name);
diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt
index 4366627a5521..91126c000a1e 100644
--- a/libfdt/Makefile.libfdt
+++ b/libfdt/Makefile.libfdt
@@ -4,7 +4,7 @@
# be easily embeddable into other systems of Makefiles.
#
LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
-LIBFDT_INCLUDES = fdt.h libfdt.h
+LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
LIBFDT_VERSION = version.lds
LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
diff --git a/libfdt/fdt.c b/libfdt/fdt.c
index e56833ae9b6f..2ce6a44179de 100644
--- a/libfdt/fdt.c
+++ b/libfdt/fdt.c
@@ -92,7 +92,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
- const uint32_t *tagp, *lenp;
+ const fdt32_t *tagp, *lenp;
uint32_t tag;
int offset = startoffset;
const char *p;
@@ -198,6 +198,34 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
return offset;
}
+int fdt_first_subnode(const void *fdt, int offset)
+{
+ int depth = 0;
+
+ offset = fdt_next_node(fdt, offset, &depth);
+ if (offset < 0 || depth != 1)
+ return -FDT_ERR_NOTFOUND;
+
+ return offset;
+}
+
+int fdt_next_subnode(const void *fdt, int offset)
+{
+ int depth = 1;
+
+ /*
+ * With respect to the parent, the depth of the next subnode will be
+ * the same as the last.
+ */
+ do {
+ offset = fdt_next_node(fdt, offset, &depth);
+ if (offset < 0 || depth < 1)
+ return -FDT_ERR_NOTFOUND;
+ } while (depth > 1);
+
+ return offset;
+}
+
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
{
int len = strlen(s) + 1;
diff --git a/libfdt/fdt.h b/libfdt/fdt.h
index 48ccfd910000..526aedb51556 100644
--- a/libfdt/fdt.h
+++ b/libfdt/fdt.h
@@ -1,48 +1,99 @@
#ifndef _FDT_H
#define _FDT_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright 2012 Kim Phillips, Freescale Semiconductor.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
#ifndef __ASSEMBLY__
struct fdt_header {
- uint32_t magic; /* magic word FDT_MAGIC */
- uint32_t totalsize; /* total size of DT block */
- uint32_t off_dt_struct; /* offset to structure */
- uint32_t off_dt_strings; /* offset to strings */
- uint32_t off_mem_rsvmap; /* offset to memory reserve map */
- uint32_t version; /* format version */
- uint32_t last_comp_version; /* last compatible version */
+ fdt32_t magic; /* magic word FDT_MAGIC */
+ fdt32_t totalsize; /* total size of DT block */
+ fdt32_t off_dt_struct; /* offset to structure */
+ fdt32_t off_dt_strings; /* offset to strings */
+ fdt32_t off_mem_rsvmap; /* offset to memory reserve map */
+ fdt32_t version; /* format version */
+ fdt32_t last_comp_version; /* last compatible version */
/* version 2 fields below */
- uint32_t boot_cpuid_phys; /* Which physical CPU id we're
+ fdt32_t boot_cpuid_phys; /* Which physical CPU id we're
booting on */
/* version 3 fields below */
- uint32_t size_dt_strings; /* size of the strings block */
+ fdt32_t size_dt_strings; /* size of the strings block */
/* version 17 fields below */
- uint32_t size_dt_struct; /* size of the structure block */
+ fdt32_t size_dt_struct; /* size of the structure block */
};
struct fdt_reserve_entry {
- uint64_t address;
- uint64_t size;
+ fdt64_t address;
+ fdt64_t size;
};
struct fdt_node_header {
- uint32_t tag;
+ fdt32_t tag;
char name[0];
};
struct fdt_property {
- uint32_t tag;
- uint32_t len;
- uint32_t nameoff;
+ fdt32_t tag;
+ fdt32_t len;
+ fdt32_t nameoff;
char data[0];
};
#endif /* !__ASSEMBLY */
#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
-#define FDT_TAGSIZE sizeof(uint32_t)
+#define FDT_TAGSIZE sizeof(fdt32_t)
#define FDT_BEGIN_NODE 0x1 /* Start node: full name */
#define FDT_END_NODE 0x2 /* End node */
@@ -51,10 +102,10 @@ struct fdt_property {
#define FDT_NOP 0x4 /* nop */
#define FDT_END 0x9
-#define FDT_V1_SIZE (7*sizeof(uint32_t))
-#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(uint32_t))
-#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(uint32_t))
+#define FDT_V1_SIZE (7*sizeof(fdt32_t))
+#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t))
+#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t))
#define FDT_V16_SIZE FDT_V3_SIZE
-#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(uint32_t))
+#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t))
#endif /* _FDT_H */
diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
index 02b6d687537f..50007f61ce66 100644
--- a/libfdt/fdt_ro.c
+++ b/libfdt/fdt_ro.c
@@ -322,7 +322,7 @@ const void *fdt_getprop(const void *fdt, int nodeoffset,
uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
{
- const uint32_t *php;
+ const fdt32_t *php;
int len;
/* FIXME: This is a bit sub-optimal, since we potentially scan
@@ -515,8 +515,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
return offset; /* error from fdt_next_node() */
}
-static int _fdt_stringlist_contains(const char *strlist, int listlen,
- const char *str)
+int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
{
int len = strlen(str);
const char *p;
@@ -542,7 +541,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
if (!prop)
return len;
- if (_fdt_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 24437dfc32b8..fdba618f12ae 100644
--- a/libfdt/fdt_rw.c
+++ b/libfdt/fdt_rw.c
@@ -339,7 +339,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
int nodelen;
int err;
uint32_t tag;
- uint32_t *endtag;
+ fdt32_t *endtag;
FDT_RW_CHECK_HEADER(fdt);
@@ -366,7 +366,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
memcpy(nh->name, name, namelen);
- endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
+ endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
*endtag = cpu_to_fdt32(FDT_END_NODE);
return offset;
diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c
index 55ebebf1eb20..6a804859fd0c 100644
--- a/libfdt/fdt_sw.c
+++ b/libfdt/fdt_sw.c
@@ -107,6 +107,38 @@ int fdt_create(void *buf, int bufsize)
return 0;
}
+int fdt_resize(void *fdt, void *buf, int bufsize)
+{
+ size_t headsize, tailsize;
+ char *oldtail, *newtail;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ headsize = fdt_off_dt_struct(fdt);
+ tailsize = fdt_size_dt_strings(fdt);
+
+ if ((headsize + tailsize) > bufsize)
+ return -FDT_ERR_NOSPACE;
+
+ oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
+ newtail = (char *)buf + bufsize - tailsize;
+
+ /* Two cases to avoid clobbering data if the old and new
+ * buffers partially overlap */
+ if (buf <= fdt) {
+ memmove(buf, fdt, headsize);
+ memmove(newtail, oldtail, tailsize);
+ } else {
+ memmove(newtail, oldtail, tailsize);
+ memmove(buf, fdt, headsize);
+ }
+
+ fdt_set_off_dt_strings(buf, bufsize);
+ fdt_set_totalsize(buf, bufsize);
+
+ return 0;
+}
+
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
{
struct fdt_reserve_entry *re;
@@ -153,7 +185,7 @@ int fdt_begin_node(void *fdt, const char *name)
int fdt_end_node(void *fdt)
{
- uint32_t *en;
+ fdt32_t *en;
FDT_SW_CHECK_HEADER(fdt);
@@ -213,7 +245,7 @@ int fdt_property(void *fdt, const char *name, const void *val, int len)
int fdt_finish(void *fdt)
{
char *p = (char *)fdt;
- uint32_t *end;
+ fdt32_t *end;
int oldstroffset, newstroffset;
uint32_t tag;
int offset, nextoffset;
diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c
index 6025fa1fe8fe..c5bbb68d3273 100644
--- a/libfdt/fdt_wip.c
+++ b/libfdt/fdt_wip.c
@@ -74,7 +74,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
static void _fdt_nop_region(void *start, int len)
{
- uint32_t *p;
+ fdt32_t *p;
for (p = start; (char *)p < ((char *)start + len); p++)
*p = cpu_to_fdt32(FDT_NOP);
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
index 73f49759a5e7..c4d5a9134bfc 100644
--- a/libfdt/libfdt.h
+++ b/libfdt/libfdt.h
@@ -136,6 +136,28 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
int fdt_next_node(const void *fdt, int offset, int *depth);
+/**
+ * fdt_first_subnode() - get offset of first direct subnode
+ *
+ * @fdt: FDT blob
+ * @offset: Offset of node to check
+ * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
+ */
+int fdt_first_subnode(const void *fdt, int offset);
+
+/**
+ * fdt_next_subnode() - get offset of next direct subnode
+ *
+ * After first calling fdt_first_subnode(), call this function repeatedly to
+ * get direct subnodes of a parent node.
+ *
+ * @fdt: FDT blob
+ * @offset: Offset of previous subnode
+ * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
+ * subnodes
+ */
+int fdt_next_subnode(const void *fdt, int offset);
+
/**********************************************************************/
/* General functions */
/**********************************************************************/
@@ -582,7 +604,7 @@ const char *fdt_get_alias_namelen(const void *fdt,
* value of the property named 'name' in the node /aliases.
*
* returns:
- * a pointer to the expansion of the alias named 'name', of it exists
+ * a pointer to the expansion of the alias named 'name', if 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);
@@ -816,6 +838,20 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
const char *compatible);
+/**
+ * fdt_stringlist_contains - check a string list property for a string
+ * @strlist: Property containing a list of strings to check
+ * @listlen: Length of property
+ * @str: String to search for
+ *
+ * This is a utility function provided for convenience. The list contains
+ * one or more strings, each terminated by \0, as is found in a device tree
+ * "compatible" property.
+ *
+ * @return: 1 if the string is found in the list, 0 not found, or invalid list
+ */
+int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
+
/**********************************************************************/
/* Write-in-place functions */
/**********************************************************************/
@@ -882,8 +918,8 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
const char *name, uint32_t val)
{
- val = cpu_to_fdt32(val);
- return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+ fdt32_t tmp = cpu_to_fdt32(val);
+ return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
}
/**
@@ -917,8 +953,8 @@ static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
const char *name, uint64_t val)
{
- val = cpu_to_fdt64(val);
- return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+ fdt64_t tmp = cpu_to_fdt64(val);
+ return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
}
/**
@@ -987,19 +1023,20 @@ int fdt_nop_node(void *fdt, int nodeoffset);
/**********************************************************************/
int fdt_create(void *buf, int bufsize);
+int fdt_resize(void *fdt, void *buf, int bufsize);
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
int fdt_finish_reservemap(void *fdt);
int fdt_begin_node(void *fdt, const char *name);
int fdt_property(void *fdt, const char *name, const void *val, int len);
static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
{
- val = cpu_to_fdt32(val);
- return fdt_property(fdt, name, &val, sizeof(val));
+ fdt32_t tmp = cpu_to_fdt32(val);
+ return fdt_property(fdt, name, &tmp, sizeof(tmp));
}
static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val)
{
- val = cpu_to_fdt64(val);
- return fdt_property(fdt, name, &val, sizeof(val));
+ fdt64_t tmp = cpu_to_fdt64(val);
+ return fdt_property(fdt, name, &tmp, sizeof(tmp));
}
static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
{
@@ -1154,8 +1191,8 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name,
uint32_t val)
{
- val = cpu_to_fdt32(val);
- return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+ fdt32_t tmp = cpu_to_fdt32(val);
+ return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
}
/**
@@ -1189,8 +1226,8 @@ static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name,
static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
uint64_t val)
{
- val = cpu_to_fdt64(val);
- return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+ fdt64_t tmp = cpu_to_fdt64(val);
+ return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
}
/**
@@ -1296,8 +1333,8 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
static inline int fdt_appendprop_u32(void *fdt, int nodeoffset,
const char *name, uint32_t val)
{
- val = cpu_to_fdt32(val);
- return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
+ fdt32_t tmp = cpu_to_fdt32(val);
+ return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
}
/**
@@ -1331,8 +1368,8 @@ static inline int fdt_appendprop_u32(void *fdt, int nodeoffset,
static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
const char *name, uint64_t val)
{
- val = cpu_to_fdt64(val);
- return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
+ fdt64_t tmp = cpu_to_fdt64(val);
+ return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
}
/**
diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h
index 213d7fb81c42..9dea97dfff81 100644
--- a/libfdt/libfdt_env.h
+++ b/libfdt/libfdt_env.h
@@ -1,29 +1,111 @@
#ifndef _LIBFDT_ENV_H
#define _LIBFDT_ENV_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright 2012 Kim Phillips, Freescale Semiconductor.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
#include <stddef.h>
#include <stdint.h>
#include <string.h>
-#define EXTRACT_BYTE(n) ((unsigned long long)((uint8_t *)&x)[n])
-static inline uint16_t fdt16_to_cpu(uint16_t x)
+#ifdef __CHECKER__
+#define __force __attribute__((force))
+#define __bitwise __attribute__((bitwise))
+#else
+#define __force
+#define __bitwise
+#endif
+
+typedef uint16_t __bitwise fdt16_t;
+typedef uint32_t __bitwise fdt32_t;
+typedef uint64_t __bitwise fdt64_t;
+
+#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n])
+#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1))
+#define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \
+ (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3))
+#define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \
+ (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \
+ (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \
+ (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7))
+
+static inline uint16_t fdt16_to_cpu(fdt16_t x)
+{
+ return (__force uint16_t)CPU_TO_FDT16(x);
+}
+static inline fdt16_t cpu_to_fdt16(uint16_t x)
{
- return (EXTRACT_BYTE(0) << 8) | EXTRACT_BYTE(1);
+ return (__force fdt16_t)CPU_TO_FDT16(x);
}
-#define cpu_to_fdt16(x) fdt16_to_cpu(x)
-static inline uint32_t fdt32_to_cpu(uint32_t x)
+static inline uint32_t fdt32_to_cpu(fdt32_t x)
{
- return (EXTRACT_BYTE(0) << 24) | (EXTRACT_BYTE(1) << 16) | (EXTRACT_BYTE(2) << 8) | EXTRACT_BYTE(3);
+ return (__force uint32_t)CPU_TO_FDT32(x);
+}
+static inline fdt32_t cpu_to_fdt32(uint32_t x)
+{
+ return (__force fdt32_t)CPU_TO_FDT32(x);
}
-#define cpu_to_fdt32(x) fdt32_to_cpu(x)
-static inline uint64_t fdt64_to_cpu(uint64_t x)
+static inline uint64_t fdt64_to_cpu(fdt64_t x)
+{
+ return (__force uint64_t)CPU_TO_FDT64(x);
+}
+static inline fdt64_t cpu_to_fdt64(uint64_t x)
{
- return (EXTRACT_BYTE(0) << 56) | (EXTRACT_BYTE(1) << 48) | (EXTRACT_BYTE(2) << 40) | (EXTRACT_BYTE(3) << 32)
- | (EXTRACT_BYTE(4) << 24) | (EXTRACT_BYTE(5) << 16) | (EXTRACT_BYTE(6) << 8) | EXTRACT_BYTE(7);
+ return (__force fdt64_t)CPU_TO_FDT64(x);
}
-#define cpu_to_fdt64(x) fdt64_to_cpu(x)
+#undef CPU_TO_FDT64
+#undef CPU_TO_FDT32
+#undef CPU_TO_FDT16
#undef EXTRACT_BYTE
#endif /* _LIBFDT_ENV_H */
diff --git a/libfdt/version.lds b/libfdt/version.lds
index 3c3994e27f7f..80b322bed6b9 100644
--- a/libfdt/version.lds
+++ b/libfdt/version.lds
@@ -48,6 +48,12 @@ LIBFDT_1.2 {
fdt_strerror;
fdt_offset_ptr;
fdt_next_tag;
+ fdt_appendprop;
+ fdt_create_empty_tree;
+ fdt_first_property_offset;
+ fdt_get_property_by_offset;
+ fdt_getprop_by_offset;
+ fdt_next_property_offset;
local:
*;
diff --git a/livetree.c b/livetree.c
index c9209d5c999e..b61465fb2f33 100644
--- a/livetree.c
+++ b/livetree.c
@@ -29,16 +29,27 @@ void add_label(struct label **labels, char *label)
struct label *new;
/* Make sure the label isn't already there */
- for_each_label(*labels, new)
- if (streq(new->label, label))
+ for_each_label_withdel(*labels, new)
+ if (streq(new->label, label)) {
+ new->deleted = 0;
return;
+ }
new = xmalloc(sizeof(*new));
+ memset(new, 0, sizeof(*new));
new->label = label;
new->next = *labels;
*labels = new;
}
+void delete_labels(struct label **labels)
+{
+ struct label *label;
+
+ for_each_label(*labels, label)
+ label->deleted = 1;
+}
+
struct property *build_property(char *name, struct data val)
{
struct property *new = xmalloc(sizeof(*new));
@@ -51,6 +62,18 @@ struct property *build_property(char *name, struct data val)
return new;
}
+struct property *build_property_delete(char *name)
+{
+ struct property *new = xmalloc(sizeof(*new));
+
+ memset(new, 0, sizeof(*new));
+
+ new->name = name;
+ new->deleted = 1;
+
+ return new;
+}
+
struct property *chain_property(struct property *first, struct property *list)
{
assert(first->next == NULL);
@@ -91,6 +114,17 @@ struct node *build_node(struct property *proplist, struct node *children)
return new;
}
+struct node *build_node_delete(void)
+{
+ struct node *new = xmalloc(sizeof(*new));
+
+ memset(new, 0, sizeof(*new));
+
+ new->deleted = 1;
+
+ return new;
+}
+
struct node *name_node(struct node *node, char *name)
{
assert(node->name == NULL);
@@ -106,8 +140,10 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
struct node *new_child, *old_child;
struct label *l;
+ old_node->deleted = 0;
+
/* Add new node labels to old node */
- for_each_label(new_node->labels, l)
+ for_each_label_withdel(new_node->labels, l)
add_label(&old_node->labels, l->label);
/* Move properties from the new node to the old node. If there
@@ -118,14 +154,21 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
new_node->proplist = new_prop->next;
new_prop->next = NULL;
+ if (new_prop->deleted) {
+ delete_property_by_name(old_node, new_prop->name);
+ free(new_prop);
+ continue;
+ }
+
/* Look for a collision, set new value if there is */
- for_each_property(old_node, old_prop) {
+ for_each_property_withdel(old_node, old_prop) {
if (streq(old_prop->name, new_prop->name)) {
/* Add new labels to old property */
- for_each_label(new_prop->labels, l)
+ for_each_label_withdel(new_prop->labels, l)
add_label(&old_prop->labels, l->label);
old_prop->val = new_prop->val;
+ old_prop->deleted = 0;
free(new_prop);
new_prop = NULL;
break;
@@ -146,8 +189,14 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
new_child->parent = NULL;
new_child->next_sibling = NULL;
+ if (new_child->deleted) {
+ delete_node_by_name(old_node, new_child->name);
+ free(new_child);
+ continue;
+ }
+
/* Search for a collision. Merge if there is */
- for_each_child(old_node, old_child) {
+ for_each_child_withdel(old_node, old_child) {
if (streq(old_child->name, new_child->name)) {
merge_nodes(old_child, new_child);
new_child = NULL;
@@ -188,6 +237,25 @@ void add_property(struct node *node, struct property *prop)
*p = prop;
}
+void delete_property_by_name(struct node *node, char *name)
+{
+ struct property *prop = node->proplist;
+
+ while (prop) {
+ if (!strcmp(prop->name, name)) {
+ delete_property(prop);
+ return;
+ }
+ prop = prop->next;
+ }
+}
+
+void delete_property(struct property *prop)
+{
+ prop->deleted = 1;
+ delete_labels(&prop->labels);
+}
+
void add_child(struct node *parent, struct node *child)
{
struct node **p;
@@ -202,6 +270,32 @@ void add_child(struct node *parent, struct node *child)
*p = child;
}
+void delete_node_by_name(struct node *parent, char *name)
+{
+ struct node *node = parent->children;
+
+ while (node) {
+ if (!strcmp(node->name, name)) {
+ delete_node(node);
+ return;
+ }
+ node = node->next_sibling;
+ }
+}
+
+void delete_node(struct node *node)
+{
+ struct property *prop;
+ struct node *child;
+
+ node->deleted = 1;
+ for_each_child(node, child)
+ delete_node(child);
+ for_each_property(node, prop)
+ delete_property(prop);
+ delete_labels(&node->labels);
+}
+
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
{
struct reserve_info *new = xmalloc(sizeof(*new));
@@ -353,8 +447,11 @@ struct node *get_node_by_path(struct node *tree, const char *path)
const char *p;
struct node *child;
- if (!path || ! (*path))
+ if (!path || ! (*path)) {
+ if (tree->deleted)
+ return NULL;
return tree;
+ }
while (path[0] == '/')
path++;
@@ -397,8 +494,11 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
assert((phandle != 0) && (phandle != -1));
- if (tree->phandle == phandle)
+ if (tree->phandle == phandle) {
+ if (tree->deleted)
+ return NULL;
return tree;
+ }
for_each_child(tree, child) {
node = get_node_by_phandle(child, phandle);
@@ -535,7 +635,7 @@ static void sort_properties(struct node *node)
int n = 0, i = 0;
struct property *prop, **tbl;
- for_each_property(node, prop)
+ for_each_property_withdel(node, prop)
n++;
if (n == 0)
@@ -543,7 +643,7 @@ static void sort_properties(struct node *node)
tbl = xmalloc(n * sizeof(*tbl));
- for_each_property(node, prop)
+ for_each_property_withdel(node, prop)
tbl[i++] = prop;
qsort(tbl, n, sizeof(*tbl), cmp_prop);
@@ -571,7 +671,7 @@ static void sort_subnodes(struct node *node)
int n = 0, i = 0;
struct node *subnode, **tbl;
- for_each_child(node, subnode)
+ for_each_child_withdel(node, subnode)
n++;
if (n == 0)
@@ -579,7 +679,7 @@ static void sort_subnodes(struct node *node)
tbl = xmalloc(n * sizeof(*tbl));
- for_each_child(node, subnode)
+ for_each_child_withdel(node, subnode)
tbl[i++] = subnode;
qsort(tbl, n, sizeof(*tbl), cmp_subnode);
@@ -598,7 +698,7 @@ static void sort_node(struct node *node)
sort_properties(node);
sort_subnodes(node);
- for_each_child(node, c)
+ for_each_child_withdel(node, c)
sort_node(c);
}
diff --git a/srcpos.c b/srcpos.c
index 3ee523d29afe..399967549a6a 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -159,7 +159,7 @@ void srcfile_push(const char *fname)
current_srcfile = srcfile;
}
-int srcfile_pop(void)
+bool srcfile_pop(void)
{
struct srcfile_state *srcfile = current_srcfile;
@@ -177,7 +177,7 @@ int srcfile_pop(void)
* fix this we could either allocate all the files from a
* table, or use a pool allocator. */
- return current_srcfile ? 1 : 0;
+ return current_srcfile ? true : false;
}
void srcfile_add_search_path(const char *dirname)
@@ -290,41 +290,32 @@ srcpos_string(struct srcpos *pos)
return pos_str;
}
-void
-srcpos_verror(struct srcpos *pos, char const *fmt, va_list va)
+void srcpos_verror(struct srcpos *pos, const char *prefix,
+ const char *fmt, va_list va)
{
- const char *srcstr;
+ char *srcstr;
+
+ srcstr = srcpos_string(pos);
- srcstr = srcpos_string(pos);
+ fprintf(stderr, "%s: %s ", prefix, srcstr);
+ vfprintf(stderr, fmt, va);
+ fprintf(stderr, "\n");
- fprintf(stdout, "Error: %s ", srcstr);
- vfprintf(stdout, fmt, va);
- fprintf(stdout, "\n");
+ free(srcstr);
}
-void
-srcpos_error(struct srcpos *pos, char const *fmt, ...)
+void srcpos_error(struct srcpos *pos, const char *prefix,
+ const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
- srcpos_verror(pos, fmt, va);
+ srcpos_verror(pos, prefix, fmt, va);
va_end(va);
}
-
-void
-srcpos_warn(struct srcpos *pos, char const *fmt, ...)
+void srcpos_set_line(char *f, int l)
{
- 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");
-
- va_end(va);
+ current_srcfile->name = f;
+ current_srcfile->lineno = l;
}
diff --git a/srcpos.h b/srcpos.h
index 5617916dcfcb..f81827bd684a 100644
--- a/srcpos.h
+++ b/srcpos.h
@@ -21,6 +21,7 @@
#define _SRCPOS_H_
#include <stdio.h>
+#include <stdbool.h>
struct srcfile_state {
FILE *f;
@@ -55,7 +56,7 @@ extern struct srcfile_state *current_srcfile; /* = NULL */
FILE *srcfile_relative_open(const char *fname, char **fullnamep);
void srcfile_push(const char *fname);
-int srcfile_pop(void);
+bool srcfile_pop(void);
/**
* Add a new directory to the search path for input files
@@ -106,11 +107,13 @@ extern struct srcpos *srcpos_copy(struct srcpos *pos);
extern char *srcpos_string(struct srcpos *pos);
extern void srcpos_dump(struct srcpos *pos);
-extern void srcpos_verror(struct srcpos *pos, char const *, va_list va)
- __attribute__((format(printf, 2, 0)));
-extern void srcpos_error(struct srcpos *pos, char const *, ...)
- __attribute__((format(printf, 2, 3)));
-extern void srcpos_warn(struct srcpos *pos, char const *, ...)
- __attribute__((format(printf, 2, 3)));
+extern void srcpos_verror(struct srcpos *pos, const char *prefix,
+ const char *fmt, va_list va)
+ __attribute__((format(printf, 3, 0)));
+extern void srcpos_error(struct srcpos *pos, const char *prefix,
+ const char *fmt, ...)
+ __attribute__((format(printf, 3, 4)));
+
+extern void srcpos_set_line(char *f, int l);
#endif /* _SRCPOS_H_ */
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index 179546683619..dafb61848744 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -12,7 +12,7 @@ LIB_TESTS_L = get_mem_rsv \
sw_tree1 \
move_and_save mangle-layout nopulate \
open_pack rw_tree1 set_name setprop del_property del_node \
- appendprop1 appendprop2 \
+ appendprop1 appendprop2 propname_escapes \
string_escapes references path-references phandle_format \
boot-cpuid incbin \
extra-terminating-null \
@@ -20,7 +20,8 @@ LIB_TESTS_L = get_mem_rsv \
dtb_reverse dtbs_equal_unordered \
add_subnode_with_nops path_offset_aliases \
utilfdt_test \
- integer-expressions
+ integer-expressions \
+ subnode_iterate
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
LIBTREE_TESTS_L = truncated_property
diff --git a/tests/add_subnode_with_nops.c b/tests/add_subnode_with_nops.c
index 4fb8f0245523..95ddf6a5928c 100644
--- a/tests/add_subnode_with_nops.c
+++ b/tests/add_subnode_with_nops.c
@@ -24,7 +24,6 @@
#include <ctype.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/aliases.dts b/tests/aliases.dts
index 39d88ffc8594..853479aee766 100644
--- a/tests/aliases.dts
+++ b/tests/aliases.dts
@@ -1,6 +1,9 @@
/dts-v1/;
/ {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
aliases {
s1 = &sub1;
ss1 = &subsub1;
@@ -9,6 +12,7 @@
sub1: subnode@1 {
compatible = "subnode1";
+ reg = <1>;
subsub1: subsubnode {
compatible = "subsubnode1", "subsubnode";
diff --git a/tests/appendprop1.c b/tests/appendprop1.c
index d716f7afde6f..9d6b3add9d43 100644
--- a/tests/appendprop1.c
+++ b/tests/appendprop1.c
@@ -24,7 +24,6 @@
#include <ctype.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/appendprop2.c b/tests/appendprop2.c
index 7eb243dfa36e..ca1446c513b4 100644
--- a/tests/appendprop2.c
+++ b/tests/appendprop2.c
@@ -24,7 +24,6 @@
#include <ctype.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/asm_tree_dump.c b/tests/asm_tree_dump.c
index 5ff50872c8ef..bd12edaa880d 100644
--- a/tests/asm_tree_dump.c
+++ b/tests/asm_tree_dump.c
@@ -26,7 +26,6 @@
#include <dlfcn.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/boot-cpuid.c b/tests/boot-cpuid.c
index 7b5433dbacbf..ca39f4b69294 100644
--- a/tests/boot-cpuid.c
+++ b/tests/boot-cpuid.c
@@ -21,7 +21,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/char_literal.c b/tests/char_literal.c
index 150f2a0c1488..d7a4773419a0 100644
--- a/tests/char_literal.c
+++ b/tests/char_literal.c
@@ -23,7 +23,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/del_node.c b/tests/del_node.c
index afad5027b791..45cb06016dc5 100644
--- a/tests/del_node.c
+++ b/tests/del_node.c
@@ -24,7 +24,6 @@
#include <ctype.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/del_property.c b/tests/del_property.c
index 449eca6150c6..42fd7cb1c15e 100644
--- a/tests/del_property.c
+++ b/tests/del_property.c
@@ -24,7 +24,6 @@
#include <ctype.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/dtb_reverse.c b/tests/dtb_reverse.c
index 25e1eef81775..527fd71336d7 100644
--- a/tests/dtb_reverse.c
+++ b/tests/dtb_reverse.c
@@ -24,7 +24,6 @@
#include <stdint.h>
#include <limits.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/dtbs_equal_ordered.c b/tests/dtbs_equal_ordered.c
index 1db25f45265a..12495dea483e 100644
--- a/tests/dtbs_equal_ordered.c
+++ b/tests/dtbs_equal_ordered.c
@@ -23,7 +23,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/dtbs_equal_unordered.c b/tests/dtbs_equal_unordered.c
index df5331883b15..20b4356f92f6 100644
--- a/tests/dtbs_equal_unordered.c
+++ b/tests/dtbs_equal_unordered.c
@@ -24,7 +24,6 @@
#include <stdint.h>
#include <limits.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/dumptrees.c b/tests/dumptrees.c
index fa1f56368413..bebf553c9bfe 100644
--- a/tests/dumptrees.c
+++ b/tests/dumptrees.c
@@ -25,9 +25,7 @@
#include <fcntl.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
-#include <libfdt_env.h>
#include "testdata.h"
diff --git a/tests/extra-terminating-null.c b/tests/extra-terminating-null.c
index 8a2043f3dd76..dc1fe89ab053 100644
--- a/tests/extra-terminating-null.c
+++ b/tests/extra-terminating-null.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh
index c3a355951dff..8d8b0587602e 100755
--- a/tests/fdtget-runtest.sh
+++ b/tests/fdtget-runtest.sh
@@ -8,7 +8,7 @@ rm -f $LOG $EXPECT
trap "rm -f $LOG $EXPECT" 0
expect="$1"
-/bin/echo -e $expect >$EXPECT
+printf '%b\n' "$expect" > $EXPECT
shift
verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@"
diff --git a/tests/find_property.c b/tests/find_property.c
index 74a696587c32..4dc3030e37e3 100644
--- a/tests/find_property.c
+++ b/tests/find_property.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/get_alias.c b/tests/get_alias.c
index 1e0faf474fe7..506079575153 100644
--- a/tests/get_alias.c
+++ b/tests/get_alias.c
@@ -23,7 +23,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/get_mem_rsv.c b/tests/get_mem_rsv.c
index 554c78868f94..181263935899 100644
--- a/tests/get_mem_rsv.c
+++ b/tests/get_mem_rsv.c
@@ -23,7 +23,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/get_name.c b/tests/get_name.c
index 0262a120d1f3..c6ca9f9bbf8c 100644
--- a/tests/get_name.c
+++ b/tests/get_name.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/get_path.c b/tests/get_path.c
index 1e05f7c21163..735297659379 100644
--- a/tests/get_path.c
+++ b/tests/get_path.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/get_phandle.c b/tests/get_phandle.c
index 5735733fadbf..2079591d4c49 100644
--- a/tests/get_phandle.c
+++ b/tests/get_phandle.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/getprop.c b/tests/getprop.c
index 239856e7c958..6255badb3fac 100644
--- a/tests/getprop.c
+++ b/tests/getprop.c
@@ -23,7 +23,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/incbin.c b/tests/incbin.c
index 76d86262644c..4100ba029971 100644
--- a/tests/incbin.c
+++ b/tests/incbin.c
@@ -23,7 +23,6 @@
#include <stdint.h>
#include <errno.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/include1.dts b/tests/include1.dts
index 893aaffe7496..0b4b773e654d 100644
--- a/tests/include1.dts
+++ b/tests/include1.dts
@@ -8,12 +8,17 @@
/include/ "include5.dts" = <0xdeadbeef>;
prop-int64 /include/ "include5a.dts";
prop-str = /include/ "include6.dts";
+ #address-cells = <1>;
+ #size-cells = <0>;
/include/ "include7.dts"
subnode@2 {
+ reg = <2>;
linux,phandle = <0x2000>;
prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
/include/ "include8.dts"
phandle = <0x2001>;
diff --git a/tests/include7.dts b/tests/include7.dts
index dba5e470559a..2f6eb890f1fa 100644
--- a/tests/include7.dts
+++ b/tests/include7.dts
@@ -1,5 +1,6 @@
subnode@1 {
compatible = "subnode1";
+ reg = <1>;
prop-int = [deadbeef];
subsubnode {
diff --git a/tests/include8.dts b/tests/include8.dts
index ec7006437657..7532ef51d7ee 100644
--- a/tests/include8.dts
+++ b/tests/include8.dts
@@ -1 +1,2 @@
-subsubnode@0 { \ No newline at end of file
+subsubnode@0 {
+ reg = <0>;
diff --git a/tests/integer-expressions.c b/tests/integer-expressions.c
index 5ba1566ab8e2..57e2ff670ded 100644
--- a/tests/integer-expressions.c
+++ b/tests/integer-expressions.c
@@ -25,7 +25,6 @@
#include <errno.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c
index 3b19788bd72a..a76e51e31b55 100644
--- a/tests/mangle-layout.c
+++ b/tests/mangle-layout.c
@@ -24,7 +24,6 @@
#include <limits.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/move_and_save.c b/tests/move_and_save.c
index 410ccb3be715..393b60ac1936 100644
--- a/tests/move_and_save.c
+++ b/tests/move_and_save.c
@@ -24,7 +24,6 @@
#include <limits.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/node_check_compatible.c b/tests/node_check_compatible.c
index 23abbf529d9e..4bdf09194c8b 100644
--- a/tests/node_check_compatible.c
+++ b/tests/node_check_compatible.c
@@ -23,7 +23,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/node_offset_by_compatible.c b/tests/node_offset_by_compatible.c
index 23179300f012..f62b591ce249 100644
--- a/tests/node_offset_by_compatible.c
+++ b/tests/node_offset_by_compatible.c
@@ -23,7 +23,6 @@
#include <stdint.h>
#include <stdarg.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/node_offset_by_phandle.c b/tests/node_offset_by_phandle.c
index a8442f15a6b0..becff0fd5a1a 100644
--- a/tests/node_offset_by_phandle.c
+++ b/tests/node_offset_by_phandle.c
@@ -23,7 +23,6 @@
#include <stdint.h>
#include <stdarg.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/node_offset_by_prop_value.c b/tests/node_offset_by_prop_value.c
index 0f2a34512ae2..9212a4efeffc 100644
--- a/tests/node_offset_by_prop_value.c
+++ b/tests/node_offset_by_prop_value.c
@@ -23,7 +23,6 @@
#include <stdint.h>
#include <stdarg.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/nop_node.c b/tests/nop_node.c
index ea3a18f6acb5..c316444f6dce 100644
--- a/tests/nop_node.c
+++ b/tests/nop_node.c
@@ -24,7 +24,6 @@
#include <ctype.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/nop_property.c b/tests/nop_property.c
index e6ef4d973149..644b0a665e6d 100644
--- a/tests/nop_property.c
+++ b/tests/nop_property.c
@@ -24,7 +24,6 @@
#include <ctype.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/nopulate.c b/tests/nopulate.c
index 3cbbe2113c79..cd79872bc4a9 100644
--- a/tests/nopulate.c
+++ b/tests/nopulate.c
@@ -24,7 +24,6 @@
#include <limits.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/notfound.c b/tests/notfound.c
index 4d55b886ba7a..dc623d624672 100644
--- a/tests/notfound.c
+++ b/tests/notfound.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/open_pack.c b/tests/open_pack.c
index 0a5a3fcc8392..407ef6c542a0 100644
--- a/tests/open_pack.c
+++ b/tests/open_pack.c
@@ -24,7 +24,6 @@
#include <limits.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/parent_offset.c b/tests/parent_offset.c
index e7affcc39afc..d4ab3cff3052 100644
--- a/tests/parent_offset.c
+++ b/tests/parent_offset.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/path-references.c b/tests/path-references.c
index 9f363b3af3cb..0746b3f7e324 100644
--- a/tests/path-references.c
+++ b/tests/path-references.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/path_offset.c b/tests/path_offset.c
index d3e1f8ebbac0..4e5b7a11f70d 100644
--- a/tests/path_offset.c
+++ b/tests/path_offset.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/path_offset_aliases.c b/tests/path_offset_aliases.c
index 3682da489a87..78d5a46967c8 100644
--- a/tests/path_offset_aliases.c
+++ b/tests/path_offset_aliases.c
@@ -23,7 +23,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/phandle_format.c b/tests/phandle_format.c
index 7e4d81630e08..5874ae79291c 100644
--- a/tests/phandle_format.c
+++ b/tests/phandle_format.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/references.c b/tests/references.c
index b20f21fdeca0..c9d05a2f2962 100644
--- a/tests/references.c
+++ b/tests/references.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/root_node.c b/tests/root_node.c
index 3f478299f9c6..58aebf6b48c9 100644
--- a/tests/root_node.c
+++ b/tests/root_node.c
@@ -23,7 +23,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index f5eebd6ffcfe..97e016b1aef9 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -7,6 +7,7 @@ if [ -z "$CC" ]; then
fi
export QUIET_TEST=1
+STOP_ON_FAIL=0
export VALGRIND=
VGCODE=126
@@ -24,6 +25,9 @@ base_run_test() {
tot_pass=$((tot_pass + 1))
else
ret="$?"
+ if [ "$STOP_ON_FAIL" -eq 1 ]; then
+ exit 1
+ fi
if [ "$ret" -eq 1 ]; then
tot_config=$((tot_config + 1))
elif [ "$ret" -eq 2 ]; then
@@ -80,7 +84,7 @@ wrap_test () {
}
run_wrap_test () {
- echo -n "$@: "
+ shorten_echo "$@: "
base_run_test wrap_test "$@"
}
@@ -190,6 +194,14 @@ libfdt_tests () {
tree1_tests unfinished_tree1.test.dtb
run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb
+ # Resizing tests
+ for mode in resize realloc; do
+ run_test sw_tree1 $mode
+ tree1_tests sw_tree1.test.dtb
+ tree1_tests unfinished_tree1.test.dtb
+ run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb
+ done
+
# fdt_move tests
for tree in test_tree1.dtb sw_tree1.test.dtb unfinished_tree1.test.dtb; do
rm -f moved.$tree shunted.$tree deshunted.$tree
@@ -241,6 +253,9 @@ libfdt_tests () {
tree1_tests_rw noppy.$basetree
done
+ run_dtc_test -I dts -O dtb -o subnode_iterate.dtb subnode_iterate.dts
+ run_test subnode_iterate subnode_iterate.dtb
+
# Tests for behaviour on various sorts of corrupted trees
run_test truncated_property
@@ -254,6 +269,11 @@ dtc_tests () {
tree1_tests_rw dtc_tree1.test.dtb
run_test dtbs_equal_ordered dtc_tree1.test.dtb test_tree1.dtb
+ run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb propname_escapes.dts
+ run_test propname_escapes dtc_escapes.test.dtb
+
+ run_dtc_test -I dts -O dtb -o line_directives.test.dtb line_directives.dts
+
run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts
run_test string_escapes dtc_escapes.test.dtb
@@ -367,6 +387,13 @@ dtc_tests () {
run_dtc_test -I dts -O dtb -o dtc_tree1_merge_path.test.dtb test_tree1_merge_path.dts
tree1_tests dtc_tree1_merge_path.test.dtb test_tree1.dtb
+ # Check prop/node delete functionality
+ run_dtc_test -I dts -O dtb -o dtc_tree1_delete.test.dtb test_tree1_delete.dts
+ tree1_tests dtc_tree1_delete.test.dtb
+
+ run_dtc_test -I dts -O dts -o delete_reinstate_multilabel.dts.test.dts delete_reinstate_multilabel.dts
+ run_wrap_test cmp delete_reinstate_multilabel.dts.test.dts delete_reinstate_multilabel_ref.dts
+
# Check some checks
check_tests dup-nodename.dts duplicate_node_names
check_tests dup-propname.dts duplicate_property_names
@@ -486,9 +513,10 @@ fdtget_tests () {
# run_fdtget_test <expected-result> [<flags>] <file> <node> <property>
run_fdtget_test "MyBoardName" $dtb / model
+ run_fdtget_test "MyBoardName MyBoardFamilyName" $dtb / compatible
run_fdtget_test "77 121 66 111 \
97 114 100 78 97 109 101 0 77 121 66 111 97 114 100 70 97 109 105 \
-108 121 78 97 109 101 0" $dtb / compatible
+108 121 78 97 109 101 0" -t bu $dtb / compatible
run_fdtget_test "MyBoardName MyBoardFamilyName" -t s $dtb / compatible
run_fdtget_test 32768 $dtb /cpus/PowerPC,970@1 d-cache-size
run_fdtget_test 8000 -tx $dtb /cpus/PowerPC,970@1 d-cache-size
@@ -533,8 +561,8 @@ fdtput_tests () {
-tx "a0b0c0d deeaae ef000000"
run_fdtput_test "$(cat $text)" $dtb /randomnode blob -ts "$(cat $text)"
- # This should be larger than available space in the fdt
- run_wrap_error_test $DTPUT $dtb /randomnode blob -ts "$(cat $text $text)"
+ # Test expansion of the blob when insufficient room for property
+ run_fdtput_test "$(cat $text $text)" $dtb /randomnode blob -ts "$(cat $text $text)"
# Start again with a fresh dtb
run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts
@@ -556,7 +584,9 @@ fdtput_tests () {
run_fdtput_test "fine wine" $dtb /blackadder/the-second/potato drink \
"-ts" "fine wine"
run_wrap_test $DTPUT $dtb -p /you/are/drunk/sir/winston slurp -ts twice
- run_wrap_error_test $DTPUT $dtb -cp "$(cat $text $text)/longish"
+
+ # Test expansion of the blob when insufficent room for a new node
+ run_wrap_test $DTPUT $dtb -cp "$(cat $text $text)/longish"
# Allowed to create an existing node with -p
run_wrap_test $DTPUT $dtb -cp /chosen
@@ -569,7 +599,7 @@ utilfdt_tests () {
run_test utilfdt_test
}
-while getopts "vt:m" ARG ; do
+while getopts "vt:me" ARG ; do
case $ARG in
"v")
unset QUIET_TEST
@@ -580,6 +610,9 @@ while getopts "vt:m" ARG ; do
"m")
VALGRIND="valgrind --tool=memcheck -q --error-exitcode=$VGCODE"
;;
+ "e")
+ STOP_ON_FAIL=1
+ ;;
esac
done
diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c
index 103a24d7769f..efd471892f1c 100644
--- a/tests/rw_tree1.c
+++ b/tests/rw_tree1.c
@@ -24,7 +24,6 @@
#include <ctype.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/set_name.c b/tests/set_name.c
index 5d1149e002cd..986158733a58 100644
--- a/tests/set_name.c
+++ b/tests/set_name.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/setprop.c b/tests/setprop.c
index 9f2bc883b25e..d089f8d5ab5e 100644
--- a/tests/setprop.c
+++ b/tests/setprop.c
@@ -24,7 +24,6 @@
#include <ctype.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c
index 82d895138d5d..daef182d0b28 100644
--- a/tests/setprop_inplace.c
+++ b/tests/setprop_inplace.c
@@ -25,7 +25,6 @@
#include <ctype.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/sized_cells.c b/tests/sized_cells.c
index 847ec96ba4ad..94da03b8a077 100644
--- a/tests/sized_cells.c
+++ b/tests/sized_cells.c
@@ -23,7 +23,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/string_escapes.c b/tests/string_escapes.c
index 30eb6a8d3d4d..8cdee4bb34fe 100644
--- a/tests/string_escapes.c
+++ b/tests/string_escapes.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c
index e58c192f7ab1..231fcb50a26c 100644
--- a/tests/subnode_offset.c
+++ b/tests/subnode_offset.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/supernode_atdepth_offset.c b/tests/supernode_atdepth_offset.c
index 73f41aecf93c..43e120d79e4e 100644
--- a/tests/supernode_atdepth_offset.c
+++ b/tests/supernode_atdepth_offset.c
@@ -22,7 +22,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c
index 5c71414692a5..6d4c53102967 100644
--- a/tests/sw_tree1.c
+++ b/tests/sw_tree1.c
@@ -24,7 +24,6 @@
#include <ctype.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
@@ -32,24 +31,92 @@
#define SPACE 65536
-#define CHECK(code) \
- { \
- err = (code); \
- if (err) \
- FAIL(#code ": %s", fdt_strerror(err)); \
+static enum {
+ FIXED = 0,
+ RESIZE,
+ REALLOC,
+} alloc_mode;
+
+static void realloc_fdt(void **fdt, size_t *size, bool created)
+{
+ switch (alloc_mode) {
+ case FIXED:
+ if (!(*fdt))
+ fdt = xmalloc(*size);
+ else
+ FAIL("Ran out of space");
+ return;
+
+ case RESIZE:
+ if (!(*fdt)) {
+ fdt = xmalloc(SPACE);
+ } else if (*size < SPACE) {
+ *size += 1;
+ fdt_resize(*fdt, *fdt, *size);
+ } else {
+ FAIL("Ran out of space");
+ }
+ return;
+
+ case REALLOC:
+ *size += 1;
+ *fdt = xrealloc(*fdt, *size);
+ if (created)
+ fdt_resize(*fdt, *fdt, *size);
+ return;
+
+ default:
+ CONFIG("Bad allocation mode");
}
+}
+
+#define CHECK(code) \
+ do { \
+ err = (code); \
+ if (err == -FDT_ERR_NOSPACE) \
+ realloc_fdt(&fdt, &size, created); \
+ else if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ } while (err != 0)
int main(int argc, char *argv[])
{
- void *fdt;
+ void *fdt = NULL;
+ size_t size;
int err;
+ bool created = false;
test_init(argc, argv);
- fdt = xmalloc(SPACE);
- CHECK(fdt_create(fdt, SPACE));
+ if (argc == 1) {
+ alloc_mode = FIXED;
+ size = SPACE;
+ } else if (argc == 2) {
+ if (streq(argv[1], "resize")) {
+ alloc_mode = REALLOC;
+ size = 0;
+ } else if (streq(argv[1], "realloc")) {
+ alloc_mode = REALLOC;
+ size = 0;
+ } else {
+ char *endp;
+
+ size = strtoul(argv[1], &endp, 0);
+ if (*endp == '\0')
+ alloc_mode = FIXED;
+ else
+ CONFIG("Bad allocation mode \"%s\" specified",
+ argv[1]);
+ }
+ }
+
+ fdt = xmalloc(size);
+ CHECK(fdt_create(fdt, size));
+
+ created = true;
CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1));
+
CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_2, TEST_SIZE_2));
CHECK(fdt_finish_reservemap(fdt));
@@ -58,9 +125,12 @@ int main(int argc, char *argv[])
CHECK(fdt_property_u32(fdt, "prop-int", TEST_VALUE_1));
CHECK(fdt_property_u64(fdt, "prop-int64", TEST_VALUE64_1));
CHECK(fdt_property_string(fdt, "prop-str", TEST_STRING_1));
+ CHECK(fdt_property_u32(fdt, "#address-cells", 1));
+ CHECK(fdt_property_u32(fdt, "#size-cells", 0));
CHECK(fdt_begin_node(fdt, "subnode@1"));
CHECK(fdt_property_string(fdt, "compatible", "subnode1"));
+ CHECK(fdt_property_u32(fdt, "reg", 1));
CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1));
CHECK(fdt_begin_node(fdt, "subsubnode"));
CHECK(fdt_property(fdt, "compatible", "subsubnode1\0subsubnode",
@@ -72,9 +142,13 @@ int main(int argc, char *argv[])
CHECK(fdt_end_node(fdt));
CHECK(fdt_begin_node(fdt, "subnode@2"));
+ CHECK(fdt_property_u32(fdt, "reg", 2));
CHECK(fdt_property_cell(fdt, "linux,phandle", PHANDLE_1));
CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2));
+ CHECK(fdt_property_u32(fdt, "#address-cells", 1));
+ CHECK(fdt_property_u32(fdt, "#size-cells", 0));
CHECK(fdt_begin_node(fdt, "subsubnode@0"));
+ CHECK(fdt_property_u32(fdt, "reg", 0));
CHECK(fdt_property_cell(fdt, "phandle", PHANDLE_2));
CHECK(fdt_property(fdt, "compatible", "subsubnode2\0subsubnode",
23));
diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts
index cf530ce4ba01..c7b170c5af60 100644
--- a/tests/test_tree1.dts
+++ b/tests/test_tree1.dts
@@ -1,38 +1,3 @@
/dts-v1/;
-/memreserve/ 0xdeadbeef00000000 0x100000;
-/memreserve/ 123456789 010000;
-
-/ {
- compatible = "test_tree1";
- prop-int = <0xdeadbeef>;
- prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
- prop-str = "hello world";
-
- subnode@1 {
- compatible = "subnode1";
- prop-int = [deadbeef];
-
- subsubnode {
- compatible = "subsubnode1", "subsubnode";
- prop-int = <0xdeadbeef>;
- };
-
- ss1 {
- };
- };
-
- subnode@2 {
- linux,phandle = <0x2000>;
- prop-int = <123456789>;
-
- ssn0: subsubnode@0 {
- phandle = <0x2001>;
- compatible = "subsubnode2", "subsubnode";
- prop-int = <0726746425>;
- };
-
- ss2 {
- };
- };
-};
+/include/ "test_tree1_body.dtsi"
diff --git a/tests/test_tree1_merge.dts b/tests/test_tree1_merge.dts
index ded08d871435..b100c12debb5 100644
--- a/tests/test_tree1_merge.dts
+++ b/tests/test_tree1_merge.dts
@@ -6,9 +6,12 @@
compatible = "test_tree1";
prop-int = "wrong!";
prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
subnode@1 {
compatible = "subnode1";
+ reg = <1>;
subsubnode {
compatible = "subsubnode1", "subsubnode";
@@ -20,8 +23,11 @@
};
subnode@2 {
+ reg = <2>;
linux,phandle = <0x2000>;
prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
ss2 {
};
@@ -36,6 +42,7 @@
};
subnode@2 {
ssn0: subsubnode@0 {
+ reg = <0>;
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
diff --git a/tests/test_tree1_merge_labelled.dts b/tests/test_tree1_merge_labelled.dts
index 29953b0aa1b3..fcf5dc45aeef 100644
--- a/tests/test_tree1_merge_labelled.dts
+++ b/tests/test_tree1_merge_labelled.dts
@@ -8,9 +8,12 @@
prop-int = <0xdeadbeef>;
prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
subnode@1 {
compatible = "subnode1";
+ reg = <1>;
prop-int = [deadbeef];
subsubnode {
@@ -23,10 +26,14 @@
};
subnode@2 {
+ reg = <2>;
linux,phandle = <0x2000>;
prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
ssn0: subsubnode@0 {
+ reg = <0>;
phandle = <0x2001>;
prop-int = <0xbad>;
};
diff --git a/tests/test_tree1_merge_path.dts b/tests/test_tree1_merge_path.dts
index 168d066fad08..c2ad829727db 100644
--- a/tests/test_tree1_merge_path.dts
+++ b/tests/test_tree1_merge_path.dts
@@ -8,9 +8,12 @@
prop-int = <0xdeadbeef>;
prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
subnode@1 {
compatible = "subnode1";
+ reg = <1>;
prop-int = [deadbeef];
subsubnode {
@@ -23,10 +26,14 @@
};
subnode@2 {
+ reg = <2>;
linux,phandle = <0x2000>;
prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
ssn0: subsubnode@0 {
+ reg = <0>;
phandle = <0x2001>;
prop-int = <0xbad>;
};
diff --git a/tests/test_tree1_wrong1.dts b/tests/test_tree1_wrong1.dts
index d71820a23864..900d38582912 100644
--- a/tests/test_tree1_wrong1.dts
+++ b/tests/test_tree1_wrong1.dts
@@ -6,9 +6,12 @@
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
subnode@1 {
compatible = "subnode1";
+ reg = <1>;
prop-int = [deadbeef];
subsubnode {
@@ -21,10 +24,14 @@
};
subnode@2 {
+ reg = <2>;
linux,phandle = <0x2000>;
prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
subsubnode@0 {
+ reg = <0>;
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
diff --git a/tests/test_tree1_wrong2.dts b/tests/test_tree1_wrong2.dts
index ac27023c3c9a..099752b374aa 100644
--- a/tests/test_tree1_wrong2.dts
+++ b/tests/test_tree1_wrong2.dts
@@ -6,9 +6,12 @@
/ {
compatible = "test_tree1";
prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
subnode@1 {
compatible = "subnode1";
+ reg = <1>;
prop-int = [deadbeef];
subsubnode {
@@ -21,10 +24,14 @@
};
subnode@2 {
+ reg = <2>;
linux,phandle = <0x2000>;
prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
subsubnode@0 {
+ reg = <0>;
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
diff --git a/tests/test_tree1_wrong3.dts b/tests/test_tree1_wrong3.dts
index 80be2fac8f63..069353a9400c 100644
--- a/tests/test_tree1_wrong3.dts
+++ b/tests/test_tree1_wrong3.dts
@@ -7,9 +7,12 @@
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
subnode@1 {
compatible = "subnode1";
+ reg = <1>;
subsubnode {
compatible = "subsubnode1", "subsubnode";
@@ -21,10 +24,14 @@
};
subnode@2 {
+ reg = <2>;
linux,phandle = <0x2000>;
prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
subsubnode@0 {
+ reg = <0>;
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
diff --git a/tests/test_tree1_wrong4.dts b/tests/test_tree1_wrong4.dts
index 09bb13b8cb89..2c5641618e4a 100644
--- a/tests/test_tree1_wrong4.dts
+++ b/tests/test_tree1_wrong4.dts
@@ -7,9 +7,12 @@
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
subnode@1 {
compatible = "subnode1";
+ reg = <1>;
prop-int = [deadbeef];
subsubnode {
@@ -22,10 +25,14 @@
};
subnode@2 {
+ reg = <2>;
linux,phandle = <0x2000>;
prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
subsubnode@0 {
+ reg = <0>;
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
diff --git a/tests/test_tree1_wrong5.dts b/tests/test_tree1_wrong5.dts
index ef4c4f7b772d..6ddd72d52e1b 100644
--- a/tests/test_tree1_wrong5.dts
+++ b/tests/test_tree1_wrong5.dts
@@ -7,9 +7,12 @@
compatible = "test_tree1";
prop-int = <0xdeadbefe>;
prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
subnode@1 {
compatible = "subnode1";
+ reg = <1>;
prop-int = [deadbeef];
subsubnode {
@@ -22,10 +25,14 @@
};
subnode@2 {
+ reg = <2>;
linux,phandle = <0x2000>;
prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
subsubnode@0 {
+ reg = <0>;
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
diff --git a/tests/test_tree1_wrong6.dts b/tests/test_tree1_wrong6.dts
index 98d6eda7fb56..36b4e1f66fe5 100644
--- a/tests/test_tree1_wrong6.dts
+++ b/tests/test_tree1_wrong6.dts
@@ -7,9 +7,12 @@
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
subnode@1 {
compatible = "subnode1";
+ reg = <1>;
prop-int = [deadbeef];
subsubnode {
@@ -23,10 +26,14 @@
};
subnode@2 {
+ reg = <2>;
linux,phandle = <0x2000>;
prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
subsubnode@0 {
+ reg = <0>;
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
diff --git a/tests/test_tree1_wrong7.dts b/tests/test_tree1_wrong7.dts
index f57ace09a30f..54150e6d9fb8 100644
--- a/tests/test_tree1_wrong7.dts
+++ b/tests/test_tree1_wrong7.dts
@@ -7,9 +7,12 @@
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
subnode@1 {
compatible = "subnode1";
+ reg = <1>;
prop-int = [deadbeef];
subsubnode {
@@ -22,10 +25,14 @@
};
subnode@2 {
+ reg = <2>;
linux,phandle = <0x2000>;
prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
subsubnode@0 {
+ reg = <0>;
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
diff --git a/tests/test_tree1_wrong8.dts b/tests/test_tree1_wrong8.dts
index 811ce6c0e536..7a28a9f2953a 100644
--- a/tests/test_tree1_wrong8.dts
+++ b/tests/test_tree1_wrong8.dts
@@ -7,9 +7,12 @@
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
subnode@1 {
compatible = "subnode1";
+ reg = <1>;
prop-int = [deadbeef];
subsubnode {
@@ -24,8 +27,12 @@
subnode@2 {
linux,phandle = <0x2000>;
prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
subsubnode@0 {
+ reg = <0>;
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
diff --git a/tests/test_tree1_wrong9.dts b/tests/test_tree1_wrong9.dts
index 6ff6fab22dd2..f6486fa9337d 100644
--- a/tests/test_tree1_wrong9.dts
+++ b/tests/test_tree1_wrong9.dts
@@ -8,9 +8,12 @@
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
subnode@1 {
compatible = "subnode1";
+ reg = <1>;
prop-int = [deadbeef];
subsubnode {
@@ -23,10 +26,14 @@
};
subnode@2 {
+ reg = <2>;
linux,phandle = <0x2000>;
prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
subsubnode@0 {
+ reg = <0>;
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
diff --git a/tests/trees.S b/tests/trees.S
index cae018760e58..2389cd379621 100644
--- a/tests/trees.S
+++ b/tests/trees.S
@@ -92,9 +92,12 @@ test_tree1_struct:
PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1)
PROP_STR(test_tree1, prop_str, TEST_STRING_1)
+ PROP_INT(test_tree1, address_cells, 1)
+ PROP_INT(test_tree1, size_cells, 0)
BEGIN_NODE("subnode@1")
PROP_STR(test_tree1, compatible, "subnode1")
+ PROP_INT(test_tree1, reg, 1)
PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
BEGIN_NODE("subsubnode")
@@ -108,10 +111,14 @@ test_tree1_struct:
END_NODE
BEGIN_NODE("subnode@2")
+ PROP_INT(test_tree1, reg, 2)
PROP_INT(test_tree1, linux_phandle, PHANDLE_1)
PROP_INT(test_tree1, prop_int, TEST_VALUE_2)
+ PROP_INT(test_tree1, address_cells, 1)
+ PROP_INT(test_tree1, size_cells, 0)
BEGIN_NODE("subsubnode@0")
+ PROP_INT(test_tree1, reg, 0)
PROP_INT(test_tree1, phandle, PHANDLE_2)
PROP_STR(test_tree1, compatible, "subsubnode2\0subsubnode")
PROP_INT(test_tree1, prop_int, TEST_VALUE_2)
@@ -133,6 +140,9 @@ test_tree1_strings:
STRING(test_tree1, prop_str, "prop-str")
STRING(test_tree1, linux_phandle, "linux,phandle")
STRING(test_tree1, phandle, "phandle")
+ STRING(test_tree1, reg, "reg")
+ STRING(test_tree1, address_cells, "#address-cells")
+ STRING(test_tree1, size_cells, "#size-cells")
test_tree1_strings_end:
test_tree1_end:
diff --git a/tests/truncated_property.c b/tests/truncated_property.c
index 56daa2276be9..f820d99e3f5d 100644
--- a/tests/truncated_property.c
+++ b/tests/truncated_property.c
@@ -23,7 +23,6 @@
#include <string.h>
#include <stdint.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/tests/utilfdt_test.c b/tests/utilfdt_test.c
index 36b4aa54de49..274c3d68e953 100644
--- a/tests/utilfdt_test.c
+++ b/tests/utilfdt_test.c
@@ -24,7 +24,6 @@
#include <stdint.h>
#include <stdarg.h>
-#include <fdt.h>
#include <libfdt.h>
#include <util.h>
diff --git a/tests/value-labels.c b/tests/value-labels.c
index abe272164927..dcf20593d5c1 100644
--- a/tests/value-labels.c
+++ b/tests/value-labels.c
@@ -26,7 +26,6 @@
#include <dlfcn.h>
-#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
diff --git a/treesource.c b/treesource.c
index 33eeba55fb4d..bf7a626e18ab 100644
--- a/treesource.c
+++ b/treesource.c
@@ -26,12 +26,12 @@ extern int yyparse(void);
extern YYLTYPE yylloc;
struct boot_info *the_boot_info;
-int treesource_error;
+bool treesource_error;
struct boot_info *dt_from_source(const char *fname)
{
the_boot_info = NULL;
- treesource_error = 0;
+ treesource_error = false;
srcfile_push(fname);
yyin = current_srcfile->f;
@@ -54,9 +54,9 @@ static void write_prefix(FILE *f, int level)
fputc('\t', f);
}
-static int isstring(char c)
+static bool isstring(char c)
{
- return (isprint(c)
+ return (isprint((unsigned char)c)
|| (c == '\0')
|| strchr("\a\b\t\n\v\f\r", c));
}
@@ -119,7 +119,7 @@ static void write_propval_string(FILE *f, struct data val)
fprintf(f, "\"");
break;
default:
- if (isprint(c))
+ if (isprint((unsigned char)c))
fprintf(f, "%c", c);
else
fprintf(f, "\\x%02hhx", c);
diff --git a/util.c b/util.c
index 2422c34e11df..330b594b70ba 100644
--- a/util.c
+++ b/util.c
@@ -34,6 +34,7 @@
#include "libfdt.h"
#include "util.h"
+#include "version_gen.h"
char *xstrdup(const char *s)
{
@@ -69,10 +70,10 @@ char *join_path(const char *path, const char *name)
return str;
}
-int util_is_printable_string(const void *data, int len)
+bool util_is_printable_string(const void *data, int len)
{
const char *s = data;
- const char *ss;
+ const char *ss, *se;
/* zero length is not */
if (len == 0)
@@ -82,13 +83,19 @@ int util_is_printable_string(const void *data, int len)
if (s[len - 1] != '\0')
return 0;
- ss = s;
- while (*s && isprint(*s))
- s++;
+ se = s + len;
- /* not zero, or not done yet */
- if (*s != '\0' || (s + 1 - ss) < len)
- return 0;
+ while (s < se) {
+ ss = s;
+ while (s < se && *s && isprint((unsigned char)*s))
+ s++;
+
+ /* not zero, or not done yet */
+ if (*s != '\0' || s == ss)
+ return 0;
+
+ s++;
+ }
return 1;
}
@@ -191,7 +198,7 @@ char get_escape_char(const char *s, int *i)
return val;
}
-int utilfdt_read_err(const char *filename, char **buffp)
+int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len)
{
int fd = 0; /* assume stdin */
char *buf = NULL;
@@ -206,12 +213,12 @@ int utilfdt_read_err(const char *filename, char **buffp)
}
/* Loop until we have read everything */
- buf = malloc(bufsize);
+ buf = xmalloc(bufsize);
do {
/* Expand the buffer to hold the next chunk */
if (offset == bufsize) {
bufsize *= 2;
- buf = realloc(buf, bufsize);
+ buf = xrealloc(buf, bufsize);
if (!buf) {
ret = ENOMEM;
break;
@@ -232,13 +239,20 @@ int utilfdt_read_err(const char *filename, char **buffp)
free(buf);
else
*buffp = buf;
+ *len = bufsize;
return ret;
}
-char *utilfdt_read(const char *filename)
+int utilfdt_read_err(const char *filename, char **buffp)
+{
+ off_t len;
+ return utilfdt_read_err_len(filename, buffp, &len);
+}
+
+char *utilfdt_read_len(const char *filename, off_t *len)
{
char *buff;
- int ret = utilfdt_read_err(filename, &buff);
+ int ret = utilfdt_read_err_len(filename, &buff, len);
if (ret) {
fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
@@ -249,6 +263,12 @@ char *utilfdt_read(const char *filename)
return buff;
}
+char *utilfdt_read(const char *filename)
+{
+ off_t len;
+ return utilfdt_read_len(filename, &len);
+}
+
int utilfdt_write_err(const char *filename, const void *blob)
{
int fd = 1; /* assume stdout */
@@ -329,3 +349,100 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
return -1;
return 0;
}
+
+void utilfdt_print_data(const char *data, int len)
+{
+ int i;
+ const char *p = data;
+ const char *s;
+
+ /* no data, don't print */
+ if (len == 0)
+ return;
+
+ if (util_is_printable_string(data, len)) {
+ printf(" = ");
+
+ s = data;
+ do {
+ printf("\"%s\"", s);
+ s += strlen(s) + 1;
+ if (s < data + len)
+ printf(", ");
+ } while (s < data + len);
+
+ } else if ((len % 4) == 0) {
+ const uint32_t *cell = (const uint32_t *)data;
+
+ printf(" = <");
+ for (i = 0; i < len; i += 4)
+ printf("0x%08x%s", fdt32_to_cpu(cell[i / 4]),
+ i < (len - 4) ? " " : "");
+ printf(">");
+ } else {
+ printf(" = [");
+ for (i = 0; i < len; i++)
+ printf("%02x%s", *p++, i < len - 1 ? " " : "");
+ printf("]");
+ }
+}
+
+void util_version(void)
+{
+ printf("Version: %s\n", DTC_VERSION);
+ exit(0);
+}
+
+void util_usage(const char *errmsg, const char *synopsis,
+ const char *short_opts, struct option const long_opts[],
+ const char * const opts_help[])
+{
+ FILE *fp = errmsg ? stderr : stdout;
+ const char a_arg[] = "<arg>";
+ size_t a_arg_len = strlen(a_arg) + 1;
+ size_t i;
+ int optlen;
+
+ fprintf(fp,
+ "Usage: %s\n"
+ "\n"
+ "Options: -[%s]\n", synopsis, short_opts);
+
+ /* prescan the --long opt length to auto-align */
+ optlen = 0;
+ for (i = 0; long_opts[i].name; ++i) {
+ /* +1 is for space between --opt and help text */
+ int l = strlen(long_opts[i].name) + 1;
+ if (long_opts[i].has_arg == a_argument)
+ l += a_arg_len;
+ if (optlen < l)
+ optlen = l;
+ }
+
+ for (i = 0; long_opts[i].name; ++i) {
+ /* helps when adding new applets or options */
+ assert(opts_help[i] != NULL);
+
+ /* first output the short flag if it has one */
+ if (long_opts[i].val > '~')
+ fprintf(fp, " ");
+ else
+ fprintf(fp, " -%c, ", long_opts[i].val);
+
+ /* then the long flag */
+ if (long_opts[i].has_arg == no_argument)
+ fprintf(fp, "--%-*s", optlen, long_opts[i].name);
+ else
+ fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg,
+ (int)(optlen - strlen(long_opts[i].name) - a_arg_len), "");
+
+ /* finally the help text */
+ fprintf(fp, "%s\n", opts_help[i]);
+ }
+
+ if (errmsg) {
+ fprintf(fp, "\nError: %s\n", errmsg);
+ exit(EXIT_FAILURE);
+ } else
+ exit(EXIT_SUCCESS);
+}
diff --git a/util.h b/util.h
index c8eb45d9f04b..ccfdf4b12433 100644
--- a/util.h
+++ b/util.h
@@ -2,6 +2,8 @@
#define _UTIL_H
#include <stdarg.h>
+#include <stdbool.h>
+#include <getopt.h>
/*
* Copyright 2011 The Chromium Authors, All Rights Reserved.
@@ -23,7 +25,9 @@
* USA
*/
-static inline void __attribute__((noreturn)) die(char * str, ...)
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+static inline void __attribute__((noreturn)) die(const char *str, ...)
{
va_list ap;
@@ -57,13 +61,15 @@ extern char *xstrdup(const char *s);
extern char *join_path(const char *path, const char *name);
/**
- * Check a string of a given length to see if it is all printable and
- * has a valid terminator.
+ * Check a property of a given length to see if it is all printable and
+ * has a valid terminator. The property can contain either a single string,
+ * or multiple strings each of non-zero length.
*
* @param data The string to check
* @param len The string length including terminator
- * @return 1 if a valid printable string, 0 if not */
-int util_is_printable_string(const void *data, int len);
+ * @return 1 if a valid printable string, 0 if not
+ */
+bool util_is_printable_string(const void *data, int len);
/*
* Parse an escaped character starting at index i in string s. The resulting
@@ -83,6 +89,13 @@ char get_escape_char(const char *s, int *i);
char *utilfdt_read(const char *filename);
/**
+ * Like utilfdt_read(), but also passes back the size of the file read.
+ *
+ * @param len If non-NULL, the amount of data we managed to read
+ */
+char *utilfdt_read_len(const char *filename, off_t *len);
+
+/**
* Read a device tree file into a buffer. Does not report errors, but only
* returns them. The value returned can be passed to strerror() to obtain
* an error message for the user.
@@ -93,6 +106,12 @@ char *utilfdt_read(const char *filename);
*/
int utilfdt_read_err(const char *filename, char **buffp);
+/**
+ * Like utilfdt_read_err(), but also passes back the size of the file read.
+ *
+ * @param len If non-NULL, the amount of data we managed to read
+ */
+int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len);
/**
* Write a device tree buffer to a file. This will report any errors on
@@ -148,6 +167,85 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size);
#define USAGE_TYPE_MSG \
"<type>\ts=string, i=int, u=unsigned, x=hex\n" \
"\tOptional modifier prefix:\n" \
- "\t\thh or b=byte, h=2 byte, l=4 byte (default)\n";
+ "\t\thh or b=byte, h=2 byte, l=4 byte (default)";
+
+/**
+ * Print property data in a readable format to stdout
+ *
+ * Properties that look like strings will be printed as strings. Otherwise
+ * the data will be displayed either as cells (if len is a multiple of 4
+ * bytes) or bytes.
+ *
+ * If len is 0 then this function does nothing.
+ *
+ * @param data Pointers to property data
+ * @param len Length of property data
+ */
+void utilfdt_print_data(const char *data, int len);
+
+/**
+ * Show source version and exit
+ */
+void util_version(void) __attribute__((noreturn));
+
+/**
+ * Show usage and exit
+ *
+ * This helps standardize the output of various utils. You most likely want
+ * to use the usage() helper below rather than call this.
+ *
+ * @param errmsg If non-NULL, an error message to display
+ * @param synopsis The initial example usage text (and possible examples)
+ * @param short_opts The string of short options
+ * @param long_opts The structure of long options
+ * @param opts_help An array of help strings (should align with long_opts)
+ */
+void util_usage(const char *errmsg, const char *synopsis,
+ const char *short_opts, struct option const long_opts[],
+ const char * const opts_help[]) __attribute__((noreturn));
+
+/**
+ * Show usage and exit
+ *
+ * If you name all your usage variables with usage_xxx, then you can call this
+ * help macro rather than expanding all arguments yourself.
+ *
+ * @param errmsg If non-NULL, an error message to display
+ */
+#define usage(errmsg) \
+ util_usage(errmsg, usage_synopsis, usage_short_opts, \
+ usage_long_opts, usage_opts_help)
+
+/**
+ * Call getopt_long() with standard options
+ *
+ * Since all util code runs getopt in the same way, provide a helper.
+ */
+#define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \
+ usage_long_opts, NULL)
+
+/* Helper for aligning long_opts array */
+#define a_argument required_argument
+
+/* Helper for usage_short_opts string constant */
+#define USAGE_COMMON_SHORT_OPTS "hV"
+
+/* Helper for usage_long_opts option array */
+#define USAGE_COMMON_LONG_OPTS \
+ {"help", no_argument, NULL, 'h'}, \
+ {"version", no_argument, NULL, 'V'}, \
+ {NULL, no_argument, NULL, 0x0}
+
+/* Helper for usage_opts_help array */
+#define USAGE_COMMON_OPTS_HELP \
+ "Print this help and exit", \
+ "Print version and exit", \
+ NULL
+
+/* Helper for getopt case statements */
+#define case_USAGE_COMMON_FLAGS \
+ case 'h': usage(NULL); \
+ case 'V': util_version(); \
+ case '?': usage("unknown option");
#endif /* _UTIL_H */