Merge tag 'devicetree-for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/robh...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 19 Mar 2016 22:15:07 +0000 (15:15 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 19 Mar 2016 22:15:07 +0000 (15:15 -0700)
Pull DeviceTree updates from Rob Herring:

 - new tool 'dtx_diff' to diff DT files

 - sync kernel's dtc/libfdt to current dtc repo master

 - fix for reserved memory regions located in highmem

 - document standard unit suffixes for DT properties

 - various DT binding doc updates

* tag 'devicetree-for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux:
  of: Add vendor prefix for eGalax_eMPIA Technology Inc
  Input: ads7846: Add description how to use internal reference (ADS7846)
  ARM: realview: add EB syscon variants to bindings
  devicetree: bindings: ARM: Use "uV" for micro-volt
  serial: fsl-imx-uart: Fix typo in fsl,dte-mode description
  of: add 'const' for of_property_*_string*() parameter '*np'
  of/unittest: fix infinite loop in of_unittest_destroy_tracked_overlays()
  of: alloc anywhere from memblock if range not specified
  kbuild: Allow using host dtc instead of kernel's copy
  of: resolver: Add missing of_node_get and of_node_put
  of: Add United Radiant Technology Corporation vendor prefix
  dt/bindings: add documentation on standard property unit suffixes
  scripts/dtc: Update to upstream commit b06e55c88b9b
  ARM: boot: Add an implementation of strnlen for libfdt
  scripts/dtc: dtx_diff - add info to error message
  dtc: create tool to diff device trees

25 files changed:
Documentation/devicetree/bindings/arm/arm-boards
Documentation/devicetree/bindings/arm/cpus.txt
Documentation/devicetree/bindings/input/ads7846.txt
Documentation/devicetree/bindings/property-units.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
arch/arm/boot/compressed/string.c
drivers/of/base.c
drivers/of/of_reserved_mem.c
drivers/of/resolver.c
drivers/of/unittest.c
include/linux/of.h
scripts/Makefile.lib
scripts/dtc/checks.c
scripts/dtc/dtc-lexer.l
scripts/dtc/dtc-lexer.lex.c_shipped
scripts/dtc/dtc-parser.tab.c_shipped
scripts/dtc/dtc-parser.y
scripts/dtc/dtc.c
scripts/dtc/dtx_diff [new file with mode: 0755]
scripts/dtc/libfdt/fdt.c
scripts/dtc/libfdt/fdt_ro.c
scripts/dtc/libfdt/fdt_rw.c
scripts/dtc/libfdt/libfdt.h
scripts/dtc/util.c
scripts/dtc/version_gen.h

index 1a70997..100db73 100644 (file)
@@ -123,7 +123,9 @@ Required nodes:
 
 - syscon: some subnode of the RealView SoC node must be a
   system controller node pointing to the control registers,
-  with the compatible string set to one of these tuples:
+  with the compatible string set to one of these:
+   "arm,realview-eb11mp-revb-syscon", "arm,realview-eb-syscon", "syscon"
+   "arm,realview-eb11mp-revc-syscon", "arm,realview-eb-syscon", "syscon"
    "arm,realview-eb-syscon", "syscon"
    "arm,realview-pb1176-syscon", "syscon"
    "arm,realview-pb11mp-syscon", "syscon"
index ae9be07..afcf50f 100644 (file)
@@ -250,7 +250,7 @@ nodes to be present and contain the properties described below.
                Usage: optional
                Value type: <prop-encoded-array>
                Definition: A u32 value that represents the running time dynamic
-                           power coefficient in units of mW/MHz/uVolt^2. The
+                           power coefficient in units of mW/MHz/uV^2. The
                            coefficient can either be calculated from power
                            measurements or derived by analysis.
 
index 33a1638..c6cfe2e 100644 (file)
@@ -29,6 +29,8 @@ Optional properties:
        ti,vref-delay-usecs             vref supply delay in usecs, 0 for
                                        external vref (u16).
        ti,vref-mv                      The VREF voltage, in millivolts (u16).
+                                       Set to 0 to use internal refernce
+                                       (ADS7846).
        ti,keep-vref-on                 set to keep vref on for differential
                                        measurements as well
        ti,swap-xy                      swap x and y axis
diff --git a/Documentation/devicetree/bindings/property-units.txt b/Documentation/devicetree/bindings/property-units.txt
new file mode 100644 (file)
index 0000000..12278d7
--- /dev/null
@@ -0,0 +1,39 @@
+Standard Unit Suffixes for Property names
+
+Properties which have a unit of measure are recommended to have a unit
+suffix appended to the property name. The list below contains the
+recommended suffixes. Other variations exist in bindings, but should not
+be used in new bindings or added here. The inconsistency in the unit
+prefixes is due to selecting the most commonly used variants.
+
+It is also recommended to use the units listed here and not add additional
+unit prefixes.
+
+Time/Frequency
+----------------------------------------
+-mhz           : megahertz
+-hz            : Hertz (preferred)
+-sec           : seconds
+-ms            : milliseconds
+-us            : microseconds
+-ns            : nanoseconds
+
+Distance
+----------------------------------------
+-mm            : millimeters
+
+Electricity
+----------------------------------------
+-microamp      : micro amps
+-ohms          : Ohms
+-micro-ohms    : micro Ohms
+-microvolt     : micro volts
+
+Temperature
+----------------------------------------
+-celsius       : Degrees Celsius
+-millicelsius  : Degreee milli-Celsius
+
+Pressure
+----------------------------------------
+-kpascal       : kiloPascal
index 156731c..787d422 100644 (file)
@@ -72,6 +72,7 @@ dmo   Data Modul AG
 ea     Embedded Artists AB
 ebv    EBV Elektronik
 edt    Emerging Display Technologies
+eeti   eGalax_eMPIA Technology Inc
 elan   Elan Microelectronic Corp.
 emmicro        EM Microelectronic
 energymicro    Silicon Laboratories (formerly Energy Micro AS)
@@ -247,6 +248,7 @@ tplink      TP-LINK Technologies Co., Ltd.
 tronfy Tronfy
 truly  Truly Semiconductors Limited
 upisemi        uPI Semiconductor Corp.
+urt    United Radiant Technology Corporation
 usi    Universal Scientific Industrial Co., Ltd.
 v3     V3 Semiconductor
 variscite      Variscite Ltd.
index 36e53ef..6894674 100644 (file)
@@ -65,6 +65,15 @@ size_t strlen(const char *s)
        return sc - s;
 }
 
