2012-10-01 16:09:49

by Rob Herring

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 09/28/2012 04:25 PM, Stephen Warren wrote:
> From: Stephen Warren <[email protected]>
>
> 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 <[email protected]>

Seems dtc doesn't really have a maintainer. Probably makes more sense
for me to take this unless there are objections.

Rob

>
> ---
> Notes:
> * I compiled all *.dts files in the kernel before and after this change,
> and all md5sums were identical.
> * This is a straight copy of the dtc source; no merge with any in-kernel-
> only changes was performed. Hopefully there is no issue here, since I
> see no functional regressions nor new warnings.
> * My system appears to have Bison 2.4.1, whereas the grammer was
> previously generated using Bison 2.4.3. Again, this doesn't appear to
> cause any issues.
> * I have posted some patches to kbuild that depend on this; see:
> https://lists.ozlabs.org/pipermail/devicetree-discuss/2012-September/020393.html
> Hopefully this patch and that series can go through the same tree.
>
> scripts/dtc/Makefile.dtc | 13 +-
> scripts/dtc/checks.c | 203 +++++++---
> scripts/dtc/data.c | 124 ++----
> scripts/dtc/dtc-lexer.l | 65 +++-
> scripts/dtc/dtc-lexer.lex.c_shipped | 503 ++++++++++++++++------
> scripts/dtc/dtc-parser.tab.c_shipped | 780 +++++++++++++++++++++++++++-------
> scripts/dtc/dtc-parser.tab.h_shipped | 47 ++-
> scripts/dtc/dtc-parser.y | 255 ++++++++++--
> scripts/dtc/dtc.c | 21 +-
> scripts/dtc/dtc.h | 51 +++-
> scripts/dtc/fdtdump.c | 162 +++++++
> scripts/dtc/fdtget.c | 366 ++++++++++++++++
> scripts/dtc/fdtput.c | 362 ++++++++++++++++
> scripts/dtc/flattree.c | 3 +
> scripts/dtc/libfdt/Makefile.libfdt | 6 +-
> scripts/dtc/libfdt/fdt.c | 61 ++-
> scripts/dtc/libfdt/fdt_empty_tree.c | 84 ++++
> scripts/dtc/libfdt/fdt_ro.c | 275 +++++++++----
> scripts/dtc/libfdt/fdt_rw.c | 29 ++
> scripts/dtc/libfdt/fdt_sw.c | 11 +-
> scripts/dtc/libfdt/fdt_wip.c | 41 +--
> scripts/dtc/libfdt/libfdt.h | 440 ++++++++++++++++++-
> scripts/dtc/libfdt/libfdt_env.h | 16 +-
> scripts/dtc/libfdt/libfdt_internal.h | 2 +-
> scripts/dtc/livetree.c | 128 +++++-
> scripts/dtc/srcpos.c | 98 ++++-
> scripts/dtc/srcpos.h | 31 ++
> scripts/dtc/treesource.c | 2 +
> scripts/dtc/util.c | 272 ++++++++++++
> scripts/dtc/util.h | 97 +++++
> 30 files changed, 3847 insertions(+), 701 deletions(-)
> create mode 100644 scripts/dtc/fdtdump.c
> create mode 100644 scripts/dtc/fdtget.c
> create mode 100644 scripts/dtc/fdtput.c
> create mode 100644 scripts/dtc/libfdt/fdt_empty_tree.c
>
> diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc
> index 6ddf9ec..bece49b 100644
> --- a/scripts/dtc/Makefile.dtc
> +++ b/scripts/dtc/Makefile.dtc
> @@ -3,7 +3,16 @@
> # This is not a complete Makefile of itself. Instead, it is designed to
> # be easily embeddable into other systems of Makefiles.
> #
> -DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
> - checks.c
> +DTC_SRCS = \
> + checks.c \
> + data.c \
> + dtc.c \
> + flattree.c \
> + fstree.c \
> + livetree.c \
> + srcpos.c \
> + treesource.c \
> + util.c
> +
> DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
> DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
> diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
> index a662a00..ee96a25 100644
> --- a/scripts/dtc/checks.c
> +++ b/scripts/dtc/checks.c
> @@ -31,12 +31,6 @@
> #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);
> }
>
> diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
> index fe555e8..4a40c5b 100644
> --- a/scripts/dtc/data.c
> +++ b/scripts/dtc/data.c
> @@ -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)
> diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
> index e866ea5..254d5af 100644
> --- a/scripts/dtc/dtc-lexer.l
> +++ b/scripts/dtc/dtc-lexer.l
> @@ -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]);
> diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
> index 8bbe128..a6c5fcd 100644
> --- a/scripts/dtc/dtc-lexer.lex.c_shipped
> +++ b/scripts/dtc/dtc-lexer.lex.c_shipped
> @@ -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 <[email protected]>, 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)
> diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped
> index b05921e..4af5590 100644
> --- a/scripts/dtc/dtc-parser.tab.c_shipped
> +++ b/scripts/dtc/dtc-parser.tab.c_shipped
> @@ -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;
> +}
> +
> diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped
> index 4ee682b..9d2dce4 100644
> --- a/scripts/dtc/dtc-parser.tab.h_shipped
> +++ b/scripts/dtc/dtc-parser.tab.h_shipped
> @@ -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
> @@ -40,14 +41,26 @@
> 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 */
> diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
> index 5e84a67..f412460 100644
> --- a/scripts/dtc/dtc-parser.y
> +++ b/scripts/dtc/dtc-parser.y
> @@ -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;
> +}
> diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
> index 2ef5e2e..a375683 100644
> --- a/scripts/dtc/dtc.c
> +++ b/scripts/dtc/dtc.c
> @@ -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)
> diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
> index f37c97e..d501c86 100644
> --- a/scripts/dtc/dtc.h
> +++ b/scripts/dtc/dtc.h
> @@ -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
> index 0000000..207a46d
> --- /dev/null
> +++ b/scripts/dtc/fdtdump.c
> @@ -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
> index 0000000..c2fbab2
> --- /dev/null
> +++ b/scripts/dtc/fdtget.c
> @@ -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, [email protected]
> + * Based on code written by:
> + * Pantelis Antoniou <[email protected]> and
> + * Matthew McClintock <[email protected]>
> + *
> + * 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
> index 0000000..f2197f5
> --- /dev/null
> +++ b/scripts/dtc/fdtput.c
> @@ -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;
> +}
> diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
> index 28d0b23..665dad7 100644
> --- a/scripts/dtc/flattree.c
> +++ b/scripts/dtc/flattree.c
> @@ -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)
> diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt
> index 6c42acf..91126c0 100644
> --- a/scripts/dtc/libfdt/Makefile.libfdt
> +++ b/scripts/dtc/libfdt/Makefile.libfdt
> @@ -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)
> diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
> index 2acaec5..e56833a 100644
> --- a/scripts/dtc/libfdt/fdt.c
> +++ b/scripts/dtc/libfdt/fdt.c
> @@ -74,7 +74,7 @@ int fdt_check_header(const void *fdt)
> return 0;
> }
>
> -const void *fdt_offset_ptr(const void *fdt, int offset, int len)
> +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
> {
> const char *p;
>
> @@ -90,42 +90,53 @@ const void *fdt_offset_ptr(const void *fdt, int offset, int len)
> return p;
> }
>
> -uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
> +uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
> {
> const uint32_t *tagp, *lenp;
> uint32_t tag;
> + int offset = startoffset;
> const char *p;
>
> - if (offset % FDT_TAGSIZE)
> - return -1;
> -
> + *nextoffset = -FDT_ERR_TRUNCATED;
> tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
> - if (! tagp)
> + if (!tagp)
> return FDT_END; /* premature end */
> tag = fdt32_to_cpu(*tagp);
> offset += FDT_TAGSIZE;
>
> + *nextoffset = -FDT_ERR_BADSTRUCTURE;
> switch (tag) {
> case FDT_BEGIN_NODE:
> /* skip name */
> do {
> p = fdt_offset_ptr(fdt, offset++, 1);
> } while (p && (*p != '\0'));
> - if (! p)
> - return FDT_END;
> + if (!p)
> + return FDT_END; /* premature end */
> break;
> +
> case FDT_PROP:
> lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
> - if (! lenp)
> - return FDT_END;
> - /* skip name offset, length and value */
> - offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
> + if (!lenp)
> + return FDT_END; /* premature end */
> + /* skip-name offset, length and value */
> + offset += sizeof(struct fdt_property) - FDT_TAGSIZE
> + + fdt32_to_cpu(*lenp);
> + break;
> +
> + case FDT_END:
> + case FDT_END_NODE:
> + case FDT_NOP:
> break;
> +
> + default:
> + return FDT_END;
> }
>
> - if (nextoffset)
> - *nextoffset = FDT_TAGALIGN(offset);
> + if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
> + return FDT_END; /* premature end */
>
> + *nextoffset = FDT_TAGALIGN(offset);
> return tag;
> }
>
> @@ -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
> index 0000000..f72d13b
> --- /dev/null
> +++ b/scripts/dtc/libfdt/fdt_empty_tree.c
> @@ -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);
> +}
> +
> diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
> index 22e6929..02b6d68 100644
> --- a/scripts/dtc/libfdt/fdt_ro.c
> +++ b/scripts/dtc/libfdt/fdt_ro.c
> @@ -80,6 +80,14 @@ const char *fdt_string(const void *fdt, int stroffset)
> return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
> }
>
> +static int _fdt_string_eq(const void *fdt, int stroffset,
> + const char *s, int len)
> +{
> + const char *p = fdt_string(fdt, stroffset);
> +
> + return (strlen(p) == len) && (memcmp(p, s, len) == 0);
> +}
> +
> int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
> {
> FDT_CHECK_HEADER(fdt);
> @@ -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;
> diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
> index 8e7ec4c..24437df 100644
> --- a/scripts/dtc/libfdt/fdt_rw.c
> +++ b/scripts/dtc/libfdt/fdt_rw.c
> @@ -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)) {
> diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
> index 698329e..55ebebf 100644
> --- a/scripts/dtc/libfdt/fdt_sw.c
> +++ b/scripts/dtc/libfdt/fdt_sw.c
> @@ -70,7 +70,7 @@ static int _fdt_sw_check_header(void *fdt)
> return err; \
> }
>
> -static void *_fdt_grab_space(void *fdt, int len)
> +static void *_fdt_grab_space(void *fdt, size_t len)
> {
> int offset = fdt_size_dt_struct(fdt);
> int spaceleft;
> @@ -82,7 +82,7 @@ static void *_fdt_grab_space(void *fdt, int len)
> return NULL;
>
> fdt_set_size_dt_struct(fdt, offset + len);
> - return fdt_offset_ptr_w(fdt, offset, len);
> + return _fdt_offset_ptr_w(fdt, offset);
> }
>
> int fdt_create(void *buf, int bufsize)
> @@ -237,18 +237,17 @@ int fdt_finish(void *fdt)
> while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
> if (tag == FDT_PROP) {
> struct fdt_property *prop =
> - fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
> + _fdt_offset_ptr_w(fdt, offset);
> int nameoff;
>
> - if (! prop)
> - return -FDT_ERR_BADSTRUCTURE;
> -
> nameoff = fdt32_to_cpu(prop->nameoff);
> nameoff += fdt_size_dt_strings(fdt);
> prop->nameoff = cpu_to_fdt32(nameoff);
> }
> offset = nextoffset;
> }
> + if (nextoffset < 0)
> + return nextoffset;
>
> /* Finally, adjust the header */
> fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
> diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c
> index a4652c6..6025fa1 100644
> --- a/scripts/dtc/libfdt/fdt_wip.c
> +++ b/scripts/dtc/libfdt/fdt_wip.c
> @@ -94,41 +94,14 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
> return 0;
> }
>
> -int _fdt_node_end_offset(void *fdt, int nodeoffset)
> +int _fdt_node_end_offset(void *fdt, int offset)
> {
> - int level = 0;
> - uint32_t tag;
> - int offset, nextoffset;
> -
> - tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
> - if (tag != FDT_BEGIN_NODE)
> - return -FDT_ERR_BADOFFSET;
> - do {
> - offset = nextoffset;
> - tag = fdt_next_tag(fdt, offset, &nextoffset);
> -
> - switch (tag) {
> - case FDT_END:
> - return offset;
> -
> - case FDT_BEGIN_NODE:
> - level++;
> - break;
> -
> - case FDT_END_NODE:
> - level--;
> - break;
> -
> - case FDT_PROP:
> - case FDT_NOP:
> - break;
> -
> - default:
> - return -FDT_ERR_BADSTRUCTURE;
> - }
> - } while (level >= 0);
> -
> - return nextoffset;
> + int depth = 0;
> +
> + while ((offset >= 0) && (depth >= 0))
> + offset = fdt_next_node(fdt, offset, &depth);
> +
> + return offset;
> }
>
> int fdt_nop_node(void *fdt, int nodeoffset)
> diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
> index ff6246f..73f4975 100644
> --- a/scripts/dtc/libfdt/libfdt.h
> +++ b/scripts/dtc/libfdt/libfdt.h
> @@ -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
> @@ -122,7 +122,7 @@
> /* Low-level functions (you probably don't need these) */
> /**********************************************************************/
>
> -const void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
> +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
> static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
> {
> return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
> @@ -156,7 +156,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth);
> #define __fdt_set_hdr(name) \
> static inline void fdt_set_##name(void *fdt, uint32_t val) \
> { \
> - struct fdt_header *fdth = fdt; \
> + struct fdt_header *fdth = (struct fdt_header*)fdt; \
> fdth->name = cpu_to_fdt32(val); \
> }
> __fdt_set_hdr(magic);
> @@ -343,6 +343,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
> diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
> index 449bf60..213d7fb 100644
> --- a/scripts/dtc/libfdt/libfdt_env.h
> +++ b/scripts/dtc/libfdt/libfdt_env.h
> @@ -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 */
> diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
> index 46eb93e..381133b 100644
> --- a/scripts/dtc/libfdt/libfdt_internal.h
> +++ b/scripts/dtc/libfdt/libfdt_internal.h
> @@ -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);
>
> diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
> index 26d0e1e..b61465f 100644
> --- a/scripts/dtc/livetree.c
> +++ b/scripts/dtc/livetree.c
> @@ -29,16 +29,27 @@ void add_label(struct label **labels, char *label)
> struct label *new;
>
> /* Make sure the label isn't already there */
> - for_each_label(*labels, new)
> - if (streq(new->label, label))
> + for_each_label_withdel(*labels, new)
> + if (streq(new->label, label)) {
> + new->deleted = 0;
> return;
> + }
>
> new = xmalloc(sizeof(*new));
> + memset(new, 0, sizeof(*new));
> new->label = label;
> new->next = *labels;
> *labels = new;
> }
>
> +void delete_labels(struct label **labels)
> +{
> + struct label *label;
> +
> + for_each_label(*labels, label)
> + label->deleted = 1;
> +}
> +
> struct property *build_property(char *name, struct data val)
> {
> struct property *new = xmalloc(sizeof(*new));
> @@ -51,6 +62,18 @@ struct property *build_property(char *name, struct data val)
> return new;
> }
>
> +struct property *build_property_delete(char *name)
> +{
> + struct property *new = xmalloc(sizeof(*new));
> +
> + memset(new, 0, sizeof(*new));
> +
> + new->name = name;
> + new->deleted = 1;
> +
> + return new;
> +}
> +
> struct property *chain_property(struct property *first, struct property *list)
> {
> assert(first->next == NULL);
> @@ -91,6 +114,17 @@ struct node *build_node(struct property *proplist, struct node *children)
> return new;
> }
>
> +struct node *build_node_delete(void)
> +{
> + struct node *new = xmalloc(sizeof(*new));
> +
> + memset(new, 0, sizeof(*new));
> +
> + new->deleted = 1;
> +
> + return new;
> +}
> +
> struct node *name_node(struct node *node, char *name)
> {
> assert(node->name == NULL);
> @@ -106,8 +140,10 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
> struct node *new_child, *old_child;
> struct label *l;
>
> + old_node->deleted = 0;
> +
> /* Add new node labels to old node */
> - for_each_label(new_node->labels, l)
> + for_each_label_withdel(new_node->labels, l)
> add_label(&old_node->labels, l->label);
>
> /* Move properties from the new node to the old node. If there
> @@ -118,14 +154,21 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
> new_node->proplist = new_prop->next;
> new_prop->next = NULL;
>
> + if (new_prop->deleted) {
> + delete_property_by_name(old_node, new_prop->name);
> + free(new_prop);
> + continue;
> + }
> +
> /* Look for a collision, set new value if there is */
> - for_each_property(old_node, old_prop) {
> + for_each_property_withdel(old_node, old_prop) {
> if (streq(old_prop->name, new_prop->name)) {
> /* Add new labels to old property */
> - for_each_label(new_prop->labels, l)
> + for_each_label_withdel(new_prop->labels, l)
> add_label(&old_prop->labels, l->label);
>
> old_prop->val = new_prop->val;
> + old_prop->deleted = 0;
> free(new_prop);
> new_prop = NULL;
> break;
> @@ -146,8 +189,14 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
> new_child->parent = NULL;
> new_child->next_sibling = NULL;
>
> + if (new_child->deleted) {
> + delete_node_by_name(old_node, new_child->name);
> + free(new_child);
> + continue;
> + }
> +
> /* Search for a collision. Merge if there is */
> - for_each_child(old_node, old_child) {
> + for_each_child_withdel(old_node, old_child) {
> if (streq(old_child->name, new_child->name)) {
> merge_nodes(old_child, new_child);
> new_child = NULL;
> @@ -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);
> }
>
> diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c
> index 36a38e9..246ab4b 100644
> --- a/scripts/dtc/srcpos.c
> +++ b/scripts/dtc/srcpos.c
> @@ -24,6 +24,15 @@
> #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;
> +}
> diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h
> index ce980ca..93a2712 100644
> --- a/scripts/dtc/srcpos.h
> +++ b/scripts/dtc/srcpos.h
> @@ -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_ */
> diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c
> index c09aafa..33eeba5 100644
> --- a/scripts/dtc/treesource.c
> +++ b/scripts/dtc/treesource.c
> @@ -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");
> diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
> index d7ac27d..2422c34 100644
> --- a/scripts/dtc/util.c
> +++ b/scripts/dtc/util.c
> @@ -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
> @@ -17,11 +21,18 @@
> * 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;
> +}
> diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h
> index 9cead84..c8eb45d 100644
> --- a/scripts/dtc/util.h
> +++ b/scripts/dtc/util.h
> @@ -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 */
>


2012-10-01 16:13:21

by Stephen Warren

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/01/2012 10:09 AM, Rob Herring wrote:
> On 09/28/2012 04:25 PM, Stephen Warren wrote:
>> From: Stephen Warren <[email protected]>
>>
>> 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 <[email protected]>
>
> Seems dtc doesn't really have a maintainer. Probably makes more sense
> for me to take this unless there are objections.

Will you also take the two kbuild patches I posted that depend on this
(e.g. "kbuild: introduce cmd_dtc_cpp")? I'd assumed that Michal Marek
would take this given the dependencies and that he's take a fair number
of dtc patches recently.

2012-10-01 17:56:33

by Rob Herring

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/01/2012 11:13 AM, Stephen Warren wrote:
> On 10/01/2012 10:09 AM, Rob Herring wrote:
>> On 09/28/2012 04:25 PM, Stephen Warren wrote:
>>> From: Stephen Warren <[email protected]>
>>>
>>> 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 <[email protected]>
>>
>> Seems dtc doesn't really have a maintainer. Probably makes more sense
>> for me to take this unless there are objections.
>
> Will you also take the two kbuild patches I posted that depend on this
> (e.g. "kbuild: introduce cmd_dtc_cpp")? I'd assumed that Michal Marek
> would take this given the dependencies and that he's take a fair number
> of dtc patches recently.

No. I think whether we use the cpp preprocessor or not needs more time
to discuss and some level of agreement. So I don't think it is 3.7 material.

Rob

2012-10-01 18:03:18

by Jon Loeliger

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

>
> Seems dtc doesn't really have a maintainer.

Picking nits, let's be clear on that phraseology:

Seems dtc doesn't really have a maintainer
within the kernel repository.

Over in git.jdl.com land, there is a well established
maintainer for the upstream DTC.

> Probably makes more sense
> for me to take this unless there are objections.

Please, and thank you.

jdl

2012-10-01 18:33:24

by Stephen Warren

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/01/2012 11:56 AM, Rob Herring wrote:
> On 10/01/2012 11:13 AM, Stephen Warren wrote:
>> On 10/01/2012 10:09 AM, Rob Herring wrote:
>>> On 09/28/2012 04:25 PM, Stephen Warren wrote:
>>>> From: Stephen Warren <[email protected]>
>>>>
>>>> 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 <[email protected]>
>>>
>>> Seems dtc doesn't really have a maintainer. Probably makes more sense
>>> for me to take this unless there are objections.
>>
>> Will you also take the two kbuild patches I posted that depend on this
>> (e.g. "kbuild: introduce cmd_dtc_cpp")? I'd assumed that Michal Marek
>> would take this given the dependencies and that he's take a fair number
>> of dtc patches recently.
>
> No. I think whether we use the cpp preprocessor or not needs more time
> to discuss and some level of agreement. So I don't think it is 3.7 material.

Oh, you were planning on taking the dtc update into 3.7? I had assumed
you meant for 3.8. There wouldn't be any dependencies if you take the
dtc update now, so it'd probably be fine.

What more do you think needs discussion re: dtc+cpp?

2012-10-01 18:39:20

by Jon Loeliger

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

>
> What more do you think needs discussion re: dtc+cpp?

How not to abuse the ever-loving shit out of it? :-)

jdl

2012-10-09 21:16:54

by Stephen Warren

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>>
>> What more do you think needs discussion re: dtc+cpp?
>
> How not to abuse the ever-loving shit out of it? :-)

Perhaps we can just handle this through the regular patch review
process; I think it may be difficult to define and agree upon exactly
what "abuse" means ahead of time, but it's probably going to be easy
enough to recognize it when one sees it?

I imagine the most common usage will simply be a bunch of:

#define TEGRA_GPIO_PB0 32
#define TEGRA_GPIO_INT_LEVEL_LOW 8

/ {
xxx {
interrupts = <TEGRA_GPIO_PB0 TEGRA_GPIO_INT_LEVEL_LOW>;

and similarly, simple math:

something = <((FOO << XXX_SHIFT) | (BAR << YYY_SHIFT))>;

2012-10-09 23:21:25

by Mitch Bradley

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/9/2012 11:16 AM, Stephen Warren wrote:
> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>>>
>>> What more do you think needs discussion re: dtc+cpp?
>>
>> How not to abuse the ever-loving shit out of it? :-)
>
> Perhaps we can just handle this through the regular patch review
> process; I think it may be difficult to define and agree upon exactly
> what "abuse" means ahead of time, but it's probably going to be easy
> enough to recognize it when one sees it?


One of the ways it could get out of hand would be via "include
dependency hell". People will be tempted to reuse existing .h files
containing pin definitions, which, if history is a guide, will end up
depending on all sorts of other .h files.

Another problem I often face with symbolic names is the difficulty of
figuring out what the numerical values really are (for debugging),
especially when .h files are in different subtrees from the files that
use the definitions, and when they use multiple macro levels and fancy
features like concatenation. Sometimes I think it's clearer just to
write the number and use a comment to say what it is.


>
> I imagine the most common usage will simply be a bunch of:
>
> #define TEGRA_GPIO_PB0 32
> #define TEGRA_GPIO_INT_LEVEL_LOW 8
>
> / {
> xxx {
> interrupts = <TEGRA_GPIO_PB0 TEGRA_GPIO_INT_LEVEL_LOW>;
>
> and similarly, simple math:
>
> something = <((FOO << XXX_SHIFT) | (BAR << YYY_SHIFT))>;
>
> _______________________________________________
> devicetree-discuss mailing list
> [email protected]
> https://lists.ozlabs.org/listinfo/devicetree-discuss
>

2012-10-10 00:04:38

by Scott Wood

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/09/2012 06:20:53 PM, Mitch Bradley wrote:
> On 10/9/2012 11:16 AM, Stephen Warren wrote:
> > On 10/01/2012 12:39 PM, Jon Loeliger wrote:
> >>>
> >>> What more do you think needs discussion re: dtc+cpp?
> >>
> >> How not to abuse the ever-loving shit out of it? :-)
> >
> > Perhaps we can just handle this through the regular patch review
> > process; I think it may be difficult to define and agree upon
> exactly
> > what "abuse" means ahead of time, but it's probably going to be easy
> > enough to recognize it when one sees it?
>
>
> One of the ways it could get out of hand would be via "include
> dependency hell". People will be tempted to reuse existing .h files
> containing pin definitions, which, if history is a guide, will end up
> depending on all sorts of other .h files.
>
> Another problem I often face with symbolic names is the difficulty of
> figuring out what the numerical values really are (for debugging),
> especially when .h files are in different subtrees from the files that
> use the definitions, and when they use multiple macro levels and fancy
> features like concatenation. Sometimes I think it's clearer just to
> write the number and use a comment to say what it is.

Both comments apply just as well to ordinary C code, and I don't think
anyone would seriously suggest just using comments instead for C code.

Is there a way to ask CPP to evaluate a macro in the context of the
input file, rather than produce normal output? If not, I guess you
could make a tool that creates a wrapper file that includes the main
file and then evaluates the symbol you want.

-Scott

2012-10-10 04:43:57

by Warner Losh

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc


On Oct 9, 2012, at 6:04 PM, Scott Wood wrote:

> On 10/09/2012 06:20:53 PM, Mitch Bradley wrote:
>> On 10/9/2012 11:16 AM, Stephen Warren wrote:
>> > On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>> >>>
>> >>> What more do you think needs discussion re: dtc+cpp?
>> >>
>> >> How not to abuse the ever-loving shit out of it? :-)
>> >
>> > Perhaps we can just handle this through the regular patch review
>> > process; I think it may be difficult to define and agree upon exactly
>> > what "abuse" means ahead of time, but it's probably going to be easy
>> > enough to recognize it when one sees it?
>> One of the ways it could get out of hand would be via "include
>> dependency hell". People will be tempted to reuse existing .h files
>> containing pin definitions, which, if history is a guide, will end up
>> depending on all sorts of other .h files.
>> Another problem I often face with symbolic names is the difficulty of
>> figuring out what the numerical values really are (for debugging),
>> especially when .h files are in different subtrees from the files that
>> use the definitions, and when they use multiple macro levels and fancy
>> features like concatenation. Sometimes I think it's clearer just to
>> write the number and use a comment to say what it is.
>
> Both comments apply just as well to ordinary C code, and I don't think anyone would seriously suggest just using comments instead for C code.

.h files include both structs and defines, which are fine for ordinary C code, but problematic in this context.

> Is there a way to ask CPP to evaluate a macro in the context of the input file, rather than produce normal output? If not, I guess you could make a tool that creates a wrapper file that includes the main file and then evaluates the symbol you want.

Not in the standard CPP, but perhaps you could scan the .dts file for all the values you need, and have it output the right values to use.

Warner-

2012-10-10 09:11:05

by David Gibson

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On Tue, Oct 09, 2012 at 10:43:50PM -0600, Warner Losh wrote:
>
> On Oct 9, 2012, at 6:04 PM, Scott Wood wrote:
>
> > On 10/09/2012 06:20:53 PM, Mitch Bradley wrote:
> >> On 10/9/2012 11:16 AM, Stephen Warren wrote:
> >> > On 10/01/2012 12:39 PM, Jon Loeliger wrote:
> >> >>>
> >> >>> What more do you think needs discussion re: dtc+cpp?
> >> >>
> >> >> How not to abuse the ever-loving shit out of it? :-)
> >> >
> >> > Perhaps we can just handle this through the regular patch review
> >> > process; I think it may be difficult to define and agree upon exactly
> >> > what "abuse" means ahead of time, but it's probably going to be easy
> >> > enough to recognize it when one sees it?
> >> One of the ways it could get out of hand would be via "include
> >> dependency hell". People will be tempted to reuse existing .h files
> >> containing pin definitions, which, if history is a guide, will end up
> >> depending on all sorts of other .h files.
> >> Another problem I often face with symbolic names is the difficulty of
> >> figuring out what the numerical values really are (for debugging),
> >> especially when .h files are in different subtrees from the files that
> >> use the definitions, and when they use multiple macro levels and fancy
> >> features like concatenation. Sometimes I think it's clearer just to
> >> write the number and use a comment to say what it is.
> >
> > Both comments apply just as well to ordinary C code, and I don't think anyone would seriously suggest just using comments instead for C code.
>
> .h files include both structs and defines, which are fine for
> ordinary C code, but problematic in this context.

Right, cpp should be invoked with similar options to the way it's done
for asm files which have the same problem. I'm not sure if the
current patch does so.

--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson

2012-10-10 15:33:36

by Rob Herring

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/10/2012 10:16 AM, Stephen Warren wrote:
> On 10/10/2012 01:24 AM, David Gibson wrote:
>> On Tue, Oct 09, 2012 at 10:43:50PM -0600, Warner Losh wrote:
>>>
>>> On Oct 9, 2012, at 6:04 PM, Scott Wood wrote:
>>>
>>>> On 10/09/2012 06:20:53 PM, Mitch Bradley wrote:
>>>>> On 10/9/2012 11:16 AM, Stephen Warren wrote:
>>>>>> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>>>>>>>>
>>>>>>>> What more do you think needs discussion re: dtc+cpp?
>>>>>>>
>>>>>>> How not to abuse the ever-loving shit out of it? :-)
>>>>>>
>>>>>> Perhaps we can just handle this through the regular patch review
>>>>>> process; I think it may be difficult to define and agree upon exactly
>>>>>> what "abuse" means ahead of time, but it's probably going to be easy
>>>>>> enough to recognize it when one sees it?
>>>>> One of the ways it could get out of hand would be via "include
>>>>> dependency hell". People will be tempted to reuse existing .h files
>>>>> containing pin definitions, which, if history is a guide, will end up
>>>>> depending on all sorts of other .h files.
>>>>> Another problem I often face with symbolic names is the difficulty of
>>>>> figuring out what the numerical values really are (for debugging),
>>>>> especially when .h files are in different subtrees from the files that
>>>>> use the definitions, and when they use multiple macro levels and fancy
>>>>> features like concatenation. Sometimes I think it's clearer just to
>>>>> write the number and use a comment to say what it is.
>>>>
>>>> Both comments apply just as well to ordinary C code, and I don't think anyone would seriously suggest just using comments instead for C code.
>>>
>>> .h files include both structs and defines, which are fine for
>>> ordinary C code, but problematic in this context.
>>
>> Right, cpp should be invoked with similar options to the way it's done
>> for asm files which have the same problem. I'm not sure if the
>> current patch does so.
>
> That's probably a reasonable idea, although I imagined that people would
> actually split out the portions of any header file they wanted to use
> with dtc, so that any headers included by *.dts would only include
> #defines. Those headers could be used by both dtc and other .h files (or
> .c files).

