1use core::{iter, ptr::NonNull};
2
3use crate::{
4 chosen::Chosen, error::*, memory::Memory, meta::MetaData, node::Node, read::FdtReader,
5 FdtHeader, MemoryRegion, Phandle, Token,
6};
7
8#[derive(Clone)]
10pub struct Fdt<'a> {
11 pub(crate) header: FdtHeader,
12 pub(crate) data: &'a [u8],
13}
14
15impl<'a> Fdt<'a> {
16 pub fn from_bytes(data: &'a [u8]) -> FdtResult<'a, Self> {
18 let header = FdtHeader::from_bytes(data)?;
19
20 header.valid_magic()?;
21
22 Ok(Self { header, data })
23 }
24
25 pub fn from_ptr(ptr: NonNull<u8>) -> FdtResult<'a, Self> {
27 let tmp_header =
28 unsafe { core::slice::from_raw_parts(ptr.as_ptr(), core::mem::size_of::<FdtHeader>()) };
29 let real_size = FdtHeader::from_bytes(tmp_header)?.totalsize.get() as usize;
30
31 Self::from_bytes(unsafe { core::slice::from_raw_parts(ptr.as_ptr(), real_size) })
32 }
33
34 fn reader(&'a self, offset: usize) -> FdtReader<'a> {
35 FdtReader::new(&self.data[offset..])
36 }
37
38 pub fn total_size(&self) -> usize {
39 self.header.totalsize.get() as _
40 }
41
42 pub fn version(&self) -> usize {
43 self.header.version.get() as _
44 }
45
46 pub fn boot_cpuid_phys(&self) -> u32 {
49 self.header.boot_cpuid_phys.get()
50 }
51
52 pub fn memory_reservation_block(&self) -> impl Iterator<Item = MemoryRegion> + '_ {
56 let mut reader = self.reader(self.header.off_mem_rsvmap.get() as _);
57 iter::from_fn(move || match reader.reserved_memory() {
58 Some(region) => {
59 if region.address == 0 && region.size == 0 {
60 None
61 } else {
62 Some(region.into())
63 }
64 }
65 None => None,
66 })
67 }
68
69 pub fn reserved_memory(&'a self) -> impl Iterator<Item = Node<'a>> + 'a {
73 self.find_nodes("/reserved-memory")
74 }
75
76 pub(crate) fn get_str(&'a self, offset: usize) -> FdtResult<'a, &'a str> {
77 let string_bytes = &self.data[self.header.strings_range()];
78 let reader = FdtReader::new(&string_bytes[offset..]);
79 reader.peek_str()
80 }
81
82 pub fn all_nodes(&'a self) -> impl Iterator<Item = Node<'a>> {
83 self.new_fdt_itr()
84 }
85
86 fn new_fdt_itr(&'a self) -> FdtIter<'a> {
87 let struct_bytes = &self.data[self.header.struct_range()];
88 let reader = FdtReader::new(struct_bytes);
89 FdtIter {
90 fdt: self,
91 current_level: 0,
92 reader,
93 stack: Default::default(),
94 node_reader: None,
95 node_name: "",
96 }
97 }
98
99 pub fn chosen(&'a self) -> Option<Chosen<'a>> {
100 self.find_nodes("/chosen").next().map(Chosen::new)
101 }
102
103 pub fn get_node_by_phandle(&'a self, phandle: Phandle) -> Option<Node<'a>> {
104 self.all_nodes()
105 .find(|x| match x.phandle() {
106 Some(p) => p.eq(&phandle),
107 None => false,
108 })
109 .clone()
110 }
111
112 pub fn get_node_by_name(&'a self, name: &str) -> Option<Node<'a>> {
113 self.all_nodes().find(|x| x.name().eq(name)).clone()
114 }
115
116 pub fn find_compatible(&'a self, with: &'a [&'a str]) -> impl Iterator<Item = Node<'a>> + 'a {
117 let mut all = self.all_nodes();
118
119 iter::from_fn(move || loop {
120 let node = all.next()?;
121 let caps = node.compatibles();
122 for cap in caps {
123 for want in with {
124 if cap.eq(*want) {
125 return Some(node);
126 }
127 }
128 }
129 })
130 }
131
132 pub fn find_nodes(&'a self, path: &'a str) -> impl Iterator<Item = Node<'a>> + 'a {
134 let path = if path.starts_with("/") {
135 path
136 } else {
137 self.find_aliase(path).expect("aliase not found")
138 };
139
140 IterFindNode::new(self.new_fdt_itr(), path)
141 }
142
143 pub fn find_aliase(&'a self, name: &str) -> Option<&'a str> {
144 let aliases = self.find_nodes("/aliases").next()?;
145 for prop in aliases.propertys() {
146 if prop.name.eq(name) {
147 return Some(prop.str());
148 }
149 }
150 None
151 }
152
153 pub fn memory(&'a self) -> impl Iterator<Item = Memory<'a>> + 'a {
154 self.find_nodes("/memory").map(Memory::new)
155 }
156}
157
158pub struct FdtIter<'a> {
159 fdt: &'a Fdt<'a>,
160 current_level: usize,
161 reader: FdtReader<'a>,
162 stack: [MetaData<'a>; 12],
163 node_reader: Option<FdtReader<'a>>,
164 node_name: &'a str,
165}
166
167impl<'a> FdtIter<'a> {
168 fn get_meta_parent(&self) -> MetaData<'a> {
169 let mut meta = MetaData::default();
170 let level = match self.level_parent_index() {
171 Some(l) => l,
172 None => return MetaData::default(),
173 } + 1;
174 macro_rules! get_field {
175 ($cell:ident) => {{
176 let mut size = None;
177 for i in (0..level).rev() {
178 if let Some(cell_size) = &self.stack[i].$cell {
179 size = Some(cell_size.clone());
180 break;
181 }
182 }
183 meta.$cell = size;
184 }};
185 }
186
187 get_field!(address_cells);
188 get_field!(size_cells);
189 get_field!(clock_cells);
190 get_field!(interrupt_cells);
191 get_field!(gpio_cells);
192 get_field!(dma_cells);
193 get_field!(cooling_cells);
194 get_field!(range);
195 get_field!(interrupt_parent);
196
197 meta
198 }
199 fn level_current_index(&self) -> usize {
200 self.current_level - 1
201 }
202 fn level_parent_index(&self) -> Option<usize> {
203 if self.level_current_index() > 0 {
204 Some(self.level_current_index() - 1)
205 } else {
206 None
207 }
208 }
209
210 fn handle_node_begin(&mut self) {
211 self.current_level += 1;
212 let i = self.level_current_index();
213 self.stack[i] = MetaData::default();
214 self.node_name = self.reader.take_unit_name().unwrap();
215 self.node_reader = Some(self.reader.clone());
216 }
217
218 fn finish_node(&mut self) -> Option<Node<'a>> {
219 let reader = self.node_reader.take()?;
220 let level = self.current_level;
221 let meta = self.stack[self.level_current_index()].clone();
222 let meta_parent = self.get_meta_parent();
223
224 let mut node = Node::new(self.fdt, level, self.node_name, reader, meta_parent, meta);
225 let ranges = node.node_ranges();
226 self.stack[self.level_current_index()].range = ranges.clone();
227 let ph = node.node_interrupt_parent();
228 self.stack[self.level_current_index()].interrupt_parent = ph;
229
230 node.meta = self.stack[self.level_current_index()].clone();
231
232 Some(node)
233 }
234}
235
236impl<'a> Iterator for FdtIter<'a> {
237 type Item = Node<'a>;
238
239 fn next(&mut self) -> Option<Self::Item> {
240 loop {
241 let token = self.reader.take_token()?;
242
243 match token {
244 Token::BeginNode => {
245 let node = self.finish_node();
246 self.handle_node_begin();
247 if node.is_some() {
248 return node;
249 }
250 }
251 Token::EndNode => {
252 let node = self.finish_node();
253 self.current_level -= 1;
254 if node.is_some() {
255 return node;
256 }
257 }
258 Token::Prop => {
259 let prop = self.reader.take_prop(self.fdt)?;
260 let index = self.level_current_index();
261 macro_rules! update_cell {
262 ($cell:ident) => {
263 self.stack[index].$cell = Some(prop.u32() as _)
264 };
265 }
266 match prop.name {
267 "#address-cells" => update_cell!(address_cells),
268 "#size-cells" => update_cell!(size_cells),
269 "#clock-cells" => update_cell!(clock_cells),
270 "#interrupt-cells" => update_cell!(interrupt_cells),
271 "#gpio-cells" => update_cell!(gpio_cells),
272 "#dma-cells" => update_cell!(dma_cells),
273 "#cooling-cells" => update_cell!(cooling_cells),
274 _ => {}
275 }
276 }
277 Token::End => {
278 return self.finish_node();
279 }
280 _ => {}
281 }
282 }
283 }
284}
285
286struct IterFindNode<'a> {
287 itr: FdtIter<'a>,
288 want: &'a str,
289 want_itr: usize,
290 is_path_last: bool,
291}
292
293impl<'a> IterFindNode<'a> {
294 fn new(itr: FdtIter<'a>, want: &'a str) -> Self {
295 IterFindNode {
296 itr,
297 want,
298 want_itr: 0,
299 is_path_last: false,
300 }
301 }
302}
303
304impl<'a> Iterator for IterFindNode<'a> {
305 type Item = Node<'a>;
306
307 fn next(&mut self) -> Option<Self::Item> {
308 let mut out = None;
309 loop {
310 let mut parts = self.want.split("/").filter(|o| !o.is_empty());
311 let mut want_part = "/";
312 for _ in 0..self.want_itr {
313 if let Some(part) = parts.next() {
314 want_part = part;
315 } else {
316 self.is_path_last = true;
317 if let Some(out) = out {
318 return Some(out);
319 }
320 }
321 }
322 let node = self.itr.next()?;
323
324 let eq = if want_part.contains("@") {
325 node.name.eq(want_part)
326 } else {
327 let name = node.name.split("@").next().unwrap();
328 name.eq(want_part)
329 };
330 if eq {
331 self.want_itr += 1;
332 out = Some(node);
333 }
334 }
335 }
336}