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"; }; }; MFC after: 3 days
This commit is contained in:
parent
55efba01c6
commit
e69f393430
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -408,6 +408,10 @@ class node
|
||||
* The name of the 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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user