+size_t strnlen(const char *s, size_t count)
+{
+       const char *sc;
+
+       for (sc = s; count-- && *sc != '\0'; ++sc)
+               /* nothing */;
+       return sc - s;
+}
+
 int memcmp(const void *cs, const void *ct, size_t count)
 {
        const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count;
index 017dd94..b299de2 100644 (file)
@@ -1341,10 +1341,10 @@ EXPORT_SYMBOL_GPL(of_property_read_u64_array);
  *
  * The out_string pointer is modified only if a valid string can be decoded.
  */
-int of_property_read_string(struct device_node *np, const char *propname,
+int of_property_read_string(const struct device_node *np, const char *propname,
                                const char **out_string)
 {
-       struct property *prop = of_find_property(np, propname, NULL);
+       const struct property *prop = of_find_property(np, propname, NULL);
        if (!prop)
                return -EINVAL;
        if (!prop->value)
@@ -1365,10 +1365,10 @@ EXPORT_SYMBOL_GPL(of_property_read_string);
  * This function searches a string list property and returns the index
  * of a specific string value.
  */
-int of_property_match_string(struct device_node *np, const char *propname,
+int of_property_match_string(const struct device_node *np, const char *propname,
                             const char *string)
 {
-       struct property *prop = of_find_property(np, propname, NULL);
+       const struct property *prop = of_find_property(np, propname, NULL);
        size_t l;
        int i;
        const char *p, *end;
@@ -1404,10 +1404,11 @@ EXPORT_SYMBOL_GPL(of_property_match_string);
  * Don't call this function directly. It is a utility helper for the
  * of_property_read_string*() family of functions.
  */
-int of_property_read_string_helper(struct device_node *np, const char *propname,
-                                  const char **out_strs, size_t sz, int skip)
+int of_property_read_string_helper(const struct device_node *np,
+                                  const char *propname, const char **out_strs,
+                                  size_t sz, int skip)
 {
-       struct property *prop = of_find_property(np, propname, NULL);
+       const struct property *prop = of_find_property(np, propname, NULL);
        int l = 0, i = 0;
        const char *p, *end;
 
index 1a3556a..ed01c01 100644 (file)
@@ -32,11 +32,13 @@ int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
        phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap,
        phys_addr_t *res_base)
 {
+       phys_addr_t base;
        /*
         * We use __memblock_alloc_base() because memblock_alloc_base()
         * panic()s on allocation failure.
         */
-       phys_addr_t base = __memblock_alloc_base(size, align, end);
+       end = !end ? MEMBLOCK_ALLOC_ANYWHERE : end;
+       base = __memblock_alloc_base(size, align, end);
        if (!base)
                return -ENOMEM;
 
index 640eb4c..d313d49 100644 (file)
@@ -36,12 +36,14 @@ static struct device_node *__of_find_node_by_full_name(struct device_node *node,
 
        /* check */
        if (of_node_cmp(node->full_name, full_name) == 0)
-               return node;
+               return of_node_get(node);
 
        for_each_child_of_node(node, child) {
                found = __of_find_node_by_full_name(child, full_name);
-               if (found != NULL)
+               if (found != NULL) {
+                       of_node_put(child);
                        return found;
+               }
        }
 
        return NULL;
@@ -174,6 +176,7 @@ static int __of_adjust_phandle_ref(struct device_node *node,
                        if (of_prop_cmp(sprop->name, propstr) == 0)
                                break;
                }
+               of_node_put(refnode);
 
                if (!sprop) {
                        pr_err("%s: Could not find property '%s'\n",
index 979b6e4..e986e6e 100644 (file)
@@ -1165,6 +1165,11 @@ static void of_unittest_destroy_tracked_overlays(void)
                                continue;
 
                        ret = of_overlay_destroy(id + overlay_first_id);
+                       if (ret == -ENODEV) {
+                               pr_warn("%s: no overlay to destroy for #%d\n",
+                                       __func__, id + overlay_first_id);
+                               continue;
+                       }
                        if (ret != 0) {
                                defers++;
                                pr_warn("%s: overlay destroy failed for #%d\n",
index dc6e396..7fcb681 100644 (file)
@@ -296,13 +296,13 @@ extern int of_property_read_u64_array(const struct device_node *np,
                                      u64 *out_values,
                                      size_t sz);
 
-extern int of_property_read_string(struct device_node *np,
+extern int of_property_read_string(const struct device_node *np,
                                   const char *propname,
                                   const char **out_string);
-extern int of_property_match_string(struct device_node *np,
+extern int of_property_match_string(const struct device_node *np,
                                    const char *propname,
                                    const char *string);
-extern int of_property_read_string_helper(struct device_node *np,
+extern int of_property_read_string_helper(const struct device_node *np,
                                              const char *propname,
                                              const char **out_strs, size_t sz, int index);
 extern int of_device_is_compatible(const struct device_node *device,
@@ -538,14 +538,14 @@ static inline int of_property_read_u64_array(const struct device_node *np,
        return -ENOSYS;
 }
 
-static inline int of_property_read_string(struct device_node *np,
+static inline int of_property_read_string(const struct device_node *np,
                                          const char *propname,
                                          const char **out_string)
 {
        return -ENOSYS;
 }
 
-static inline int of_property_read_string_helper(struct device_node *np,
+static inline int of_property_read_string_helper(const struct device_node *np,
                                                 const char *propname,
                                                 const char **out_strs, size_t sz, int index)
 {
@@ -571,7 +571,7 @@ static inline int of_property_read_u64(const struct device_node *np,
        return -ENOSYS;
 }
 
-static inline int of_property_match_string(struct device_node *np,
+static inline int of_property_match_string(const struct device_node *np,
                                           const char *propname,
                                           const char *string)
 {
@@ -773,7 +773,7 @@ static inline int of_property_count_u64_elems(const struct device_node *np,
  *
  * If @out_strs is NULL, the number of strings in the property is returned.
  */
-static inline int of_property_read_string_array(struct device_node *np,
+static inline int of_property_read_string_array(const struct device_node *np,
                                                const char *propname, const char **out_strs,
                                                size_t sz)
 {
@@ -792,7 +792,7 @@ static inline int of_property_read_string_array(struct device_node *np,
  * does not have a value, and -EILSEQ if the string is not null-terminated
  * within the length of the property data.
  */
-static inline int of_property_count_strings(struct device_node *np,
+static inline int of_property_count_strings(const struct device_node *np,
                                            const char *propname)
 {
        return of_property_read_string_helper(np, propname, NULL, 0, 0);
@@ -816,7 +816,7 @@ static inline int of_property_count_strings(struct device_node *np,
  *
  * The out_string pointer is modified only if a valid string can be decoded.
  */
-static inline int of_property_read_string_index(struct device_node *np,
+static inline int of_property_read_string_index(const struct device_node *np,
                                                const char *propname,
                                                int index, const char **output)
 {
index 2edbcad..ad50d58 100644 (file)
@@ -269,6 +269,7 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \
 
 # DTC
 # ---------------------------------------------------------------------------
+DTC ?= $(objtree)/scripts/dtc/dtc
 
 # Generate an assembly file to wrap the output of the device tree compiler
 quiet_cmd_dt_S_dtb= DTB     $@
@@ -291,7 +292,7 @@ $(obj)/%.dtb.S: $(obj)/%.dtb
 quiet_cmd_dtc = DTC     $@
 cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
        $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
-       $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 \
+       $(DTC) -O dtb -o $@ -b 0 \
                -i $(dir $<) $(DTC_FLAGS) \
                -d $(depfile).dtc.tmp $(dtc-tmp) ; \
        cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
index e81a8c7..0c03ac9 100644 (file)
@@ -560,7 +560,7 @@ static void check_reg_format(struct check *c, struct node *dt,
        size_cells = node_size_cells(node->parent);
        entrylen = (addr_cells + size_cells) * sizeof(cell_t);
 
-       if ((prop->val.len % entrylen) != 0)
+       if (!entrylen || (prop->val.len % entrylen) != 0)
                FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
                     "(#address-cells == %d, #size-cells == %d)",
                     node->fullpath, prop->val.len, addr_cells, size_cells);
index 0ee1caf..790fbf6 100644 (file)
@@ -73,24 +73,32 @@ static void lexical_error(const char *fmt, ...);
                }
 
 <*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
-                       char *line, *tmp, *fn;
+                       char *line, *fnstart, *fnend;
+                       struct data fn;
                        /* skip text before line # */
                        line = yytext;
                        while (!isdigit((unsigned char)*line))
                                line++;
-                       /* skip digits in line # */
-                       tmp = line;
-                       while (!isspace((unsigned char)*tmp))
-                               tmp++;
-                       /* "NULL"-terminate line # */
-                       *tmp = '\0';
-                       /* start of filename */
-                       fn = strchr(tmp + 1, '"') + 1;
-                       /* strip trailing " from filename */
-                       tmp = strchr(fn, '"');
-                       *tmp = 0;
+
+                       /* regexp ensures that first and list "
+                        * in the whole yytext are those at
+                        * beginning and end of the filename string */
+                       fnstart = memchr(yytext, '"', yyleng);
+                       for (fnend = yytext + yyleng - 1;
+                            *fnend != '"'; fnend--)
+                               ;
+                       assert(fnstart && fnend && (fnend > fnstart));
+
+                       fn = data_copy_escape_string(fnstart + 1,
+                                                    fnend - fnstart - 1);
+
+                       /* Don't allow nuls in filenames */
+                       if (memchr(fn.val, '\0', fn.len - 1))
+                               lexical_error("nul in line number directive");
+
                        /* -1 since #line is the number of the next line */
-                       srcpos_set_line(xstrdup(fn), atoi(line) - 1);
+                       srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
+                       data_free(fn);
                }
 
 <*><<EOF>>             {
@@ -153,7 +161,10 @@ static void lexical_error(const char *fmt, ...);
                        errno = 0;
                        yylval.integer = strtoull(yytext, &e, 0);
 
-                       assert(!(*e) || !e[strspn(e, "UL")]);
+                       if (*e && e[strspn(e, "UL")]) {
+                               lexical_error("Bad integer literal '%s'",
+                                             yytext);
+                       }
 
                        if (errno == ERANGE)
                                lexical_error("Integer literal '%s' out of range",
index 11cd78e..ba525c2 100644 (file)
@@ -951,31 +951,39 @@ case 2:
 YY_RULE_SETUP
 #line 75 "dtc-lexer.l"
 {
-                       char *line, *tmp, *fn;
+                       char *line, *fnstart, *fnend;
+                       struct data fn;
                        /* skip text before line # */
                        line = yytext;
                        while (!isdigit((unsigned char)*line))
                                line++;
-                       /* skip digits in line # */
-                       tmp = line;
-                       while (!isspace((unsigned char)*tmp))
-                               tmp++;
-                       /* "NULL"-terminate line # */
-                       *tmp = '\0';
-                       /* start of filename */
-                       fn = strchr(tmp + 1, '"') + 1;
-                       /* strip trailing " from filename */
-                       tmp = strchr(fn, '"');
-                       *tmp = 0;
+
+                       /* regexp ensures that first and list "
+                        * in the whole yytext are those at
+                        * beginning and end of the filename string */
+                       fnstart = memchr(yytext, '"', yyleng);
+                       for (fnend = yytext + yyleng - 1;
+                            *fnend != '"'; fnend--)
+                               ;
+                       assert(fnstart && fnend && (fnend > fnstart));
+
+                       fn = data_copy_escape_string(fnstart + 1,
+                                                    fnend - fnstart - 1);
+
+                       /* Don't allow nuls in filenames */
+                       if (memchr(fn.val, '\0', fn.len - 1))
+                               lexical_error("nul in line number directive");
+
                        /* -1 since #line is the number of the next line */
-                       srcpos_set_line(xstrdup(fn), atoi(line) - 1);
+                       srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
+                       data_free(fn);
                }
        YY_BREAK
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(BYTESTRING):
 case YY_STATE_EOF(PROPNODENAME):
 case YY_STATE_EOF(V1):
-#line 96 "dtc-lexer.l"
+#line 104 "dtc-lexer.l"
 {
                        if (!pop_input_file()) {
                                yyterminate();
@@ -985,7 +993,7 @@ case YY_STATE_EOF(V1):
 case 3:
 /* rule 3 can match eol */
 YY_RULE_SETUP
-#line 102 "dtc-lexer.l"
+#line 110 "dtc-lexer.l"
 {
                        DPRINT("String: %s\n", yytext);
                        yylval.data = data_copy_escape_string(yytext+1,
@@ -995,7 +1003,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 109 "dtc-lexer.l"
+#line 117 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /dts-v1/\n");
                        dts_version = 1;
@@ -1005,7 +1013,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 116 "dtc-lexer.l"
+#line 124 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /memreserve/\n");
                        BEGIN_DEFAULT();
@@ -1014,7 +1022,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 122 "dtc-lexer.l"
+#line 130 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /bits/\n");
                        BEGIN_DEFAULT();
@@ -1023,7 +1031,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 128 "dtc-lexer.l"
+#line 136 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /delete-property/\n");
                        DPRINT("<PROPNODENAME>\n");
@@ -1033,7 +1041,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 135 "dtc-lexer.l"
+#line 143 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /delete-node/\n");
                        DPRINT("<PROPNODENAME>\n");
@@ -1043,7 +1051,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 142 "dtc-lexer.l"
+#line 150 "dtc-lexer.l"
 {
                        DPRINT("Label: %s\n", yytext);
                        yylval.labelref = xstrdup(yytext);
@@ -1053,7 +1061,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 149 "dtc-lexer.l"
+#line 157 "dtc-lexer.l"
 {
                        char *e;
                        DPRINT("Integer Literal: '%s'\n", yytext);
@@ -1061,7 +1069,10 @@ YY_RULE_SETUP
                        errno = 0;
                        yylval.integer = strtoull(yytext, &e, 0);
 
-                       assert(!(*e) || !e[strspn(e, "UL")]);
+                       if (*e && e[strspn(e, "UL")]) {
+                               lexical_error("Bad integer literal '%s'",
+                                             yytext);
+                       }
 
                        if (errno == ERANGE)
                                lexical_error("Integer literal '%s' out of range",
@@ -1076,7 +1087,7 @@ YY_RULE_SETUP
 case 11:
 /* rule 11 can match eol */
 YY_RULE_SETUP
-#line 168 "dtc-lexer.l"
+#line 179 "dtc-lexer.l"
 {
                        struct data d;
                        DPRINT("Character literal: %s\n", yytext);
@@ -1100,7 +1111,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 189 "dtc-lexer.l"
+#line 200 "dtc-lexer.l"
 {      /* label reference */
                        DPRINT("Ref: %s\n", yytext+1);
                        yylval.labelref = xstrdup(yytext+1);
@@ -1109,7 +1120,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 195 "dtc-lexer.l"
+#line 206 "dtc-lexer.l"
 {      /* new-style path reference */
                        yytext[yyleng-1] = '\0';
                        DPRINT("Ref: %s\n", yytext+2);
@@ -1119,7 +1130,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 202 "dtc-lexer.l"
+#line 213 "dtc-lexer.l"
 {
                        yylval.byte = strtol(yytext, NULL, 16);
                        DPRINT("Byte: %02x\n", (int)yylval.byte);
@@ -1128,7 +1139,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 208 "dtc-lexer.l"
+#line 219 "dtc-lexer.l"
 {
                        DPRINT("/BYTESTRING\n");
                        BEGIN_DEFAULT();
@@ -1137,7 +1148,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 214 "dtc-lexer.l"
+#line 225 "dtc-lexer.l"
 {
                        DPRINT("PropNodeName: %s\n", yytext);
                        yylval.propnodename = xstrdup((yytext[0] == '\\') ?
@@ -1148,7 +1159,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 222 "dtc-lexer.l"
+#line 233 "dtc-lexer.l"
 {
                        DPRINT("Binary Include\n");
                        return DT_INCBIN;
@@ -1157,64 +1168,64 @@ YY_RULE_SETUP
 case 18:
 /* rule 18 can match eol */
 YY_RULE_SETUP
-#line 227 "dtc-lexer.l"
+#line 238 "dtc-lexer.l"
 /* eat whitespace */
        YY_BREAK
 case 19:
 /* rule 19 can match eol */
 YY_RULE_SETUP
-#line 228 "dtc-lexer.l"
+#line 239 "dtc-lexer.l"
 /* eat C-style comments */
        YY_BREAK
 case 20:
 /* rule 20 can match eol */
 YY_RULE_SETUP
-#line 229 "dtc-lexer.l"
+#line 240 "dtc-lexer.l"
 /* eat C++-style comments */
        YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 231 "dtc-lexer.l"
+#line 242 "dtc-lexer.l"
 { return DT_LSHIFT; };
        YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 232 "dtc-lexer.l"
+#line 243 "dtc-lexer.l"
 { return DT_RSHIFT; };
        YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 233 "dtc-lexer.l"
+#line 244 "dtc-lexer.l"
 { return DT_LE; };
        YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 234 "dtc-lexer.l"
+#line 245 "dtc-lexer.l"
 { return DT_GE; };
        YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 235 "dtc-lexer.l"
+#line 246 "dtc-lexer.l"
 { return DT_EQ; };
        YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 236 "dtc-lexer.l"
+#line 247 "dtc-lexer.l"
 { return DT_NE; };
        YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 237 "dtc-lexer.l"
+#line 248 "dtc-lexer.l"
 { return DT_AND; };
        YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 238 "dtc-lexer.l"
+#line 249 "dtc-lexer.l"
 { return DT_OR; };
        YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 240 "dtc-lexer.l"
+#line 251 "dtc-lexer.l"
 {
                        DPRINT("Char: %c (\\x%02x)\n", yytext[0],
                                (unsigned)yytext[0]);
@@ -1232,10 +1243,10 @@ YY_RULE_SETUP
        YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 255 "dtc-lexer.l"
+#line 266 "dtc-lexer.l"
 ECHO;
        YY_BREAK
-#line 1239 "dtc-lexer.lex.c"
+#line 1250 "dtc-lexer.lex.c"
 
        case YY_END_OF_BUFFER:
                {
@@ -2195,7 +2206,7 @@ void yyfree (void * ptr )
 
 #define YYTABLES_NAME "yytables"
 
-#line 254 "dtc-lexer.l"
+#line 265 "dtc-lexer.l"
 
 
 
index 116458c..31cec50 100644 (file)
@@ -499,9 +499,9 @@ static const yytype_uint16 yyrline[] =
      298,   303,   322,   336,   343,   344,   345,   352,   356,   357,
      361,   362,   366,   367,   371,   372,   376,   377,   381,   382,
      386,   387,   388,   392,   393,   394,   395,   396,   400,   401,
-     402,   406,   407,   408,   412,   413,   414,   415,   419,   420,
-     421,   422,   427,   430,   434,   442,   445,   449,   457,   461,
-     465
+     402,   406,   407,   408,   412,   413,   422,   431,   435,   436,
+     437,   438,   443,   446,   450,   458,   461,   465,   473,   477,
+     481
 };
 #endif
 
@@ -1909,111 +1909,125 @@ yyreduce:
     break;
 
   case 65:
-#line 413 "dtc-parser.y" /* yacc.c:1646  */
-    { (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer); }
-#line 1915 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 414 "dtc-parser.y" /* yacc.c:1646  */
+    {
+                       if ((yyvsp[0].integer) != 0) {
+                               (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer);
+                       } else {
+                               ERROR(&(yyloc), "Division by zero");
+                               (yyval.integer) = 0;
+                       }
+               }
+#line 1922 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 66:
-#line 414 "dtc-parser.y" /* yacc.c:1646  */
-    { (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer); }
-#line 1921 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 423 "dtc-parser.y" /* yacc.c:1646  */
+    {
+                       if ((yyvsp[0].integer) != 0) {
+                               (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer);
+                       } else {
+                               ERROR(&(yyloc), "Division by zero");
+                               (yyval.integer) = 0;
+                       }
+               }
+#line 1935 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 69:
-#line 420 "dtc-parser.y" /* yacc.c:1646  */
+#line 436 "dtc-parser.y" /* yacc.c:1646  */
     { (yyval.integer) = -(yyvsp[0].integer); }
-#line 1927 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1941 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 70:
-#line 421 "dtc-parser.y" /* yacc.c:1646  */
+#line 437 "dtc-parser.y" /* yacc.c:1646  */
     { (yyval.integer) = ~(yyvsp[0].integer); }
-#line 1933 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1947 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 71:
-#line 422 "dtc-parser.y" /* yacc.c:1646  */
+#line 438 "dtc-parser.y" /* yacc.c:1646  */
     { (yyval.integer) = !(yyvsp[0].integer); }
-#line 1939 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1953 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 72:
-#line 427 "dtc-parser.y" /* yacc.c:1646  */
+#line 443 "dtc-parser.y" /* yacc.c:1646  */
     {
                        (yyval.data) = empty_data;
                }
-#line 1947 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1961 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 73:
-#line 431 "dtc-parser.y" /* yacc.c:1646  */
+#line 447 "dtc-parser.y" /* yacc.c:1646  */
     {
                        (yyval.data) = data_append_byte((yyvsp[-1].data), (yyvsp[0].byte));
                }
-#line 1955 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1969 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 74:
-#line 435 "dtc-parser.y" /* yacc.c:1646  */
+#line 451 "dtc-parser.y" /* yacc.c:1646  */
     {
                        (yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref));
                }
-#line 1963 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1977 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 75:
-#line 442 "dtc-parser.y" /* yacc.c:1646  */
+#line 458 "dtc-parser.y" /* yacc.c:1646  */
     {
                        (yyval.nodelist) = NULL;
                }
-#line 1971 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1985 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 76:
-#line 446 "dtc-parser.y" /* yacc.c:1646  */
+#line 462 "dtc-parser.y" /* yacc.c:1646  */
     {
                        (yyval.nodelist) = chain_node((yyvsp[-1].node), (yyvsp[0].nodelist));
                }
-#line 1979 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1993 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 77:
-#line 450 "dtc-parser.y" /* yacc.c:1646  */
+#line 466 "dtc-parser.y" /* yacc.c:1646  */
     {
                        ERROR(&(yylsp[0]), "Properties must precede subnodes");
                        YYERROR;
                }
-#line 1988 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2002 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 78:
-#line 458 "dtc-parser.y" /* yacc.c:1646  */
+#line 474 "dtc-parser.y" /* yacc.c:1646  */
     {
                        (yyval.node) = name_node((yyvsp[0].node), (yyvsp[-1].propnodename));
                }
-#line 1996 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2010 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 79:
-#line 462 "dtc-parser.y" /* yacc.c:1646  */
+#line 478 "dtc-parser.y" /* yacc.c:1646  */
     {
                        (yyval.node) = name_node(build_node_delete(), (yyvsp[-1].propnodename));
                }
-#line 2004 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2018 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 80:
-#line 466 "dtc-parser.y" /* yacc.c:1646  */
+#line 482 "dtc-parser.y" /* yacc.c:1646  */
     {
                        add_label(&(yyvsp[0].node)->labels, (yyvsp[-1].labelref));
                        (yyval.node) = (yyvsp[0].node);
                }
-#line 2013 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2027 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
 
-#line 2017 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2031 "dtc-parser.tab.c" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -2248,7 +2262,7 @@ yyreturn:
 #endif
   return yyresult;
 }
-#line 472 "dtc-parser.y" /* yacc.c:1906  */
+#line 488 "dtc-parser.y" /* yacc.c:1906  */
 
 
 void yyerror(char const *s)
index 5a897e3..000873f 100644 (file)
@@ -410,8 +410,24 @@ integer_add:
 
 integer_mul:
          integer_mul '*' integer_unary { $$ = $1 * $3; }
-       | integer_mul '/' integer_unary { $$ = $1 / $3; }
-       | integer_mul '%' integer_unary { $$ = $1 % $3; }
+       | integer_mul '/' integer_unary
+               {
+                       if ($3 != 0) {
+                               $$ = $1 / $3;
+                       } else {
+                               ERROR(&@$, "Division by zero");
+                               $$ = 0;
+                       }
+               }
+       | integer_mul '%' integer_unary
+               {
+                       if ($3 != 0) {
+                               $$ = $1 % $3;
+                       } else {
+                               ERROR(&@$, "Division by zero");
+                               $$ = 0;
+                       }
+               }
        | integer_unary
        ;
 
index 8c4add6..5fa23c4 100644 (file)
@@ -18,6 +18,8 @@
  *                                                                   USA
  */
 
+#include <sys/stat.h>
+
 #include "dtc.h"
 #include "srcpos.h"
 
@@ -104,11 +106,56 @@ static const char * const usage_opts_help[] = {
        NULL,
 };
 
+static const char *guess_type_by_name(const char *fname, const char *fallback)
+{
+       const char *s;
+
+       s = strrchr(fname, '.');
+       if (s == NULL)
+               return fallback;
+       if (!strcasecmp(s, ".dts"))
+               return "dts";
+       if (!strcasecmp(s, ".dtb"))
+               return "dtb";
+       return fallback;
+}
+
+static const char *guess_input_format(const char *fname, const char *fallback)
+{
+       struct stat statbuf;
+       uint32_t magic;
+       FILE *f;
+
+       if (stat(fname, &statbuf) != 0)
+               return fallback;
+
+       if (S_ISDIR(statbuf.st_mode))
+               return "fs";
+
+       if (!S_ISREG(statbuf.st_mode))
+               return fallback;
+
+       f = fopen(fname, "r");
+       if (f == NULL)
+               return fallback;
+       if (fread(&magic, 4, 1, f) != 1) {
+               fclose(f);
+               return fallback;
+       }
+       fclose(f);
+
+       magic = fdt32_to_cpu(magic);
+       if (magic == FDT_MAGIC)
+               return "dtb";
+
+       return guess_type_by_name(fname, fallback);
+}
+
 int main(int argc, char *argv[])
 {
        struct boot_info *bi;
-       const char *inform = "dts";
-       const char *outform = "dts";
+       const char *inform = NULL;
+       const char *outform = NULL;
        const char *outname = "-";
        const char *depname = NULL;
        bool force = false, sort = false;
@@ -213,6 +260,17 @@ int main(int argc, char *argv[])
                fprintf(depfile, "%s:", outname);
        }
 
+       if (inform == NULL)
+               inform = guess_input_format(arg, "dts");
+       if (outform == NULL) {
+               outform = guess_type_by_name(outname, NULL);
+               if (outform == NULL) {
+                       if (streq(inform, "dts"))
+                               outform = "dtb";
+                       else
+                               outform = "dts";
+               }
+       }
        if (streq(inform, "dts"))
                bi = dt_from_source(arg);
        else if (streq(inform, "fs"))
diff --git a/scripts/dtc/dtx_diff b/scripts/dtc/dtx_diff
new file mode 100755 (executable)
index 0000000..959ab26
--- /dev/null
@@ -0,0 +1,349 @@
+#! /bin/bash
+
+# Copyright (C) 2015 Frank Rowand
+#
+# 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; version 2 of the License.
+
+
+usage() {
+
+       # use spaces instead of tabs in the usage message
+       cat >&2 <<eod
+
+Usage:
+
+   `basename $0` DTx
+        decompile DTx
+
+   `basename $0` DTx_1 DTx_2
+        diff DTx_1 and DTx_2
+
+
+       -f           print full dts in diff (--unified=99999)
+       -h           synonym for --help
+       -help        synonym for --help
+      --help        print this message and exit
+       -s SRCTREE   linux kernel source tree is at path SRCTREE
+                        (default is current directory)
+       -S           linux kernel source tree is at root of current git repo
+       -u           unsorted, do not sort DTx
+
+
+Each DTx is processed by the dtc compiler to produce a sorted dts source
+file.  If DTx is a dts source file then it is pre-processed in the same
+manner as done for the compile of the dts source file in the Linux kernel
+build system ('#include' and '/include/' directives are processed).
+
+If two DTx are provided, the resulting dts source files are diffed.
+
+If DTx is a directory, it is treated as a DT subtree, such as
+  /proc/device-tree.
+
+If DTx contains the binary blob magic value in the first four bytes,
+  it is treated as a binary blob (aka .dtb or FDT).
+
+Otherwise DTx is treated as a dts source file (aka .dts).
+
+   If this script is not run from the root of the linux source tree,
+   and DTx utilizes '#include' or '/include/' then the path of the
+   linux source tree can be provided by '-s SRCTREE' or '-S' so that
+   include paths will be set properly.
+
+   The shell variable \${ARCH} must provide the architecture containing
+   the dts source file for include paths to be set properly for '#include'
+   or '/include/' to be processed.
+
+   If DTx_1 and DTx_2 are in different architectures, then this script
+   may not work since \${ARCH} is part of the include path.  Two possible
+   workarounds:
+
+      `basename $0` \\
+          <(ARCH=arch_of_dtx_1 `basename $0` DTx_1) \\
+          <(ARCH=arch_of_dtx_2 `basename $0` DTx_2)
+
+      `basename $0` ARCH=arch_of_dtx_1 DTx_1 >tmp_dtx_1.dts
+      `basename $0` ARCH=arch_of_dtx_2 DTx_2 >tmp_dtx_2.dts
+      `basename $0` tmp_dtx_1.dts tmp_dtx_2.dts
+      rm tmp_dtx_1.dts tmp_dtx_2.dts
+
+   If DTx_1 and DTx_2 are in different directories, then this script will
+   add the path of DTx_1 and DTx_2 to the include paths.  If DTx_2 includes
+   a local file that exists in both the path of DTx_1 and DTx_2 then the
+   file in the path of DTx_1 will incorrectly be included.  Possible
+   workaround:
+
+      `basename $0` DTx_1 >tmp_dtx_1.dts
+      `basename $0` DTx_2 >tmp_dtx_2.dts
+      `basename $0` tmp_dtx_1.dts tmp_dtx_2.dts
+      rm tmp_dtx_1.dts tmp_dtx_2.dts
+
+eod
+}
+
+
+compile_to_dts() {
+
+       dtx="$1"
+
+       if [ -d "${dtx}" ] ; then
+
+               # -----  input is file tree
+
+               if ( ! ${DTC} -I fs ${dtx} ) ; then
+                       exit 3
+               fi
+
+       elif [ -f "${dtx}" ] && [ -r "${dtx}" ] ; then
+
+               magic=`hexdump -n 4 -e '/1 "%02x"' ${dtx}`
+               if [ "${magic}" = "d00dfeed" ] ; then
+
+                       # -----  input is FDT (binary blob)
+
+                       if ( ! ${DTC} -I dtb ${dtx} ) ; then
+                               exit 3
+                       fi
+
+                       return
+
+               fi
+
+               # -----  input is DTS (source)
+
+               if ( cpp ${cpp_flags} -x assembler-with-cpp ${dtx} \
+                       | ${DTC} -I dts ) ; then
+                       return
+               fi
+
+               echo ""                                                      >&2
+               echo "Possible hints to resolve the above error:"            >&2
+               echo "  (hints might not fix the problem)"                   >&2
+
+               hint_given=0
+
+               if [ "${ARCH}" = "" ] ; then
+                       hint_given=1
+                       echo ""                                              >&2
+                       echo "  shell variable \$ARCH not set"               >&2
+               fi
+
+               dtx_arch=`echo "/${dtx}" | sed -e 's|.*/arch/||' -e 's|/.*||'`
+
+               if [ "${dtx_arch}" != ""  -a "${dtx_arch}" != "${ARCH}" ] ; then
+                       hint_given=1
+                       echo ""                                              >&2
+                       echo "  architecture ${dtx_arch} is in file path,"   >&2
+                       echo "  but does not match shell variable \$ARCH"    >&2
+                       echo "  >>\$ARCH<< is: >>${ARCH}<<"                  >&2
+               fi
+
+               if [ ! -d ${srctree}/arch/${ARCH} ] ; then
+                       hint_given=1
+                       echo ""                                              >&2
+                       echo "  ${srctree}/arch/${ARCH}/ does not exist"     >&2
+                       echo "  Is \$ARCH='${ARCH}' correct?"                >&2
+                       echo "  Possible fix: use '-s' option"               >&2
+
+                       git_root=`git rev-parse --show-toplevel 2>/dev/null`
+                       if [ -d ${git_root}/arch/ ] ; then
+                               echo "  Possible fix: use '-S' option"       >&2
+                       fi
+               fi
+
+               if [ $hint_given = 0 ] ; then
+                       echo ""                                              >&2
+                       echo "  No hints available."                         >&2
+               fi
+
+               echo ""                                                      >&2
+
+               exit 3
+
+       else
+               echo ""                                                     >&2
+               echo "ERROR: ${dtx} does not exist or is not readable"      >&2
+               echo ""                                                     >&2
+               exit 2
+       fi
+
+}
+
+
+# -----  start of script
+
+cmd_diff=0
+diff_flags="-u"
+dtx_file_1=""
+dtx_file_2=""
+dtc_sort="-s"
+help=0
+srctree=""
+
+
+while [ $# -gt 0 ] ; do
+
+       case $1 in
+
+       -f )
+               diff_flags="--unified=999999"
+               shift
+               ;;
+
+       -h | -help | --help )
+               help=1
+               shift
+               ;;
+
+       -s )
+               srctree="$2"
+               shift 2
+               ;;
+
+       -S )
+               git_root=`git rev-parse --show-toplevel 2>/dev/null`
+               srctree="${git_root}"
+               shift
+               ;;
+
+       -u )
+               dtc_sort=""
+               shift
+               ;;
+
+       *)
+               if [ "${dtx_file_1}"  = "" ] ; then
+                       dtx_file_1="$1"
+               elif [ "${dtx_file_2}" = "" ] ; then
+                       dtx_file_2="$1"
+               else
+                       echo ""                                             >&2
+                       echo "ERROR: Unexpected parameter: $1"              >&2
+                       echo ""                                             >&2
+                       exit 2
+               fi
+               shift
+               ;;
+
+       esac
+
+done
+
+if [ "${srctree}" = "" ] ; then
+       srctree="."
+fi
+
+if [ "${dtx_file_2}" != "" ]; then
+       cmd_diff=1
+fi
+
+if (( ${help} )) ; then
+       usage
+       exit 1
+fi
+
+# this must follow check for ${help}
+if [ "${dtx_file_1}" = "" ]; then
+       echo ""                                                             >&2
+       echo "ERROR: parameter DTx required"                                >&2
+       echo ""                                                             >&2
+       exit 2
+fi
+
+
+# -----  prefer dtc from linux kernel, allow fallback to dtc in $PATH
+
+if [ "${KBUILD_OUTPUT:0:2}" = ".." ] ; then
+       __KBUILD_OUTPUT="${srctree}/${KBUILD_OUTPUT}"
+elif [ "${KBUILD_OUTPUT}" = "" ] ; then
+       __KBUILD_OUTPUT="."
+else
+       __KBUILD_OUTPUT="${KBUILD_OUTPUT}"
+fi
+
+DTC="${__KBUILD_OUTPUT}/scripts/dtc/dtc"
+
+if [ ! -x ${DTC} ] ; then
+       __DTC="dtc"
+       if grep -q "^CONFIG_DTC=y" ${__KBUILD_OUTPUT}/.config ; then
+               make_command='
+         make scripts'
+       else
+               make_command='
+         Enable CONFIG_DTC in the kernel configuration
+         make scripts'
+       fi
+       if ( ! which ${__DTC} >/dev/null ) ; then
+
+               # use spaces instead of tabs in the error message
+               cat >&2 <<eod
+
+ERROR: unable to find a 'dtc' program
+
+   Preferred 'dtc' (built from Linux kernel source tree) was not found or
+   is not executable.
+
+      'dtc' is: ${DTC}
+
+      If it does not exist, create it from the root of the Linux source tree:
+${make_command}
+
+      If not at the root of the Linux kernel source tree -s SRCTREE or -S
+      may need to be specified to find 'dtc'.
+
+      If 'O=\${dir}' is specified in your Linux builds, this script requires
+      'export KBUILD_OUTPUT=\${dir}' or add \${dir}/scripts/dtc to \$PATH
+      before running.
+
+      If \${KBUILD_OUTPUT} is a relative path, then '-s SRCDIR', -S, or run
+      this script from the root of the Linux kernel source tree is required.
+
+   Fallback '${__DTC}' was also not in \${PATH} or is not executable.
+
+eod
+               exit 2
+       fi
+       DTC=${__DTC}
+fi
+
+
+# -----  cpp and dtc flags same as for linux source tree build of .dtb files,
+#        plus directories of the dtx file(s)
+
+dtx_path_1_dtc_include="-i `dirname ${dtx_file_1}`"
+
+dtx_path_2_dtc_include=""
+if (( ${cmd_diff} )) ; then
+       dtx_path_2_dtc_include="-i `dirname ${dtx_file_2}`"
+fi
+
+cpp_flags="\
+       -nostdinc                                  \
+       -I${srctree}/arch/${ARCH}/boot/dts         \
+       -I${srctree}/arch/${ARCH}/boot/dts/include \
+       -I${srctree}/drivers/of/testcase-data      \
+       -undef -D__DTS__"
+
+dtc_flags="\
+       -i ${srctree}/arch/${ARCH}/boot/dts/ \
+       -i ${srctree}/kernel/dts             \
+       ${dtx_path_1_dtc_include}            \
+       ${dtx_path_2_dtc_include}"
+
+DTC="${DTC} ${dtc_flags} -O dts -qq -f ${dtc_sort} -o -"
+
+
+# -----  do the diff or decompile
+
+if (( ${cmd_diff} )) ; then
+
+       diff ${diff_flags} \
+               <(compile_to_dts "${dtx_file_1}") \
+               <(compile_to_dts "${dtx_file_2}")
+
+else
+
+       compile_to_dts "${dtx_file_1}"
+
+fi
index 2ce6a44..22286a1 100644 (file)
@@ -76,18 +76,19 @@ int fdt_check_header(const void *fdt)
 
 const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
 {
-       const char *p;
+       unsigned absoffset = offset + fdt_off_dt_struct(fdt);
+
+       if ((absoffset < offset)
+           || ((absoffset + len) < absoffset)
+           || (absoffset + len) > fdt_totalsize(fdt))
+               return NULL;
 
        if (fdt_version(fdt) >= 0x11)
                if (((offset + len) < offset)
                    || ((offset + len) > fdt_size_dt_struct(fdt)))
                        return NULL;
 
-       p = _fdt_offset_ptr(fdt, offset);
-
-       if (p + len < p)
-               return NULL;
-       return p;
+       return _fdt_offset_ptr(fdt, offset);
 }
 
 uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
index a65e4b5..e5b3136 100644 (file)
@@ -538,6 +538,106 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
        return 0;
 }
 
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
+{
+       const char *list, *end;
+       int length, count = 0;
+
+       list = fdt_getprop(fdt, nodeoffset, property, &length);
+       if (!list)
+               return -length;
+
+       end = list + length;
+
+       while (list < end) {
+               length = strnlen(list, end - list) + 1;
+
+               /* Abort if the last string isn't properly NUL-terminated. */
+               if (list + length > end)
+                       return -FDT_ERR_BADVALUE;
+
+               list += length;
+               count++;
+       }
+
+       return count;
+}
+
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
+                         const char *string)
+{
+       int length, len, idx = 0;
+       const char *list, *end;
+
+       list = fdt_getprop(fdt, nodeoffset, property, &length);
+       if (!list)
+               return -length;
+
+       len = strlen(string) + 1;
+       end = list + length;
+
+       while (list < end) {
+               length = strnlen(list, end - list) + 1;
+
+               /* Abort if the last string isn't properly NUL-terminated. */
+               if (list + length > end)
+                       return -FDT_ERR_BADVALUE;
+
+               if (length == len && memcmp(list, string, length) == 0)
+                       return idx;
+
+               list += length;
+               idx++;
+       }
+
+       return -FDT_ERR_NOTFOUND;
+}
+
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
+                              const char *property, int idx,
+                              int *lenp)
+{
+       const char *list, *end;
+       int length;
+
+       list = fdt_getprop(fdt, nodeoffset, property, &length);
+       if (!list) {
+               if (lenp)
+                       *lenp = length;
+
+               return NULL;
+       }
+
+       end = list + length;
+
+       while (list < end) {
+               length = strnlen(list, end - list) + 1;
+
+               /* Abort if the last string isn't properly NUL-terminated. */
+               if (list + length > end) {
+                       if (lenp)
+                               *lenp = -FDT_ERR_BADVALUE;
+
+                       return NULL;
+               }
+
+               if (idx == 0) {
+                       if (lenp)
+                               *lenp = length - 1;
+
+                       return list;
+               }
+
+               list += length;
+               idx--;
+       }
+
+       if (lenp)
+               *lenp = -FDT_ERR_NOTFOUND;
+
+       return NULL;
+}
+
 int fdt_node_check_compatible(const void *fdt, int nodeoffset,
                              const char *compatible)
 {
index 70adec6..8be02b1 100644 (file)
@@ -101,6 +101,8 @@ static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
 
        if (((p + oldlen) < p) || ((p + oldlen) > end))
                return -FDT_ERR_BADOFFSET;
+       if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
+               return -FDT_ERR_BADOFFSET;
        if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
                return -FDT_ERR_NOSPACE;
        memmove(p + newlen, p + oldlen, end - p - oldlen);
index ea35ac3..59ca339 100644 (file)
        /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells
         * or similar property with a bad format or value */
 
-#define FDT_ERR_MAX            14
+#define FDT_ERR_BADVALUE       15
+       /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected
+        * value. For example: a property expected to contain a string list
+        * is not NUL-terminated within the length of its value. */
+
+#define FDT_ERR_MAX            15
 
 /**********************************************************************/
 /* Low-level functions (you probably don't need these)                */
@@ -457,8 +462,8 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
  * @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.
+ * Identical to fdt_get_property(), 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,
@@ -868,6 +873,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
  */
 int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
 
+/**
+ * fdt_stringlist_count - count the number of strings in a string list
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @property: name of the property containing the string list
+ * @return:
+ *   the number of strings in the given property
+ *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *   -FDT_ERR_NOTFOUND if the property does not exist
+ */
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
+
+/**
+ * fdt_stringlist_search - find a string in a string list and return its index
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @property: name of the property containing the string list
+ * @string: string to look up in the string list
+ *
+ * Note that it is possible for this function to succeed on property values
+ * that are not NUL-terminated. That's because the function will stop after
+ * finding the first occurrence of @string. This can for example happen with
+ * small-valued cell properties, such as #address-cells, when searching for
+ * the empty string.
+ *
+ * @return:
+ *   the index of the string in the list of strings
+ *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *   -FDT_ERR_NOTFOUND if the property does not exist or does not contain
+ *                     the given string
+ */
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
+                         const char *string);
+
+/**
+ * fdt_stringlist_get() - obtain the string at a given index in a string list
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @property: name of the property containing the string list
+ * @index: index of the string to return
+ * @lenp: return location for the string length or an error code on failure
+ *
+ * Note that this will successfully extract strings from properties with
+ * non-NUL-terminated values. For example on small-valued cell properties
+ * this function will return the empty string.
+ *
+ * If non-NULL, the length of the string (on success) or a negative error-code
+ * (on failure) will be stored in the integer pointer to by lenp.
+ *
+ * @return:
+ *   A pointer to the string at the given index in the string list or NULL on
+ *   failure. On success the length of the string will be stored in the memory
+ *   location pointed to by the lenp parameter, if non-NULL. On failure one of
+ *   the following negative error codes will be returned in the lenp parameter
+ *   (if non-NULL):
+ *     -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *     -FDT_ERR_NOTFOUND if the property does not exist
+ */
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
+                              const char *property, int index,
+                              int *lenp);
+
 /**********************************************************************/
 /* Read-only functions (addressing related)                           */
 /**********************************************************************/
index 9d65226..fb124ee 100644 (file)
@@ -152,7 +152,6 @@ char get_escape_char(const char *s, int *i)
        int     j = *i + 1;
        char    val;
 
-       assert(c);
        switch (c) {
        case 'a':
                val = '\a';
@@ -349,7 +348,6 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
 void utilfdt_print_data(const char *data, int len)
 {
        int i;
-       const char *p = data;
        const char *s;
 
        /* no data, don't print */
@@ -376,6 +374,7 @@ void utilfdt_print_data(const char *data, int len)
                               i < (len - 1) ? " " : "");
                printf(">");
        } else {
+               const unsigned char *p = (const unsigned char *)data;
                printf(" = [");
                for (i = 0; i < len; i++)
                        printf("%02x%s", *p++, i < len - 1 ? " " : "");
index 5b8c7d5..11d93e6 100644 (file)
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.4.1-g9d3649bd"
+#define DTC_VERSION "DTC 1.4.1-gb06e55c8"