Skip to content

Commit d2946a9

Browse files
committed
feat: 更新属性处理,优化 reg 数据访问和增加新属性方法
1 parent 3b43bf8 commit d2946a9

File tree

6 files changed

+157
-20
lines changed

6 files changed

+157
-20
lines changed

fdt-edit/src/node/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,6 @@ impl<'a> From<fdt_raw::Node<'a>> for Node {
553553
if prop.name() == "reg" {
554554
if let Some(reg_iter) = raw_node.reg() {
555555
let entries = reg_iter
556-
.iter()
557556
.map(|e| super::prop::Reg {
558557
address: e.address,
559558
size: e.size,

fdt-edit/src/prop/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ impl<'a> From<fdt_raw::Property<'a>> for Property {
265265
if prop.name() == "reg" {
266266
return Property {
267267
name,
268-
kind: PropertyKind::Raw(RawProperty(prop.data().to_vec())),
268+
kind: PropertyKind::Raw(RawProperty(prop.as_slice().to_vec())),
269269
};
270270
}
271271

@@ -338,15 +338,15 @@ impl<'a> From<fdt_raw::Property<'a>> for Property {
338338
} else {
339339
Property {
340340
name,
341-
kind: PropertyKind::Raw(RawProperty(prop.data().to_vec())),
341+
kind: PropertyKind::Raw(RawProperty(prop.as_slice().to_vec())),
342342
}
343343
}
344344
}
345345
_ => {
346346
// 未知属性,使用原始数据
347347
Property {
348348
name,
349-
kind: PropertyKind::Raw(RawProperty(prop.data().to_vec())),
349+
kind: PropertyKind::Raw(RawProperty(prop.as_slice().to_vec())),
350350
}
351351
}
352352
}

fdt-raw/src/data.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use core::{
66
use crate::define::{FdtError, Token};
77

88
#[derive(Clone)]
9-
pub(crate) struct Bytes<'a> {
9+
pub struct Bytes<'a> {
1010
pub(crate) all: &'a [u8],
1111
range: Range<usize>,
1212
}
@@ -80,7 +80,7 @@ impl<'a> Bytes<'a> {
8080
}
8181

8282
#[derive(Clone)]
83-
pub(crate) struct Reader<'a> {
83+
pub struct Reader<'a> {
8484
pub(crate) bytes: Bytes<'a>,
8585
pub(crate) iter: usize,
8686
}

fdt-raw/src/node/prop/mod.rs

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use core::fmt;
77

88
use log::error;
99

10-
pub use reg::{RegInfo, RegIter};
10+
pub use reg::{Reg, RegInfo, RegIter};
1111

1212
use super::NodeContext;
1313
use crate::{
@@ -53,6 +53,11 @@ impl<'a> Property<'a> {
5353
self.data.as_str_iter()
5454
}
5555

56+
/// 获取数据作为字节切片
57+
pub fn as_slice(&self) -> &[u8] {
58+
self.data.as_slice()
59+
}
60+
5661
/// 作为单个 u64 值
5762
pub fn as_u64(&self) -> Option<u64> {
5863
let mut iter = self.as_u32_iter();
@@ -130,6 +135,56 @@ impl<'a> Property<'a> {
130135
None
131136
}
132137
}
138+
139+
/// 获取为 device_type 字符串
140+
pub fn as_device_type(&self) -> Option<&'a str> {
141+
if self.name == "device_type" {
142+
self.as_str()
143+
} else {
144+
None
145+
}
146+
}
147+
148+
/// 获取为 interrupt-parent
149+
pub fn as_interrupt_parent(&self) -> Option<Phandle> {
150+
if self.name == "interrupt-parent" {
151+
self.as_u32().map(Phandle::from)
152+
} else {
153+
None
154+
}
155+
}
156+
157+
/// 获取为 clock-names 字符串列表
158+
pub fn as_clock_names(&self) -> Option<StrIter<'a>> {
159+
if self.name == "clock-names" {
160+
Some(self.as_str_iter())
161+
} else {
162+
None
163+
}
164+
}
165+
166+
/// 获取为 compatible 字符串列表
167+
pub fn as_compatible(&self) -> Option<StrIter<'a>> {
168+
if self.name == "compatible" {
169+
Some(self.as_str_iter())
170+
} else {
171+
None
172+
}
173+
}
174+
175+
/// 获取为 reg 属性(需要 context 信息)
176+
pub fn as_reg(&self, address_cells: u32, size_cells: u32) -> Option<Reg<'a>> {
177+
if self.name == "reg" {
178+
Some(Reg::new(self.data.as_slice(), address_cells as u8, size_cells as u8))
179+
} else {
180+
None
181+
}
182+
}
183+
184+
/// 是否为 dma-coherent 属性
185+
pub fn is_dma_coherent(&self) -> bool {
186+
self.name == "dma-coherent" && self.data.is_empty()
187+
}
133188
}
134189

