Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 Apr 2018 13:50:02 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r332562 - stable/11/usr.bin/dtc
Message-ID:  <201804161350.w3GDo2v9017329@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Mon Apr 16 13:50:01 2018
New Revision: 332562
URL: https://svnweb.freebsd.org/changeset/base/332562

Log:
  MFC r332483:
  
  dtc(1): Update to upstream 006664a
  
  Highlights:
  
  - Passing "-" to -o will now cause output to go to stdout
  - Path-based syntactic sugar for overlays is now accepted. This looks like:
  
  /dts-v1/;
  /plugin/;
  
  &{/soc} {
      sid: eeprom@1c14000 {
          compatible = "allwinner,sun8i-h3-sid";
          reg = <0x1c14000 0x400>;
          status = "okay";
      };
  };

Modified:
  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
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/usr.bin/dtc/dtc.1
==============================================================================
--- stable/11/usr.bin/dtc/dtc.1	Mon Apr 16 13:18:18 2018	(r332561)
+++ stable/11/usr.bin/dtc/dtc.1	Mon Apr 16 13:50:01 2018	(r332562)
@@ -30,7 +30,7 @@
 .\"
 .\" $FreeBSD$
 .\"/
-.Dd January 17, 2018
+.Dd April 7, 2018
 .Dt DTC 1
 .Os
 .Sh NAME
@@ -275,7 +275,7 @@ 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
+node that targets a label in the base FDT using the
 .Va &label
 syntax supported in conventional DTS.
 This will indicate that a fragment should be generated for the node, with the
@@ -283,6 +283,19 @@ given
 .Va label
 being the target, and the properties and child nodes will be used as the
 __overlay__.
+.Pp
+Additionally, a path-based version of this syntactic sugar is supported.
+A root node may target a path in the base FDT using a name of the form
+.Va &{/path} .
+A fragment will be generated for the node as it is in the
+.Va &label
+case, except the
+.Va target-path
+property will be set to
+.Va /path
+and no
+.Va target
+will be set.
 .Pp
 Both conventional overlays and the later-added syntactic sugar are supported.
 .Pp

Modified: stable/11/usr.bin/dtc/dtc.cc
==============================================================================
--- stable/11/usr.bin/dtc/dtc.cc	Mon Apr 16 13:18:18 2018	(r332561)
+++ stable/11/usr.bin/dtc/dtc.cc	Mon Apr 16 13:50:01 2018	(r332562)
@@ -171,11 +171,14 @@ main(int argc, char **argv)
 		case 'o':
 		{
 			outfile_name = optarg;
-			outfile = open(optarg, O_CREAT | O_TRUNC | O_WRONLY, 0666);
-			if (outfile == -1)
+			if (strcmp(outfile_name, "-") != 0)
 			{
-				perror("Unable to open output file");
-				return EXIT_FAILURE;
+				outfile = open(optarg, O_CREAT | O_TRUNC | O_WRONLY, 0666);
+				if (outfile == -1)
+				{
+					perror("Unable to open output file");
+					return EXIT_FAILURE;
+				}
 			}
 			break;
 		}

Modified: stable/11/usr.bin/dtc/fdt.cc
==============================================================================
--- stable/11/usr.bin/dtc/fdt.cc	Mon Apr 16 13:18:18 2018	(r332561)
+++ stable/11/usr.bin/dtc/fdt.cc	Mon Apr 16 13:50:01 2018	(r332562)
@@ -727,14 +727,32 @@ node::parse_name(text_input_buffer &input, bool &is_pr
 	return n;
 }
 
-void
-node::visit(std::function<void(node&)> fn)
+node::visit_behavior
+node::visit(std::function<visit_behavior(node&, node*)> fn, node *parent)
 {
-	fn(*this);
-	for (auto &&c : children)
+	visit_behavior behavior;
+	behavior = fn(*this, parent);
+	if (behavior == VISIT_BREAK)
 	{
-		c->visit(fn);
+		return VISIT_BREAK;
 	}
+	else if (behavior != VISIT_CONTINUE)
+	{
+		for (auto &&c : children)
+		{
+			behavior = c->visit(fn, this);
+			// Any status other than VISIT_RECURSE stops our execution and
+			// bubbles up to our caller.  The caller may then either continue
+			// visiting nodes that are siblings to this one or completely halt
+			// visiting.
+			if (behavior != VISIT_RECURSE)
+			{
+				return behavior;
+			}
+		}
+	}
+	// Continue recursion by default
+	return VISIT_RECURSE;
 }
 
 node::node(input_buffer &structs, input_buffer &strings) : valid(true)
