Author: gonzo
Date: Fri Mar 10 17:36:05 2017
New Revision: 315009
URL: https://svnweb.freebsd.org/changeset/base/315009

Log:
  Merge from vendor branch importing dtc 1.4.3
  
  Major new feature in this import is FDT overlay support

Added:
  head/contrib/dtc/Documentation/dt-object-internal.txt
     - copied unchanged from r314985, 
vendor/dtc/dist/Documentation/dt-object-internal.txt
  head/contrib/dtc/README
     - copied unchanged from r314985, vendor/dtc/dist/README
  head/contrib/dtc/libfdt/fdt_addresses.c
     - copied unchanged from r314985, vendor/dtc/dist/libfdt/fdt_addresses.c
  head/contrib/dtc/libfdt/fdt_overlay.c
     - copied unchanged from r314985, vendor/dtc/dist/libfdt/fdt_overlay.c
  head/contrib/dtc/scripts/kup-dtc
     - copied unchanged from r314985, vendor/dtc/dist/scripts/kup-dtc
Modified:
  head/contrib/dtc/Documentation/manual.txt
  head/contrib/dtc/Makefile
  head/contrib/dtc/checks.c
  head/contrib/dtc/data.c
  head/contrib/dtc/dtc-lexer.l
  head/contrib/dtc/dtc-parser.y
  head/contrib/dtc/dtc.c
  head/contrib/dtc/dtc.h
  head/contrib/dtc/fdtdump.c
  head/contrib/dtc/fdtget.c
  head/contrib/dtc/fdtput.c
  head/contrib/dtc/flattree.c
  head/contrib/dtc/fstree.c
  head/contrib/dtc/libfdt/Makefile.libfdt
  head/contrib/dtc/libfdt/fdt.c
  head/contrib/dtc/libfdt/fdt_ro.c
  head/contrib/dtc/libfdt/fdt_rw.c
  head/contrib/dtc/libfdt/fdt_strerror.c
  head/contrib/dtc/libfdt/fdt_wip.c
  head/contrib/dtc/libfdt/libfdt.h
  head/contrib/dtc/libfdt/libfdt_env.h
  head/contrib/dtc/libfdt/libfdt_internal.h
  head/contrib/dtc/libfdt/version.lds
  head/contrib/dtc/livetree.c
  head/contrib/dtc/srcpos.c
  head/contrib/dtc/srcpos.h
  head/contrib/dtc/treesource.c
  head/contrib/dtc/util.c
  head/contrib/dtc/util.h
Directory Properties:
  head/contrib/dtc/   (props changed)

