fdt_parser/cache/node/
mod.rs

1use core::{fmt::Debug, ops::Deref};
2
3use super::Fdt;
4use crate::{
5    base::{self, RegIter},
6    data::{Raw, U32Iter2D},
7    property::PropIter,
8    FdtError, FdtRangeSilce, FdtReg, Phandle, Property, Status,
9};
10
11use alloc::{
12    string::{String, ToString},
13    vec::Vec,
14};
15
16mod chosen;
17mod clock;
18mod interrupt_controller;
19mod memory;
20mod pci;
21
22pub use chosen::*;
23pub use clock::*;
24pub use interrupt_controller::*;
25pub use memory::*;
26pub use pci::*;
27
28#[derive(Debug, Clone)]
29pub enum Node {
30    General(NodeBase),
31    Chosen(Chosen),
32    Memory(Memory),
33    InterruptController(InterruptController),
34    Pci(Pci),
35}
36
37impl Node {
38    pub(super) fn new(fdt: &Fdt, meta: &NodeMeta) -> Self {
39        let base = NodeBase {
40            fdt: fdt.clone(),
41            meta: meta.clone(),
42        };
43
44        // 根据节点类型创建具体类型
45        match meta.name.as_str() {
46            "chosen" => Self::Chosen(Chosen::new(base)),
47            name if name.starts_with("memory@") => Self::Memory(Memory::new(base)),
48            _ => {
49                // 检查是否是PCI节点
50                let pci = Pci::new(base.clone());
51                if pci.is_pci_host_bridge() {
52                    Self::Pci(pci)
53                } else if base.is_interrupt_controller() {
54                    Self::InterruptController(InterruptController::new(base))
55                } else {
56                    Self::General(base)
57                }
58            }
59        }
60    }
61}
62
63impl Deref for Node {
64    type Target = NodeBase;
65
66    fn deref(&self) -> &Self::Target {
67        match self {
68            Node::General(n) => n,
69            Node::Chosen(n) => n,
70            Node::Memory(n) => n,
71            Node::InterruptController(n) => n,
72            Node::Pci(n) => n,
73        }
74    }
75}
76
77#[derive(Clone)]
78pub struct NodeBase {
79    fdt: Fdt,
80    meta: NodeMeta,
81}
82
83impl NodeBase {
84    fn raw<'a>(&'a self) -> Raw<'a> {
85        self.fdt.raw().begin_at(self.meta.pos)
86    }
87
88    pub fn level(&self) -> usize {
89        self.meta.level
90    }
91
92    pub fn name(&self) -> &str {
93        &self.meta.name
94    }
95
96    pub fn full_path(&self) -> &str {
97        &self.meta.full_path
98    }
99
100    pub fn parent(&self) -> Option<Node> {
101        let parent_path = self.meta.parent.as_ref()?.path.as_str();
102        let parent_meta = self.fdt.inner.get_node_by_path(parent_path)?;
103        Some(Node::new(&self.fdt, &parent_meta))
104    }
105
106    pub fn properties<'a>(&'a self) -> Vec<Property<'a>> {
107        let reader = self.raw().buffer();
108        PropIter::new(self.fdt.fdt_base(), reader)
109            .flatten()
110            .collect()
111    }
112
113    pub fn find_property<'a>(&'a self, name: impl AsRef<str>) -> Option<Property<'a>> {
114        self.properties()
115            .into_iter()
116            .find(|prop| prop.name == name.as_ref())
117    }
118
119    /// Get compatible strings for this node (placeholder implementation)
120    pub fn compatibles(&self) -> Vec<String> {
121        self.find_property("compatible")
122            .map(|p| {
123                p.str_list()
124                    .filter(|s| !s.is_empty())
125                    .map(|s| s.into())
126                    .collect()
127            })
128            .unwrap_or_default()
129    }
130
131    /// Get the status of this node
132    pub fn status(&self) -> Option<Status> {
133        self.find_property("status")
134            .and_then(|prop| prop.str().ok())
135            .and_then(|s| {
136                if s.contains("disabled") {
137                    Some(Status::Disabled)
138                } else if s.contains("okay") {
139                    Some(Status::Okay)
140                } else {
141                    None
142                }
143            })
144    }
145
146    pub fn address_cells(&self) -> u8 {
147        self.find_property("#address-cells")
148            .and_then(|p| p.u32().ok())
149            .map(|v| v as u8)
150            .or_else(|| {
151                self.meta
152                    .parent
153                    .as_ref()
154                    .and_then(|info| info.address_cells)
155            })
156            .unwrap_or(2)
157    }
158
159    fn is_interrupt_controller(&self) -> bool {
160        self.name().starts_with("interrupt-controller")
161            || self.find_property("interrupt-controller").is_some()
162            || self.find_property("#interrupt-controller").is_some()
163    }
164
165    /// Get register information for this node
166    pub fn reg(&self) -> Result<Vec<FdtReg>, FdtError> {
167        let prop = self.find_property("reg").ok_or(FdtError::NotFound)?;
168
169        // Get parent info from ParentInfo structure
170        let parent_info = self
171            .meta
172            .parent
173            .as_ref()
174            .ok_or(FdtError::NodeNotFound("parent"))?;
175
176        // reg parsing uses the immediate parent's cells
177        let address_cell = parent_info.address_cells.unwrap_or(2);
178        let size_cell = parent_info.size_cells.unwrap_or(1);
179
180        let parent = self.parent().ok_or(FdtError::NodeNotFound("parent"))?;
181        let ranges = parent.ranges();
182        let iter = RegIter {
183            size_cell,
184            address_cell,
185            buff: prop.data.buffer(),
186            ranges,
187        };
188
189        Ok(iter.collect())
190    }
191
192    pub fn ranges(&self) -> Option<FdtRangeSilce<'_>> {
193        let p = self.find_property("ranges")?;
194        let parent_info = self.meta.parent.as_ref();
195
196        let address_cell = self
197            .find_property("#address-cells")
198            .and_then(|prop| prop.u32().ok())
199            .map(|v| v as u8)
200            .or_else(|| parent_info.and_then(|info| info.address_cells))
201            .unwrap_or(2);
202
203        let size_cell = self
204            .find_property("#size-cells")
205            .and_then(|prop| prop.u32().ok())
206            .map(|v| v as u8)
207            .or_else(|| parent_info.and_then(|info| info.size_cells))
208            .unwrap_or(1);
209
210        let address_cell_parent = parent_info.and_then(|info| info.address_cells).unwrap_or(2);
211
212        Some(FdtRangeSilce::new(
213            address_cell,
214            address_cell_parent,
215            size_cell,
216            &p.data,
217        ))
218    }
219
220    pub fn interrupt_parent_phandle(&self) -> Option<Phandle> {
221        self.meta.interrupt_parent
222    }
223
224    pub fn interrupt_parent(&self) -> Option<InterruptController> {
225        let phandle = self.interrupt_parent_phandle()?;
226        let irq = self.fdt.get_node_by_phandle(phandle)?;
227        let Node::InterruptController(i) = irq else {
228            return None;
229        };
230        Some(i)
231    }
232
233    pub fn interrupts(&self) -> Result<Vec<Vec<u32>>, FdtError> {
234        let res = self
235            .find_property("interrupts")
236            .ok_or(FdtError::PropertyNotFound("interrupts"))?;
237        let parent = self
238            .interrupt_parent()
239            .ok_or(FdtError::PropertyNotFound("interrupt-parent"))?;
240        let cells = parent.interrupt_cells()?;
241        let mut iter = U32Iter2D::new(&res.data, cells as _);
242        let mut out = Vec::new();
243        while let Some(entry) = iter.next() {
244            out.push(entry.collect());
245        }
246        Ok(out)
247    }
248
249    /// Get the clocks used by this node following the Devicetree clock binding
250    pub fn clocks(&self) -> Result<Vec<ClockInfo>, FdtError> {
251        let mut clocks = Vec::new();
252        let Some(prop) = self.find_property("clocks") else {
253            return Ok(clocks);
254        };
255
256        let mut data = prop.data.buffer();
257        let clock_names: Vec<String> = self
258            .find_property("clock-names")
259            .map(|p| p.str_list().map(|s| s.to_string()).collect())
260            .unwrap_or_else(Vec::new);
261
262        let mut index = 0usize;
263        while !data.remain().as_ref().is_empty() {
264            let phandle_raw = data.take_u32()?;
265            let phandle = Phandle::from(phandle_raw);
266
267            let provider = self
268                .fdt
269                .get_node_by_phandle(phandle)
270                .ok_or(FdtError::NodeNotFound("clock"))?;
271
272            let provider_node = provider.deref().clone();
273            let clock_cells = provider_node
274                .find_property("#clock-cells")
275                .and_then(|p| p.u32().ok())
276                .unwrap_or(0);
277            let select = if clock_cells > 0 {
278                data.take_by_cell_size(clock_cells as _)
279                    .ok_or(FdtError::BufferTooSmall { pos: data.pos() })?
280            } else {
281                0
282            };
283
284            let provider = ClockType::new(provider_node);
285            let provider_output_name = provider.output_name(select);
286            let name = clock_names.get(index).cloned();
287
288            clocks.push(ClockInfo {
289                name,
290                provider_output_name,
291                provider,
292                phandle,
293                select,
294            });
295
296            index += 1;
297        }
298
299        Ok(clocks)
300    }
301}
302
303impl Debug for NodeBase {
304    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
305        let mut st = f.debug_struct("NodeBase");
306        // st.field("name", &self.name());
307        st.finish()
308    }
309}
310
311#[derive(Clone)]
312pub(super) struct NodeMeta {
313    name: String,
314    full_path: String,
315    pos: usize,
316    pub level: usize,
317    interrupt_parent: Option<Phandle>,
318    parent: Option<ParentInfo>,
319}
320
321impl NodeMeta {
322    pub fn new(node: &base::Node<'_>, full_path: String, parent: Option<&NodeMeta>) -> Self {
323        NodeMeta {
324            full_path,
325            name: node.name().into(),
326            pos: node.raw.pos(),
327            level: node.level(),
328            interrupt_parent: node.get_interrupt_parent_phandle(),
329            parent: node.parent.as_ref().map(|p| ParentInfo {
330                path: parent.map(|n| n.full_path.clone()).unwrap_or_default(),
331                address_cells: p.address_cells,
332                size_cells: p.size_cells,
333            }),
334        }
335    }
336}
337
338#[derive(Clone)]
339struct ParentInfo {
340    path: String,
341    address_cells: Option<u8>,
342    size_cells: Option<u8>,
343}