Author: kevans
Date: Sat Jan 27 22:50:26 2018
New Revision: 328495
URL: https://svnweb.freebsd.org/changeset/base/328495

Log:
  MFC r320296, r328173: Update dtc(1)
  
  MFC r320296 (manu): dtc: Update to upstream 9ce35ff8
  
   - Add "compatible with gpl dtc X.Y.Z" to version output so U-Boot doesn't 
complain
   - Fix cross reference node
  
  This fixes some Allwinner DTS (and probably others).
  
  MFC r328173: dtc(1): Update to upstream ea3c233
  
  Highlights of this update:
  - /__local_fixups__ is now generated to be GPL dtc and libfdt compliant
  - Compiling with -@ will now cause dtc to assign phandles to all labelled
    nodes
  - /include/ and /incbin/ now handle absolute paths correctly
  - The manpage now has information about overlays, including how to apply
    them and how to generate them
  - Syntactic sugar for overlays is now supported, allowing an overlay DTS
    like:
  
  =
  /dts-v1/;
  /plugin/;
  
  &foo {
      foo,status = "okay";
  };
  =
  
  to generate a fragment targetting <&foo>.

Modified:
  stable/11/usr.bin/dtc/Makefile
  stable/11/usr.bin/dtc/dtc.1
  stable/11/usr.bin/dtc/dtc.cc
  stable/11/usr.bin/dtc/fdt.cc
  stable/11/usr.bin/dtc/fdt.hh
  stable/11/usr.bin/dtc/input_buffer.cc
  stable/11/usr.bin/dtc/input_buffer.hh
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/usr.bin/dtc/Makefile
==============================================================================
--- stable/11/usr.bin/dtc/Makefile      Sat Jan 27 22:49:34 2018        
(r328494)
+++ stable/11/usr.bin/dtc/Makefile      Sat Jan 27 22:50:26 2018        
(r328495)
@@ -4,8 +4,6 @@ PROG_CXX=dtc
 SRCS=  dtc.cc input_buffer.cc string.cc dtb.cc fdt.cc checking.cc
 MAN=   dtc.1
 
-WARNS?=        3
-
 CXXFLAGS+=     -std=c++11 -fno-rtti -fno-exceptions
 
 NO_SHARED?=NO

Modified: stable/11/usr.bin/dtc/dtc.1
==============================================================================
--- stable/11/usr.bin/dtc/dtc.1 Sat Jan 27 22:49:34 2018        (r328494)
+++ stable/11/usr.bin/dtc/dtc.1 Sat Jan 27 22:50:26 2018        (r328495)
@@ -30,7 +30,7 @@
 .\"
 .\" $FreeBSD$
 .\"/
-.Dd January 1, 2013
+.Dd January 17, 2018
 .Dt DTC 1
 .Os
 .Sh NAME
@@ -57,7 +57,7 @@
 The
 .Nm
 utility converts flattened device tree (FDT) representations.
- It is most commonly used to generate device tree blobs (DTB), the binary
+It is most commonly used to generate device tree blobs (DTB), the binary
 representation of an FDT, from device tree sources (DTS), the ASCII text source
 representation.
 .Pp
@@ -153,9 +153,9 @@ format for property values.
 These allow property value to be specified on the command line.
 .It Fl R Ar entries
 The number of empty reservation table entries to pad the table with.
-This is
-useful if you are generating a device tree blob for bootloader or similar that
-needs to reserve some memory before passing control to the operating system.
+This is useful if you are generating a device tree blob for bootloader or
+similar that needs to reserve some memory before passing control to the
+operating system.
 .It Fl S Ar bytes
 The minimum size in bytes of the blob.
 The blob will be padded after the strings table to ensure that it is the
@@ -244,6 +244,54 @@ Checks that all
 .Va /delete-node/
 statements refer to nodes that are merged.
 .El
