A pure-Rust, #![no_std] Flattened Device Tree (FDT) parser library and CLI tool based on the devicetree-specification-v0.4.
This project provides a comprehensive device tree blob (DTB) parser with both direct and cached parsing capabilities, specialized node types, and extensive test coverage. It is designed for embedded systems and kernel development where device tree parsing is required.
no_stdCompatible: Works in embedded environments without standard library- Dual Parsing Modes:
- Direct walk parser for memory-efficient parsing
- Cached indexing parser for fast repeated lookups
- Comprehensive PCI Support: Full PCI bridge implementation with interrupt mapping
- Complete Device Tree Support: Memory reservations, aliases, properties, and hierarchies
- Robust Error Handling: Detailed error types with context information
- Extensive Testing: Comprehensive test coverage across all components
- Memory Efficient: Optimized for embedded systems with limited resources
Add to your Cargo.toml:
[dependencies]
fdt-parser = "0.5.0"# Convert a DTB file to DTS format
cargo run -p dtb-tool -- --input <dtb_file> --output <dts_file>
# Example:
cargo run -p dtb-tool -- --input bcm2711-rpi-4-b.dtb --output rpi4.dtsuse fdt_parser::Fdt;
// Parse a device tree from bytes
let fdt = Fdt::from_bytes(&dtb_data)?;
// Access the root node
let root = fdt.root();
// Find nodes by path
let chosen = fdt.find_node("/chosen")?;
// Find nodes by compatible string
let pci_nodes = fdt.find_compatible(&["pci-host-ecam-generic"]);
// Access properties
let model = root.find_property("model")?.str()?;
let reg = root.reg()?;
// Access raw slice data
let raw_data = fdt.as_slice();use fdt_parser::cache::node::{Node, PciSpace};
// Find PCI host bridge
let pci_nodes = fdt.find_compatible(&["pci-host-ecam-generic"]);
let pci_node = pci_nodes.first().unwrap();
if let Node::Pci(pci) = pci_node {
// Get PCI address ranges
for range in pci.ranges().unwrap() {
match range.space {
PciSpace::IO => println!("IO space: 0x{:x}-0x{:x}",
range.cpu_address,
range.cpu_address + range.size),
PciSpace::Memory32 => println!("32-bit memory: 0x{:x}-0x{:x}",
range.cpu_address,
range.cpu_address + range.size),
PciSpace::Memory64 => println!("64-bit memory: 0x{:x}-0x{:x}",
range.cpu_address,
range.cpu_address + range.size),
}
}
// Resolve PCI device interrupts
let interrupt_info = pci.child_interrupts(0, 2, 0, 1)?; // bus=0, device=2, func=0, pin=INTB
for irq in &interrupt_info.irqs {
println!("PCI interrupt: {}", irq);
}
}// List all memory reservation blocks
for rsv in fdt.memory_reservation_blocks() {
println!("Reserved: 0x{:x}-0x{:x}", rsv.address, rsv.address + rsv.size);
}The project consists of three main crates:
The core parsing library with two main implementations:
- Base Parser (
base/): Direct parsing that walks the FDT structure with minimal memory overhead - Cached Parser (
cache/): Index/cached representation for faster repeated lookups
- Header Parsing: FDT header structure validation and metadata extraction
- Node Management: Hierarchical tree traversal and relationship handling
- Property Handling: Complete device tree property parsing with type conversion
- Specialized Nodes: Enhanced support for specific device types
-
PCI Nodes: Complete PCI bridge support with:
- Address space mapping (IO, Memory32, Memory64)
- Interrupt mapping (
interrupt-map,interrupt-map-mask) - Range translation and prefetchable memory
- Child interrupt resolution with fallback mechanisms
- Bus range configuration
-
Memory Nodes: Memory reservation block parsing and iteration
-
Interrupt Controllers: Complete interrupt hierarchy support with parent/child relationships
-
Clock Nodes: Clock provider and consumer parsing with cell configuration
-
Chosen Nodes: Boot parameter and chosen configuration access
Command-line tool for converting device tree blobs to device tree source format using clap for argument parsing:
# Convert a DTB file to DTS format
cargo run -p dtb-tool -- --input <dtb_file> --output <dts_file>
# Example:
cargo run -p dtb-tool -- --input bcm2711-rpi-4-b.dtb --output rpi4.dtsThe tool outputs a human-readable device tree source (.dts) file including:
- Device tree version information (
/dts-v{version}/;) - Memory reservation blocks (
/memreserve/entries) - Node hierarchy with proper indentation based on node level
- Compatible strings for each node (filtered for non-empty values)
- Raw FDT data access capabilities
Test device tree files and utilities for development and testing, including:
- Real device tree files from various platforms
- Custom test scenarios
- Memory reservation examples
Fdt: Main device tree parser with multiple access methodsNode: Device tree node with full API access and type safetyProperty: Device tree property with various type accessorsFdtError: Comprehensive error types with detailed context
Pci: PCI host bridge with full PCI support including ranges and interruptsMemory: Memory node with range parsing and reservation supportInterruptController: Interrupt controller with hierarchy and cell configurationClock: Clock provider/consumer with rate and parent relationshipsChosen: Boot parameter node for kernel arguments and configuration
find_node(path): Find node by absolute pathfind_compatible(compatible_strings): Find nodes by compatible stringsmemory_reservation_blocks(): Get memory reservations as iteratoraliases(): Get node aliases for path shortcutschosen(): Get chosen boot parametersall_nodes(): Iterator over all nodes in the treeroot(): Access the root nodeas_slice(): Get access to the raw FDT data sliceversion(): Get the device tree versionheader(): Get the FDT header information
name(): Node name without pathfind_property(name): Get property by namereg(): Get register information with address translationcompatible(): Get compatible strings listinterrupts(): Get interrupt information with parent resolutionparent(): Get parent node referencechildren(): Get child nodes listaddress_cells(): Get #address-cells propertysize_cells(): Get #size-cells propertylevel(): Get node depth level in the tree hierarchy
str(): String property value with UTF-8 validationu32(): 32-bit integer property value (big-endian)u64(): 64-bit integer property value (big-endian)data(): Raw property data access
ranges(): Get PCI address space ranges with space type decodinginterrupt_map(): Parse interrupt mapping table with mask applicationinterrupt_map_mask(): Get interrupt mapping maskchild_interrupts(bus, device, function, pin): Resolve device interruptsbus_range(): Get PCI bus number rangeis_pci_host_bridge(): Check if node is a PCI host bridge
The project includes comprehensive test coverage:
# Run all tests
cargo test
# Run specific test categories
cargo test -p fdt-parser cache # Cached parser tests
cargo test -p fdt-parser base # Base parser tests
cargo test -p fdt-parser pci # PCI-specific tests
# Run with output for debugging
cargo test -p fdt-parser -- --nocapture- Comprehensive test coverage across all components
- PCI node functionality (ranges, interrupts, properties, edge cases)
- Memory reservation block parsing and iteration
- Node hierarchy and property access validation
- Error handling and boundary condition testing
- Multiple real device tree files from various platforms
- Performance and memory usage validation
- Base Parser: O(N) time complexity, minimal memory overhead
- Cached Parser: O(1) lookup for cached nodes, O(N) initial indexing
- Memory Usage: Optimized for embedded systems with allocators
- PCI Interrupt Resolution: O(log M) where M is number of interrupt map entries
The cached parser provides O(1) lookup for frequently accessed nodes and properties, making it suitable for performance-critical applications where the device tree is accessed repeatedly.
This implementation follows industry standards:
- Devicetree Specification v0.4: Complete compliance with device tree format
- PCI Bus Binding Documentation: PCI bridge and interrupt mapping standards
- Open Firmware Interrupt Mapping Practice: Interrupt mapping conventions
- Device Tree Copyright License: Specification licensing
The project includes several example device tree files for testing and development:
- BCM2711 (Raspberry Pi 4): ARM platform with PCIe support and complex interrupt mapping
- Phytium: ARM platform with comprehensive PCI configuration
- QEMU: Virtual platform with simplified device tree for testing
- RK3568: ARM SoC platform with multiple device types
- Custom: Device trees with specific features for edge case testing
- x86_64: Full support for development and testing
- ARM: Complete support for embedded platforms
- RISC-V: Cross-compilation support
- AArch64: 64-bit ARM platform support
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Add tests for new functionality
- Ensure all tests pass (
cargo test) - Format code (
cargo fmt --all) - Run clippy (
cargo clippy --all) - Submit a pull request
- Follow Rust best practices and idioms
- Add comprehensive tests for new features
- Update documentation for API changes
- Ensure
no_stdcompatibility - Test with real device tree files when possible
This project is licensed under the MPL-2.0 License - see the LICENSE file for details.
https://github.com/drivercraft/fdt-parser
- PCI Support: Complete PCI node implementation with full feature support
- Address space types (IO, Memory32, Memory64) with prefetchable flag
- Interrupt mapping with
interrupt-mapandinterrupt-map-maskparsing - Child interrupt resolution with fallback mechanisms
- Range translation and bus range support
- Enhanced CLI Tool: Updated dtb-tool with clap argument parsing and improved output formatting
- Raw Data Access: New
Fdt::as_slice()method for accessing internal raw data - Enhanced Testing: Comprehensive test suite with real device tree files
- Memory Reservations: Improved iterator support and parsing accuracy with corrected method names
- Error Handling: Better error context and recovery mechanisms with thiserror v2
- Performance: Optimized parsing algorithms and memory usage
- Documentation: Complete API documentation and usage examples
- Repository Updates: Updated repository URL to https://github.com/drivercraft/fdt-parser
- Initial cached parser implementation
- Basic node type support
- Memory reservation block parsing
- Base parser implementation
- Core device tree parsing functionality
- Property and node access methods
- Linux Device Tree: Official device tree specification and resources
- Device Tree Compiler (DTC): Reference device tree compiler
- Rust Embedded Working Group: Embedded Rust community
If you use this project in research or production, please cite:
FDT Parser - A pure-Rust, no_std Flattened Device Tree parser
https://github.com/drivercraft/fdt-parser