Used by what other files? kernel files? We ultimately want to split out
dts files from the kernel, so whatever we add needs to be self
contained. I don't see this as a huge issue though because the whole
point of the DT data is to move that information out of the kernel. If
it is needed in both places, then something is wrong.

Rob

2012-10-10 15:16:40

by Stephen Warren

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/10/2012 01:24 AM, David Gibson wrote:
> On Tue, Oct 09, 2012 at 10:43:50PM -0600, Warner Losh wrote:
>>
>> On Oct 9, 2012, at 6:04 PM, Scott Wood wrote:
>>
>>> On 10/09/2012 06:20:53 PM, Mitch Bradley wrote:
>>>> On 10/9/2012 11:16 AM, Stephen Warren wrote:
>>>>> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>>>>>>>
>>>>>>> What more do you think needs discussion re: dtc+cpp?
>>>>>>
>>>>>> How not to abuse the ever-loving shit out of it? :-)
>>>>>
>>>>> Perhaps we can just handle this through the regular patch review
>>>>> process; I think it may be difficult to define and agree upon exactly
>>>>> what "abuse" means ahead of time, but it's probably going to be easy
>>>>> enough to recognize it when one sees it?
>>>> One of the ways it could get out of hand would be via "include
>>>> dependency hell". People will be tempted to reuse existing .h files
>>>> containing pin definitions, which, if history is a guide, will end up
>>>> depending on all sorts of other .h files.
>>>> Another problem I often face with symbolic names is the difficulty of
>>>> figuring out what the numerical values really are (for debugging),
>>>> especially when .h files are in different subtrees from the files that
>>>> use the definitions, and when they use multiple macro levels and fancy
>>>> features like concatenation. Sometimes I think it's clearer just to
>>>> write the number and use a comment to say what it is.
>>>
>>> Both comments apply just as well to ordinary C code, and I don't think anyone would seriously suggest just using comments instead for C code.
>>
>> .h files include both structs and defines, which are fine for
>> ordinary C code, but problematic in this context.
>
> Right, cpp should be invoked with similar options to the way it's done
> for asm files which have the same problem. I'm not sure if the
> current patch does so.

