1use core::fmt;
9
10use crate::{
11 Chosen, FdtError, Memory, MemoryReservation, Node, Property, VecRange, data, data::Bytes,
12 fmt_utils, header::Header, iter::FdtIter,
13};
14
15pub struct MemoryReservationIter<'a> {
21 data: &'a [u8],
22 offset: usize,
23}
24
25impl<'a> Iterator for MemoryReservationIter<'a> {
26 type Item = MemoryReservation;
27
28 fn next(&mut self) -> Option<Self::Item> {
29 if self.offset + data::MEM_RSV_ENTRY_SIZE > self.data.len() {
31 return None;
32 }
33
34 let address_bytes = &self.data[self.offset..self.offset + 8];
36 let address = u64::from_be_bytes(address_bytes.try_into().unwrap());
37 self.offset += 8;
38
39 let size_bytes = &self.data[self.offset..self.offset + 8];
41 let size = u64::from_be_bytes(size_bytes.try_into().unwrap());
42 self.offset += 8;
43
44 if address == 0 && size == 0 {
46 return None;
47 }
48
49 Some(MemoryReservation { address, size })
50 }
51}
52
53#[derive(Clone)]
62pub struct Fdt<'a> {
63 header: Header,
64 pub(crate) data: Bytes<'a>,
65}
66
67impl<'a> Fdt<'a> {
68 pub fn from_bytes(data: &'a [u8]) -> Result<Fdt<'a>, FdtError> {
78 let header = Header::from_bytes(data)?;
79 if data.len() < header.totalsize as usize {
80 return Err(FdtError::BufferTooSmall {
81 pos: header.totalsize as usize,
82 });
83 }
84 let buffer = Bytes::new(data);
85
86 Ok(Fdt {
87 header,
88 data: buffer,
89 })
90 }
91
92 pub unsafe fn from_ptr(ptr: *mut u8) -> Result<Fdt<'a>, FdtError> {
108 let header = unsafe { Header::from_ptr(ptr)? };
109
110 let data_slice = unsafe { core::slice::from_raw_parts(ptr, header.totalsize as _) };
111 let data = Bytes::new(data_slice);
112
113 Ok(Fdt { header, data })
114 }
115
116 pub fn header(&self) -> &Header {
118 &self.header
119 }
120
121 pub fn as_slice(&self) -> &'a [u8] {
123 self.data.as_slice()
124 }
125
126 pub fn all_nodes(&self) -> FdtIter<'a> {
128 FdtIter::new(self.clone())
129 }
130
131 pub fn find_by_path(&self, path: &str) -> Option<Node<'a>> {
143 let path = self.normalize_path(path)?;
144 let split = path.trim_matches('/').split('/');
145
146 let mut current_iter = self.all_nodes();
147 let mut found_node: Option<Node<'a>> = None;
148
149 for part in split {
150 let mut found = false;
151 for node in current_iter.by_ref() {
152 let node_name = node.name();
153 if node_name == part {
154 found = true;
155 found_node = Some(node);
156 break;
157 }
158 }
159 if !found {
160 return None;
161 }
162 }
163
164 found_node
165 }
166
167 pub fn find_children_by_path(&self, path: &str) -> ChildrenIter<'a> {
187 let Some(path) = self.normalize_path(path) else {
188 return ChildrenIter {
189 node_iter: self.all_nodes(),
190 child_level: 0,
191 done: true,
192 };
193 };
194 let split = path.trim_matches('/').split('/');
195
196 let mut iter = self.all_nodes();
197 let mut target_level = 0usize;
198
199 for part in split {
200 if part.is_empty() {
201 iter.next();
203 break;
204 }
205 let mut found = false;
206 for node in iter.by_ref() {
207 if node.name() == part {
208 found = true;
209 target_level = node.level();
210 break;
211 }
212 }
213 if !found {
214 return ChildrenIter {
215 node_iter: self.all_nodes(),
216 child_level: 0,
217 done: true,
218 };
219 }
220 }
221
222 let child_level = target_level + 1;
223 ChildrenIter {
224 node_iter: iter,
225 child_level,
226 done: false,
227 }
228 }
229
230 fn resolve_alias(&self, alias: &str) -> Option<&'a str> {
235 let aliases_node = self.find_by_path("/aliases")?;
236 aliases_node.find_property_str(alias)
237 }
238
239 fn normalize_path(&self, path: &'a str) -> Option<&'a str> {
244 if path.starts_with('/') {
245 Some(path)
246 } else {
247 self.resolve_alias(path)
248 }
249 }
250
251 pub fn translate_address(&self, path: &'a str, address: u64) -> u64 {
272 let mut addresses = [address];
273 self.translate_addresses(path, &mut addresses);
274 addresses[0]
275 }
276
277 pub fn translate_addresses(&self, path: &'a str, addresses: &mut [u64]) {
293 let path = match self.normalize_path(path) {
294 Some(p) => p,
295 None => return,
296 };
297
298 let path_parts = Self::split_path(path);
299 if path_parts.is_empty() {
300 return;
301 }
302
303 self.translate_addresses_with_parts(&path_parts, addresses);
304 }
305
306 fn split_path(path: &str) -> heapless::Vec<&str, 16> {
310 path.trim_matches('/')
311 .split('/')
312 .filter(|s| !s.is_empty())
313 .collect()
314 }
315
316 fn translate_addresses_with_parts(&self, path_parts: &[&str], addresses: &mut [u64]) {
321 for depth in (0..path_parts.len()).rev() {
324 let parent_parts = &path_parts[..depth];
325
326 if parent_parts.is_empty() {
327 break;
329 }
330
331 if let Some(parent_node) = self.find_node_by_parts(parent_parts) {
332 let ranges = match parent_node.ranges() {
333 Some(r) => r,
334 None => break, };
336
337 for addr in addresses.iter_mut() {
339 *addr = Self::apply_ranges_one(&ranges, *addr);
340 }
341 }
342 }
343 }
344
345 fn find_node_by_parts(&self, parts: &[&str]) -> Option<Node<'a>> {
347 let mut path = heapless::String::<256>::new();
348 path.push('/').ok();
349 for (i, part) in parts.iter().enumerate() {
350 if i > 0 {
351 path.push('/').ok();
352 }
353 path.push_str(part).ok();
354 }
355 self.find_by_path(path.as_str())
356 }
357
358 fn apply_ranges_one(ranges: &VecRange<'_>, address: u64) -> u64 {
363 for range in ranges.iter() {
364 if address >= range.child_address && address < range.child_address + range.length {
366 let offset = address - range.child_address;
367 return range.parent_address + offset;
368 }
369 }
370
371 address
373 }
374
375 pub fn memory_reservations(&self) -> MemoryReservationIter<'a> {
377 MemoryReservationIter {
378 data: self.data.as_slice(),
379 offset: self.header.off_mem_rsvmap as usize,
380 }
381 }
382
383 pub fn chosen(&self) -> Option<Chosen<'a>> {
385 for node in self.all_nodes() {
386 if let Node::Chosen(c) = node {
387 return Some(c);
388 }
389 }
390 None
391 }
392
393 pub fn memory(&self) -> impl Iterator<Item = Memory<'a>> + 'a {
395 self.all_nodes().filter_map(|node| {
396 if let Node::Memory(mem) = node {
397 Some(mem)
398 } else {
399 None
400 }
401 })
402 }
403
404 pub fn reserved_memory(&self) -> impl Iterator<Item = Node<'a>> + 'a {
406 ReservedMemoryIter {
407 node_iter: self.all_nodes(),
408 in_reserved_memory: false,
409 reserved_level: 0,
410 }
411 }
412}
413
414struct ReservedMemoryIter<'a> {
419 node_iter: FdtIter<'a>,
420 in_reserved_memory: bool,
421 reserved_level: usize,
422}
423
424impl<'a> Iterator for ReservedMemoryIter<'a> {
425 type Item = Node<'a>;
426
427 fn next(&mut self) -> Option<Self::Item> {
428 for node in self.node_iter.by_ref() {
429 if node.name() == "reserved-memory" {
430 self.in_reserved_memory = true;
431 self.reserved_level = node.level();
432 continue;
433 }
434
435 if self.in_reserved_memory {
436 if node.level() <= self.reserved_level {
437 self.in_reserved_memory = false;
439 return None;
440 } else {
441 return Some(node);
442 }
443 }
444 }
445 None
446 }
447}
448
449pub struct ChildrenIter<'a> {
455 node_iter: FdtIter<'a>,
456 child_level: usize,
457 done: bool,
458}
459
460impl<'a> Iterator for ChildrenIter<'a> {
461 type Item = Node<'a>;
462
463 fn next(&mut self) -> Option<Self::Item> {
464 if self.done {
465 return None;
466 }
467 for node in self.node_iter.by_ref() {
468 if node.level() == self.child_level {
469 return Some(node);
470 }
471 if node.level() < self.child_level {
472 self.done = true;
474 return None;
475 }
476 }
478 None
479 }
480}
481
482impl fmt::Display for Fdt<'_> {
483 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
484 writeln!(f, "/dts-v1/;")?;
485 writeln!(f)?;
486
487 let mut state = DisplayState::new();
488
489 for node in self.all_nodes() {
490 self.close_open_nodes(f, &mut state, node.level())?;
491 self.write_node(f, &node)?;
492 state.prev_level = node.level() + 1;
493 }
494
495 self.close_all_nodes(f, &mut state)
496 }
497}
498
499struct DisplayState {
501 prev_level: usize,
502}
503
504impl DisplayState {
505 fn new() -> Self {
506 Self { prev_level: 0 }
507 }
508}
509
510impl Fdt<'_> {
511 fn write_node(&self, f: &mut fmt::Formatter<'_>, node: &Node<'_>) -> fmt::Result {
513 fmt_utils::write_indent(f, node.level(), " ")?;
514 let name = Self::format_node_name(node.name());
515 writeln!(f, "{} {{", name)?;
516
517 for prop in node.properties() {
518 fmt_utils::write_indent(f, node.level() + 1, " ")?;
519 writeln!(f, "{};", prop)?;
520 }
521 Ok(())
522 }
523
524 fn format_node_name(name: &str) -> &str {
526 if name.is_empty() { "/" } else { name }
527 }
528
529 fn close_open_nodes(
531 &self,
532 f: &mut fmt::Formatter<'_>,
533 state: &mut DisplayState,
534 current_level: usize,
535 ) -> fmt::Result {
536 while state.prev_level > current_level {
537 state.prev_level -= 1;
538 fmt_utils::write_indent(f, state.prev_level, " ")?;
539 writeln!(f, "}};\n")?;
540 }
541 Ok(())
542 }
543
544 fn close_all_nodes(&self, f: &mut fmt::Formatter<'_>, state: &mut DisplayState) -> fmt::Result {
546 while state.prev_level > 0 {
547 state.prev_level -= 1;
548 fmt_utils::write_indent(f, state.prev_level, " ")?;
549 writeln!(f, "}};\n")?;
550 }
551 Ok(())
552 }
553}
554
555impl fmt::Debug for Fdt<'_> {
556 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
557 writeln!(f, "Fdt {{")?;
558 writeln!(f, "\theader: {:?}", self.header)?;
559 writeln!(f, "\tnodes:")?;
560
561 for node in self.all_nodes() {
562 self.debug_node(f, &node)?;
563 }
564
565 writeln!(f, "}}")
566 }
567}
568
569impl Fdt<'_> {
570 fn debug_node(&self, f: &mut fmt::Formatter<'_>, node: &Node<'_>) -> fmt::Result {
572 let level = node.level();
573 fmt_utils::write_indent(f, level + 2, "\t")?;
574
575 let name = Self::format_node_name(node.name());
576 writeln!(
577 f,
578 "[{}] address_cells={}, size_cells={}",
579 name, node.address_cells, node.size_cells
580 )?;
581
582 for prop in node.properties() {
583 self.debug_property(f, level, &prop)?;
584 }
585 Ok(())
586 }
587
588 fn debug_property(
590 &self,
591 f: &mut fmt::Formatter<'_>,
592 level: usize,
593 prop: &Property<'_>,
594 ) -> fmt::Result {
595 fmt_utils::write_indent(f, level + 3, "\t")?;
596
597 match () {
598 () if prop.as_address_cells().is_some() => {
599 writeln!(f, "#address-cells: {}", prop.as_address_cells().unwrap())?
600 }
601 () if prop.as_size_cells().is_some() => {
602 writeln!(f, "#size-cells: {}", prop.as_size_cells().unwrap())?
603 }
604 () if prop.as_interrupt_cells().is_some() => writeln!(
605 f,
606 "#interrupt-cells: {}",
607 prop.as_interrupt_cells().unwrap()
608 )?,
609 () if prop.as_status().is_some() => {
610 writeln!(f, "status: {:?}", prop.as_status().unwrap())?
611 }
612 () if prop.as_phandle().is_some() => {
613 writeln!(f, "phandle: {}", prop.as_phandle().unwrap())?
614 }
615 () if prop.is_empty() => writeln!(f, "{}", prop.name())?,
616 () if prop.as_str().is_some() => {
617 writeln!(f, "{}: \"{}\"", prop.name(), prop.as_str().unwrap())?
618 }
619 () if prop.len() == 4 => {
620 let v = u32::from_be_bytes(prop.data().as_slice().try_into().unwrap());
621 writeln!(f, "{}: {:#x}", prop.name(), v)?
622 }
623 () => writeln!(f, "{}: <{} bytes>", prop.name(), prop.len())?,
624 }
625 Ok(())
626 }
627}
628
629#[cfg(test)]
630mod tests {
631 use super::*;
632 use heapless::Vec;
633
634 #[test]
635 fn test_memory_reservation_iterator() {
636 let mut test_data = [0u8; data::MEM_RSV_ENTRY_SIZE * 2];
638
639 test_data[0..8].copy_from_slice(&0x80000000u64.to_be_bytes());
641 test_data[8..16].copy_from_slice(&0x10000000u64.to_be_bytes());
642 test_data[16..24].copy_from_slice(&0u64.to_be_bytes());
644 test_data[24..32].copy_from_slice(&0u64.to_be_bytes());
645
646 let iter = MemoryReservationIter {
647 data: &test_data,
648 offset: 0,
649 };
650
651 let reservations: Vec<MemoryReservation, 4> = iter.collect();
652 assert_eq!(reservations.len(), 1);
653 assert_eq!(reservations[0].address, 0x80000000);
654 assert_eq!(reservations[0].size, 0x10000000);
655 }
656
657 #[test]
658 fn test_empty_memory_reservation_iterator() {
659 let mut test_data = [0u8; data::MEM_RSV_ENTRY_SIZE];
661 test_data[0..8].copy_from_slice(&0u64.to_be_bytes());
662 test_data[8..16].copy_from_slice(&0u64.to_be_bytes());
663
664 let iter = MemoryReservationIter {
665 data: &test_data,
666 offset: 0,
667 };
668
669 let reservations: Vec<MemoryReservation, 4> = iter.collect();
670 assert_eq!(reservations.len(), 0);
671 }
672}