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: &'a Fdt<'a>,
19 pub(crate) meta_parents: MetaData<'a>,
21 pub(crate) meta: MetaData<'a>,
23 body: FdtReader<'a>,
24}
25
26impl<'a> Node<'a> {
27 pub(crate) fn new(
28 fdt: &'a 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,
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,
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 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 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
183struct RegIter<'a> {
184 size_cell: u8,
185 address_cell: u8,
186 prop: Property<'a>,
187 ranges: Option<FdtRangeSilce<'a>>,
188}
189impl Iterator for RegIter<'_> {
190 type Item = FdtReg;
191
192 fn next(&mut self) -> Option<Self::Item> {
193 let child_bus_address = self.prop.data.take_by_cell_size(self.address_cell)?;
194
195 let mut address = child_bus_address;
196
197 if let Some(ranges) = &self.ranges {
198 for one in ranges.iter() {
199 let range_child_bus_address = one.child_bus_address().as_u64();
200 let range_parent_bus_address = one.parent_bus_address().as_u64();
201
202 if child_bus_address >= range_child_bus_address
203 && child_bus_address < range_child_bus_address + one.size
204 {
205 address =
206 child_bus_address - range_child_bus_address + range_parent_bus_address;
207 break;
208 }
209 }
210 }
211
212 let size = if self.size_cell > 0 {
213 Some(self.prop.data.take_by_cell_size(self.size_cell)? as usize)
214 } else {
215 None
216 };
217 Some(FdtReg {
218 address,
219 child_bus_address,
220 size,
221 })
222 }
223}
224
225struct PropIter<'a> {
226 fdt: &'a Fdt<'a>,
227 reader: FdtReader<'a>,
228}
229
230impl<'a> Iterator for PropIter<'a> {
231 type Item = Property<'a>;
232
233 fn next(&mut self) -> Option<Self::Item> {
234 loop {
235 match self.reader.take_token() {
236 Some(token) => match token {
237 Token::Prop => break,
238 Token::Nop => {}
239 _ => return None,
240 },
241 None => return None,
242 }
243 }
244 self.reader.take_prop(self.fdt)
245 }
246}
247
248