dtc: Sync with upstream commit 26a0fe5

- 0206c0f ("Handle top-level /delete-node/ directives.")
- d612a9e ("Remove C++11 standard constrain")
- Remove extra white lines after the $FreeBSD$ tag removal

Reviewed by:	kevans (earlier), theraven, emaste
Differential Revision: https://reviews.freebsd.org/D41482
This commit is contained in:
Jose Luis Duran 2023-09-26 12:37:52 -04:00 committed by Ed Maste
parent e6dc6a2723
commit 29a55fd09b
4 changed files with 121 additions and 41 deletions

View file

@ -1,4 +1,3 @@
Notes for people hacking on dtc Notes for people hacking on dtc
=============================== ===============================

View file

@ -1,4 +1,3 @@
PROG_CXX=dtc PROG_CXX=dtc
SRCS= dtc.cc input_buffer.cc string.cc dtb.cc fdt.cc checking.cc SRCS= dtc.cc input_buffer.cc string.cc dtb.cc fdt.cc checking.cc
MAN= dtc.1 MAN= dtc.1
@ -7,8 +6,6 @@ WARNS?= 3
CXXFLAGS+= -fno-rtti -fno-exceptions CXXFLAGS+= -fno-rtti -fno-exceptions
CXXSTD= c++11
NO_SHARED?=NO NO_SHARED?=NO
.include <bsd.prog.mk> .include <bsd.prog.mk>

View file

