Skip to content

Commit ed2b6de

Browse files
committed
wip: add dump of entire live FDT from the board
1 parent b9506a1 commit ed2b6de

File tree

2 files changed

+137
-6
lines changed

2 files changed

+137
-6
lines changed

machine/src/device_tree.rs

Lines changed: 132 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
#![allow(dead_code)]
22

33
use {
4-
crate::println,
5-
core::alloc::Layout,
4+
crate::{print, println},
5+
core::{alloc::Layout, mem::size_of, ptr::read_unaligned},
66
fdt_rs::{
7-
base::DevTree,
8-
error::DevTreeError,
7+
base::{iters::StringPropIter, DevTree},
8+
error::{DevTreeError, Result as DevTreeResult},
99
index::{DevTreeIndex, DevTreeIndexNode, DevTreeIndexProp},
10-
prelude::PropReader,
10+
prelude::{PropReader, *},
1111
},
1212
shrinkwraprs::Shrinkwrap,
1313
};
@@ -54,7 +54,7 @@ pub fn get_size_cells<'a, 'i: 'a, 'dt: 'i>(node: DevTreeIndexNode<'a, 'i, 'dt>)
5454
/// This requires allocation of a single buffer, which is done at boot time via bump allocator.
5555
/// This means we can only parse the tree after bump allocator is initialized.
5656
#[derive(Shrinkwrap)]
57-
pub struct DeviceTree<'a>(DevTreeIndex<'a, 'a>);
57+
pub struct DeviceTree<'a>(pub DevTreeIndex<'a, 'a>);
5858

5959
impl<'a> DeviceTree<'a> {
6060
pub fn layout(tree: DevTree<'a>) -> Result<Layout, DevTreeError> {
@@ -149,6 +149,7 @@ impl<'a, 'i: 'a, 'dt: 'i> Iterator for PayloadPairsIter<'a, 'i, 'dt> {
149149
/// Return a pair of (address, size) values on each iteration.
150150
type Item = (u64, u64);
151151
fn next(&mut self) -> Option<Self::Item> {
152+
println!("Offset {}, total {}", self.offset, self.total);
152153
if self.offset >= self.total {
153154
return None;
154155
}
@@ -354,3 +355,128 @@ mod tests {
354355
assert_eq!(path.move_next(), false);
355356
}
356357
}
358+
359+
//=================================================================================================
360+
// Dump the entire FDT
361+
// From https://github.com/rs-embedded/fdtdump/blob/master/src/main.rs
362+
//=================================================================================================
363+
364+
fn are_printable_strings(mut prop_iter: StringPropIter) -> bool {
365+
loop {
366+
match prop_iter.next() {
367+
Ok(Some(s_ref)) => {
368+
if s_ref.is_empty() {
369+
return false;
370+
}
371+
}
372+
Ok(None) => return true,
373+
Err(_) => return false,
374+
}
375+
}
376+
}
377+
378+
pub struct FdtDumper {
379+
pub indent: usize,
380+
}
381+
382+
impl<'i, 'dt> FdtDumper {
383+
fn push_indent(&mut self) {
384+
for _ in 0..self.indent {
385+
print!(" ");
386+
}
387+
}
388+
389+
fn dump_node_name(&mut self, name: &str) {
390+
self.push_indent();
391+
print!("{}", name);
392+
println!(" {{");
393+
}
394+
395+
fn dump_node(&mut self, node: &DevTreeIndexNode) -> DevTreeResult<()> {
396+
let mut name = node.name()?;
397+
if name.is_empty() {
398+
name = "/";
399+
} else {
400+
name = node.name()?;
401+
}
402+
self.dump_node_name(name);
403+
Ok(())
404+
}
405+
406+
fn dump_property(&mut self, prop: DevTreeIndexProp) -> DevTreeResult<()> {
407+
self.push_indent();
408+
409+
print!("{}", prop.name()?);
410+
411+
if prop.length() == 0 {
412+
println!(";");
413+
return Ok(());
414+
}
415+
print!(" = ");
416+
417+
// Unsafe Ok - we're reinterpreting the data as expected.
418+
unsafe {
419+
// First try to parse as an array of strings
420+
if are_printable_strings(prop.iter_str()) {
421+
let mut iter = prop.iter_str();
422+
while let Some(s) = iter.next()? {
423+
print!("\"{}\", ", s);
424+
}
425+
// let _ = self.dump.pop();
426+
// let _ = self.dump.pop();
427+
} else if prop.propbuf().len() % size_of::<u32>() == 0 {
428+
print!("<");
429+
for val in prop.propbuf().chunks_exact(size_of::<u32>()) {
430+
// We use read_unaligned
431+
#[allow(clippy::cast_ptr_alignment)]
432+
let v = read_unaligned::<u32>(val.as_ptr() as *const u32);
433+
let v = u32::from_be(v);
434+
print!("{:#010x} ", v);
435+
}
436+
// let _ = self.dump.pop(); // Pop off extra space
437+
print!(">");
438+
} else {
439+
print!("[");
440+
for val in prop.propbuf() {
441+
print!("{:02x} ", val);
442+
}
443+
// let _ = self.dump.pop(); // Pop off extra space
444+
print!("]");
445+
}
446+
}
447+
448+
println!(";");
449+
Ok(())
450+
}
451+
452+
pub fn dump_level(&mut self, node: &DevTreeIndexNode) -> DevTreeResult<()> {
453+
self.dump_node(node)?;
454+
self.indent += 1;
455+
for prop in node.props() {
456+
let _ = self.dump_property(prop)?;
457+
}
458+
for child in node.children() {
459+
let _ = self.dump_level(&child)?;
460+
}
461+
self.indent -= 1;
462+
self.push_indent();
463+
println!("}};");
464+
Ok(())
465+
}
466+
467+
pub fn dump_metadata(&mut self, index: &DevTreeIndex) {
468+
let fdt = index.fdt();
469+
println!("// magic:\t\t{:#x}", fdt.magic());
470+
let s = fdt.totalsize();
471+
println!("// totalsize:\t\t{:#x} ({})", s, s);
472+
println!("// off_dt_struct:\t{:#x}", fdt.off_dt_struct());
473+
println!("// off_dt_strings:\t{:#x}", fdt.off_dt_strings());
474+
println!("// off_mem_rsvmap:\t{:#x}", fdt.off_mem_rsvmap());
475+
println!("// version:\t\t{:}", fdt.version());
476+
println!("// last_comp_version:\t{:}", fdt.last_comp_version());
477+
println!("// boot_cpuid_phys:\t{:#x}", fdt.boot_cpuid_phys());
478+
println!("// size_dt_strings:\t{:#x}", fdt.size_dt_strings());
479+
println!("// size_dt_struct:\t{:#x}", fdt.size_dt_struct());
480+
println!();
481+
}
482+
}

nucleus/src/main.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@ pub fn kmain(dtb: u32) -> ! {
155155
println!("Running on {}", board_name);
156156
}
157157

158+
let mut dumper = machine::device_tree::FdtDumper { indent: 0 };
159+
160+
dumper.dump_metadata(&device_tree.0);
161+
dumper.dump_level(&device_tree.root()).expect("oof");
162+
158163
// To init memory allocation we need to parse memory regions from dtb and add the regions to
159164
// available memory regions list. Then initial BootRegionAllocator will get memory from these
160165
// regions and record their usage into some OTHER structures, removing these allocations from

0 commit comments

Comments
 (0)