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 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: &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 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 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