1use core::iter;
2
3use super::node::*;
4use crate::{
5 data::{Buffer, Raw},
6 FdtError, FdtRangeSilce, Header, MemoryRegion, Phandle, Property, Token,
7};
8
9#[derive(Clone)]
10pub struct Fdt<'a> {
11 header: Header,
12 pub(crate) raw: Raw<'a>,
13}
14
15impl<'a> Fdt<'a> {
16 pub fn from_bytes(data: &'a [u8]) -> Result<Fdt<'a>, FdtError> {
18 let header = Header::from_bytes(data)?;
19 if data.len() < header.totalsize as usize {
20 return Err(FdtError::BufferTooSmall {
21 pos: header.totalsize as usize,
22 });
23 }
24 let buffer = Raw::new(data);
25 Ok(Fdt {
26 header,
27 raw: buffer,
28 })
29 }
30
31 pub unsafe fn from_ptr(ptr: *mut u8) -> Result<Fdt<'a>, FdtError> {
39 let header = unsafe { Header::from_ptr(ptr)? };
40
41 let raw = Raw::new(core::slice::from_raw_parts(ptr, header.totalsize as _));
42
43 Ok(Fdt { header, raw })
44 }
45
46 pub fn as_slice(&self) -> &'a [u8] {
47 self.raw.value()
48 }
49
50 pub fn header(&self) -> &Header {
52 &self.header
53 }
54
55 pub fn total_size(&self) -> usize {
56 self.header.totalsize as usize
57 }
58
59 pub fn boot_cpuid_phys(&self) -> u32 {
62 self.header.boot_cpuid_phys
63 }
64
65 pub fn raw(&self) -> &'a [u8] {
67 self.raw.value()
68 }
69
70 pub fn version(&self) -> u32 {
72 self.header.version
73 }
74
75 pub fn memory_reservation_blocks(&self) -> impl Iterator<Item = MemoryRegion> + 'a {
76 let mut buffer = self
77 .raw
78 .begin_at(self.header.off_mem_rsvmap as usize)
79 .buffer();
80
81 core::iter::from_fn(move || {
82 let address = buffer.take_u64().ok()?;
83 let size = buffer.take_u64().ok()?;
84
85 if address == 0 && size == 0 {
86 return None;
87 }
88
89 Some(MemoryRegion {
90 address: address as usize as _,
91 size: size as _,
92 })
93 })
94 }
95
96 pub(crate) fn get_str(&self, offset: usize) -> Result<&'a str, FdtError> {
97 let start = self.header.off_dt_strings as usize + offset;
98 let mut buffer = self.raw.begin_at(start).buffer();
99 buffer.take_str()
100 }
101
102 pub fn all_nodes(&self) -> NodeIter<'a, 16> {
103 NodeIter::new(self.clone())
104 }
105
106 pub fn find_nodes(
108 &self,
109 path: &'a str,
110 ) -> impl Iterator<Item = Result<Node<'a>, FdtError>> + 'a {
111 let path = if path.starts_with("/") {
112 path
113 } else {
114 self.find_aliase(path).unwrap()
115 };
116
117 IterFindNode::new(self.all_nodes(), path)
118 }
119
120 pub fn find_aliase(&self, name: &str) -> Result<&'a str, FdtError> {
121 let aliases = self
122 .find_nodes("/aliases")
123 .next()
124 .ok_or(FdtError::NoAlias)??;
125 for prop in aliases.properties() {
126 let prop = prop?;
127 if prop.name.eq(name) {
128 return prop.str();
129 }
130 }
131 Err(FdtError::NoAlias)
132 }
133
134 pub fn find_compatible<'b, 'c: 'b>(
135 &'b self,
136 with: &'c [&'c str],
137 ) -> impl Iterator<Item = Result<Node<'a>, FdtError>> + 'b {
138 let mut iter = self.all_nodes();
139 let mut has_err = false;
140 iter::from_fn(move || loop {
141 if has_err {
142 return None;
143 }
144 let node = iter.next()?;
145 let node = match node {
146 Ok(n) => n,
147 Err(e) => {
148 return {
149 has_err = true;
150 Some(Err(e))
151 }
152 }
153 };
154 match node.compatibles() {
155 Ok(mut comp) => {
156 if comp.any(|c| with.iter().any(|w| w.eq(&c))) {
157 return Some(Ok(node));
158 }
159 }
160 Err(FdtError::NotFound) => {}
161 Err(e) => {
162 return {
163 has_err = true;
164 Some(Err(e))
165 }
166 }
167 }
168 })
169 }
170
171 pub fn chosen(&self) -> Result<Chosen<'a>, FdtError> {
172 let node = self
173 .find_nodes("/chosen")
174 .next()
175 .ok_or(FdtError::NotFound)??;
176 let node = match node {
177 Node::Chosen(c) => c,
178 _ => return Err(FdtError::NodeNotFound("chosen")),
179 };
180 Ok(node)
181 }
182
183 pub fn get_node_by_phandle(&self, phandle: Phandle) -> Result<Node<'a>, FdtError> {
184 for node in self.all_nodes() {
185 let node = node?;
186 match node.phandle() {
187 Ok(p) if p == phandle => return Ok(node),
188 Ok(_) => {}
189 Err(FdtError::NotFound) => {}
190 Err(e) => return Err(e),
191 }
192 }
193 Err(FdtError::NotFound)
194 }
195
196 pub fn get_node_by_name(&'a self, name: &str) -> Result<Node<'a>, FdtError> {
197 for node in self.all_nodes() {
198 let node = node?;
199 if node.name() == name {
200 return Ok(node);
201 }
202 }
203 Err(FdtError::NotFound)
204 }
205
206 pub fn memory(&'a self) -> impl Iterator<Item = Result<Memory<'a>, FdtError>> + 'a {
207 self.find_nodes("/memory@").map(|o| {
208 o.map(|o| match o {
209 Node::Memory(m) => m,
210 _ => unreachable!(),
211 })
212 })
213 }
214
215 fn reserved_memory_node(&self) -> Result<Node<'a>, FdtError> {
217 let node = self
218 .find_nodes("/reserved-memory")
219 .next()
220 .ok_or(FdtError::NotFound)?;
221 node
222 }
223
224 pub fn reserved_memory_regions(&self) -> Result<ReservedMemoryRegionsIter<'a>, FdtError> {
226 match self.reserved_memory_node() {
227 Ok(reserved_memory_node) => Ok(ReservedMemoryRegionsIter::new(reserved_memory_node)),
228 Err(FdtError::NotFound) => Ok(ReservedMemoryRegionsIter::empty()),
229 Err(e) => Err(e),
230 }
231 }
232}
233
234pub struct ReservedMemoryRegionsIter<'a> {
236 child_iter: Option<NodeChildIter<'a>>,
237}
238
239impl<'a> ReservedMemoryRegionsIter<'a> {
240 fn new(reserved_memory_node: Node<'a>) -> Self {
242 ReservedMemoryRegionsIter {
243 child_iter: Some(reserved_memory_node.children()),
244 }
245 }
246
247 fn empty() -> Self {
249 ReservedMemoryRegionsIter { child_iter: None }
250 }
251
252 pub fn find_by_name(self, name: &str) -> Result<Node<'a>, FdtError> {
254 for region_result in self {
255 let region = region_result?;
256 if region.name() == name {
257 return Ok(region);
258 }
259 }
260 Err(FdtError::NotFound)
261 }
262
263 pub fn find_by_compatible(
265 self,
266 compatible: &str,
267 ) -> Result<alloc::vec::Vec<Node<'a>>, FdtError> {
268 let mut matching_regions = alloc::vec::Vec::new();
269
270 for region_result in self {
271 let region = region_result?;
272 match region.compatibles() {
273 Ok(mut compatibles) => {
274 if compatibles.any(|comp| comp == compatible) {
275 matching_regions.push(region);
276 }
277 }
278 Err(FdtError::NotFound) => {}
279 Err(e) => return Err(e),
280 }
281 }
282
283 Ok(matching_regions)
284 }
285}
286
287impl<'a> Iterator for ReservedMemoryRegionsIter<'a> {
288 type Item = Result<Node<'a>, FdtError>;
289
290 fn next(&mut self) -> Option<Self::Item> {
291 match &mut self.child_iter {
292 Some(iter) => iter.next(),
293 None => None,
294 }
295 }
296}
297
298#[derive(Clone)]
300struct NodeStackFrame<'a> {
301 level: usize,
302 node: NodeBase<'a>,
303 address_cells: u8,
304 size_cells: u8,
305 ranges: Option<FdtRangeSilce<'a>>,
306 interrupt_parent: Option<Phandle>,
307}
308
309pub struct NodeIter<'a, const MAX_DEPTH: usize = 16> {
310 buffer: Buffer<'a>,
311 fdt: Fdt<'a>,
312 level: isize,
313 has_err: bool,
314 node_stack: heapless::Vec<NodeStackFrame<'a>, MAX_DEPTH>,
316}
317
318impl<'a, const MAX_DEPTH: usize> NodeIter<'a, MAX_DEPTH> {
319 pub fn new(fdt: Fdt<'a>) -> Self {
321 NodeIter {
322 buffer: fdt.raw.begin_at(fdt.header.off_dt_struct as usize).buffer(),
323 fdt,
324 level: -1,
325 has_err: false,
326 node_stack: heapless::Vec::new(),
327 }
328 }
329
330 fn current_parent(&self) -> Option<&NodeBase<'a>> {
332 self.node_stack.last().map(|frame| &frame.node)
333 }
334
335 fn current_interrupt_parent(&self) -> Option<Phandle> {
337 for frame in self.node_stack.iter().rev() {
339 if let Some(phandle) = frame.interrupt_parent {
340 return Some(phandle);
341 }
342 }
343 None
344 }
345
346 fn current_cells(&self) -> (u8, u8) {
348 self.node_stack
349 .last()
350 .map(|frame| (frame.address_cells, frame.size_cells))
351 .unwrap_or((2, 1))
352 }
353
354 fn push_node(&mut self, frame: NodeStackFrame<'a>) -> Result<(), FdtError> {
356 self.node_stack
357 .push(frame)
358 .map_err(|_| FdtError::BufferTooSmall {
359 pos: self.node_stack.len(),
360 })
361 }
362
363 fn pop_to_level(&mut self, target_level: isize) {
365 while let Some(frame) = self.node_stack.last() {
366 if frame.level as isize > target_level {
367 self.node_stack.pop();
368 } else {
369 break;
370 }
371 }
372 }
373
374 fn scan_node_properties(
376 &self,
377 ) -> Result<
378 (
379 Option<u8>,
380 Option<u8>,
381 Option<Phandle>,
382 Option<Property<'a>>,
383 ),
384 FdtError,
385 > {
386 let mut address_cells = None;
387 let mut size_cells = None;
388 let mut interrupt_parent = self.current_interrupt_parent();
389 let mut ranges = None;
390 let mut temp_buffer = self.buffer.clone();
391
392 loop {
394 match temp_buffer.take_token() {
395 Ok(Token::Prop) => {
396 let prop = temp_buffer.take_prop(&self.fdt)?;
397 match prop.name {
398 "#address-cells" => {
399 if let Ok(value) = prop.u32() {
400 address_cells = Some(value as u8);
401 }
402 }
403 "#size-cells" => {
404 if let Ok(value) = prop.u32() {
405 size_cells = Some(value as u8);
406 }
407 }
408 "interrupt-parent" => {
409 if let Ok(phandle_value) = prop.u32() {
410 interrupt_parent = Some(Phandle::from(phandle_value));
411 }
412 }
413 "ranges" => {
414 ranges = Some(prop);
415 }
416 _ => {}
417 }
418 }
419 Ok(Token::BeginNode) | Ok(Token::EndNode) | Ok(Token::End) => {
420 break;
421 }
422 _ => {
423 continue;
424 }
425 }
426 }
427
428 Ok((address_cells, size_cells, interrupt_parent, ranges))
429 }
430
431 fn handle_begin_node(&mut self) -> Result<Option<NodeBase<'a>>, FdtError> {
433 self.level += 1;
434
435 let name = self.buffer.take_str()?;
436 self.buffer.take_to_aligned();
437
438 let (address_cells, size_cells, interrupt_parent, ranges_prop) =
440 self.scan_node_properties()?;
441
442 let (default_addr, default_size) = self.current_cells();
444 let address_cells = address_cells.unwrap_or(default_addr);
445 let size_cells = size_cells.unwrap_or(default_size);
446 let interrupt_parent = interrupt_parent.or_else(|| self.current_interrupt_parent());
447
448 let parent = self.current_parent();
450 let (parent_address_cells, parent_size_cells, parent_ranges) = self
451 .node_stack
452 .last()
453 .map(|frame| {
454 (
455 Some(frame.address_cells),
456 Some(frame.size_cells),
457 frame.ranges.clone(),
458 )
459 })
460 .unwrap_or((None, None, None));
461
462 let ranges = if let Some(ranges_prop) = ranges_prop {
465 let parent_addr_cells = parent_address_cells.unwrap_or(2);
467
468 Some(FdtRangeSilce::new(
469 address_cells,
470 parent_addr_cells,
471 size_cells,
472 &ranges_prop.data,
473 ))
474 } else {
475 None
476 };
477
478 let node = NodeBase::new_with_parent_info(
480 name,
481 self.fdt.clone(),
482 self.buffer.remain(),
483 self.level as _,
484 parent,
485 parent_address_cells,
486 parent_size_cells,
487 parent_ranges,
488 interrupt_parent,
489 );
490 let frame = NodeStackFrame {
492 level: self.level as usize,
493 node: node.clone(),
494 address_cells,
495 size_cells,
496 ranges,
497 interrupt_parent,
498 };
499 self.push_node(frame)?;
500
501 Ok(Some(node))
503 }
504
505 fn handle_end_node(&mut self) -> Option<NodeBase<'a>> {
507 self.level -= 1;
508
509 self.pop_to_level(self.level);
511
512 None
514 }
515
516 fn handle_prop(&mut self) -> Result<(), FdtError> {
518 let _prop = self.buffer.take_prop(&self.fdt)?;
519 Ok(())
521 }
522
523 fn try_next(&mut self) -> Result<Option<NodeBase<'a>>, FdtError> {
524 loop {
525 let token = self.buffer.take_token()?;
526 match token {
527 Token::BeginNode => {
528 if let Some(finished_node) = self.handle_begin_node()? {
529 return Ok(Some(finished_node));
530 }
531 }
532 Token::EndNode => {
533 if let Some(node) = self.handle_end_node() {
534 return Ok(Some(node));
535 }
536 }
537 Token::Prop => {
538 self.handle_prop()?;
539 }
540 Token::End => {
541 return Ok(None);
542 }
543 _ => continue,
544 }
545 }
546 }
547}
548
549impl<'a, const MAX_DEPTH: usize> Iterator for NodeIter<'a, MAX_DEPTH> {
550 type Item = Result<Node<'a>, FdtError>;
551
552 fn next(&mut self) -> Option<Self::Item> {
553 if self.has_err {
554 return None;
555 }
556 match self.try_next() {
557 Ok(Some(node)) => Some(Ok(node.into())),
558 Ok(None) => None,
559 Err(e) => {
560 self.has_err = true;
561 Some(Err(e))
562 }
563 }
564 }
565}
566
567struct IterFindNode<'a, const MAX_DEPTH: usize = 16> {
568 itr: NodeIter<'a, MAX_DEPTH>,
569 want: &'a str,
570 want_itr: usize,
571 is_path_last: bool,
572 has_err: bool,
573}
574
575impl<'a, const MAX_DEPTH: usize> IterFindNode<'a, MAX_DEPTH> {
576 fn new(itr: NodeIter<'a, MAX_DEPTH>, want: &'a str) -> Self {
577 IterFindNode {
578 itr,
579 want,
580 want_itr: 0,
581 is_path_last: false,
582 has_err: false,
583 }
584 }
585}
586
587impl<'a, const MAX_DEPTH: usize> Iterator for IterFindNode<'a, MAX_DEPTH> {
588 type Item = Result<Node<'a>, FdtError>;
589
590 fn next(&mut self) -> Option<Self::Item> {
591 let mut out = None;
592 loop {
593 let mut parts = self.want.split("/").filter(|o| !o.is_empty());
594 let mut want_part = "/";
595 for _ in 0..self.want_itr {
596 if let Some(part) = parts.next() {
597 want_part = part;
598 } else {
599 self.is_path_last = true;
600 if let Some(out) = out {
601 return Some(out);
602 }
603 }
604 }
605 let node = match self.itr.next()? {
606 Ok(v) => v,
607 Err(e) => {
608 self.has_err = true;
609 return Some(Err(e));
610 }
611 };
612
613 let eq = if want_part.contains("@") {
614 node.name().eq(want_part)
615 } else {
616 let name = node.name().split("@").next().unwrap();
617 name.eq(want_part)
618 };
619 if eq {
620 self.want_itr += 1;
621 out = Some(Ok(node));
622 }
623 }
624 }
625}