That's probably a reasonable idea, although I imagined that people would
actually split out the portions of any header file they wanted to use
with dtc, so that any headers included by *.dts would only include
#defines. Those headers could be used by both dtc and other .h files (or
.c files).

2012-10-10 16:10:08

by Scott Wood

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/10/2012 10:15:17 AM, Stephen Warren wrote:
> On 10/09/2012 06:04 PM, Scott Wood wrote:
> > On 10/09/2012 06:20:53 PM, Mitch Bradley wrote:
> >> On 10/9/2012 11:16 AM, Stephen Warren wrote:
> >> > On 10/01/2012 12:39 PM, Jon Loeliger wrote:
> >> >>>
> >> >>> What more do you think needs discussion re: dtc+cpp?
> >> >>
> >> >> How not to abuse the ever-loving shit out of it? :-)
> >> >
> >> > Perhaps we can just handle this through the regular patch review
> >> > process; I think it may be difficult to define and agree upon
> exactly
> >> > what "abuse" means ahead of time, but it's probably going to be
> easy
> >> > enough to recognize it when one sees it?
> >>
> >>
> >> One of the ways it could get out of hand would be via "include
> >> dependency hell". People will be tempted to reuse existing .h
> files
> >> containing pin definitions, which, if history is a guide, will end
> up
> >> depending on all sorts of other .h files.
> >>
> >> Another problem I often face with symbolic names is the difficulty
> of
> >> figuring out what the numerical values really are (for debugging),
> >> especially when .h files are in different subtrees from the files
> that
> >> use the definitions, and when they use multiple macro levels and
> fancy
> >> features like concatenation. Sometimes I think it's clearer just
> to
> >> write the number and use a comment to say what it is.
> >
> > Both comments apply just as well to ordinary C code, and I don't
> think
> > anyone would seriously suggest just using comments instead for C
> code.
> >
> > Is there a way to ask CPP to evaluate a macro in the context of the
> > input file, rather than produce normal output? If not, I guess you
> > could make a tool that creates a wrapper file that includes the main
> > file and then evaluates the symbol you want.
>
> I'm not sure what "evaluate a macro in the context of the input file"
> means. Macros are obviously already evaluated based on the current set
> of macros defined by the file that's been processed or those it
> included. Do you mean only allowing the use of macros in the current
> file and not included files? What exactly would the wrapper you
> mentioned do?

