dtc: import latest upstream dtc
authorStephen Warren <swarren@nvidia.com>
Fri, 28 Sep 2012 21:25:59 +0000 (21:25 +0000)
committerRob Herring <rob.herring@calxeda.com>
Mon, 1 Oct 2012 16:11:35 +0000 (11:11 -0500)
This updates scripts/dtc to commit 317a5d9 "dtc: zero out new label
objects" from git://git.jdl.com/software/dtc.git.

This adds features such as:
* /bits/ syntax for cell data.
* Math expressions within cell data.
* The ability to delete properties or nodes.
* Support for #line directives in the input file, which allows the use of
  cpp on *.dts.
* -i command-line option (/include/ path)
* -W/-E command-line options for error/warning control.
* Removal of spew to STDOUT containing the filename being compiled.
* Many additions to the libfdt API.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Jon Loeliger <jdl@jdl.com>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
30 files changed:
scripts/dtc/Makefile.dtc
scripts/dtc/checks.c
scripts/dtc/data.c
scripts/dtc/dtc-lexer.l
scripts/dtc/dtc-lexer.lex.c_shipped
scripts/dtc/dtc-parser.tab.c_shipped
scripts/dtc/dtc-parser.tab.h_shipped
scripts/dtc/dtc-parser.y
scripts/dtc/dtc.c
scripts/dtc/dtc.h
scripts/dtc/fdtdump.c [new file with mode: 0644]
scripts/dtc/fdtget.c [new file with mode: 0644]
scripts/dtc/fdtput.c [new file with mode: 0644]
scripts/dtc/flattree.c
scripts/dtc/libfdt/Makefile.libfdt
scripts/dtc/libfdt/fdt.c
scripts/dtc/libfdt/fdt_empty_tree.c [new file with mode: 0644]
scripts/dtc/libfdt/fdt_ro.c
scripts/dtc/libfdt/fdt_rw.c
scripts/dtc/libfdt/fdt_sw.c
scripts/dtc/libfdt/fdt_wip.c
scripts/dtc/libfdt/libfdt.h
scripts/dtc/libfdt/libfdt_env.h
scripts/dtc/libfdt/libfdt_internal.h
scripts/dtc/livetree.c
scripts/dtc/srcpos.c
scripts/dtc/srcpos.h
scripts/dtc/treesource.c
scripts/dtc/util.c
scripts/dtc/util.h

index 6ddf9ec..bece49b 100644 (file)
@@ -3,7 +3,16 @@
 # This is not a complete Makefile of itself.  Instead, it is designed to
 # be easily embeddable into other systems of Makefiles.
 #
-DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
-       checks.c
+DTC_SRCS = \
+       checks.c \
+       data.c \
+       dtc.c \
+       flattree.c \
+       fstree.c \
+       livetree.c \
+       srcpos.c \
+       treesource.c \
+       util.c
+
 DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
 DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
index a662a00..ee96a25 100644 (file)
 #define TRACE(c, fmt, ...)     do { } while (0)
 #endif
 
-enum checklevel {
-       IGNORE = 0,
-       WARN = 1,
-       ERROR = 2,
-};
-
 enum checkstatus {
        UNCHECKED = 0,
        PREREQ,
@@ -57,14 +51,14 @@ struct check {
        node_check_fn node_fn;
        prop_check_fn prop_fn;
        void *data;
-       enum checklevel level;
+       bool warn, error;
        enum checkstatus status;
        int inprogress;
        int num_prereqs;
        struct check **prereq;
 };
 
-#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \
+#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...)          \
        static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
        static struct check nm = { \
                .name = #nm, \
@@ -72,20 +66,37 @@ struct check {
                .node_fn = (nfn), \
                .prop_fn = (pfn), \
                .data = (d), \
-               .level = (lvl), \
+               .warn = (w), \
+               .error = (e), \
                .status = UNCHECKED, \
                .num_prereqs = ARRAY_SIZE(nm##_prereqs), \
                .prereq = nm##_prereqs, \
        };
-
-#define TREE_CHECK(nm, d, lvl, ...) \
-       CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__)
-#define NODE_CHECK(nm, d, lvl, ...) \
-       CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__)
-#define PROP_CHECK(nm, d, lvl, ...) \
-       CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__)
-#define BATCH_CHECK(nm, lvl, ...) \
-       CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__)
+#define WARNING(nm, tfn, nfn, pfn, d, ...) \
+       CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
+#define ERROR(nm, tfn, nfn, pfn, d, ...) \
+       CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__)
+#define CHECK(nm, tfn, nfn, pfn, d, ...) \
+       CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__)
+
+#define TREE_WARNING(nm, d, ...) \
+       WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
+#define TREE_ERROR(nm, d, ...) \
+       ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
+#define TREE_CHECK(nm, d, ...) \
+       CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
+#define NODE_WARNING(nm, d, ...) \
+       WARNING(nm, NULL, check_##nm, NULL, d,  __VA_ARGS__)
+#define NODE_ERROR(nm, d, ...) \
+       ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
+#define NODE_CHECK(nm, d, ...) \
+       CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
+#define PROP_WARNING(nm, d, ...) \
+       WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
+#define PROP_ERROR(nm, d, ...) \
+       ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
+#define PROP_CHECK(nm, d, ...) \
+       CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
 
 #ifdef __GNUC__
 static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
@@ -95,13 +106,13 @@ static inline void check_msg(struct check *c, const char *fmt, ...)
        va_list ap;
        va_start(ap, fmt);
 
-       if ((c->level < WARN) || (c->level <= quiet))
-               return; /* Suppress message */
-
-       fprintf(stderr, "%s (%s): ",
-               (c->level == ERROR) ? "ERROR" : "Warning", c->name);
-       vfprintf(stderr, fmt, ap);
-       fprintf(stderr, "\n");
+       if ((c->warn && (quiet < 1))
+           || (c->error && (quiet < 2))) {
+               fprintf(stderr, "%s (%s): ",
+                       (c->error) ? "ERROR" : "Warning", c->name);
+               vfprintf(stderr, fmt, ap);
+               fprintf(stderr, "\n");
+       }
 }
 
 #define FAIL(c, ...) \
@@ -167,7 +178,7 @@ static int run_check(struct check *c, struct node *dt)
 
 out:
        c->inprogress = 0;
-       if ((c->status != PASSED) && (c->level == ERROR))
+       if ((c->status != PASSED) && (c->error))
                error = 1;
        return error;
 }
@@ -176,6 +187,13 @@ out:
  * Utility check functions
  */
 
+/* A check which always fails, for testing purposes only */
+static inline void check_always_fail(struct check *c, struct node *dt)
+{
+       FAIL(c, "always_fail check");
+}
+TREE_CHECK(always_fail, NULL);
+
 static void check_is_string(struct check *c, struct node *root,
                            struct node *node)
 {
@@ -190,8 +208,10 @@ static void check_is_string(struct check *c, struct node *root,
                FAIL(c, "\"%s\" property in %s is not a string",
                     propname, node->fullpath);
 }
-#define CHECK_IS_STRING(nm, propname, lvl) \
-       CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl))
+#define WARNING_IF_NOT_STRING(nm, propname) \
+       WARNING(nm, NULL, check_is_string, NULL, (propname))
+#define ERROR_IF_NOT_STRING(nm, propname) \
+       ERROR(nm, NULL, check_is_string, NULL, (propname))
 
 static void check_is_cell(struct check *c, struct node *root,
                          struct node *node)
@@ -207,8 +227,10 @@ static void check_is_cell(struct check *c, struct node *root,
                FAIL(c, "\"%s\" property in %s is not a single cell",
                     propname, node->fullpath);
 }
-#define CHECK_IS_CELL(nm, propname, lvl) \
-       CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl))
+#define WARNING_IF_NOT_CELL(nm, propname) \
+       WARNING(nm, NULL, check_is_cell, NULL, (propname))
+#define ERROR_IF_NOT_CELL(nm, propname) \
+       ERROR(nm, NULL, check_is_cell, NULL, (propname))
 
 /*
  * Structural check functions
@@ -227,20 +249,24 @@ static void check_duplicate_node_names(struct check *c, struct node *dt,
                                FAIL(c, "Duplicate node name %s",
                                     child->fullpath);
 }
-NODE_CHECK(duplicate_node_names, NULL, ERROR);
+NODE_ERROR(duplicate_node_names, NULL);
 
 static void check_duplicate_property_names(struct check *c, struct node *dt,
                                           struct node *node)
 {
        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_CHECK(duplicate_property_names, NULL, ERROR);
+NODE_ERROR(duplicate_property_names, NULL);
 
 #define LOWERCASE      "abcdefghijklmnopqrstuvwxyz"
 #define UPPERCASE      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -256,7 +282,7 @@ static void check_node_name_chars(struct check *c, struct node *dt,
                FAIL(c, "Bad character '%c' in node %s",
                     node->name[n], node->fullpath);
 }
-NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);
+NODE_ERROR(node_name_chars, PROPNODECHARS "@");
 
 static void check_node_name_format(struct check *c, struct node *dt,
                                   struct node *node)
@@ -265,7 +291,7 @@ static void check_node_name_format(struct check *c, struct node *dt,
                FAIL(c, "Node %s has multiple '@' characters in name",
                     node->fullpath);
 }
-NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);
+NODE_ERROR(node_name_format, NULL, &node_name_chars);
 
 static void check_property_name_chars(struct check *c, struct node *dt,
                                      struct node *node, struct property *prop)
@@ -276,7 +302,7 @@ static void check_property_name_chars(struct check *c, struct node *dt,
                FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
                     prop->name[n], prop->name, node->fullpath);
 }
-PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);
+PROP_ERROR(property_name_chars, PROPNODECHARS);
 
 #define DESCLABEL_FMT  "%s%s%s%s%s"
 #define DESCLABEL_ARGS(node,prop,mark)         \
@@ -331,8 +357,8 @@ static void check_duplicate_label_prop(struct check *c, struct node *dt,
        for_each_marker_of_type(m, LABEL)
                check_duplicate_label(c, dt, m->ref, node, prop, m);
 }
-CHECK(duplicate_label, NULL, check_duplicate_label_node,
-      check_duplicate_label_prop, NULL, ERROR);
+ERROR(duplicate_label, NULL, check_duplicate_label_node,
+      check_duplicate_label_prop, NULL);
 
 static void check_explicit_phandles(struct check *c, struct node *root,
                                    struct node *node, struct property *prop)
@@ -391,7 +417,7 @@ static void check_explicit_phandles(struct check *c, struct node *root,
 
        node->phandle = phandle;
 }
-PROP_CHECK(explicit_phandles, NULL, ERROR);
+PROP_ERROR(explicit_phandles, NULL);
 
 static void check_name_properties(struct check *c, struct node *root,
                                  struct node *node)
@@ -420,8 +446,8 @@ static void check_name_properties(struct check *c, struct node *root,
                free(prop);
        }
 }
-CHECK_IS_STRING(name_is_string, "name", ERROR);
-NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
+ERROR_IF_NOT_STRING(name_is_string, "name");
+NODE_ERROR(name_properties, NULL, &name_is_string);
 
 /*
  * Reference fixup functions
@@ -448,7 +474,7 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
                *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
        }
 }
-CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
+ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,
       &duplicate_node_names, &explicit_phandles);
 
 static void fixup_path_references(struct check *c, struct node *dt,
@@ -473,19 +499,19 @@ static void fixup_path_references(struct check *c, struct node *dt,
                                                  strlen(path) + 1);
        }
 }
-CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR,
+ERROR(path_references, NULL, NULL, fixup_path_references, NULL,
       &duplicate_node_names);
 
 /*
  * Semantic checks
  */
-CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN);
-CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
-CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
+WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
+WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
+WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
 
-CHECK_IS_STRING(device_type_is_string, "device_type", WARN);
-CHECK_IS_STRING(model_is_string, "model", WARN);
-CHECK_IS_STRING(status_is_string, "status", WARN);
+WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
+WARNING_IF_NOT_STRING(model_is_string, "model");
+WARNING_IF_NOT_STRING(status_is_string, "status");
 
 static void fixup_addr_size_cells(struct check *c, struct node *dt,
                                  struct node *node)
@@ -503,8 +529,8 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt,
        if (prop)
                node->size_cells = propval_cell(prop);
 }
-CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN,
-      &address_cells_is_cell, &size_cells_is_cell);
+WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL,
+       &address_cells_is_cell, &size_cells_is_cell);
 
 #define node_addr_cells(n) \
        (((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
@@ -538,7 +564,7 @@ static void check_reg_format(struct check *c, struct node *dt,
                     "(#address-cells == %d, #size-cells == %d)",
                     node->fullpath, prop->val.len, addr_cells, size_cells);
 }
-NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells);
+NODE_WARNING(reg_format, NULL, &addr_size_cells);
 
 static void check_ranges_format(struct check *c, struct node *dt,
                                struct node *node)
@@ -579,7 +605,7 @@ static void check_ranges_format(struct check *c, struct node *dt,
                     p_addr_cells, c_addr_cells, c_size_cells);
        }
 }
-NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells);
+NODE_WARNING(ranges_format, NULL, &addr_size_cells);
 
 /*
  * Style checks
@@ -606,7 +632,7 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt,
                FAIL(c, "Relying on default #size-cells value for %s",
                     node->fullpath);
 }
-NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells);
+NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells);
 
 static void check_obsolete_chosen_interrupt_controller(struct check *c,
                                                       struct node *dt)
@@ -623,7 +649,7 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
                FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
                     "property");
 }
-TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
+TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
 
 static struct check *check_table[] = {
        &duplicate_node_names, &duplicate_property_names,
@@ -642,8 +668,71 @@ static struct check *check_table[] = {
 
        &avoid_default_addr_size,
        &obsolete_chosen_interrupt_controller,
+
+       &always_fail,
 };
 
+static void enable_warning_error(struct check *c, bool warn, bool error)
+{
+       int i;
+
+       /* Raising level, also raise it for prereqs */
+       if ((warn && !c->warn) || (error && !c->error))
+               for (i = 0; i < c->num_prereqs; i++)
+                       enable_warning_error(c->prereq[i], warn, error);
+
+       c->warn = c->warn || warn;
+       c->error = c->error || error;
+}
+
+static void disable_warning_error(struct check *c, bool warn, bool error)
+{
+       int i;
+
+       /* Lowering level, also lower it for things this is the prereq
+        * for */
+       if ((warn && c->warn) || (error && c->error)) {
+               for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+                       struct check *cc = check_table[i];
+                       int j;
+
+                       for (j = 0; j < cc->num_prereqs; j++)
+                               if (cc->prereq[j] == c)
+                                       disable_warning_error(cc, warn, error);
+               }
+       }
+
+       c->warn = c->warn && !warn;
+       c->error = c->error && !error;
+}
+
+void parse_checks_option(bool warn, bool error, const char *optarg)
+{
+       int i;
+       const char *name = optarg;
+       bool enable = true;
+
+       if ((strncmp(optarg, "no-", 3) == 0)
+           || (strncmp(optarg, "no_", 3) == 0)) {
+               name = optarg + 3;
+               enable = false;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+               struct check *c = check_table[i];
+
+               if (streq(c->name, name)) {
+                       if (enable)
+                               enable_warning_error(c, warn, error);
+                       else
+                               disable_warning_error(c, warn, error);
+                       return;
+               }
+       }
+
+       die("Unrecognized check name \"%s\"\n", name);
+}
+
 void process_checks(int force, struct boot_info *bi)
 {
        struct node *dt = bi->dt;
@@ -653,7 +742,7 @@ void process_checks(int force, struct boot_info *bi)
        for (i = 0; i < ARRAY_SIZE(check_table); i++) {
                struct check *c = check_table[i];
 
-               if (c->level != IGNORE)
+               if (c->warn || c->error)
                        error = error || run_check(c, dt);
        }
 
index fe555e8..4a40c5b 100644 (file)
@@ -68,40 +68,6 @@ struct data data_copy_mem(const char *mem, int len)
        return d;
 }
 
-static char get_oct_char(const char *s, int *i)
-{
-       char x[4];
-       char *endx;
-       long val;
-
-       x[3] = '\0';
-       strncpy(x, s + *i, 3);
-
-       val = strtol(x, &endx, 8);
-
-       assert(endx > x);
-
-       (*i) += endx - x;
-       return val;
-}
-
-static char get_hex_char(const char *s, int *i)
-{
-       char x[3];
-       char *endx;
-       long val;
-
-       x[2] = '\0';
-       strncpy(x, s + *i, 2);
-
-       val = strtol(x, &endx, 16);
-       if (!(endx  > x))
-               die("\\x used with no following hex digits\n");
-
-       (*i) += endx - x;
-       return val;
-}
-
 struct data data_copy_escape_string(const char *s, int len)
 {
        int i = 0;
@@ -114,53 +80,10 @@ struct data data_copy_escape_string(const char *s, int len)
        while (i < len) {
                char c = s[i++];
 
-               if (c != '\\') {
-                       q[d.len++] = c;
-                       continue;
-               }
-
-               c = s[i++];
-               assert(c);
-               switch (c) {
-               case 'a':
-                       q[d.len++] = '\a';
-                       break;
-               case 'b':
-                       q[d.len++] = '\b';
-                       break;
-               case 't':
-                       q[d.len++] = '\t';
-                       break;
-               case 'n':
-                       q[d.len++] = '\n';
-                       break;
-               case 'v':
-                       q[d.len++] = '\v';
-                       break;
-               case 'f':
-                       q[d.len++] = '\f';
-                       break;
-               case 'r':
-                       q[d.len++] = '\r';
-                       break;
-               case '0':
-               case '1':
-               case '2':
-               case '3':
-               case '4':
-               case '5':
-               case '6':
-               case '7':
-                       i--; /* need to re-read the first digit as
-                             * part of the octal value */
-                       q[d.len++] = get_oct_char(s, &i);
-                       break;
-               case 'x':
-                       q[d.len++] = get_hex_char(s, &i);
-                       break;
-               default:
-                       q[d.len++] = c;
-               }
+               if (c == '\\')
+                       c = get_escape_char(s, &i);
+
+               q[d.len++] = c;
        }
 
        q[d.len++] = '\0';
@@ -245,11 +168,33 @@ struct data data_merge(struct data d1, struct data d2)
        return d;
 }
 
-struct data data_append_cell(struct data d, cell_t word)
+struct data data_append_integer(struct data d, uint64_t value, int bits)
 {
-       cell_t beword = cpu_to_fdt32(word);
-
-       return data_append_data(d, &beword, sizeof(beword));
+       uint8_t value_8;
+       uint16_t value_16;
+       uint32_t value_32;
+       uint64_t value_64;
+
+       switch (bits) {
+       case 8:
+               value_8 = value;
+               return data_append_data(d, &value_8, 1);
+
+       case 16:
+               value_16 = cpu_to_fdt16(value);
+               return data_append_data(d, &value_16, 2);
+
+       case 32:
+               value_32 = cpu_to_fdt32(value);
+               return data_append_data(d, &value_32, 4);
+
+       case 64:
+               value_64 = cpu_to_fdt64(value);
+               return data_append_data(d, &value_64, 8);
+
+       default:
+               die("Invalid literal size (%d)\n", bits);
+       }
 }
 
 struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
@@ -262,11 +207,14 @@ struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
        return data_append_data(d, &bere, sizeof(bere));
 }
 
-struct data data_append_addr(struct data d, uint64_t addr)
+struct data data_append_cell(struct data d, cell_t word)
 {
-       uint64_t beaddr = cpu_to_fdt64(addr);
+       return data_append_integer(d, word, sizeof(word) * 8);
+}
 
-       return data_append_data(d, &beaddr, sizeof(beaddr));
+struct data data_append_addr(struct data d, uint64_t addr)
+{
+       return data_append_integer(d, addr, sizeof(addr) * 8);
 }
 
 struct data data_append_byte(struct data d, uint8_t byte)
index e866ea5..254d5af 100644 (file)
@@ -29,6 +29,7 @@ PROPNODECHAR  [a-zA-Z0-9,._+*#?@-]
 PATHCHAR       ({PROPNODECHAR}|[/])
 LABEL          [a-zA-Z_][a-zA-Z0-9_]*
 STRING         \"([^\\"]|\\.)*\"
+CHAR_LITERAL   '([^']|\\')*'
 WS             [[:space:]]
 COMMENT                "/*"([^*]|\*+[^*/])*\*+"/"
 LINECOMMENT    "//".*\n
@@ -70,6 +71,27 @@ static int pop_input_file(void);
                        push_input_file(name);
                }
 
