On Mon, Aug 19, 2019 at 03:38:41PM +0200, Sascha Hauer wrote: > This adds the following commits from upstream: > > d37f6b2 Bump version to v1.5.0 > a4b1a30 pylibfdt:tests: Extend the way how to find a Python module I'm sorry if this will probably mean a lot of work for you, but sadly those SHA1 hashes are too short to be unique :-( linux (master) $ git show d37f6b2 fatal: ambiguous argument 'd37f6b2': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git <command> [<revision>...] -- [<file>...]' linux (master) $ git show a4b1a30 fatal: ambiguous argument 'a4b1a30': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git <command> [<revision>...] -- [<file>...]' - Roland > 625dd8a pylibfdt: Change how passing tests are recognized > 3646316 pylibfdt: Test fdt.setprop take bytes on Python 3, add error handling > cb0f454 pylibfdt: check_err accepts only integer as a first argument. > 4b68c6b pylibfdt: Proper handling of bytes/unicode strings and octal literals > 78e113e Use PRIxPTR for printing uintptr_t values > ea7a8f6 libfdt: Fix FDT_ERR_NOTFOUND typos in documentation > 5aafd7c libfdt: Fix fdt_getprop_by_offset() parameter name in documentation > 7cbc550 checks: Add unit address check if node is enabled > f267e67 checks: Fix crash with multiple source annotations > 3616b9a checks: Use source position information for check failures > 2bdbd07 checks: Make each message output atomic > a1eff70 util: Add xa{v}sprintf_append functions > 82a52ce libfdt: Add a test for fdt_getprop_by_offset() > 607b858 PEP8 / Flake8 cleanups for setup.py > f9c0a42 Remove broken objdir / srcdir support > 5182b5e pylibfdt: Use common PREFIX variable > d45bf1f Refine make tests_clean target > 99284c4 Refine pylibfdt_clean target > a4629cf Refine libfdt_clean target > 08380fc tests: Use modern octal literals for Python > 8113c00 pylibfdt: Allow switch to Python 3 via environment variable PYTHON > 11738cf libfdt: Don't use memcpy to handle unaligned reads on ARM > 86a288a checks: Restructure check_msg to decrease indentation > 5667e7e annotations: add the annotation functionality > 8e20ccf annotations: add positions > ca930e2 tests: Don't lose errors from make checkm > 43366bb tests: Property count valgrind errors in wrapped tests > 5062516 srcpos: Remove srcpos_empty > a3143fa Revert "annotations: add positions" > 403cc79 checks: Update SPI bus check for 'spi-slave' > baa1d2c annotations: add positions > ff2ad38 Merge remote-tracking branch 'origin/pr/18' > aa7254d libfdt: return correct value if #size-cells property is not present > 49903ae use ptrdiff_t modifier for printing pointer differences > da2b691 treesource: Fix dts output for phandles in middle of a sequence of ints > 8f8b77a tests: Wrap check_align() calls with base_run_test() > 522d81d Fix dts output with a REF_PATH marker > e45198c Added test cases for target references > 0fcffda Merge nodes with local target label references > 1e4a092 pylibfdt: Don't have setup.py depend on where it's invoked from > ca399b1 pylibfdt: Eliminate run_setup make function > 98972f1 pylibfdt: Improved version extraction > 7ba2be6 pylibfdt: Don't silence setup.py when V=1 > 7691f9d pylibfdt: Make SETUP make variable > 855b996 pylibfdt: Simpler CFLAGS handling > 47cafbe pylibfdt: Link extension module with libfdt rather than rebuilding > dd695d6 pylibfdt: Correctly set build output directory > 5932752 pylibfdt: We don't need include files from the base directory > e84742a checks: fix simple-bus compatible matching > 8c59a97 Fix missing labels when emitting dts format > d448f9a Revert dts output formatting changes of spaces around brackets > c86da84 Add support for YAML encoded output > 361b5e7 Make type_marker_length helper public > bfbfab0 pylibfdt: Add a means to add and delete notes > 9005f41 pylibfdt: Allow delprop() to return errors > b94c056 Make valgrind optional > fd06c54 tests: Better testing of dtc -I fs mode > c3f50c9 tests: Allow dtbs_equal_unordered to ignore mem reserves > 0ac9fde dtc: trivial '-I fs -O dts' test > 0fd1c8c pylibfdt: fdt_get_mem_rsv returns 2 uint64_t values > 04853ca pylibfdt: Don't incorrectly / unnecessarily override uint64_t typemap > 9619c86 Kill bogus TYPE_BLOB marker type > ac68ff9 parser: add TYPE_STRING marker to path references > 90a190e checks: add SPI bus checks > 53a1bd5 checks: add I2C bus checks > > Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> > --- > scripts/dtc/Makefile | 49 +-- > scripts/dtc/Makefile.dtc | 4 + > scripts/dtc/checks.c | 255 +++++++++++++- > scripts/dtc/data.c | 2 +- > scripts/dtc/dtc-lexer.l | 4 +- > scripts/dtc/dtc-parser.y | 53 ++- > scripts/dtc/dtc.c | 22 +- > scripts/dtc/dtc.h | 18 +- > scripts/dtc/fdtget.c | 383 --------------------- > scripts/dtc/flattree.c | 4 +- > scripts/dtc/fstree.c | 5 +- > scripts/dtc/libfdt/Makefile.libfdt | 15 + > scripts/dtc/{ => libfdt}/fdt.c | 0 > scripts/dtc/{ => libfdt}/fdt.h | 0 > scripts/dtc/{ => libfdt}/fdt_addresses.c | 16 +- > scripts/dtc/{ => libfdt}/fdt_empty_tree.c | 0 > scripts/dtc/{ => libfdt}/fdt_overlay.c | 0 > scripts/dtc/{ => libfdt}/fdt_ro.c | 0 > scripts/dtc/{ => libfdt}/fdt_rw.c | 0 > scripts/dtc/{ => libfdt}/fdt_strerror.c | 0 > scripts/dtc/{ => libfdt}/fdt_sw.c | 0 > scripts/dtc/{ => libfdt}/fdt_wip.c | 0 > scripts/dtc/{ => libfdt}/libfdt.h | 30 +- > scripts/dtc/{ => libfdt}/libfdt_env.h | 0 > scripts/dtc/{ => libfdt}/libfdt_internal.h | 0 > scripts/dtc/livetree.c | 33 +- > scripts/dtc/srcpos.c | 153 +++++++- > scripts/dtc/srcpos.h | 14 +- > scripts/dtc/treesource.c | 124 ++++--- > scripts/dtc/util.c | 60 ++-- > scripts/dtc/util.h | 2 + > scripts/dtc/version_gen.h | 2 +- > scripts/dtc/yamltree.c | 247 +++++++++++++ > 33 files changed, 926 insertions(+), 569 deletions(-) > delete mode 100644 scripts/dtc/fdtget.c > create mode 100644 scripts/dtc/libfdt/Makefile.libfdt > rename scripts/dtc/{ => libfdt}/fdt.c (100%) > rename scripts/dtc/{ => libfdt}/fdt.h (100%) > rename scripts/dtc/{ => libfdt}/fdt_addresses.c (92%) > rename scripts/dtc/{ => libfdt}/fdt_empty_tree.c (100%) > rename scripts/dtc/{ => libfdt}/fdt_overlay.c (100%) > rename scripts/dtc/{ => libfdt}/fdt_ro.c (100%) > rename scripts/dtc/{ => libfdt}/fdt_rw.c (100%) > rename scripts/dtc/{ => libfdt}/fdt_strerror.c (100%) > rename scripts/dtc/{ => libfdt}/fdt_sw.c (100%) > rename scripts/dtc/{ => libfdt}/fdt_wip.c (100%) > rename scripts/dtc/{ => libfdt}/libfdt.h (99%) > rename scripts/dtc/{ => libfdt}/libfdt_env.h (100%) > rename scripts/dtc/{ => libfdt}/libfdt_internal.h (100%) > create mode 100644 scripts/dtc/yamltree.c > > diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile > index 1d63476ecc..5f227d8d39 100644 > --- a/scripts/dtc/Makefile > +++ b/scripts/dtc/Makefile > @@ -1,43 +1,30 @@ > +# SPDX-License-Identifier: GPL-2.0 > # scripts/dtc makefile > > -hostprogs-y := dtc fdtget > +hostprogs-$(CONFIG_DTC) := dtc > always := $(hostprogs-y) > > dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \ > srcpos.o checks.o util.o > dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o > > -libfdt-objs = fdt.o fdt_ro.o fdt_strerror.o fdt_wip.o fdt_overlay.o > -libfdt-objs += fdt_empty_tree.o fdt_rw.o fdt_sw.o > - > -fdtget-objs += fdtget.o $(libfdt-objs) util.o > - > # Source files need to get at the userspace version of libfdt_env.h to compile > - > -HOSTCFLAGS_DTC := -I$(src) > - > -HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_dtc.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_flattree.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fstree.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_livetree.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_util.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdtget.o := $(HOSTCFLAGS_DTC) > - > -HOSTCFLAGS_fdt.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdt_ro.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdt_strerror.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdt_wip.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdt_empty_tree.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdt_rw.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdt_sw.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdt_overlay.o := $(HOSTCFLAGS_DTC) > - > -HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC) > +HOST_EXTRACFLAGS := -I$(src)/libfdt > + > +ifeq ($(wildcard /usr/include/yaml.h),) > +ifneq ($(CHECK_DTBS),) > +$(error dtc needs libyaml for DT schema validation support. \ > + Install the necessary libyaml development package.) > +endif > +HOST_EXTRACFLAGS += -DNO_YAML > +else > +dtc-objs += yamltree.o > +HOSTLDLIBS_dtc := -lyaml > +endif > + > +# Generated files need one more search path to include headers in source tree > +HOSTCFLAGS_dtc-lexer.lex.o := -I$(src) > +HOSTCFLAGS_dtc-parser.tab.o := -I$(src) > > # dependencies on generated files need to be listed explicitly > $(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h > diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc > index bece49b355..d4375630a7 100644 > --- a/scripts/dtc/Makefile.dtc > +++ b/scripts/dtc/Makefile.dtc > @@ -14,5 +14,9 @@ DTC_SRCS = \ > treesource.c \ > util.c > > +ifneq ($(NO_YAML),1) > +DTC_SRCS += yamltree.c > +endif > + > 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 a2cc1036c9..c0ed45e1c3 100644 > --- a/scripts/dtc/checks.c > +++ b/scripts/dtc/checks.c > @@ -19,6 +19,7 @@ > */ > > #include "dtc.h" > +#include "srcpos.h" > > #ifdef TRACE_CHECKS > #define TRACE(c, ...) \ > @@ -78,23 +79,56 @@ static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti, > const char *fmt, ...) > { > va_list ap; > - va_start(ap, fmt); > + char *str = NULL; > + struct srcpos *pos = NULL; > + char *file_str; > + > + if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2))) > + return; > + > + if (prop && prop->srcpos) > + pos = prop->srcpos; > + else if (node && node->srcpos) > + pos = node->srcpos; > + > + if (pos) { > + file_str = srcpos_string(pos); > + xasprintf(&str, "%s", file_str); > + free(file_str); > + } else if (streq(dti->outname, "-")) { > + xasprintf(&str, "<stdout>"); > + } else { > + xasprintf(&str, "%s", dti->outname); > + } > > - if ((c->warn && (quiet < 1)) > - || (c->error && (quiet < 2))) { > - fprintf(stderr, "%s: %s (%s): ", > - strcmp(dti->outname, "-") ? dti->outname : "<stdout>", > + xasprintf_append(&str, ": %s (%s): ", > (c->error) ? "ERROR" : "Warning", c->name); > - if (node) { > - fprintf(stderr, "%s", node->fullpath); > - if (prop) > - fprintf(stderr, ":%s", prop->name); > - fputs(": ", stderr); > - } > - vfprintf(stderr, fmt, ap); > - fprintf(stderr, "\n"); > + > + if (node) { > + if (prop) > + xasprintf_append(&str, "%s:%s: ", node->fullpath, prop->name); > + else > + xasprintf_append(&str, "%s: ", node->fullpath); > } > + > + va_start(ap, fmt); > + xavsprintf_append(&str, fmt, ap); > va_end(ap); > + > + xasprintf_append(&str, "\n"); > + > + if (!prop && pos) { > + pos = node->srcpos; > + while (pos->next) { > + pos = pos->next; > + > + file_str = srcpos_string(pos); > + xasprintf_append(&str, " also defined at %s\n", file_str); > + free(file_str); > + } > + } > + > + fputs(str, stderr); > } > > #define FAIL(c, dti, node, ...) \ > @@ -910,7 +944,7 @@ static bool node_is_compatible(struct node *node, const char *compat) > > for (str = prop->val.val, end = str + prop->val.len; str < end; > str += strnlen(str, end - str) + 1) { > - if (strprefixeq(str, end - str, compat)) > + if (streq(str, compat)) > return true; > } > return false; > @@ -921,7 +955,8 @@ static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct > if (node_is_compatible(node, "simple-bus")) > node->bus = &simple_bus; > } > -WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells); > +WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, > + &addr_size_cells, &compatible_is_string_list); > > static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node) > { > @@ -962,6 +997,149 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no > } > WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge); > > +static const struct bus_type i2c_bus = { > + .name = "i2c-bus", > +}; > + > +static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) > +{ > + if (strprefixeq(node->name, node->basenamelen, "i2c-bus") || > + strprefixeq(node->name, node->basenamelen, "i2c-arb")) { > + node->bus = &i2c_bus; > + } else if (strprefixeq(node->name, node->basenamelen, "i2c")) { > + struct node *child; > + for_each_child(node, child) { > + if (strprefixeq(child->name, node->basenamelen, "i2c-bus")) > + return; > + } > + node->bus = &i2c_bus; > + } else > + return; > + > + if (!node->children) > + return; > + > + if (node_addr_cells(node) != 1) > + FAIL(c, dti, node, "incorrect #address-cells for I2C bus"); > + if (node_size_cells(node) != 0) > + FAIL(c, dti, node, "incorrect #size-cells for I2C bus"); > + > +} > +WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells); > + > +static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node) > +{ > + struct property *prop; > + const char *unitname = get_unitname(node); > + char unit_addr[17]; > + uint32_t reg = 0; > + int len; > + cell_t *cells = NULL; > + > + if (!node->parent || (node->parent->bus != &i2c_bus)) > + return; > + > + prop = get_property(node, "reg"); > + if (prop) > + cells = (cell_t *)prop->val.val; > + > + if (!cells) { > + FAIL(c, dti, node, "missing or empty reg property"); > + return; > + } > + > + reg = fdt32_to_cpu(*cells); > + snprintf(unit_addr, sizeof(unit_addr), "%x", reg); > + if (!streq(unitname, unit_addr)) > + FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"", > + unit_addr); > + > + for (len = prop->val.len; len > 0; len -= 4) { > + reg = fdt32_to_cpu(*(cells++)); > + if (reg > 0x3ff) > + FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"", > + reg); > + > + } > +} > +WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, ®_format, &i2c_bus_bridge); > + > +static const struct bus_type spi_bus = { > + .name = "spi-bus", > +}; > + > +static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) > +{ > + int spi_addr_cells = 1; > + > + if (strprefixeq(node->name, node->basenamelen, "spi")) { > + node->bus = &spi_bus; > + } else { > + /* Try to detect SPI buses which don't have proper node name */ > + struct node *child; > + > + if (node_addr_cells(node) != 1 || node_size_cells(node) != 0) > + return; > + > + for_each_child(node, child) { > + struct property *prop; > + for_each_property(child, prop) { > + if (strprefixeq(prop->name, 4, "spi-")) { > + node->bus = &spi_bus; > + break; > + } > + } > + if (node->bus == &spi_bus) > + break; > + } > + > + if (node->bus == &spi_bus && get_property(node, "reg")) > + FAIL(c, dti, node, "node name for SPI buses should be 'spi'"); > + } > + if (node->bus != &spi_bus || !node->children) > + return; > + > + if (get_property(node, "spi-slave")) > + spi_addr_cells = 0; > + if (node_addr_cells(node) != spi_addr_cells) > + FAIL(c, dti, node, "incorrect #address-cells for SPI bus"); > + if (node_size_cells(node) != 0) > + FAIL(c, dti, node, "incorrect #size-cells for SPI bus"); > + > +} > +WARNING(spi_bus_bridge, check_spi_bus_bridge, NULL, &addr_size_cells); > + > +static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node *node) > +{ > + struct property *prop; > + const char *unitname = get_unitname(node); > + char unit_addr[9]; > + uint32_t reg = 0; > + cell_t *cells = NULL; > + > + if (!node->parent || (node->parent->bus != &spi_bus)) > + return; > + > + if (get_property(node->parent, "spi-slave")) > + return; > + > + prop = get_property(node, "reg"); > + if (prop) > + cells = (cell_t *)prop->val.val; > + > + if (!cells) { > + FAIL(c, dti, node, "missing or empty reg property"); > + return; > + } > + > + reg = fdt32_to_cpu(*cells); > + snprintf(unit_addr, sizeof(unit_addr), "%x", reg); > + if (!streq(unitname, unit_addr)) > + FAIL(c, dti, node, "SPI bus unit address format error, expected \"%s\"", > + unit_addr); > +} > +WARNING(spi_bus_reg, check_spi_bus_reg, NULL, ®_format, &spi_bus_bridge); > + > static void check_unit_address_format(struct check *c, struct dt_info *dti, > struct node *node) > { > @@ -1034,8 +1212,24 @@ static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *d > } > WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size); > > -static void check_unique_unit_address(struct check *c, struct dt_info *dti, > - struct node *node) > +static bool node_is_disabled(struct node *node) > +{ > + struct property *prop; > + > + prop = get_property(node, "status"); > + if (prop) { > + char *str = prop->val.val; > + if (streq("disabled", str)) > + return true; > + } > + > + return false; > +} > + > +static void check_unique_unit_address_common(struct check *c, > + struct dt_info *dti, > + struct node *node, > + bool disable_check) > { > struct node *childa; > > @@ -1052,18 +1246,38 @@ static void check_unique_unit_address(struct check *c, struct dt_info *dti, > if (!strlen(addr_a)) > continue; > > + if (disable_check && node_is_disabled(childa)) > + continue; > + > for_each_child(node, childb) { > const char *addr_b = get_unitname(childb); > if (childa == childb) > break; > > + if (disable_check && node_is_disabled(childb)) > + continue; > + > if (streq(addr_a, addr_b)) > FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath); > } > } > } > + > +static void check_unique_unit_address(struct check *c, struct dt_info *dti, > + struct node *node) > +{ > + check_unique_unit_address_common(c, dti, node, false); > +} > WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size); > > +static void check_unique_unit_address_if_enabled(struct check *c, struct dt_info *dti, > + struct node *node) > +{ > + check_unique_unit_address_common(c, dti, node, true); > +} > +CHECK_ENTRY(unique_unit_address_if_enabled, check_unique_unit_address_if_enabled, > + NULL, false, false, &avoid_default_addr_size); > + > static void check_obsolete_chosen_interrupt_controller(struct check *c, > struct dt_info *dti, > struct node *node) > @@ -1582,9 +1796,16 @@ static struct check *check_table[] = { > &simple_bus_bridge, > &simple_bus_reg, > > + &i2c_bus_bridge, > + &i2c_bus_reg, > + > + &spi_bus_bridge, > + &spi_bus_reg, > + > &avoid_default_addr_size, > &avoid_unnecessary_addr_size, > &unique_unit_address, > + &unique_unit_address_if_enabled, > &obsolete_chosen_interrupt_controller, > &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path, > > diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c > index accdfaef66..4a204145cc 100644 > --- a/scripts/dtc/data.c > +++ b/scripts/dtc/data.c > @@ -95,7 +95,7 @@ struct data data_copy_file(FILE *f, size_t maxlen) > { > struct data d = empty_data; > > - d = data_add_marker(d, TYPE_BLOB, NULL); > + d = data_add_marker(d, TYPE_NONE, NULL); > while (!feof(f) && (d.len < maxlen)) { > size_t chunksize, ret; > > diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l > index 615b7ec658..06c0409024 100644 > --- a/scripts/dtc/dtc-lexer.l > +++ b/scripts/dtc/dtc-lexer.l > @@ -213,14 +213,14 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...); > <*>\&{LABEL} { /* label reference */ > DPRINT("Ref: %s\n", yytext+1); > yylval.labelref = xstrdup(yytext+1); > - return DT_REF; > + return DT_LABEL_REF; > } > > <*>"&{/"{PATHCHAR}*\} { /* new-style path reference */ > yytext[yyleng-1] = '\0'; > DPRINT("Ref: %s\n", yytext+2); > yylval.labelref = xstrdup(yytext+2); > - return DT_REF; > + return DT_PATH_REF; > } > > <BYTESTRING>[0-9a-fA-F]{2} { > diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y > index 815481a9bb..2ec981e861 100644 > --- a/scripts/dtc/dtc-parser.y > +++ b/scripts/dtc/dtc-parser.y > @@ -70,7 +70,8 @@ extern bool treesource_error; > %token <byte> DT_BYTE > %token <data> DT_STRING > %token <labelref> DT_LABEL > -%token <labelref> DT_REF > +%token <labelref> DT_LABEL_REF > +%token <labelref> DT_PATH_REF > %token DT_INCBIN > > %type <data> propdata > @@ -83,6 +84,7 @@ extern bool treesource_error; > %type <data> bytestring > %type <prop> propdef > %type <proplist> proplist > +%type <labelref> dt_ref > > %type <node> devicetree > %type <node> nodedef > @@ -158,6 +160,8 @@ memreserve: > } > ; > > +dt_ref: DT_LABEL_REF | DT_PATH_REF; > + > devicetree: > '/' nodedef > { > @@ -167,7 +171,7 @@ devicetree: > { > $$ = merge_nodes($1, $3); > } > - | DT_REF nodedef > + | dt_ref nodedef > { > /* > * We rely on the rule being always: > @@ -176,9 +180,12 @@ devicetree: > */ > if (!($<flags>-1 & DTSF_PLUGIN)) > ERROR(&@2, "Label or path %s not found", $1); > - $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1); > + $$ = add_orphan_node( > + name_node(build_node(NULL, NULL, NULL), > + ""), > + $2, $1); > } > - | devicetree DT_LABEL DT_REF nodedef > + | devicetree DT_LABEL dt_ref nodedef > { > struct node *target = get_node_by_ref($1, $3); > > @@ -189,7 +196,7 @@ devicetree: > ERROR(&@3, "Label or path %s not found", $3); > $$ = $1; > } > - | devicetree DT_REF nodedef > + | devicetree DT_PATH_REF nodedef > { > /* > * We rely on the rule being always: > @@ -208,7 +215,26 @@ devicetree: > } > $$ = $1; > } > - | devicetree DT_DEL_NODE DT_REF ';' > + | devicetree DT_LABEL_REF nodedef > + { > + struct node *target = get_node_by_ref($1, $2); > + > + if (target) { > + merge_nodes(target, $3); > + } else { > + /* > + * We rely on the rule being always: > + * versioninfo plugindecl memreserves devicetree > + * so $-1 is what we want (plugindecl) > + */ > + if ($<flags>-1 & DTSF_PLUGIN) > + add_orphan_node($1, $3, $2); > + else > + ERROR(&@2, "Label or path %s not found", $2); > + } > + $$ = $1; > + } > + | devicetree DT_DEL_NODE dt_ref ';' > { > struct node *target = get_node_by_ref($1, $3); > > @@ -220,7 +246,7 @@ devicetree: > > $$ = $1; > } > - | devicetree DT_OMIT_NO_REF DT_REF ';' > + | devicetree DT_OMIT_NO_REF dt_ref ';' > { > struct node *target = get_node_by_ref($1, $3); > > @@ -237,7 +263,7 @@ devicetree: > nodedef: > '{' proplist subnodes '}' ';' > { > - $$ = build_node($2, $3); > + $$ = build_node($2, $3, &@$); > } > ; > > @@ -255,11 +281,11 @@ proplist: > propdef: > DT_PROPNODENAME '=' propdata ';' > { > - $$ = build_property($1, $3); > + $$ = build_property($1, $3, &@$); > } > | DT_PROPNODENAME ';' > { > - $$ = build_property($1, empty_data); > + $$ = build_property($1, empty_data, &@$); > } > | DT_DEL_PROP DT_PROPNODENAME ';' > { > @@ -285,8 +311,9 @@ propdata: > { > $$ = data_merge($1, $3); > } > - | propdataprefix DT_REF > + | propdataprefix dt_ref > { > + $1 = data_add_marker($1, TYPE_STRING, $2); > $$ = data_add_marker($1, REF_PATH, $2); > } > | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' > @@ -382,7 +409,7 @@ arrayprefix: > > $$.data = data_append_integer($1.data, $2, $1.bits); > } > - | arrayprefix DT_REF > + | arrayprefix dt_ref > { > uint64_t val = ~0ULL >> (64 - $1.bits); > > @@ -539,7 +566,7 @@ subnode: > } > | DT_DEL_NODE DT_PROPNODENAME ';' > { > - $$ = name_node(build_node_delete(), $2); > + $$ = name_node(build_node_delete(&@$), $2); > } > | DT_OMIT_NO_REF subnode > { > diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c > index c36994e6ea..695e1f789f 100644 > --- a/scripts/dtc/dtc.c > +++ b/scripts/dtc/dtc.c > @@ -35,6 +35,8 @@ int phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties * > int generate_symbols; /* enable symbols & fixup support */ > int generate_fixups; /* suppress generation of fixups on symbol support */ > int auto_label_aliases; /* auto generate labels -> aliases */ > +int annotate; /* Level of annotation: 1 for input source location > + >1 for full input source location. */ > > static int is_power_of_2(int x) > { > @@ -60,7 +62,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix) > > /* Usage related data. */ > static const char usage_synopsis[] = "dtc [options] <input file>"; > -static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv"; > +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv"; > static struct option const usage_long_opts[] = { > {"quiet", no_argument, NULL, 'q'}, > {"in-format", a_argument, NULL, 'I'}, > @@ -81,6 +83,7 @@ static struct option const usage_long_opts[] = { > {"error", a_argument, NULL, 'E'}, > {"symbols", no_argument, NULL, '@'}, > {"auto-alias", no_argument, NULL, 'A'}, > + {"annotate", no_argument, NULL, 'T'}, > {"help", no_argument, NULL, 'h'}, > {"version", no_argument, NULL, 'v'}, > {NULL, no_argument, NULL, 0x0}, > @@ -95,6 +98,9 @@ static const char * const usage_opts_help[] = { > "\n\tOutput formats are:\n" > "\t\tdts - device tree source text\n" > "\t\tdtb - device tree blob\n" > +#ifndef NO_YAML > + "\t\tyaml - device tree encoded as YAML\n" > +#endif > "\t\tasm - assembler source", > "\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)", > "\n\tOutput dependency file", > @@ -114,6 +120,7 @@ static const char * const usage_opts_help[] = { > "\n\tEnable/disable errors (prefix with \"no-\")", > "\n\tEnable generation of symbols", > "\n\tEnable auto-alias of labels", > + "\n\tAnnotate output .dts with input source file and line (-T -T for more details)", > "\n\tPrint this help and exit", > "\n\tPrint version and exit", > NULL, > @@ -128,6 +135,8 @@ static const char *guess_type_by_name(const char *fname, const char *fallback) > return fallback; > if (!strcasecmp(s, ".dts")) > return "dts"; > + if (!strcasecmp(s, ".yaml")) > + return "yaml"; > if (!strcasecmp(s, ".dtb")) > return "dtb"; > return fallback; > @@ -259,6 +268,9 @@ int main(int argc, char *argv[]) > case 'A': > auto_label_aliases = 1; > break; > + case 'T': > + annotate++; > + break; > > case 'h': > usage(NULL); > @@ -297,6 +309,8 @@ int main(int argc, char *argv[]) > outform = "dts"; > } > } > + if (annotate && (!streq(inform, "dts") || !streq(outform, "dts"))) > + die("--annotate requires -I dts -O dts\n"); > if (streq(inform, "dts")) > dti = dt_from_source(arg); > else if (streq(inform, "fs")) > @@ -350,6 +364,12 @@ int main(int argc, char *argv[]) > > if (streq(outform, "dts")) { > dt_to_source(outf, dti); > +#ifndef NO_YAML > + } else if (streq(outform, "yaml")) { > + if (!streq(inform, "dts")) > + die("YAML output format requires dts input format\n"); > + dt_to_yaml(outf, dti); > +#endif > } else if (streq(outform, "dtb")) { > dt_to_blob(outf, dti, outversion); > } else if (streq(outform, "asm")) { > diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h > index 303c2a6a73..789e0b1bc0 100644 > --- a/scripts/dtc/dtc.h > +++ b/scripts/dtc/dtc.h > @@ -58,6 +58,7 @@ extern int phandle_format; /* Use linux,phandle or phandle properties */ > extern int generate_symbols; /* generate symbols for nodes with labels */ > extern int generate_fixups; /* generate fixups */ > extern int auto_label_aliases; /* auto generate labels -> aliases */ > +extern int annotate; /* annotate .dts with input source location */ > > #define PHANDLE_LEGACY 0x1 > #define PHANDLE_EPAPR 0x2 > @@ -82,7 +83,6 @@ enum markertype { > TYPE_UINT16, > TYPE_UINT32, > TYPE_UINT64, > - TYPE_BLOB, > TYPE_STRING, > }; > extern const char *markername(enum markertype markertype); > @@ -109,6 +109,8 @@ struct data { > for_each_marker(m) \ > if ((m)->type == (t)) > > +size_t type_marker_length(struct marker *m); > + > void data_free(struct data d); > > struct data data_grow_for(struct data d, int xlen); > @@ -157,6 +159,7 @@ struct property { > struct property *next; > > struct label *labels; > + struct srcpos *srcpos; > }; > > struct node { > @@ -176,6 +179,7 @@ struct node { > > struct label *labels; > const struct bus_type *bus; > + struct srcpos *srcpos; > > bool omit_if_unused, is_referenced; > }; > @@ -204,13 +208,15 @@ struct node { > 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(char *name, struct data val, > + struct srcpos *srcpos); > 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 *build_node(struct property *proplist, struct node *children, > + struct srcpos *srcpos); > +struct node *build_node_delete(struct srcpos *srcpos); > struct node *name_node(struct node *node, char *name); > struct node *omit_node_if_unused(struct node *node); > struct node *reference_node(struct node *node); > @@ -298,6 +304,10 @@ struct dt_info *dt_from_blob(const char *fname); > void dt_to_source(FILE *f, struct dt_info *dti); > struct dt_info *dt_from_source(const char *f); > > +/* YAML source */ > + > +void dt_to_yaml(FILE *f, struct dt_info *dti); > + > /* FS trees */ > > struct dt_info *dt_from_fs(const char *dirname); > diff --git a/scripts/dtc/fdtget.c b/scripts/dtc/fdtget.c > deleted file mode 100644 > index a79c3b2aa1..0000000000 > --- a/scripts/dtc/fdtget.c > +++ /dev/null > @@ -1,383 +0,0 @@ > -/* > - * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. > - * > - * Portions from U-Boot cmd_fdt.c (C) Copyright 2007 > - * Gerald Van Baren, Custom IDEAS, vanbaren@xxxxxxxxxx > - * Based on code written by: > - * Pantelis Antoniou <pantelis.antoniou@xxxxxxxxx> and > - * Matthew McClintock <msm@xxxxxxxxxxxxx> > - * > - * 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)); > -} > - > -/** > - * Shows a list of cells in the requested format > - * > - * @param disp Display information / options > - * @param data Data to display > - * @param len Maximum length of buffer > - * @param size Data size to use for display (e.g. 4 for 32-bit) > - * @return 0 if ok, -1 on error > - */ > -static int show_cell_list(struct display_info *disp, const char *data, int len, > - int size) > -{ > - const uint8_t *p = (const uint8_t *)data; > - char fmt[3]; > - int value; > - int i; > - > - 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_ld((const fdt32_t *)p) : > - size == 2 ? (*p << 8) | p[1] : *p; > - printf(fmt, value); > - } > - > - return 0; > -} > - > -/** > - * 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 size; > - const char *s; > - int is_string; > - > - /* 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; > - } > - > - return show_cell_list(disp, data, len, size); > -} > - > -/** > - * 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 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; > - fdt_getprop_by_offset(blob, prop, &name, NULL); > - 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 > - * @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, NULL); > - 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); > - free(blob); > - return -1; > - } > - } > - prop = args_per_step == 1 ? NULL : arg[i + 1]; > - > - if (show_data_for_item(blob, disp, node, prop)) { > - free(blob); > - return -1; > - } > - } > - > - free(blob); > - > - return 0; > -} > - > -/* Usage related data. */ > -static const char usage_synopsis[] = > - "read values from device tree\n" > - " fdtget <options> <dt file> [<node> <property>]...\n" > - " fdtget -p <options> <dt file> [<node> ]...\n" > - "\n" > - "Each value is printed on a new line.\n" > - USAGE_TYPE_MSG; > -static const char usage_short_opts[] = "t:pld:" USAGE_COMMON_SHORT_OPTS; > -static struct option const usage_long_opts[] = { > - {"type", a_argument, NULL, 't'}, > - {"properties", no_argument, NULL, 'p'}, > - {"list", no_argument, NULL, 'l'}, > - {"default", a_argument, NULL, 'd'}, > - USAGE_COMMON_LONG_OPTS, > -}; > -static const char * const usage_opts_help[] = { > - "Type of data", > - "List properties for each node", > - "List subnodes for each node", > - "Default value to display when the property is missing", > - USAGE_COMMON_OPTS_HELP > -}; > - > -int main(int argc, char *argv[]) > -{ > - int opt; > - char *filename = NULL; > - struct display_info disp; > - int args_per_step = 2; > - > - /* set defaults */ > - memset(&disp, '\0', sizeof(disp)); > - disp.size = -1; > - disp.mode = MODE_SHOW_VALUE; > - while ((opt = util_getopt_long()) != EOF) { > - switch (opt) { > - case_USAGE_COMMON_FLAGS > - > - case 't': > - if (utilfdt_decode_type(optarg, &disp.type, > - &disp.size)) > - usage("invalid type string"); > - 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/flattree.c b/scripts/dtc/flattree.c > index 851ea87dbc..acf04c3066 100644 > --- a/scripts/dtc/flattree.c > +++ b/scripts/dtc/flattree.c > @@ -692,7 +692,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf, > > val = flat_read_data(dtbuf, proplen); > > - return build_property(name, val); > + return build_property(name, val, NULL); > } > > > @@ -750,7 +750,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, > char *flatname; > uint32_t val; > > - node = build_node(NULL, NULL); > + node = build_node(NULL, NULL, NULL); > > flatname = flat_read_string(dtbuf); > > diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c > index ae7d06c3c4..1e7eeba47f 100644 > --- a/scripts/dtc/fstree.c > +++ b/scripts/dtc/fstree.c > @@ -34,7 +34,7 @@ static struct node *read_fstree(const char *dirname) > if (!d) > die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno)); > > - tree = build_node(NULL, NULL); > + tree = build_node(NULL, NULL, NULL); > > while ((de = readdir(d)) != NULL) { > char *tmpname; > @@ -60,7 +60,8 @@ static struct node *read_fstree(const char *dirname) > } else { > prop = build_property(xstrdup(de->d_name), > data_copy_file(pfile, > - st.st_size)); > + st.st_size), > + NULL); > add_property(tree, prop); > fclose(pfile); > } > diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt > new file mode 100644 > index 0000000000..3af3656df8 > --- /dev/null > +++ b/scripts/dtc/libfdt/Makefile.libfdt > @@ -0,0 +1,15 @@ > +# Makefile.libfdt > +# > +# This is not a complete Makefile of itself. Instead, it is designed to > +# be easily embeddable into other systems of Makefiles. > +# > +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 \ > + fdt_addresses.c fdt_overlay.c > +LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) > + > +libfdt_clean: > + @$(VECHO) CLEAN "(libfdt)" > + rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%) > diff --git a/scripts/dtc/fdt.c b/scripts/dtc/libfdt/fdt.c > similarity index 100% > rename from scripts/dtc/fdt.c > rename to scripts/dtc/libfdt/fdt.c > diff --git a/scripts/dtc/fdt.h b/scripts/dtc/libfdt/fdt.h > similarity index 100% > rename from scripts/dtc/fdt.h > rename to scripts/dtc/libfdt/fdt.h > diff --git a/scripts/dtc/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c > similarity index 92% > rename from scripts/dtc/fdt_addresses.c > rename to scripts/dtc/libfdt/fdt_addresses.c > index 49537b578d..f13a87dfa0 100644 > --- a/scripts/dtc/fdt_addresses.c > +++ b/scripts/dtc/libfdt/fdt_addresses.c > @@ -64,7 +64,7 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name) > > c = fdt_getprop(fdt, nodeoffset, name, &len); > if (!c) > - return 2; > + return len; > > if (len != sizeof(*c)) > return -FDT_ERR_BADNCELLS; > @@ -78,10 +78,20 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name) > > int fdt_address_cells(const void *fdt, int nodeoffset) > { > - return fdt_cells(fdt, nodeoffset, "#address-cells"); > + int val; > + > + val = fdt_cells(fdt, nodeoffset, "#address-cells"); > + if (val == -FDT_ERR_NOTFOUND) > + return 2; > + return val; > } > > int fdt_size_cells(const void *fdt, int nodeoffset) > { > - return fdt_cells(fdt, nodeoffset, "#size-cells"); > + int val; > + > + val = fdt_cells(fdt, nodeoffset, "#size-cells"); > + if (val == -FDT_ERR_NOTFOUND) > + return 1; > + return val; > } > diff --git a/scripts/dtc/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c > similarity index 100% > rename from scripts/dtc/fdt_empty_tree.c > rename to scripts/dtc/libfdt/fdt_empty_tree.c > diff --git a/scripts/dtc/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c > similarity index 100% > rename from scripts/dtc/fdt_overlay.c > rename to scripts/dtc/libfdt/fdt_overlay.c > diff --git a/scripts/dtc/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c > similarity index 100% > rename from scripts/dtc/fdt_ro.c > rename to scripts/dtc/libfdt/fdt_ro.c > diff --git a/scripts/dtc/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c > similarity index 100% > rename from scripts/dtc/fdt_rw.c > rename to scripts/dtc/libfdt/fdt_rw.c > diff --git a/scripts/dtc/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c > similarity index 100% > rename from scripts/dtc/fdt_strerror.c > rename to scripts/dtc/libfdt/fdt_strerror.c > diff --git a/scripts/dtc/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c > similarity index 100% > rename from scripts/dtc/fdt_sw.c > rename to scripts/dtc/libfdt/fdt_sw.c > diff --git a/scripts/dtc/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c > similarity index 100% > rename from scripts/dtc/fdt_wip.c > rename to scripts/dtc/libfdt/fdt_wip.c > diff --git a/scripts/dtc/libfdt.h b/scripts/dtc/libfdt/libfdt.h > similarity index 99% > rename from scripts/dtc/libfdt.h > rename to scripts/dtc/libfdt/libfdt.h > index 2bd151dd35..15eb0fd3c6 100644 > --- a/scripts/dtc/libfdt.h > +++ b/scripts/dtc/libfdt/libfdt.h > @@ -163,18 +163,26 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); > > static inline uint32_t fdt32_ld(const fdt32_t *p) > { > - fdt32_t v; > + const uint8_t *bp = (const uint8_t *)p; > > - memcpy(&v, p, sizeof(v)); > - return fdt32_to_cpu(v); > + return ((uint32_t)bp[0] << 24) > + | ((uint32_t)bp[1] << 16) > + | ((uint32_t)bp[2] << 8) > + | bp[3]; > } > > static inline uint64_t fdt64_ld(const fdt64_t *p) > { > - fdt64_t v; > - > - memcpy(&v, p, sizeof(v)); > - return fdt64_to_cpu(v); > + const uint8_t *bp = (const uint8_t *)p; > + > + return ((uint64_t)bp[0] << 56) > + | ((uint64_t)bp[1] << 48) > + | ((uint64_t)bp[2] << 40) > + | ((uint64_t)bp[3] << 32) > + | ((uint64_t)bp[4] << 24) > + | ((uint64_t)bp[5] << 16) > + | ((uint64_t)bp[6] << 8) > + | bp[7]; > } > > /**********************************************************************/ > @@ -219,7 +227,7 @@ int fdt_next_subnode(const void *fdt, int offset); > * ... > * } > * > - * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) { > + * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) { > * Error handling > * } > * > @@ -558,7 +566,7 @@ int fdt_next_property_offset(const void *fdt, int offset); > * ... > * } > * > - * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) { > + * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) { > * Error handling > * } > * > @@ -661,7 +669,7 @@ 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 > + * @offset: 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 > * > @@ -1145,7 +1153,7 @@ int fdt_address_cells(const void *fdt, int nodeoffset); > * > * returns: > * 0 <= n < FDT_MAX_NCELLS, on success > - * 2, if the node has no #size-cells property > + * 1, if the node has no #size-cells property > * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid > * #size-cells property > * -FDT_ERR_BADMAGIC, > diff --git a/scripts/dtc/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h > similarity index 100% > rename from scripts/dtc/libfdt_env.h > rename to scripts/dtc/libfdt/libfdt_env.h > diff --git a/scripts/dtc/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h > similarity index 100% > rename from scripts/dtc/libfdt_internal.h > rename to scripts/dtc/libfdt/libfdt_internal.h > diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c > index 4ff0679e00..7a2e6446a1 100644 > --- a/scripts/dtc/livetree.c > +++ b/scripts/dtc/livetree.c > @@ -19,6 +19,7 @@ > */ > > #include "dtc.h" > +#include "srcpos.h" > > /* > * Tree building functions > @@ -50,7 +51,8 @@ void delete_labels(struct label **labels) > label->deleted = 1; > } > > -struct property *build_property(char *name, struct data val) > +struct property *build_property(char *name, struct data val, > + struct srcpos *srcpos) > { > struct property *new = xmalloc(sizeof(*new)); > > @@ -58,6 +60,7 @@ struct property *build_property(char *name, struct data val) > > new->name = name; > new->val = val; > + new->srcpos = srcpos_copy(srcpos); > > return new; > } > @@ -97,7 +100,8 @@ struct property *reverse_properties(struct property *first) > return head; > } > > -struct node *build_node(struct property *proplist, struct node *children) > +struct node *build_node(struct property *proplist, struct node *children, > + struct srcpos *srcpos) > { > struct node *new = xmalloc(sizeof(*new)); > struct node *child; > @@ -106,6 +110,7 @@ struct node *build_node(struct property *proplist, struct node *children) > > new->proplist = reverse_properties(proplist); > new->children = children; > + new->srcpos = srcpos_copy(srcpos); > > for_each_child(new, child) { > child->parent = new; > @@ -114,13 +119,14 @@ struct node *build_node(struct property *proplist, struct node *children) > return new; > } > > -struct node *build_node_delete(void) > +struct node *build_node_delete(struct srcpos *srcpos) > { > struct node *new = xmalloc(sizeof(*new)); > > memset(new, 0, sizeof(*new)); > > new->deleted = 1; > + new->srcpos = srcpos_copy(srcpos); > > return new; > } > @@ -183,6 +189,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) > > old_prop->val = new_prop->val; > old_prop->deleted = 0; > + free(old_prop->srcpos); > + old_prop->srcpos = new_prop->srcpos; > free(new_prop); > new_prop = NULL; > break; > @@ -223,6 +231,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) > add_child(old_node, new_child); > } > > + old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos); > + > /* The new node contents are now merged into the old node. Free > * the new node. */ > free(new_node); > @@ -241,18 +251,18 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) > if (ref[0] == '/') { > d = data_append_data(d, ref, strlen(ref) + 1); > > - p = build_property("target-path", d); > + p = build_property("target-path", d, NULL); > } else { > d = data_add_marker(d, REF_PHANDLE, ref); > d = data_append_integer(d, 0xffffffff, 32); > > - p = build_property("target", d); > + p = build_property("target", d, NULL); > } > > xasprintf(&name, "fragment@%u", > next_orphan_fragment++); > name_node(new_node, "__overlay__"); > - node = build_node(p, new_node); > + node = build_node(p, new_node, NULL); > name_node(node, name); > > add_child(dt, node); > @@ -351,7 +361,7 @@ void append_to_property(struct node *node, > p->val = d; > } else { > d = data_append_data(empty_data, data, len); > - p = build_property(name, d); > + p = build_property(name, d, NULL); > add_property(node, p); > } > } > @@ -609,11 +619,11 @@ cell_t get_node_phandle(struct node *root, struct node *node) > > if (!get_property(node, "linux,phandle") > && (phandle_format & PHANDLE_LEGACY)) > - add_property(node, build_property("linux,phandle", d)); > + add_property(node, build_property("linux,phandle", d, NULL)); > > if (!get_property(node, "phandle") > && (phandle_format & PHANDLE_EPAPR)) > - add_property(node, build_property("phandle", d)); > + add_property(node, build_property("phandle", d, NULL)); > > /* If the node *does* have a phandle property, we must > * be dealing with a self-referencing phandle, which will be > @@ -787,7 +797,7 @@ static struct node *build_and_name_child_node(struct node *parent, char *name) > { > struct node *node; > > - node = build_node(NULL, NULL); > + node = build_node(NULL, NULL, NULL); > name_node(node, xstrdup(name)); > add_child(parent, node); > > @@ -849,7 +859,8 @@ static void generate_label_tree_internal(struct dt_info *dti, > /* insert it */ > p = build_property(l->label, > data_copy_mem(node->fullpath, > - strlen(node->fullpath) + 1)); > + strlen(node->fullpath) + 1), > + NULL); > add_property(an, p); > } > > diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c > index cb6ed0e3e5..41f83700ee 100644 > --- a/scripts/dtc/srcpos.c > +++ b/scripts/dtc/srcpos.c > @@ -33,6 +33,9 @@ struct search_path { > /* This is the list of directories that we search for source files */ > static struct search_path *search_path_head, **search_path_tail; > > +/* Detect infinite include recursion. */ > +#define MAX_SRCFILE_DEPTH (100) > +static int srcfile_depth; /* = 0 */ > > static char *get_dirname(const char *path) > { > @@ -51,11 +54,51 @@ static char *get_dirname(const char *path) > > FILE *depfile; /* = NULL */ > struct srcfile_state *current_srcfile; /* = NULL */ > +static char *initial_path; /* = NULL */ > +static int initial_pathlen; /* = 0 */ > +static bool initial_cpp = true; > > -/* Detect infinite include recursion. */ > -#define MAX_SRCFILE_DEPTH (100) > -static int srcfile_depth; /* = 0 */ > +static void set_initial_path(char *fname) > +{ > + int i, len = strlen(fname); > > + xasprintf(&initial_path, "%s", fname); > + initial_pathlen = 0; > + for (i = 0; i != len; i++) > + if (initial_path[i] == '/') > + initial_pathlen++; > +} > + > +static char *shorten_to_initial_path(char *fname) > +{ > + char *p1, *p2, *prevslash1 = NULL; > + int slashes = 0; > + > + for (p1 = fname, p2 = initial_path; *p1 && *p2; p1++, p2++) { > + if (*p1 != *p2) > + break; > + if (*p1 == '/') { > + prevslash1 = p1; > + slashes++; > + } > + } > + p1 = prevslash1 + 1; > + if (prevslash1) { > + int diff = initial_pathlen - slashes, i, j; > + int restlen = strlen(fname) - (p1 - fname); > + char *res; > + > + res = xmalloc((3 * diff) + restlen + 1); > + for (i = 0, j = 0; i != diff; i++) { > + res[j++] = '.'; > + res[j++] = '.'; > + res[j++] = '/'; > + } > + strcpy(res + j, p1); > + return res; > + } > + return NULL; > +} > > /** > * Try to open a file in a given directory. > @@ -157,6 +200,9 @@ void srcfile_push(const char *fname) > srcfile->colno = 1; > > current_srcfile = srcfile; > + > + if (srcfile_depth == 1) > + set_initial_path(srcfile->name); > } > > bool srcfile_pop(void) > @@ -197,18 +243,6 @@ void srcfile_add_search_path(const char *dirname) > search_path_tail = &node->next; > } > > -/* > - * The empty source position. > - */ > - > -struct srcpos srcpos_empty = { > - .first_line = 0, > - .first_column = 0, > - .last_line = 0, > - .last_column = 0, > - .file = NULL, > -}; > - > void srcpos_update(struct srcpos *pos, const char *text, int len) > { > int i; > @@ -234,13 +268,35 @@ struct srcpos * > srcpos_copy(struct srcpos *pos) > { > struct srcpos *pos_new; > + struct srcfile_state *srcfile_state; > + > + if (!pos) > + return NULL; > > pos_new = xmalloc(sizeof(struct srcpos)); > + assert(pos->next == NULL); > memcpy(pos_new, pos, sizeof(struct srcpos)); > > + /* allocate without free */ > + srcfile_state = xmalloc(sizeof(struct srcfile_state)); > + memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state)); > + pos_new->file = srcfile_state; > + > return pos_new; > } > > +struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail) > +{ > + struct srcpos *p; > + > + if (!pos) > + return newtail; > + > + for (p = pos; p->next != NULL; p = p->next); > + p->next = newtail; > + return pos; > +} > + > char * > srcpos_string(struct srcpos *pos) > { > @@ -266,6 +322,68 @@ srcpos_string(struct srcpos *pos) > return pos_str; > } > > +static char * > +srcpos_string_comment(struct srcpos *pos, bool first_line, int level) > +{ > + char *pos_str, *fname, *first, *rest; > + bool fresh_fname = false; > + > + if (!pos) { > + if (level > 1) { > + xasprintf(&pos_str, "<no-file>:<no-line>"); > + return pos_str; > + } else { > + return NULL; > + } > + } > + > + if (!pos->file) > + fname = "<no-file>"; > + else if (!pos->file->name) > + fname = "<no-filename>"; > + else if (level > 1) > + fname = pos->file->name; > + else { > + fname = shorten_to_initial_path(pos->file->name); > + if (fname) > + fresh_fname = true; > + else > + fname = pos->file->name; > + } > + > + if (level > 1) > + xasprintf(&first, "%s:%d:%d-%d:%d", fname, > + pos->first_line, pos->first_column, > + pos->last_line, pos->last_column); > + else > + xasprintf(&first, "%s:%d", fname, > + first_line ? pos->first_line : pos->last_line); > + > + if (fresh_fname) > + free(fname); > + > + if (pos->next != NULL) { > + rest = srcpos_string_comment(pos->next, first_line, level); > + xasprintf(&pos_str, "%s, %s", first, rest); > + free(first); > + free(rest); > + } else { > + pos_str = first; > + } > + > + return pos_str; > +} > + > +char *srcpos_string_first(struct srcpos *pos, int level) > +{ > + return srcpos_string_comment(pos, true, level); > +} > + > +char *srcpos_string_last(struct srcpos *pos, int level) > +{ > + return srcpos_string_comment(pos, false, level); > +} > + > void srcpos_verror(struct srcpos *pos, const char *prefix, > const char *fmt, va_list va) > { > @@ -294,4 +412,9 @@ void srcpos_set_line(char *f, int l) > { > current_srcfile->name = f; > current_srcfile->lineno = l; > + > + if (initial_cpp) { > + initial_cpp = false; > + set_initial_path(f); > + } > } > diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h > index 9ded12a383..6326a952c4 100644 > --- a/scripts/dtc/srcpos.h > +++ b/scripts/dtc/srcpos.h > @@ -74,6 +74,7 @@ struct srcpos { > int last_line; > int last_column; > struct srcfile_state *file; > + struct srcpos *next; > }; > > #define YYLTYPE struct srcpos > @@ -93,19 +94,18 @@ struct srcpos { > YYRHSLOC(Rhs, 0).last_column; \ > (Current).file = YYRHSLOC (Rhs, 0).file; \ > } \ > + (Current).next = NULL; \ > } while (0) > > > -/* > - * Fictional source position used for IR nodes that are > - * created without otherwise knowing a true source position. > - * For example,constant definitions from the command line. > - */ > -extern struct srcpos srcpos_empty; > - > extern void srcpos_update(struct srcpos *pos, const char *text, int len); > extern struct srcpos *srcpos_copy(struct srcpos *pos); > +extern struct srcpos *srcpos_extend(struct srcpos *new_srcpos, > + struct srcpos *old_srcpos); > extern char *srcpos_string(struct srcpos *pos); > +extern char *srcpos_string_first(struct srcpos *pos, int level); > +extern char *srcpos_string_last(struct srcpos *pos, int level); > + > > extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix, > const char *fmt, va_list va); > diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c > index f99544d723..1af36628b7 100644 > --- a/scripts/dtc/treesource.c > +++ b/scripts/dtc/treesource.c > @@ -64,6 +64,10 @@ static bool isstring(char c) > static void write_propval_string(FILE *f, const char *s, size_t len) > { > const char *end = s + len - 1; > + > + if (!len) > + return; > + > assert(*end == '\0'); > > fprintf(f, "\""); > @@ -118,29 +122,36 @@ static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) > for (; p < end; p += width) { > switch (width) { > case 1: > - fprintf(f, " %02"PRIx8, *(const uint8_t*)p); > + fprintf(f, "%02"PRIx8, *(const uint8_t*)p); > break; > case 2: > - fprintf(f, " 0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p)); > + fprintf(f, "0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p)); > break; > case 4: > - fprintf(f, " 0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); > + fprintf(f, "0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); > break; > case 8: > - fprintf(f, " 0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); > + fprintf(f, "0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); > break; > } > + if (p + width < end) > + fputc(' ', f); > } > } > > +static bool has_data_type_information(struct marker *m) > +{ > + return m->type >= TYPE_UINT8; > +} > + > static struct marker *next_type_marker(struct marker *m) > { > - while (m && (m->type == LABEL || m->type == REF_PHANDLE || m->type == REF_PATH)) > + while (m && !has_data_type_information(m)) > m = m->next; > return m; > } > > -static size_t type_marker_length(struct marker *m) > +size_t type_marker_length(struct marker *m) > { > struct marker *next = next_type_marker(m->next); > > @@ -157,10 +168,10 @@ static const char *delim_start[] = { > [TYPE_STRING] = "", > }; > static const char *delim_end[] = { > - [TYPE_UINT8] = " ]", > - [TYPE_UINT16] = " >", > - [TYPE_UINT32] = " >", > - [TYPE_UINT64] = " >", > + [TYPE_UINT8] = "]", > + [TYPE_UINT16] = ">", > + [TYPE_UINT32] = ">", > + [TYPE_UINT64] = ">", > [TYPE_STRING] = "", > }; > > @@ -203,13 +214,22 @@ static void write_propval(FILE *f, struct property *prop) > struct marker *m = prop->val.markers; > struct marker dummy_marker; > enum markertype emit_type = TYPE_NONE; > + char *srcstr; > > if (len == 0) { > - fprintf(f, ";\n"); > + fprintf(f, ";"); > + if (annotate) { > + srcstr = srcpos_string_first(prop->srcpos, annotate); > + if (srcstr) { > + fprintf(f, " /* %s */", srcstr); > + free(srcstr); > + } > + } > + fprintf(f, "\n"); > return; > } > > - fprintf(f, " = "); > + fprintf(f, " ="); > > if (!next_type_marker(m)) { > /* data type information missing, need to guess */ > @@ -220,32 +240,23 @@ static void write_propval(FILE *f, struct property *prop) > m = &dummy_marker; > } > > - struct marker *m_label = prop->val.markers; > for_each_marker(m) { > - size_t chunk_len; > + size_t chunk_len = (m->next ? m->next->offset : len) - m->offset; > + size_t data_len = type_marker_length(m) ? : len - m->offset; > const char *p = &prop->val.val[m->offset]; > > - if (m->type < TYPE_UINT8) > - continue; > - > - chunk_len = type_marker_length(m); > - if (!chunk_len) > - chunk_len = len - m->offset; > - > - if (emit_type != TYPE_NONE) > - fprintf(f, "%s, ", delim_end[emit_type]); > - emit_type = m->type; > - > - for_each_marker_of_type(m_label, LABEL) { > - if (m_label->offset > m->offset) > - break; > - fprintf(f, "%s: ", m_label->ref); > - } > - > - fprintf(f, "%s", delim_start[emit_type]); > + if (has_data_type_information(m)) { > + emit_type = m->type; > + fprintf(f, " %s", delim_start[emit_type]); > + } else if (m->type == LABEL) > + fprintf(f, " %s:", m->ref); > + else if (m->offset) > + fputc(' ', f); > > - if (chunk_len <= 0) > + if (emit_type == TYPE_NONE) { > + assert(chunk_len == 0); > continue; > + } > > switch(emit_type) { > case TYPE_UINT16: > @@ -263,15 +274,23 @@ static void write_propval(FILE *f, struct property *prop) > default: > write_propval_int(f, p, chunk_len, 1); > } > - } > > - /* Wrap up any labels at the end of the value */ > - for_each_marker_of_type(m_label, LABEL) { > - assert (m_label->offset == len); > - fprintf(f, " %s:", m_label->ref); > + if (chunk_len == data_len) { > + size_t pos = m->offset + chunk_len; > + fprintf(f, pos == len ? "%s" : "%s,", > + delim_end[emit_type] ? : ""); > + emit_type = TYPE_NONE; > + } > } > - > - fprintf(f, "%s;\n", delim_end[emit_type] ? : ""); > + fprintf(f, ";"); > + if (annotate) { > + srcstr = srcpos_string_first(prop->srcpos, annotate); > + if (srcstr) { > + fprintf(f, " /* %s */", srcstr); > + free(srcstr); > + } > + } > + fprintf(f, "\n"); > } > > static void write_tree_source_node(FILE *f, struct node *tree, int level) > @@ -279,14 +298,24 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) > struct property *prop; > struct node *child; > struct label *l; > + char *srcstr; > > write_prefix(f, level); > for_each_label(tree->labels, l) > fprintf(f, "%s: ", l->label); > if (tree->name && (*tree->name)) > - fprintf(f, "%s {\n", tree->name); > + fprintf(f, "%s {", tree->name); > else > - fprintf(f, "/ {\n"); > + fprintf(f, "/ {"); > + > + if (annotate) { > + srcstr = srcpos_string_first(tree->srcpos, annotate); > + if (srcstr) { > + fprintf(f, " /* %s */", srcstr); > + free(srcstr); > + } > + } > + fprintf(f, "\n"); > > for_each_property(tree, prop) { > write_prefix(f, level+1); > @@ -300,10 +329,17 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) > write_tree_source_node(f, child, level+1); > } > write_prefix(f, level); > - fprintf(f, "};\n"); > + fprintf(f, "};"); > + if (annotate) { > + srcstr = srcpos_string_last(tree->srcpos, annotate); > + if (srcstr) { > + fprintf(f, " /* %s */", srcstr); > + free(srcstr); > + } > + } > + fprintf(f, "\n"); > } > > - > void dt_to_source(FILE *f, struct dt_info *dti) > { > struct reserve_info *re; > diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c > index a69b7a1346..9c6fb5f286 100644 > --- a/scripts/dtc/util.c > +++ b/scripts/dtc/util.c > @@ -46,36 +46,54 @@ char *xstrdup(const char *s) > return d; > } > > -/* based in part from (3) vsnprintf */ > -int xasprintf(char **strp, const char *fmt, ...) > +int xavsprintf_append(char **strp, const char *fmt, va_list ap) > { > - int n, size = 128; /* start with 128 bytes */ > + int n, size = 0; /* start with 128 bytes */ > char *p; > - va_list ap; > + va_list ap_copy; > > - /* initial pointer is NULL making the fist realloc to be malloc */ > - p = NULL; > - while (1) { > - p = xrealloc(p, size); > + p = *strp; > + if (p) > + size = strlen(p); > > - /* Try to print in the allocated space. */ > - va_start(ap, fmt); > - n = vsnprintf(p, size, fmt, ap); > - va_end(ap); > + va_copy(ap_copy, ap); > + n = vsnprintf(NULL, 0, fmt, ap_copy) + 1; > + va_end(ap_copy); > + > + p = xrealloc(p, size + n); > + > + n = vsnprintf(p + size, n, fmt, ap); > > - /* If that worked, return the string. */ > - if (n > -1 && n < size) > - break; > - /* Else try again with more space. */ > - if (n > -1) /* glibc 2.1 */ > - size = n + 1; /* precisely what is needed */ > - else /* glibc 2.0 */ > - size *= 2; /* twice the old size */ > - } > *strp = p; > return strlen(p); > } > > +int xasprintf_append(char **strp, const char *fmt, ...) > +{ > + int n; > + va_list ap; > + > + va_start(ap, fmt); > + n = xavsprintf_append(strp, fmt, ap); > + va_end(ap); > + > + return n; > +} > + > +int xasprintf(char **strp, const char *fmt, ...) > +{ > + int n; > + va_list ap; > + > + *strp = NULL; > + > + va_start(ap, fmt); > + n = xavsprintf_append(strp, fmt, ap); > + va_end(ap); > + > + return n; > +} > + > char *join_path(const char *path, const char *name) > { > int lenp = strlen(path); > diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h > index f6cea82741..7658781a62 100644 > --- a/scripts/dtc/util.h > +++ b/scripts/dtc/util.h > @@ -72,6 +72,8 @@ static inline void *xrealloc(void *p, size_t len) > extern char *xstrdup(const char *s); > > extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...); > +extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...); > +extern int xavsprintf_append(char **strp, const char *fmt, va_list ap); > extern char *join_path(const char *path, const char *name); > > /** > diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h > index 2adf65b761..5c04ba938c 100644 > --- a/scripts/dtc/version_gen.h > +++ b/scripts/dtc/version_gen.h > @@ -1 +1 @@ > -#define DTC_VERSION "DTC 1.4.7" > +#define DTC_VERSION "DTC 1.5.0" > diff --git a/scripts/dtc/yamltree.c b/scripts/dtc/yamltree.c > new file mode 100644 > index 0000000000..a00285a5a9 > --- /dev/null > +++ b/scripts/dtc/yamltree.c > @@ -0,0 +1,247 @@ > +/* > + * (C) Copyright Linaro, Ltd. 2018 > + * (C) Copyright Arm Holdings. 2017 > + * (C) Copyright David Gibson <dwg@xxxxxxxxxxx>, IBM Corporation. 2005. > + * > + * 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 <stdlib.h> > +#include <yaml.h> > +#include "dtc.h" > +#include "srcpos.h" > + > +char *yaml_error_name[] = { > + [YAML_NO_ERROR] = "no error", > + [YAML_MEMORY_ERROR] = "memory error", > + [YAML_READER_ERROR] = "reader error", > + [YAML_SCANNER_ERROR] = "scanner error", > + [YAML_PARSER_ERROR] = "parser error", > + [YAML_COMPOSER_ERROR] = "composer error", > + [YAML_WRITER_ERROR] = "writer error", > + [YAML_EMITTER_ERROR] = "emitter error", > +}; > + > +#define yaml_emitter_emit_or_die(emitter, event) ( \ > +{ \ > + if (!yaml_emitter_emit(emitter, event)) \ > + die("yaml '%s': %s in %s, line %i\n", \ > + yaml_error_name[(emitter)->error], \ > + (emitter)->problem, __func__, __LINE__); \ > +}) > + > +static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width) > +{ > + yaml_event_t event; > + void *tag; > + int off, start_offset = markers->offset; > + > + switch(width) { > + case 1: tag = "!u8"; break; > + case 2: tag = "!u16"; break; > + case 4: tag = "!u32"; break; > + case 8: tag = "!u64"; break; > + default: > + die("Invalid width %i", width); > + } > + assert(len % width == 0); > + > + yaml_sequence_start_event_initialize(&event, NULL, > + (yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > + > + for (off = 0; off < len; off += width) { > + char buf[32]; > + struct marker *m; > + bool is_phandle = false; > + > + switch(width) { > + case 1: > + sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off)); > + break; > + case 2: > + sprintf(buf, "0x%"PRIx16, fdt16_to_cpu(*(fdt16_t*)(data + off))); > + break; > + case 4: > + sprintf(buf, "0x%"PRIx32, fdt32_to_cpu(*(fdt32_t*)(data + off))); > + m = markers; > + is_phandle = false; > + for_each_marker_of_type(m, REF_PHANDLE) { > + if (m->offset == (start_offset + off)) { > + is_phandle = true; > + break; > + } > + } > + break; > + case 8: > + sprintf(buf, "0x%"PRIx64, fdt64_to_cpu(*(fdt64_t*)(data + off))); > + break; > + } > + > + if (is_phandle) > + yaml_scalar_event_initialize(&event, NULL, > + (yaml_char_t*)"!phandle", (yaml_char_t *)buf, > + strlen(buf), 0, 0, YAML_PLAIN_SCALAR_STYLE); > + else > + yaml_scalar_event_initialize(&event, NULL, > + (yaml_char_t*)YAML_INT_TAG, (yaml_char_t *)buf, > + strlen(buf), 1, 1, YAML_PLAIN_SCALAR_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > + } > + > + yaml_sequence_end_event_initialize(&event); > + yaml_emitter_emit_or_die(emitter, &event); > +} > + > +static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len) > +{ > + yaml_event_t event; > + int i; > + > + assert(str[len-1] == '\0'); > + > + /* Make sure the entire string is in the lower 7-bit ascii range */ > + for (i = 0; i < len; i++) > + assert(isascii(str[i])); > + > + yaml_scalar_event_initialize(&event, NULL, > + (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)str, > + len-1, 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > +} > + > +static void yaml_propval(yaml_emitter_t *emitter, struct property *prop) > +{ > + yaml_event_t event; > + int len = prop->val.len; > + struct marker *m = prop->val.markers; > + > + /* Emit the property name */ > + yaml_scalar_event_initialize(&event, NULL, > + (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)prop->name, > + strlen(prop->name), 1, 1, YAML_PLAIN_SCALAR_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > + > + /* Boolean properties are easiest to deal with. Length is zero, so just emit 'true' */ > + if (len == 0) { > + yaml_scalar_event_initialize(&event, NULL, > + (yaml_char_t *)YAML_BOOL_TAG, > + (yaml_char_t*)"true", > + strlen("true"), 1, 0, YAML_PLAIN_SCALAR_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > + return; > + } > + > + if (!m) > + die("No markers present in property '%s' value\n", prop->name); > + > + yaml_sequence_start_event_initialize(&event, NULL, > + (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > + > + for_each_marker(m) { > + int chunk_len; > + char *data = &prop->val.val[m->offset]; > + > + if (m->type < TYPE_UINT8) > + continue; > + > + chunk_len = type_marker_length(m) ? : len; > + assert(chunk_len > 0); > + len -= chunk_len; > + > + switch(m->type) { > + case TYPE_UINT16: > + yaml_propval_int(emitter, m, data, chunk_len, 2); > + break; > + case TYPE_UINT32: > + yaml_propval_int(emitter, m, data, chunk_len, 4); > + break; > + case TYPE_UINT64: > + yaml_propval_int(emitter, m, data, chunk_len, 8); > + break; > + case TYPE_STRING: > + yaml_propval_string(emitter, data, chunk_len); > + break; > + default: > + yaml_propval_int(emitter, m, data, chunk_len, 1); > + break; > + } > + } > + > + yaml_sequence_end_event_initialize(&event); > + yaml_emitter_emit_or_die(emitter, &event); > +} > + > + > +static void yaml_tree(struct node *tree, yaml_emitter_t *emitter) > +{ > + struct property *prop; > + struct node *child; > + yaml_event_t event; > + > + if (tree->deleted) > + return; > + > + yaml_mapping_start_event_initialize(&event, NULL, > + (yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > + > + for_each_property(tree, prop) > + yaml_propval(emitter, prop); > + > + /* Loop over all the children, emitting them into the map */ > + for_each_child(tree, child) { > + yaml_scalar_event_initialize(&event, NULL, > + (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)child->name, > + strlen(child->name), 1, 0, YAML_PLAIN_SCALAR_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > + yaml_tree(child, emitter); > + } > + > + yaml_mapping_end_event_initialize(&event); > + yaml_emitter_emit_or_die(emitter, &event); > +} > + > +void dt_to_yaml(FILE *f, struct dt_info *dti) > +{ > + yaml_emitter_t emitter; > + yaml_event_t event; > + > + yaml_emitter_initialize(&emitter); > + yaml_emitter_set_output_file(&emitter, f); > + yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING); > + yaml_emitter_emit_or_die(&emitter, &event); > + > + yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0); > + yaml_emitter_emit_or_die(&emitter, &event); > + > + yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_ANY_SEQUENCE_STYLE); > + yaml_emitter_emit_or_die(&emitter, &event); > + > + yaml_tree(dti->dt, &emitter); > + > + yaml_sequence_end_event_initialize(&event); > + yaml_emitter_emit_or_die(&emitter, &event); > + > + yaml_document_end_event_initialize(&event, 0); > + yaml_emitter_emit_or_die(&emitter, &event); > + > + yaml_stream_end_event_initialize(&event); > + yaml_emitter_emit_or_die(&emitter, &event); > + > + yaml_emitter_delete(&emitter); > +} > -- > 2.20.1 > > > _______________________________________________ > barebox mailing list > barebox@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/barebox > -- Roland Hieber | r.hieber@xxxxxxxxxxxxxx | Pengutronix e.K. | https://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim | Phone: +49-5121-206917-5086 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox