Skip to content

Commit d88ed0b

Browse files
committed
feat: 添加 FDT 深度调试和显示功能,扩展节点格式化逻辑,增加相关测试用例
1 parent b100731 commit d88ed0b

10 files changed

Lines changed: 884 additions & 21 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//! FDT 深度调试演示
2+
//!
3+
//! 演示如何使用新的深度调试功能来遍历和打印设备树的所有节点
4+
5+
use fdt_edit::Fdt;
6+
use dtb_file::fdt_rpi_4b;
7+
8+
fn main() -> Result<(), Box<dyn std::error::Error>> {
9+
env_logger::init();
10+
11+
// 从 RPI 4B DTB 数据创建 FDT
12+
let raw_data = fdt_rpi_4b();
13+
let fdt = Fdt::from_bytes(&raw_data)?;
14+
15+
println!("=== FDT 基本调试信息 ===");
16+
// 基本调试格式(紧凑)
17+
println!("{:?}", fdt);
18+
println!();
19+
20+
println!("=== FDT 深度调试信息 ===");
21+
// 深度调试格式(遍历所有节点)
22+
println!("{:#?}", fdt);
23+
24+
Ok(())
25+
}

fdt-edit/src/fdt.rs

Lines changed: 136 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ pub use fdt_raw::MemoryReservation;
99
use fdt_raw::{FdtError, Phandle, Status};
1010

1111
use crate::{
12-
Node, NodeIter, NodeIterMut, NodeMut, NodeRef,
12+
Node, NodeIter, NodeIterMut, NodeMut, NodeRef, NodeKind, ClockType,
1313
encode::{FdtData, FdtEncoder},
1414
};
1515

