fdt_raw/node/
mod.rs

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