+<*>^"#"(line)?{WS}+[0-9]+{WS}+{STRING}({WS}+[0-9]+)? {
+                       char *line, *tmp, *fn;
+                       /* skip text before line # */
+                       line = yytext;
+                       while (!isdigit(*line))
+                               line++;
+                       /* skip digits in line # */
+                       tmp = line;
+                       while (!isspace(*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();
@@ -96,6 +118,26 @@ static int pop_input_file(void);
                        return DT_MEMRESERVE;
                }
 
+<*>"/bits/"    {
+                       DPRINT("Keyword: /bits/\n");
+                       BEGIN_DEFAULT();
+                       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);
@@ -103,12 +145,19 @@ static int pop_input_file(void);
                        return DT_LABEL;
                }
 
-<V1>[0-9]+|0[xX][0-9a-fA-F]+      {
+<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
                        yylval.literal = xstrdup(yytext);
                        DPRINT("Literal: '%s'\n", yylval.literal);
                        return DT_LITERAL;
                }
 
+<*>{CHAR_LITERAL}      {
+                       yytext[yyleng-1] = '\0';
+                       yylval.literal = xstrdup(yytext+1);
+                       DPRINT("Character literal: %s\n", yylval.literal);
+                       return DT_CHAR_LITERAL;
+               }
+
 <*>\&{LABEL}   {       /* label reference */
                        DPRINT("Ref: %s\n", yytext+1);
                        yylval.labelref = xstrdup(yytext+1);
@@ -134,9 +183,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;
                }
@@ -150,6 +200,15 @@ static int pop_input_file(void);
 <*>{COMMENT}+  /* eat C-style comments */
 <*>{LINECOMMENT}+ /* eat C++-style comments */
 
+<*>"<<"                { return DT_LSHIFT; };
+<*>">>"                { return DT_RSHIFT; };
+<*>"<="                { return DT_LE; };
+<*>">="                { return DT_GE; };
+<*>"=="                { return DT_EQ; };
+<*>"!="                { return DT_NE; };
+<*>"&&"                { return DT_AND; };
+<*>"||"                { return DT_OR; };
+
 <*>.           {
                        DPRINT("Char: %c (\\x%02x)\n", yytext[0],
                                (unsigned)yytext[0]);
index 8bbe128..a6c5fcd 100644 (file)
@@ -1,5 +1,6 @@
+#line 2 "dtc-lexer.lex.c"
 
-#line 3 "scripts/dtc/dtc-lexer.lex.c_shipped"
+#line 4 "dtc-lexer.lex.c"
 
 #define  YY_INT_ALIGNED short int
 
@@ -53,7 +54,6 @@ typedef int flex_int32_t;
 typedef unsigned char flex_uint8_t; 
 typedef unsigned short int flex_uint16_t;
 typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
 
 /* Limits of integral types. */
 #ifndef INT8_MIN
@@ -84,6 +84,8 @@ typedef unsigned int flex_uint32_t;
 #define UINT32_MAX             (4294967295U)
 #endif
 
+#endif /* ! C99 */
+
 #endif /* ! FLEXINT_H */
 
 #ifdef __cplusplus
@@ -140,7 +142,15 @@ typedef unsigned int flex_uint32_t;
 
 /* Size of default input buffer. */
 #ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
 #define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
 #endif
 
 /* The state buf must be large enough to hold one state per character in the main buffer.
@@ -362,8 +372,8 @@ static void yy_fatal_error (yyconst char msg[]  );
        *yy_cp = '\0'; \
        (yy_c_buf_p) = yy_cp;
 
-#define YY_NUM_RULES 17
-#define YY_END_OF_BUFFER 18
+#define YY_NUM_RULES 30
+#define YY_END_OF_BUFFER 31
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -371,19 +381,25 @@ struct yy_trans_info
        flex_int32_t yy_verify;
        flex_int32_t yy_nxt;
        };
-static yyconst flex_int16_t yy_accept[94] =
+static yyconst flex_int16_t yy_accept[161] =
     {   0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       18,   16,   13,   13,   16,   16,   16,   16,   16,   16,
-       16,   10,   11,   11,    6,    6,   13,    0,    2,    0,
-        7,    0,    0,    0,    0,    0,    0,    0,    5,    0,
-        9,    9,   11,   11,    6,    0,    7,    0,    0,    0,
-        0,   15,    0,    0,    0,    0,    6,    0,   14,    0,
-        0,    0,    0,    0,    8,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    3,   12,
-        0,    0,    0,    0,    0,    0,    0,    0,    1,    0,
-        0,    4,    0
-
+       31,   29,   18,   18,   29,   29,   29,   29,   29,   29,
+       29,   29,   29,   29,   29,   29,   29,   29,   15,   16,
+       16,   29,   16,   10,   10,   18,   26,    0,    3,    0,
+       27,   12,    0,    0,   11,    0,    0,    0,    0,    0,
+        0,    0,   21,   23,   25,   24,   22,    0,    9,   28,
+        0,    0,    0,   14,   14,   16,   16,   16,   10,   10,
+       10,    0,   12,    0,   11,    0,    0,    0,   20,    0,
+        0,    0,    0,    0,    0,    0,    0,   16,   10,   10,
+       10,    0,   19,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,   16,   13,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,   16,    6,    0,    0,    0,    0,    0,
+        0,    2,    0,    0,    0,    0,    0,    0,    0,    0,
+        4,   17,    0,    0,    2,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    1,    0,    0,
+        0,    0,    5,    8,    0,    0,    0,    0,    7,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -391,17 +407,17 @@ static yyconst flex_int32_t yy_ec[256] =
         1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
         2,    2,    2,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    1,    4,    5,    1,    1,    6,    1,    1,
-        1,    7,    5,    5,    8,    5,    9,   10,   11,   12,
-       12,   12,   12,   12,   12,   12,   12,   13,    1,    1,
-        1,    1,    5,    5,   14,   14,   14,   14,   14,   14,
-       15,   15,   15,   15,   15,   15,   15,   15,   15,   15,
-       15,   15,   15,   15,   15,   15,   15,   16,   15,   15,
-        1,   17,   18,    1,   15,    1,   14,   19,   20,   21,
-
-       22,   14,   15,   15,   23,   15,   15,   24,   25,   26,
-       15,   15,   15,   27,   28,   29,   30,   31,   15,   16,
-       15,   15,   32,    1,   33,    1,    1,    1,    1,    1,
+        1,    2,    4,    5,    6,    1,    1,    7,    8,    1,
+        1,    9,   10,   10,   11,   10,   12,   13,   14,   15,
+       15,   15,   15,   15,   15,   15,   15,   16,    1,   17,
+       18,   19,   10,   10,   20,   20,   20,   20,   20,   20,
+       21,   21,   21,   21,   21,   22,   21,   21,   21,   21,
+       21,   21,   21,   21,   23,   21,   21,   24,   21,   21,
+        1,   25,   26,    1,   21,    1,   20,   27,   28,   29,
+
+       30,   20,   21,   21,   31,   21,   21,   32,   33,   34,
+       35,   36,   21,   37,   38,   39,   40,   41,   21,   24,
+       42,   21,   43,   44,   45,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -418,112 +434,163 @@ static yyconst flex_int32_t yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int32_t yy_meta[34] =
+static yyconst flex_int32_t yy_meta[46] =
     {   0,
-        1,    1,    1,    1,    2,    1,    2,    2,    3,    4,
-        4,    4,    5,    6,    7,    7,    1,    1,    6,    6,
-        6,    6,    7,    7,    7,    7,    7,    7,    7,    7,
-        7,    8,    1
+        1,    1,    1,    1,    1,    2,    3,    1,    2,    2,
+        2,    4,    5,    5,    5,    6,    1,    1,    1,    7,
+        8,    8,    8,    8,    1,    1,    7,    7,    7,    7,
+        8,    8,    8,    8,    8,    8,    8,    8,    8,    8,
+        8,    8,    3,    1,    1
     } ;
 
-static yyconst flex_int16_t yy_base[106] =
+static yyconst flex_int16_t yy_base[175] =
     {   0,
-        0,    0,  237,  236,   25,    0,   47,    0,   30,   71,
-      244,  247,   82,   84,   84,  211,   95,  229,  218,    0,
-      111,  247,    0,   84,   83,   95,  106,   86,  247,  237,
-        0,  230,  231,  234,  207,  209,  212,  220,  247,  206,
-      247,  218,    0,  106,  116,    0,    0,    0,  223,   89,
-      226,  219,  199,  206,  200,  204,    0,  190,  213,  212,
-      202,   91,  178,  161,  247,  172,  144,  150,  140,  130,
-      140,  124,  128,  120,  138,  137,  123,  122,  247,  247,
-      134,  114,  132,   86,  135,  125,   90,  136,  247,   97,
-       29,  247,  247,  153,  156,  161,  165,  170,  176,  180,
-
-      187,  195,  200,  205,  212
+        0,  388,  381,   40,   41,  386,   71,  385,   34,   44,
+      390,  395,   60,   62,  371,  112,  111,  111,  111,  104,
+      370,  106,  371,  342,  124,  119,    0,  144,  395,    0,
+      123,    0,  159,  153,  165,  167,  395,  130,  395,  382,
+      395,    0,  372,  122,  395,  157,  374,  379,  350,   21,
+      346,  349,  395,  395,  395,  395,  395,  362,  395,  395,
+      181,  346,  342,  395,  359,    0,  191,  343,  190,  351,
+      350,    0,    0,    0,  173,  362,  177,  367,  357,  329,
+      335,  328,  337,  331,  206,  329,  334,  327,  395,  338,
+      170,  314,  346,  345,  318,  325,  343,  158,  316,  212,
+
+      322,  319,  320,  395,  340,  336,  308,  305,  314,  304,
+      295,  138,  208,  220,  395,  292,  305,  265,  264,  254,
+      201,  222,  285,  275,  273,  270,  236,  235,  225,  115,
+      395,  395,  252,  216,  216,  217,  214,  230,  209,  220,
+      213,  239,  211,  217,  216,  209,  229,  395,  240,  225,
+      206,  169,  395,  395,  116,  106,   99,   54,  395,  395,
+      254,  260,  268,  272,  276,  282,  289,  293,  301,  309,
+      313,  319,  327,  335
     } ;
 
-static yyconst flex_int16_t yy_def[106] =
+static yyconst flex_int16_t yy_def[175] =
     {   0,
-       93,    1,    1,    1,    1,    5,   93,    7,    1,    1,
-       93,   93,   93,   93,   94,   95,   93,   96,   17,   97,
-       96,   93,   98,   99,   93,   93,   93,   94,   93,   94,
-      100,   93,  101,  102,   93,   93,   93,   96,   93,   93,
-       93,   96,   98,   99,   93,  103,  100,  104,  101,  101,
-      102,   93,   93,   93,   93,   93,  103,  104,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,  105,   93,  105,   93,  105,
-       93,   93,    0,   93,   93,   93,   93,   93,   93,   93,
-
-       93,   93,   93,   93,   93
+      160,    1,    1,    1,    1,    5,  160,    7,    1,    1,
+      160,  160,  160,  160,  160,  161,  162,  163,  160,  160,
+      160,  160,  164,  160,  160,  160,  165,  164,  160,  166,
+      167,  166,  166,  160,  160,  160,  160,  161,  160,  161,
+      160,  168,  160,  163,  160,  163,  169,  170,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  164,  160,  160,
+      160,  160,  160,  160,  164,  166,  167,  166,  160,  160,
+      160,  171,  168,  172,  163,  169,  169,  170,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  166,  160,  160,
+      171,  172,  160,  160,  160,  160,  160,  160,  160,  160,
+
+      160,  160,  166,  160,  160,  160,  160,  160,  160,  160,
+      160,  173,  160,  166,  160,  160,  160,  160,  160,  160,
+      173,  160,  173,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  174,  160,  160,  160,  174,  160,  174,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,    0,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160
     } ;
 
-static yyconst flex_int16_t yy_nxt[281] =
+static yyconst flex_int16_t yy_nxt[441] =
     {   0,
-       12,   13,   14,   15,   12,   16,   12,   12,   17,   12,
-       12,   12,   12,   18,   18,   18,   12,   12,   18,   18,
-       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
-       18,   12,   12,   19,   20,   20,   20,   92,   21,   25,
-       26,   26,   22,   21,   21,   21,   21,   12,   13,   14,
-       15,   23,   16,   23,   23,   19,   23,   23,   23,   12,
-       24,   24,   24,   12,   12,   24,   24,   24,   24,   24,
-       24,   24,   24,   24,   24,   24,   24,   24,   12,   12,
-       25,   26,   26,   27,   27,   27,   27,   29,   43,   29,
-       43,   43,   45,   45,   45,   50,   39,   59,   46,   93,
-
-       30,   33,   30,   34,   45,   45,   45,   27,   27,   68,
-       43,   91,   43,   43,   69,   35,   87,   36,   39,   37,
-       42,   42,   42,   39,   42,   45,   45,   45,   89,   42,
-       42,   42,   42,   85,   85,   86,   85,   85,   86,   89,
-       84,   90,   83,   82,   81,   80,   79,   78,   77,   76,
-       75,   74,   90,   28,   28,   28,   28,   28,   28,   28,
-       28,   31,   31,   31,   38,   38,   38,   38,   41,   73,
-       41,   43,   72,   43,   71,   43,   43,   44,   33,   44,
-       44,   44,   44,   47,   69,   47,   47,   49,   49,   49,
-       49,   49,   49,   49,   49,   51,   51,   51,   51,   51,
-
-       51,   51,   51,   57,   70,   57,   58,   58,   58,   67,
-       58,   58,   88,   88,   88,   88,   88,   88,   88,   88,
-       34,   66,   65,   64,   63,   62,   61,   60,   52,   50,
-       39,   56,   39,   55,   54,   53,   52,   50,   48,   93,
-       40,   39,   32,   93,   19,   19,   11,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93
+       12,   13,   14,   15,   16,   12,   17,   18,   12,   12,
+       12,   19,   12,   12,   12,   12,   20,   21,   22,   23,
+       23,   23,   23,   23,   12,   12,   23,   23,   23,   23,
+       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       23,   23,   12,   24,   12,   25,   34,   35,   35,   25,
+       81,   26,   26,   27,   27,   27,   34,   35,   35,   82,
+       28,   36,   36,   36,   36,  159,   29,   28,   28,   28,
+       28,   12,   13,   14,   15,   16,   30,   17,   18,   30,
+       30,   30,   26,   30,   30,   30,   12,   20,   21,   22,
+       31,   31,   31,   31,   31,   32,   12,   31,   31,   31,
+
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   12,   24,   12,   39,   41,   45,   47,
+       53,   54,   48,   56,   57,   61,   61,   47,   66,   45,
+       48,   66,   66,   66,   39,   46,   40,   49,   59,   50,
+      158,   51,  122,   52,  157,   49,   46,   50,  136,   63,
+      137,   52,  156,   43,   40,   62,   65,   65,   65,   59,
+       61,   61,  123,   65,   75,   69,   69,   69,   36,   36,
+       65,   65,   65,   65,   70,   71,   72,   69,   69,   69,
+       45,   46,   61,   61,  109,   77,   70,   71,   93,  110,
+       68,   70,   71,   85,   85,   85,   66,   46,  155,   66,
+
+       66,   66,   69,   69,   69,  122,   59,  100,  100,   61,
+       61,   70,   71,  100,  100,  148,  112,  154,   85,   85,
+       85,   61,   61,  129,  129,  123,  129,  129,  135,  135,
+      135,  142,  142,  148,  143,  149,  153,  135,  135,  135,
+      142,  142,  160,  143,  152,  151,  150,  146,  145,  144,
+      141,  140,  139,  149,   38,   38,   38,   38,   38,   38,
+       38,   38,   42,  138,  134,  133,   42,   42,   44,   44,
+       44,   44,   44,   44,   44,   44,   58,   58,   58,   58,
+       64,  132,   64,   66,  131,  130,   66,  160,   66,   66,
+       67,  128,  127,   67,   67,   67,   67,   73,  126,   73,
+
+       73,   76,   76,   76,   76,   76,   76,   76,   76,   78,
+       78,   78,   78,   78,   78,   78,   78,   91,  125,   91,
+       92,  124,   92,   92,  120,   92,   92,  121,  121,  121,
+      121,  121,  121,  121,  121,  147,  147,  147,  147,  147,
+      147,  147,  147,  119,  118,  117,  116,  115,   47,  114,
+      110,  113,  111,  108,  107,  106,   48,  105,  104,   89,
+      103,  102,  101,   99,   98,   97,   96,   95,   94,   79,
+       77,   90,   89,   88,   59,   87,   86,   59,   84,   83,
+       80,   79,   77,   74,  160,   60,   59,   55,   37,  160,
+       33,   25,   26,   25,   11,  160,  160,  160,  160,  160,
+
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160
     } ;
 
-static yyconst flex_int16_t yy_chk[281] =
+static yyconst flex_int16_t yy_chk[441] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    5,    5,    5,    5,   91,    5,    9,
-        9,    9,    5,    5,    5,    5,    5,    7,    7,    7,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    4,    9,    9,    9,   10,
+       50,    4,    5,    5,    5,    5,   10,   10,   10,   50,
+        5,   13,   13,   14,   14,  158,    5,    5,    5,    5,
+        5,    7,    7,    7,    7,    7,    7,    7,    7,    7,
         7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
         7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
+
         7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
-       10,   10,   10,   13,   13,   14,   14,   15,   24,   28,
-       24,   24,   25,   25,   25,   50,   24,   50,   25,   90,
-
-       15,   17,   28,   17,   26,   26,   26,   27,   27,   62,
-       44,   87,   44,   44,   62,   17,   84,   17,   44,   17,
-       21,   21,   21,   21,   21,   45,   45,   45,   86,   21,
-       21,   21,   21,   83,   83,   83,   85,   85,   85,   88,
-       82,   86,   81,   78,   77,   76,   75,   74,   73,   72,
-       71,   70,   88,   94,   94,   94,   94,   94,   94,   94,
-       94,   95,   95,   95,   96,   96,   96,   96,   97,   69,
-       97,   98,   68,   98,   67,   98,   98,   99,   66,   99,
-       99,   99,   99,  100,   64,  100,  100,  101,  101,  101,
-      101,  101,  101,  101,  101,  102,  102,  102,  102,  102,
-
-      102,  102,  102,  103,   63,  103,  104,  104,  104,   61,
-      104,  104,  105,  105,  105,  105,  105,  105,  105,  105,
-       60,   59,   58,   56,   55,   54,   53,   52,   51,   49,
-       42,   40,   38,   37,   36,   35,   34,   33,   32,   30,
-       19,   18,   16,   11,    4,    3,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93
+        7,    7,    7,    7,    7,    7,   16,   17,   18,   19,
+       20,   20,   19,   22,   22,   25,   25,   26,   31,   44,
+       26,   31,   31,   31,   38,   18,   16,   19,   31,   19,
+      157,   19,  112,   19,  156,   26,   44,   26,  130,   26,
+      130,   26,  155,   17,   38,   25,   28,   28,   28,   28,
+       33,   33,  112,   28,   46,   34,   34,   34,   36,   36,
+       28,   28,   28,   28,   34,   34,   34,   35,   35,   35,
+       75,   46,   61,   61,   98,   77,   35,   35,   77,   98,
+       33,   91,   91,   61,   61,   61,   67,   75,  152,   67,
+
+       67,   67,   69,   69,   69,  121,   67,   85,   85,  113,
+      113,   69,   69,  100,  100,  143,  100,  151,   85,   85,
+       85,  114,  114,  122,  122,  121,  129,  129,  135,  135,
+      135,  138,  138,  147,  138,  143,  150,  129,  129,  129,
+      142,  142,  149,  142,  146,  145,  144,  141,  140,  139,
+      137,  136,  134,  147,  161,  161,  161,  161,  161,  161,
+      161,  161,  162,  133,  128,  127,  162,  162,  163,  163,
+      163,  163,  163,  163,  163,  163,  164,  164,  164,  164,
+      165,  126,  165,  166,  125,  124,  166,  123,  166,  166,
+      167,  120,  119,  167,  167,  167,  167,  168,  118,  168,
+
+      168,  169,  169,  169,  169,  169,  169,  169,  169,  170,
+      170,  170,  170,  170,  170,  170,  170,  171,  117,  171,
+      172,  116,  172,  172,  111,  172,  172,  173,  173,  173,
+      173,  173,  173,  173,  173,  174,  174,  174,  174,  174,
+      174,  174,  174,  110,  109,  108,  107,  106,  105,  103,
+      102,  101,   99,   97,   96,   95,   94,   93,   92,   90,
+       88,   87,   86,   84,   83,   82,   81,   80,   79,   78,
+       76,   71,   70,   68,   65,   63,   62,   58,   52,   51,
+       49,   48,   47,   43,   40,   24,   23,   21,   15,   11,
+        8,    6,    3,    2,  160,  160,  160,  160,  160,  160,
+
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160
     } ;
 
 static yy_state_type yy_last_accepting_state;
@@ -540,6 +607,7 @@ int yy_flex_debug = 0;
 #define YY_MORE_ADJ 0
 #define YY_RESTORE_YY_MORE_OFFSET
 char *yytext;
+#line 1 "dtc-lexer.l"
 /*
  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
  *
@@ -561,6 +629,10 @@ char *yytext;
  */
 #define YY_NO_INPUT 1
 
+
+
+
+#line 38 "dtc-lexer.l"
 #include "dtc.h"
 #include "srcpos.h"
 #include "dtc-parser.tab.h"
@@ -588,6 +660,7 @@ static int dts_version = 1;
 
 static void push_input_file(const char *filename);
 static int pop_input_file(void);
+#line 664 "dtc-lexer.lex.c"
 
 #define INITIAL 0
 #define INCLUDE 1
@@ -670,7 +743,12 @@ static int input (void );
 
 /* Amount of stuff to slurp up with each read. */
 #ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
 #define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
 #endif
 
 /* Copy whatever the last rule matched to the standard output. */
@@ -689,7 +767,7 @@ static int input (void );
        if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
                { \
                int c = '*'; \
-               unsigned n; \
+               size_t n; \
                for ( n = 0; n < max_size && \
                             (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
                        buf[n] = (char) c; \
@@ -761,6 +839,9 @@ extern int yylex (void);
 #endif
 
 #define YY_RULE_SETUP \
+       if ( yyleng > 0 ) \
+               YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+                               (yytext[yyleng - 1] == '\n'); \
        YY_USER_ACTION
 
 /** The main scanner function which does all the work.
@@ -771,6 +852,10 @@ YY_DECL
        register char *yy_cp, *yy_bp;
        register int yy_act;
     
+#line 67 "dtc-lexer.l"
+
+#line 858 "dtc-lexer.lex.c"
+
        if ( !(yy_init) )
                {
                (yy_init) = 1;
@@ -810,6 +895,7 @@ YY_DECL
                yy_bp = yy_cp;
 
                yy_current_state = (yy_start);
+               yy_current_state += YY_AT_BOL();
 yy_match:
                do
                        {
@@ -822,13 +908,13 @@ yy_match:
                        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                                {
                                yy_current_state = (int) yy_def[yy_current_state];
-                               if ( yy_current_state >= 94 )
+                               if ( yy_current_state >= 161 )
                                        yy_c = yy_meta[(unsigned int) yy_c];
                                }
                        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
                        ++yy_cp;
                        }
-               while ( yy_current_state != 93 );
+               while ( yy_current_state != 160 );
                yy_cp = (yy_last_accepting_cpos);
                yy_current_state = (yy_last_accepting_state);
 
@@ -851,26 +937,54 @@ do_action:        /* This label is used only to access EOF actions. */
 case 1:
 /* rule 1 can match eol */
 YY_RULE_SETUP
+#line 68 "dtc-lexer.l"
 {
                        char *name = strchr(yytext, '\"') + 1;
                        yytext[yyleng-1] = '\0';
                        push_input_file(name);
                }
        YY_BREAK
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+#line 74 "dtc-lexer.l"
+{
+                       char *line, *tmp, *fn;
+                       /* skip text before line # */
+                       line = yytext;
+                       while (!isdigit(*line))
+                               line++;
+                       /* skip digits in line # */
+                       tmp = line;
+                       while (!isspace(*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);
+               }
+       YY_BREAK
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(INCLUDE):
 case YY_STATE_EOF(BYTESTRING):
 case YY_STATE_EOF(PROPNODENAME):
 case YY_STATE_EOF(V1):
+#line 95 "dtc-lexer.l"
 {
                        if (!pop_input_file()) {
                                yyterminate();
                        }
                }
        YY_BREAK
-case 2:
-/* rule 2 can match eol */
+case 3:
+/* rule 3 can match eol */
 YY_RULE_SETUP
+#line 101 "dtc-lexer.l"
 {
                        DPRINT("String: %s\n", yytext);
                        yylval.data = data_copy_escape_string(yytext+1,
@@ -878,8 +992,9 @@ YY_RULE_SETUP
                        return DT_STRING;
                }
        YY_BREAK
-case 3:
+case 4:
 YY_RULE_SETUP
+#line 108 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /dts-v1/\n");
                        dts_version = 1;
@@ -887,16 +1002,47 @@ YY_RULE_SETUP
                        return DT_V1;
                }
        YY_BREAK
-case 4:
+case 5:
 YY_RULE_SETUP
+#line 115 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /memreserve/\n");
                        BEGIN_DEFAULT();
                        return DT_MEMRESERVE;
                }
        YY_BREAK
-case 5:
+case 6:
+YY_RULE_SETUP
+#line 121 "dtc-lexer.l"
+{
+                       DPRINT("Keyword: /bits/\n");
+                       BEGIN_DEFAULT();
+                       return DT_BITS;
+               }
+       YY_BREAK
+case 7:
 YY_RULE_SETUP
+#line 127 "dtc-lexer.l"
+{
+                       DPRINT("Keyword: /delete-property/\n");
+                       DPRINT("<PROPNODENAME>\n");
+                       BEGIN(PROPNODENAME);
+                       return DT_DEL_PROP;
+               }
+       YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 134 "dtc-lexer.l"
+{
+                       DPRINT("Keyword: /delete-node/\n");
+                       DPRINT("<PROPNODENAME>\n");
+                       BEGIN(PROPNODENAME);
+                       return DT_DEL_NODE;
+               }
+       YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 141 "dtc-lexer.l"
 {
                        DPRINT("Label: %s\n", yytext);
                        yylval.labelref = xstrdup(yytext);
@@ -904,24 +1050,38 @@ YY_RULE_SETUP
                        return DT_LABEL;
                }
        YY_BREAK
-case 6:
+case 10:
 YY_RULE_SETUP
+#line 148 "dtc-lexer.l"
 {
                        yylval.literal = xstrdup(yytext);
                        DPRINT("Literal: '%s'\n", yylval.literal);
                        return DT_LITERAL;
                }
        YY_BREAK
-case 7:
+case 11:
+/* rule 11 can match eol */
+YY_RULE_SETUP
+#line 154 "dtc-lexer.l"
+{
+                       yytext[yyleng-1] = '\0';
+                       yylval.literal = xstrdup(yytext+1);
+                       DPRINT("Character literal: %s\n", yylval.literal);
+                       return DT_CHAR_LITERAL;
+               }
+       YY_BREAK
+case 12:
 YY_RULE_SETUP
+#line 161 "dtc-lexer.l"
 {      /* label reference */
                        DPRINT("Ref: %s\n", yytext+1);
                        yylval.labelref = xstrdup(yytext+1);
                        return DT_REF;
                }
        YY_BREAK
-case 8:
+case 13:
 YY_RULE_SETUP
+#line 167 "dtc-lexer.l"
 {      /* new-style path reference */
                        yytext[yyleng-1] = '\0';
                        DPRINT("Ref: %s\n", yytext+2);
@@ -929,55 +1089,104 @@ YY_RULE_SETUP
                        return DT_REF;
                }
        YY_BREAK
-case 9:
+case 14:
 YY_RULE_SETUP
+#line 174 "dtc-lexer.l"
 {
                        yylval.byte = strtol(yytext, NULL, 16);
                        DPRINT("Byte: %02x\n", (int)yylval.byte);
                        return DT_BYTE;
                }
        YY_BREAK
-case 10:
+case 15:
 YY_RULE_SETUP
+#line 180 "dtc-lexer.l"
 {
                        DPRINT("/BYTESTRING\n");
                        BEGIN_DEFAULT();
                        return ']';
                }
        YY_BREAK
-case 11:
+case 16:
 YY_RULE_SETUP
+#line 186 "dtc-lexer.l"
 {
                        DPRINT("PropNodeName: %s\n", yytext);
-                       yylval.propnodename = xstrdup(yytext);
+                       yylval.propnodename = xstrdup((yytext[0] == '\\') ?
+                                                       yytext + 1 : yytext);
                        BEGIN_DEFAULT();
                        return DT_PROPNODENAME;
                }
        YY_BREAK
-case 12:
+case 17:
 YY_RULE_SETUP
+#line 194 "dtc-lexer.l"
 {
                        DPRINT("Binary Include\n");
                        return DT_INCBIN;
                }
        YY_BREAK
-case 13:
-/* rule 13 can match eol */
+case 18:
+/* rule 18 can match eol */
 YY_RULE_SETUP
+#line 199 "dtc-lexer.l"
 /* eat whitespace */
        YY_BREAK
-case 14:
-/* rule 14 can match eol */
+case 19:
+/* rule 19 can match eol */
 YY_RULE_SETUP
+#line 200 "dtc-lexer.l"
 /* eat C-style comments */
        YY_BREAK
-case 15:
-/* rule 15 can match eol */
+case 20:
+/* rule 20 can match eol */
 YY_RULE_SETUP
+#line 201 "dtc-lexer.l"
 /* eat C++-style comments */
        YY_BREAK
-case 16:
+case 21:
 YY_RULE_SETUP
+#line 203 "dtc-lexer.l"
+{ return DT_LSHIFT; };
+       YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 204 "dtc-lexer.l"
+{ return DT_RSHIFT; };
+       YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 205 "dtc-lexer.l"
+{ return DT_LE; };
+       YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 206 "dtc-lexer.l"
+{ return DT_GE; };
+       YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 207 "dtc-lexer.l"
+{ return DT_EQ; };
+       YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 208 "dtc-lexer.l"
+{ return DT_NE; };
+       YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 209 "dtc-lexer.l"
+{ return DT_AND; };
+       YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 210 "dtc-lexer.l"
+{ return DT_OR; };
+       YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 212 "dtc-lexer.l"
 {
                        DPRINT("Char: %c (\\x%02x)\n", yytext[0],
                                (unsigned)yytext[0]);
@@ -993,10 +1202,12 @@ YY_RULE_SETUP
                        return yytext[0];
                }
        YY_BREAK
-case 17:
+case 30:
 YY_RULE_SETUP
+#line 227 "dtc-lexer.l"
 ECHO;
        YY_BREAK
+#line 1211 "dtc-lexer.lex.c"
 
        case YY_END_OF_BUFFER:
                {
@@ -1275,6 +1486,7 @@ static int yy_get_next_buffer (void)
        register char *yy_cp;
     
        yy_current_state = (yy_start);
+       yy_current_state += YY_AT_BOL();
 
        for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
                {
@@ -1287,7 +1499,7 @@ static int yy_get_next_buffer (void)
                while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                        {
                        yy_current_state = (int) yy_def[yy_current_state];
-                       if ( yy_current_state >= 94 )
+                       if ( yy_current_state >= 161 )
                                yy_c = yy_meta[(unsigned int) yy_c];
                        }
                yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1315,11 +1527,11 @@ static int yy_get_next_buffer (void)
        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                {
                yy_current_state = (int) yy_def[yy_current_state];
-               if ( yy_current_state >= 94 )
+               if ( yy_current_state >= 161 )
                        yy_c = yy_meta[(unsigned int) yy_c];
                }
        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-       yy_is_jam = (yy_current_state == 93);
+       yy_is_jam = (yy_current_state == 160);
 
        return yy_is_jam ? 0 : yy_current_state;
 }
@@ -1394,6 +1606,8 @@ static int yy_get_next_buffer (void)
        *(yy_c_buf_p) = '\0';   /* preserve yytext */
        (yy_hold_char) = *++(yy_c_buf_p);
 
+       YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
        return c;
 }
 #endif /* ifndef YY_NO_INPUT */
@@ -1712,8 +1926,8 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
 
 /** Setup the input buffer state to scan the given bytes. The next call to yylex() will
  * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
  * 
  * @return the newly allocated buffer state object.
  */
@@ -1952,6 +2166,10 @@ void yyfree (void * ptr )
 
 #define YYTABLES_NAME "yytables"
 
+#line 227 "dtc-lexer.l"
+
+
+
 static void push_input_file(const char *filename)
 {
        assert(filename);
@@ -1963,6 +2181,7 @@ static void push_input_file(const char *filename)
        yypush_buffer_state(yy_create_buffer(yyin,YY_BUF_SIZE));
 }
 
+
 static int pop_input_file(void)
 {
        if (srcfile_pop() == 0)
index b05921e..4af5590 100644 (file)
@@ -1,9 +1,10 @@
-/* A Bison parser, made by GNU Bison 2.4.3.  */
+
+/* A Bison parser, made by GNU Bison 2.4.1.  */
 
 /* Skeleton implementation for Bison's Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-   2009, 2010 Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -45,7 +46,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.4.3"
+#define YYBISON_VERSION "2.4.1"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -66,6 +67,8 @@
 
 /* Copy the first part of user declarations.  */
 
+/* Line 189 of yacc.c  */
+#line 21 "dtc-parser.y"
 
 #include <stdio.h>
 
@@ -82,12 +85,15 @@ 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);
 
 
+/* Line 189 of yacc.c  */
+#line 93 "dtc-parser.tab.c"
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
-# define YYDEBUG 1
+# define YYDEBUG 0
 #endif
 
 /* Enabling verbose error messages.  */
@@ -112,14 +118,26 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
    enum yytokentype {
      DT_V1 = 258,
      DT_MEMRESERVE = 259,
-     DT_PROPNODENAME = 260,
-     DT_LITERAL = 261,
-     DT_BASE = 262,
-     DT_BYTE = 263,
-     DT_STRING = 264,
-     DT_LABEL = 265,
-     DT_REF = 266,
-     DT_INCBIN = 267
+     DT_LSHIFT = 260,
+     DT_RSHIFT = 261,
+     DT_LE = 262,
+     DT_GE = 263,
+     DT_EQ = 264,
+     DT_NE = 265,
+     DT_AND = 266,
+     DT_OR = 267,
+     DT_BITS = 268,
+     DT_DEL_PROP = 269,
+     DT_DEL_NODE = 270,
+     DT_PROPNODENAME = 271,
+     DT_LITERAL = 272,
+     DT_CHAR_LITERAL = 273,
+     DT_BASE = 274,
+     DT_BYTE = 275,
+     DT_STRING = 276,
+     DT_LABEL = 277,
+     DT_REF = 278,
+     DT_INCBIN = 279
    };
 #endif
 
@@ -129,6 +147,8 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
 typedef union YYSTYPE
 {
 
+/* Line 214 of yacc.c  */
+#line 40 "dtc-parser.y"
 
        char *propnodename;
        char *literal;
@@ -137,16 +157,22 @@ typedef union YYSTYPE
        uint8_t byte;
        struct data data;
 
-       uint64_t addr;
-       cell_t cell;
+       struct {
+               struct data     data;
+               int             bits;
+       } array;
+
        struct property *prop;
        struct property *proplist;
        struct node *node;
        struct node *nodelist;
        struct reserve_info *re;
+       uint64_t integer;
 
 
 
+/* Line 214 of yacc.c  */
+#line 176 "dtc-parser.tab.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -157,6 +183,8 @@ typedef union YYSTYPE
 /* Copy the second part of user declarations.  */
 
 
+/* Line 264 of yacc.c  */
+#line 188 "dtc-parser.tab.c"
 
 #ifdef short
 # undef short
@@ -206,7 +234,7 @@ typedef short int yytype_int16;
 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
 #ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
+# if YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -371,20 +399,20 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  4
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   56
+#define YYLAST   133
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  25
+#define YYNTOKENS  48
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  16
+#define YYNNTS  28
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  39
+#define YYNRULES  79
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  67
+#define YYNSTATES  141
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   267
+#define YYMAXUTOK   279
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -395,16 +423,16 @@ static const yytype_uint8 yytranslate[] =
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      22,    24,     2,     2,    23,     2,     2,    14,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,    13,
-      18,    17,    19,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    47,     2,     2,     2,    45,    41,     2,
+      33,    35,    44,    42,    34,    43,     2,    26,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    38,    25,
+      36,    29,    30,    37,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    20,     2,    21,     2,     2,     2,     2,     2,     2,
+       2,    31,     2,    32,    40,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    15,     2,    16,     2,     2,     2,     2,
+       2,     2,     2,    27,    39,    28,    46,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -418,45 +446,68 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24
 };
 
 #if YYDEBUG
 /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
    YYRHS.  */
-static const yytype_uint8 yyprhs[] =
+static const yytype_uint16 yyprhs[] =
 {
-       0,     0,     3,     8,     9,    12,    17,    20,    22,    25,
-      29,    33,    39,    40,    43,    48,    51,    54,    57,    62,
-      67,    70,    80,    86,    89,    90,    93,    96,    97,   100,
-     103,   106,   108,   109,   112,   115,   116,   119,   122,   125
+       0,     0,     3,     8,     9,    12,    17,    20,    23,    27,
+      31,    36,    42,    43,    46,    51,    54,    58,    61,    64,
+      68,    73,    76,    86,    92,    95,    96,    99,   102,   106,
+     108,   111,   114,   117,   119,   121,   125,   127,   129,   135,
+     137,   141,   143,   147,   149,   153,   155,   159,   161,   165,
+     167,   171,   175,   177,   181,   185,   189,   193,   197,   201,
+     203,   207,   211,   213,   217,   221,   225,   227,   229,   232,
+     235,   238,   239,   242,   245,   246,   249,   252,   255,   259
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      26,     0,    -1,     3,    13,    27,    30,    -1,    -1,    28,
-      27,    -1,     4,    29,    29,    13,    -1,    10,    28,    -1,
-       6,    -1,    14,    31,    -1,    30,    14,    31,    -1,    30,
-      11,    31,    -1,    15,    32,    39,    16,    13,    -1,    -1,
-      32,    33,    -1,     5,    17,    34,    13,    -1,     5,    13,
-      -1,    10,    33,    -1,    35,     9,    -1,    35,    18,    36,
-      19,    -1,    35,    20,    38,    21,    -1,    35,    11,    -1,
-      35,    12,    22,     9,    23,    29,    23,    29,    24,    -1,
-      35,    12,    22,     9,    24,    -1,    34,    10,    -1,    -1,
-      34,    23,    -1,    35,    10,    -1,    -1,    36,    37,    -1,
-      36,    11,    -1,    36,    10,    -1,     6,    -1,    -1,    38,
-       8,    -1,    38,    10,    -1,    -1,    40,    39,    -1,    40,
-      33,    -1,     5,    31,    -1,    10,    40,    -1
+      49,     0,    -1,     3,    25,    50,    52,    -1,    -1,    51,
+      50,    -1,     4,    59,    59,    25,    -1,    22,    51,    -1,
+      26,    53,    -1,    52,    26,    53,    -1,    52,    23,    53,
+      -1,    52,    15,    23,    25,    -1,    27,    54,    74,    28,
+      25,    -1,    -1,    54,    55,    -1,    16,    29,    56,    25,
+      -1,    16,    25,    -1,    14,    16,    25,    -1,    22,    55,
+      -1,    57,    21,    -1,    57,    58,    30,    -1,    57,    31,
+      73,    32,    -1,    57,    23,    -1,    57,    24,    33,    21,
+      34,    59,    34,    59,    35,    -1,    57,    24,    33,    21,
+      35,    -1,    56,    22,    -1,    -1,    56,    34,    -1,    57,
+      22,    -1,    13,    17,    36,    -1,    36,    -1,    58,    59,
+      -1,    58,    23,    -1,    58,    22,    -1,    17,    -1,    18,
+      -1,    33,    60,    35,    -1,    61,    -1,    62,    -1,    62,
+      37,    60,    38,    61,    -1,    63,    -1,    62,    12,    63,
+      -1,    64,    -1,    63,    11,    64,    -1,    65,    -1,    64,
+      39,    65,    -1,    66,    -1,    65,    40,    66,    -1,    67,
+      -1,    66,    41,    67,    -1,    68,    -1,    67,     9,    68,
+      -1,    67,    10,    68,    -1,    69,    -1,    68,    36,    69,
+      -1,    68,    30,    69,    -1,    68,     7,    69,    -1,    68,
+       8,    69,    -1,    69,     5,    70,    -1,    69,     6,    70,
+      -1,    70,    -1,    70,    42,    71,    -1,    70,    43,    71,
+      -1,    71,    -1,    71,    44,    72,    -1,    71,    26,    72,
+      -1,    71,    45,    72,    -1,    72,    -1,    59,    -1,    43,
+      72,    -1,    46,    72,    -1,    47,    72,    -1,    -1,    73,
+      20,    -1,    73,    22,    -1,    -1,    75,    74,    -1,    75,
+      55,    -1,    16,    53,    -1,    15,    16,    25,    -1,    22,
+      75,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,    86,    86,    95,    98,   105,   109,   117,   124,   128,
-     132,   145,   153,   156,   163,   167,   171,   179,   183,   187,
-     191,   195,   212,   222,   230,   233,   237,   245,   248,   252,
-     257,   264,   272,   275,   279,   287,   290,   294,   302,   306
+       0,   109,   109,   118,   121,   128,   132,   140,   144,   148,
+     158,   172,   180,   183,   190,   194,   198,   202,   210,   214,
+     218,   222,   226,   243,   253,   261,   264,   268,   275,   290,
+     295,   315,   329,   336,   340,   344,   351,   355,   356,   360,
+     361,   365,   366,   370,   371,   375,   376,   380,   381,   385,
+     386,   387,   391,   392,   393,   394,   395,   399,   400,   401,
+     405,   406,   407,   411,   412,   413,   414,   418,   419,   420,
+     421,   426,   429,   433,   441,   444,   448,   456,   460,   464
 };
 #endif
 
@@ -465,13 +516,19 @@ static const yytype_uint16 yyrline[] =
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
 {
-  "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE",
-  "DT_PROPNODENAME", "DT_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING",
-  "DT_LABEL", "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='",
-  "'<'", "'>'", "'['", "']'", "'('", "','", "')'", "$accept", "sourcefile",
-  "memreserves", "memreserve", "addr", "devicetree", "nodedef", "proplist",
-  "propdef", "propdata", "propdataprefix", "celllist", "cellval",
-  "bytestring", "subnodes", "subnode", 0
+  "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE", "DT_LSHIFT",
+  "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND", "DT_OR",
+  "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME", "DT_LITERAL",
+  "DT_CHAR_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING", "DT_LABEL",
+  "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['",
+  "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'",
+  "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile",
+  "memreserves", "memreserve", "devicetree", "nodedef", "proplist",
+  "propdef", "propdata", "propdataprefix", "arrayprefix", "integer_prim",
+  "integer_expr", "integer_trinary", "integer_or", "integer_and",
+  "integer_bitor", "integer_bitxor", "integer_bitand", "integer_eq",
+  "integer_rela", "integer_shift", "integer_add", "integer_mul",
+  "integer_unary", "bytestring", "subnodes", "subnode", 0
 };
 #endif
 
@@ -481,27 +538,37 @@ static const char *const yytname[] =
 static const yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,    59,    47,   123,   125,    61,    60,    62,
-      91,    93,    40,    44,    41
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,    59,    47,   123,   125,    61,
+      62,    91,    93,    40,    44,    41,    60,    63,    58,   124,
+      94,    38,    43,    45,    42,    37,   126,    33
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    25,    26,    27,    27,    28,    28,    29,    30,    30,
-      30,    31,    32,    32,    33,    33,    33,    34,    34,    34,
-      34,    34,    34,    34,    35,    35,    35,    36,    36,    36,
-      36,    37,    38,    38,    38,    39,    39,    39,    40,    40
+       0,    48,    49,    50,    50,    51,    51,    52,    52,    52,
+      52,    53,    54,    54,    55,    55,    55,    55,    56,    56,
+      56,    56,    56,    56,    56,    57,    57,    57,    58,    58,
+      58,    58,    58,    59,    59,    59,    60,    61,    61,    62,
+      62,    63,    63,    64,    64,    65,    65,    66,    66,    67,
+      67,    67,    68,    68,    68,    68,    68,    69,    69,    69,
+      70,    70,    70,    71,    71,    71,    71,    72,    72,    72,
+      72,    73,    73,    73,    74,    74,    74,    75,    75,    75
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
-       0,     2,     4,     0,     2,     4,     2,     1,     2,     3,
-       3,     5,     0,     2,     4,     2,     2,     2,     4,     4,
-       2,     9,     5,     2,     0,     2,     2,     0,     2,     2,
-       2,     1,     0,     2,     2,     0,     2,     2,     2,     2
+       0,     2,     4,     0,     2,     4,     2,     2,     3,     3,
+       4,     5,     0,     2,     4,     2,     3,     2,     2,     3,
+       4,     2,     9,     5,     2,     0,     2,     2,     3,     1,
+       2,     2,     2,     1,     1,     3,     1,     1,     5,     1,
+       3,     1,     3,     1,     3,     1,     3,     1,     3,     1,
+       3,     3,     1,     3,     3,     3,     3,     3,     3,     1,
+       3,     3,     1,     3,     3,     3,     1,     1,     2,     2,
+       2,     0,     2,     2,     0,     2,     2,     2,     3,     2
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -509,41 +576,59 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       0,     0,     0,     3,     1,     0,     0,     0,     3,     7,
-       0,     6,     0,     2,     4,     0,    12,     8,     0,     0,
-       5,    35,    10,     9,     0,     0,    13,     0,    35,    15,
-      24,    38,    16,    39,     0,    37,    36,     0,     0,    11,
-      23,    14,    25,    17,    26,    20,     0,    27,    32,     0,
-       0,     0,     0,    31,    30,    29,    18,    28,    33,    34,
-      19,     0,    22,     0,     0,     0,    21
+       0,     0,     0,     3,     1,     0,     0,     0,     3,    33,
+      34,     0,     0,     6,     0,     2,     4,     0,     0,     0,
+      67,     0,    36,    37,    39,    41,    43,    45,    47,    49,
+      52,    59,    62,    66,     0,    12,     7,     0,     0,     0,
+      68,    69,    70,    35,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     5,    74,     0,     9,     8,    40,     0,
+      42,    44,    46,    48,    50,    51,    55,    56,    54,    53,
+      57,    58,    60,    61,    64,    63,    65,     0,     0,     0,
+       0,    13,     0,    74,    10,     0,     0,     0,    15,    25,
+      77,    17,    79,     0,    76,    75,    38,    16,    78,     0,
+       0,    11,    24,    14,    26,     0,    18,    27,    21,     0,
+      71,    29,     0,     0,     0,     0,    32,    31,    19,    30,
+      28,     0,    72,    73,    20,     0,    23,     0,     0,     0,
+      22
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,     2,     7,     8,    10,    13,    17,    21,    26,    37,
-      38,    50,    57,    51,    27,    28
+      -1,     2,     7,     8,    15,    36,    64,    91,   109,   110,
+     122,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    32,    33,   125,    92,    93
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -12
+#define YYPACT_NINF -78
 static const yytype_int8 yypact[] =
 {
-      10,   -11,    18,    -1,   -12,    22,    -1,    15,    -1,   -12,
-      22,   -12,    20,     1,   -12,    17,   -12,   -12,    20,    20,
-     -12,     6,   -12,   -12,    21,     6,   -12,    23,     6,   -12,
-     -12,   -12,   -12,   -12,    28,   -12,   -12,    -6,    13,   -12,
-     -12,   -12,   -12,   -12,   -12,   -12,    24,   -12,   -12,    33,
-      -5,     0,    -4,   -12,   -12,   -12,   -12,   -12,   -12,   -12,
-     -12,    22,   -12,    25,    22,    19,   -12
+      22,    11,    51,    10,   -78,    23,    10,     2,    10,   -78,
+     -78,    -9,    23,   -78,    30,    38,   -78,    -9,    -9,    -9,
+     -78,    35,   -78,    -6,    52,    29,    48,    49,    33,     3,
+      71,    36,     0,   -78,    64,   -78,   -78,    68,    30,    30,
+     -78,   -78,   -78,   -78,    -9,    -9,    -9,    -9,    -9,    -9,
+      -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,
+      -9,    -9,    -9,   -78,    44,    67,   -78,   -78,    52,    55,
+      29,    48,    49,    33,     3,     3,    71,    71,    71,    71,
+      36,    36,     0,     0,   -78,   -78,   -78,    78,    79,    42,
+      44,   -78,    69,    44,   -78,    -9,    73,    74,   -78,   -78,
+     -78,   -78,   -78,    75,   -78,   -78,   -78,   -78,   -78,    -7,
+      -1,   -78,   -78,   -78,   -78,    84,   -78,   -78,   -78,    63,
+     -78,   -78,    32,    66,    82,    -3,   -78,   -78,   -78,   -78,
+     -78,    46,   -78,   -78,   -78,    23,   -78,    70,    23,    72,
+     -78
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -12,   -12,    36,    39,   -10,   -12,     8,   -12,    12,   -12,
-     -12,   -12,   -12,   -12,    27,    31
+     -78,   -78,    97,   100,   -78,   -37,   -78,   -77,   -78,   -78,
+     -78,    -5,    65,    13,   -78,    76,    77,    62,    80,    83,
+      34,    20,    26,    28,   -14,   -78,    18,    24
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -553,35 +638,59 @@ static const yytype_int8 yypgoto[] =
 #define YYTABLE_NINF -1
 static const yytype_uint8 yytable[] =
 {
-      15,    53,     3,     5,    40,    54,    55,    41,    58,     6,
-      59,    24,    18,     1,    56,    19,    25,    42,     4,    61,
-      62,    60,    43,    44,    45,    46,    22,    23,     9,    12,
-      20,    47,    31,    48,    29,    16,    16,    32,    30,    34,
-      35,    39,    52,    66,    14,    11,    49,     0,    64,     0,
-       0,    63,     0,     0,    65,    36,    33
+      12,    66,    67,    40,    41,    42,    44,    34,     9,    10,
+      52,    53,   115,   101,     5,   112,   104,   132,   113,   133,
+     116,   117,   118,   119,    11,     1,    60,   114,    14,   134,
+     120,    45,     6,    54,    17,   121,     3,    18,    19,    55,
+       9,    10,    50,    51,    61,    62,    84,    85,    86,     9,
+      10,     4,   100,    37,   126,   127,    11,    35,    87,    88,
+      89,    38,   128,    46,    39,    11,    90,    98,    47,    35,
+      43,    99,    76,    77,    78,    79,    56,    57,    58,    59,
+     135,   136,    80,    81,    74,    75,    82,    83,    48,    63,
+      49,    65,    94,    95,    96,    97,   124,   103,   107,   108,
+     111,   123,   130,   131,   138,    16,    13,   140,   106,    71,
+      69,   105,     0,     0,   102,     0,     0,   129,     0,     0,
+      68,     0,     0,    70,     0,     0,     0,     0,    72,     0,
+     137,     0,    73,   139
 };
 
-static const yytype_int8 yycheck[] =
+static const yytype_int16 yycheck[] =
 {
-      10,     6,    13,     4,    10,    10,    11,    13,     8,    10,
-      10,     5,    11,     3,    19,    14,    10,    23,     0,    23,
-      24,    21,     9,    10,    11,    12,    18,    19,     6,    14,
-      13,    18,    24,    20,    13,    15,    15,    25,    17,    16,
-      28,    13,     9,    24,     8,     6,    22,    -1,    23,    -1,
-      -1,    61,    -1,    -1,    64,    28,    25
+       5,    38,    39,    17,    18,    19,    12,    12,    17,    18,
+       7,     8,    13,    90,     4,    22,    93,    20,    25,    22,
+      21,    22,    23,    24,    33,     3,    26,    34,    26,    32,
+      31,    37,    22,    30,    43,    36,    25,    46,    47,    36,
+      17,    18,     9,    10,    44,    45,    60,    61,    62,    17,
+      18,     0,    89,    15,    22,    23,    33,    27,    14,    15,
+      16,    23,    30,    11,    26,    33,    22,    25,    39,    27,
+      35,    29,    52,    53,    54,    55,     5,     6,    42,    43,
+      34,    35,    56,    57,    50,    51,    58,    59,    40,    25,
+      41,    23,    25,    38,    16,    16,    33,    28,    25,    25,
+      25,    17,    36,    21,    34,     8,     6,    35,    95,    47,
+      45,    93,    -1,    -1,    90,    -1,    -1,   122,    -1,    -1,
+      44,    -1,    -1,    46,    -1,    -1,    -1,    -1,    48,    -1,
+     135,    -1,    49,   138
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     3,    26,    13,     0,     4,    10,    27,    28,     6,
-      29,    28,    14,    30,    27,    29,    15,    31,    11,    14,
-      13,    32,    31,    31,     5,    10,    33,    39,    40,    13,
-      17,    31,    33,    40,    16,    33,    39,    34,    35,    13,
-      10,    13,    23,     9,    10,    11,    12,    18,    20,    22,
-      36,    38,     9,     6,    10,    11,    19,    37,     8,    10,
-      21,    23,    24,    29,    23,    29,    24
+       0,     3,    49,    25,     0,     4,    22,    50,    51,    17,
+      18,    33,    59,    51,    26,    52,    50,    43,    46,    47,
+      59,    60,    61,    62,    63,    64,    65,    66,    67,    68,
+      69,    70,    71,    72,    59,    27,    53,    15,    23,    26,
+      72,    72,    72,    35,    12,    37,    11,    39,    40,    41,
+       9,    10,     7,     8,    30,    36,     5,     6,    42,    43,
+      26,    44,    45,    25,    54,    23,    53,    53,    63,    60,
+      64,    65,    66,    67,    68,    68,    69,    69,    69,    69,
+      70,    70,    71,    71,    72,    72,    72,    14,    15,    16,
+      22,    55,    74,    75,    25,    38,    16,    16,    25,    29,
+      53,    55,    75,    28,    55,    74,    61,    25,    25,    56,
+      57,    25,    22,    25,    34,    13,    21,    22,    23,    24,
+      31,    36,    58,    17,    33,    73,    22,    23,    30,    59,
+      36,    21,    20,    22,    32,    34,    35,    59,    34,    59,
+      35
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -596,18 +705,9 @@ static const yytype_uint8 yystos[] =
 
 /* Like YYERROR except do call yyerror.  This remains here temporarily
    to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  However,
-   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
-   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
-   discussed.  */
+   Once GCC version 2 has supplanted version 1, this can go.  */
 
 #define YYFAIL         goto yyerrlab
-#if defined YYFAIL
-  /* This is here to suppress warnings from the GCC cpp's
-     -Wunused-macros.  Normally we don't worry about that warning, but
-     some users do, and we want to make it easy for users to remove
-     YYFAIL uses, which will produce warnings from Bison 2.5.  */
-#endif
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
@@ -664,7 +764,7 @@ while (YYID (0))
    we won't break user code: when these are the locations we know.  */
 
 #ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+# if YYLTYPE_IS_TRIVIAL
 #  define YY_LOCATION_PRINT(File, Loc)                 \
      fprintf (File, "%d.%d-%d.%d",                     \
              (Loc).first_line, (Loc).first_column,     \
@@ -1403,6 +1503,8 @@ yyreduce:
     {
         case 2:
 
+/* Line 1455 of yacc.c  */
+#line 110 "dtc-parser.y"
     {
                        the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node),
                                                        guess_boot_cpuid((yyvsp[(4) - (4)].node)));
@@ -1411,6 +1513,8 @@ yyreduce:
 
   case 3:
 
+/* Line 1455 of yacc.c  */
+#line 118 "dtc-parser.y"
     {
                        (yyval.re) = NULL;
                ;}
@@ -1418,6 +1522,8 @@ yyreduce:
 
   case 4:
 
+/* Line 1455 of yacc.c  */
+#line 122 "dtc-parser.y"
     {
                        (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
                ;}
@@ -1425,13 +1531,17 @@ yyreduce:
 
   case 5:
 
+/* Line 1455 of yacc.c  */
+#line 129 "dtc-parser.y"
     {
-                       (yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].addr), (yyvsp[(3) - (4)].addr));
+                       (yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].integer), (yyvsp[(3) - (4)].integer));
                ;}
     break;
 
   case 6:
 
+/* Line 1455 of yacc.c  */
+#line 133 "dtc-parser.y"
     {
                        add_label(&(yyvsp[(2) - (2)].re)->labels, (yyvsp[(1) - (2)].labelref));
                        (yyval.re) = (yyvsp[(2) - (2)].re);
@@ -1440,40 +1550,57 @@ yyreduce:
 
   case 7:
 
+/* Line 1455 of yacc.c  */
+#line 141 "dtc-parser.y"
     {
-                       (yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
+                       (yyval.node) = name_node((yyvsp[(2) - (2)].node), "");
                ;}
     break;
 
   case 8:
 
+/* Line 1455 of yacc.c  */
+#line 145 "dtc-parser.y"
     {
-                       (yyval.node) = name_node((yyvsp[(2) - (2)].node), "");
+                       (yyval.node) = merge_nodes((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
                ;}
     break;
 
   case 9:
 
+/* Line 1455 of yacc.c  */
+#line 149 "dtc-parser.y"
     {
-                       (yyval.node) = merge_nodes((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+                       struct node *target = get_node_by_ref((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].labelref));
+
+                       if (target)
+                               merge_nodes(target, (yyvsp[(3) - (3)].node));
+                       else
+                               print_error("label or path, '%s', not found", (yyvsp[(2) - (3)].labelref));
+                       (yyval.node) = (yyvsp[(1) - (3)].node);
                ;}
     break;
 
   case 10:
 
+/* Line 1455 of yacc.c  */
+#line 159 "dtc-parser.y"
     {
-                       struct node *target = get_node_by_ref((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].labelref));
+                       struct node *target = get_node_by_ref((yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].labelref));
 
-                       if (target)
-                               merge_nodes(target, (yyvsp[(3) - (3)].node));
+                       if (!target)
+                               print_error("label or path, '%s', not found", (yyvsp[(3) - (4)].labelref));
                        else
-                               print_error("label or path, '%s', not found", (yyvsp[(2) - (3)].labelref));
-                       (yyval.node) = (yyvsp[(1) - (3)].node);
+                               delete_node(target);
+
+                       (yyval.node) = (yyvsp[(1) - (4)].node);
                ;}
     break;
 
   case 11:
 
+/* Line 1455 of yacc.c  */
+#line 173 "dtc-parser.y"
     {
                        (yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist));
                ;}
@@ -1481,6 +1608,8 @@ yyreduce:
 
   case 12:
 
+/* Line 1455 of yacc.c  */
+#line 180 "dtc-parser.y"
     {
                        (yyval.proplist) = NULL;
                ;}
@@ -1488,6 +1617,8 @@ yyreduce:
 
   case 13:
 
+/* Line 1455 of yacc.c  */
+#line 184 "dtc-parser.y"
     {
                        (yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist));
                ;}
@@ -1495,6 +1626,8 @@ yyreduce:
 
   case 14:
 
+/* Line 1455 of yacc.c  */
+#line 191 "dtc-parser.y"
     {
                        (yyval.prop) = build_property((yyvsp[(1) - (4)].propnodename), (yyvsp[(3) - (4)].data));
                ;}
@@ -1502,6 +1635,8 @@ yyreduce:
 
   case 15:
 
+/* Line 1455 of yacc.c  */
+#line 195 "dtc-parser.y"
     {
                        (yyval.prop) = build_property((yyvsp[(1) - (2)].propnodename), empty_data);
                ;}
@@ -1509,62 +1644,85 @@ yyreduce:
 
   case 16:
 
+/* Line 1455 of yacc.c  */
+#line 199 "dtc-parser.y"
     {
-                       add_label(&(yyvsp[(2) - (2)].prop)->labels, (yyvsp[(1) - (2)].labelref));
-                       (yyval.prop) = (yyvsp[(2) - (2)].prop);
+                       (yyval.prop) = build_property_delete((yyvsp[(2) - (3)].propnodename));
                ;}
     break;
 
   case 17:
 
+/* Line 1455 of yacc.c  */
+#line 203 "dtc-parser.y"
     {
-                       (yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
+                       add_label(&(yyvsp[(2) - (2)].prop)->labels, (yyvsp[(1) - (2)].labelref));
+                       (yyval.prop) = (yyvsp[(2) - (2)].prop);
                ;}
     break;
 
   case 18:
 
+/* Line 1455 of yacc.c  */
+#line 211 "dtc-parser.y"
     {
-                       (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
+                       (yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
                ;}
     break;
 
   case 19:
 
+/* Line 1455 of yacc.c  */
+#line 215 "dtc-parser.y"
     {
-                       (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
+                       (yyval.data) = data_merge((yyvsp[(1) - (3)].data), (yyvsp[(2) - (3)].array).data);
                ;}
     break;
 
   case 20:
 
+/* Line 1455 of yacc.c  */
+#line 219 "dtc-parser.y"
     {
-                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
+                       (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
                ;}
     break;
 
   case 21:
 
+/* Line 1455 of yacc.c  */
+#line 223 "dtc-parser.y"
+    {
+                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
+               ;}
+    break;
+
+  case 22:
+
+/* Line 1455 of yacc.c  */
+#line 227 "dtc-parser.y"
     {
                        FILE *f = srcfile_relative_open((yyvsp[(4) - (9)].data).val, NULL);
                        struct data d;
 
-                       if ((yyvsp[(6) - (9)].addr) != 0)
-                               if (fseek(f, (yyvsp[(6) - (9)].addr), SEEK_SET) != 0)
+                       if ((yyvsp[(6) - (9)].integer) != 0)
+                               if (fseek(f, (yyvsp[(6) - (9)].integer), SEEK_SET) != 0)
                                        print_error("Couldn't seek to offset %llu in \"%s\": %s",
-                                                    (unsigned long long)(yyvsp[(6) - (9)].addr),
+                                                    (unsigned long long)(yyvsp[(6) - (9)].integer),
                                                     (yyvsp[(4) - (9)].data).val,
                                                     strerror(errno));
 
-                       d = data_copy_file(f, (yyvsp[(8) - (9)].addr));
+                       d = data_copy_file(f, (yyvsp[(8) - (9)].integer));
 
                        (yyval.data) = data_merge((yyvsp[(1) - (9)].data), d);
                        fclose(f);
                ;}
     break;
 
-  case 22:
+  case 23:
 
+/* Line 1455 of yacc.c  */
+#line 244 "dtc-parser.y"
     {
                        FILE *f = srcfile_relative_open((yyvsp[(4) - (5)].data).val, NULL);
                        struct data d = empty_data;
@@ -1576,122 +1734,383 @@ yyreduce:
                ;}
     break;
 
-  case 23:
-
-    {
-                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
-               ;}
-    break;
-
   case 24:
 
+/* Line 1455 of yacc.c  */
+#line 254 "dtc-parser.y"
     {
-                       (yyval.data) = empty_data;
+                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
                ;}
     break;
 
   case 25:
 
+/* Line 1455 of yacc.c  */
+#line 261 "dtc-parser.y"
     {
-                       (yyval.data) = (yyvsp[(1) - (2)].data);
+                       (yyval.data) = empty_data;
                ;}
     break;
 
   case 26:
 
+/* Line 1455 of yacc.c  */
+#line 265 "dtc-parser.y"
     {
-                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+                       (yyval.data) = (yyvsp[(1) - (2)].data);
                ;}
     break;
 
   case 27:
 
+/* Line 1455 of yacc.c  */
+#line 269 "dtc-parser.y"
     {
-                       (yyval.data) = empty_data;
+                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
                ;}
     break;
 
   case 28:
 
+/* Line 1455 of yacc.c  */
+#line 276 "dtc-parser.y"
     {
-                       (yyval.data) = data_append_cell((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].cell));
+                       (yyval.array).data = empty_data;
+                       (yyval.array).bits = eval_literal((yyvsp[(2) - (3)].literal), 0, 7);
+
+                       if (((yyval.array).bits !=  8) &&
+                           ((yyval.array).bits != 16) &&
+                           ((yyval.array).bits != 32) &&
+                           ((yyval.array).bits != 64))
+                       {
+                               print_error("Only 8, 16, 32 and 64-bit elements"
+                                           " are currently supported");
+                               (yyval.array).bits = 32;
+                       }
                ;}
     break;
 
   case 29:
 
+/* Line 1455 of yacc.c  */
+#line 291 "dtc-parser.y"
     {
-                       (yyval.data) = data_append_cell(data_add_marker((yyvsp[(1) - (2)].data), REF_PHANDLE,
-                                                             (yyvsp[(2) - (2)].labelref)), -1);
+                       (yyval.array).data = empty_data;
+                       (yyval.array).bits = 32;
                ;}
     break;
 
   case 30:
 
+/* Line 1455 of yacc.c  */
+#line 296 "dtc-parser.y"
     {
-                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+                       if ((yyvsp[(1) - (2)].array).bits < 64) {
+                               uint64_t mask = (1ULL << (yyvsp[(1) - (2)].array).bits) - 1;
+                               /*
+                                * Bits above mask must either be all zero
+                                * (positive within range of mask) or all one
+                                * (negative and sign-extended). The second
+                                * condition is true if when we set all bits
+                                * within the mask to one (i.e. | in the
+                                * mask), all bits are one.
+                                */
+                               if (((yyvsp[(2) - (2)].integer) > mask) && (((yyvsp[(2) - (2)].integer) | mask) != -1ULL))
+                                       print_error(
+                                               "integer value out of range "
+                                               "%016lx (%d bits)", (yyvsp[(1) - (2)].array).bits);
+                       }
+
+                       (yyval.array).data = data_append_integer((yyvsp[(1) - (2)].array).data, (yyvsp[(2) - (2)].integer), (yyvsp[(1) - (2)].array).bits);
                ;}
     break;
 
   case 31:
 
+/* Line 1455 of yacc.c  */
+#line 316 "dtc-parser.y"
     {
-                       (yyval.cell) = eval_literal((yyvsp[(1) - (1)].literal), 0, 32);
+                       uint64_t val = ~0ULL >> (64 - (yyvsp[(1) - (2)].array).bits);
+
+                       if ((yyvsp[(1) - (2)].array).bits == 32)
+                               (yyvsp[(1) - (2)].array).data = data_add_marker((yyvsp[(1) - (2)].array).data,
+                                                         REF_PHANDLE,
+                                                         (yyvsp[(2) - (2)].labelref));
+                       else
+                               print_error("References are only allowed in "
+                                           "arrays with 32-bit elements.");
+
+                       (yyval.array).data = data_append_integer((yyvsp[(1) - (2)].array).data, val, (yyvsp[(1) - (2)].array).bits);
                ;}
     break;
 
   case 32:
 
+/* Line 1455 of yacc.c  */
+#line 330 "dtc-parser.y"
     {
-                       (yyval.data) = empty_data;
+                       (yyval.array).data = data_add_marker((yyvsp[(1) - (2)].array).data, LABEL, (yyvsp[(2) - (2)].labelref));
                ;}
     break;
 
   case 33:
 
+/* Line 1455 of yacc.c  */
+#line 337 "dtc-parser.y"
     {
-                       (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
+                       (yyval.integer) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
                ;}
     break;
 
   case 34:
 
+/* Line 1455 of yacc.c  */
+#line 341 "dtc-parser.y"
     {
-                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+                       (yyval.integer) = eval_char_literal((yyvsp[(1) - (1)].literal));
                ;}
     break;
 
   case 35:
 
+/* Line 1455 of yacc.c  */
+#line 345 "dtc-parser.y"
+    {
+                       (yyval.integer) = (yyvsp[(2) - (3)].integer);
+               ;}
+    break;
+
+  case 38:
+
+/* Line 1455 of yacc.c  */
+#line 356 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (5)].integer) ? (yyvsp[(3) - (5)].integer) : (yyvsp[(5) - (5)].integer); ;}
+    break;
+
+  case 40:
+
+/* Line 1455 of yacc.c  */
+#line 361 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) || (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 42:
+
+/* Line 1455 of yacc.c  */
+#line 366 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) && (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 44:
+
+/* Line 1455 of yacc.c  */
+#line 371 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) | (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 46:
+
+/* Line 1455 of yacc.c  */
+#line 376 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) ^ (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 48:
+
+/* Line 1455 of yacc.c  */
+#line 381 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) & (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 50:
+
+/* Line 1455 of yacc.c  */
+#line 386 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) == (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 51:
+
+/* Line 1455 of yacc.c  */
+#line 387 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) != (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 53:
+
+/* Line 1455 of yacc.c  */
+#line 392 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) < (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 54:
+
+/* Line 1455 of yacc.c  */
+#line 393 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) > (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 55:
+
+/* Line 1455 of yacc.c  */
+#line 394 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) <= (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 56:
+
+/* Line 1455 of yacc.c  */
+#line 395 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) >= (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 57:
+
+/* Line 1455 of yacc.c  */
+#line 399 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) << (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 58:
+
+/* Line 1455 of yacc.c  */
+#line 400 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) >> (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 60:
+
+/* Line 1455 of yacc.c  */
+#line 405 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) + (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 61:
+
+/* Line 1455 of yacc.c  */
+#line 406 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) - (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 63:
+
+/* Line 1455 of yacc.c  */
+#line 411 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) * (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 64:
+
+/* Line 1455 of yacc.c  */
+#line 412 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) / (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 65:
+
+/* Line 1455 of yacc.c  */
+#line 413 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) % (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 68:
+
+/* Line 1455 of yacc.c  */
+#line 419 "dtc-parser.y"
+    { (yyval.integer) = -(yyvsp[(2) - (2)].integer); ;}
+    break;
+
+  case 69:
+
+/* Line 1455 of yacc.c  */
+#line 420 "dtc-parser.y"
+    { (yyval.integer) = ~(yyvsp[(2) - (2)].integer); ;}
+    break;
+
+  case 70:
+
+/* Line 1455 of yacc.c  */
+#line 421 "dtc-parser.y"
+    { (yyval.integer) = !(yyvsp[(2) - (2)].integer); ;}
+    break;
+
+  case 71:
+
+/* Line 1455 of yacc.c  */
+#line 426 "dtc-parser.y"
+    {
+                       (yyval.data) = empty_data;
+               ;}
+    break;
+
+  case 72:
+
+/* Line 1455 of yacc.c  */
+#line 430 "dtc-parser.y"
+    {
+                       (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
+               ;}
+    break;
+
+  case 73:
+
+/* Line 1455 of yacc.c  */
+#line 434 "dtc-parser.y"
+    {
+                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+               ;}
+    break;
+
+  case 74:
+
+/* Line 1455 of yacc.c  */
+#line 441 "dtc-parser.y"
     {
                        (yyval.nodelist) = NULL;
                ;}
     break;
 
-  case 36:
+  case 75:
 
+/* Line 1455 of yacc.c  */
+#line 445 "dtc-parser.y"
     {
                        (yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist));
                ;}
     break;
 
-  case 37:
+  case 76:
 
+/* Line 1455 of yacc.c  */
+#line 449 "dtc-parser.y"
     {
                        print_error("syntax error: properties must precede subnodes");
                        YYERROR;
                ;}
     break;
 
-  case 38:
+  case 77:
 
+/* Line 1455 of yacc.c  */
+#line 457 "dtc-parser.y"
     {
                        (yyval.node) = name_node((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].propnodename));
                ;}
     break;
 
-  case 39:
+  case 78:
+
+/* Line 1455 of yacc.c  */
+#line 461 "dtc-parser.y"
+    {
+                       (yyval.node) = name_node(build_node_delete(), (yyvsp[(2) - (3)].propnodename));
+               ;}
+    break;
+
+  case 79:
 
+/* Line 1455 of yacc.c  */
+#line 465 "dtc-parser.y"
     {
                        add_label(&(yyvsp[(2) - (2)].node)->labels, (yyvsp[(1) - (2)].labelref));
                        (yyval.node) = (yyvsp[(2) - (2)].node);
@@ -1700,6 +2119,8 @@ yyreduce:
 
 
 
+/* Line 1455 of yacc.c  */
+#line 2124 "dtc-parser.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -1910,6 +2331,8 @@ yyreturn:
 
 
 
+/* Line 1675 of yacc.c  */
+#line 471 "dtc-parser.y"
 
 
 void print_error(char const *fmt, ...)
@@ -1934,9 +2357,12 @@ static unsigned long long eval_literal(const char *s, int base, int bits)
 
        errno = 0;
        val = strtoull(s, &e, base);
-       if (*e)
-               print_error("bad characters in literal");
-       else if ((errno == ERANGE)
+       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)
@@ -1944,3 +2370,29 @@ static unsigned long long eval_literal(const char *s, int base, int bits)
        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;
+}
+
index 4ee682b..9d2dce4 100644 (file)
@@ -1,9 +1,10 @@
-/* A Bison parser, made by GNU Bison 2.4.3.  */
+
+/* A Bison parser, made by GNU Bison 2.4.1.  */
 
 /* Skeleton interface for Bison's Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-   2009, 2010 Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    enum yytokentype {
      DT_V1 = 258,
      DT_MEMRESERVE = 259,
-     DT_PROPNODENAME = 260,
-     DT_LITERAL = 261,
-     DT_BASE = 262,
-     DT_BYTE = 263,
-     DT_STRING = 264,
-     DT_LABEL = 265,
-     DT_REF = 266,
-     DT_INCBIN = 267
+     DT_LSHIFT = 260,
+     DT_RSHIFT = 261,
+     DT_LE = 262,
+     DT_GE = 263,
+     DT_EQ = 264,
+     DT_NE = 265,
+     DT_AND = 266,
+     DT_OR = 267,
+     DT_BITS = 268,
+     DT_DEL_PROP = 269,
+     DT_DEL_NODE = 270,
+     DT_PROPNODENAME = 271,
+     DT_LITERAL = 272,
+     DT_CHAR_LITERAL = 273,
+     DT_BASE = 274,
+     DT_BYTE = 275,
+     DT_STRING = 276,
+     DT_LABEL = 277,
+     DT_REF = 278,
+     DT_INCBIN = 279
    };
 #endif
 
@@ -57,6 +70,8 @@
 typedef union YYSTYPE
 {
 
+/* Line 1676 of yacc.c  */
+#line 40 "dtc-parser.y"
 
        char *propnodename;
        char *literal;
@@ -65,16 +80,22 @@ typedef union YYSTYPE
        uint8_t byte;
        struct data data;
 
-       uint64_t addr;
-       cell_t cell;
+       struct {
+               struct data     data;
+               int             bits;
+       } array;
+
        struct property *prop;
        struct property *proplist;
        struct node *node;
        struct node *nodelist;
        struct reserve_info *re;
+       uint64_t integer;
 
 
 
+/* Line 1676 of yacc.c  */
+#line 99 "dtc-parser.tab.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
index 5e84a67..f412460 100644 (file)
@@ -34,6 +34,7 @@ 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);
 %}
 
 %union {
@@ -44,19 +45,28 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
        uint8_t byte;
        struct data data;
 
-       uint64_t addr;
-       cell_t cell;
+       struct {
+               struct data     data;
+               int             bits;
+       } array;
+
        struct property *prop;
        struct property *proplist;
        struct node *node;
        struct node *nodelist;
        struct reserve_info *re;
+       uint64_t integer;
 }
 
 %token DT_V1
 %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 <cbase> DT_BASE
 %token <byte> DT_BYTE
 %token <data> DT_STRING
@@ -68,9 +78,7 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
 %type <data> propdataprefix
 %type <re> memreserve
 %type <re> memreserves
-%type <addr> addr
-%type <data> celllist
-%type <cell> cellval
+%type <array> arrayprefix
 %type <data> bytestring
 %type <prop> propdef
 %type <proplist> proplist
@@ -80,6 +88,21 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
 %type <node> subnode
 %type <nodelist> subnodes
 
+%type <integer> integer_prim
+%type <integer> integer_unary
+%type <integer> integer_mul
+%type <integer> integer_add
+%type <integer> integer_shift
+%type <integer> integer_rela
+%type <integer> integer_eq
+%type <integer> integer_bitand
+%type <integer> integer_bitxor
+%type <integer> integer_bitor
+%type <integer> integer_and
+%type <integer> integer_or
+%type <integer> integer_trinary
+%type <integer> integer_expr
+
 %%
 
 sourcefile:
@@ -102,7 +125,7 @@ memreserves:
        ;
 
 memreserve:
-         DT_MEMRESERVE addr addr ';'
+         DT_MEMRESERVE integer_prim integer_prim ';'
                {
                        $$ = build_reserve_entry($2, $3);
                }
@@ -113,13 +136,6 @@ memreserve:
                }
        ;
 
-addr:
-         DT_LITERAL
-               {
-                       $$ = eval_literal($1, 0, 64);
-               }
-         ;
-
 devicetree:
          '/' nodedef
                {
@@ -139,6 +155,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:
@@ -168,6 +195,10 @@ propdef:
                {
                        $$ = build_property($1, empty_data);
                }
+       | DT_DEL_PROP DT_PROPNODENAME ';'
+               {
+                       $$ = build_property_delete($2);
+               }
        | DT_LABEL propdef
                {
                        add_label(&$2->labels, $1);
@@ -180,9 +211,9 @@ propdata:
                {
                        $$ = data_merge($1, $2);
                }
-       | propdataprefix '<' celllist '>'
+       | propdataprefix arrayprefix '>'
                {
-                       $$ = data_merge($1, $3);
+                       $$ = data_merge($1, $2.data);
                }
        | propdataprefix '[' bytestring ']'
                {
@@ -192,7 +223,7 @@ propdata:
                {
                        $$ = data_add_marker($1, REF_PATH, $2);
                }
-       | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
+       | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
                {
                        FILE *f = srcfile_relative_open($4.val, NULL);
                        struct data d;
@@ -240,31 +271,154 @@ propdataprefix:
                }
        ;
 
-celllist:
-         /* empty */
+arrayprefix:
+       DT_BITS DT_LITERAL '<'
+               {
+                       $$.data = empty_data;
+                       $$.bits = eval_literal($2, 0, 7);
+
+                       if (($$.bits !=  8) &&
+                           ($$.bits != 16) &&
+                           ($$.bits != 32) &&
+                           ($$.bits != 64))
+                       {
+                               print_error("Only 8, 16, 32 and 64-bit elements"
+                                           " are currently supported");
+                               $$.bits = 32;
+                       }
+               }
+       | '<'
+               {
+                       $$.data = empty_data;
+                       $$.bits = 32;
+               }
+       | arrayprefix integer_prim
+               {
+                       if ($1.bits < 64) {
+                               uint64_t mask = (1ULL << $1.bits) - 1;
+                               /*
+                                * Bits above mask must either be all zero
+                                * (positive within range of mask) or all one
+                                * (negative and sign-extended). The second
+                                * condition is true if when we set all bits
+                                * within the mask to one (i.e. | in the
+                                * mask), all bits are one.
+                                */
+                               if (($2 > mask) && (($2 | mask) != -1ULL))
+                                       print_error(
+                                               "integer value out of range "
+                                               "%016lx (%d bits)", $1.bits);
+                       }
+
+                       $$.data = data_append_integer($1.data, $2, $1.bits);
+               }
+       | arrayprefix DT_REF
+               {
+                       uint64_t val = ~0ULL >> (64 - $1.bits);
+
+                       if ($1.bits == 32)
+                               $1.data = data_add_marker($1.data,
+                                                         REF_PHANDLE,
+                                                         $2);
+                       else
+                               print_error("References are only allowed in "
+                                           "arrays with 32-bit elements.");
+
+                       $$.data = data_append_integer($1.data, val, $1.bits);
+               }
+       | arrayprefix DT_LABEL
                {
-                       $$ = empty_data;
+                       $$.data = data_add_marker($1.data, LABEL, $2);
                }
-       | celllist cellval
+       ;
+
+integer_prim:
+         DT_LITERAL
                {
-                       $$ = data_append_cell($1, $2);
+                       $$ = eval_literal($1, 0, 64);
                }
-       | celllist DT_REF
+       | DT_CHAR_LITERAL
                {
-                       $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
-                                                             $2), -1);
+                       $$ = eval_char_literal($1);
                }
-       | celllist DT_LABEL
+       | '(' integer_expr ')'
                {
-                       $$ = data_add_marker($1, LABEL, $2);
+                       $$ = $2;
                }
        ;
 
-cellval:
-         DT_LITERAL
-               {
-                       $$ = eval_literal($1, 0, 32);
-               }
+integer_expr:
+       integer_trinary
+       ;
+
+integer_trinary:
+         integer_or
+       | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
+       ;
+
+integer_or:
+         integer_and
+       | integer_or DT_OR integer_and { $$ = $1 || $3; }
+       ;
+
+integer_and:
+         integer_bitor
+       | integer_and DT_AND integer_bitor { $$ = $1 && $3; }
+       ;
+
+integer_bitor:
+         integer_bitxor
+       | integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
+       ;
+
+integer_bitxor:
+         integer_bitand
+       | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
+       ;
+
+integer_bitand:
+         integer_eq
+       | integer_bitand '&' integer_eq { $$ = $1 & $3; }
+       ;
+
+integer_eq:
+         integer_rela
+       | integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
+       | integer_eq DT_NE integer_rela { $$ = $1 != $3; }
+       ;
+
+integer_rela:
+         integer_shift
+       | integer_rela '<' integer_shift { $$ = $1 < $3; }
+       | integer_rela '>' integer_shift { $$ = $1 > $3; }
+       | integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
+       | integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
+       ;
+
+integer_shift:
+         integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
+       | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
+       | integer_add
+       ;
+
+integer_add:
+         integer_add '+' integer_mul { $$ = $1 + $3; }
+       | integer_add '-' integer_mul { $$ = $1 - $3; }
+       | integer_mul
+       ;
+
+integer_mul:
+         integer_mul '*' integer_unary { $$ = $1 * $3; }
+       | integer_mul '/' integer_unary { $$ = $1 / $3; }
+       | integer_mul '%' integer_unary { $$ = $1 % $3; }
+       | integer_unary
+       ;
+
+integer_unary:
+         integer_prim
+       | '-' integer_unary { $$ = -$2; }
+       | '~' integer_unary { $$ = ~$2; }
+       | '!' integer_unary { $$ = !$2; }
        ;
 
 bytestring:
@@ -303,6 +457,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);
@@ -334,12 +492,41 @@ static unsigned long long eval_literal(const char *s, int base, int bits)
 
        errno = 0;
        val = strtoull(s, &e, base);
-       if (*e)
-               print_error("bad characters in literal");
-       else if ((errno == ERANGE)
+       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;
+}
index 2ef5e2e..a375683 100644 (file)
@@ -82,6 +82,8 @@ static void  __attribute__ ((noreturn)) usage(void)
        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");
@@ -91,6 +93,9 @@ static void  __attribute__ ((noreturn)) usage(void)
        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);
 }
 
@@ -113,7 +118,7 @@ int main(int argc, char *argv[])
        minsize    = 0;
        padsize    = 0;
 
-       while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fcqb:vH:s"))
+       while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:"))
                        != EOF) {
                switch (opt) {
                case 'I':
@@ -149,6 +154,9 @@ int main(int argc, char *argv[])
                case 'b':
                        cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
                        break;
+               case 'i':
+                       srcfile_add_search_path(optarg);
+                       break;
                case 'v':
                        printf("Version: %s\n", DTC_VERSION);
                        exit(0);
@@ -168,6 +176,14 @@ int main(int argc, char *argv[])
                        sort = 1;
                        break;
 
+               case 'W':
+                       parse_checks_option(true, false, optarg);
+                       break;
+
+               case 'E':
+                       parse_checks_option(false, true, optarg);
+                       break;
+
                case 'h':
                default:
                        usage();
@@ -188,9 +204,6 @@ int main(int argc, char *argv[])
        if (minsize)
                fprintf(stderr, "DTC: Use of \"-S\" is deprecated; it will be removed soon, use \"-p\" instead\n");
 
-       fprintf(stderr, "DTC: %s->%s  on file \"%s\"\n",
-               inform, outform, arg);
-
        if (depname) {
                depfile = fopen(depname, "w");
                if (!depfile)
index f37c97e..d501c86 100644 (file)
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include <stdarg.h>
 #include <assert.h>
 #include <ctype.h>
@@ -109,6 +110,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m,
                                  const void *p, int len);
 struct data data_merge(struct data d1, struct data d2);
 struct data data_append_cell(struct data d, cell_t word);
+struct data data_append_integer(struct data d, uint64_t word, int bits);
 struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
 struct data data_append_addr(struct data d, uint64_t addr);
 struct data data_append_byte(struct data d, uint8_t byte);
@@ -126,11 +128,13 @@ int data_is_one_string(struct data d);
 
 /* Live trees */
 struct label {
+       int deleted;
        char *label;
        struct label *next;
 };
 
 struct property {
+       int deleted;
        char *name;
        struct data val;
 
@@ -140,6 +144,7 @@ struct property {
 };
 
 struct node {
+       int deleted;
        char *name;
        struct property *proplist;
        struct node *children;
@@ -156,28 +161,71 @@ struct node {
        struct label *labels;
 };
 
+static inline struct label *for_each_label_next(struct label *l)
+{
+       do {
+               l = l->next;
+       } while (l && l->deleted);
+
+       return l;
+}
+
 #define for_each_label(l0, l) \
+       for ((l) = (l0); (l); (l) = for_each_label_next(l))
+
+#define for_each_label_withdel(l0, l) \
        for ((l) = (l0); (l); (l) = (l)->next)
 
+static inline struct property *for_each_property_next(struct property *p)
+{
+       do {
+               p = p->next;
+       } while (p && p->deleted);
+
+       return p;
+}
+
 #define for_each_property(n, p) \
+       for ((p) = (n)->proplist; (p); (p) = for_each_property_next(p))
+
+#define for_each_property_withdel(n, p) \
        for ((p) = (n)->proplist; (p); (p) = (p)->next)
 
-#define for_each_child(n, c)   \
+static inline struct node *for_each_child_next(struct node *c)
+{
+       do {
+               c = c->next_sibling;
+       } while (c && c->deleted);
+
+       return c;
+}
+
+#define for_each_child(n, c) \
+       for ((c) = (n)->children; (c); (c) = for_each_child_next(c))
+
+#define for_each_child_withdel(n, c) \
        for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
 
 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);
@@ -224,6 +272,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);
 
 /* Flattened trees */
diff --git a/scripts/dtc/fdtdump.c b/scripts/dtc/fdtdump.c
new file mode 100644 (file)
index 0000000..207a46d
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <fdt.h>
+#include <libfdt_env.h>
+
+#include "util.h"
+
+#define ALIGN(x, a)    (((x) + ((a) - 1)) & ~((a) - 1))
+#define PALIGN(p, a)   ((void *)(ALIGN((unsigned long)(p), (a))))
+#define GET_CELL(p)    (p += 4, *((const uint32_t *)(p-4)))
+
+static void print_data(const char *data, int len)
+{
+       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 void dump_blob(void *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);
+       uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings);
+       struct fdt_reserve_entry *p_rsvmap =
+               (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap);
+       const char *p_struct = (const char *)blob + off_dt;
+       const char *p_strings = (const char *)blob + off_str;
+       uint32_t version = fdt32_to_cpu(bph->version);
+       uint32_t totalsize = fdt32_to_cpu(bph->totalsize);
+       uint32_t tag;
+       const char *p, *s, *t;
+       int depth, sz, shift;
+       int i;
+       uint64_t addr, size;
+
+       depth = 0;
+       shift = 4;
+
+       printf("/dts-v1/;\n");
+       printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
+       printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
+       printf("// off_dt_struct:\t0x%x\n", off_dt);
+       printf("// off_dt_strings:\t0x%x\n", off_str);
+       printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
+       printf("// version:\t\t%d\n", version);
+       printf("// last_comp_version:\t%d\n",
+              fdt32_to_cpu(bph->last_comp_version));
+       if (version >= 2)
+               printf("// boot_cpuid_phys:\t0x%x\n",
+                      fdt32_to_cpu(bph->boot_cpuid_phys));
+
+       if (version >= 3)
+               printf("// size_dt_strings:\t0x%x\n",
+                      fdt32_to_cpu(bph->size_dt_strings));
+       if (version >= 17)
+               printf("// size_dt_struct:\t0x%x\n",
+                      fdt32_to_cpu(bph->size_dt_struct));
+       printf("\n");
+
+       for (i = 0; ; i++) {
+               addr = fdt64_to_cpu(p_rsvmap[i].address);
+               size = fdt64_to_cpu(p_rsvmap[i].size);
+               if (addr == 0 && size == 0)
+                       break;
+
+               printf("/memreserve/ %llx %llx;\n",
+                      (unsigned long long)addr, (unsigned long long)size);
+       }
+
+       p = p_struct;
+       while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
+
+               /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
+
+               if (tag == FDT_BEGIN_NODE) {
+                       s = p;
+                       p = PALIGN(p + strlen(s) + 1, 4);
+
+                       if (*s == '\0')
+                               s = "/";
+
+                       printf("%*s%s {\n", depth * shift, "", s);
+
+                       depth++;
+                       continue;
+               }
+
+               if (tag == FDT_END_NODE) {
+                       depth--;
+
+                       printf("%*s};\n", depth * shift, "");
+                       continue;
+               }
+
+               if (tag == FDT_NOP) {
+                       printf("%*s// [NOP]\n", depth * shift, "");
+                       continue;
+               }
+
+               if (tag != FDT_PROP) {
+                       fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
+                       break;
+               }
+               sz = fdt32_to_cpu(GET_CELL(p));
+               s = p_strings + fdt32_to_cpu(GET_CELL(p));
+               if (version < 16 && sz >= 8)
+                       p = PALIGN(p, 8);
+               t = p;
+
+               p = PALIGN(p + sz, 4);
+
+               printf("%*s%s", depth * shift, "", s);
+               print_data(t, sz);
+               printf(";\n");
+       }
+}
+
+
+int main(int argc, char *argv[])
+{
+       char *buf;
+
+       if (argc < 2) {
+               fprintf(stderr, "supply input filename\n");
+               return 5;
+       }
+
+       buf = utilfdt_read(argv[1]);
+       if (buf)
+               dump_blob(buf);
+       else
+               return 10;
+
+       return 0;
+}
diff --git a/scripts/dtc/fdtget.c b/scripts/dtc/fdtget.c
new file mode 100644 (file)
index 0000000..c2fbab2
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * Portions from U-Boot cmd_fdt.c (C) Copyright 2007
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
+ * Based on code written by:
+ *   Pantelis Antoniou <pantelis.antoniou@gmail.com> and
+ *   Matthew McClintock <msm@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libfdt.h>
+
+#include "util.h"
+
+enum display_mode {
+       MODE_SHOW_VALUE,        /* show values for node properties */
+       MODE_LIST_PROPS,        /* list the properties for a node */
+       MODE_LIST_SUBNODES,     /* list the subnodes of a node */
+};
+
+/* Holds information which controls our output and options */
+struct display_info {
+       int type;               /* data type (s/i/u/x or 0 for default) */
+       int size;               /* data size (1/2/4) */
+       enum display_mode mode; /* display mode that we are using */
+       const char *default_val; /* default value if node/property not found */
+};
+
+static void report_error(const char *where, int err)
+{
+       fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
+}
+
+/**
+ * Displays data of a given length according to selected options
+ *
+ * If a specific data type is provided in disp, then this is used. Otherwise
+ * we try to guess the data type / size from the contents.
+ *
+ * @param disp         Display information / options
+ * @param data         Data to display
+ * @param len          Maximum length of buffer
+ * @return 0 if ok, -1 if data does not match format
+ */
+static int show_data(struct display_info *disp, const char *data, int len)
+{
+       int i, size;
+       const uint8_t *p = (const uint8_t *)data;
+       const char *s;
+       int value;
+       int is_string;
+       char fmt[3];
+
+       /* no data, don't print */
+       if (len == 0)
+               return 0;
+
+       is_string = (disp->type) == 's' ||
+               (!disp->type && util_is_printable_string(data, len));
+       if (is_string) {
+               if (data[len - 1] != '\0') {
+                       fprintf(stderr, "Unterminated string\n");
+                       return -1;
+               }
+               for (s = data; s - data < len; s += strlen(s) + 1) {
+                       if (s != data)
+                               printf(" ");
+                       printf("%s", (const char *)s);
+               }
+               return 0;
+       }
+       size = disp->size;
+       if (size == -1) {
+               size = (len % 4) == 0 ? 4 : 1;
+       } else if (len % size) {
+               fprintf(stderr, "Property length must be a multiple of "
+                               "selected data size\n");
+               return -1;
+       }
+       fmt[0] = '%';
+       fmt[1] = disp->type ? disp->type : 'd';
+       fmt[2] = '\0';
+       for (i = 0; i < len; i += size, p += size) {
+               if (i)
+                       printf(" ");
+               value = size == 4 ? fdt32_to_cpu(*(const uint32_t *)p) :
+                       size == 2 ? (*p << 8) | p[1] : *p;
+               printf(fmt, value);
+       }
+       return 0;
+}
+
+/**
+ * List all properties in a node, one per line.
+ *
+ * @param blob         FDT blob
+ * @param node         Node to display
+ * @return 0 if ok, or FDT_ERR... if not.
+ */
+static int list_properties(const void *blob, int node)
+{
+       const struct fdt_property *data;
+       const char *name;
+       int prop;
+
+       prop = fdt_first_property_offset(blob, node);
+       do {
+               /* Stop silently when there are no more properties */
+               if (prop < 0)
+                       return prop == -FDT_ERR_NOTFOUND ? 0 : prop;
+               data = fdt_get_property_by_offset(blob, prop, NULL);
+               name = fdt_string(blob, fdt32_to_cpu(data->nameoff));
+               if (name)
+                       puts(name);
+               prop = fdt_next_property_offset(blob, prop);
+       } while (1);
+}
+
+#define MAX_LEVEL      32              /* how deeply nested we will go */
+
+/**
+ * List all subnodes in a node, one per line
+ *
+ * @param blob         FDT blob
+ * @param node         Node to display
+ * @return 0 if ok, or FDT_ERR... if not.
+ */
+static int list_subnodes(const void *blob, int node)
+{
+       int nextoffset;         /* next node offset from libfdt */
+       uint32_t tag;           /* current tag */
+       int level = 0;          /* keep track of nesting level */
+       const char *pathp;
+       int depth = 1;          /* the assumed depth of this node */
+
+       while (level >= 0) {
+               tag = fdt_next_tag(blob, node, &nextoffset);
+               switch (tag) {
+               case FDT_BEGIN_NODE:
+                       pathp = fdt_get_name(blob, node, NULL);
+                       if (level <= depth) {
+                               if (pathp == NULL)
+                                       pathp = "/* NULL pointer error */";
+                               if (*pathp == '\0')
+                                       pathp = "/";    /* root is nameless */
+                               if (level == 1)
+                                       puts(pathp);
+                       }
+                       level++;
+                       if (level >= MAX_LEVEL) {
+                               printf("Nested too deep, aborting.\n");
+                               return 1;
+                       }
+                       break;
+               case FDT_END_NODE:
+                       level--;
+                       if (level == 0)
+                               level = -1;             /* exit the loop */
+                       break;
+               case FDT_END:
+                       return 1;
+               case FDT_PROP:
+                       break;
+               default:
+                       if (level <= depth)
+                               printf("Unknown tag 0x%08X\n", tag);
+                       return 1;
+               }
+               node = nextoffset;
+       }
+       return 0;
+}
+
+/**
+ * Show the data for a given node (and perhaps property) according to the
+ * display option provided.
+ *
+ * @param blob         FDT blob
+ * @param disp         Display information / options
+ * @param node         Node to display
+ * @param property     Name of property to display, or NULL if none
+ * @return 0 if ok, -ve on error
+ */
+static int show_data_for_item(const void *blob, struct display_info *disp,
+               int node, const char *property)
+{
+       const void *value = NULL;
+       int len, err = 0;
+
+       switch (disp->mode) {
+       case MODE_LIST_PROPS:
+               err = list_properties(blob, node);
+               break;
+
+       case MODE_LIST_SUBNODES:
+               err = list_subnodes(blob, node);
+               break;
+
+       default:
+               assert(property);
+               value = fdt_getprop(blob, node, property, &len);
+               if (value) {
+                       if (show_data(disp, value, len))
+                               err = -1;
+                       else
+                               printf("\n");
+               } else if (disp->default_val) {
+                       puts(disp->default_val);
+               } else {
+                       report_error(property, len);
+                       err = -1;
+               }
+               break;
+       }
+
+       return err;
+}
+
+/**
+ * Run the main fdtget operation, given a filename and valid arguments
+ *
+ * @param disp         Display information / options
+ * @param filename     Filename of blob file
+ * @param arg          List of arguments to process
+ * @param arg_count    Number of arguments
+ * @param return 0 if ok, -ve on error
+ */
+static int do_fdtget(struct display_info *disp, const char *filename,
+                    char **arg, int arg_count, int args_per_step)
+{
+       char *blob;
+       const char *prop;
+       int i, node;
+
+       blob = utilfdt_read(filename);
+       if (!blob)
+               return -1;
+
+       for (i = 0; i + args_per_step <= arg_count; i += args_per_step) {
+               node = fdt_path_offset(blob, arg[i]);
+               if (node < 0) {
+                       if (disp->default_val) {
+                               puts(disp->default_val);
+                               continue;
+                       } else {
+                               report_error(arg[i], node);
+                               return -1;
+                       }
+               }
+               prop = args_per_step == 1 ? NULL : arg[i + 1];
+
+               if (show_data_for_item(blob, disp, node, prop))
+                       return -1;
+       }
+       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"
+       "       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"
+       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);
+}
+
+int main(int argc, char *argv[])
+{
+       char *filename = NULL;
+       struct display_info disp;
+       int args_per_step = 2;
+
+       /* set defaults */
+       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);
+
+               case 't':
+                       if (utilfdt_decode_type(optarg, &disp.type,
+                                       &disp.size))
+                               usage("Invalid type string");
+                       break;
+
+               case 'p':
+                       disp.mode = MODE_LIST_PROPS;
+                       args_per_step = 1;
+                       break;
+
+               case 'l':
+                       disp.mode = MODE_LIST_SUBNODES;
+                       args_per_step = 1;
+                       break;
+
+               case 'd':
+                       disp.default_val = optarg;
+                       break;
+               }
+       }
+
+       if (optind < argc)
+               filename = argv[optind++];
+       if (!filename)
+               usage("Missing filename");
+
+       argv += optind;
+       argc -= optind;
+
+       /* Allow no arguments, and silently succeed */
+       if (!argc)
+               return 0;
+
+       /* Check for node, property arguments */
+       if (args_per_step == 2 && (argc % 2))
+               usage("Must have an even number of arguments");
+
+       if (do_fdtget(&disp, filename, argv, argc, args_per_step))
+               return 1;
+       return 0;
+}
diff --git a/scripts/dtc/fdtput.c b/scripts/dtc/fdtput.c
new file mode 100644 (file)
index 0000000..f2197f5
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libfdt.h>
+
+#include "util.h"
+
+/* These are the operations we support */
+enum oper_type {
+       OPER_WRITE_PROP,                /* Write a property in a node */
+       OPER_CREATE_NODE,               /* Create a new node */
+};
+
+struct display_info {
+       enum oper_type oper;    /* operation to perform */
+       int type;               /* data type (s/i/u/x or 0 for default) */
+       int size;               /* data size (1/2/4) */
+       int verbose;            /* verbose output */
+       int auto_path;          /* automatically create all path components */
+};
+
+
+/**
+ * Report an error with a particular node.
+ *
+ * @param name         Node name to report error on
+ * @param namelen      Length of node name, or -1 to use entire string
+ * @param err          Error number to report (-FDT_ERR_...)
+ */
+static void report_error(const char *name, int namelen, int err)
+{
+       if (namelen == -1)
+               namelen = strlen(name);
+       fprintf(stderr, "Error at '%1.*s': %s\n", namelen, name,
+               fdt_strerror(err));
+}
+
+/**
+ * Encode a series of arguments in a property value.
+ *
+ * @param disp         Display information / options
+ * @param arg          List of arguments from command line
+ * @param arg_count    Number of arguments (may be 0)
+ * @param valuep       Returns buffer containing value
+ * @param *value_len   Returns length of value encoded
+ */
+static int encode_value(struct display_info *disp, char **arg, int arg_count,
+                       char **valuep, int *value_len)
+{
+       char *value = NULL;     /* holding area for value */
+       int value_size = 0;     /* size of holding area */
+       char *ptr;              /* pointer to current value position */
+       int len;                /* length of this cell/string/byte */
+       int ival;
+       int upto;       /* the number of bytes we have written to buf */
+       char fmt[3];
+
+       upto = 0;
+
+       if (disp->verbose)
+               fprintf(stderr, "Decoding value:\n");
+
+       fmt[0] = '%';
+       fmt[1] = disp->type ? disp->type : 'd';
+       fmt[2] = '\0';
+       for (; arg_count > 0; arg++, arg_count--, upto += len) {
+               /* assume integer unless told otherwise */
+               if (disp->type == 's')
+                       len = strlen(*arg) + 1;
+               else
+                       len = disp->size == -1 ? 4 : disp->size;
+
+               /* enlarge our value buffer by a suitable margin if needed */
+               if (upto + len > value_size) {
+                       value_size = (upto + len) + 500;
+                       value = realloc(value, value_size);
+                       if (!value) {
+                               fprintf(stderr, "Out of mmory: cannot alloc "
+                                       "%d bytes\n", value_size);
+                               return -1;
+                       }
+               }
+
+               ptr = value + upto;
+               if (disp->type == 's') {
+                       memcpy(ptr, *arg, len);
+                       if (disp->verbose)
+                               fprintf(stderr, "\tstring: '%s'\n", ptr);
+               } else {
+                       int *iptr = (int *)ptr;
+                       sscanf(*arg, fmt, &ival);
+                       if (len == 4)
+                               *iptr = cpu_to_fdt32(ival);
+                       else
+                               *ptr = (uint8_t)ival;
+                       if (disp->verbose) {
+                               fprintf(stderr, "\t%s: %d\n",
+                                       disp->size == 1 ? "byte" :
+                                       disp->size == 2 ? "short" : "int",
+                                       ival);
+                       }
+               }
+       }
+       *value_len = upto;
+       *valuep = value;
+       if (disp->verbose)
+               fprintf(stderr, "Value size %d\n", upto);
+       return 0;
+}
+
+static int store_key_value(void *blob, const char *node_name,
+               const char *property, const char *buf, int len)
+{
+       int node;
+       int err;
+
+       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);
+       if (err) {
+               report_error(property, -1, err);
+               return -1;
+       }
+       return 0;
+}
+
+/**
+ * Create paths as needed for all components of a path
+ *
+ * Any components of the path that do not exist are created. Errors are
+ * reported.
+ *
+ * @param blob         FDT blob to write into
+ * @param in_path      Path to process
+ * @return 0 if ok, -1 on error
+ */
+static int create_paths(void *blob, const char *in_path)
+{
+       const char *path = in_path;
+       const char *sep;
+       int node, offset = 0;
+
+       /* skip leading '/' */
+       while (*path == '/')
+               path++;
+
+       for (sep = path; *sep; path = sep + 1, offset = node) {
+               /* equivalent to strchrnul(), but it requires _GNU_SOURCE */
+               sep = strchr(path, '/');
+               if (!sep)
+                       sep = path + strlen(path);
+
+               node = fdt_subnode_offset_namelen(blob, offset, path,
+                               sep - path);
+               if (node == -FDT_ERR_NOTFOUND) {
+                       node = fdt_add_subnode_namelen(blob, offset, path,
+                                                      sep - path);
+               }
+               if (node < 0) {
+                       report_error(path, sep - path, node);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * Create a new node in the fdt.
+ *
+ * This will overwrite the node_name string. Any error is reported.
+ *
+ * TODO: Perhaps create fdt_path_offset_namelen() so we don't need to do this.
+ *
+ * @param blob         FDT blob to write into
+ * @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)
+{
+       int node = 0;
+       char *p;
+
+       p = strrchr(node_name, '/');
+       if (!p) {
+               report_error(node_name, -1, -FDT_ERR_BADPATH);
+               return -1;
+       }
+       *p = '\0';
+
+       if (p > 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);
+       if (node < 0) {
+               report_error(p + 1, -1, node);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int do_fdtput(struct display_info *disp, const char *filename,
+                   char **arg, int arg_count)
+{
+       char *value;
+       char *blob;
+       int len, ret = 0;
+
+       blob = utilfdt_read(filename);
+       if (!blob)
+               return -1;
+
+       switch (disp->oper) {
+       case OPER_WRITE_PROP:
+               /*
+                * Convert the arguments into a single binary value, then
+                * store them into the property.
+                */
+               assert(arg_count >= 2);
+               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))
+                       ret = -1;
+               break;
+       case OPER_CREATE_NODE:
+               for (; ret >= 0 && arg_count--; arg++) {
+                       if (disp->auto_path)
+                               ret = create_paths(blob, *arg);
+                       else
+                               ret = create_node(blob, *arg);
+               }
+               break;
+       }
+       if (ret >= 0)
+               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"
+       "       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"
+       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);
+}
+
+int main(int argc, char *argv[])
+{
+       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;
+
+               /*
+                * TODO: add options to:
+                * - delete property
+                * - delete node (optionally recursively)
+                * - rename node
+                * - pack fdt before writing
+                * - set amount of free space when writing
+                * - expand fdt if value doesn't fit
+                */
+               switch (c) {
+               case 'c':
+                       disp.oper = OPER_CREATE_NODE;
+                       break;
+               case 'h':
+               case '?':
+                       usage(NULL);
+               case 'p':
+                       disp.auto_path = 1;
+                       break;
+               case 't':
+                       if (utilfdt_decode_type(optarg, &disp.type,
+                                       &disp.size))
+                               usage("Invalid type string");
+                       break;
+
+               case 'v':
+                       disp.verbose = 1;
+                       break;
+               }
+       }
+
+       if (optind < argc)
+               filename = argv[optind++];
+       if (!filename)
+               usage("Missing filename");
+
+       argv += optind;
+       argc -= optind;
+
+       if (disp.oper == OPER_WRITE_PROP) {
+               if (argc < 1)
+                       usage("Missing node");
+               if (argc < 2)
+                       usage("Missing property");
+       }
+
+       if (do_fdtput(&disp, filename, argv, argc))
+               return 1;
+       return 0;
+}
index 28d0b23..665dad7 100644 (file)
@@ -263,6 +263,9 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
        struct node *child;
        int seen_name_prop = 0;
 