I just meant a way for a developer to quickly ask the preprocessor what
a particular macro expands to, rather than try to figure it out
manually. I was not suggesting any change to normal operation.

-Scott

2012-10-10 17:09:32

by Rob Herring

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/09/2012 04:16 PM, Stephen Warren wrote:
> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>>>
>>> What more do you think needs discussion re: dtc+cpp?
>>
>> How not to abuse the ever-loving shit out of it? :-)
>
> Perhaps we can just handle this through the regular patch review
> process; I think it may be difficult to define and agree upon exactly
> what "abuse" means ahead of time, but it's probably going to be easy
> enough to recognize it when one sees it?

Rather than repeating things over and over in reviews, we should
document at least rules we can easily agree on and then add to it when
people get "creative." Also, I can't keep up with every single binding
review as is, and this could just add another level of complexity to the
review. A few off the top of my head and from the thread discussion:

- Headers must be self contained with no outside (i.e. libc, kernel,
etc.) header dependencies.
- No kernel kconfig option usage
- No gcc built-in define usage
- No unused items (i.e. externs, structs, etc.)
- No macro concatenation
- No macros for strings or property names

Do we further restrict things to say defines are only numbers? One could
start to define complex macros to build the nodes themselves. If each
platform does this slightly differently, it will become difficult to
review and maintain. Then we will be doing dts consolidation. The fact
that we have some fixed structure and each SOC is not free to do things
their own way makes things easier to maintain. You don't have that in
the kernel across platforms. For example, look how register defines and
static mappings or platform device creation are done. They are all
similar, but yet slightly different. That makes doing changes across
platforms more difficult.

> I imagine the most common usage will simply be a bunch of:
>
> #define TEGRA_GPIO_PB0 32
> #define TEGRA_GPIO_INT_LEVEL_LOW 8
>
> / {
> xxx {
> interrupts = <TEGRA_GPIO_PB0 TEGRA_GPIO_INT_LEVEL_LOW>;
>
> and similarly, simple math:
>
> something = <((FOO << XXX_SHIFT) | (BAR << YYY_SHIFT))>;
>

These are all perfectly fine and sane use, but if we don't restrict
things then the next step is this:

#define PROP_SOMETHING(v) (something = <(v)>)

Rob

2012-10-10 16:19:30

by Stephen Warren

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/10/2012 09:33 AM, Rob Herring wrote:
> On 10/10/2012 10:16 AM, Stephen Warren wrote:
>> On 10/10/2012 01:24 AM, David Gibson wrote:
>>> On Tue, Oct 09, 2012 at 10:43:50PM -0600, Warner Losh wrote:
>>>>
>>>> On Oct 9, 2012, at 6:04 PM, Scott Wood wrote:
>>>>
>>>>> On 10/09/2012 06:20:53 PM, Mitch Bradley wrote:
>>>>>> On 10/9/2012 11:16 AM, Stephen Warren wrote:
>>>>>>> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>>>>>>>>>
>>>>>>>>> What more do you think needs discussion re: dtc+cpp?
>>>>>>>>
>>>>>>>> How not to abuse the ever-loving shit out of it? :-)
>>>>>>>
>>>>>>> Perhaps we can just handle this through the regular patch review
>>>>>>> process; I think it may be difficult to define and agree upon exactly
>>>>>>> what "abuse" means ahead of time, but it's probably going to be easy
>>>>>>> enough to recognize it when one sees it?
>>>>>> One of the ways it could get out of hand would be via "include
>>>>>> dependency hell". People will be tempted to reuse existing .h files
>>>>>> containing pin definitions, which, if history is a guide, will end up
>>>>>> depending on all sorts of other .h files.
>>>>>> Another problem I often face with symbolic names is the difficulty of
>>>>>> figuring out what the numerical values really are (for debugging),
>>>>>> especially when .h files are in different subtrees from the files that
>>>>>> use the definitions, and when they use multiple macro levels and fancy
>>>>>> features like concatenation. Sometimes I think it's clearer just to
>>>>>> write the number and use a comment to say what it is.
>>>>>
>>>>> Both comments apply just as well to ordinary C code, and I don't think anyone would seriously suggest just using comments instead for C code.
>>>>
>>>> .h files include both structs and defines, which are fine for
>>>> ordinary C code, but problematic in this context.
>>>
>>> Right, cpp should be invoked with similar options to the way it's done
>>> for asm files which have the same problem. I'm not sure if the
>>> current patch does so.
>>
>> That's probably a reasonable idea, although I imagined that people would
>> actually split out the portions of any header file they wanted to use
>> with dtc, so that any headers included by *.dts would only include
>> #defines. Those headers could be used by both dtc and other .h files (or
>> .c files).
>
> Used by what other files? kernel files? We ultimately want to split out
> dts files from the kernel, so whatever we add needs to be self
> contained. I don't see this as a huge issue though because the whole
> point of the DT data is to move that information out of the kernel. If
> it is needed in both places, then something is wrong.

One example is the IDs of the GPIOs, e.g.:

#define TEGRA_PIN_VI_GP6_PA0 _GPIO(0)
#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1)
#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2)
#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3)

Those defines are useful to both the .dts files (so named constants can
be used) and the pinctrl driver. By using the same header file, we
guarantee that the .dts files and pinctrl driver use the exact same
naming for the pins; the pin naming/numbering being defined by the DT
binding more than anything else.

It'd be similarly useful to share GPIO or interrupt flag definitions,
etc. etc.

We could do something like we do for dtc today, where there's an
external repository for *.dts (and required *.h), yet those *.h are
duplicated into the kernel tree as needed by drivers.

2012-10-10 14:41:59

by Warner Losh

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc


On Oct 10, 2012, at 1:24 AM, David Gibson wrote:

> On Tue, Oct 09, 2012 at 10:43:50PM -0600, Warner Losh wrote:
>>
>> On Oct 9, 2012, at 6:04 PM, Scott Wood wrote:
>>
>>> On 10/09/2012 06:20:53 PM, Mitch Bradley wrote:
>>>> On 10/9/2012 11:16 AM, Stephen Warren wrote:
>>>>> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>>>>>>>
>>>>>>> What more do you think needs discussion re: dtc+cpp?
>>>>>>
>>>>>> How not to abuse the ever-loving shit out of it? :-)
>>>>>
>>>>> Perhaps we can just handle this through the regular patch review
>>>>> process; I think it may be difficult to define and agree upon exactly
>>>>> what "abuse" means ahead of time, but it's probably going to be easy
>>>>> enough to recognize it when one sees it?
>>>> One of the ways it could get out of hand would be via "include
>>>> dependency hell". People will be tempted to reuse existing .h files
>>>> containing pin definitions, which, if history is a guide, will end up
>>>> depending on all sorts of other .h files.
>>>> Another problem I often face with symbolic names is the difficulty of
>>>> figuring out what the numerical values really are (for debugging),
>>>> especially when .h files are in different subtrees from the files that
>>>> use the definitions, and when they use multiple macro levels and fancy
>>>> features like concatenation. Sometimes I think it's clearer just to
>>>> write the number and use a comment to say what it is.
>>>
>>> Both comments apply just as well to ordinary C code, and I don't think anyone would seriously suggest just using comments instead for C code.
>>
>> .h files include both structs and defines, which are fine for
>> ordinary C code, but problematic in this context.
>
> Right, cpp should be invoked with similar options to the way it's done
> for asm files which have the same problem. I'm not sure if the
> current patch does so.

I know the current dtc code is very careful to license itself in a very agnostic way. Would including files, possibly from the Linux kernel, pose any kind of license issue? Or does the fact that many (but not all) .dts files being apparently licensed GPL already make this a moot point? Or does it not matter since this is an interface and declaration of information, which likely isn't creative enough to receive to copyright protection.... Or is this a can of worms best avoided :)

Warner-

2012-10-10 18:23:43

by Mitch Bradley

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/10/2012 7:09 AM, Rob Herring wrote:
> On 10/09/2012 04:16 PM, Stephen Warren wrote:
>> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>>>>
>>>> What more do you think needs discussion re: dtc+cpp?
>>>
>>> How not to abuse the ever-loving shit out of it? :-)
>>
>> Perhaps we can just handle this through the regular patch review
>> process; I think it may be difficult to define and agree upon exactly
>> what "abuse" means ahead of time, but it's probably going to be easy
>> enough to recognize it when one sees it?
>
> Rather than repeating things over and over in reviews, we should
> document at least rules we can easily agree on and then add to it when
> people get "creative." Also, I can't keep up with every single binding
> review as is, and this could just add another level of complexity to the
> review. A few off the top of my head and from the thread discussion:
>
> - Headers must be self contained with no outside (i.e. libc, kernel,
> etc.) header dependencies.
> - No kernel kconfig option usage
> - No gcc built-in define usage
> - No unused items (i.e. externs, structs, etc.)
> - No macro concatenation
> - No macros for strings or property names

Instead of making a bunch of rules about how you can only use a small
subset of cpp, why not just add a "define name value" command to DTC?