+.Sh OVERLAYS
+The utility provides support for generating overlays, also known as plugins.
+Overlays are a method of patching a base device tree that has been compiled 
with
+the
+.Fl @
+flag, with some limited support for patching device trees that were not 
compiled
+with the
+.Fl @
+flag.
+.Pp
+To denote that a DTS is intended to be used as an overlay,
+.Va /plugin/;
+should be included in the header, following any applicable
+.Va /dts-v1/;
+tag.
+.Pp
+Conventional overlays are crafted by creating
+.Va fragment
+nodes in a root.
+Each fragment node must have either a
+.Va target
+property set to a label reference, or a
+.Va target-path
+string property set to a path.
+It must then have an
+.Va __overlay__
+child node, whose properties and child nodes are merged into the base device
+tree when the overlay is applied.
+.Pp
+Much simpler syntactic sugar was later invented to simplify generating 
overlays.
+Instead of creating targetted fragments manually, one can instead create a root
+node that targets a label in the base node using the
+.Va &label
+syntax supported in conventional DTS.
+This will indicate that a fragment should be generated for the node, with the
+given
+.Va label
+being the target, and the properties and child nodes will be used as the
+__overlay__.
+.Pp
+Both conventional overlays and the later-added syntactic sugar are supported.
+.Pp
+Overlay blobs can be applied at boot time by setting
+.Va fdt_overlays
+in
+.Xr loader.conf 5 .
+Multiple overlays may be specified, and they will be applied in the order 
given.
+.El
 .Sh EXAMPLES
 The command:
 .Pp
@@ -254,8 +302,7 @@ will generate a
 file from the device tree source
 .Pa device.dts
 and print errors if any occur during parsing or property checking.
-The
-resulting file can be assembled and linked into a binary.
+The resulting file can be assembled and linked into a binary.
 .Pp
 The command:
 .Pp
@@ -265,6 +312,33 @@ will write the device tree source for the device tree 
 .Pa device.dtb
 to the standard output.
 This is useful when debugging device trees.
+.Pp
+The command:
+.Pp
+.Dl "dtc -@ -O dtb -I dts -o device.dtb device.dts"
+.Pp
+will generate a
+.Pa device.dtb
+file from the device tree source
+.Pa device.dts
+with a __symbols__ node included so that overlays may be applied to it.
+.Pp
+The command:
+.Pp
+.Dl "dtc -@ -O dtb -I dts -o device_overlay.dtbo device_overlay.dts"
+.Pp
+will generate a
+.Pa device_overlay.dtbo
+file, using the standard extension for a device tree overlay, from the device
+tree source
+.Pa device_overlay.dts .
+A __symbols__ node will be included so that overlays may be applied to it.
+The presence of a
+.Va /plugin/;
+directive in
+.Pa device_overlay.dts
+will indicate to the utility that it should also generate the underlying
+metadata required in overlays.
 .Sh COMPATIBILITY
 This utility is intended to be compatible with the device tree compiler
 provided by elinux.org.

Modified: stable/11/usr.bin/dtc/dtc.cc
==============================================================================
--- stable/11/usr.bin/dtc/dtc.cc        Sat Jan 27 22:49:34 2018        
(r328494)
+++ stable/11/usr.bin/dtc/dtc.cc        Sat Jan 27 22:50:26 2018        
(r328495)
@@ -47,20 +47,25 @@
 using namespace dtc;
 using std::string;
 
