Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102121712
D41482.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D41482.diff
View Options
diff --git a/usr.bin/dtc/HACKING b/usr.bin/dtc/HACKING
--- a/usr.bin/dtc/HACKING
+++ b/usr.bin/dtc/HACKING
@@ -1,4 +1,3 @@
-
Notes for people hacking on dtc
===============================
diff --git a/usr.bin/dtc/Makefile b/usr.bin/dtc/Makefile
--- a/usr.bin/dtc/Makefile
+++ b/usr.bin/dtc/Makefile
@@ -1,4 +1,3 @@
-
PROG_CXX=dtc
SRCS= dtc.cc input_buffer.cc string.cc dtb.cc fdt.cc checking.cc
MAN= dtc.1
@@ -7,8 +6,6 @@
CXXFLAGS+= -fno-rtti -fno-exceptions
-CXXSTD= c++11
-
NO_SHARED?=NO
.include <bsd.prog.mk>
diff --git a/usr.bin/dtc/fdt.hh b/usr.bin/dtc/fdt.hh
--- a/usr.bin/dtc/fdt.hh
+++ b/usr.bin/dtc/fdt.hh
@@ -71,7 +71,7 @@
/**
* 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.
*/
@@ -663,7 +663,7 @@
/**
* 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());
}
@@ -761,7 +761,11 @@
* Mapping from names to nodes. Only unambiguous names are recorded,
* 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,
* we look up referenced nodes in this and replace the cross reference
@@ -779,6 +783,10 @@
* These should be expanded to the full path of their targets.
*/
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.
*/
@@ -827,7 +835,7 @@
* find phandles that were provided by the user explicitly when we are
* 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
* nul-terminated strings, which are not owned by this class and so
@@ -864,19 +872,19 @@
* used in resolving cross references. Also collects phandle
* 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
* holds the phandle to be assigned, and will be incremented upon
* 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
* require one. This method will recursively visit the tree starting at
* 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.
*/
@@ -925,7 +933,7 @@
* 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.
*/
- node *referenced_node(property_value &v);
+ node_ptr referenced_node(property_value &v);
/**
* Writes this FDT as a DTB to the specified output.
*/
diff --git a/usr.bin/dtc/fdt.cc b/usr.bin/dtc/fdt.cc
--- a/usr.bin/dtc/fdt.cc
+++ b/usr.bin/dtc/fdt.cc
@@ -861,7 +861,15 @@
node_ptr node::create_special_node(const string &name,
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;
}
@@ -1035,12 +1043,31 @@
string &&address,
define_map *defines)
{
- node_ptr n(new node(input,
- tree,
- std::move(name),
- std::move(label),
- std::move(address),
- defines));
+ // 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(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)
{
n = 0;
@@ -1208,7 +1235,7 @@
}
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));
for (const string &name : n->labels)
@@ -1218,9 +1245,13 @@
auto iter = node_names.find(name);
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));
ordered_node_paths.push_back({name, path});
+ if (parent)
+ {
+ node_name_parents.insert({name, parent});
+ }
}
else
{
@@ -1236,7 +1267,7 @@
}
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
// other nodes.
@@ -1264,7 +1295,7 @@
else
{
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 @@
ordered_node_paths.clear();
cross_references.clear();
fixups.clear();
- collect_names_recursive(root, p);
+ collect_names_recursive(nullptr, root, p);
}
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
property_ptr p = n->get_property("phandle");
@@ -1329,11 +1360,11 @@
}
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())
{
- assign_phandle(n.get(), next);
+ assign_phandle(n, next);
}
for (auto &c : n->child_nodes())
@@ -1391,14 +1422,14 @@
for (auto &i : sorted_phandles)
{
string target_name = i.get().val.string_data;
- node *target = nullptr;
+ node_ptr target;
string possible;
// If the node name is a path, then look it up by following the path,
// otherwise jump directly to the named node.
if (target_name[0] == '/')
{
string path;
- target = root.get();
+ target = root;
std::istringstream ss(target_name);
string path_element;
// Read the leading /
@@ -1412,14 +1443,14 @@
string node_name, node_address;
std::getline(nss, node_name, '@');
std::getline(nss, node_address, '@');
- node *next = nullptr;
+ node_ptr next;
for (auto &c : target->child_nodes())
{
if (c->name == node_name)
{
if (c->unit_address == node_address)
{
- next = c.get();
+ next = c;
break;
}
else
@@ -1478,8 +1509,8 @@
bool
device_tree::garbage_collect_marked_nodes()
{
- std::unordered_set<node*> previously_referenced_nodes;
- std::unordered_set<node*> newly_referenced_nodes;
+ std::unordered_set<node_ptr> previously_referenced_nodes;
+ std::unordered_set<node_ptr> newly_referenced_nodes;
auto mark_referenced_nodes_used = [&](node &n)
{
@@ -1489,7 +1520,7 @@
{
if (v.is_phandle())
{
- node *nx = node_names[v.string_data];
+ node_ptr nx = node_names[v.string_data];
if (nx == nullptr)
{
// Try it again, but as a path
@@ -1534,8 +1565,9 @@
while (!newly_referenced_nodes.empty())
{
- previously_referenced_nodes = std::move(newly_referenced_nodes);
- for (auto *n : previously_referenced_nodes)
+ previously_referenced_nodes = newly_referenced_nodes;
+ newly_referenced_nodes.clear();
+ for (auto &n : previously_referenced_nodes)
{
mark_referenced_nodes_used(*n);
}
@@ -1617,7 +1649,38 @@
while (valid && !input.finished())
{
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();
n = node::parse(input, *this, string(), string_set(), string(), &defines);
@@ -1732,7 +1795,7 @@
strings_writer.write_to_file(fd);
}
-node*
+node_ptr
device_tree::referenced_node(property_value &v)
{
if (v.is_phandle())
@@ -2032,6 +2095,19 @@
}
}
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
// recollect names
if (garbage_collect && garbage_collect_marked_nodes())
@@ -2127,7 +2203,7 @@
{
continue;
}
- node *n = local_fixups.get();
+ node_ptr n = local_fixups;
for (auto &p : i.path)
{
// Skip the implicit root
@@ -2142,7 +2218,7 @@
{
if (c->unit_address == p.second)
{
- n = c.get();
+ n = c;
found = true;
break;
}
@@ -2157,7 +2233,7 @@
path += p.second;
}
n->add_child(node::create_special_node(path, symbols));
- n = (--n->child_end())->get();
+ n = *(--(n->child_end()));
}
}
assert(n);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 8, 9:30 PM (21 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14543297
Default Alt Text
D41482.diff (11 KB)
Attached To
Mode
D41482: dtc: Sync with upstream commit 26a0fe5
Attached
Detach File
Event Timeline
Log In to Comment