+       if (tree->deleted)
+               return;
+
        emit->beginnode(etarget, tree->labels);
 
        if (vi->flags & FTF_FULLPATH)
index 6c42acf..91126c0 100644 (file)
@@ -3,6 +3,8 @@
 # This is not a complete Makefile of itself.  Instead, it is designed to
 # be easily embeddable into other systems of Makefiles.
 #
-LIBFDT_INCLUDES = fdt.h libfdt.h
-LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
+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)
index 2acaec5..e56833a 100644 (file)
@@ -74,7 +74,7 @@ int fdt_check_header(const void *fdt)
        return 0;
 }
 
-const void *fdt_offset_ptr(const void *fdt, int offset, int len)
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
 {
        const char *p;
 
@@ -90,42 +90,53 @@ const void *fdt_offset_ptr(const void *fdt, int offset, int len)
        return p;
 }
 
-uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
+uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
 {
        const uint32_t *tagp, *lenp;
        uint32_t tag;
+       int offset = startoffset;
        const char *p;
 
-       if (offset % FDT_TAGSIZE)
-               return -1;
-
+       *nextoffset = -FDT_ERR_TRUNCATED;
        tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
-       if (! tagp)
+       if (!tagp)
                return FDT_END; /* premature end */
        tag = fdt32_to_cpu(*tagp);
        offset += FDT_TAGSIZE;
 
+       *nextoffset = -FDT_ERR_BADSTRUCTURE;
        switch (tag) {
        case FDT_BEGIN_NODE:
                /* skip name */
                do {
                        p = fdt_offset_ptr(fdt, offset++, 1);
                } while (p && (*p != '\0'));
-               if (! p)
-                       return FDT_END;
+               if (!p)
+                       return FDT_END; /* premature end */
                break;
+
        case FDT_PROP:
                lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
-               if (! lenp)
-                       return FDT_END;
-               /* skip name offset, length and value */
-               offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
+               if (!lenp)
+                       return FDT_END; /* premature end */
+               /* skip-name offset, length and value */
+               offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+                       + fdt32_to_cpu(*lenp);
+               break;
+
+       case FDT_END:
+       case FDT_END_NODE:
+       case FDT_NOP:
                break;
+
+       default:
+               return FDT_END;
        }
 
-       if (nextoffset)
-               *nextoffset = FDT_TAGALIGN(offset);
+       if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
+               return FDT_END; /* premature end */
 
+       *nextoffset = FDT_TAGALIGN(offset);
        return tag;
 }
 
