Skip to content

Commit 8429a7a

Browse files
committed
feat: more doc
1 parent 07134b2 commit 8429a7a

File tree

3 files changed

+190
-103
lines changed

3 files changed

+190
-103
lines changed

fdt-edit/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ keywords = ["device-tree", "dtb", "embedded", "no-std", "editor"]
99
license = "MIT OR Apache-2.0"
1010
name = "fdt-edit"
1111
readme = "README.md"
12+
homepage = "https://github.com/drivercraft/fdt-parser"
1213
repository = "https://github.com/drivercraft/fdt-parser"
13-
version = "0.1.0"
14+
version = "0.1.1"
1415

1516
[dependencies]
1617
log = "0.4"

fdt-edit/README.md

Lines changed: 187 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,233 @@
11
# fdt-edit
22

3-
用于创建、编辑和编码设备树(FDT)的高级 Rust 库。
3+
A high-level Rust library for creating, editing, and encoding Flattened Device Tree (FDT) structures.
44

5-
## 概述
5+
## Overview
66

7-
`fdt-edit` 是一个功能丰富的设备树操作库,基于 `fdt-raw` 构建,提供了完整的设备树创建、编辑和编码功能。该库支持从零创建新的设备树,修改现有的设备树,以及将编辑后的设备树编码为标准 DTB 格式。
7+
`fdt-edit` is a feature-rich device tree manipulation library built on top of `fdt-raw`. It provides comprehensive functionality for creating new device trees from scratch, modifying existing device trees, and encoding the edited device trees into standard DTB format.
88

9-
## 特性
9+
## Features
1010

11-
- **完整的设备树编辑**:支持节点和属性的增删改查
12-
- **类型安全的节点操作**:提供专门的节点类型(时钟、内存、PCI、中断控制器等)
13-
- **高效的编码器**:将内存中的设备树结构编码为标准 DTB 格式
14-
- **phandle 管理**:自动 phandle 分配和引用管理
15-
- **内存保留块支持**:完整的内存保留区域操作
16-
- **`no_std` 兼容**:适用于嵌入式环境
11+
- **Complete device tree editing**: Full CRUD operations for nodes and properties
12+
- **Type-safe node operations**: Specialized node types (clocks, memory, PCI, interrupt controllers, etc.)
13+
- **Efficient encoder**: Converts in-memory device tree structures to standard DTB format
14+
- **phandle management**: Automatic phandle allocation and reference management
15+
- **Memory reservation support**: Complete memory reservation region operations
16+
- **`no_std` compatible**: Suitable for embedded environments
1717

18-
## 核心组件
18+
## Core Components
1919

20-
### Fdt 结构
21-
可编辑的设备树容器:
22-
- 从原始 DTB 数据解析
23-
- 创建新的空设备树
24-
- 管理 phandle 缓存
25-
- 编码为 DTB 格式
20+
### Fdt Structure
21+
An editable device tree container that:
22+
- Parses from raw DTB data
23+
- Creates new empty device trees
24+
- Manages phandle cache
25+
- Encodes to DTB format
2626

27-
### 节点系统
28-
支持多种专用节点类型:
29-
- **时钟节点**:时钟源和时钟消费者
30-
- **内存节点**:内存区域定义
31-
- **PCI 节点**PCI 总线和设备
32-
- **中断控制器**:中断映射和管理
33-
- **通用节点**:可自定义的节点类型
27+
### Node System
28+
Supports multiple specialized node types:
29+
- **Clock nodes**: Clock sources and clock consumers
30+
- **Memory nodes**: Memory region definitions
31+
- **PCI nodes**: PCI buses and devices
32+
- **Interrupt controllers**: Interrupt mapping and management
33+
- **Generic nodes**: Customizable node types
3434

35-
### 属性系统
36-
- **强类型属性**:各种数据类型的属性支持
37-
- **自动属性管理**:智能的属性增删改查
38-
- **格式化显示**:友好的节点和属性显示
35+
### Property System
36+
- **Type-safe properties**: Support for various data types
37+
- **Automatic property management**: Intelligent property CRUD operations
38+
- **Formatted display**: Friendly node and property display
3939

40-
## 快速开始
40+
## Quick Start
4141

4242
```rust
43-
use fdt_edit::{Fdt, Node, NodeKind};
44-
45-
// 创建新的空设备树
46-
let mut fdt = Fdt::new();
47-
48-
// 添加根节点下的子节点
49-
let memory_node = fdt.root_mut()
50-
.add_child("memory@80000000")
51-
.unwrap();
52-
memory_node.add_property("device_type", "memory")?;
53-
memory_node.add_property("reg", &[0x8000_0000u64, 0x1000_0000u64])?;
54-
55-
// 添加时钟节点
56-
let clock_node = fdt.root_mut()
57-
.add_child("clk_osc")
58-
.unwrap();
59-
clock_node.add_property("compatible", &["fixed-clock"])?;
60-
clock_node.add_property("#clock-cells", &[0u32])?;
61-
clock_node.add_property("clock-frequency", &[24_000_000u32])?;
62-
63-
// 编码为 DTB 数据
64-
let dtb_data = fdt.encode()?;
65-
```
66-
67-
### 从现有 DTB 编辑
43+
use fdt_edit::Fdt;
6844

