summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorkevans <kevans@FreeBSD.org>2018-04-16 13:50:01 +0000
committerkevans <kevans@FreeBSD.org>2018-04-16 13:50:01 +0000
commitd9f90880e2063329f721aee66e12e94ee3540d82 (patch)
treef4383696c31f73808595873efaf3f74de3740902 /usr.bin
parente4eebb56f6e3f1477fa7f98acc01506e46503d56 (diff)
downloadFreeBSD-src-d9f90880e2063329f721aee66e12e94ee3540d82.zip
FreeBSD-src-d9f90880e2063329f721aee66e12e94ee3540d82.tar.gz
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"; }; };
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/dtc/dtc.117
-rw-r--r--usr.bin/dtc/dtc.cc11
-rw-r--r--usr.bin/dtc/fdt.cc67
-rw-r--r--usr.bin/dtc/fdt.hh31
4 files changed, 107 insertions, 19 deletions
diff --git a/usr.bin/dtc/dtc.1 b/usr.bin/dtc/dtc.1
index 17bf509..2458ac5 100644
--- a/usr.bin/dtc/dtc.1
+++ b/usr.bin/dtc/dtc.1
@@ -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
@@ -284,6 +284,19 @@ given
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
Overlay blobs can be applied at boot time by setting
diff --git a/usr.bin/dtc/dtc.cc b/usr.bin/dtc/dtc.cc
index 4a34419..aec5c3a 100644
--- a/usr.bin/dtc/dtc.cc
+++ b/usr.bin/dtc/dtc.cc
@@ -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;
}
diff --git a/usr.bin/dtc/fdt.cc b/usr.bin/dtc/fdt.cc
index a153756..a3bc297 100644
--- a/usr.bin/dtc/fdt.cc
+++ b/usr.bin/dtc/fdt.cc
@@ -727,14 +727,32 @@ node::parse_name(text_input_buffer &input, bool &is_property, const char *error)
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 &phandle)
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 &phandle)
}
}
}
- });
+ // 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, int &fragnum)
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);
diff --git a/usr.bin/dtc/fdt.hh b/usr.bin/dtc/fdt.hh
index cc80aed..3781d13 100644
--- a/usr.bin/dtc/fdt.hh
+++ b/usr.bin/dtc/fdt.hh
@@ -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);
};
/**
OpenPOWER on IntegriCloud