Copied: head/contrib/dtc/Documentation/dt-object-internal.txt (from r314985, 
vendor/dtc/dist/Documentation/dt-object-internal.txt)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/contrib/dtc/Documentation/dt-object-internal.txt       Fri Mar 10 
17:36:05 2017        (r315009, copy of r314985, 
vendor/dtc/dist/Documentation/dt-object-internal.txt)
@@ -0,0 +1,310 @@
+Device Tree Dynamic Object format internals
+-------------------------------------------
+
+The Device Tree for most platforms is a static representation of
+the hardware capabilities. This is insufficient for platforms
+that need to dynamically insert Device Tree fragments into the
+live tree.
+
+This document explains the the Device Tree object format and
+modifications made to the Device Tree compiler, which make it possible.
+
+1. Simplified Problem Definition
+--------------------------------
+
+Assume we have a platform which boots using following simplified Device Tree.
+
+---- foo.dts -----------------------------------------------------------------
+       /* FOO platform */
+       / {
+               compatible = "corp,foo";
+
+               /* shared resources */
+               res: res {
+               };
+
+               /* On chip peripherals */
+               ocp: ocp {
+                       /* peripherals that are always instantiated */
+                       peripheral1 { ... };
+               };
+       };
+---- foo.dts -----------------------------------------------------------------
+
+We have a number of peripherals that after probing (using some undefined 
method)
+should result in different Device Tree configuration.
+
+We cannot boot with this static tree because due to the configuration of the
+foo platform there exist multiple conficting peripherals DT fragments.
+
+So for the bar peripheral we would have this:
+
+---- foo+bar.dts -------------------------------------------------------------
+       /* FOO platform + bar peripheral */
+       / {
+               compatible = "corp,foo";
+
+               /* shared resources */
+               res: res {
+               };
+
+               /* On chip peripherals */
+               ocp: ocp {
+                       /* peripherals that are always instantiated */
+                       peripheral1 { ... };
+
+                       /* bar peripheral */
+                       bar {
+                               compatible = "corp,bar";
+                               ... /* various properties and child nodes */
+                       };
+               };
+       };
+---- foo+bar.dts -------------------------------------------------------------
+
+While for the baz peripheral we would have this:
+
+---- foo+baz.dts -------------------------------------------------------------
+       /* FOO platform + baz peripheral */
+       / {
+               compatible = "corp,foo";
+
+               /* shared resources */
+               res: res {
+                       /* baz resources */
+                       baz_res: res_baz { ... };
+               };
+
+               /* On chip peripherals */
+               ocp: ocp {
+                       /* peripherals that are always instantiated */
+                       peripheral1 { ... };
+
+                       /* baz peripheral */
+                       baz {
+                               compatible = "corp,baz";
+                               /* reference to another point in the tree */
+                               ref-to-res = <&baz_res>;
+                               ... /* various properties and child nodes */
+                       };
+               };
+       };
+---- foo+baz.dts -------------------------------------------------------------
+
+We note that the baz case is more complicated, since the baz peripheral needs 
to
+reference another node in the DT tree.
+
+2. Device Tree Object Format Requirements
+-----------------------------------------
+
+Since the Device Tree is used for booting a number of very different hardware
+platforms it is imperative that we tread very carefully.
+
+2.a) No changes to the Device Tree binary format for the base tree. We cannot
+modify the tree format at all and all the information we require should be
+encoded using Device Tree itself. We can add nodes that can be safely ignored
+by both bootloaders and the kernel. The plugin dtbs are optionally tagged
+with a different magic number in the header but otherwise they're simple
+blobs.
+
+2.b) Changes to the DTS source format should be absolutely minimal, and should
+only be needed for the DT fragment definitions, and not the base boot DT.
+
+2.c) An explicit option should be used to instruct DTC to generate the required
+information needed for object resolution. Platforms that don't use the
+dynamic object format can safely ignore it.
+
+2.d) Finally, DT syntax changes should be kept to a minimum. It should be
+possible to express everything using the existing DT syntax.
+
+3. Implementation
+-----------------
+
+The basic unit of addressing in Device Tree is the phandle. Turns out it's
+relatively simple to extend the way phandles are generated and referenced
+so that it's possible to dynamically convert symbolic references (labels)
+to phandle values. This is a valid assumption as long as the author uses
+reference syntax and does not assign phandle values manually (which might
+be a problem with decompiled source files).
+
+We can roughly divide the operation into two steps.
+
+3.a) Compilation of the base board DTS file using the '-@' option
+generates a valid DT blob with an added __symbols__ node at the root node,
+containing a list of all nodes that are marked with a label.
+
+Using the foo.dts file above the following node will be generated;
+
+$ dtc -@ -O dtb -o foo.dtb -b 0 foo.dts
+$ fdtdump foo.dtb
+...
+/ {
+       ...
+       res {
+               ...
+               phandle = <0x00000001>;
+               ...
+       };
+       ocp {
+               ...
+               phandle = <0x00000002>;
+               ...
+       };
+       __symbols__ {
+               res="/res";
+               ocp="/ocp";
+       };
+};
+
+Notice that all the nodes that had a label have been recorded, and that
+phandles have been generated for them.
+
+This blob can be used to boot the board normally, the __symbols__ node will
+be safely ignored both by the bootloader and the kernel (the only loss will
+be a few bytes of memory and disk space).
+
+We generate a __symbols__ node to record nodes that had labels in the base
+tree (or subsequent loaded overlays) so that they can be matched up with
+references made to them in Device Tree objects.
+
+3.b) The Device Tree fragments must be compiled with the same option but they
+must also have a tag (/plugin/) that allows undefined references to nodes
+that are not present at compilation time to be recorded so that the runtime
+loader can fix them.
+
+So the bar peripheral's DTS format would be of the form:
+
+/dts-v1/;
+/plugin/;      /* allow undefined references and record them */
+/ {
+       ....    /* various properties for loader use; i.e. part id etc. */
+       fragment@0 {
+               target = <&ocp>;
+               __overlay__ {
+                       /* bar peripheral */
+                       bar {
+                               compatible = "corp,bar";
+                               ... /* various properties and child nodes */
+                       }
+               };
+       };
+};
+
+Note that there's a target property that specifies the location where the
+contents of the overlay node will be placed, and it references the node
+in the foo.dts file.
+
+$ dtc -@ -O dtb -o bar.dtbo -b 0 bar.dts
+$ fdtdump bar.dtbo
+...
+/ {
+       ... /* properties */
+       fragment@0 {
+               target = <0xffffffff>;
+               __overlay__ {
+                       bar {
+                               compatible = "corp,bar";
+                               ... /* various properties and child nodes */
+                       }
+               };
+       };
+       __fixups__ {
+           ocp = "/fragment@0:target:0";
+       };
+};
+
+No __symbols__ node has been generated (no label in bar.dts).
+Note that the target's ocp label is undefined, so the phandle
+value is filled with the illegal value '0xffffffff', while a __fixups__
+node has been generated, which marks the location in the tree where
+the label lookup should store the runtime phandle value of the ocp node.
+
+The format of the __fixups__ node entry is
+
+  <label> = "<local-full-path>:<property-name>:<offset>" 
+           [, "<local-full-path>:<property-name>:<offset>"...];
+
+  <label>              Is the label we're referring
+  <local-full-path>    Is the full path of the node the reference is
+  <property-name>      Is the name of the property containing the
+                       reference
+  <offset>             The offset (in bytes) of where the property's
+                       phandle value is located.
+
+Doing the same with the baz peripheral's DTS format is a little bit more
+involved, since baz contains references to local labels which require
+local fixups.
+
+/dts-v1/;
+/plugin/;      /* allow undefined label references and record them */
+/ {
+       ....    /* various properties for loader use; i.e. part id etc. */
+       fragment@0 {
+               target = <&res>;
+               __overlay__ {
+                       /* baz resources */
+                       baz_res: res_baz { ... };
+               };
+       };
+       fragment@1 {
+               target = <&ocp>;
+               __overlay__ {
+                       /* baz peripheral */
+                       baz {
+                               compatible = "corp,baz";
+                               /* reference to another point in the tree */
+                               ref-to-res = <&baz_res>;
+                               ... /* various properties and child nodes */
+                       }
+               };
+       };
+};
+
+Note that &bar_res reference.
+
+$ dtc -@ -O dtb -o baz.dtbo -b 0 baz.dts
+$ fdtdump baz.dtbo
+...
+/ {
+       ... /* properties */
+       fragment@0 {
+               target = <0xffffffff>;
+               __overlay__ {
+                       res_baz {
+                               ....
+                               phandle = <0x00000001>;
+                       };
+               };
+       };
+       fragment@1 {
+               target = <0xffffffff>;
+               __overlay__ {
+                       baz {
+                               compatible = "corp,baz";
+                               ... /* various properties and child nodes */
+                               ref-to-res = <0x00000001>;
+                       }
+               };
+       };
+       __fixups__ {
+               res = "/fragment@0:target:0";
+               ocp = "/fragment@1:target:0";
+       };
+       __local_fixups__ {
+               fragment@1 {
+                       __overlay__ {
+                               baz {
+                                       ref-to-res = <0>;
+                               };
+                       };
+               };
+       };
+};
+
+This is similar to the bar case, but the reference of a local label by the
+baz node generates a __local_fixups__ entry that records the place that the
+local reference is being made. No matter how phandles are allocated from dtc
+the run time loader must apply an offset to each phandle in every dynamic
+DT object loaded. The __local_fixups__ node records the offset relative to the
+start of every local reference within that property so that the loader can 
apply
+the offset.