One of the things I like least about C is that the language itself is
incomplete; in order to actually program in C, you have to deal with not
only with the C syntactic structure, but also cpp, with its different
rules, and also make, with fundamentally different linguistic structure,
and then you end up wrapping that in something like KConfig, with yet
another linguistic framework, and the makefile contains embedded shell
commands, which is yet another syntax.

Rather than open Pandora's box by grafting on cpp, why not solve the
actual problem?


>
> Do we further restrict things to say defines are only numbers? One could
> start to define complex macros to build the nodes themselves. If each
> platform does this slightly differently, it will become difficult to
> review and maintain. Then we will be doing dts consolidation. The fact
> that we have some fixed structure and each SOC is not free to do things
> their own way makes things easier to maintain. You don't have that in
> the kernel across platforms. For example, look how register defines and
> static mappings or platform device creation are done. They are all
> similar, but yet slightly different. That makes doing changes across
> platforms more difficult.
>
>> I imagine the most common usage will simply be a bunch of:
>>
>> #define TEGRA_GPIO_PB0 32
>> #define TEGRA_GPIO_INT_LEVEL_LOW 8
>>
>> / {
>> xxx {
>> interrupts = <TEGRA_GPIO_PB0 TEGRA_GPIO_INT_LEVEL_LOW>;
>>
>> and similarly, simple math:
>>
>> something = <((FOO << XXX_SHIFT) | (BAR << YYY_SHIFT))>;
>>
>
> These are all perfectly fine and sane use, but if we don't restrict
> things then the next step is this:
>
> #define PROP_SOMETHING(v) (something = <(v)>)
>
> Rob
> _______________________________________________
> devicetree-discuss mailing list
> [email protected]
> https://lists.ozlabs.org/listinfo/devicetree-discuss
>

2012-10-10 15:15:25

by Stephen Warren

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/09/2012 06:04 PM, Scott Wood wrote:
> On 10/09/2012 06:20:53 PM, Mitch Bradley wrote:
>> On 10/9/2012 11:16 AM, Stephen Warren wrote:
>> > On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>> >>>
>> >>> What more do you think needs discussion re: dtc+cpp?
>> >>
>> >> How not to abuse the ever-loving shit out of it? :-)
>> >
>> > Perhaps we can just handle this through the regular patch review
>> > process; I think it may be difficult to define and agree upon exactly
>> > what "abuse" means ahead of time, but it's probably going to be easy
>> > enough to recognize it when one sees it?
>>
>>
>> One of the ways it could get out of hand would be via "include
>> dependency hell". People will be tempted to reuse existing .h files
>> containing pin definitions, which, if history is a guide, will end up
>> depending on all sorts of other .h files.
>>
>> Another problem I often face with symbolic names is the difficulty of
>> figuring out what the numerical values really are (for debugging),
>> especially when .h files are in different subtrees from the files that
>> use the definitions, and when they use multiple macro levels and fancy
>> features like concatenation. Sometimes I think it's clearer just to
>> write the number and use a comment to say what it is.
>
> Both comments apply just as well to ordinary C code, and I don't think
> anyone would seriously suggest just using comments instead for C code.
>
> Is there a way to ask CPP to evaluate a macro in the context of the
> input file, rather than produce normal output? If not, I guess you
> could make a tool that creates a wrapper file that includes the main
> file and then evaluates the symbol you want.

I'm not sure what "evaluate a macro in the context of the input file"
means. Macros are obviously already evaluated based on the current set
of macros defined by the file that's been processed or those it
included. Do you mean only allowing the use of macros in the current
file and not included files? What exactly would the wrapper you
mentioned do?

2012-10-10 16:22:10

by Stephen Warren

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/10/2012 10:09 AM, Scott Wood wrote:
> On 10/10/2012 10:15:17 AM, Stephen Warren wrote:
>> On 10/09/2012 06:04 PM, Scott Wood wrote:
>> > On 10/09/2012 06:20:53 PM, Mitch Bradley wrote:
>> >> On 10/9/2012 11:16 AM, Stephen Warren wrote:
>> >> > On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>> >> >>>
>> >> >>> What more do you think needs discussion re: dtc+cpp?
>> >> >>
>> >> >> How not to abuse the ever-loving shit out of it? :-)
>> >> >
>> >> > Perhaps we can just handle this through the regular patch review
>> >> > process; I think it may be difficult to define and agree upon
>> exactly
>> >> > what "abuse" means ahead of time, but it's probably going to be easy
>> >> > enough to recognize it when one sees it?
>> >>
>> >>
>> >> One of the ways it could get out of hand would be via "include
>> >> dependency hell". People will be tempted to reuse existing .h files
>> >> containing pin definitions, which, if history is a guide, will end up
>> >> depending on all sorts of other .h files.
>> >>
>> >> Another problem I often face with symbolic names is the difficulty of
>> >> figuring out what the numerical values really are (for debugging),
>> >> especially when .h files are in different subtrees from the files that
>> >> use the definitions, and when they use multiple macro levels and fancy
>> >> features like concatenation. Sometimes I think it's clearer just to
>> >> write the number and use a comment to say what it is.
>> >
>> > Both comments apply just as well to ordinary C code, and I don't think
>> > anyone would seriously suggest just using comments instead for C code.
>> >
>> > Is there a way to ask CPP to evaluate a macro in the context of the
>> > input file, rather than produce normal output? If not, I guess you
>> > could make a tool that creates a wrapper file that includes the main
>> > file and then evaluates the symbol you want.
>>
>> I'm not sure what "evaluate a macro in the context of the input file"
>> means. Macros are obviously already evaluated based on the current set
>> of macros defined by the file that's been processed or those it
>> included. Do you mean only allowing the use of macros in the current
>> file and not included files? What exactly would the wrapper you
>> mentioned do?
>
> I just meant a way for a developer to quickly ask the preprocessor what
> a particular macro expands to, rather than try to figure it out
> manually. I was not suggesting any change to normal operation.

Oh right. Well, the patch I proposed to the kernel was basically:

%.dtb: %.dtsp
cpp -E $< | dtc -o $@ -

A developer could run the same cpp -E command to find that out, or that
build rule could instead save the intermediate result rather than just
piping it, so you could just go read the file.

2012-10-10 17:19:01

by Rob Herring

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/10/2012 11:19 AM, Stephen Warren wrote:
> On 10/10/2012 09:33 AM, Rob Herring wrote:
>> On 10/10/2012 10:16 AM, Stephen Warren wrote:
>>> On 10/10/2012 01:24 AM, David Gibson wrote:
>>>> On Tue, Oct 09, 2012 at 10:43:50PM -0600, Warner Losh wrote:
>>>>>
>>>>> On Oct 9, 2012, at 6:04 PM, Scott Wood wrote:
>>>>>
>>>>>> On 10/09/2012 06:20:53 PM, Mitch Bradley wrote:
>>>>>>> On 10/9/2012 11:16 AM, Stephen Warren wrote:
>>>>>>>> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>>>>>>>>>>
>>>>>>>>>> What more do you think needs discussion re: dtc+cpp?
>>>>>>>>>
>>>>>>>>> How not to abuse the ever-loving shit out of it? :-)
>>>>>>>>
>>>>>>>> Perhaps we can just handle this through the regular patch review
>>>>>>>> process; I think it may be difficult to define and agree upon exactly
>>>>>>>> what "abuse" means ahead of time, but it's probably going to be easy
>>>>>>>> enough to recognize it when one sees it?
>>>>>>> One of the ways it could get out of hand would be via "include
>>>>>>> dependency hell". People will be tempted to reuse existing .h files
>>>>>>> containing pin definitions, which, if history is a guide, will end up
>>>>>>> depending on all sorts of other .h files.
>>>>>>> Another problem I often face with symbolic names is the difficulty of
>>>>>>> figuring out what the numerical values really are (for debugging),
>>>>>>> especially when .h files are in different subtrees from the files that
>>>>>>> use the definitions, and when they use multiple macro levels and fancy
>>>>>>> features like concatenation. Sometimes I think it's clearer just to
>>>>>>> write the number and use a comment to say what it is.
>>>>>>
>>>>>> Both comments apply just as well to ordinary C code, and I don't think anyone would seriously suggest just using comments instead for C code.
>>>>>
>>>>> .h files include both structs and defines, which are fine for
>>>>> ordinary C code, but problematic in this context.
>>>>
>>>> Right, cpp should be invoked with similar options to the way it's done
>>>> for asm files which have the same problem. I'm not sure if the
>>>> current patch does so.
>>>
>>> That's probably a reasonable idea, although I imagined that people would
>>> actually split out the portions of any header file they wanted to use
>>> with dtc, so that any headers included by *.dts would only include
>>> #defines. Those headers could be used by both dtc and other .h files (or
>>> .c files).
>>
>> Used by what other files? kernel files? We ultimately want to split out
>> dts files from the kernel, so whatever we add needs to be self
>> contained. I don't see this as a huge issue though because the whole
>> point of the DT data is to move that information out of the kernel. If
>> it is needed in both places, then something is wrong.
>
> One example is the IDs of the GPIOs, e.g.:
>
> #define TEGRA_PIN_VI_GP6_PA0 _GPIO(0)
> #define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1)
> #define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2)
> #define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3)
>
> Those defines are useful to both the .dts files (so named constants can
> be used) and the pinctrl driver. By using the same header file, we
> guarantee that the .dts files and pinctrl driver use the exact same
> naming for the pins; the pin naming/numbering being defined by the DT
> binding more than anything else.

If pinctrl needs to get a matching name, then it should get it from the
dtb. We should not have 2 sources of data. That is just broken.

>
> It'd be similarly useful to share GPIO or interrupt flag definitions,
> etc. etc.
>
> We could do something like we do for dtc today, where there's an
> external repository for *.dts (and required *.h), yet those *.h are
> duplicated into the kernel tree as needed by drivers.

So as long as we only need to sync up about once a year that's fine
because we have yet to prove that doing it frequently for dtc will be
easy and painless.

I'd like fewer things to copy around, not more. If you have some
self-contained platform defines to copy, then it is your problem.

Rob

2012-10-10 18:40:18

by Stephen Warren

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/10/2012 11:09 AM, Rob Herring wrote:
> On 10/09/2012 04:16 PM, Stephen Warren wrote:
>> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>>>>
>>>> What more do you think needs discussion re: dtc+cpp?
>>>
>>> How not to abuse the ever-loving shit out of it? :-)
>>
>> Perhaps we can just handle this through the regular patch review
>> process; I think it may be difficult to define and agree upon exactly
>> what "abuse" means ahead of time, but it's probably going to be easy
>> enough to recognize it when one sees it?
>
> Rather than repeating things over and over in reviews, we should
> document at least rules we can easily agree on and then add to it when
> people get "creative." Also, I can't keep up with every single binding
> review as is, and this could just add another level of complexity to the
> review. A few off the top of my head and from the thread discussion:
>
> - Headers must be self contained with no outside (i.e. libc, kernel,
> etc.) header dependencies.
> - No kernel kconfig option usage
> - No gcc built-in define usage
> - No unused items (i.e. externs, structs, etc.)

> - No macro concatenation

That seems to be potentially a very useful feature; I have no idea why
we would ban that; it isn't banned in C code in the kernel is it?

> - No macros for strings or property names

Property names I can understand. Property values - I can perhaps see a
use-case for...

2012-10-10 18:42:22