69-
```rust
70-
// 解析现有 DTB
71-
let mut fdt = Fdt::from_bytes(&existing_dtb)?;
45+
// Parse existing DTB from bytes
46+
let raw_data = include_bytes!("path/to/device-tree.dtb");
47+
let fdt = Fdt::from_bytes(&raw_data)?;
7248

73-
// 查找并修改节点
74-
if let Some(cpu_node) = fdt.root_mut()
75-
.find_child_mut("cpus")?
76-
.and_then(|n| n.find_child_mut("cpu@0")) {
77-
78-
// 修改时钟频率
79-
cpu_node.set_property("clock-frequency", &[1_200_000_000u32])?;
49+
// Access nodes by path
50+
let node = fdt.get_by_path("/chosen");
51+
if let Some(chosen) = node {
52+
println!("Found chosen node: {}", chosen.name());
8053
}
8154

82-
// 添加新的属性
83-
cpu_node.add_property("new-property", "value")?;
84-
85-
// 重新编码
86-
let modified_dtb = fdt.encode()?;
55+
// Encode back to DTB format
56+
let dtb_data = fdt.encode();
57+
std::fs::write("output.dtb", dtb_data.as_bytes())?;
8758
```
8859

89-
### 节点遍历和查找
60+
### Node Traversal and Searching
9061

9162
```rust
92-
// 遍历所有节点
93-
for node in fdt.root().traverse() {
94-
match node.kind() {
63+
use fdt_edit::{Fdt, NodeKind};
64+
65+
let fdt = Fdt::from_bytes(&dtb_data)?;
66+
67+
// Iterate through all nodes
68+
for node in fdt.all_nodes() {
69+
println!("Node: {} at path {}", node.name(), node.path());
70+
71+
// Match specialized node types
72+
match node.as_ref() {
9573
NodeKind::Memory(mem) => {
96-
println!("Memory node: {:x?}", mem.regions());
74+
println!(" Memory node with regions:");
75+
for region in mem.regions() {
76+
println!(" address=0x{:x}, size=0x{:x}", region.address, region.size);
77+
}
9778
}
9879
NodeKind::Clock(clock) => {
99-
println!("Clock: {}, freq: {}", clock.name(), clock.frequency()?);
80+
println!(" Clock node: {} (#clock-cells={})", clock.name(), clock.clock_cells);
81+
}
82+
NodeKind::Pci(pci) => {
83+
if let Some(range) = pci.bus_range() {
84+
println!(" PCI bus range: {:?}", range);
85+
}
10086
}
10187
_ => {
102-
println!("Generic node: {}", node.name());
88+
println!(" Generic node");
89+
}
90+
}
91+
}
92+
93+
// Find nodes by path pattern
94+
let virtio_nodes: Vec<_> = fdt.find_by_path("/virtio_mmio").collect();
95+
println!("Found {} virtio_mmio nodes", virtio_nodes.len());
96+
```
97+
98+
### Node Modification and Creation
99+
100+
```rust
101+
use fdt_edit::{Fdt, Node};
102+
103+
let mut fdt = Fdt::from_bytes(&dtb_data)?;
104+
105+
// Create new node manually
106+
let mut new_node = Node::new("test-device@12340000");
107+
// Add properties (API in development)
108+
// new_node.add_property("compatible", &["vendor,test-device"]);
109+
// new_node.add_property("reg", &[0x12340000u64, 0x1000u64]);
110+
111+
// Add to root node
112+
fdt.root.add_child(new_node);
113+
114+
// Remove existing node
115+
if fdt.get_by_path("/psci").is_some() {
116+
let removed = fdt.remove_node("/psci")?;
117+
println!("Removed psci node: {}", removed.unwrap().name());
118+
}
119+
120+
// Save the modified device tree
121+
let modified_dtb = fdt.encode();
122+
std::fs::write("modified.dtb", modified_dtb.as_bytes())?;
123+
```
124+
125+
### Specialized Node Access
126+
127+
```rust
128+
use fdt_edit::{Fdt, NodeKind};
129+
130+
let fdt = Fdt::from_bytes(&dtb_data)?;
131+
132+
// Find and work with memory nodes
133+
for node in fdt.all_nodes() {
134+
if let NodeKind::Memory(mem) = node.as_ref() {
135+
let regions = mem.regions();
136+
if !regions.is_empty() {
137+
println!("Memory node '{}' has {} regions:", mem.name(), regions.len());
138+
for (i, region) in regions.iter().enumerate() {
139+
println!(" Region {}: 0x{:x}-0x{:x}", i, region.address, region.address + region.size);
140+
}
103141
}
104142
}
105143
}
106144

107-
// 查找特定节点
108-
if let Some(chosen) = fdt.root().find_child("chosen") {
109-
if let Some(bootargs) = chosen.get_property("bootargs") {
110-
println!("Boot args: {}", bootargs.as_str()?);
145+
// Find clock nodes
146+
let mut clock_count = 0;
147+
for node in fdt.all_nodes() {
148+
if let NodeKind::Clock(clock) = node.as_ref() {
149+
clock_count += 1;
150+
println!("Clock {}: cells={}, output-names={:?}",
151+
clock.name(),
152+
clock.clock_cells,
153+
clock.clock_output_names);
111154
}
112155
}
113156
```
114157