+namespace {
+
 /**
  * The current major version of the tool.
  */
 int version_major = 0;
+int version_major_compatible = 1;
 /**
  * The current minor version of the tool.
  */
 int version_minor = 5;
+int version_minor_compatible = 4;
 /**
  * The current patch level of the tool.
  */
 int version_patch = 0;
+int version_patch_compatible = 0;
 
-static void usage(const string &argv0)
+void usage(const string &argv0)
 {
        fprintf(stderr, "Usage:\n"
                "\t%s\t[-fhsv@] [-b boot_cpu_id] [-d dependency_file]"
@@ -75,11 +80,15 @@ static void usage(const string &argv0)
 /**
  * Prints the current version of this program..
  */
-static void version(const char* progname)
+void version(const char* progname)
 {
-       fprintf(stderr, "Version: %s %d.%d.%d\n", progname, version_major,
-                       version_minor, version_patch);
+       fprintf(stdout, "Version: %s %d.%d.%d compatible with gpl dtc 
%d.%d.%d\n", progname,
+               version_major, version_minor, version_patch,
+               version_major_compatible, version_minor_compatible,
+               version_patch_compatible);
 }
+
+} // Anonymous namespace
 
 using fdt::device_tree;
 

Modified: stable/11/usr.bin/dtc/fdt.cc
==============================================================================
--- stable/11/usr.bin/dtc/fdt.cc        Sat Jan 27 22:49:34 2018        
(r328494)
+++ stable/11/usr.bin/dtc/fdt.cc        Sat Jan 27 22:50:26 2018        
(r328495)
@@ -495,6 +495,29 @@ property::property(text_input_buffer &input,
                                return;
                        case '/':
                        {
+                               if (input.consume("/incbin/(\""))
+                               {
+                                       auto loc = input.location();
+                                       std::string filename = 
input.parse_to('"');
+                                       if (!(valid = input.consume('"')))
+                                       {
+                                               loc.report_error("Syntax error, 
expected '\"' to terminate /incbin/(");
+                                               return;
+                                       }
+                                       property_value v;
+                                       if (!(valid = 
input.read_binary_file(filename, v.byte_data)))
+                                       {
+                                               input.parse_error("Cannot open 
binary include file");
+                                               return;
+                                       }
+                                       if (!(valid &= input.consume(')')))
+                                       {
+                                               input.parse_error("Syntax 
error, expected ')' to terminate /incbin/(");
+                                               return;
+                                       }
+                                       values.push_back(v);
+                                       break;
+                               }
                                unsigned long long bits = 0;
                                valid = input.consume("/bits/");
                                input.next_token();
@@ -997,7 +1020,7 @@ node::get_property(const string &key)
 }
 
 void
-node::merge_node(node_ptr other)
+node::merge_node(node_ptr &other)
 {
        for (auto &l : other->labels)
        {
@@ -1032,7 +1055,7 @@ node::merge_node(node_ptr other)
                {
                        if (i->name == c->name && i->unit_address == 
c->unit_address)
                        {
-                               i->merge_node(std::move(c));
+                               i->merge_node(c);
                                found = true;
                                break;
                        }
@@ -1205,9 +1228,68 @@ device_tree::collect_names()
        collect_names_recursive(root, p);
 }
 
+property_ptr
+device_tree::assign_phandle(node *n, uint32_t &phandle)
+{
+       // If there is an existing phandle, use it
+       property_ptr p = n->get_property("phandle");
+       if (p == 0)
+       {
+               p = n->get_property("linux,phandle");
+       }
+       if (p == 0)
+       {
+               // Otherwise insert a new phandle node
+               property_value v;
+               while (used_phandles.find(phandle) != used_phandles.end())
+               {
+                       // Note that we only don't need to
+                       // store this phandle in the set,
+                       // because we are monotonically
+                       // increasing the value of phandle and
+                       // so will only ever revisit this value
+                       // if we have used 2^32 phandles, at
+                       // which point our blob won't fit in
+                       // any 32-bit system and we've done
+                       // something badly wrong elsewhere
+                       // already.
+                       phandle++;
+               }
+               push_big_endian(v.byte_data, phandle++);
+               if (phandle_node_name == BOTH || phandle_node_name == LINUX)
+               {
+                       p.reset(new property("linux,phandle"));
+                       p->add_value(v);
+                       n->add_property(p);
+               }
+               if (phandle_node_name == BOTH || phandle_node_name == EPAPR)
+               {
+                       p.reset(new property("phandle"));
+                       p->add_value(v);
+                       n->add_property(p);
+               }
+       }
+
+       return (p);
+}
+
 void
-device_tree::resolve_cross_references()
+device_tree::assign_phandles(node_ptr &n, uint32_t &next)
 {
+       if (!n->labels.empty())
+       {
+               assign_phandle(n.get(), next);
+       }
+
+       for (auto &c : n->child_nodes())
+       {
+               assign_phandles(c, next);
+       }
+}
+
+void
+device_tree::resolve_cross_references(uint32_t &phandle)
+{
        for (auto *pv : cross_references)
        {
                node_path path = node_paths[pv->string_data];
@@ -1224,9 +1306,9 @@ device_tree::resolve_cross_references()
                                {
                                        pv->byte_data.push_back('@');
                                        push_string(pv->byte_data, p->second);
-                                       pv->byte_data.push_back(0);
                                }
                        }
+                       pv->byte_data.push_back(0);
                }
        }
        std::unordered_map<property_value*, fixup&> phandle_set;
@@ -1250,7 +1332,6 @@ device_tree::resolve_cross_references()
        });
        assert(sorted_phandles.size() == fixups.size());
 
-       uint32_t phandle = 1;
        for (auto &i : sorted_phandles)
        {
                string target_name = i.get().val.string_data;
@@ -1332,43 +1413,7 @@ device_tree::resolve_cross_references()
                        }
                }
                // If there is an existing phandle, use it
-               property_ptr p = target->get_property("phandle");
-               if (p == 0)
-               {
-                       p = target->get_property("linux,phandle");
-               }
-               if (p == 0)
-               {
-                       // Otherwise insert a new phandle node
-                       property_value v;
-                       while (used_phandles.find(phandle) != 
used_phandles.end())
-                       {
-                               // Note that we only don't need to
-                               // store this phandle in the set,
-                               // because we are monotonically
-                               // increasing the value of phandle and
-                               // so will only ever revisit this value
-                               // if we have used 2^32 phandles, at
-                               // which point our blob won't fit in
-                               // any 32-bit system and we've done
-                               // something badly wrong elsewhere
-                               // already.
-                               phandle++;
-                       }
-                       push_big_endian(v.byte_data, phandle++);
-                       if (phandle_node_name == BOTH || phandle_node_name == 
LINUX)
-                       {
-                               p.reset(new property("linux,phandle"));
-                               p->add_value(v);
-                               target->add_property(p);
-                       }
-                       if (phandle_node_name == BOTH || phandle_node_name == 
EPAPR)
-                       {
-                               p.reset(new property("phandle"));
-                               p->add_value(v);
-                               target->add_property(p);
-                       }
-               }
+               property_ptr p = assign_phandle(target, phandle);
                p->begin()->push_to_buffer(i.get().val.byte_data);
                assert(i.get().val.byte_data.size() == 4);
        }
@@ -1642,7 +1687,73 @@ device_tree::node_path::to_string() const
        return path;
 }
 
+node_ptr
+device_tree::create_fragment_wrapper(node_ptr &node, int &fragnum)
+{
+       // In a plugin, we can massage these non-/ root nodes into into a 
fragment
+       std::string fragment_address = "fragment@" + std::to_string(fragnum);
+       ++fragnum;
+
+       std::vector<property_ptr> symbols;
+
+       // Intentionally left empty
+       node_ptr newroot = node::create_special_node("", symbols);
+       node_ptr wrapper = node::create_special_node("__overlay__", symbols);
+
+       // Generate the fragment with target = <&name>
+       property_value v;
+       v.string_data = node->name;
+       v.type = property_value::PHANDLE;
+       auto prop = std::make_shared<property>(std::string("target"));
+       prop->add_value(v);
+       symbols.push_back(prop);
+
+       node_ptr fragment = node::create_special_node(fragment_address, 
symbols);
+
+       wrapper->merge_node(node);
+       fragment->add_child(std::move(wrapper));
+       newroot->add_child(std::move(fragment));
+       return newroot;
+}
+
+node_ptr
+device_tree::generate_root(node_ptr &node, int &fragnum)
+{
+
+       string name = node->name;
+       if (name == string())
+       {
+               return std::move(node);
+       }
+       else if (!is_plugin)
+       {
+               return nullptr;
+       }
+
+       return create_fragment_wrapper(node, fragnum);
+}
+
 void
+device_tree::reassign_fragment_numbers(node_ptr &node, int &delta)
+{
+
+       for (auto &c : node->child_nodes())
+       {
+               if (c->name == std::string("fragment"))
+               {
+                       int current_address = std::stoi(c->unit_address, 
nullptr, 16);
+                       std::ostringstream new_address;
+                       current_address += delta;
+                       // It's possible that we hopped more than one 
somewhere, so just reset
+                       // delta to the next in sequence.
+                       delta = current_address + 1;
+                       new_address << std::hex << current_address;
+                       c->unit_address = new_address.str();
+               }
+       }
+}
+
+void
 device_tree::parse_dts(const string &fn, FILE *depfile)
 {
        auto in = input_buffer::buffer_for_file(fn);
@@ -1663,6 +1774,7 @@ device_tree::parse_dts(const string &fn, FILE *depfile
                                dirname(fn),
                                depfile);
        bool read_header = false;
+       int fragnum = 0;
        parse_file(input, roots, read_header);
        switch (roots.size())
        {
@@ -1671,18 +1783,36 @@ device_tree::parse_dts(const string &fn, FILE *depfile
                        input.parse_error("Failed to find root node /.");
                        return;
                case 1:
-                       root = std::move(roots[0]);
+                       root = generate_root(roots[0], fragnum);
+                       if (!root)
+                       {
+                               valid = false;
+                               input.parse_error("Failed to find root node 
/.");
+                               return;
+                       }
                        break;
                default:
                {
-                       root = std::move(roots[0]);
+                       root = generate_root(roots[0], fragnum);
+                       if (!root)
+                       {
+                               valid = false;
+                               input.parse_error("Failed to find root node 
/.");
+                               return;
+                       }
                        for (auto i=++(roots.begin()), e=roots.end() ; i!=e ; 
++i)
                        {
                                auto &node = *i;
                                string name = node->name;
                                if (name == string())
                                {
-                                       root->merge_node(std::move(node));
+                                       if (is_plugin)
+                                       {
+                                               // Re-assign any fragment 
numbers based on a delta of
+                                               // fragnum before we merge it
+                                               reassign_fragment_numbers(node, 
fragnum);
+                                       }
+                                       root->merge_node(node);
                                }
                                else
                                {
@@ -1694,20 +1824,36 @@ device_tree::parse_dts(const string &fn, FILE *depfile
                                        }
                                        if (existing == node_names.end())
                                        {
-                                               fprintf(stderr, "Unable to 
merge node: %s\n", name.c_str());
+                                               if (is_plugin)
+                                               {
+                                                       auto fragment = 
create_fragment_wrapper(node, fragnum);
+                                                       
root->merge_node(fragment);
+                                               }
+                                               else
+                                               {
+                                                       fprintf(stderr, "Unable 
to merge node: %s\n", name.c_str());
+                                               }
                                        }
                                        else
                                        {
-                                               
existing->second->merge_node(std::move(node));
+                                               
existing->second->merge_node(node);
                                        }
                                }
                        }
                }
        }
        collect_names();
-       resolve_cross_references();
+       uint32_t phandle = 1;
+       // If we're writing symbols, go ahead and assign phandles to the entire
+       // tree. We'll do this before we resolve cross references, just to keep
+       // order semi-predictable and stable.
        if (write_symbols)
        {
+               assign_phandles(root, phandle);
+       }
+       resolve_cross_references(phandle);
+       if (write_symbols)
+       {
                std::vector<property_ptr> symbols;
                // Create a symbol table.  Each label  in this device tree may 
be
                // referenced by other plugins, so we create a __symbols__ node 
inside
@@ -1767,21 +1913,72 @@ device_tree::parse_dts(const string &fn, FILE *depfile
                        }
                        symbols.clear();
                        // If we have any resolved phandle references in this 
plugin, then
-                       // we must leave a property in the /__local_fixups__ 
node whose key
-                       // is 'fixup' and whose value is as described above.
+                       // we must create a child in the __local_fixups__ node 
whose path
+                       // matches the node path from the root and whose value 
contains the
+                       // location of the reference within a property.
+                       
+                       // Create a local_fixups node that is initially empty.
+                       node_ptr local_fixups = 
node::create_special_node("__local_fixups__", symbols);
                        for (auto &i : fixups)
                        {
                                if (!i.val.is_phandle())
                                {
                                        continue;
                                }
-                               symbols.push_back(create_fixup_entry(i, 
"fixup"));
+                               node *n = local_fixups.get();
+                               for (auto &p : i.path)
+                               {
+                                       // Skip the implicit root
+                                       if (p.first.empty())
+                                       {
+                                               continue;
+                                       }
+                                       bool found = false;
+                                       for (auto &c : n->child_nodes())
+                                       {
+                                               if (c->name == p.first)
+                                               {
+                                                       n = c.get();
+                                                       found = true;
+                                                       break;
+                                               }
+                                       }
+                                       if (!found)
+                                       {
+                                               
n->add_child(node::create_special_node(p.first, symbols));
+                                               n = (--n->child_end())->get();
+                                       }
+                               }
+                               assert(n);
+                               property_value pv;
+                               push_big_endian(pv.byte_data, 
static_cast<uint32_t>(i.prop->offset_of_value(i.val)));
+                               pv.type = property_value::BINARY;
+                               auto key = i.prop->get_key();
+                               property_ptr prop = n->get_property(key);
+                               // If we don't have an existing property then 
create one and
+                               // use this property value
+                               if (!prop)
+                               {
+                                       prop = 
std::make_shared<property>(std::move(key));
+                                       n->add_property(prop);
+                                       prop->add_value(pv);
+                               }
+                               else
+                               {
+                                       // If we do have an existing property 
value, try to append
+                                       // this value.
+                                       property_value &old_val = 
*(--prop->end());
+                                       if (!old_val.try_to_merge(pv))
+                                       {
+                                               prop->add_value(pv);
+                                       }
+                               }
                        }
                        // We've iterated over all fixups, but only emit the
                        // __local_fixups__ if we found some that were resolved 
internally.
-                       if (!symbols.empty())
+                       if (local_fixups->child_begin() != 
local_fixups->child_end())
                        {
-                               
root->add_child(node::create_special_node("__local_fixups__", symbols));
+                               root->add_child(std::move(local_fixups));
                        }
                }
        }

Modified: stable/11/usr.bin/dtc/fdt.hh
==============================================================================
--- stable/11/usr.bin/dtc/fdt.hh        Sat Jan 27 22:49:34 2018        
(r328494)
+++ stable/11/usr.bin/dtc/fdt.hh        Sat Jan 27 22:50:26 2018        
(r328495)
@@ -368,7 +368,7 @@ class property
        /**
         * Returns the key for this property.
         */
-       inline std::string get_key()
+       inline const std::string &get_key()
        {
                return key;
        }
@@ -618,7 +618,7 @@ class node
         * Merges a node into this one.  Any properties present in both are
         * overridden, any properties present in only one are preserved.
         */
-       void merge_node(node_ptr other);
+       void merge_node(node_ptr &other);
        /**
         * Write this node to the specified output.  Although nodes do not
         * refer to a string table directly, their properties do.  The string
@@ -674,12 +674,12 @@ class device_tree
        /**
         * The format that we should use for writing phandles.
         */
-       phandle_format phandle_node_name;
+       phandle_format phandle_node_name = EPAPR;
        /**
         * Flag indicating that this tree is valid.  This will be set to false
         * on parse errors. 
         */
-       bool valid;
+       bool valid = true;
        /**
         * Type used for memory reservations.  A reservation is two 64-bit
         * values indicating a base address and length in memory that the
@@ -773,23 +773,23 @@ class device_tree
        /**
         * The default boot CPU, specified in the device tree header.
         */
-       uint32_t boot_cpu;
+       uint32_t boot_cpu = 0;
        /**
         * The number of empty reserve map entries to generate in the blob.
         */
-       uint32_t spare_reserve_map_entries;
+       uint32_t spare_reserve_map_entries = 0;
        /**
         * The minimum size in bytes of the blob.
         */
-       uint32_t minimum_blob_size;
+       uint32_t minimum_blob_size = 0;
        /**
         * The number of bytes of padding to add to the end of the blob.
         */
-       uint32_t blob_padding;
+       uint32_t blob_padding = 0;
        /**
         * Is this tree a plugin?
         */
-       bool is_plugin;
+       bool is_plugin = false;
        /**
         * Visit all of the nodes recursively, and if they have labels then add
         * them to the node_paths and node_names vectors so that they can be
@@ -798,6 +798,12 @@ class device_tree
         */
        void collect_names_recursive(node_ptr &n, node_path &path);
        /**
+        * Assign a phandle property to a single node.  The next parameter
+        * holds the phandle to be assigned, and will be incremented upon
+        * assignment.
+        */
+       property_ptr assign_phandle(node *n, uint32_t &next);
+       /**
         * Assign phandle properties to all nodes that have been referenced and
         * require one.  This method will recursively visit the tree starting at
         * the node that it is passed.
@@ -810,9 +816,11 @@ class device_tree
        /**
         * Resolves all cross references.  Any properties that refer to another
         * node must have their values replaced by either the node path or
-        * phandle value.
+        * phandle value.  The phandle parameter holds the next phandle to be
+        * assigned, should the need arise.  It will be incremented upon each
+        * assignment of a phandle.
         */
-       void resolve_cross_references();
+       void resolve_cross_references(uint32_t &phandle);
        /**
         * Parses a dts file in the given buffer and adds the roots to the 
parsed
         * set.  The `read_header` argument indicates whether the header has
@@ -857,15 +865,33 @@ class device_tree
        /**
         * Default constructor.  Creates a valid, but empty FDT.
         */
-       device_tree() : phandle_node_name(EPAPR), valid(true),
-               boot_cpu(0), spare_reserve_map_entries(0),
-               minimum_blob_size(0), blob_padding(0) {}
+       device_tree() {}
        /**
         * Constructs a device tree from the specified file name, referring to
         * a file that contains a device tree blob.
         */
        void parse_dtb(const std::string &fn, FILE *depfile);
        /**
+        * Construct a fragment wrapper around node.  This will assume that 
node's
+        * name may be used as the target of the fragment, and the contents are 
to
+        * be wrapped in an __overlay__ node.  The fragment wrapper will be 
assigned
+        * fragnumas its fragment number, and fragment number will be 
incremented.
+        */
+       node_ptr create_fragment_wrapper(node_ptr &node, int &fragnum);
+       /**
+        * Generate a root node from the node passed in.  This is sensitive to
+        * whether we're in a plugin context or not, so that if we're in a 
plugin we
+        * can circumvent any errors that might normally arise from a non-/ 
root.
+        * fragnum will be assigned to any fragment wrapper generated as a 
result
+        * of the call, and fragnum will be incremented.
+        */
+       node_ptr generate_root(node_ptr &node, int &fragnum);
+       /**
+        * Reassign any fragment numbers from this new node, based on the given
+        * delta.
+        */
+       void reassign_fragment_numbers(node_ptr &node, int &delta);
+       /*
         * Constructs a device tree from the specified file name, referring to
         * a file that contains device tree source.
         */
@@ -904,7 +930,10 @@ class device_tree
         */
        void sort()
        {
-               root->sort();
+               if (root)
+               {
+                       root->sort();
+               }
        }
        /**
         * Adds a path to search for include files.  The argument must be a

Modified: stable/11/usr.bin/dtc/input_buffer.cc
==============================================================================
--- stable/11/usr.bin/dtc/input_buffer.cc       Sat Jan 27 22:49:34 2018        
(r328494)
+++ stable/11/usr.bin/dtc/input_buffer.cc       Sat Jan 27 22:50:26 2018        
(r328495)
@@ -204,9 +204,9 @@ text_input_buffer::handle_include()
        {
                next_token();
                string name = parse_property_name();
-               if (defines.count(name) > 0)
+               if (defines.count(name) == 0)
                {
-                       reallyInclude = true;
+                       reallyInclude = false;
                }
                consume('/');
        }
@@ -248,6 +248,48 @@ text_input_buffer::handle_include()
                return;
        }
        input_stack.push(std::move(include_buffer));
+}
+
+bool text_input_buffer::read_binary_file(const std::string &filename, 
byte_buffer &b)
+{
+       bool try_include_paths = true;
+       string include_file;
+       if (filename[0] == '/')
+       {
+               include_file = filename;
+               // Don't try include paths if we're given an absolute path.
+               // Failing is better so that we don't accidentally do the wrong 
thing,
+               // but make it seem like everything is alright.
+               try_include_paths = false;
+       }
+       else
+       {
+               include_file = dir + '/' + filename;
+       }
+       auto include_buffer = input_buffer::buffer_for_file(include_file, 
false);
+       if (include_buffer == 0 && try_include_paths)
+       {
+               for (auto i : include_paths)
+               {
+                       include_file = i + '/' + filename;
+                       include_buffer = 
input_buffer::buffer_for_file(include_file, false);
+                       if (include_buffer != 0)
+                       {
+                               break;
+                       }
+               }
+       }
+       if (!include_buffer)
+       {
+               return false;
+       }
+       if (depfile)
+       {
+               putc(' ', depfile);
+               fputs(include_file.c_str(), depfile);
+       }
+       b.insert(b.begin(), include_buffer->begin(), include_buffer->end());
+       return true;
 }
 
 input_buffer

Modified: stable/11/usr.bin/dtc/input_buffer.hh
==============================================================================
--- stable/11/usr.bin/dtc/input_buffer.hh       Sat Jan 27 22:49:34 2018        
(r328494)
+++ stable/11/usr.bin/dtc/input_buffer.hh       Sat Jan 27 22:50:26 2018        
(r328495)
@@ -164,6 +164,14 @@ class input_buffer
                cursor++; 
                return *this;
        }
+       const char *begin()
+       {
+               return buffer;
+       }
+       const char *end()
+       {
+               return buffer + size;
+       }
        /**
         * Consumes a character.  Moves the cursor one character forward if the
         * next character matches the argument, returning true.  If the current
@@ -523,6 +531,13 @@ class text_input_buffer
         * Prints a message indicating the location of a parse error.
         */
        void parse_error(const char *msg);
+       /**
+        * Reads the contents of a binary file into `b`.  The file name is 
assumed
+        * to be relative to one of the include paths.
+        *
+        * Returns true if the file exists and can be read, false otherwise.
+        */
+       bool read_binary_file(const std::string &filename, byte_buffer &b);
        private:
        /**
         * Prints a message indicating the location of a parse error, given a
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to