by Stephen Warren

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/10/2012 11:18 AM, Rob Herring wrote:
> On 10/10/2012 11:19 AM, Stephen Warren wrote:
>> On 10/10/2012 09:33 AM, Rob Herring wrote:
>>> On 10/10/2012 10:16 AM, Stephen Warren wrote:
>>>> On 10/10/2012 01:24 AM, David Gibson wrote:
>>>>> On Tue, Oct 09, 2012 at 10:43:50PM -0600, Warner Losh wrote:
>>>>>>
>>>>>> On Oct 9, 2012, at 6:04 PM, Scott Wood wrote:
>>>>>>
>>>>>>> On 10/09/2012 06:20:53 PM, Mitch Bradley wrote:
>>>>>>>> On 10/9/2012 11:16 AM, Stephen Warren wrote:
>>>>>>>>> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>>>>>>>>>>>
>>>>>>>>>>> What more do you think needs discussion re: dtc+cpp?
>>>>>>>>>>
>>>>>>>>>> How not to abuse the ever-loving shit out of it? :-)
>>>>>>>>>
>>>>>>>>> Perhaps we can just handle this through the regular patch review
>>>>>>>>> process; I think it may be difficult to define and agree upon exactly
>>>>>>>>> what "abuse" means ahead of time, but it's probably going to be easy
>>>>>>>>> enough to recognize it when one sees it?
>>>>>>>> One of the ways it could get out of hand would be via "include
>>>>>>>> dependency hell". People will be tempted to reuse existing .h files
>>>>>>>> containing pin definitions, which, if history is a guide, will end up
>>>>>>>> depending on all sorts of other .h files.
>>>>>>>> Another problem I often face with symbolic names is the difficulty of
>>>>>>>> figuring out what the numerical values really are (for debugging),
>>>>>>>> especially when .h files are in different subtrees from the files that
>>>>>>>> use the definitions, and when they use multiple macro levels and fancy
>>>>>>>> features like concatenation. Sometimes I think it's clearer just to
>>>>>>>> write the number and use a comment to say what it is.
>>>>>>>
>>>>>>> Both comments apply just as well to ordinary C code, and I don't think anyone would seriously suggest just using comments instead for C code.
>>>>>>
>>>>>> .h files include both structs and defines, which are fine for
>>>>>> ordinary C code, but problematic in this context.
>>>>>
>>>>> Right, cpp should be invoked with similar options to the way it's done
>>>>> for asm files which have the same problem. I'm not sure if the
>>>>> current patch does so.
>>>>
>>>> That's probably a reasonable idea, although I imagined that people would
>>>> actually split out the portions of any header file they wanted to use
>>>> with dtc, so that any headers included by *.dts would only include
>>>> #defines. Those headers could be used by both dtc and other .h files (or
>>>> .c files).
>>>
>>> Used by what other files? kernel files? We ultimately want to split out
>>> dts files from the kernel, so whatever we add needs to be self
>>> contained. I don't see this as a huge issue though because the whole
>>> point of the DT data is to move that information out of the kernel. If
>>> it is needed in both places, then something is wrong.
>>
>> One example is the IDs of the GPIOs, e.g.:
>>
>> #define TEGRA_PIN_VI_GP6_PA0 _GPIO(0)
>> #define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1)
>> #define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2)
>> #define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3)
>>
>> Those defines are useful to both the .dts files (so named constants can
>> be used) and the pinctrl driver. By using the same header file, we
>> guarantee that the .dts files and pinctrl driver use the exact same
>> naming for the pins; the pin naming/numbering being defined by the DT
>> binding more than anything else.
>
> If pinctrl needs to get a matching name, then it should get it from the
> dtb. We should not have 2 sources of data. That is just broken.

Why? The data is static and there's zero need for it to be in the DTB.
We've been over this already many times.

This is just like /any/ other header file usage. Something defines the
legal values. Various things need to use them. So, we define the values
in a header file, and both *.dts and *.c include them.

2012-10-10 18:45:47

by Stephen Warren

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/10/2012 12:23 PM, Mitch Bradley wrote:
> On 10/10/2012 7:09 AM, Rob Herring wrote:
>> On 10/09/2012 04:16 PM, Stephen Warren wrote:
>>> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>>>>>
>>>>> What more do you think needs discussion re: dtc+cpp?
>>>>
>>>> How not to abuse the ever-loving shit out of it? :-)
>>>
>>> Perhaps we can just handle this through the regular patch review
>>> process; I think it may be difficult to define and agree upon exactly
>>> what "abuse" means ahead of time, but it's probably going to be easy
>>> enough to recognize it when one sees it?
>>
>> Rather than repeating things over and over in reviews, we should
>> document at least rules we can easily agree on and then add to it when
>> people get "creative." Also, I can't keep up with every single binding
>> review as is, and this could just add another level of complexity to the
>> review. A few off the top of my head and from the thread discussion:
>>
>> - Headers must be self contained with no outside (i.e. libc, kernel,
>> etc.) header dependencies.
>> - No kernel kconfig option usage
>> - No gcc built-in define usage
>> - No unused items (i.e. externs, structs, etc.)
>> - No macro concatenation
>> - No macros for strings or property names
>
> Instead of making a bunch of rules about how you can only use a small
> subset of cpp, why not just add a "define name value" command to DTC?

I implemented a patch to do exactly that, and it was rejected because it
only solved part of the problem (named constants) and not the reset (a
completely generic macro language/... within dtc). The argument was that
defining just the named constant syntax on its own without knowing what
the unspecified future macro language will look like might result in the
named constant syntax not fitting into it.

That all said, I now think that using cpp is actually a much better
solution that adding yet more dtc-specific syntax. The *huge* benefit
here is that it allows you to share .h files between *.dts and C code,
so you don't have to write out the same set of #defines once in dtc
syntax and once in cpp syntax.

2012-10-10 18:53:04

by Mitch Bradley

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/10/2012 8:40 AM, Stephen Warren wrote:
> On 10/10/2012 11:09 AM, Rob Herring wrote:
>> On 10/09/2012 04:16 PM, Stephen Warren wrote:
>>> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>>>>>
>>>>> What more do you think needs discussion re: dtc+cpp?
>>>>
>>>> How not to abuse the ever-loving shit out of it? :-)
>>>
>>> Perhaps we can just handle this through the regular patch review
>>> process; I think it may be difficult to define and agree upon exactly
>>> what "abuse" means ahead of time, but it's probably going to be easy
>>> enough to recognize it when one sees it?
>>
>> Rather than repeating things over and over in reviews, we should
>> document at least rules we can easily agree on and then add to it when
>> people get "creative." Also, I can't keep up with every single binding
>> review as is, and this could just add another level of complexity to the
>> review. A few off the top of my head and from the thread discussion:
>>
>> - Headers must be self contained with no outside (i.e. libc, kernel,
>> etc.) header dependencies.
>> - No kernel kconfig option usage
>> - No gcc built-in define usage
>> - No unused items (i.e. externs, structs, etc.)
>
>> - No macro concatenation
>
> That seems to be potentially a very useful feature; I have no idea why
> we would ban that; it isn't banned in C code in the kernel is it?

It's used in the kernel. It is useful, but it has an unexpected side
effect that can be extremely annoying - it can make it extremely
difficult to find a definition with grep. All the grep hits will be for
the fully-expanded uses of a symbol, while the definition is "hidden" by
virtue of being synthesized by concatenation.

Maybe it's not a big deal in a small project, but in a code base the
size of the Linux kernel, where you don't know a priori where something
is defined, it can make you want to tear your hair out.

>
>> - No macros for strings or property names
>
> Property names I can understand. Property values - I can perhaps see a
> use-case for...
>
> _______________________________________________
> devicetree-discuss mailing list
> [email protected]
> https://lists.ozlabs.org/listinfo/devicetree-discuss
>

2012-10-10 18:56:28

by Mitch Bradley

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/10/2012 8:45 AM, Stephen Warren wrote:
> On 10/10/2012 12:23 PM, Mitch Bradley wrote:
>> On 10/10/2012 7:09 AM, Rob Herring wrote:
>>> On 10/09/2012 04:16 PM, Stephen Warren wrote:
>>>> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
>>>>>>
>>>>>> What more do you think needs discussion re: dtc+cpp?
>>>>>
>>>>> How not to abuse the ever-loving shit out of it? :-)
>>>>
>>>> Perhaps we can just handle this through the regular patch review
>>>> process; I think it may be difficult to define and agree upon exactly
>>>> what "abuse" means ahead of time, but it's probably going to be easy
>>>> enough to recognize it when one sees it?
>>>
>>> Rather than repeating things over and over in reviews, we should
>>> document at least rules we can easily agree on and then add to it when
>>> people get "creative." Also, I can't keep up with every single binding
>>> review as is, and this could just add another level of complexity to the
>>> review. A few off the top of my head and from the thread discussion:
>>>
>>> - Headers must be self contained with no outside (i.e. libc, kernel,
>>> etc.) header dependencies.
>>> - No kernel kconfig option usage
>>> - No gcc built-in define usage
>>> - No unused items (i.e. externs, structs, etc.)
>>> - No macro concatenation
>>> - No macros for strings or property names
>>
>> Instead of making a bunch of rules about how you can only use a small
>> subset of cpp, why not just add a "define name value" command to DTC?
>
> I implemented a patch to do exactly that, and it was rejected because it
> only solved part of the problem (named constants) and not the reset (a
> completely generic macro language/... within dtc). The argument was that
> defining just the named constant syntax on its own without knowing what
> the unspecified future macro language will look like might result in the
> named constant syntax not fitting into it.
>
> That all said, I now think that using cpp is actually a much better
> solution that adding yet more dtc-specific syntax. The *huge* benefit
> here is that it allows you to share .h files between *.dts and C code,
> so you don't have to write out the same set of #defines once in dtc
> syntax and once in cpp syntax.

... and it imposes an equally *huge* restriction that you have to
restrict the .h file to avoid avoid C constructs. That can be done, but
I've personally experienced a lot of headaches when trying to share .h
files between different languages.

>

2012-10-11 00:27:44

by David Gibson

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On Wed, Oct 10, 2012 at 10:33:31AM -0500, Rob Herring wrote:
> On 10/10/2012 10:16 AM, Stephen Warren wrote:
> > On 10/10/2012 01:24 AM, David Gibson wrote:
> >> On Tue, Oct 09, 2012 at 10:43:50PM -0600, Warner Losh wrote:
> >>> On Oct 9, 2012, at 6:04 PM, Scott Wood wrote:
[snip]
> > That's probably a reasonable idea, although I imagined that people would
> > actually split out the portions of any header file they wanted to use
> > with dtc, so that any headers included by *.dts would only include
> > #defines. Those headers could be used by both dtc and other .h files (or
> > .c files).
>
> Used by what other files? kernel files? We ultimately want to split out
> dts files from the kernel, so whatever we add needs to be self
> contained. I don't see this as a huge issue though because the whole
> point of the DT data is to move that information out of the kernel. If
> it is needed in both places, then something is wrong.

People get very hung up on this idea of having the DT move device
information out of the kernel, but that was never really the
motivation behind it. Or at least, not the only or foremost
motivation.

