1use alloc::{
11 collections::BTreeMap,
12 string::{String, ToString},
13 vec::Vec,
14};
15
16use crate::{
17 FdtData, FdtEncoder, FdtError, Node, NodeId, NodeType, NodeTypeMut, NodeView, Phandle,
18};
19
20pub use fdt_raw::MemoryReservation;
21
22#[derive(Clone)]
28pub struct Fdt {
29 pub boot_cpuid_phys: u32,
31 pub memory_reservations: Vec<MemoryReservation>,
33 nodes: BTreeMap<NodeId, Node>,
35 parent_map: BTreeMap<NodeId, NodeId>,
37 root: NodeId,
39 next_id: NodeId,
41 phandle_cache: BTreeMap<Phandle, NodeId>,
43}
44
45impl Default for Fdt {
46 fn default() -> Self {
47 Self::new()
48 }
49}
50
51impl Fdt {
52 pub fn new() -> Self {
54 let mut nodes = BTreeMap::new();
55 let root_id: NodeId = 0;
56 nodes.insert(root_id, Node::new(""));
57 Self {
58 boot_cpuid_phys: 0,
59 memory_reservations: Vec::new(),
60 nodes,
61 parent_map: BTreeMap::new(),
62 root: root_id,
63 next_id: 1,
64 phandle_cache: BTreeMap::new(),
65 }
66 }
67
68 fn alloc_node(&mut self, node: Node) -> NodeId {
70 let id = self.next_id;
71 self.next_id += 1;
72 self.nodes.insert(id, node);
73 id
74 }
75
76 pub fn root_id(&self) -> NodeId {
78 self.root
79 }
80
81 pub fn parent_of(&self, id: NodeId) -> Option<NodeId> {
83 self.parent_map.get(&id).copied()
84 }
85
86 pub fn node(&self, id: NodeId) -> Option<&Node> {
88 self.nodes.get(&id)
89 }
90
91 pub fn node_mut(&mut self, id: NodeId) -> Option<&mut Node> {
93 self.nodes.get_mut(&id)
94 }
95
96 pub fn node_count(&self) -> usize {
98 self.nodes.len()
99 }
100
101 pub fn add_node(&mut self, parent: NodeId, node: Node) -> NodeId {
106 let name = node.name.clone();
107 let id = self.alloc_node(node);
108 self.parent_map.insert(id, parent);
109
110 if let Some(parent_node) = self.nodes.get_mut(&parent) {
111 parent_node.add_child(&name, id);
112 }
113
114 if let Some(phandle) = self.nodes.get(&id).and_then(|n| n.phandle()) {
116 self.phandle_cache.insert(phandle, id);
117 }
118
119 id
120 }
121
122 pub fn remove_node(&mut self, parent: NodeId, name: &str) -> Option<NodeId> {
127 let removed_id = {
128 let parent_node = self.nodes.get_mut(&parent)?;
129 parent_node.remove_child(name)?
130 };
131
132 self.rebuild_name_cache(parent);
134
135 self.remove_subtree(removed_id);
137
138 Some(removed_id)
139 }
140
141 fn remove_subtree(&mut self, id: NodeId) {
143 if let Some(node) = self.nodes.remove(&id) {
144 self.parent_map.remove(&id);
146 if let Some(phandle) = node.phandle() {
148 self.phandle_cache.remove(&phandle);
149 }
150 for child_id in node.children() {
152 self.remove_subtree(*child_id);
153 }
154 }
155 }
156
157 fn rebuild_name_cache(&mut self, id: NodeId) {
159 let names: Vec<(String, usize)> = {
160 let node = match self.nodes.get(&id) {
161 Some(n) => n,
162 None => return,
163 };
164 node.children()
165 .iter()
166 .enumerate()
167 .filter_map(|(idx, &child_id)| {
168 self.nodes.get(&child_id).map(|c| (c.name.clone(), idx))
169 })
170 .collect()
171 };
172 if let Some(node) = self.nodes.get_mut(&id) {
173 node.rebuild_name_cache_with_names(&names);
174 }
175 }
176
177 pub fn resolve_alias(&self, alias: &str) -> Option<&str> {
178 let root = self.nodes.get(&self.root)?;
179 let alias_node_id = root.get_child("aliases")?;
180 let alias_node = self.nodes.get(&alias_node_id)?;
181 let prop = alias_node.get_property(alias)?;
182 prop.as_str()
183 }
184
185 fn normalize_path(&self, path: &str) -> Option<String> {
187 if path.starts_with('/') {
188 Some(path.to_string())
189 } else {
190 self.resolve_alias(path).map(|s| s.to_string())
192 }
193 }
194
195 pub fn get_by_path_id(&self, path: &str) -> Option<NodeId> {
200 let normalized_path = self.normalize_path(path)?;
201 let normalized = normalized_path.trim_start_matches('/');
202 if normalized.is_empty() {
203 return Some(self.root);
204 }
205
206 let mut current = self.root;
207 for part in normalized.split('/') {
208 let node = self.nodes.get(¤t)?;
209 current = node.get_child(part)?;
210 }
211 Some(current)
212 }
213
214 pub fn get_by_phandle_id(&self, phandle: Phandle) -> Option<NodeId> {
216 self.phandle_cache.get(&phandle).copied()
217 }
218
219 pub fn path_of(&self, id: NodeId) -> String {
221 let mut parts: Vec<&str> = Vec::new();
222 let mut cur = id;
223 while let Some(node) = self.nodes.get(&cur) {
224 if cur == self.root {
225 break;
226 }
227 parts.push(&node.name);
228 match self.parent_map.get(&cur) {
229 Some(&p) => cur = p,
230 None => break,
231 }
232 }
233 parts.reverse();
234 if parts.is_empty() {
235 return String::from("/");
236 }
237 format!("/{}", parts.join("/"))
238 }
239
240 pub fn remove_by_path(&mut self, path: &str) -> Option<NodeId> {
244 let normalized = path.trim_start_matches('/');
245 if normalized.is_empty() {
246 return None; }
248
249 let parts: Vec<&str> = normalized.split('/').collect();
250 let child_name = *parts.last()?;
251
252 let parent_path = &parts[..parts.len() - 1];
254 let mut parent_id = self.root;
255 for &part in parent_path {
256 let node = self.nodes.get(&parent_id)?;
257 parent_id = node.get_child(part)?;
258 }
259
260 self.remove_node(parent_id, child_name)
261 }
262
263 pub fn iter_node_ids(&self) -> NodeDfsIter<'_> {
265 NodeDfsIter {
266 fdt: self,
267 stack: vec![self.root],
268 }
269 }
270
271 pub fn from_bytes(data: &[u8]) -> Result<Self, FdtError> {
273 let raw_fdt = fdt_raw::Fdt::from_bytes(data)?;
274 Self::from_raw(&raw_fdt)
275 }
276
277 pub unsafe fn from_ptr(ptr: *mut u8) -> Result<Self, FdtError> {
284 let raw_fdt = unsafe { fdt_raw::Fdt::from_ptr(ptr)? };
285 Self::from_raw(&raw_fdt)
286 }
287
288 fn from_raw(raw_fdt: &fdt_raw::Fdt) -> Result<Self, FdtError> {
290 let header = raw_fdt.header();
291
292 let mut fdt = Fdt {
293 boot_cpuid_phys: header.boot_cpuid_phys,
294 memory_reservations: raw_fdt.memory_reservations().collect(),
295 nodes: BTreeMap::new(),
296 parent_map: BTreeMap::new(),
297 root: 0,
298 next_id: 0,
299 phandle_cache: BTreeMap::new(),
300 };
301
302 let mut id_stack: Vec<(NodeId, usize)> = Vec::new();
306
307 for raw_node in raw_fdt.all_nodes() {
308 let level = raw_node.level();
309 let node = Node::from(&raw_node);
310 let node_name = node.name.clone();
311
312 let node_id = fdt.alloc_node(node);
314
315 if let Some(phandle) = fdt.nodes.get(&node_id).and_then(|n| n.phandle()) {
317 fdt.phandle_cache.insert(phandle, node_id);
318 }
319
320 while let Some(&(_, stack_level)) = id_stack.last() {
322 if stack_level >= level {
323 id_stack.pop();
324 } else {
325 break;
326 }
327 }
328
329 if let Some(&(parent_id, _)) = id_stack.last() {
330 fdt.parent_map.insert(node_id, parent_id);
332 if let Some(parent) = fdt.nodes.get_mut(&parent_id) {
334 parent.add_child(&node_name, node_id);
335 }
336 } else {
337 fdt.root = node_id;
339 }
340
341 id_stack.push((node_id, level));
342 }
343
344 Ok(fdt)
345 }
346
347 pub fn get_by_path(&self, path: &str) -> Option<NodeType<'_>> {
349 let id = self.get_by_path_id(path)?;
350 Some(NodeView::new(self, id).classify())
351 }
352
353 pub fn get_by_path_mut(&mut self, path: &str) -> Option<NodeTypeMut<'_>> {
355 let id = self.get_by_path_id(path)?;
356 Some(NodeView::new(self, id).classify_mut())
357 }
358
359 pub fn get_by_phandle(&self, phandle: crate::Phandle) -> Option<NodeType<'_>> {
361 let id = self.get_by_phandle_id(phandle)?;
362 Some(NodeView::new(self, id).classify())
363 }
364
365 pub fn get_by_phandle_mut(&mut self, phandle: crate::Phandle) -> Option<NodeTypeMut<'_>> {
367 let id = self.get_by_phandle_id(phandle)?;
368 Some(NodeView::new(self, id).classify_mut())
369 }
370
371 fn iter_raw_nodes(&self) -> impl Iterator<Item = NodeView<'_>> {
373 self.iter_node_ids().map(move |id| NodeView::new(self, id))
374 }
375
376 pub fn all_nodes(&self) -> impl Iterator<Item = NodeType<'_>> {
378 self.iter_raw_nodes().map(|v| v.classify())
379 }
380
381 pub fn root_mut(&mut self) -> NodeTypeMut<'_> {
382 self.view_typed_mut(self.root).unwrap()
383 }
384
385 pub fn find_compatible(&self, compatible: &[&str]) -> Vec<NodeType<'_>> {
387 let mut results = Vec::new();
388 for node_ref in self.all_nodes() {
389 let compatibles = node_ref.as_node().compatibles();
390 let mut found = false;
391
392 for comp in compatibles {
393 if compatible.contains(&comp) {
394 results.push(node_ref);
395 found = true;
396 break;
397 }
398 }
399
400 if found {
401 continue;
402 }
403 }
404 results
405 }
406
407 pub fn encode(&self) -> FdtData {
409 FdtEncoder::new(self).encode()
410 }
411}
412
413pub struct NodeDfsIter<'a> {
415 fdt: &'a Fdt,
416 stack: Vec<NodeId>,
417}
418
419impl<'a> Iterator for NodeDfsIter<'a> {
420 type Item = NodeId;
421
422 fn next(&mut self) -> Option<Self::Item> {
423 let id = self.stack.pop()?;
424 if let Some(node) = self.fdt.nodes.get(&id) {
425 for &child_id in node.children().iter().rev() {
427 self.stack.push(child_id);
428 }
429 }
430 Some(id)
431 }
432}