Skip to content

Commit a65b3fa

Browse files
committed
refactor: 移除不必要的 phandle 映射设置,优化上下文管理逻辑;更新 PCI 节点处理以支持更高效的地址和 IRQ 处理;添加测试用例以初始化日志记录
1 parent 5056a20 commit a65b3fa

File tree

4 files changed

+115
-72
lines changed

4 files changed

+115
-72
lines changed

fdt-edit/src/ctx.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,6 @@ impl<'a> Context<'a> {
121121
}
122122

123123
pub fn push(&mut self, node: &'a Node) {
124-
if let Some(ph) = node.phandle() {
125-
self.phandle_map.insert(ph, node);
126-
}
127124
self.parents.push(node);
128125
}
129126

@@ -132,11 +129,6 @@ impl<'a> Context<'a> {
132129
self.phandle_map.get(&phandle).copied()
133130
}
134131

135-
/// 设置 phandle 到节点的映射
136-
pub fn set_phandle_map(&mut self, map: BTreeMap<Phandle, &'a Node>) {
137-
self.phandle_map = map;
138-
}
139-
140132
/// 从 Fdt 构建 phandle 映射
141133
pub fn build_phandle_map_from_node(node: &'a Node, map: &mut BTreeMap<Phandle, &'a Node>) {
142134
if let Some(phandle) = node.phandle() {

fdt-edit/src/node/iter.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ pub struct NodeIter<'a> {
7979

8080
impl<'a> NodeIter<'a> {
8181
pub fn new(root: &'a Node) -> Self {
82-
let ctx = Context::new();
82+
let mut ctx = Context::new();
83+
// 预先构建整棵树的 phandle_map
84+
// 这样在遍历任何节点时都能通过 phandle 找到其他节点
85+
Context::build_phandle_map_from_node(root, &mut ctx.phandle_map);
8386

8487
Self {
8588
ctx,
@@ -151,9 +154,18 @@ impl RawChildIter {
151154

152155
impl<'a> NodeIterMut<'a> {
153156
pub fn new(root: &'a mut Node) -> Self {
157+
let mut ctx = Context::new();
158+
// 预先构建整棵树的 phandle_map
159+
// 使用原始指针来避免借用冲突
160+
let root_ptr = root as *mut Node;
161+
unsafe {
162+
// 用不可变引用构建 phandle_map
163+
Context::build_phandle_map_from_node(&*root_ptr, &mut ctx.phandle_map);
164+
}
165+
154166
Self {
155-
ctx: Context::new(),
156-
node: Some(NonNull::from(root)),
167+
ctx,
168+
node: NonNull::new(root_ptr),
157169
stack: vec![],
158170
_marker: core::marker::PhantomData,
159171
}

fdt-edit/src/node/pci.rs

Lines changed: 86 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use core::ops::{Deref, Range};
22

33
use alloc::vec::Vec;
44
use fdt_raw::{FdtError, Phandle, data::U32Iter};
5+
use log::debug;
56

67
use crate::node::gerneric::NodeRefGen;
78

@@ -139,7 +140,11 @@ impl<'a> NodeRefPci<'a> {
139140
// 获取 interrupt-map 和 mask
140141
let interrupt_map = self.interrupt_map()?;
141142

142-
let mut mask = self.interrupt_map_mask().ok_or(FdtError::NotFound)?;
143+
// 将 mask 转换为 Vec 以便索引访问
144+
let mask: Vec<u32> = self
145+
.interrupt_map_mask()
146+
.ok_or(FdtError::NotFound)?
147+
.collect();
143148

144149
// 构造 PCI 设备的子地址
145150
// 格式: [bus_num, device_num, func_num] 在适当的位
@@ -151,41 +156,35 @@ impl<'a> NodeRefPci<'a> {
151156

152157
let child_addr_cells = self.address_cells().unwrap_or(3) as usize;
153158
let child_irq_cells = self.interrupt_cells() as usize;
154-
let required_mask_len = child_addr_cells + child_irq_cells;
155-
if mask.len() < required_mask_len {
156-
mask.resize(required_mask_len, 0xffff_ffff);
157-
}
158159

159160
let encoded_address = [child_addr_high, child_addr_mid, child_addr_low];
160161
let mut masked_child_address = Vec::with_capacity(child_addr_cells);
161162

162-
// 使用迭代器替代不必要的范围循环
163-
for (idx, value) in encoded_address.iter().enumerate() {
164-
masked_child_address.push(value & mask[idx]);
163+
// 应用 mask 到子地址
164+
for (idx, value) in encoded_address.iter().take(child_addr_cells).enumerate() {
165+
let mask_value = mask.get(idx).copied().unwrap_or(0xffff_ffff);
166+
masked_child_address.push(value & mask_value);
165167
}
166168

167-
// 如果 encoded_address 比 mask 短,处理剩余的 mask 值
168-
if encoded_address.len() < child_addr_cells {
169-
// 如果 encoded_address 比 mask 短,填充剩余的 0 值
170-
let remaining_zeros = child_addr_cells - encoded_address.len();
171-
masked_child_address.extend(core::iter::repeat_n(0, remaining_zeros));
172-
}
169+
// 如果 encoded_address 比 child_addr_cells 短,填充 0
170+
let remaining = child_addr_cells.saturating_sub(encoded_address.len());
171+
masked_child_address.extend(core::iter::repeat_n(0, remaining));
173172

174173
let encoded_irq = [interrupt_pin as u32];
175174
let mut masked_child_irq = Vec::with_capacity(child_irq_cells);
176175

177-
// 使用迭代器替代不必要的范围循环
178-
let mask_start = child_addr_cells;
179-
let mask_end = child_addr_cells + encoded_irq.len().min(child_irq_cells);
180-
for (value, mask_value) in encoded_irq.iter().zip(&mask[mask_start..mask_end]) {
176+
// 应用 mask 到子 IRQ
177+
for (idx, value) in encoded_irq.iter().take(child_irq_cells).enumerate() {
178+
let mask_value = mask
179+
.get(child_addr_cells + idx)
180+
.copied()
181+
.unwrap_or(0xffff_ffff);
181182
masked_child_irq.push(value & mask_value);
182183
}
183184

184-
// 如果 encoded_irq 比 child_irq_cells 短,处理剩余的 mask 值
185-
if encoded_irq.len() < child_irq_cells {
186-
let remaining_zeros = child_irq_cells - encoded_irq.len();
187-
masked_child_irq.extend(core::iter::repeat_n(0, remaining_zeros));
188-
}
185+
// 如果 encoded_irq 比 child_irq_cells 短,填充 0
186+
let remaining_irq = child_irq_cells.saturating_sub(encoded_irq.len());
187+
masked_child_irq.extend(core::iter::repeat_n(0, remaining_irq));
189188

190189
// 在 interrupt-map 中查找匹配的条目
191190
for mapping in &interrupt_map {
@@ -211,74 +210,102 @@ impl<'a> NodeRefPci<'a> {
211210
.find_property("interrupt-map")
212211
.ok_or(FdtError::NotFound)?;
213212

214-
let mut mask = self.interrupt_map_mask().ok_or(FdtError::NotFound)?;
213+
// 将 mask 和 data 转换为 Vec 以便索引访问
214+
let mask: Vec<u32> = self
215+
.interrupt_map_mask()
216+
.ok_or(FdtError::NotFound)?
217+
.collect();
215218

216-
let mut data = prop.get_u32_iter();
219+
let mut data = prop.as_reader();
217220
let mut mappings = Vec::new();
218221

219222
// 计算每个条目的大小
220223
// 格式: <child-address child-irq interrupt-parent parent-address parent-irq...>
221224
let child_addr_cells = self.address_cells().unwrap_or(3) as usize;
222225
let child_irq_cells = self.interrupt_cells() as usize;
223226

224-
let required_mask_len = child_addr_cells + child_irq_cells;
225-
if mask.len() < required_mask_len {
226-
mask.resize(required_mask_len, 0xffff_ffff);
227-
}
228-
229-
let mut idx = 0;
230-
while idx < data.len() {
227+
loop {
231228
// 解析子地址
232-
if idx + child_addr_cells > data.len() {
233-
break;
229+
let mut child_address = Vec::with_capacity(child_addr_cells);
230+
for _ in 0..child_addr_cells {
231+
match data.read_u32() {
232+
Some(v) => child_address.push(v),
233+
None => return Ok(mappings), // 数据结束
234+
}
234235
}
235-
let child_address = data[idx..idx + child_addr_cells].to_vec();
236-
idx += child_addr_cells;
237236

238237
// 解析子 IRQ
239-
if idx + child_irq_cells > data.len() {
240-
break;
238+
let mut child_irq = Vec::with_capacity(child_irq_cells);
239+
for _ in 0..child_irq_cells {
240+
match data.read_u32() {
241+
Some(v) => child_irq.push(v),
242+
None => return Ok(mappings),
243+
}
241244
}
242-
let child_irq = data[idx..idx + child_irq_cells].to_vec();
243-
idx += child_irq_cells;
244245

245246
// 解析中断父 phandle
246-
if idx >= data.len() {
247-
break;
248-
}
249-
let interrupt_parent_raw = data[idx];
247+
let interrupt_parent_raw = match data.read_u32() {
248+
Some(v) => v,
249+
None => return Ok(mappings),
250+
};
250251
let interrupt_parent = Phandle::from(interrupt_parent_raw);
251-
idx += 1;
252252

253-
// 通过 phandle 查找中断父节点以获取其 address_cells 和 interrupt_cells
253+
debug!(
254+
"Looking for interrupt parent phandle: 0x{:x} (raw: {})",
255+
interrupt_parent.raw(),
256+
interrupt_parent_raw
257+
);
258+
debug!(
259+
"Context phandle_map keys: {:?}",
260+
self.ctx
261+
.phandle_map
262+
.keys()
263+
.map(|p| format!("0x{:x}", p.raw()))
264+
.collect::<Vec<_>>()
265+
);
266+
267+
// 通过 phandle 查找中断父节点以获取其 #address-cells 和 #interrupt-cells
268+
// 根据 devicetree 规范,interrupt-map 中的 parent unit address 使用中断父节点的 #address-cells
254269
let (parent_addr_cells, parent_irq_cells) =
255270
if let Some(irq_parent) = self.ctx.find_by_phandle(interrupt_parent) {
271+
debug!("Found interrupt parent: {:?}", irq_parent.name);
272+
273+
// 直接使用中断父节点的 #address-cells
256274
let addr_cells = irq_parent.address_cells().unwrap_or(0) as usize;
275+
257276
let irq_cells = irq_parent
258-
.find_property("#interrupt-cells")
259-
.and_then(|p| match &p.kind {
260-
PropertyKind::Num(v) => Some(*v as usize),
261-
_ => None,
262-
})
263-
.unwrap_or(3);
277+
.get_property("#interrupt-cells")
278+
.and_then(|p| p.get_u32())
279+
.unwrap_or(3) as usize;
280+
debug!(
281+
"irq_parent addr_cells: {}, irq_cells: {}",
282+
addr_cells, irq_cells
283+
);
264284
(addr_cells, irq_cells)
265285
} else {
286+
debug!(
287+
"Interrupt parent phandle 0x{:x} NOT FOUND in context!",
288+
interrupt_parent.raw()
289+
);
266290
// 默认值:address_cells=0, interrupt_cells=3 (GIC 格式)
267291
(0, 3)
268292
};
269293

270294
// 跳过父地址 cells
271-
if idx + parent_addr_cells > data.len() {
272-
break;
295+
for _ in 0..parent_addr_cells {
296+
if data.read_u32().is_none() {
297+
return Ok(mappings);
298+
}
273299
}
274-
idx += parent_addr_cells;
275300

276301
// 解析父 IRQ
277-
if idx + parent_irq_cells > data.len() {
278-
break;
302+
let mut parent_irq = Vec::with_capacity(parent_irq_cells);
303+
for _ in 0..parent_irq_cells {
304+
match data.read_u32() {
305+
Some(v) => parent_irq.push(v),
306+
None => return Ok(mappings),
307+
}
279308
}
280-
let parent_irq = data[idx..idx + parent_irq_cells].to_vec();
281-
idx += parent_irq_cells;
282309

283310
// 应用 mask 到子地址和 IRQ
284311
let masked_address: Vec<u32> = child_address
@@ -308,8 +335,6 @@ impl<'a> NodeRefPci<'a> {
308335
parent_irq,
309336
});
310337
}
311-
312-
Ok(mappings)
313338
}
314339
}
315340

fdt-edit/tests/pci.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
#[cfg(test)]
22
mod tests {
3+
use std::sync::Once;
4+
35
use dtb_file::{fdt_phytium, fdt_qemu};
46
use fdt_edit::*;
57

8+
fn init_logging() {
9+
static INIT: Once = Once::new();
10+
INIT.call_once(|| {
11+
let _ = env_logger::builder()
12+
.is_test(true)
13+
.filter_level(log::LevelFilter::Trace)
14+
.try_init();
15+
});
16+
}
17+
618
#[test]
719
fn test_pci_node_detection() {
820
let raw_data = fdt_qemu();
@@ -145,6 +157,8 @@ mod tests {
145157

146158
#[test]
147159
fn test_pci_irq_map2() {
160+
init_logging();
161+
148162
let raw = fdt_qemu();
149163
let fdt = Fdt::from_bytes(&raw).unwrap();
150164
let node_ref = fdt

0 commit comments

Comments
 (0)