Modified: head/contrib/dtc/Documentation/manual.txt
==============================================================================
--- head/contrib/dtc/Documentation/manual.txt   Fri Mar 10 17:14:08 2017        
(r315008)
+++ head/contrib/dtc/Documentation/manual.txt   Fri Mar 10 17:36:05 2017        
(r315009)
@@ -30,25 +30,23 @@ I - "dtc", the device tree compiler
 
 1) Sources
 
-Source code for the Device Tree Compiler can be found at jdl.com.
-The gitweb interface is:
+Source code for the Device Tree Compiler can be found at git.kernel.org.
 
-    http://git.jdl.com/gitweb/
+The upstream repository is here:
 
-The repository is here:
+    git://git.kernel.org/pub/scm/utils/dtc/dtc.git
+    https://git.kernel.org/pub/scm/utils/dtc/dtc.git
 
-    git://www.jdl.com/software/dtc.git
-    http://www.jdl.com/software/dtc.git
+The gitweb interface for the upstream respository is:
 
-Tarballs of the 1.0.0 and latest releases are here:
-
-    http://www.jdl.com/software/dtc-v1.2.0.tgz
-    http://www.jdl.com/software/dtc-latest.tgz
+    https://git.kernel.org/cgit/utils/dtc/dtc.git/
 
 1.1) Submitting Patches
 
-Patches should be sent to j...@jdl.com, and CC'ed to
-devicetree-disc...@lists.ozlabs.org.
+Patches should be sent to the maintainers:
+       David Gibson <da...@gibson.dropbear.id.au>
+       Jon Loeliger <j...@jdl.com>
+and CCed to <devicetree-compi...@vger.kernel.org>.
 
 2) Description
 
@@ -121,6 +119,20 @@ Options:
        Make space for <number> reserve map entries
        Relevant for dtb and asm output only.
 
+    -@
+       Generates a __symbols__ node at the root node of the resulting blob
+       for any node labels used, and for any local references using phandles
+       it also generates a __local_fixups__ node that tracks them.
+
+       When using the /plugin/ tag all unresolved label references to
+       be tracked in the __fixups__ node, making dynamic resolution possible.
+
+    -A
+       Generate automatically aliases for all node labels. This is similar to
+       the -@ option (the __symbols__ node contain identical information) but
+       the semantics are slightly different since no phandles are automatically
+       generated for labeled nodes.
+
     -S <bytes>
        Ensure the blob at least <bytes> long, adding additional
        space if needed.