135190
impl fmt::Display for Property<'_> {
@@ -151,6 +206,34 @@ impl fmt::Display for Property<'_> {
151206
write!(f, "status = \"{:?}\"", s)
152207
} else if let Some(p) = self.as_phandle() {
153208
write!(f, "phandle = {}", p)
209+
} else if let Some(p) = self.as_interrupt_parent() {
210+
write!(f, "interrupt-parent = {}", p)
211+
} else if let Some(s) = self.as_device_type() {
212+
write!(f, "device_type = \"{}\"", s)
213+
} else if let Some(iter) = self.as_compatible() {
214+
write!(f, "compatible = ")?;
215+
let mut first = true;
216+
for s in iter.clone() {
217+
if !first {
218+
write!(f, ", ")?;
219+
}
220+
write!(f, "\"{}\"", s)?;
221+
first = false;
222+
}
223+
Ok(())
224+
} else if let Some(iter) = self.as_clock_names() {
225+
write!(f, "clock-names = ")?;
226+
let mut first = true;
227+
for s in iter.clone() {
228+
if !first {
229+
write!(f, ", ")?;
230+
}
231+
write!(f, "\"{}\"", s)?;
232+
first = false;
233+
}
234+
Ok(())
235+
} else if self.is_dma_coherent() {
236+
write!(f, "dma-coherent")
154237
} else if let Some(s) = self.as_str() {
155238
// 检查是否有多个字符串
156239
if self.data().iter().filter(|&&b| b == 0).count() > 1 {

fdt-raw/src/node/prop/reg.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,40 @@
11
//! Reg 属性相关类型
22
3-
use crate::data::{Reader, U32Iter};
3+
use crate::data::{Bytes, Reader, U32Iter};
4+
5+
/// Reg 属性包装器
6+
#[derive(Clone)]
7+
pub struct Reg<'a> {
8+
data: &'a [u8],
9+
address_cells: u8,
10+
size_cells: u8,
11+
}
12+
13+
impl<'a> Reg<'a> {
14+
pub(crate) fn new(data: &'a [u8], address_cells: u8, size_cells: u8) -> Self {
15+
Self {
16+
data,
17+
address_cells,
18+
size_cells,
19+
}
20+
}
21+
22+
/// 获取 reg 数据的原始字节
23+
pub fn as_slice(&self) -> &[u8] {
24+
self.data
25+
}
26+
27+
/// 获取 u32 迭代器
28+
pub fn as_u32_iter(&self) -> U32Iter<'a> {
29+
Bytes::new(self.data).as_u32_iter()
30+
}
31+
32+
/// 获取 reg 信息迭代器
33+
pub fn iter(&self) -> RegIter<'a> {
34+
let bytes = Bytes::new(self.data);
35+
RegIter::new(bytes.reader(), self.address_cells, self.size_cells)
36+
}
37+
}
438

539
/// Reg 条目信息
640
#[derive(Debug, Clone, Copy, PartialEq, Eq)]

