fdt_parser/
node.rs

1use core::iter;
2
3use crate::{
4    clocks::{ClockRef, ClocksIter},
5    error::{FdtError, FdtResult},
6    interrupt::InterruptController,
7    meta::MetaData,
8    pci::Pci,
9    property::Property,
10    read::{FdtReader, U32Array2D},
11    Fdt, FdtRangeSilce, FdtReg, Phandle, Status, Token,
12};
13
14#[derive(Clone)]
15pub struct Node<'a> {
16    pub level: usize,
17    pub name: &'a str,
18    pub(crate) fdt: Fdt<'a>,
19    /// 父节点的元数据
20    pub(crate) meta_parents: MetaData<'a>,
21    /// 当前节点的元数据
22    pub(crate) meta: MetaData<'a>,
23    body: FdtReader<'a>,
24}
25
26impl<'a> Node<'a> {
27    pub(crate) fn new(
28        fdt: &Fdt<'a>,
29        level: usize,
30        name: &'a str,
31        reader: FdtReader<'a>,
32        meta_parents: MetaData<'a>,
33        meta: MetaData<'a>,
34    ) -> Self {
35        Self {
36            fdt: fdt.clone(),
37            level,
38            body: reader,
39            name,
40            meta,
41            meta_parents,
42        }
43    }
44
45    pub fn name(&self) -> &'a str {
46        self.name
47    }
48
49    pub fn propertys(&self) -> impl Iterator<Item = Property<'a>> + '_ {
50        let reader = self.body.clone();
51        PropIter {
52            reader,
53            fdt: self.fdt.clone(),
54        }
55    }
56
57    pub fn find_property(&self, name: &str) -> Option<Property<'a>> {
58        self.propertys().find(|x| x.name.eq(name))
59    }
60
61    pub fn reg(&self) -> Option<impl Iterator<Item = FdtReg> + 'a> {
62        let mut iter = self.propertys();
63        let reg = iter.find(|x| x.name.eq("reg"))?;
64
65        Some(RegIter {
66            size_cell: self.meta_parents.size_cells.unwrap(),
67            address_cell: self.meta_parents.address_cells.unwrap(),
68            prop: reg,
69            ranges: self.meta_parents.range.clone(),
70        })
71    }
72
73    pub(crate) fn node_ranges(&self) -> Option<FdtRangeSilce<'a>> {
74        let prop = self.find_property("ranges")?;
75
76        Some(FdtRangeSilce::new(
77            self.meta.address_cells.unwrap(),
78            self.meta_parents.address_cells.unwrap(),
79            self.meta.size_cells.unwrap(),
80            prop.data.clone(),
81        ))
82    }
83
84    pub(crate) fn node_interrupt_parent(&self) -> Option<Phandle> {
85        let prop = self.find_property("interrupt-parent")?;
86        Some(prop.u32().into())
87    }
88
89    /// Find [InterruptController] from current node or its parent
90    pub fn interrupt_parent(&self) -> Option<InterruptController<'a>> {
91        let phandle = if let Some(p) = self.meta.interrupt_parent {
92            Some(p)
93        } else {
94            self.meta_parents.interrupt_parent
95        }?;
96
97        self.fdt
98            .get_node_by_phandle(phandle)
99            .map(|node| InterruptController { node })
100    }
101
102    pub fn compatible(&self) -> Option<impl Iterator<Item = FdtResult<'a, &'a str>> + 'a> {
103        let prop = self.find_property("compatible")?;
104        let mut value = prop.data.clone();
105
106        Some(iter::from_fn(move || {
107            let s = value.take_str();
108            match s {
109                Ok(s) => {
110                    if s.is_empty() {
111                        None
112                    } else {
113                        Some(Ok(s))
114                    }
115                }
116                Err(e) => match e {
117                    FdtError::Eof => None,
118                    _ => Some(Err(e)),
119                },
120            }
121        }))
122    }
123
124    /// Get all compatible ignoring errors
125    pub fn compatibles(&self) -> impl Iterator<Item = &'a str> + 'a {
126        let mut cap_raw = self.compatible();
127
128        iter::from_fn(move || {
129            if let Some(caps) = &mut cap_raw {
130                let cap = caps.next()?.ok()?;
131                Some(cap)
132            } else {
133                None
134            }
135        })
136    }
137
138    pub fn phandle(&self) -> Option<Phandle> {
139        let prop = self.find_property("phandle")?;
140        Some(prop.u32().into())
141    }
142
143    pub fn interrupts(&self) -> Option<impl Iterator<Item = impl Iterator<Item = u32> + 'a> + 'a> {
144        let prop = self.find_property("interrupts")?;
145        let cell_size = self.interrupt_parent()?.interrupt_cells();
146
147        Some(U32Array2D::new(prop.raw_value(), cell_size))
148    }
149
150    pub fn clocks(&'a self) -> impl Iterator<Item = ClockRef<'a>> + 'a {
151        ClocksIter::new(self)
152    }
153
154    pub fn clock_frequency(&self) -> Option<u32> {
155        let prop = self.find_property("clock-frequency")?;
156        Some(prop.u32())
157    }
158
159    pub fn into_pci(self) -> Option<Pci<'a>> {
160        if self.name.contains("pci") {
161            Some(Pci { node: self })
162        } else {
163            None
164        }
165    }
166
167    pub fn status(&self) -> Option<Status> {
168        let prop = self.find_property("status")?;
169        let s = prop.str();
170
171        if s.contains("disabled") {
172            return Some(Status::Disabled);
173        }
174
175        if s.contains("okay") {
176            return Some(Status::Okay);
177        }
178
179        None
180    }
181
182    pub fn fdt(&self) -> Fdt<'a> {
183        self.fdt.clone()
184    }
185}
186
187struct RegIter<'a> {
188    size_cell: u8,
189    address_cell: u8,
190    prop: Property<'a>,
191    ranges: Option<FdtRangeSilce<'a>>,
192}
193impl Iterator for RegIter<'_> {
194    type Item = FdtReg;
195
196    fn next(&mut self) -> Option<Self::Item> {
197        let child_bus_address = self.prop.data.take_by_cell_size(self.address_cell)?;
198
199        let mut address = child_bus_address;
200
201        if let Some(ranges) = &self.ranges {
202            for one in ranges.iter() {
203                let range_child_bus_address = one.child_bus_address().as_u64();
204                let range_parent_bus_address = one.parent_bus_address().as_u64();
205
206                if child_bus_address >= range_child_bus_address
207                    && child_bus_address < range_child_bus_address + one.size
208                {
209                    address =
210                        child_bus_address - range_child_bus_address + range_parent_bus_address;
211                    break;
212                }
213            }
214        }
215
216        let size = if self.size_cell > 0 {
217            Some(self.prop.data.take_by_cell_size(self.size_cell)? as usize)
218        } else {
219            None
220        };
221        Some(FdtReg {
222            address,
223            child_bus_address,
224            size,
225        })
226    }
227}
228
229struct PropIter<'a> {
230    fdt: Fdt<'a>,
231    reader: FdtReader<'a>,
232}
233
234impl<'a> Iterator for PropIter<'a> {
235    type Item = Property<'a>;
236
237    fn next(&mut self) -> Option<Self::Item> {
238        loop {
239            match self.reader.take_token() {
240                Some(token) => match token {
241                    Token::Prop => break,
242                    Token::Nop => {}
243                    _ => return None,
244                },
245                None => return None,
246            }
247        }
248        self.reader.take_prop(&self.fdt)
249    }
250}
251
252// #[derive(Clone)]
253// pub struct MemoryRegionSilce<'a> {
254//     address_cell: u8,
255//     size_cell: u8,
256//     reader: FdtReader<'a>,
257// }
258
259// impl<'a> MemoryRegionSilce<'a> {
260//     pub fn iter(&self) -> impl Iterator<Item = FdtRange> + 'a {
261//         MemoryRegionIter {
262//             address_cell: self.address_cell,
263//             size_cell: self.size_cell,
264//             reader: self.reader.clone(),
265//         }
266//     }
267// }
268
269// struct MemoryRegionIter<'a> {
270//     address_cell: u8,
271//     size_cell: u8,
272//     reader: FdtReader<'a>,
273// }
274
275// impl<'a> Iterator for MemoryRegionIter<'a> {
276//     type Item = FdtRange;
277
278//     fn next(&mut self) -> Option<Self::Item> {
279//         todo!()
280//     }
281// }