@@ -148,13 +160,18 @@ Additionally, dtc performs various sanit
 Here is a very rough overview of the layout of a DTS source file:
 
 
-    sourcefile:   list_of_memreserve devicetree
+    sourcefile:   versioninfo plugindecl list_of_memreserve devicetree
 
     memreserve:   label 'memreserve' ADDR ADDR ';'
                | label 'memreserve' ADDR '-' ADDR ';'
 
     devicetree:   '/' nodedef
 
+    versioninfo:  '/' 'dts-v1' '/' ';'
+
+    plugindecl:   '/' 'plugin' '/' ';'
+                | /* empty */
+
     nodedef:      '{' list_of_property list_of_subnode '}' ';'
 
     property:     label PROPNAME '=' propdata ';'
@@ -211,7 +228,7 @@ Node may contain sub-nodes to obtain a h
 For example:
 
     - A child node named "childnode" whose unit name is
-      "childnode at address".  It it turn has a string property
+      "childnode at address".  It in turn has a string property
       called "childprop".
 
        childnode@addresss {

Modified: head/contrib/dtc/Makefile
==============================================================================
--- head/contrib/dtc/Makefile   Fri Mar 10 17:14:08 2017        (r315008)
+++ head/contrib/dtc/Makefile   Fri Mar 10 17:36:05 2017        (r315009)
@@ -10,14 +10,14 @@
 #
 VERSION = 1
 PATCHLEVEL = 4
-SUBLEVEL = 0
+SUBLEVEL = 3
 EXTRAVERSION =
 LOCAL_VERSION =
 CONFIG_LOCALVERSION =
 
 CPPFLAGS = -I libfdt -I .
-WARNINGS = -Werror -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
-       -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls
+WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
+       -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow
 CFLAGS = -g -Os -fPIC -Werror $(WARNINGS)
 
 BISON = bison
@@ -196,6 +196,33 @@ fdtget:    $(FDTGET_OBJS) $(LIBFDT_archive)
 
 fdtput:        $(FDTPUT_OBJS) $(LIBFDT_archive)
 
+dist:
+       git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
+               > ../dtc-$(dtc_version).tar
+       cat ../dtc-$(dtc_version).tar | \
+               gzip -9 > ../dtc-$(dtc_version).tar.gz
+
+#
+# Release signing and uploading
+# This is for maintainer convenience, don't try this at home.
+#
+ifeq ($(MAINTAINER),y)
+GPG = gpg2
+KUP = kup
+KUPDIR = /pub/software/utils/dtc
+
+kup: dist
+       $(GPG) --detach-sign --armor -o ../dtc-$(dtc_version).tar.sign \
+               ../dtc-$(dtc_version).tar
+       $(KUP) put ../dtc-$(dtc_version).tar.gz ../dtc-$(dtc_version).tar.sign \
+               $(KUPDIR)/dtc-$(dtc_version).tar.gz
+endif
+
+tags: FORCE
+       rm -f tags
+       find . \( -name tests -type d -prune \) -o \
+              \( ! -name '*.tab.[ch]' ! -name '*.lex.c' \
+              -name '*.[chly]' -type f -print \) | xargs ctags -a
 
 #
 # Testsuite rules
@@ -206,6 +233,7 @@ TESTS_BIN += dtc
 TESTS_BIN += convert-dtsv0
 TESTS_BIN += fdtput
 TESTS_BIN += fdtget
+TESTS_BIN += fdtdump
 
 include tests/Makefile.tests
 
@@ -220,6 +248,7 @@ clean: libfdt_clean tests_clean
        rm -f $(STD_CLEANFILES)
        rm -f $(VERSION_FILE)
        rm -f $(BIN)
+       rm -f dtc-*.tar dtc-*.tar.sign dtc-*.tar.asc
 
 #
 # Generic compile rules

Copied: head/contrib/dtc/README (from r314985, vendor/dtc/dist/README)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/contrib/dtc/README     Fri Mar 10 17:36:05 2017        (r315009, copy 
of r314985, vendor/dtc/dist/README)
@@ -0,0 +1,16 @@
+The source tree contains the Device Tree Compiler (dtc) toolchain for
+working with device tree source and binary files and also libfdt, a
+utility library for reading and manipulating the binary format.
+
+DTC and LIBFDT are maintained by:
+
+David Gibson <da...@gibson.dropbear.id.au>
+Jon Loeliger <j...@jdl.com>
+
+Mailing list
+------------
+The following list is for discussion about dtc and libfdt implementation
+mailto:devicetree-compi...@vger.kernel.org
+
+Core device tree bindings are discussed on the devicetree-spec list:
+mailto:devicetree-s...@vger.kernel.org

Modified: head/contrib/dtc/checks.c
==============================================================================
--- head/contrib/dtc/checks.c   Fri Mar 10 17:14:08 2017        (r315008)
+++ head/contrib/dtc/checks.c   Fri Mar 10 17:36:05 2017        (r315009)
@@ -40,16 +40,11 @@ enum checkstatus {
 
 struct check;
 
-typedef void (*tree_check_fn)(struct check *c, struct node *dt);
-typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node 
*node);
-typedef void (*prop_check_fn)(struct check *c, struct node *dt,
-                             struct node *node, struct property *prop);
+typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node 
*node);
 
 struct check {
        const char *name;
-       tree_check_fn tree_fn;
-       node_check_fn node_fn;
-       prop_check_fn prop_fn;
+       check_fn fn;
        void *data;
        bool warn, error;
        enum checkstatus status;
@@ -58,91 +53,68 @@ struct check {
        struct check **prereq;
 };
 
-#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...)          \
-       static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
-       static struct check nm = { \
-               .name = #nm, \
-               .tree_fn = (tfn), \
-               .node_fn = (nfn), \
-               .prop_fn = (pfn), \
-               .data = (d), \
-               .warn = (w), \
-               .error = (e), \
+#define CHECK_ENTRY(_nm, _fn, _d, _w, _e, ...)        \
+       static struct check *_nm##_prereqs[] = { __VA_ARGS__ }; \
+       static struct check _nm = { \
+               .name = #_nm, \
+               .fn = (_fn), \
+               .data = (_d), \
+               .warn = (_w), \
+               .error = (_e), \
                .status = UNCHECKED, \
-               .num_prereqs = ARRAY_SIZE(nm##_prereqs), \
-               .prereq = nm##_prereqs, \
+               .num_prereqs = ARRAY_SIZE(_nm##_prereqs), \
+               .prereq = _nm##_prereqs, \
        };
-#define WARNING(nm, tfn, nfn, pfn, d, ...) \
-       CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
-#define ERROR(nm, tfn, nfn, pfn, d, ...) \
-       CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__)
-#define CHECK(nm, tfn, nfn, pfn, d, ...) \
-       CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__)
-
-#define TREE_WARNING(nm, d, ...) \
-       WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
-#define TREE_ERROR(nm, d, ...) \
-       ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
-#define TREE_CHECK(nm, d, ...) \
-       CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
-#define NODE_WARNING(nm, d, ...) \
-       WARNING(nm, NULL, check_##nm, NULL, d,  __VA_ARGS__)
-#define NODE_ERROR(nm, d, ...) \
-       ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
-#define NODE_CHECK(nm, d, ...) \
-       CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
-#define PROP_WARNING(nm, d, ...) \
-       WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
-#define PROP_ERROR(nm, d, ...) \
-       ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
-#define PROP_CHECK(nm, d, ...) \
-       CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
+#define WARNING(_nm, _fn, _d, ...) \
+       CHECK_ENTRY(_nm, _fn, _d, true, false, __VA_ARGS__)
+#define ERROR(_nm, _fn, _d, ...) \
+       CHECK_ENTRY(_nm, _fn, _d, false, true, __VA_ARGS__)
+#define CHECK(_nm, _fn, _d, ...) \
+       CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__)
 
 #ifdef __GNUC__
-static inline void check_msg(struct check *c, const char *fmt, ...) 
__attribute__((format (printf, 2, 3)));
+static inline void check_msg(struct check *c, struct dt_info *dti,
+                            const char *fmt, ...) __attribute__((format 
(printf, 3, 4)));
 #endif
-static inline void check_msg(struct check *c, const char *fmt, ...)
+static inline void check_msg(struct check *c, struct dt_info *dti,
+                            const char *fmt, ...)
 {
        va_list ap;
        va_start(ap, fmt);
 
        if ((c->warn && (quiet < 1))
            || (c->error && (quiet < 2))) {
-               fprintf(stderr, "%s (%s): ",
+               fprintf(stderr, "%s: %s (%s): ",
+                       strcmp(dti->outname, "-") ? dti->outname : "<stdout>",
                        (c->error) ? "ERROR" : "Warning", c->name);
                vfprintf(stderr, fmt, ap);
                fprintf(stderr, "\n");
        }
+       va_end(ap);
 }
 
-#define FAIL(c, ...) \
-       do { \
-               TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
-               (c)->status = FAILED; \
-               check_msg((c), __VA_ARGS__); \
+#define FAIL(c, dti, ...)                                              \
+       do {                                                            \
+               TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__);  \
+               (c)->status = FAILED;                                   \
+               check_msg((c), dti, __VA_ARGS__);                       \
        } while (0)
 
-static void check_nodes_props(struct check *c, struct node *dt, struct node 
*node)
+static void check_nodes_props(struct check *c, struct dt_info *dti, struct 
node *node)
 {
        struct node *child;
-       struct property *prop;
 
        TRACE(c, "%s", node->fullpath);
-       if (c->node_fn)
-               c->node_fn(c, dt, node);
-
-       if (c->prop_fn)
-               for_each_property(node, prop) {
-                       TRACE(c, "%s\t'%s'", node->fullpath, prop->name);
-                       c->prop_fn(c, dt, node, prop);
-               }
+       if (c->fn)
+               c->fn(c, dti, node);
 
        for_each_child(node, child)
-               check_nodes_props(c, dt, child);
+               check_nodes_props(c, dti, child);
 }
 
-static bool run_check(struct check *c, struct node *dt)
+static bool run_check(struct check *c, struct dt_info *dti)
 {
+       struct node *dt = dti->dt;
        bool error = false;
        int i;
 
@@ -155,10 +127,10 @@ static bool run_check(struct check *c, s
 
        for (i = 0; i < c->num_prereqs; i++) {
                struct check *prq = c->prereq[i];
-               error = error || run_check(prq, dt);
+               error = error || run_check(prq, dti);
                if (prq->status != PASSED) {
                        c->status = PREREQ;
-                       check_msg(c, "Failed prerequisite '%s'",
+                       check_msg(c, dti, "Failed prerequisite '%s'",
                                  c->prereq[i]->name);
                }
        }
@@ -166,11 +138,8 @@ static bool run_check(struct check *c, s
        if (c->status != UNCHECKED)
                goto out;
 
-       if (c->node_fn || c->prop_fn)
-               check_nodes_props(c, dt, dt);
+       check_nodes_props(c, dti, dt);
 
-       if (c->tree_fn)
-               c->tree_fn(c, dt);
        if (c->status == UNCHECKED)
                c->status = PASSED;
 
@@ -188,13 +157,14 @@ out:
  */
 
 /* A check which always fails, for testing purposes only */
-static inline void check_always_fail(struct check *c, struct node *dt)
+static inline void check_always_fail(struct check *c, struct dt_info *dti,
+                                    struct node *node)
 {
-       FAIL(c, "always_fail check");
+       FAIL(c, dti, "always_fail check");
 }
-TREE_CHECK(always_fail, NULL);
+CHECK(always_fail, check_always_fail, NULL);
 
-static void check_is_string(struct check *c, struct node *root,
+static void check_is_string(struct check *c, struct dt_info *dti,
                            struct node *node)
 {
        struct property *prop;
@@ -205,15 +175,15 @@ static void check_is_string(struct check
                return; /* Not present, assumed ok */
 
        if (!data_is_one_string(prop->val))
-               FAIL(c, "\"%s\" property in %s is not a string",
+               FAIL(c, dti, "\"%s\" property in %s is not a string",
                     propname, node->fullpath);
 }
 #define WARNING_IF_NOT_STRING(nm, propname) \
-       WARNING(nm, NULL, check_is_string, NULL, (propname))
+       WARNING(nm, check_is_string, (propname))
 #define ERROR_IF_NOT_STRING(nm, propname) \
-       ERROR(nm, NULL, check_is_string, NULL, (propname))
+       ERROR(nm, check_is_string, (propname))
 
-static void check_is_cell(struct check *c, struct node *root,
+static void check_is_cell(struct check *c, struct dt_info *dti,
                          struct node *node)
 {
        struct property *prop;
@@ -224,19 +194,19 @@ static void check_is_cell(struct check *
                return; /* Not present, assumed ok */
 
        if (prop->val.len != sizeof(cell_t))
-               FAIL(c, "\"%s\" property in %s is not a single cell",
+               FAIL(c, dti, "\"%s\" property in %s is not a single cell",
                     propname, node->fullpath);
 }
 #define WARNING_IF_NOT_CELL(nm, propname) \
-       WARNING(nm, NULL, check_is_cell, NULL, (propname))
+       WARNING(nm, check_is_cell, (propname))
 #define ERROR_IF_NOT_CELL(nm, propname) \
-       ERROR(nm, NULL, check_is_cell, NULL, (propname))
+       ERROR(nm, check_is_cell, (propname))
 
 /*
  * Structural check functions
  */
 
-static void check_duplicate_node_names(struct check *c, struct node *dt,
+static void check_duplicate_node_names(struct check *c, struct dt_info *dti,
                                       struct node *node)
 {
        struct node *child, *child2;
@@ -246,12 +216,12 @@ static void check_duplicate_node_names(s
                     child2;
                     child2 = child2->next_sibling)
                        if (streq(child->name, child2->name))
-                               FAIL(c, "Duplicate node name %s",
+                               FAIL(c, dti, "Duplicate node name %s",
                                     child->fullpath);
 }
-NODE_ERROR(duplicate_node_names, NULL);
+ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
 
-static void check_duplicate_property_names(struct check *c, struct node *dt,
+static void check_duplicate_property_names(struct check *c, struct dt_info 
*dti,
                                           struct node *node)
 {
        struct property *prop, *prop2;
@@ -261,48 +231,120 @@ static void check_duplicate_property_nam
                        if (prop2->deleted)
                                continue;
                        if (streq(prop->name, prop2->name))
-                               FAIL(c, "Duplicate property name %s in %s",
+                               FAIL(c, dti, "Duplicate property name %s in %s",
                                     prop->name, node->fullpath);
                }
        }
 }
-NODE_ERROR(duplicate_property_names, NULL);
+ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
 
 #define LOWERCASE      "abcdefghijklmnopqrstuvwxyz"
 #define UPPERCASE      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 #define DIGITS         "0123456789"
 #define PROPNODECHARS  LOWERCASE UPPERCASE DIGITS ",._+*#?-"
+#define PROPNODECHARSSTRICT    LOWERCASE UPPERCASE DIGITS ",-"
 
-static void check_node_name_chars(struct check *c, struct node *dt,
+static void check_node_name_chars(struct check *c, struct dt_info *dti,
                                  struct node *node)
 {
        int n = strspn(node->name, c->data);
 
        if (n < strlen(node->name))
-               FAIL(c, "Bad character '%c' in node %s",
+               FAIL(c, dti, "Bad character '%c' in node %s",
                     node->name[n], node->fullpath);
 }
-NODE_ERROR(node_name_chars, PROPNODECHARS "@");
+ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
+
+static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
+                                        struct node *node)
+{
+       int n = strspn(node->name, c->data);
 
-static void check_node_name_format(struct check *c, struct node *dt,
+       if (n < node->basenamelen)
+               FAIL(c, dti, "Character '%c' not recommended in node %s",
+                    node->name[n], node->fullpath);
+}
+CHECK(node_name_chars_strict, check_node_name_chars_strict, 
PROPNODECHARSSTRICT);
+
+static void check_node_name_format(struct check *c, struct dt_info *dti,
                                   struct node *node)
 {
        if (strchr(get_unitname(node), '@'))
-               FAIL(c, "Node %s has multiple '@' characters in name",
+               FAIL(c, dti, "Node %s has multiple '@' characters in name",
                     node->fullpath);
 }
-NODE_ERROR(node_name_format, NULL, &node_name_chars);
+ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
 
-static void check_property_name_chars(struct check *c, struct node *dt,
-                                     struct node *node, struct property *prop)
+static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
+                                     struct node *node)
 {
-       int n = strspn(prop->name, c->data);
+       const char *unitname = get_unitname(node);
+       struct property *prop = get_property(node, "reg");
+
+       if (!prop) {
+               prop = get_property(node, "ranges");
+               if (prop && !prop->val.len)
+                       prop = NULL;
+       }
 
-       if (n < strlen(prop->name))
-               FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
-                    prop->name[n], prop->name, node->fullpath);
+       if (prop) {
+               if (!unitname[0])
+                       FAIL(c, dti, "Node %s has a reg or ranges property, but 
no unit name",
+                           node->fullpath);
+       } else {
+               if (unitname[0])
+                       FAIL(c, dti, "Node %s has a unit name, but no reg 
property",
+                           node->fullpath);
+       }
+}
+WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
+
+static void check_property_name_chars(struct check *c, struct dt_info *dti,
+                                     struct node *node)
+{
+       struct property *prop;
+
+       for_each_property(node, prop) {
+               int n = strspn(prop->name, c->data);
+
+               if (n < strlen(prop->name))
+                       FAIL(c, dti, "Bad character '%c' in property name 
\"%s\", node %s",
+                            prop->name[n], prop->name, node->fullpath);
+       }
 }
-PROP_ERROR(property_name_chars, PROPNODECHARS);
+ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
+
+static void check_property_name_chars_strict(struct check *c,
+                                            struct dt_info *dti,
+                                            struct node *node)
+{
+       struct property *prop;
+
+       for_each_property(node, prop) {
+               const char *name = prop->name;
+               int n = strspn(name, c->data);
+
+               if (n == strlen(prop->name))
+                       continue;
+
+               /* Certain names are whitelisted */
+               if (streq(name, "device_type"))
+                       continue;
+
+               /*
+                * # is only allowed at the beginning of property names not 
counting
+                * the vendor prefix.
+                */
+               if (name[n] == '#' && ((n == 0) || (name[n-1] == ','))) {
+                       name += n + 1;
+                       n = strspn(name, c->data);
+               }
+               if (n < strlen(name))
+                       FAIL(c, dti, "Character '%c' not recommended in 
property name \"%s\", node %s",
+                            name[n], prop->name, node->fullpath);
+       }
+}
+CHECK(property_name_chars_strict, check_property_name_chars_strict, 
PROPNODECHARSSTRICT);
 
 #define DESCLABEL_FMT  "%s%s%s%s%s"
 #define DESCLABEL_ARGS(node,prop,mark)         \
@@ -311,10 +353,11 @@ PROP_ERROR(property_name_chars, PROPNODE
        ((prop) ? (prop)->name : ""), \
        ((prop) ? "' in " : ""), (node)->fullpath
 
-static void check_duplicate_label(struct check *c, struct node *dt,
+static void check_duplicate_label(struct check *c, struct dt_info *dti,
                                  const char *label, struct node *node,
                                  struct property *prop, struct marker *mark)
 {
+       struct node *dt = dti->dt;
        struct node *othernode = NULL;
        struct property *otherprop = NULL;
        struct marker *othermark = NULL;
@@ -331,50 +374,49 @@ static void check_duplicate_label(struct
                return;
 
        if ((othernode != node) || (otherprop != prop) || (othermark != mark))
-               FAIL(c, "Duplicate label '%s' on " DESCLABEL_FMT
+               FAIL(c, dti, "Duplicate label '%s' on " DESCLABEL_FMT
                     " and " DESCLABEL_FMT,
                     label, DESCLABEL_ARGS(node, prop, mark),
                     DESCLABEL_ARGS(othernode, otherprop, othermark));
 }
 
-static void check_duplicate_label_node(struct check *c, struct node *dt,
+static void check_duplicate_label_node(struct check *c, struct dt_info *dti,
                                       struct node *node)
 {
        struct label *l;
+       struct property *prop;
 
        for_each_label(node->labels, l)
-               check_duplicate_label(c, dt, l->label, node, NULL, NULL);
-}
-static void check_duplicate_label_prop(struct check *c, struct node *dt,
-                                      struct node *node, struct property *prop)
-{
-       struct marker *m = prop->val.markers;
-       struct label *l;
+               check_duplicate_label(c, dti, l->label, node, NULL, NULL);
 
-       for_each_label(prop->labels, l)
-               check_duplicate_label(c, dt, l->label, node, prop, NULL);
+       for_each_property(node, prop) {
+               struct marker *m = prop->val.markers;
 
-       for_each_marker_of_type(m, LABEL)
-               check_duplicate_label(c, dt, m->ref, node, prop, m);
+               for_each_label(prop->labels, l)
+                       check_duplicate_label(c, dti, l->label, node, prop, 
NULL);
+
+               for_each_marker_of_type(m, LABEL)
+                       check_duplicate_label(c, dti, m->ref, node, prop, m);
+       }
 }
-ERROR(duplicate_label, NULL, check_duplicate_label_node,
-      check_duplicate_label_prop, NULL);
+ERROR(duplicate_label, check_duplicate_label_node, NULL);
 
-static void check_explicit_phandles(struct check *c, struct node *root,
-                                   struct node *node, struct property *prop)
+static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
+                                struct node *node, const char *propname)
 {
+       struct node *root = dti->dt;
+       struct property *prop;
        struct marker *m;
-       struct node *other;
        cell_t phandle;
 
-       if (!streq(prop->name, "phandle")
-           && !streq(prop->name, "linux,phandle"))
-               return;
+       prop = get_property(node, propname);
+       if (!prop)
+               return 0;
 
        if (prop->val.len != sizeof(cell_t)) {
-               FAIL(c, "%s has bad length (%d) %s property",
+               FAIL(c, dti, "%s has bad length (%d) %s property",
                     node->fullpath, prop->val.len, prop->name);
-               return;
+               return 0;
        }
 
        m = prop->val.markers;
@@ -384,42 +426,65 @@ static void check_explicit_phandles(stru
                        /* "Set this node's phandle equal to some
                         * other node's phandle".  That's nonsensical
                         * by construction. */ {
-                       FAIL(c, "%s in %s is a reference to another node",
+                       FAIL(c, dti, "%s in %s is a reference to another node",
                             prop->name, node->fullpath);
-                       return;
                }
                /* But setting this node's phandle equal to its own
                 * phandle is allowed - that means allocate a unique
                 * phandle for this node, even if it's not otherwise
                 * referenced.  The value will be filled in later, so
-                * no further checking for now. */
-               return;
+                * we treat it as having no phandle data for now. */
+               return 0;
        }
 
        phandle = propval_cell(prop);
 
        if ((phandle == 0) || (phandle == -1)) {
-               FAIL(c, "%s has bad value (0x%x) in %s property",
+               FAIL(c, dti, "%s has bad value (0x%x) in %s property",
                     node->fullpath, phandle, prop->name);
-               return;
+               return 0;
        }
 
-       if (node->phandle && (node->phandle != phandle))
-               FAIL(c, "%s has %s property which replaces existing phandle 
information",
-                    node->fullpath, prop->name);
+       return phandle;
+}
+
+static void check_explicit_phandles(struct check *c, struct dt_info *dti,

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to