fdt_parser/base/node/
mod.rs

1use core::ops::Deref;
2
3use super::Fdt;
4use crate::{
5    base::NodeIter,
6    data::{Buffer, Raw, U32Iter2D},
7    property::PropIter,
8    FdtError, FdtRangeSilce, FdtReg, Phandle, Property, Status,
9};
10
11mod chosen;
12mod interrupt_controller;
13mod memory;
14
15pub use chosen::*;
16pub use interrupt_controller::*;
17pub use memory::*;
18
19#[derive(Clone)]
20pub struct NodeBase<'a> {
21    name: &'a str,
22    pub(crate) fdt: Fdt<'a>,
23    pub level: usize,
24    pub(crate) raw: Raw<'a>,
25    pub(crate) parent: Option<ParentInfo<'a>>,
26    interrupt_parent: Option<Phandle>,
27}
28
29#[derive(Clone)]
30pub(crate) struct ParentInfo<'a> {
31    pub name: &'a str,
32    pub level: usize,
33    pub raw: Raw<'a>,
34    // Parent's #address-cells and #size-cells (for parsing reg)
35    pub address_cells: Option<u8>,
36    pub size_cells: Option<u8>,
37    // Parent's ranges for address translation
38    pub ranges: Option<FdtRangeSilce<'a>>,
39}
40
41impl<'a> NodeBase<'a> {
42    /// Create a new NodeBase with pre-calculated parent information from the stack
43    pub(crate) fn new_with_parent_info(
44        name: &'a str,
45        fdt: Fdt<'a>,
46        raw: Raw<'a>,
47        level: usize,
48        parent: Option<&NodeBase<'a>>,
49        parent_address_cells: Option<u8>,
50        parent_size_cells: Option<u8>,
51        parent_ranges: Option<FdtRangeSilce<'a>>,
52        interrupt_parent: Option<Phandle>,
53    ) -> Self {
54        let name = if name.is_empty() { "/" } else { name };
55        NodeBase {
56            name,
57            fdt,
58            level,
59            parent: parent.map(|p| ParentInfo {
60                name: p.name(),
61                level: p.level(),
62                raw: p.raw(),
63                address_cells: parent_address_cells,
64                size_cells: parent_size_cells,
65                ranges: parent_ranges,
66            }),
67            interrupt_parent,
68            raw,
69        }
70    }
71
72    pub fn parent_name(&self) -> Option<&'a str> {
73        self.parent_fast().map(|p| p.name())
74    }
75
76    pub fn parent(&self) -> Option<Node<'a>> {
77        let parent_info = self.parent.as_ref()?;
78        self.fdt
79            .all_nodes()
80            .flatten()
81            .find(|node| node.name() == parent_info.name && node.level() == parent_info.level)
82    }
83
84    pub(crate) fn parent_fast(&self) -> Option<NodeBase<'a>> {
85        self.parent.as_ref().map(|p| NodeBase {
86            name: p.name,
87            fdt: self.fdt.clone(),
88            level: p.level,
89            raw: p.raw,
90            parent: None,
91            interrupt_parent: None,
92        })
93    }
94
95    pub fn raw(&self) -> Raw<'a> {
96        self.raw
97    }
98
99    /// Get the name of this node
100    pub fn name(&self) -> &'a str {
101        self.name
102    }
103
104    /// Get the level/depth of this node in the device tree
105    pub fn level(&self) -> usize {
106        self.level
107    }
108
109    /// Get compatible strings for this node (placeholder implementation)
110    pub fn compatibles(&self) -> Result<impl Iterator<Item = &'a str> + 'a, FdtError> {
111        let prop = self.find_property("compatible")?;
112        Ok(prop.str_list())
113    }
114
115    pub fn compatibles_flatten(&self) -> Result<impl Iterator<Item = &'a str> + 'a, FdtError> {
116        self.compatibles()
117    }
118
119    pub fn reg(&self) -> Result<RegIter<'a>, FdtError> {
120        let prop = self.find_property("reg")?;
121
122        // Get parent info from ParentInfo structure
123        let parent_info = self
124            .parent
125            .as_ref()
126            .ok_or(FdtError::NodeNotFound("parent"))?;
127
128        // reg parsing uses the immediate parent's cells
129        let address_cell = parent_info.address_cells.unwrap_or(2);
130        let size_cell = parent_info.size_cells.unwrap_or(1);
131
132        // Use parent's pre-calculated ranges for address translation
133        let ranges = parent_info.ranges.clone();
134
135        Ok(RegIter {
136            size_cell,
137            address_cell,
138            buff: prop.data.buffer(),
139            ranges,
140        })
141    }
142
143    fn is_interrupt_controller(&self) -> bool {
144        self.find_property("#interrupt-controller").is_ok()
145    }
146
147    /// 检查这个节点是否是根节点
148    pub fn is_root(&self) -> bool {
149        self.level == 0
150    }
151
152    /// 获取节点的完整路径信息(仅限调试用途)
153    pub fn debug_info(&self) -> NodeDebugInfo<'a> {
154        NodeDebugInfo {
155            name: self.name(),
156            level: self.level,
157            pos: self.raw.pos(),
158        }
159    }
160
161    pub fn properties(&self) -> impl Iterator<Item = Result<Property<'a>, FdtError>> + '_ {
162        let reader = self.raw.buffer();
163        PropIter::new(self.fdt.clone(), reader)
164    }
165
166    pub fn find_property(&self, name: &str) -> Result<Property<'a>, FdtError> {
167        for prop in self.properties() {
168            let prop = prop?;
169            if prop.name.eq(name) {
170                return Ok(prop);
171            }
172        }
173        Err(FdtError::NotFound)
174    }
175
176    pub fn phandle(&self) -> Result<Phandle, FdtError> {
177        let prop = self.find_property("phandle")?;
178        Ok(prop.u32()?.into())
179    }
180
181    /// Find [InterruptController] from current node or its parent
182    pub fn interrupt_parent(&self) -> Result<InterruptController<'a>, FdtError> {
183        // First try to get the interrupt parent phandle from the node itself
184        let phandle = self.interrupt_parent.ok_or(FdtError::NotFound)?;
185
186        // Find the node with this phandle
187        let node = self.fdt.get_node_by_phandle(phandle)?;
188        match node {
189            Node::InterruptController(ic) => Ok(ic),
190            _ => Err(FdtError::NodeNotFound("interrupt-parent")),
191        }
192    }
193
194    /// Get the interrupt parent phandle for this node
195    pub fn get_interrupt_parent_phandle(&self) -> Option<Phandle> {
196        self.interrupt_parent
197    }
198
199    pub fn interrupts(
200        &self,
201    ) -> Result<impl Iterator<Item = impl Iterator<Item = u32> + 'a> + 'a, FdtError> {
202        let prop = self.find_property("interrupts")?;
203        let irq_parent = self.interrupt_parent()?;
204        let cell_size = irq_parent.interrupt_cells()?;
205        let iter = U32Iter2D::new(&prop.data, cell_size);
206
207        Ok(iter)
208    }
209
210    pub fn clock_frequency(&self) -> Result<u32, FdtError> {
211        let prop = self.find_property("clock-frequency")?;
212        Ok(prop.u32()?)
213    }
214
215    pub fn children(&self) -> NodeChildIter<'a> {
216        NodeChildIter {
217            fdt: self.fdt.clone(),
218            parent: self.clone(),
219            all_nodes: None,
220            target_level: 0,
221            found_parent: false,
222        }
223    }
224
225    pub fn status(&self) -> Result<Status, FdtError> {
226        let prop = self.find_property("status")?;
227        let s = prop.str()?;
228
229        if s.contains("disabled") {
230            return Ok(Status::Disabled);
231        }
232
233        if s.contains("okay") {
234            return Ok(Status::Okay);
235        }
236
237        Err(FdtError::NotFound)
238    }
239}
240
241/// 节点调试信息
242#[derive(Debug)]
243pub struct NodeDebugInfo<'a> {
244    pub name: &'a str,
245    pub level: usize,
246    pub pos: usize,
247}
248
249impl core::fmt::Debug for NodeBase<'_> {
250    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
251        f.debug_struct("Node").field("name", &self.name()).finish()
252    }
253}
254
255pub struct RegIter<'a> {
256    pub(crate) size_cell: u8,
257    pub(crate) address_cell: u8,
258    pub(crate) buff: Buffer<'a>,
259    pub(crate) ranges: Option<FdtRangeSilce<'a>>,
260}
261impl Iterator for RegIter<'_> {
262    type Item = FdtReg;
263
264    fn next(&mut self) -> Option<Self::Item> {
265        let child_bus_address = self.buff.take_by_cell_size(self.address_cell)?;
266
267        let mut address = child_bus_address;
268
269        if let Some(ranges) = &self.ranges {
270            for one in ranges.iter() {
271                let range_child_bus_address = one.child_bus_address().as_u64();
272                let range_parent_bus_address = one.parent_bus_address().as_u64();
273
274                if child_bus_address >= range_child_bus_address
275                    && child_bus_address < range_child_bus_address + one.size
276                {
277                    address =
278                        child_bus_address - range_child_bus_address + range_parent_bus_address;
279                    break;
280                }
281            }
282        }
283
284        let size = if self.size_cell > 0 {
285            Some(self.buff.take_by_cell_size(self.size_cell)? as usize)
286        } else {
287            None
288        };
289        Some(FdtReg {
290            address,
291            child_bus_address,
292            size,
293        })
294    }
295}
296
297#[derive(Debug, Clone)]
298pub enum Node<'a> {
299    General(NodeBase<'a>),
300    Chosen(Chosen<'a>),
301    Memory(Memory<'a>),
302    InterruptController(InterruptController<'a>),
303}
304
305impl<'a> Node<'a> {
306    pub fn node(&self) -> &NodeBase<'a> {
307        self.deref()
308    }
309}
310
311impl<'a> From<NodeBase<'a>> for Node<'a> {
312    fn from(node: NodeBase<'a>) -> Self {
313        if node.name() == "chosen" {
314            Node::Chosen(Chosen::new(node))
315        } else if node.name().starts_with("memory@") {
316            Node::Memory(Memory::new(node))
317        } else if node.is_interrupt_controller() {
318            Node::InterruptController(InterruptController::new(node))
319        } else {
320            Node::General(node)
321        }
322    }
323}
324
325impl<'a> Deref for Node<'a> {
326    type Target = NodeBase<'a>;
327
328    fn deref(&self) -> &Self::Target {
329        match self {
330            Node::General(n) => n,
331            Node::Chosen(n) => n,
332            Node::Memory(n) => n,
333            Node::InterruptController(n) => n,
334        }
335    }
336}
337
338pub struct NodeChildIter<'a> {
339    fdt: Fdt<'a>,
340    parent: NodeBase<'a>,
341    all_nodes: Option<NodeIter<'a, 16>>,
342    target_level: usize,
343    found_parent: bool,
344}
345
346impl<'a> Iterator for NodeChildIter<'a> {
347    type Item = Result<Node<'a>, FdtError>;
348
349    fn next(&mut self) -> Option<Self::Item> {
350        // 懒初始化节点迭代器
351        if self.all_nodes.is_none() {
352            self.all_nodes = Some(self.fdt.all_nodes());
353        }
354
355        let all_nodes = self.all_nodes.as_mut()?;
356
357        // 寻找子节点
358        loop {
359            let node = match all_nodes.next()? {
360                Ok(node) => node,
361                Err(e) => return Some(Err(e)),
362            };
363
364            // 首先找到父节点
365            if !self.found_parent {
366                if node.name() == self.parent.name() && node.level() == self.parent.level() {
367                    self.found_parent = true;
368                    self.target_level = node.level() + 1;
369                }
370                continue;
371            }
372
373            // 已经找到父节点,现在查找子节点
374            let current_level = node.level();
375
376            // 如果当前节点的级别等于目标级别,并且在树结构中紧跟在父节点之后,
377            // 那么它就是父节点的直接子节点
378            if current_level == self.target_level {
379                return Some(Ok(node));
380            }
381
382            // 如果当前节点的级别小于或等于父节点级别,说明我们已经离开了父节点的子树
383            if current_level <= self.parent.level() {
384                break;
385            }
386        }
387
388        None
389    }
390}
391
392impl<'a> NodeChildIter<'a> {
393    /// 创建一个新的子节点迭代器
394    pub fn new(fdt: Fdt<'a>, parent: NodeBase<'a>) -> Self {
395        NodeChildIter {
396            fdt,
397            parent,
398            all_nodes: None,
399            target_level: 0,
400            found_parent: false,
401        }
402    }
403
404    /// 获取父节点的引用
405    pub fn parent(&self) -> &NodeBase<'a> {
406        &self.parent
407    }
408
409    /// 收集所有子节点到一个 Vec 中
410    pub fn collect_children(self) -> Result<alloc::vec::Vec<Node<'a>>, FdtError> {
411        self.collect()
412    }
413
414    /// 查找具有特定名称的子节点
415    pub fn find_child_by_name(self, name: &str) -> Result<Node<'a>, FdtError> {
416        for child_result in self {
417            let child = child_result?;
418            if child.name() == name {
419                return Ok(child);
420            }
421        }
422        Err(FdtError::NotFound)
423    }
424
425    /// 查找具有特定兼容性字符串的子节点
426    pub fn find_child_by_compatible(self, compatible: &str) -> Result<Node<'a>, FdtError> {
427        for child_result in self {
428            let child = child_result?;
429            match child.compatibles() {
430                Ok(mut compatibles) => {
431                    if compatibles.any(|comp| comp == compatible) {
432                        return Ok(child);
433                    }
434                }
435                Err(FdtError::NotFound) => {}
436                Err(e) => return Err(e),
437            }
438        }
439        Err(FdtError::NotFound)
440    }
441}
442
443#[cfg(test)]
444mod tests {
445    use super::{Fdt, FdtError};
446
447    #[test]
448    fn test_node_child_iter_basic() {
449        let dtb_data = include_bytes!("../../../../dtb-file/src/dtb/bcm2711-rpi-4-b.dtb");
450        let fdt = Fdt::from_bytes(dtb_data).unwrap();
451
452        // 查找根节点
453        let root_node = fdt.find_nodes("/").next().unwrap().unwrap();
454
455        // 测试子节点迭代器
456        let children: Result<alloc::vec::Vec<_>, _> = root_node.children().collect();
457        let children = children.unwrap();
458
459        // 根节点应该有子节点
460        assert!(!children.is_empty(), "根节点应该有子节点");
461
462        // 所有子节点的 level 应该是 1
463        for child in &children {
464            assert_eq!(child.level(), 1, "根节点的直接子节点应该在 level 1");
465        }
466
467        // 检查是否包含一些预期的子节点
468        let child_names: alloc::vec::Vec<_> = children.iter().map(|c| c.name()).collect();
469        assert!(child_names.contains(&"chosen"), "应该包含 chosen 节点");
470        assert!(child_names.contains(&"memory@0"), "应该包含 memory@0 节点");
471    }
472
473    #[test]
474    fn test_find_child_by_name() {
475        let dtb_data = include_bytes!("../../../../dtb-file/src/dtb/bcm2711-rpi-4-b.dtb");
476        let fdt = Fdt::from_bytes(dtb_data).unwrap();
477
478        // 查找根节点
479        let root_node = fdt.find_nodes("/").next().unwrap().unwrap();
480
481        // 测试通过名称查找子节点
482        let memory_node = root_node.children().find_child_by_name("memory@0").unwrap();
483
484        assert_eq!(memory_node.name(), "memory@0");
485
486        // 测试查找不存在的节点
487        let nonexistent_err = root_node
488            .children()
489            .find_child_by_name("nonexistent")
490            .unwrap_err();
491        assert!(matches!(nonexistent_err, FdtError::NotFound));
492    }
493
494    #[test]
495    fn test_child_iter_empty() {
496        let dtb_data = include_bytes!("../../../../dtb-file/src/dtb/bcm2711-rpi-4-b.dtb");
497        let fdt = Fdt::from_bytes(dtb_data).unwrap();
498
499        // 查找一个叶子节点(没有子节点的节点)
500        let leaf_node = fdt.find_nodes("/chosen").next().unwrap().unwrap();
501
502        // 测试叶子节点的子节点迭代器
503        let children: Result<alloc::vec::Vec<_>, _> = leaf_node.children().collect();
504        let children = children.unwrap();
505
506        assert!(children.is_empty(), "叶子节点不应该有子节点");
507    }
508
509    #[test]
510    fn test_child_iter_multiple_levels() {
511        let dtb_data = include_bytes!("../../../../dtb-file/src/dtb/bcm2711-rpi-4-b.dtb");
512        let fdt = Fdt::from_bytes(dtb_data).unwrap();
513
514        // 查找 reserved-memory 节点,它应该有子节点
515        let reserved_memory = fdt
516            .all_nodes()
517            .find(|node| node.as_ref().is_ok_and(|n| n.name() == "reserved-memory"))
518            .unwrap()
519            .unwrap();
520
521        // 测试子节点迭代器
522        let children: Result<alloc::vec::Vec<_>, _> = reserved_memory.children().collect();
523        let children = children.unwrap();
524
525        // 确保子节点的 level 正确
526        for child in &children {
527            assert_eq!(
528                child.level(),
529                reserved_memory.level() + 1,
530                "子节点的 level 应该比父节点高 1"
531            );
532        }
533    }
534}