@@ -138,6 +149,15 @@ int _fdt_check_node_offset(const void *fdt, int offset)
        return offset;
 }
 
+int _fdt_check_prop_offset(const void *fdt, int offset)
+{
+       if ((offset < 0) || (offset % FDT_TAGSIZE)
+           || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
+               return -FDT_ERR_BADOFFSET;
+
+       return offset;
+}
+
 int fdt_next_node(const void *fdt, int offset, int *depth)
 {
        int nextoffset = 0;
@@ -162,15 +182,16 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
                        break;
 
                case FDT_END_NODE:
-                       if (depth)
-                               (*depth)--;
+                       if (depth && ((--(*depth)) < 0))
+                               return nextoffset;
                        break;
 
                case FDT_END:
-                       return -FDT_ERR_NOTFOUND;
-
-               default:
-                       return -FDT_ERR_BADSTRUCTURE;
+                       if ((nextoffset >= 0)
+                           || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth))
+                               return -FDT_ERR_NOTFOUND;
+                       else
+                               return nextoffset;
                }
        } while (tag != FDT_BEGIN_NODE);
 
diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c
new file mode 100644 (file)
index 0000000..f72d13b
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2012 David Gibson, IBM Corporation.
+ *
+ * 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 "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_create_empty_tree(void *buf, int bufsize)
+{
+       int err;
+
+       err = fdt_create(buf, bufsize);
+       if (err)
+               return err;
+
+       err = fdt_finish_reservemap(buf);
+       if (err)
+               return err;
+
+       err = fdt_begin_node(buf, "");
+       if (err)
+               return err;
+
+       err =  fdt_end_node(buf);
+       if (err)
+               return err;
+
+       err = fdt_finish(buf);
+       if (err)
+               return err;
+
+       return fdt_open_into(buf, buf, bufsize);
+}
+
index 22e6929..02b6d68 100644 (file)
@@ -80,6 +80,14 @@ const char *fdt_string(const void *fdt, int stroffset)
        return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
 }
 