fdt-raw/tests/node.rs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -447,12 +447,12 @@ fn test_node_properties() {
447447
let mut found_address_cells = false;
448448
let mut found_size_cells = false;
449449
let mut found_interrupt_cells = false;
450-
let found_device_type = false;
451-
let found_compatible = false;
452-
let found_phandle = false;
453-
let found_interrupt_parent = false;
454-
let found_reg = false;
455-
let found_dma_coherent = false;
450+
let mut found_device_type = false;
451+
let mut found_compatible = false;
452+
let mut found_phandle = false;
453+
let mut found_interrupt_parent = false;
454+
let mut found_reg = false;
455+
let mut found_dma_coherent = false;
456456
let mut found_empty_property = false;
457457

458458
for node in fdt.all_nodes() {
@@ -488,6 +488,27 @@ fn test_node_properties() {
488488
match s {
489489
Status::Okay | Status::Disabled => {}
490490
}
491+
} else if let Some(iter) = prop.as_compatible() {
492+
let strs: Vec<_> = iter.clone().collect();
493+
if !strs.is_empty() {
494+
found_compatible = true;
495+
info!(" compatible = {:?}", strs);
496+
}
497+
} else if let Some(s) = prop.as_device_type() {
498+
found_device_type = true;
499+
info!(" device_type = \"{}\"", s);
500+
} else if prop.as_phandle().is_some() {
501+
found_phandle = true;
502+
info!(" {} = <{:?}>", prop.name(), prop.as_phandle());
503+
} else if prop.as_interrupt_parent().is_some() {
504+
found_interrupt_parent = true;
505+
info!(" {} = <{:?}>", prop.name(), prop.as_interrupt_parent());
506+
} else if prop.name() == "reg" {
507+
found_reg = true;
508+
info!(" reg ({} bytes)", prop.len());
509+
} else if prop.name() == "dma-coherent" {
510+
found_dma_coherent = true;
511+
info!(" dma-coherent (empty)");
491512
} else {
492513
// 处理未知属性
493514
if let Some(s) = prop.as_str() {
@@ -743,8 +764,8 @@ fn test_memory_in_fdt(raw: &[u8], name: &str) {
743764
);
744765
info!("[{}] device_type = \"{}\"", name, s);
745766
} else if let Some(reg) = prop.as_reg(
746-
node.reg_address_cells() as u32,
747-
node.reg_size_cells() as u32,
767+
node.context.parent_address_cells.into(),
768+
node.context.parent_size_cells.into(),
748769
) {
749770
found_reg = true;
750771
let reg_infos: Vec<_> = reg.iter().collect();
@@ -754,8 +775,8 @@ fn test_memory_in_fdt(raw: &[u8], name: &str) {
754775
info!(
755776
"[{}] address_cells={}, size_cells={}",
756777
name,
757-
node.reg_address_cells(),
758-
node.reg_size_cells()
778+
node.context.parent_address_cells,
779+
node.context.parent_size_cells
759780
);
760781
info!(
761782
"[{}] raw data ({} bytes): {:02x?}",
@@ -823,7 +844,7 @@ fn test_memory_in_fdt(raw: &[u8], name: &str) {
823844

824845
// RPi 4B 的特殊情况 - 当前测试数据显示地址和大小为0
825846
// 这可能是测试数据的特殊情况,我们只验证基本结构
826-
if node.reg_size_cells() == 1 {
847+
if node.context.parent_size_cells == 1 {
827848
assert_eq!(
828849
reg.as_slice().len() % 12,
829850
0,
@@ -841,7 +862,7 @@ fn test_memory_in_fdt(raw: &[u8], name: &str) {
841862

842863
// 验证 reg 数据长度的一致性
843864
let expected_entry_size =
844-
(node.reg_address_cells() + node.reg_size_cells()) * 4;
865+
(node.context.parent_address_cells + node.context.parent_size_cells) * 4;
845866
assert_eq!(
846867
reg.as_slice().len() % expected_entry_size as usize,
847868
0,

0 commit comments

Comments
 (0)