@@ -1319,7 +1337,7 @@ device_tree::resolve_cross_references(uint32_t &phandl
 		phandle_set.insert({&i.val, i});
 	}
 	std::vector<std::reference_wrapper<fixup>> sorted_phandles;
-	root->visit([&](node &n) {
+	root->visit([&](node &n, node *parent) {
 		for (auto &p : n.properties())
 		{
 			for (auto &v : *p)
@@ -1331,7 +1349,9 @@ device_tree::resolve_cross_references(uint32_t &phandl
 				}
 			}
 		}
-	});
+		// Allow recursion
+		return node::VISIT_RECURSE;
+	}, nullptr);
 	assert(sorted_phandles.size() == fixups.size());
 
 	for (auto &i : sorted_phandles)
@@ -1471,9 +1491,24 @@ device_tree::parse_file(text_input_buffer &input,
 		else if (input.consume('&'))
 		{
 			input.next_token();
-			string name = input.parse_node_name();
+			string name;
+			bool name_is_path_reference = false;
+			// This is to deal with names intended as path references, e.g. &{/path}.
+			// While it may make sense in a non-plugin context, we don't support such
+			// usage at this time.
+			if (input.consume('{') && is_plugin)
+			{
+				name = input.parse_to('}');
+				input.consume('}');
+				name_is_path_reference = true;
+			}
+			else
+			{
+				name = input.parse_node_name();
+			}
 			input.next_token();
 			n = node::parse(input, std::move(name), string_set(), string(), &defines);
+			n->name_is_path_reference = name_is_path_reference;
 		}
 		else
 		{
@@ -1702,11 +1737,21 @@ device_tree::create_fragment_wrapper(node_ptr &node, i
 	node_ptr newroot = node::create_special_node("", symbols);
 	node_ptr wrapper = node::create_special_node("__overlay__", symbols);
 
-	// Generate the fragment with target = <&name>
+	// Generate the fragment with $propname = <&name>
 	property_value v;
+	std::string propname;
 	v.string_data = node->name;
-	v.type = property_value::PHANDLE;
-	auto prop = std::make_shared<property>(std::string("target"));
+	if (!node->name_is_path_reference)
+	{
+		propname = "target";
+		v.type = property_value::PHANDLE;
+	}
+	else
+	{
+		propname = "target-path";
+		v.type = property_value::STRING;
+	}
+	auto prop = std::make_shared<property>(std::string(propname));
 	prop->add_value(v);
 	symbols.push_back(prop);
 

Modified: stable/11/usr.bin/dtc/fdt.hh
==============================================================================
--- stable/11/usr.bin/dtc/fdt.hh	Mon Apr 16 13:18:18 2018	(r332561)
+++ stable/11/usr.bin/dtc/fdt.hh	Mon Apr 16 13:50:01 2018	(r332562)
@@ -409,6 +409,10 @@ class node
 	 */
 	std::string name;
 	/**
+	 * The name of the node is a path reference.
+	 */
+	bool name_is_path_reference = false;
+	/**
 	 * The unit address of the node, which is optionally written after the
 	 * name followed by an at symbol.
 	 */
@@ -421,6 +425,25 @@ class node
 	 * Iterator type for child nodes.
 	 */
 	typedef std::vector<node_ptr>::iterator child_iterator;
+	/**
+	 * Recursion behavior to be observed for visiting
+	 */
+	enum visit_behavior
+	{
+		/**
+		 * Recurse as normal through the rest of the tree.
+		 */
+		VISIT_RECURSE,
+		/**
+		 * Continue recursing through the device tree, but do not
+		 * recurse through this branch of the tree any further.
+		 */
+		VISIT_CONTINUE,
+		/**
+		 * Immediately halt the visit.  No further nodes will be visited.
+		 */
+		VISIT_BREAK
+	};
 	private:
 	/**
 	 * Adaptor to use children in range-based for loops.
@@ -635,9 +658,13 @@ class node
 	 */
 	void write_dts(FILE *file, int indent);
 	/**
-	 * Recursively visit this node and then its children.
+	 * Recursively visit this node and then its children based on the
+	 * callable's return value.  The callable may return VISIT_BREAK
+	 * immediately halt all recursion and end the visit, VISIT_CONTINUE to
+	 * not recurse into the current node's children, or VISIT_RECURSE to recurse
+	 * through children as expected.  parent will be passed to the callable.
 	 */
-	void visit(std::function<void(node&)>);
+	visit_behavior visit(std::function<visit_behavior(node&, node*)>, node *parent);
 };
 
 /**



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201804161350.w3GDo2v9017329>