+static int _fdt_string_eq(const void *fdt, int stroffset,
+                         const char *s, int len)
+{
+       const char *p = fdt_string(fdt, stroffset);
+
+       return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+}
+
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
        FDT_CHECK_HEADER(fdt);
@@ -97,6 +105,30 @@ int fdt_num_mem_rsv(const void *fdt)
        return i;
 }
 
+static int _nextprop(const void *fdt, int offset)
+{
+       uint32_t tag;
+       int nextoffset;
+
+       do {
+               tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+               switch (tag) {
+               case FDT_END:
+                       if (nextoffset >= 0)
+                               return -FDT_ERR_BADSTRUCTURE;
+                       else
+                               return nextoffset;
+
+               case FDT_PROP:
+                       return offset;
+               }
+               offset = nextoffset;
+       } while (tag == FDT_NOP);
+
+       return -FDT_ERR_NOTFOUND;
+}
+
 int fdt_subnode_offset_namelen(const void *fdt, int offset,
                               const char *name, int namelen)
 {
@@ -104,20 +136,16 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
 
        FDT_CHECK_HEADER(fdt);
 
-       for (depth = 0, offset = fdt_next_node(fdt, offset, &depth);
-            (offset >= 0) && (depth > 0);
-            offset = fdt_next_node(fdt, offset, &depth)) {
-               if (depth < 0)
-                       return -FDT_ERR_NOTFOUND;
-               else if ((depth == 1)
-                        && _fdt_nodename_eq(fdt, offset, name, namelen))
+       for (depth = 0;
+            (offset >= 0) && (depth >= 0);
+            offset = fdt_next_node(fdt, offset, &depth))
+               if ((depth == 1)
+                   && _fdt_nodename_eq(fdt, offset, name, namelen))
                        return offset;
-       }
 
-       if (offset < 0)
-               return offset; /* error */
-       else
+       if (depth < 0)
                return -FDT_ERR_NOTFOUND;
+       return offset; /* error */
 }
 
 int fdt_subnode_offset(const void *fdt, int parentoffset,
@@ -134,8 +162,20 @@ int fdt_path_offset(const void *fdt, const char *path)
 
        FDT_CHECK_HEADER(fdt);
 
-       if (*path != '/')
-               return -FDT_ERR_BADPATH;
+       /* see if we have an alias */
+       if (*path != '/') {
+               const char *q = strchr(path, '/');
+
+               if (!q)
+                       q = end;
+
+               p = fdt_get_alias_namelen(fdt, p, q - p);
+               if (!p)
+                       return -FDT_ERR_BADPATH;
+               offset = fdt_path_offset(fdt, p);
+
+               p = q;
+       }
 
        while (*p) {
                const char *q;
@@ -178,93 +218,142 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
        return NULL;
 }
 
-const struct fdt_property *fdt_get_property(const void *fdt,
-                                           int nodeoffset,
-                                           const char *name, int *lenp)
+int fdt_first_property_offset(const void *fdt, int nodeoffset)
+{
+       int offset;
+
+       if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+               return offset;
+
+       return _nextprop(fdt, offset);
+}
+
+int fdt_next_property_offset(const void *fdt, int offset)
+{
+       if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
+               return offset;
+
+       return _nextprop(fdt, offset);
+}
+
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+                                                     int offset,
+                                                     int *lenp)
 {
-       uint32_t tag;
-       const struct fdt_property *prop;
-       int namestroff;
-       int offset, nextoffset;
        int err;
+       const struct fdt_property *prop;
 
-       if (((err = fdt_check_header(fdt)) != 0)
-           || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
-                       goto fail;
+       if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
+               if (lenp)
+                       *lenp = err;
+               return NULL;
+       }
 
-       nextoffset = err;
-       do {
-               offset = nextoffset;
+       prop = _fdt_offset_ptr(fdt, offset);
 
-               tag = fdt_next_tag(fdt, offset, &nextoffset);
-               switch (tag) {
-               case FDT_END:
-                       err = -FDT_ERR_TRUNCATED;
-                       goto fail;
+       if (lenp)
+               *lenp = fdt32_to_cpu(prop->len);
 
-               case FDT_BEGIN_NODE:
-               case FDT_END_NODE:
-               case FDT_NOP:
-                       break;
+       return prop;
+}
 
-               case FDT_PROP:
-                       err = -FDT_ERR_BADSTRUCTURE;
-                       prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
-                       if (! prop)
-                               goto fail;
-                       namestroff = fdt32_to_cpu(prop->nameoff);
-                       if (strcmp(fdt_string(fdt, namestroff), name) == 0) {
-                               /* Found it! */
-                               int len = fdt32_to_cpu(prop->len);
-                               prop = fdt_offset_ptr(fdt, offset,
-                                                     sizeof(*prop)+len);
-                               if (! prop)
-                                       goto fail;
-
-                               if (lenp)
-                                       *lenp = len;
-
-                               return prop;
-                       }
-                       break;
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+                                                   int offset,
+                                                   const char *name,
+                                                   int namelen, int *lenp)
+{
+       for (offset = fdt_first_property_offset(fdt, offset);
+            (offset >= 0);
+            (offset = fdt_next_property_offset(fdt, offset))) {
+               const struct fdt_property *prop;
 
-               default:
-                       err = -FDT_ERR_BADSTRUCTURE;
-                       goto fail;
+               if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
+                       offset = -FDT_ERR_INTERNAL;
+                       break;
                }
-       } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
+               if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
+                                  name, namelen))
+                       return prop;
+       }
 