115-
## 依赖
158+
### Display as Device Tree Source
116159

117-
- `fdt-raw` - 底层 FDT 解析库
118-
- `log = "0.4"` - 日志记录
119-
- `enum_dispatch = "0.3.13"` - 枚举分发优化
160+
```rust
161+
use fdt_edit::Fdt;
162+
163+
let fdt = Fdt::from_bytes(&dtb_data)?;
164+
165+
// Display as DTS format (including memory reservations)
166+
println!("{}", fdt);
167+
// Output will show:
168+
// /dts-v1/;
169+
// /memreserve/ 0x80000000 0x100000;
170+
// / {
171+
// #address-cells = <0x2>;
172+
// #size-cells = <0x2>;
173+
// compatible = "qemu,arm64";
174+
// ...
175+
// };
176+
```
120177

121-
## 开发依赖
178+
## Current Status
179+
180+
This library is under active development. Currently supported features:
181+
- ✅ Parse DTB files into editable structures
182+
- ✅ Encode device trees back to DTB format
183+
- ✅ Display device trees in DTS format
184+
- ✅ Access to memory reservations
185+
- 🚧 Node editing APIs (in development)
186+
187+
## Dependencies
188+
189+
- `fdt-raw` - Low-level FDT parsing library
190+
- `log = "0.4"` - Logging support
191+
- `enum_dispatch = "0.3.13"` - Enum dispatch optimization
192+
193+
## Dev Dependencies
194+
195+
- `dtb-file` - Test data
196+
- `env_logger = "0.11"` - Logger implementation
197+
198+
## Testing
199+
200+
The library includes comprehensive tests that verify round-trip compatibility:
201+
202+
```bash
203+
cargo test
204+
```
122205

123-
- `dtb-file` - 测试数据
124-
- `env_logger = "0.11"` - 日志实现
206+
The main test (`test_parse_and_rebuild`) ensures that:
207+
1. A DTB file can be parsed successfully
208+
2. The parsed structure can be encoded back to DTB
209+
3. The original and rebuilt DTB files produce identical DTS output when using `dtc`
125210

126-
## 许可证
211+
## License
127212

128-
本项目采用开源许可证,具体许可证类型请查看项目根目录的 LICENSE 文件。
213+
This project is licensed under open source licenses. Please see the LICENSE file in the project root for specific license types.
129214

130-
## 贡献
215+
## Contributing
131216

132-
欢迎提交 Issue 和 Pull Request。请确保:
217+
Issues and Pull Requests are welcome. Please ensure:
133218

134-
1. 代码遵循项目的格式规范(`cargo fmt`
135-
2. 通过所有测试(`cargo test`
136-
3. 通过 Clippy 检查(`cargo clippy`
137-
4. 新功能添加相应的测试用例
219+
1. Code follows the project's formatting standards (`cargo fmt`)
220+
2. All tests pass (`cargo test`)
221+
3. Clippy checks pass (`cargo clippy`)
222+
4. New features include appropriate test cases
138223

139-
## 相关项目
224+
## Related Projects
140225

141-
- [fdt-raw](../fdt-raw/) - 底层 FDT 解析库
142-
- [fdt-parser](../fdt-parser/) - 高级缓存式 FDT 解析器
143-
- [dtb-tool](../dtb-tool/) - DTB 文件检查工具
144-
- [dtb-file](../dtb-file/) - 测试数据包
226+
- [fdt-raw](../fdt-raw/) - Low-level FDT parsing library
227+
- [fdt-parser](../fdt-parser/) - High-level cached FDT parser
228+
- [dtb-tool](../dtb-tool/) - DTB file inspection tool
229+
- [dtb-file](../dtb-file/) - Test data package
145230

146-
## 示例
231+
## Examples
147232

148-
更多使用示例请查看 `examples/` 目录(如果存在)或源码中的测试用例。
233+
More usage examples can be found in the source code test files, particularly in `tests/edit.rs`.

fdt-raw/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ keywords = ["device-tree", "dtb", "embedded", "no-std", "bare-metal"]
99
license = "MIT OR Apache-2.0"
1010
name = "fdt-raw"
1111
readme = "README.md"
12+
homepage = "https://github.com/drivercraft/fdt-parser"
1213
repository = "https://github.com/drivercraft/fdt-parser"
1314
version = "0.1.0"
1415

0 commit comments

Comments
 (0)