1616
/// 可编辑的 FDT
17-
#[derive(Clone, Debug)]
17+
#[derive(Clone)]
1818
pub struct Fdt {
1919
/// 引导 CPU ID
2020
pub boot_cpuid_phys: u32,
@@ -392,9 +392,13 @@ impl Fdt {
392392
/// soc.add_child(Node::new("gpio@1000"));
393393
/// fdt.root.add_child(soc);
394394
///
395-
/// // 精确删除节点
396-
/// let removed = fdt.remove_node("soc/gpio@1000")?;
395+
/// // 精确删除节点(使用完整路径)
396+
/// let removed = fdt.remove_node("/soc/gpio@1000")?;
397397
/// assert!(removed.is_some());
398+
///
399+
/// // 尝试删除不存在的节点会返回错误
400+
/// let not_found = fdt.remove_node("/soc/nonexistent");
401+
/// assert!(not_found.is_err());
398402
/// # Ok::<(), fdt_raw::FdtError>(())
399403
/// ```
400404
pub fn remove_node(&mut self, path: &str) -> Result<Option<Node>, FdtError> {
@@ -480,3 +484,131 @@ impl Fdt {
480484
FdtEncoder::new(self).encode()
481485
}
482486
}
487+
488+
impl core::fmt::Display for Fdt {
489+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
490+
// 输出 DTS 头部信息
491+
writeln!(f, "/dts-v1/;")?;
492+
493+
// 输出内存保留块
494+
for reservation in &self.memory_reservations {
495+
writeln!(f, "/memreserve/ 0x{:x} 0x{:x};", reservation.address, reservation.size)?;
496+
}
497+
498+
// 输出根节点
499+
writeln!(f, "{}", self.root)
500+
}
501+
}
502+
503+
impl core::fmt::Debug for Fdt {
504+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
505+
if f.alternate() {
506+
// Deep debug format with node traversal
507+
self.fmt_debug_deep(f)
508+
} else {
509+
// Simple debug format (current behavior)
510+
f.debug_struct("Fdt")
511+
.field("boot_cpuid_phys", &self.boot_cpuid_phys)
512+
.field("memory_reservations_count", &self.memory_reservations.len())
513+
.field("root_node_name", &self.root.name)
514+
.field("total_nodes", &self.root.children.len())
515+
.field("phandle_cache_size", &self.phandle_cache.len())
516+
.finish()
517+
}
518+
}
519+
}
520+
521+
impl Fdt {
522+
fn fmt_debug_deep(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
523+
writeln!(f, "Fdt {{")?;
524+
writeln!(f, " boot_cpuid_phys: 0x{:x},", self.boot_cpuid_phys)?;
525+
writeln!(f, " memory_reservations_count: {},", self.memory_reservations.len())?;
526+
writeln!(f, " phandle_cache_size: {},", self.phandle_cache.len())?;
527+
writeln!(f, " nodes:")?;
528+
529+
// 遍历所有节点并打印带缩进的调试信息
530+
for (i, node) in self.all_nodes().enumerate() {
531+
self.fmt_node_debug(f, &node, 2, i)?;
532+
}
533+
534+
writeln!(f, "}}")
535+
}
536+
537+
fn fmt_node_debug(&self, f: &mut core::fmt::Formatter<'_>, node: &NodeRef, indent: usize, index: usize) -> core::fmt::Result {
538+
// 打印缩进
539+
for _ in 0..indent {
540+
write!(f, " ")?;
541+
}
542+
543+
// 打印节点索引和基本信息
544+
write!(f, "[{:03}] {}: ", index, node.name())?;
545+
546+
// 根据节点类型打印特定信息
547+
match node.as_ref() {
548+
NodeKind::Clock(clock) => {
549+
write!(f, "Clock")?;
550+
if let ClockType::Fixed(fixed) = &clock.kind {
551+
write!(f, " (Fixed, {}Hz)", fixed.frequency)?;
552+
} else {
553+
write!(f, " (Provider)")?;
554+
}
555+
if !clock.clock_output_names.is_empty() {
556+
write!(f, ", outputs: {:?}", clock.clock_output_names)?;
557+
}
558+
write!(f, ", cells={}", clock.clock_cells)?;
559+
}
560+
NodeKind::Pci(pci) => {
561+
write!(f, "PCI")?;
562+
if let Some(bus_range) = pci.bus_range() {
563+
write!(f, " (bus: {:?})", bus_range)?;
564+
}
565+
write!(f, ", interrupt-cells={}", pci.interrupt_cells())?;
566+
}
567+
NodeKind::InterruptController(ic) => {
568+
write!(f, "InterruptController")?;
569+
if let Some(cells) = ic.interrupt_cells() {
570+
write!(f, " (cells={})", cells)?;
571+
}
572+
let compatibles = ic.compatibles();
573+
if !compatibles.is_empty() {
574+
write!(f, ", compatible: {:?}", compatibles)?;
575+
}
576+
}
577+
NodeKind::Memory(mem) => {
578+
write!(f, "Memory")?;
579+
let regions = mem.regions();
580+
if !regions.is_empty() {
581+
write!(f, " ({} regions", regions.len())?;
582+
for (i, region) in regions.iter().take(2).enumerate() {
583+
write!(f, ", [{}]: 0x{:x}+0x{:x}",
584+
i, region.address, region.size)?;
585+
}
586+
if regions.len() > 2 {
587+
write!(f, ", ...")?;
588+
}
589+
write!(f, ")")?;
590+
}
591+
}
592+
NodeKind::Generic(_) => {
593+
write!(f, "Generic")?;
594+
}
595+
}
596+
597+
// 打印 phandle 信息
598+
if let Some(phandle) = node.phandle() {
599+
write!(f, ", phandle={}", phandle)?;
600+
}
601+
602+
// 打印地址和大小 cells 信息
603+
if let Some(address_cells) = node.address_cells() {
604+
write!(f, ", #address-cells={}", address_cells)?;
605+
}
606+
if let Some(size_cells) = node.size_cells() {
607+
write!(f, ", #size-cells={}", size_cells)?;
608+
}
609+
610+
writeln!(f)?;
611+
612+
Ok(())
613+
}
614+
}

fdt-edit/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ mod prop;
1212

1313
pub use ctx::Context;
1414
// pub use display::FmtLevel;
15-
// pub use encode::{FdtData, FdtEncoder, NodeEncode};
1615
pub use fdt::{Fdt, MemoryReservation};
17-
pub use node::*;
1816
pub use node::NodeKind;
17+
pub use node::*;
1918
pub use prop::{Phandle, Property, RangesEntry, RegInfo, Status};

fdt-edit/src/node/clock.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ impl ClockRef {
8484
}
8585

8686
/// 时钟提供者节点引用
87-
#[derive(Clone, Debug)]
87+
#[derive(Clone)]
8888
pub struct NodeRefClock<'a> {
8989
pub node: NodeRefGen<'a>,
9090
pub clock_output_names: Vec<String>,

0 commit comments

Comments
 (0)