-       err = -FDT_ERR_NOTFOUND;
- fail:
        if (lenp)
-               *lenp = err;
+               *lenp = offset;
        return NULL;
 }
 
-const void *fdt_getprop(const void *fdt, int nodeoffset,
-                 const char *name, int *lenp)
+const struct fdt_property *fdt_get_property(const void *fdt,
+                                           int nodeoffset,
+                                           const char *name, int *lenp)
+{
+       return fdt_get_property_namelen(fdt, nodeoffset, name,
+                                       strlen(name), lenp);
+}
+
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+                               const char *name, int namelen, int *lenp)
 {
        const struct fdt_property *prop;
 
-       prop = fdt_get_property(fdt, nodeoffset, name, lenp);
+       prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
        if (! prop)
                return NULL;
 
        return prop->data;
 }
 
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+                                 const char **namep, int *lenp)
+{
+       const struct fdt_property *prop;
+
+       prop = fdt_get_property_by_offset(fdt, offset, lenp);
+       if (!prop)
+               return NULL;
+       if (namep)
+               *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+       return prop->data;
+}
+
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+                       const char *name, int *lenp)
+{
+       return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
+}
+
 uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
 {
        const uint32_t *php;
        int len;
 
-       php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
-       if (!php || (len != sizeof(*php)))
-               return 0;
+       /* FIXME: This is a bit sub-optimal, since we potentially scan
+        * over all the properties twice. */
+       php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
+       if (!php || (len != sizeof(*php))) {
+               php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
+               if (!php || (len != sizeof(*php)))
+                       return 0;
+       }
 
        return fdt32_to_cpu(*php);
 }
 