The DT provides a consistent, flexible way of describing device
information. That allows the core runtime the kernel to operate the
same way, regardless of how the DT information was obtained. The DT
could come from firmware, but it could also come from an intermediate
bootloader or from early kernel code. All are perfectly acceptable
options depending on the constraints of the platform.

The idea of firmware supplying the DT is much touted, but while it's a
theoretically nice idea, I think it's frequently a bad idea for
practical reasons. Those being, in essence that a) firmware usually
sucks, b) it's usually harder (or at least no easier) to replace
firmware with a fixed version than the kernel/bootwrapper and c)
firmware usually *really* sucks.

--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson

2012-10-11 00:27:47

by David Gibson

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On Wed, Oct 10, 2012 at 08:56:11AM -1000, Mitch Bradley wrote:
> On 10/10/2012 8:45 AM, Stephen Warren wrote:
> > On 10/10/2012 12:23 PM, Mitch Bradley wrote:
> >> On 10/10/2012 7:09 AM, Rob Herring wrote:
> >>> On 10/09/2012 04:16 PM, Stephen Warren wrote:
> >>>> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
[snip]
> >> Instead of making a bunch of rules about how you can only use a small
> >> subset of cpp, why not just add a "define name value" command to DTC?
> >
> > I implemented a patch to do exactly that, and it was rejected because it
> > only solved part of the problem (named constants) and not the reset (a
> > completely generic macro language/... within dtc). The argument was that
> > defining just the named constant syntax on its own without knowing what
> > the unspecified future macro language will look like might result in the
> > named constant syntax not fitting into it.
> >
> > That all said, I now think that using cpp is actually a much better
> > solution that adding yet more dtc-specific syntax. The *huge* benefit
> > here is that it allows you to share .h files between *.dts and C code,
> > so you don't have to write out the same set of #defines once in dtc
> > syntax and once in cpp syntax.
>
> ... and it imposes an equally *huge* restriction that you have to
> restrict the .h file to avoid avoid C constructs. That can be done, but
> I've personally experienced a lot of headaches when trying to share .h
> files between different languages.

Yes, but we already deal with that for asm files. And the sorts of
defines we use in asm files are often the same ones we'd want in dts
files.


--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson

2012-10-11 00:27:42

by David Gibson

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On Wed, Oct 10, 2012 at 12:45:40PM -0600, Stephen Warren wrote:
> On 10/10/2012 12:23 PM, Mitch Bradley wrote:
> > On 10/10/2012 7:09 AM, Rob Herring wrote:
> >> On 10/09/2012 04:16 PM, Stephen Warren wrote:
> >>> On 10/01/2012 12:39 PM, Jon Loeliger wrote:
> >>>>>
> >>>>> What more do you think needs discussion re: dtc+cpp?
> >>>>
> >>>> How not to abuse the ever-loving shit out of it? :-)
> >>>
> >>> Perhaps we can just handle this through the regular patch review
> >>> process; I think it may be difficult to define and agree upon exactly
> >>> what "abuse" means ahead of time, but it's probably going to be easy
> >>> enough to recognize it when one sees it?
> >>
> >> Rather than repeating things over and over in reviews, we should
> >> document at least rules we can easily agree on and then add to it when
> >> people get "creative." Also, I can't keep up with every single binding
> >> review as is, and this could just add another level of complexity to the
> >> review. A few off the top of my head and from the thread discussion:
> >>
> >> - Headers must be self contained with no outside (i.e. libc, kernel,
> >> etc.) header dependencies.
> >> - No kernel kconfig option usage
> >> - No gcc built-in define usage
> >> - No unused items (i.e. externs, structs, etc.)
> >> - No macro concatenation
> >> - No macros for strings or property names
> >
> > Instead of making a bunch of rules about how you can only use a small
> > subset of cpp, why not just add a "define name value" command to DTC?
>
> I implemented a patch to do exactly that, and it was rejected because it

Well... more indefinitely postponed, rather than rejected. Which you
would be entirely justified in seeing as a meaningless semantic
difference at this point.

> only solved part of the problem (named constants) and not the reset (a
> completely generic macro language/... within dtc). The argument was that
> defining just the named constant syntax on its own without knowing what
> the unspecified future macro language will look like might result in the
> named constant syntax not fitting into it.
>
> That all said, I now think that using cpp is actually a much better
> solution that adding yet more dtc-specific syntax. The *huge* benefit
> here is that it allows you to share .h files between *.dts and C code,
> so you don't have to write out the same set of #defines once in dtc
> syntax and once in cpp syntax.

Right, I tend to agree. In addition to those reasons, it avoids
creating yet another micro-language, and it obeys the #1 guiding
principle for dts syntax which is "don't surprise C programmers".

That said, there are a number of number of dtc extensions that would
make cpp-ability more useful. The integer expression support that has
already gone in was a start on that, but richer expressions
(particularly strings and bytestrings) would be useful too. Support
for invoking cpp automatically from within dtc would make that support
easier to use too.

I really would like to be working more actively on those things, but
unfortunately I don't have that much time free for dtc work.

--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson

2012-10-11 00:27:37

by David Gibson

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On Wed, Oct 10, 2012 at 08:41:45AM -0600, Warner Losh wrote:
> On Oct 10, 2012, at 1:24 AM, David Gibson wrote:
> > On Tue, Oct 09, 2012 at 10:43:50PM -0600, Warner Losh wrote:
[snip]
> >> .h files include both structs and defines, which are fine for
> >> ordinary C code, but problematic in this context.
> >
> > Right, cpp should be invoked with similar options to the way it's done
> > for asm files which have the same problem. I'm not sure if the
> > current patch does so.
>
> I know the current dtc code is very careful to license itself in a
> very agnostic way. Would including files, possibly from the Linux
> kernel, pose any kind of license issue? Or does the fact that many
> (but not all) .dts files being apparently licensed GPL already make
> this a moot point? Or does it not matter since this is an interface
> and declaration of information, which likely isn't creative enough
> to receive to copyright protection.... Or is this a can of worms
> best avoided :)

Um... what? The licensing of dtc itself has nothing to do with the
licensing of the dts files used as input to it. Those, and their
includes, would be licensed GPLv2 just like the rest of the kernel,
I'd expect.

--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson

2012-10-11 00:27:34

by David Gibson

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On Wed, Oct 10, 2012 at 10:22:02AM -0600, Stephen Warren wrote:
> On 10/10/2012 10:09 AM, Scott Wood wrote:
> > On 10/10/2012 10:15:17 AM, Stephen Warren wrote:
> >> On 10/09/2012 06:04 PM, Scott Wood wrote:
> >> > On 10/09/2012 06:20:53 PM, Mitch Bradley wrote:
> >> >> On 10/9/2012 11:16 AM, Stephen Warren wrote:
> >> >> > On 10/01/2012 12:39 PM, Jon Loeliger wrote:
> >> >> >>>
> >> >> >>> What more do you think needs discussion re: dtc+cpp?
> >> >> >>
> >> >> >> How not to abuse the ever-loving shit out of it? :-)
> >> >> >
> >> >> > Perhaps we can just handle this through the regular patch review
> >> >> > process; I think it may be difficult to define and agree upon
> >> exactly
> >> >> > what "abuse" means ahead of time, but it's probably going to be easy
> >> >> > enough to recognize it when one sees it?
> >> >>
> >> >>
> >> >> One of the ways it could get out of hand would be via "include
> >> >> dependency hell". People will be tempted to reuse existing .h files
> >> >> containing pin definitions, which, if history is a guide, will end up
> >> >> depending on all sorts of other .h files.
> >> >>
> >> >> Another problem I often face with symbolic names is the difficulty of
> >> >> figuring out what the numerical values really are (for debugging),
> >> >> especially when .h files are in different subtrees from the files that
> >> >> use the definitions, and when they use multiple macro levels and fancy
> >> >> features like concatenation. Sometimes I think it's clearer just to
> >> >> write the number and use a comment to say what it is.
> >> >
> >> > Both comments apply just as well to ordinary C code, and I don't think
> >> > anyone would seriously suggest just using comments instead for C code.
> >> >
> >> > Is there a way to ask CPP to evaluate a macro in the context of the
> >> > input file, rather than produce normal output? If not, I guess you
> >> > could make a tool that creates a wrapper file that includes the main
> >> > file and then evaluates the symbol you want.
> >>
> >> I'm not sure what "evaluate a macro in the context of the input file"
> >> means. Macros are obviously already evaluated based on the current set
> >> of macros defined by the file that's been processed or those it
> >> included. Do you mean only allowing the use of macros in the current
> >> file and not included files? What exactly would the wrapper you
> >> mentioned do?
> >
> > I just meant a way for a developer to quickly ask the preprocessor what
> > a particular macro expands to, rather than try to figure it out
> > manually. I was not suggesting any change to normal operation.
>
> Oh right. Well, the patch I proposed to the kernel was basically:
>
> %.dtb: %.dtsp
> cpp -E $< | dtc -o $@ -
>
> A developer could run the same cpp -E command to find that out, or that
> build rule could instead save the intermediate result rather than just
> piping it, so you could just go read the file.

It would be nice to have a make target to actually do just that step,
even though it would usually only be invoked manually for debugging,
just as we have a %.i make target which can be used to see what the
preprocessor did to .c files.

And as stated elsewhere, cpp should be invoked with similar options to
the way it's done for asm files. A -D__DTS__ or something like that
would probably be a good idea too, just in case some .h needs to be
conditional on that.

--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson

2012-10-11 00:28:45

by David Gibson

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On Wed, Oct 10, 2012 at 09:16:34AM -0600, Stephen Warren wrote:
> On 10/10/2012 01:24 AM, David Gibson wrote:
> > On Tue, Oct 09, 2012 at 10:43:50PM -0600, Warner Losh wrote:
[snip]
> >> .h files include both structs and defines, which are fine for
> >> ordinary C code, but problematic in this context.
> >
> > Right, cpp should be invoked with similar options to the way it's done
> > for asm files which have the same problem. I'm not sure if the
> > current patch does so.
>
> That's probably a reasonable idea, although I imagined that people would
> actually split out the portions of any header file they wanted to use
> with dtc, so that any headers included by *.dts would only include
> #defines. Those headers could be used by both dtc and other .h files (or
> .c files).

Given that header files are right now frequently used in both .c and
.S for the #defines, I don't think we can reasonably expect
differently for dts files. There certainly is the potential for
#include dependency mess, but we cope with it for .S so we can cope
with it for dts as well.

But cpp should definitely be invoked "asm style" for dts files.

--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson

2012-10-11 01:42:47