@ -861,7 +861,15 @@ node::node(const string &n,
node_ptr node::create_special_node(const string &name, node_ptr node::create_special_node(const string &name,
const std::vector<property_ptr> &props) const std::vector<property_ptr> &props)
{ {
node_ptr n(new node(name, props)); // Work around for the fact that we can't call make_shared on something
// with a private constructor. Instead create a subclass with a public
// constructor that is visible only in this function and construct that
// instead.
struct constructable_node : public node
{
constructable_node(const string &n, const std::vector<property_ptr> &p) : node(n, p) {}
};
node_ptr n{std::make_shared<constructable_node>(name, props)};
return n; return n;
} }
@ -1035,12 +1043,31 @@ node::parse(text_input_buffer &input,
string &&address, string &&address,
define_map *defines) define_map *defines)
{ {
node_ptr n(new node(input, // Work around for the fact that we can't call make_shared on something
tree, // with a private constructor. Instead create a subclass with a public
std::move(name), // constructor that is visible only in this function and construct that
std::move(label), // instead.
std::move(address), struct constructable_node : public node
defines)); {
constructable_node(text_input_buffer &input,
device_tree &tree,
std::string &&n,
std::unordered_set<std::string> &&l,
std::string &&a,
define_map*m) : node(input,
tree,
std::move(n),
std::move(l),
std::move(a),
m)
{}
};
node_ptr n{std::make_shared<constructable_node>(input,
tree,
std::move(name),
std::move(label),
std::move(address),
defines)};
if (!n->valid) if (!n->valid)
{ {
n = 0; n = 0;
@ -1208,7 +1235,7 @@ node::write_dts(FILE *file, int indent)
} }
void void
device_tree::collect_names_recursive(node_ptr &n, node_path &path) device_tree::collect_names_recursive(node_ptr parent, node_ptr n, node_path &path)
{ {
path.push_back(std::make_pair(n->name, n->unit_address)); path.push_back(std::make_pair(n->name, n->unit_address));
for (const string &name : n->labels) for (const string &name : n->labels)
@ -1218,9 +1245,13 @@ device_tree::collect_names_recursive(node_ptr &n, node_path &path)
auto iter = node_names.find(name); auto iter = node_names.find(name);
if (iter == node_names.end()) if (iter == node_names.end())
{ {
node_names.insert(std::make_pair(name, n.get())); node_names.insert(std::make_pair(name, n));
node_paths.insert(std::make_pair(name, path)); node_paths.insert(std::make_pair(name, path));
ordered_node_paths.push_back({name, path}); ordered_node_paths.push_back({name, path});
if (parent)
{
node_name_parents.insert({name, parent});
}
} }
else else
{ {
@ -1236,7 +1267,7 @@ device_tree::collect_names_recursive(node_ptr &n, node_path &path)
} }
for (auto &c : n->child_nodes()) for (auto &c : n->child_nodes())
{ {
collect_names_recursive(c, path); collect_names_recursive(n, c, path);
} }
// Now we collect the phandles and properties that reference // Now we collect the phandles and properties that reference
// other nodes. // other nodes.
@ -1264,7 +1295,7 @@ device_tree::collect_names_recursive(node_ptr &n, node_path &path)
else else
{ {
uint32_t phandle = p->begin()->get_as_uint32(); uint32_t phandle = p->begin()->get_as_uint32();
used_phandles.insert(std::make_pair(phandle, n.get())); used_phandles.insert(std::make_pair(phandle, n));
} }
} }
} }
@ -1280,11 +1311,11 @@ device_tree::collect_names()
ordered_node_paths.clear(); ordered_node_paths.clear();
cross_references.clear(); cross_references.clear();
fixups.clear(); fixups.clear();
collect_names_recursive(root, p); collect_names_recursive(nullptr, root, p);
} }
property_ptr property_ptr
device_tree::assign_phandle(node *n, uint32_t &phandle) device_tree::assign_phandle(node_ptr n, uint32_t &phandle)
{ {
// If there is an existing phandle, use it // If there is an existing phandle, use it
property_ptr p = n->get_property("phandle"); property_ptr p = n->get_property("phandle");
@ -1329,11 +1360,11 @@ device_tree::assign_phandle(node *n, uint32_t &phandle)
} }
void void
device_tree::assign_phandles(node_ptr &n, uint32_t &next) device_tree::assign_phandles(node_ptr n, uint32_t &next)
{ {
if (!n->labels.empty()) if (!n->labels.empty())
{ {
assign_phandle(n.get(), next); assign_phandle(n, next);
} }
for (auto &c : n->child_nodes()) for (auto &c : n->child_nodes())
@ -1391,14 +1422,14 @@ device_tree::resolve_cross_references(uint32_t &phandle)
for (auto &i : sorted_phandles) for (auto &i : sorted_phandles)
{ {
string target_name = i.get().val.string_data; string target_name = i.get().val.string_data;
node *target = nullptr; node_ptr target;
string possible; string possible;
// If the node name is a path, then look it up by following the path, // If the node name is a path, then look it up by following the path,
// otherwise jump directly to the named node. // otherwise jump directly to the named node.
if (target_name[0] == '/') if (target_name[0] == '/')
{ {
string path; string path;
target = root.get(); target = root;
std::istringstream ss(target_name); std::istringstream ss(target_name);
string path_element; string path_element;
// Read the leading / // Read the leading /
@ -1412,14 +1443,14 @@ device_tree::resolve_cross_references(uint32_t &phandle)
string node_name, node_address; string node_name, node_address;
std::getline(nss, node_name, '@'); std::getline(nss, node_name, '@');
std::getline(nss, node_address, '@'); std::getline(nss, node_address, '@');
node *next = nullptr; node_ptr next;
for (auto &c : target->child_nodes()) for (auto &c : target->child_nodes())
{ {
if (c->name == node_name) if (c->name == node_name)
{ {
if (c->unit_address == node_address) if (c->unit_address == node_address)
{ {
next = c.get(); next = c;
break; break;
} }
else else
@ -1478,8 +1509,8 @@ device_tree::resolve_cross_references(uint32_t &phandle)
bool bool
device_tree::garbage_collect_marked_nodes() device_tree::garbage_collect_marked_nodes()
{ {
std::unordered_set<node*> previously_referenced_nodes; std::unordered_set<node_ptr> previously_referenced_nodes;
std::unordered_set<node*> newly_referenced_nodes; std::unordered_set<node_ptr> newly_referenced_nodes;
auto mark_referenced_nodes_used = [&](node &n) auto mark_referenced_nodes_used = [&](node &n)
{ {
@ -1489,7 +1520,7 @@ device_tree::garbage_collect_marked_nodes()
{ {
if (v.is_phandle()) if (v.is_phandle())
{ {
node *nx = node_names[v.string_data]; node_ptr nx = node_names[v.string_data];
if (nx == nullptr) if (nx == nullptr)
{ {
// Try it again, but as a path // Try it again, but as a path
@ -1534,8 +1565,9 @@ device_tree::garbage_collect_marked_nodes()
while (!newly_referenced_nodes.empty()) while (!newly_referenced_nodes.empty())
{ {
previously_referenced_nodes = std::move(newly_referenced_nodes); previously_referenced_nodes = newly_referenced_nodes;
for (auto *n : previously_referenced_nodes) newly_referenced_nodes.clear();
for (auto &n : previously_referenced_nodes)
{ {
mark_referenced_nodes_used(*n); mark_referenced_nodes_used(*n);
} }
@ -1617,7 +1649,38 @@ device_tree::parse_file(text_input_buffer &input,
while (valid && !input.finished()) while (valid && !input.finished())
{ {
node_ptr n; node_ptr n;
if (input.consume('/')) if (input.consume("/delete-node/"))
{
// Top-level /delete-node/ directives refer to references that must
// be deleted later.
input.next_token();
auto expect = [&](auto token, const char *msg)
{
if (!input.consume(token))
{
input.parse_error(msg);
valid = false;
}
input.next_token();
return valid;
};
if (expect('&', "Expected reference after top-level /delete-node/."))
{
string ref = input.parse_node_name();
if (ref == string())
{
input.parse_error("Expected label name for top-level /delete-node/.");
valid = false;
}
else
{
deletions.push_back(std::move(ref));
}
expect(';', "Missing semicolon.");
}
continue;
}
else if (input.consume('/'))
{ {
input.next_token(); input.next_token();
n = node::parse(input, *this, string(), string_set(), string(), &defines); n = node::parse(input, *this, string(), string_set(), string(), &defines);
@ -1732,7 +1795,7 @@ device_tree::write(int fd)
strings_writer.write_to_file(fd); strings_writer.write_to_file(fd);
} }
node* node_ptr
device_tree::referenced_node(property_value &v) device_tree::referenced_node(property_value &v)
{ {
if (v.is_phandle()) if (v.is_phandle())
@ -2032,6 +2095,19 @@ device_tree::parse_dts(const string &fn, FILE *depfile)
} }
} }
collect_names(); collect_names();
for (auto &ref : deletions)
{
auto parent = node_name_parents[ref];
auto node = node_names[ref];
if (!parent)
{
fprintf(stderr, "Top-level /delete-node/ directive refers to label %s, which is not found.\n", ref.c_str());
}
else
{
parent->delete_children_if([&](node_ptr &child) { return child == node; });
}
}
// Return value indicates whether we've dirtied the tree or not and need to // Return value indicates whether we've dirtied the tree or not and need to
// recollect names // recollect names
if (garbage_collect && garbage_collect_marked_nodes()) if (garbage_collect && garbage_collect_marked_nodes())
@ -2127,7 +2203,7 @@ device_tree::parse_dts(const string &fn, FILE *depfile)
{ {
continue; continue;
} }
node *n = local_fixups.get(); node_ptr n = local_fixups;
for (auto &p : i.path) for (auto &p : i.path)
{ {
// Skip the implicit root // Skip the implicit root
@ -2142,7 +2218,7 @@ device_tree::parse_dts(const string &fn, FILE *depfile)
{ {
if (c->unit_address == p.second) if (c->unit_address == p.second)
{ {
n = c.get(); n = c;
found = true; found = true;
break; break;
} }
@ -2157,7 +2233,7 @@ device_tree::parse_dts(const string &fn, FILE *depfile)
path += p.second; path += p.second;
} }
n->add_child(node::create_special_node(path, symbols)); n->add_child(node::create_special_node(path, symbols));
n = (--n->child_end())->get(); n = *(--(n->child_end()));
} }
} }
assert(n); assert(n);

View file

@ -71,7 +71,7 @@ typedef std::shared_ptr<property> property_ptr;
/** /**
* Owning pointer to a node. * Owning pointer to a node.
*/ */
typedef std::unique_ptr<node> node_ptr; typedef std::shared_ptr<node> node_ptr;
/** /**
* Map from macros to property pointers. * Map from macros to property pointers.
*/ */
@ -663,7 +663,7 @@ class node
/** /**
* Deletes any children from this node. * Deletes any children from this node.
*/ */
inline void delete_children_if(bool (*predicate)(node_ptr &)) inline void delete_children_if(std::function<bool(node_ptr &)> predicate)
{ {
children.erase(std::remove_if(children.begin(), children.end(), predicate), children.end()); children.erase(std::remove_if(children.begin(), children.end(), predicate), children.end());
} }
@ -761,7 +761,11 @@ class device_tree
* Mapping from names to nodes. Only unambiguous names are recorded, * Mapping from names to nodes. Only unambiguous names are recorded,
* duplicate names are stored as (node*)-1. * duplicate names are stored as (node*)-1.
*/ */
std::unordered_map<std::string, node*> node_names; std::unordered_map<std::string, node_ptr> node_names;
/**
* Mapping from names to the nodes that contain them.
*/
std::unordered_map<std::string, node_ptr> node_name_parents;
/** /**
* A map from labels to node paths. When resolving cross references, * A map from labels to node paths. When resolving cross references,
* we look up referenced nodes in this and replace the cross reference * we look up referenced nodes in this and replace the cross reference
@ -779,6 +783,10 @@ class device_tree
* These should be expanded to the full path of their targets. * These should be expanded to the full path of their targets.
*/ */
std::vector<property_value*> cross_references; std::vector<property_value*> cross_references;
/**
* Labels collected from top-level /delete-node/ directives.
*/
std::vector<std::string> deletions;
/** /**
* The location of something requiring a fixup entry. * The location of something requiring a fixup entry.
*/ */
@ -827,7 +835,7 @@ class device_tree
* find phandles that were provided by the user explicitly when we are * find phandles that were provided by the user explicitly when we are
* doing checking. * doing checking.
*/ */
std::unordered_map<uint32_t, node*> used_phandles; std::unordered_map<uint32_t, node_ptr> used_phandles;
/** /**
* Paths to search for include files. This contains a set of * Paths to search for include files. This contains a set of
* nul-terminated strings, which are not owned by this class and so * nul-terminated strings, which are not owned by this class and so
@ -864,19 +872,19 @@ class device_tree
* used in resolving cross references. Also collects phandle * used in resolving cross references. Also collects phandle
* properties that have been explicitly added. * properties that have been explicitly added.
*/ */
void collect_names_recursive(node_ptr &n, node_path &path); void collect_names_recursive(node_ptr parent, node_ptr n, node_path &path);
/** /**
* Assign a phandle property to a single node. The next parameter * Assign a phandle property to a single node. The next parameter
* holds the phandle to be assigned, and will be incremented upon * holds the phandle to be assigned, and will be incremented upon
* assignment. * assignment.
*/ */
property_ptr assign_phandle(node *n, uint32_t &next); property_ptr assign_phandle(node_ptr n, uint32_t &next);
/** /**
* Assign phandle properties to all nodes that have been referenced and * Assign phandle properties to all nodes that have been referenced and
* require one. This method will recursively visit the tree starting at * require one. This method will recursively visit the tree starting at
* the node that it is passed. * the node that it is passed.
*/ */
void assign_phandles(node_ptr &n, uint32_t &next); void assign_phandles(node_ptr n, uint32_t &next);
/** /**
* Calls the recursive version of this method on every root node. * Calls the recursive version of this method on every root node.
*/ */
@ -925,7 +933,7 @@ class device_tree
* is in source form, then we have a string that we can use to index * is in source form, then we have a string that we can use to index
* the cross_references array and so we can just look that up. * the cross_references array and so we can just look that up.
*/ */
node *referenced_node(property_value &v); node_ptr referenced_node(property_value &v);
/** /**
* Writes this FDT as a DTB to the specified output. * Writes this FDT as a DTB to the specified output.
*/ */