+const char *fdt_get_alias_namelen(const void *fdt,
+                                 const char *name, int namelen)
+{
+       int aliasoffset;
+
+       aliasoffset = fdt_path_offset(fdt, "/aliases");
+       if (aliasoffset < 0)
+               return NULL;
+
+       return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
+}
+
+const char *fdt_get_alias(const void *fdt, const char *name)
+{
+       return fdt_get_alias_namelen(fdt, name, strlen(name));
+}
+
 int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
 {
        int pdepth = 0, p = 0;
@@ -279,9 +368,6 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
        for (offset = 0, depth = 0;
             (offset >= 0) && (offset <= nodeoffset);
             offset = fdt_next_node(fdt, offset, &depth)) {
-               if (pdepth < depth)
-                       continue; /* overflowed buffer */
-
                while (pdepth > depth) {
                        do {
                                p--;
@@ -289,14 +375,16 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
                        pdepth--;
                }
 
-               name = fdt_get_name(fdt, offset, &namelen);
-               if (!name)
-                       return namelen;
-               if ((p + namelen + 1) <= buflen) {
-                       memcpy(buf + p, name, namelen);
-                       p += namelen;
-                       buf[p++] = '/';
-                       pdepth++;
+               if (pdepth >= depth) {
+                       name = fdt_get_name(fdt, offset, &namelen);
+                       if (!name)
+                               return namelen;
+                       if ((p + namelen + 1) <= buflen) {
+                               memcpy(buf + p, name, namelen);
+                               p += namelen;
+                               buf[p++] = '/';
+                               pdepth++;
+                       }
                }
 
                if (offset == nodeoffset) {
@@ -306,7 +394,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
                        if (p > 1) /* special case so that root path is "/", not "" */
                                p--;
                        buf[p] = '\0';
-                       return p;
+                       return 0;
                }
        }
 
@@ -404,14 +492,31 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
 
 int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
 {
+       int offset;
+
        if ((phandle == 0) || (phandle == -1))
                return -FDT_ERR_BADPHANDLE;
-       phandle = cpu_to_fdt32(phandle);
-       return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
-                                            &phandle, sizeof(phandle));
+
+       FDT_CHECK_HEADER(fdt);
+
+       /* FIXME: The algorithm here is pretty horrible: we
+        * potentially scan each property of a node in
+        * fdt_get_phandle(), then if that didn't find what
+        * we want, we scan over them again making our way to the next
+        * node.  Still it's the easiest to implement approach;
+        * performance can come later. */
+       for (offset = fdt_next_node(fdt, -1, NULL);
+            offset >= 0;
+            offset = fdt_next_node(fdt, offset, NULL)) {
+               if (fdt_get_phandle(fdt, offset) == phandle)
+                       return offset;
+       }
+
+       return offset; /* error from fdt_next_node() */
 }
 
-static int _stringlist_contains(const char *strlist, int listlen, const char *str)
+static int _fdt_stringlist_contains(const char *strlist, int listlen,
+                                   const char *str)
 {
        int len = strlen(str);
        const char *p;
@@ -437,7 +542,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
        prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
        if (!prop)
                return len;
-       if (_stringlist_contains(prop, len, compatible))
+       if (_fdt_stringlist_contains(prop, len, compatible))
                return 0;
        else
                return 1;
index 8e7ec4c..24437df 100644 (file)
@@ -289,6 +289,33 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
        return 0;
 }
 
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+                  const void *val, int len)
+{
+       struct fdt_property *prop;
+       int err, oldlen, newlen;
+
+       FDT_RW_CHECK_HEADER(fdt);
+
+       prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+       if (prop) {
+               newlen = len + oldlen;
+               err = _fdt_splice_struct(fdt, prop->data,
+                                        FDT_TAGALIGN(oldlen),
+                                        FDT_TAGALIGN(newlen));
+               if (err)
+                       return err;
+               prop->len = cpu_to_fdt32(newlen);
+               memcpy(prop->data + oldlen, val, len);
+       } else {
+               err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+               if (err)
+                       return err;
+               memcpy(prop->data, val, len);
+       }
+       return 0;
+}
+
 int fdt_delprop(void *fdt, int nodeoffset, const char *name)
 {
        struct fdt_property *prop;
@@ -406,6 +433,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
                struct_size = 0;
                while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
                        ;
+               if (struct_size < 0)
+                       return struct_size;
        }
 
        if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
index 698329e..55ebebf 100644 (file)
@@ -70,7 +70,7 @@ static int _fdt_sw_check_header(void *fdt)
                        return err; \
        }
 
-static void *_fdt_grab_space(void *fdt, int len)
+static void *_fdt_grab_space(void *fdt, size_t len)
 {
        int offset = fdt_size_dt_struct(fdt);
        int spaceleft;
@@ -82,7 +82,7 @@ static void *_fdt_grab_space(void *fdt, int len)
                return NULL;
 
        fdt_set_size_dt_struct(fdt, offset + len);
-       return fdt_offset_ptr_w(fdt, offset, len);
+       return _fdt_offset_ptr_w(fdt, offset);
 }
 
 int fdt_create(void *buf, int bufsize)
@@ -237,18 +237,17 @@ int fdt_finish(void *fdt)
        while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
                if (tag == FDT_PROP) {
                        struct fdt_property *prop =
-                               fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
+                               _fdt_offset_ptr_w(fdt, offset);
                        int nameoff;
 
-                       if (! prop)
-                               return -FDT_ERR_BADSTRUCTURE;
-
                        nameoff = fdt32_to_cpu(prop->nameoff);
                        nameoff += fdt_size_dt_strings(fdt);
                        prop->nameoff = cpu_to_fdt32(nameoff);
                }
                offset = nextoffset;
        }
+       if (nextoffset < 0)
+               return nextoffset;
 
        /* Finally, adjust the header */
        fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
index a4652c6..6025fa1 100644 (file)
@@ -94,41 +94,14 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
        return 0;
 }
 
-int _fdt_node_end_offset(void *fdt, int nodeoffset)
+int _fdt_node_end_offset(void *fdt, int offset)
 {
-       int level = 0;
-       uint32_t tag;
-       int offset, nextoffset;
-
-       tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
-       if (tag != FDT_BEGIN_NODE)
-               return -FDT_ERR_BADOFFSET;
-       do {
-               offset = nextoffset;
-               tag = fdt_next_tag(fdt, offset, &nextoffset);
-
-               switch (tag) {
-               case FDT_END:
-                       return offset;
-
-               case FDT_BEGIN_NODE:
-                       level++;
-                       break;
-
-               case FDT_END_NODE:
-                       level--;
-                       break;
-
-               case FDT_PROP:
-               case FDT_NOP:
-                       break;
-
-               default:
-                       return -FDT_ERR_BADSTRUCTURE;
-               }
-       } while (level >= 0);
-
-       return nextoffset;
+       int depth = 0;
+
+       while ((offset >= 0) && (depth >= 0))
+               offset = fdt_next_node(fdt, offset, &depth);
+
+       return offset;
 }
 
 int fdt_nop_node(void *fdt, int nodeoffset)
index ff6246f..73f4975 100644 (file)
@@ -61,7 +61,7 @@
 #define FDT_ERR_NOTFOUND       1
        /* FDT_ERR_NOTFOUND: The requested node or property does not exist */
 #define FDT_ERR_EXISTS         2
-       /* FDT_ERR_EXISTS: Attempted to create a node or property which
+       /* FDT_ERR_EXISTS: Attemped to create a node or property which
         * already exists */
 #define FDT_ERR_NOSPACE                3
        /* FDT_ERR_NOSPACE: Operation needed to expand the device
 /* Low-level functions (you probably don't need these)                */
 /**********************************************************************/
 
-const void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
 static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
 {
        return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
@@ -156,7 +156,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth);
 #define __fdt_set_hdr(name) \
        static inline void fdt_set_##name(void *fdt, uint32_t val) \
        { \
-               struct fdt_header *fdth = fdt; \
+               struct fdt_header *fdth = (struct fdt_header*)fdt; \
                fdth->name = cpu_to_fdt32(val); \
        }
 __fdt_set_hdr(magic);
@@ -343,6 +343,91 @@ int fdt_path_offset(const void *fdt, const char *path);
 const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
 
 /**
+ * fdt_first_property_offset - find the offset of a node's first property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of a node
+ *
+ * fdt_first_property_offset() finds the first property of the node at
+ * the given structure block offset.
+ *
+ * returns:
+ *     structure block offset of the property (>=0), on success
+ *     -FDT_ERR_NOTFOUND, if the requested node has no properties
+ *     -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag
+ *      -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_first_property_offset(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_next_property_offset - step through a node's properties
+ * @fdt: pointer to the device tree blob
+ * @offset: structure block offset of a property
+ *
+ * fdt_next_property_offset() finds the property immediately after the
+ * one at the given structure block offset.  This will be a property
+ * of the same node as the given property.
+ *
+ * returns:
+ *     structure block offset of the next property (>=0), on success
+ *     -FDT_ERR_NOTFOUND, if the given property is the last in its node
+ *     -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag
+ *      -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_next_property_offset(const void *fdt, int offset);
+
+/**
+ * fdt_get_property_by_offset - retrieve the property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @offset: offset of the property to retrieve
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_property_by_offset() retrieves a pointer to the
+ * fdt_property structure within the device tree blob at the given
+ * offset.  If lenp is non-NULL, the length of the property value is
+ * also returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ *     pointer to the structure representing the property
+ *             if lenp is non-NULL, *lenp contains the length of the property
+ *             value (>=0)
+ *     NULL, on error
+ *             if lenp is non-NULL, *lenp contains an error code (<0):
+ *             -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ *             -FDT_ERR_BADMAGIC,
+ *             -FDT_ERR_BADVERSION,
+ *             -FDT_ERR_BADSTATE,
+ *             -FDT_ERR_BADSTRUCTURE,
+ *             -FDT_ERR_TRUNCATED, standard meanings
+ */
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+                                                     int offset,
+                                                     int *lenp);
+
+/**
+ * fdt_get_property_namelen - find a property based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_get_property_namelen(), but only examine the first
+ * namelen characters of name for matching the property name.
+ */
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+                                                   int nodeoffset,
+                                                   const char *name,
+                                                   int namelen, int *lenp);
+
+/**
  * fdt_get_property - find a given property in a given node
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to find
@@ -380,6 +465,54 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
 }
 
 /**
+ * fdt_getprop_by_offset - retrieve the value of a property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @ffset: offset of the property to read
+ * @namep: pointer to a string variable (will be overwritten) or NULL
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop_by_offset() retrieves a pointer to the value of the
+ * property at structure block offset 'offset' (this will be a pointer
+ * to within the device blob itself, not a copy of the value).  If
+ * lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by lenp.  If namep is non-NULL,
+ * the property's namne will also be returned in the char * pointed to
+ * by namep (this will be a pointer to within the device tree's string
+ * block, not a new copy of the name).
+ *
+ * returns:
+ *     pointer to the property's value
+ *             if lenp is non-NULL, *lenp contains the length of the property
+ *             value (>=0)
+ *             if namep is non-NULL *namep contiains a pointer to the property
+ *             name.
+ *     NULL, on error
+ *             if lenp is non-NULL, *lenp contains an error code (<0):
+ *             -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ *             -FDT_ERR_BADMAGIC,
+ *             -FDT_ERR_BADVERSION,
+ *             -FDT_ERR_BADSTATE,
+ *             -FDT_ERR_BADSTRUCTURE,
+ *             -FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+                                 const char **namep, int *lenp);
+
+/**
+ * fdt_getprop_namelen - get property value based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_getprop(), but only examine the first namelen
+ * characters of name for matching the property name.
+ */
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+                               const char *name, int namelen, int *lenp);
+
+/**
  * fdt_getprop - retrieve the value of a given property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to find
@@ -429,6 +562,32 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
 uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
 
 /**
+ * fdt_get_alias_namelen - get alias based on substring
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_get_alias(), but only examine the first namelen
+ * characters of name for matching the alias name.
+ */
+const char *fdt_get_alias_namelen(const void *fdt,
+                                 const char *name, int namelen);
+
+/**
+ * fdt_get_alias - retreive the path referenced by a given alias
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ *
+ * fdt_get_alias() retrieves the value of a given alias.  That is, the
+ * value of the property named 'name' in the node /aliases.
+ *
+ * returns:
+ *     a pointer to the expansion of the alias named 'name', of it exists
+ *     NULL, if the given alias or the /aliases node does not exist
+ */
+const char *fdt_get_alias(const void *fdt, const char *name);
+
+/**
  * fdt_get_path - determine the full path of a node
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose path to find
@@ -693,17 +852,17 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
                        const void *val, int len);
 
 /**
- * fdt_setprop_inplace_cell - change the value of a single-cell property
+ * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
  * @name: name of the property to change
- * @val: cell (32-bit integer) value to replace the property with
+ * @val: 32-bit integer value to replace the property with
  *
- * fdt_setprop_inplace_cell() replaces the value of a given property
- * with the 32-bit integer cell value in val, converting val to
- * big-endian if necessary.  This function cannot change the size of a
- * property, and so will only work if the property already exists and
- * has length 4.
+ * fdt_setprop_inplace_u32() replaces the value of a given property
+ * with the 32-bit integer value in val, converting val to big-endian
+ * if necessary.  This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 4.
  *
  * This function will alter only the bytes in the blob which contain
  * the given property value, and will not alter or move any other part
@@ -712,7 +871,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
  * returns:
  *     0, on success
  *     -FDT_ERR_NOSPACE, if the property's length is not equal to 4
 *    -FDT_ERR_NOTFOUND, node does not have the named property
    -FDT_ERR_NOTFOUND, node does not have the named property
  *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
  *     -FDT_ERR_BADMAGIC,
  *     -FDT_ERR_BADVERSION,
@@ -720,14 +879,60 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
  *     -FDT_ERR_BADSTRUCTURE,
  *     -FDT_ERR_TRUNCATED, standard meanings
  */
-static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
-                                          const char *name, uint32_t val)
+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));
 }
 
 /**
+ * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to replace the property with
+ *
+ * fdt_setprop_inplace_u64() replaces the value of a given property
+ * with the 64-bit integer value in val, converting val to big-endian
+ * if necessary.  This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 8.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, if the property's length is not equal to 8
+ *     -FDT_ERR_NOTFOUND, node does not have the named property
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
+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));
+}
+
+/**
+ * fdt_setprop_inplace_cell - change the value of a single-cell property
+ *
+ * This is an alternative name for fdt_setprop_inplace_u32()
+ */
+static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
+                                          const char *name, uint32_t val)
+{
+       return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val);
+}
+
+/**
  * fdt_nop_property - replace a property with nop tags
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to nop
@@ -786,11 +991,20 @@ 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_cell(void *fdt, const char *name, uint32_t val)
+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));
 }
+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));
+}
+static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
+{
+       return fdt_property_u32(fdt, name, val);
+}
 #define fdt_property_string(fdt, name, str) \
        fdt_property(fdt, name, str, strlen(str)+1)
 int fdt_end_node(void *fdt);
@@ -800,6 +1014,7 @@ int fdt_finish(void *fdt);
 /* Read-write functions                                               */
 /**********************************************************************/
 
+int fdt_create_empty_tree(void *buf, int bufsize);
 int fdt_open_into(const void *fdt, void *buf, int bufsize);
 int fdt_pack(void *fdt);
 
@@ -909,14 +1124,14 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
                const void *val, int len);
 
 /**
- * fdt_setprop_cell - set a property to a single cell value
+ * fdt_setprop_u32 - set a property to a 32-bit integer
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
  * @name: name of the property to change
  * @val: 32-bit integer value for the property (native endian)
  *
- * fdt_setprop_cell() sets the value of the named property in the
- * given node to the given cell value (converting to big-endian if
+ * fdt_setprop_u32() sets the value of the named property in the given
+ * node to the given 32-bit integer value (converting to big-endian if
  * necessary), or creates a new property with that value if it does
  * not already exist.
  *
@@ -936,14 +1151,60 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
  *     -FDT_ERR_BADLAYOUT,
  *     -FDT_ERR_TRUNCATED, standard meanings
  */
-static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
-                                  uint32_t val)
+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));
 }
 
 /**
+ * fdt_setprop_u64 - set a property to a 64-bit integer
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value for the property (native endian)
+ *
+ * fdt_setprop_u64() sets the value of the named property in the given
+ * node to the given 64-bit integer value (converting to big-endian if
+ * necessary), or creates a new property with that value if it does
+ * not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *             contain the new property value
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
+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));
+}
+
+/**
+ * fdt_setprop_cell - set a property to a single cell value
+ *
+ * This is an alternative name for fdt_setprop_u32()
+ */
+static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
+                                  uint32_t val)
+{
+       return fdt_setprop_u32(fdt, nodeoffset, name, val);
+}
+
+/**
  * fdt_setprop_string - set a property to a string value
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
@@ -975,6 +1236,147 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
        fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
 
 /**
+ * fdt_appendprop - append to or create a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to append to
+ * @val: pointer to data to append to the property value
+ * @len: length of the data to append to the property value
+ *
+ * fdt_appendprop() appends the value to the named property in the
+ * given node, creating the property if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *             contain the new property value
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+                  const void *val, int len);
+
+/**
+ * fdt_appendprop_u32 - append a 32-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u32() appends the given 32-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *             contain the new property value
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
+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));
+}
+
+/**
+ * fdt_appendprop_u64 - append a 64-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u64() appends the given 64-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *             contain the new property value
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
+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));
+}
+
+/**
+ * fdt_appendprop_cell - append a single cell value to a property
+ *
+ * This is an alternative name for fdt_appendprop_u32()
+ */
+static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
+                                     const char *name, uint32_t val)
+{
+       return fdt_appendprop_u32(fdt, nodeoffset, name, val);
+}
+
+/**
+ * fdt_appendprop_string - append a string to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @str: string value to append to the property
+ *
+ * fdt_appendprop_string() appends the given string to the value of
+ * the named property in the given node, or creates a new property
+ * with that value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *             contain the new property value
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
+#define fdt_appendprop_string(fdt, nodeoffset, name, str) \
+       fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
  * fdt_delprop - delete a property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to nop
index 449bf60..213d7fb 100644 (file)
@@ -5,19 +5,25 @@
 #include <stdint.h>
 #include <string.h>
 
-#define _B(n)  ((unsigned long long)((uint8_t *)&x)[n])
+#define EXTRACT_BYTE(n)        ((unsigned long long)((uint8_t *)&x)[n])
+static inline uint16_t fdt16_to_cpu(uint16_t x)
+{
+       return (EXTRACT_BYTE(0) << 8) | EXTRACT_BYTE(1);
+}
+#define cpu_to_fdt16(x) fdt16_to_cpu(x)
+
 static inline uint32_t fdt32_to_cpu(uint32_t x)
 {
-       return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3);
+       return (EXTRACT_BYTE(0) << 24) | (EXTRACT_BYTE(1) << 16) | (EXTRACT_BYTE(2) << 8) | EXTRACT_BYTE(3);
 }
 #define cpu_to_fdt32(x) fdt32_to_cpu(x)
 
 static inline uint64_t fdt64_to_cpu(uint64_t x)
 {
-       return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32)
-               | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7);
+       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);
 }
 #define cpu_to_fdt64(x) fdt64_to_cpu(x)
-#undef _B
+#undef EXTRACT_BYTE
 
 #endif /* _LIBFDT_ENV_H */
index 46eb93e..381133b 100644 (file)
@@ -62,8 +62,8 @@
                        return err; \
        }
 
-uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
 int _fdt_check_node_offset(const void *fdt, int offset);
+int _fdt_check_prop_offset(const void *fdt, int offset);
 const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
 int _fdt_node_end_offset(void *fdt, int nodeoffset);
 
index 26d0e1e..b61465f 100644 (file)
@@ -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;
@@ -155,7 +204,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
                        }
                }
 
-               /* if no collision occurred, add child to the old node. */
+               /* if no collision occured, add child to the old node. */
                if (new_child)
                        add_child(old_node, new_child);
        }
@@ -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);
 }
 
index 36a38e9..246ab4b 100644 (file)
 #include "dtc.h"
 #include "srcpos.h"
 
+/* A node in our list of directories to search for source/include files */
+struct search_path {
+       struct search_path *next;       /* next node in list, NULL for end */
+       const char *dirname;            /* name of directory to search */
+};
+
+/* This is the list of directories that we search for source files */
+static struct search_path *search_path_head, **search_path_tail;
+
 
 static char *dirname(const char *path)
 {
@@ -47,6 +56,64 @@ struct srcfile_state *current_srcfile; /* = NULL */
 #define MAX_SRCFILE_DEPTH     (100)
 static int srcfile_depth; /* = 0 */
 
+
+/**
+ * Try to open a file in a given directory.
+ *
+ * If the filename is an absolute path, then dirname is ignored. If it is a
+ * relative path, then we look in that directory for the file.
+ *
+ * @param dirname      Directory to look in, or NULL for none
+ * @param fname                Filename to look for
+ * @param fp           Set to NULL if file did not open
+ * @return allocated filename on success (caller must free), NULL on failure
+ */
+static char *try_open(const char *dirname, const char *fname, FILE **fp)
+{
+       char *fullname;
+
+       if (!dirname || fname[0] == '/')
+               fullname = xstrdup(fname);
+       else
+               fullname = join_path(dirname, fname);
+
+       *fp = fopen(fullname, "r");
+       if (!*fp) {
+               free(fullname);
+               fullname = NULL;
+       }
+
+       return fullname;
+}
+
+/**
+ * Open a file for read access
+ *
+ * If it is a relative filename, we search the full search path for it.
+ *
+ * @param fname        Filename to open
+ * @param fp   Returns pointer to opened FILE, or NULL on failure
+ * @return pointer to allocated filename, which caller must free
+ */
+static char *fopen_any_on_path(const char *fname, FILE **fp)
+{
+       const char *cur_dir = NULL;
+       struct search_path *node;
+       char *fullname;
+
+       /* Try current directory first */
+       assert(fp);
+       if (current_srcfile)
+               cur_dir = current_srcfile->dir;
+       fullname = try_open(cur_dir, fname, fp);
+
+       /* Failing that, try each search path in turn */
+       for (node = search_path_head; !*fp && node; node = node->next)
+               fullname = try_open(node->dirname, fname, fp);
+
+       return fullname;
+}
+
 FILE *srcfile_relative_open(const char *fname, char **fullnamep)
 {
        FILE *f;
@@ -56,13 +123,7 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep)
                f = stdin;
                fullname = xstrdup("<stdin>");
        } else {
-               if (!current_srcfile || !current_srcfile->dir
-                   || (fname[0] == '/'))
-                       fullname = xstrdup(fname);
-               else
-                       fullname = join_path(current_srcfile->dir, fname);
-
-               f = fopen(fullname, "r");
+               fullname = fopen_any_on_path(fname, &f);
                if (!f)
                        die("Couldn't open \"%s\": %s\n", fname,
                            strerror(errno));
@@ -119,6 +180,23 @@ int srcfile_pop(void)
        return current_srcfile ? 1 : 0;
 }
 
+void srcfile_add_search_path(const char *dirname)
+{
+       struct search_path *node;
+
+       /* Create the node */
+       node = xmalloc(sizeof(*node));
+       node->next = NULL;
+       node->dirname = xstrdup(dirname);
+
+       /* Add to the end of our list */
+       if (search_path_tail)
+               *search_path_tail = node;
+       else
+               search_path_head = node;
+       search_path_tail = &node->next;
+}
+
 /*
  * The empty source position.
  */
@@ -250,3 +328,9 @@ srcpos_warn(struct srcpos *pos, char const *fmt, ...)
 
        va_end(va);
 }
+
+void srcpos_set_line(char *f, int l)
+{
+       current_srcfile->name = f;
+       current_srcfile->lineno = l;
+}
index ce980ca..93a2712 100644 (file)
@@ -33,10 +33,39 @@ struct srcfile_state {
 extern FILE *depfile; /* = NULL */
 extern struct srcfile_state *current_srcfile; /* = NULL */
 
+/**
+ * Open a source file.
+ *
+ * If the source file is a relative pathname, then it is searched for in the
+ * current directory (the directory of the last source file read) and after
+ * that in the search path.
+ *
+ * We work through the search path in order from the first path specified to
+ * the last.
+ *
+ * If the file is not found, then this function does not return, but calls
+ * die().
+ *
+ * @param fname                Filename to search
+ * @param fullnamep    If non-NULL, it is set to the allocated filename of the
+ *                     file that was opened. The caller is then responsible
+ *                     for freeing the pointer.
+ * @return pointer to opened FILE
+ */
 FILE *srcfile_relative_open(const char *fname, char **fullnamep);
+
 void srcfile_push(const char *fname);
 int srcfile_pop(void);
 
+/**
+ * Add a new directory to the search path for input files
+ *
+ * The new path is added at the end of the list.
+ *
+ * @param dirname      Directory to add
+ */
+void srcfile_add_search_path(const char *dirname);
+
 struct srcpos {
     int first_line;
     int first_column;
@@ -84,4 +113,6 @@ extern void srcpos_error(struct srcpos *pos, char const *, ...)
 extern void srcpos_warn(struct srcpos *pos, char const *, ...)
      __attribute__((format(printf, 2, 3)));
 
+extern void srcpos_set_line(char *f, int l);
+
 #endif /* _SRCPOS_H_ */
index c09aafa..33eeba5 100644 (file)
@@ -23,6 +23,7 @@
 
 extern FILE *yyin;
 extern int yyparse(void);
+extern YYLTYPE yylloc;
 
 struct boot_info *the_boot_info;
 int treesource_error;
@@ -34,6 +35,7 @@ struct boot_info *dt_from_source(const char *fname)
 
        srcfile_push(fname);
        yyin = current_srcfile->f;
+       yylloc.file = current_srcfile;
 
        if (yyparse() != 0)
                die("Unable to parse input tree\n");
index d7ac27d..2422c34 100644 (file)
@@ -1,6 +1,10 @@
 /*
+ * Copyright 2011 The Chromium Authors, All Rights Reserved.
  * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
  *
+ * util_is_printable_string contributed by
+ *     Pantelis Antoniou <pantelis.antoniou AT gmail.com>
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
  *                                                                   USA
  */
 
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
+#include <assert.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
 
+#include "libfdt.h"
 #include "util.h"
 
 char *xstrdup(const char *s)
@@ -57,3 +68,264 @@ char *join_path(const char *path, const char *name)
        memcpy(str+lenp, name, lenn+1);
        return str;
 }
+
+int util_is_printable_string(const void *data, int len)
+{
+       const char *s = data;
+       const char *ss;
+
+       /* zero length is not */
+       if (len == 0)
+               return 0;
+
+       /* must terminate with zero */
+       if (s[len - 1] != '\0')
+               return 0;
+
+       ss = s;
+       while (*s && isprint(*s))
+               s++;
+
+       /* not zero, or not done yet */
+       if (*s != '\0' || (s + 1 - ss) < len)
+               return 0;
+
+       return 1;
+}
+
+/*
+ * Parse a octal encoded character starting at index i in string s.  The
+ * resulting character will be returned and the index i will be updated to
+ * point at the character directly after the end of the encoding, this may be
+ * the '\0' terminator of the string.
+ */
+static char get_oct_char(const char *s, int *i)
+{
+       char x[4];
+       char *endx;
+       long val;
+
+       x[3] = '\0';
+       strncpy(x, s + *i, 3);
+
+       val = strtol(x, &endx, 8);
+
+       assert(endx > x);
+
+       (*i) += endx - x;
+       return val;
+}
+
+/*
+ * Parse a hexadecimal encoded character starting at index i in string s.  The
+ * resulting character will be returned and the index i will be updated to
+ * point at the character directly after the end of the encoding, this may be
+ * the '\0' terminator of the string.
+ */
+static char get_hex_char(const char *s, int *i)
+{
+       char x[3];
+       char *endx;
+       long val;
+
+       x[2] = '\0';
+       strncpy(x, s + *i, 2);
+
+       val = strtol(x, &endx, 16);
+       if (!(endx  > x))
+               die("\\x used with no following hex digits\n");
+
+       (*i) += endx - x;
+       return val;
+}
+
+char get_escape_char(const char *s, int *i)
+{
+       char    c = s[*i];
+       int     j = *i + 1;
+       char    val;
+
+       assert(c);
+       switch (c) {
+       case 'a':
+               val = '\a';
+               break;
+       case 'b':
+               val = '\b';
+               break;
+       case 't':
+               val = '\t';
+               break;
+       case 'n':
+               val = '\n';
+               break;
+       case 'v':
+               val = '\v';
+               break;
+       case 'f':
+               val = '\f';
+               break;
+       case 'r':
+               val = '\r';
+               break;
+       case '0':
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+               j--; /* need to re-read the first digit as
+                     * part of the octal value */
+               val = get_oct_char(s, &j);
+               break;
+       case 'x':
+               val = get_hex_char(s, &j);
+               break;
+       default:
+               val = c;
+       }
+
+       (*i) = j;
+       return val;
+}
+
+int utilfdt_read_err(const char *filename, char **buffp)
+{
+       int fd = 0;     /* assume stdin */
+       char *buf = NULL;
+       off_t bufsize = 1024, offset = 0;
+       int ret = 0;
+
+       *buffp = NULL;
+       if (strcmp(filename, "-") != 0) {
+               fd = open(filename, O_RDONLY);
+               if (fd < 0)
+                       return errno;
+       }
+
+       /* Loop until we have read everything */
+       buf = malloc(bufsize);
+       do {
+               /* Expand the buffer to hold the next chunk */
+               if (offset == bufsize) {
+                       bufsize *= 2;
+                       buf = realloc(buf, bufsize);
+                       if (!buf) {
+                               ret = ENOMEM;
+                               break;
+                       }
+               }
+
+               ret = read(fd, &buf[offset], bufsize - offset);
+               if (ret < 0) {
+                       ret = errno;
+                       break;
+               }
+               offset += ret;
+       } while (ret != 0);
+
+       /* Clean up, including closing stdin; return errno on error */
+       close(fd);
+       if (ret)
+               free(buf);
+       else
+               *buffp = buf;
+       return ret;
+}
+
+char *utilfdt_read(const char *filename)
+{
+       char *buff;
+       int ret = utilfdt_read_err(filename, &buff);
+
+       if (ret) {
+               fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
+                       strerror(ret));
+               return NULL;
+       }
+       /* Successful read */
+       return buff;
+}
+
+int utilfdt_write_err(const char *filename, const void *blob)
+{
+       int fd = 1;     /* assume stdout */
+       int totalsize;
+       int offset;
+       int ret = 0;
+       const char *ptr = blob;
+
+       if (strcmp(filename, "-") != 0) {
+               fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+               if (fd < 0)
+                       return errno;
+       }
+
+       totalsize = fdt_totalsize(blob);
+       offset = 0;
+
+       while (offset < totalsize) {
+               ret = write(fd, ptr + offset, totalsize - offset);
+               if (ret < 0) {
+                       ret = -errno;
+                       break;
+               }
+               offset += ret;
+       }
+       /* Close the file/stdin; return errno on error */
+       if (fd != 1)
+               close(fd);
+       return ret < 0 ? -ret : 0;
+}
+
+
+int utilfdt_write(const char *filename, const void *blob)
+{
+       int ret = utilfdt_write_err(filename, blob);
+
+       if (ret) {
+               fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename,
+                       strerror(ret));
+       }
+       return ret ? -1 : 0;
+}
+
+int utilfdt_decode_type(const char *fmt, int *type, int *size)
+{
+       int qualifier = 0;
+
+       if (!*fmt)
+               return -1;
+
+       /* get the conversion qualifier */
+       *size = -1;
+       if (strchr("hlLb", *fmt)) {
+               qualifier = *fmt++;
+               if (qualifier == *fmt) {
+                       switch (*fmt++) {
+/* TODO:               case 'l': qualifier = 'L'; break;*/
+                       case 'h':
+                               qualifier = 'b';
+                               break;
+                       }
+               }
+       }
+
+       /* we should now have a type */
+       if ((*fmt == '\0') || !strchr("iuxs", *fmt))
+               return -1;
+
+       /* convert qualifier (bhL) to byte size */
+       if (*fmt != 's')
+               *size = qualifier == 'b' ? 1 :
+                               qualifier == 'h' ? 2 :
+                               qualifier == 'l' ? 4 : -1;
+       *type = *fmt++;
+
+       /* that should be it! */
+       if (*fmt)
+               return -1;
+       return 0;
+}
index 9cead84..c8eb45d 100644 (file)
@@ -1,7 +1,10 @@
 #ifndef _UTIL_H
 #define _UTIL_H
 
+#include <stdarg.h>
+
 /*
+ * Copyright 2011 The Chromium Authors, All Rights Reserved.
  * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
@@ -53,4 +56,98 @@ static inline void *xrealloc(void *p, size_t len)
 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.
+ *
+ * @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);
+
+/*
+ * Parse an escaped character starting at index i in string s.  The resulting
+ * character will be returned and the index i will be updated to point at the
+ * character directly after the end of the encoding, this may be the '\0'
+ * terminator of the string.
+ */
+char get_escape_char(const char *s, int *i);
+
+/**
+ * Read a device tree file into a buffer. This will report any errors on
+ * stderr.
+ *
+ * @param filename     The filename to read, or - for stdin
+ * @return Pointer to allocated buffer containing fdt, or NULL on error
+ */
+char *utilfdt_read(const char *filename);
+
+/**
+ * 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.
+ *
+ * @param filename     The filename to read, or - for stdin
+ * @param buffp                Returns pointer to buffer containing fdt
+ * @return 0 if ok, else an errno value representing the error
+ */
+int utilfdt_read_err(const char *filename, char **buffp);
+
+
+/**
+ * Write a device tree buffer to a file. This will report any errors on
+ * stderr.
+ *
+ * @param filename     The filename to write, or - for stdout
+ * @param blob         Poiner to buffer containing fdt
+ * @return 0 if ok, -1 on error
+ */
+int utilfdt_write(const char *filename, const void *blob);
+
+/**
+ * Write a device tree buffer to a file. Does not report errors, but only
+ * returns them. The value returned can be passed to strerror() to obtain
+ * an error message for the user.
+ *
+ * @param filename     The filename to write, or - for stdout
+ * @param blob         Poiner to buffer containing fdt
+ * @return 0 if ok, else an errno value representing the error
+ */
+int utilfdt_write_err(const char *filename, const void *blob);
+
+/**
+ * Decode a data type string. The purpose of this string
+ *
+ * The string consists of an optional character followed by the type:
+ *     Modifier characters:
+ *             hh or b 1 byte
+ *             h       2 byte
+ *             l       4 byte, default
+ *
+ *     Type character:
+ *             s       string
+ *             i       signed integer
+ *             u       unsigned integer
+ *             x       hex
+ *
+ * TODO: Implement ll modifier (8 bytes)
+ * TODO: Implement o type (octal)
+ *
+ * @param fmt          Format string to process
+ * @param type         Returns type found(s/d/u/x), or 0 if none
+ * @param size         Returns size found(1,2,4,8) or 4 if none
+ * @return 0 if ok, -1 on error (no type given, or other invalid format)
+ */
+int utilfdt_decode_type(const char *fmt, int *type, int *size);
+
+/*
+ * This is a usage message fragment for the -t option. It is the format
+ * supported by utilfdt_decode_type.
+ */
+
+#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";
+
 #endif /* _UTIL_H */