fdt_raw/node/
mod.rs

1use core::fmt;
2use core::ops::Deref;
3use core::{ffi::CStr, fmt::Debug};
4
5use crate::Fdt;
6use crate::{
7    FdtError, Token,
8    data::{Bytes, Reader},
9};
10
11mod chosen;
12mod memory;
13mod prop;
14
15pub use chosen::Chosen;
16pub use memory::{Memory, MemoryRegion};
17pub use prop::{PropIter, Property, RangeInfo, RegInfo, RegIter, VecRange};
18
19/// 节点上下文,保存从父节点继承的信息
20#[derive(Clone)]
21pub(crate) struct NodeContext {
22    /// 父节点的 #address-cells (用于解析当前节点的 reg)
23    pub address_cells: u8,
24    /// 父节点的 #size-cells (用于解析当前节点的 reg)
25    pub size_cells: u8,
26}
27
28impl Default for NodeContext {
29    fn default() -> Self {
30        NodeContext {
31            address_cells: 2,
32            size_cells: 1,
33        }
34    }
35}
36
37/// 基础节点结构
38#[derive(Clone)]
39pub struct NodeBase<'a> {
40    name: &'a str,
41    data: Bytes<'a>,
42    strings: Bytes<'a>,
43    level: usize,
44    _fdt: Fdt<'a>,
45    /// 当前节点的 #address-cells(用于子节点)
46    pub address_cells: u8,
47    /// 当前节点的 #size-cells(用于子节点)
48    pub size_cells: u8,
49    /// 继承的上下文(包含父节点的 cells 和累积的 ranges)
50    context: NodeContext,
51}
52
53impl<'a> NodeBase<'a> {
54    pub fn name(&self) -> &'a str {
55        self.name
56    }
57
58    pub fn level(&self) -> usize {
59        self.level
60    }
61
62    /// 获取节点属性迭代器
63    pub fn properties(&self) -> PropIter<'a> {
64        PropIter::new(self.data.reader(), self.strings.clone())
65    }
66
67    /// 查找指定名称的属性
68    pub fn find_property(&self, name: &str) -> Option<Property<'a>> {
69        self.properties().find(|p| p.name() == name)
70    }
71
72    /// 查找指定名称的字符串属性
73    pub fn find_property_str(&self, name: &str) -> Option<&'a str> {
74        let prop = self.find_property(name)?;
75
76        // 否则作为普通字符串处理
77        prop.as_str()
78    }
79
80    /// 查找并解析 reg 属性,返回 Reg 迭代器
81    pub fn reg(&self) -> Option<RegIter<'a>> {
82        let prop = self.find_property("reg")?;
83        Some(RegIter::new(
84            prop.data().reader(),
85            self.context.address_cells,
86            self.context.size_cells,
87        ))
88    }
89
90    /// 查找并解析 reg 属性,返回所有 RegInfo 条目
91    pub fn reg_array<const N: usize>(&self) -> heapless::Vec<RegInfo, N> {
92        let mut result = heapless::Vec::new();
93        if let Some(reg) = self.reg() {
94            for info in reg {
95                if result.push(info).is_err() {
96                    break; // 数组已满
97                }
98            }
99        }
100        result
101    }
102
103    /// 检查是否是 chosen 节点
104    fn is_chosen(&self) -> bool {
105        self.name == "chosen"
106    }
107
108    /// 检查是否是 memory 节点
109    fn is_memory(&self) -> bool {
110        self.name.starts_with("memory")
111    }
112
113    pub fn ranges(&self) -> Option<VecRange<'a>> {
114        let prop = self.find_property("ranges")?;
115        Some(VecRange::new(
116            self.address_cells as usize,
117            self.context.address_cells as usize,
118            self.context.size_cells as usize,
119            prop.data(),
120        ))
121    }
122}
123
124/// 写入缩进
125fn write_indent(f: &mut fmt::Formatter<'_>, count: usize, ch: &str) -> fmt::Result {
126    for _ in 0..count {
127        write!(f, "{}", ch)?;
128    }
129    Ok(())
130}
131
132impl fmt::Display for NodeBase<'_> {
133    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134        write_indent(f, self.level, "    ")?;
135        let name = if self.name.is_empty() { "/" } else { self.name };
136
137        writeln!(f, "{} {{", name)?;
138        for prop in self.properties() {
139            write_indent(f, self.level + 1, "    ")?;
140            writeln!(f, "{};", prop)?;
141        }
142        write_indent(f, self.level, "    ")?;
143        write!(f, "}}")
144    }
145}
146
147// ============================================================================
148// Node 枚举:支持特化节点类型
149// ============================================================================
150
151/// 节点枚举,支持 General、Chosen、Memory 等特化类型
152#[derive(Clone)]
153pub enum Node<'a> {
154    /// 通用节点
155    General(NodeBase<'a>),
156    /// Chosen 节点,包含启动参数
157    Chosen(Chosen<'a>),
158    /// Memory 节点,描述物理内存布局
159    Memory(Memory<'a>),
160}
161
162impl<'a> From<NodeBase<'a>> for Node<'a> {
163    fn from(node: NodeBase<'a>) -> Self {
164        if node.is_chosen() {
165            Node::Chosen(Chosen::new(node))
166        } else if node.is_memory() {
167            Node::Memory(Memory::new(node))
168        } else {
169            Node::General(node)
170        }
171    }
172}
173
174impl<'a> Deref for Node<'a> {
175    type Target = NodeBase<'a>;
176
177    fn deref(&self) -> &Self::Target {
178        match self {
179            Node::General(n) => n,
180            Node::Chosen(c) => c.deref(),
181            Node::Memory(m) => m.deref(),
182        }
183    }
184}
185
186impl fmt::Display for Node<'_> {
187    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188        Debug::fmt(self, f)
189    }
190}
191
192impl fmt::Debug for Node<'_> {
193    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194        match self {
195            Node::General(n) => f.debug_tuple("General").field(&n.name()).finish(),
196            Node::Chosen(c) => c.fmt(f),
197            Node::Memory(m) => m.fmt(f),
198        }
199    }
200}
201
202/// 解析属性时提取的关键信息
203#[derive(Debug, Clone, Default)]
204pub(crate) struct ParsedProps {
205    pub address_cells: Option<u8>,
206    pub size_cells: Option<u8>,
207}
208
209/// 单节点迭代状态
210#[derive(Debug, Clone, Copy, PartialEq, Eq)]
211pub(crate) enum OneNodeState {
212    /// 正在处理当前节点
213    Processing,
214    /// 遇到子节点的 BeginNode,需要回溯
215    ChildBegin,
216    /// 遇到 EndNode,当前节点处理完成
217    End,
218}
219
220/// An iterator over a single node's content.
221/// When encountering a child's BeginNode, it backtracks and signals FdtIter to handle it.
222pub(crate) struct OneNodeIter<'a> {
223    reader: Reader<'a>,
224    strings: Bytes<'a>,
225    state: OneNodeState,
226    level: usize,
227    context: NodeContext,
228    parsed_props: ParsedProps,
229    fdt: Fdt<'a>,
230}
231
232impl<'a> OneNodeIter<'a> {
233    pub fn new(
234        reader: Reader<'a>,
235        strings: Bytes<'a>,
236        level: usize,
237        context: NodeContext,
238        fdt: Fdt<'a>,
239    ) -> Self {
240        Self {
241            reader,
242            strings,
243            state: OneNodeState::Processing,
244            level,
245            context,
246            parsed_props: ParsedProps::default(),
247            fdt,
248        }
249    }
250
251    pub fn reader(&self) -> &Reader<'a> {
252        &self.reader
253    }
254
255    pub fn parsed_props(&self) -> &ParsedProps {
256        &self.parsed_props
257    }
258
259    /// 读取节点名称(在 BeginNode token 之后调用)
260    pub fn read_node_name(&mut self) -> Result<NodeBase<'a>, FdtError> {
261        // 读取以 null 结尾的名称字符串
262        let name = self.read_cstr()?;
263
264        // 对齐到 4 字节边界
265        self.align4();
266
267        let data = self.reader.remain();
268
269        Ok(NodeBase {
270            name,
271            data,
272            strings: self.strings.clone(),
273            level: self.level,
274            // 默认值,会在 process() 中更新
275            address_cells: 2,
276            size_cells: 1,
277            context: self.context.clone(),
278            _fdt: self.fdt.clone(),
279        })
280    }
281
282    fn read_cstr(&mut self) -> Result<&'a str, FdtError> {
283        let bytes = self.reader.remain();
284        let cstr = CStr::from_bytes_until_nul(bytes.as_slice())?;
285        let s = cstr.to_str()?;
286        // 跳过字符串内容 + null 终止符
287        let _ = self.reader.read_bytes(s.len() + 1);
288        Ok(s)
289    }
290
291    fn align4(&mut self) {
292        let pos = self.reader.position();
293        let aligned = (pos + 3) & !3;
294        let skip = aligned - pos;
295        if skip > 0 {
296            let _ = self.reader.read_bytes(skip);
297        }
298    }
299
300    /// 从 strings block 读取属性名
301    fn read_prop_name(&self, nameoff: u32) -> Result<&'a str, FdtError> {
302        let bytes = self.strings.slice(nameoff as usize..self.strings.len());
303        let cstr = CStr::from_bytes_until_nul(bytes.as_slice())?;
304        Ok(cstr.to_str()?)
305    }
306
307    /// 读取 u32 从大端字节
308    fn read_u32_be(data: &[u8], offset: usize) -> u64 {
309        u32::from_be_bytes(data[offset..offset + 4].try_into().unwrap()) as u64
310    }
311
312    /// 处理节点内容,解析关键属性,遇到子节点或结束时返回
313    pub fn process(&mut self) -> Result<OneNodeState, FdtError> {
314        loop {
315            let token = self.reader.read_token()?;
316            match token {
317                Token::BeginNode => {
318                    // 遇到子节点,回溯 token 并返回
319                    self.reader.backtrack(4);
320                    self.state = OneNodeState::ChildBegin;
321                    return Ok(OneNodeState::ChildBegin);
322                }
323                Token::EndNode => {
324                    self.state = OneNodeState::End;
325                    return Ok(OneNodeState::End);
326                }
327                Token::Prop => {
328                    // 读取属性:len 和 nameoff
329                    let len = self.reader.read_u32().ok_or(FdtError::BufferTooSmall {
330                        pos: self.reader.position(),
331                    })? as usize;
332
333                    let nameoff = self.reader.read_u32().ok_or(FdtError::BufferTooSmall {
334                        pos: self.reader.position(),
335                    })?;
336
337                    // 读取属性数据
338                    let prop_data = if len > 0 {
339                        self.reader
340                            .read_bytes(len)
341                            .ok_or(FdtError::BufferTooSmall {
342                                pos: self.reader.position(),
343                            })?
344                    } else {
345                        Bytes::new(&[])
346                    };
347
348                    // 解析关键属性
349                    if let Ok(prop_name) = self.read_prop_name(nameoff) {
350                        match prop_name {
351                            "#address-cells" if len == 4 => {
352                                self.parsed_props.address_cells =
353                                    Some(Self::read_u32_be(&prop_data, 0) as u8);
354                            }
355                            "#size-cells" if len == 4 => {
356                                self.parsed_props.size_cells =
357                                    Some(Self::read_u32_be(&prop_data, 0) as u8);
358                            }
359                            _ => {}
360                        }
361                    }
362
363                    // 对齐到 4 字节边界
364                    self.align4();
365                }
366                Token::Nop => {
367                    // 忽略 NOP
368                }
369                Token::End => {
370                    // 结构块结束
371                    self.state = OneNodeState::End;
372                    return Ok(OneNodeState::End);
373                }
374                Token::Data(_) => {
375                    // 非法 token
376                    return Err(FdtError::BufferTooSmall {
377                        pos: self.reader.position(),
378                    });
379                }
380            }
381        }
382    }
383}