by Mitch Bradley

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/10/2012 1:16 PM, David Gibson wrote:
> On Wed, Oct 10, 2012 at 10:33:31AM -0500, Rob Herring wrote:
>> On 10/10/2012 10:16 AM, Stephen Warren wrote:
>>> On 10/10/2012 01:24 AM, David Gibson wrote:
>>>> On Tue, Oct 09, 2012 at 10:43:50PM -0600, Warner Losh wrote:
>>>>> On Oct 9, 2012, at 6:04 PM, Scott Wood wrote:
> [snip]
>>> That's probably a reasonable idea, although I imagined that people would
>>> actually split out the portions of any header file they wanted to use
>>> with dtc, so that any headers included by *.dts would only include
>>> #defines. Those headers could be used by both dtc and other .h files (or
>>> .c files).
>>
>> Used by what other files? kernel files? We ultimately want to split out
>> dts files from the kernel, so whatever we add needs to be self
>> contained. I don't see this as a huge issue though because the whole
>> point of the DT data is to move that information out of the kernel. If
>> it is needed in both places, then something is wrong.
>
> People get very hung up on this idea of having the DT move device
> information out of the kernel, but that was never really the
> motivation behind it. Or at least, not the only or foremost
> motivation.
>
> The DT provides a consistent, flexible way of describing device
> information. That allows the core runtime the kernel to operate the
> same way, regardless of how the DT information was obtained. The DT
> could come from firmware, but it could also come from an intermediate
> bootloader or from early kernel code. All are perfectly acceptable
> options depending on the constraints of the platform.
>
> The idea of firmware supplying the DT is much touted, but while it's a
> theoretically nice idea, I think it's frequently a bad idea for
> practical reasons. Those being, in essence that a) firmware usually
> sucks, b) it's usually harder (or at least no easier) to replace
> firmware with a fixed version than the kernel/bootwrapper and c)
> firmware usually *really* sucks.
>

Gee, it sounds like you want firmware to suck. Beating on the "firmware
sucks" drum is sort of a self-fulfilling prophecy, discouraging talented
programmers from doing firmware. Who would want to work on something
that "everyone knows sucks"?

2012-10-11 05:10:40

by David Gibson

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On Wed, Oct 10, 2012 at 03:42:33PM -1000, Mitch Bradley wrote:
> On 10/10/2012 1:16 PM, David Gibson wrote:
> > On Wed, Oct 10, 2012 at 10:33:31AM -0500, Rob Herring wrote:
> >> On 10/10/2012 10:16 AM, Stephen Warren wrote:
> >>> On 10/10/2012 01:24 AM, David Gibson wrote:
> >>>> On Tue, Oct 09, 2012 at 10:43:50PM -0600, Warner Losh wrote:
> >>>>> On Oct 9, 2012, at 6:04 PM, Scott Wood wrote:
> > [snip]
> >>> That's probably a reasonable idea, although I imagined that people would
> >>> actually split out the portions of any header file they wanted to use
> >>> with dtc, so that any headers included by *.dts would only include
> >>> #defines. Those headers could be used by both dtc and other .h files (or
> >>> .c files).
> >>
> >> Used by what other files? kernel files? We ultimately want to split out
> >> dts files from the kernel, so whatever we add needs to be self
> >> contained. I don't see this as a huge issue though because the whole
> >> point of the DT data is to move that information out of the kernel. If
> >> it is needed in both places, then something is wrong.
> >
> > People get very hung up on this idea of having the DT move device
> > information out of the kernel, but that was never really the
> > motivation behind it. Or at least, not the only or foremost
> > motivation.
> >
> > The DT provides a consistent, flexible way of describing device
> > information. That allows the core runtime the kernel to operate the
> > same way, regardless of how the DT information was obtained. The DT
> > could come from firmware, but it could also come from an intermediate
> > bootloader or from early kernel code. All are perfectly acceptable
> > options depending on the constraints of the platform.
> >
> > The idea of firmware supplying the DT is much touted, but while it's a
> > theoretically nice idea, I think it's frequently a bad idea for
> > practical reasons. Those being, in essence that a) firmware usually
> > sucks, b) it's usually harder (or at least no easier) to replace
> > firmware with a fixed version than the kernel/bootwrapper and c)
> > firmware usually *really* sucks.
>
> Gee, it sounds like you want firmware to suck. Beating on the "firmware
> sucks" drum is sort of a self-fulfilling prophecy, discouraging talented
> programmers from doing firmware. Who would want to work on something
> that "everyone knows sucks"?

At this point it's already fulfilled. Unfortunately, it really
doesn't matter how many more nice firmwares appear, once you have to
support the shitty ones - which we already do - the damage is done.

--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson

2012-10-12 17:24:47

by Stephen Warren

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On 10/10/2012 05:18 PM, David Gibson wrote:
...
> And as stated elsewhere, cpp should be invoked with similar options to
> the way it's done for asm files. A -D__DTS__ or something like that
> would probably be a good idea too, just in case some .h needs to be
> conditional on that.

Hmm. There are some problems here.

Right now, the command I proposed is basically:

$(CPP) -x c $< | dtc ...

Without "-x c", $(CPP) doesn't recognise the file extension of the input
file, and defaults to assuming it's a linker script rather than an input
file, even in pre-processing mode (CPP == $(CC) -E), which obviously
doesn't work too well.

I chose "-x c" because *.dts syntax is closest to C.

However, related to your request above, "-x assembler" might be more
appropriate, since this would presumably define __ASSEMBLY__, which is
what the kernel headers currently use to determine whether to compile
out anything other than #defines. However, executing $(CPP) -x assembler
foo.dts yields a completely empty output! I'm not sure why that is yet.

I also tried passing to $(CPP) the exact same options that the kernel
uses for compiling true assembly files, namely $(a_flags). Doing so
would presumably provide complete compatibility in the pre-defined
#defines between compiling *.S and *.dtsp, which would reduce the
likelihood of needing to do anything different in *.h to support usage
by both *.S and *.dtsp. (Note that I still need to pass a -x option, and
the issue I described above still applies here too). This doesn't work
out, because on ARM you get arch/arm/include/asm/unified.h
force-included, which emits true assembly macros into the output, which
obviously dtc can't parse. This could be avoided by editing that file to
add #ifndef __DTS__ around the offending parts (and passing -D__DTS__ to
$(CPP)), and that does appear to currently be the only file requiring a
change. I wonder if using $(a_flags) is inviting more issues like this
in the future though?

Given this, I'm not convinced we should try to make $(CPP) usage for
*.dts too much like its usage for *.S. I agree it'd probably make sense
to add -D__DTS__ to the command-line, but switching away from -x c or to
using $(a_flags) seems like it'd increase the maintenance requirements
rather than reduce them.

2012-10-13 06:24:00

by David Gibson

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On Fri, Oct 12, 2012 at 11:24:43AM -0600, Stephen Warren wrote:
> On 10/10/2012 05:18 PM, David Gibson wrote:
> ...
> > And as stated elsewhere, cpp should be invoked with similar options to
> > the way it's done for asm files. A -D__DTS__ or something like that
> > would probably be a good idea too, just in case some .h needs to be
> > conditional on that.
>
> Hmm. There are some problems here.
>
> Right now, the command I proposed is basically:
>
> $(CPP) -x c $< | dtc ...
>
> Without "-x c", $(CPP) doesn't recognise the file extension of the input
> file, and defaults to assuming it's a linker script rather than an input
> file, even in pre-processing mode (CPP == $(CC) -E), which obviously
> doesn't work too well.
>
> I chose "-x c" because *.dts syntax is closest to C.
>
> However, related to your request above, "-x assembler" might be more
> appropriate, since this would presumably define __ASSEMBLY__, which is
> what the kernel headers currently use to determine whether to compile
> out anything other than #defines. However, executing $(CPP) -x assembler
> foo.dts yields a completely empty output! I'm not sure why that is yet.

Oh, that's strange. I'm pretty sure I've used -x assembler when I've
experimented with using cpp on dts manually before, and it seems to
have worked. Note that IIRC with gcc cpp, -x assembler also means
that # won't be handled as a cpp directive except in column 0 which is
also an advantage for us, although no longer essential with your
escaping support. Not all cpps have an equivalent option, though.

> I also tried passing to $(CPP) the exact same options that the kernel
> uses for compiling true assembly files, namely $(a_flags). Doing so
> would presumably provide complete compatibility in the pre-defined
> #defines between compiling *.S and *.dtsp, which would reduce the
> likelihood of needing to do anything different in *.h to support usage
> by both *.S and *.dtsp. (Note that I still need to pass a -x option, and
> the issue I described above still applies here too). This doesn't work
> out, because on ARM you get arch/arm/include/asm/unified.h
> force-included, which emits true assembly macros into the output, which
> obviously dtc can't parse. This could be avoided by editing that file to
> add #ifndef __DTS__ around the offending parts (and passing -D__DTS__ to
> $(CPP)), and that does appear to currently be the only file requiring a
> change. I wonder if using $(a_flags) is inviting more issues like this
> in the future though?

Ah, ok. No we probably don't want a_flags, although I think we do
want -x assembler (once we work out what's going wrong with that).
Actually, what we should look at is how cpp is invoked for the .lds.S
linker scripts. Hrm.. possibly that's why .S was used for that,
despite the potential confusion with asm files - because it
automatically triggers the behaviour wanted from cpp.

> Given this, I'm not convinced we should try to make $(CPP) usage for
> *.dts too much like its usage for *.S. I agree it'd probably make sense
> to add -D__DTS__ to the command-line, but switching away from -x c or to
> using $(a_flags) seems like it'd increase the maintenance requirements
> rather than reduce them.

Hrm. I don't think we want $(a_flags), but I'm not convinced either
way about the -x option. I definitely think we do want -D__DTS__, and
I think we want -D__ASSEMBLY__ (either directly or indirectly) too.
It's not really accurate, but will at least do the right thing for
quite a lot of the .h files existing in the kernel already.

--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson

2012-10-13 13:43:49

by Segher Boessenkool

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

> Oh, that's strange. I'm pretty sure I've used -x assembler when I've
> experimented with using cpp on dts manually before, and it seems to
> have worked.

Maybe you used "-x assembler-with-cpp"? That should work better ;-)
Or just use the "-traditional-cpp" option, i.e. "gcc -E -traditional-
cpp".

> Note that IIRC with gcc cpp, -x assembler also means
> that # won't be handled as a cpp directive except in column 0 which is
> also an advantage for us, although no longer essential with your
> escaping support. Not all cpps have an equivalent option, though.

This is how the traditional C pre-processor behaves. I don't think
this is exactly what matters for DTS, or does it ever happen that
you have a # preceded only by whitespace? The # and ## stringification
and token pasting ops will of course bite you with the ISO C pre-
processor,
indeed.


Segher

2012-10-14 07:44:09

by David Gibson

[permalink] [raw]
Subject: Re: dtc: import latest upstream dtc

On Sat, Oct 13, 2012 at 03:42:35PM +0200, Segher Boessenkool wrote:
> >Oh, that's strange. I'm pretty sure I've used -x assembler when I've
> >experimented with using cpp on dts manually before, and it seems to
> >have worked.
>
> Maybe you used "-x assembler-with-cpp"? That should work better ;-)
> Or just use the "-traditional-cpp" option, i.e. "gcc -E
> -traditional-cpp".

Ah, yes, assembler-with-cpp, that's the one I used.

> > Note that IIRC with gcc cpp, -x assembler also means
> >that # won't be handled as a cpp directive except in column 0 which is
> >also an advantage for us, although no longer essential with your
> >escaping support. Not all cpps have an equivalent option, though.
>
> This is how the traditional C pre-processor behaves. I don't think
> this is exactly what matters for DTS, or does it ever happen that
> you have a # preceded only by whitespace?

Uh.. pretty much whenever you define a #address-cells or #size-cells
property. At least until Stephen's patch to allow escaping that.

> The # and ## stringification
> and token pasting ops will of course bite you with the ISO C pre-processor,
> indeed.
>
>
> Segher
>

--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson