fdt_raw/node/prop/
mod.rs

1//! 属性相关类型和迭代器
2
3mod ranges;
4mod reg;
5
6use core::ffi::CStr;
7use core::fmt;
8
9use log::error;
10
11pub use ranges::*;
12pub use reg::{RegInfo, RegIter};
13
14use crate::{
15    FdtError, Phandle, Status, Token,
16    data::{Bytes, Reader, StrIter, U32Iter},
17};
18
19/// 通用属性,包含名称和原始数据
20#[derive(Clone)]
21pub struct Property<'a> {
22    name: &'a str,
23    data: Bytes<'a>,
24}
25
26impl<'a> Property<'a> {
27    pub fn new(name: &'a str, data: Bytes<'a>) -> Self {
28        Self { name, data }
29    }
30
31    pub fn name(&self) -> &'a str {
32        self.name
33    }
34
35    pub fn data(&self) -> Bytes<'a> {
36        self.data.clone()
37    }
38
39    pub fn is_empty(&self) -> bool {
40        self.data.is_empty()
41    }
42
43    pub fn len(&self) -> usize {
44        self.data.len()
45    }
46
47    /// 作为 u32 迭代器
48    pub fn as_u32_iter(&self) -> U32Iter<'a> {
49        self.data.as_u32_iter()
50    }
51
52    /// 作为字符串迭代器(用于 compatible 等属性)
53    pub fn as_str_iter(&self) -> StrIter<'a> {
54        self.data.as_str_iter()
55    }
56
57    /// 获取数据作为字节切片
58    pub fn as_slice(&self) -> &[u8] {
59        self.data.as_slice()
60    }
61
62    /// 作为单个 u64 值
63    pub fn as_u64(&self) -> Option<u64> {
64        let mut iter = self.as_u32_iter();
65        let high = iter.next()? as u64;
66        let low = iter.next()? as u64;
67        if iter.next().is_some() {
68            return None;
69        }
70        Some((high << 32) | low)
71    }
72
73    /// 作为单个 u32 值
74    pub fn as_u32(&self) -> Option<u32> {
75        let mut iter = self.as_u32_iter();
76        let value = iter.next()?;
77        if iter.next().is_some() {
78            return None;
79        }
80        Some(value)
81    }
82
83    /// 作为字符串
84    pub fn as_str(&self) -> Option<&'a str> {
85        let bytes = self.data.as_slice();
86        let cstr = CStr::from_bytes_until_nul(bytes).ok()?;
87        cstr.to_str().ok()
88    }
89
90    /// 获取为 #address-cells 值
91    pub fn as_address_cells(&self) -> Option<u8> {
92        if self.name == "#address-cells" {
93            self.as_u32().map(|v| v as u8)
94        } else {
95            None
96        }
97    }
98
99    /// 获取为 #size-cells 值
100    pub fn as_size_cells(&self) -> Option<u8> {
101        if self.name == "#size-cells" {
102            self.as_u32().map(|v| v as u8)
103        } else {
104            None
105        }
106    }
107
108    /// 获取为 #interrupt-cells 值
109    pub fn as_interrupt_cells(&self) -> Option<u8> {
110        if self.name == "#interrupt-cells" {
111            self.as_u32().map(|v| v as u8)
112        } else {
113            None
114        }
115    }
116
117    /// 获取为 status 枚举
118    pub fn as_status(&self) -> Option<Status> {
119        let v = self.as_str()?;
120        if self.name == "status" {
121            match v {
122                "okay" | "ok" => Some(Status::Okay),
123                "disabled" => Some(Status::Disabled),
124                _ => None,
125            }
126        } else {
127            None
128        }
129    }
130
131    /// 获取为 phandle
132    pub fn as_phandle(&self) -> Option<Phandle> {
133        if self.name == "phandle" {
134            self.as_u32().map(Phandle::from)
135        } else {
136            None
137        }
138    }
139
140    /// 获取为 device_type 字符串
141    pub fn as_device_type(&self) -> Option<&'a str> {
142        if self.name == "device_type" {
143            self.as_str()
144        } else {
145            None
146        }
147    }
148
149    /// 获取为 interrupt-parent
150    pub fn as_interrupt_parent(&self) -> Option<Phandle> {
151        if self.name == "interrupt-parent" {
152            self.as_u32().map(Phandle::from)
153        } else {
154            None
155        }
156    }
157
158    /// 获取为 clock-names 字符串列表
159    pub fn as_clock_names(&self) -> Option<StrIter<'a>> {
160        if self.name == "clock-names" {
161            Some(self.as_str_iter())
162        } else {
163            None
164        }
165    }
166
167    /// 获取为 compatible 字符串列表
168    pub fn as_compatible(&self) -> Option<StrIter<'a>> {
169        if self.name == "compatible" {
170            Some(self.as_str_iter())
171        } else {
172            None
173        }
174    }
175
176    /// 是否为 dma-coherent 属性
177    pub fn is_dma_coherent(&self) -> bool {
178        self.name == "dma-coherent" && self.data.is_empty()
179    }
180}
181
182impl fmt::Display for Property<'_> {
183    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184        if self.is_empty() {
185            write!(f, "{}", self.name())
186        } else if let Some(v) = self.as_address_cells() {
187            write!(f, "#address-cells = <{:#x}>", v)
188        } else if let Some(v) = self.as_size_cells() {
189            write!(f, "#size-cells = <{:#x}>", v)
190        } else if let Some(v) = self.as_interrupt_cells() {
191            write!(f, "#interrupt-cells = <{:#x}>", v)
192        } else if self.name() == "reg" {
193            // reg 属性需要特殊处理,但我们没有 context 信息
194            // 直接显示原始数据
195            write!(f, "reg = ")?;
196            format_bytes(f, &self.data())
197        } else if let Some(s) = self.as_status() {
198            write!(f, "status = \"{:?}\"", s)
199        } else if let Some(p) = self.as_phandle() {
200            write!(f, "phandle = {}", p)
201        } else if let Some(p) = self.as_interrupt_parent() {
202            write!(f, "interrupt-parent = {}", p)
203        } else if let Some(s) = self.as_device_type() {
204            write!(f, "device_type = \"{}\"", s)
205        } else if let Some(iter) = self.as_compatible() {
206            write!(f, "compatible = ")?;
207            let mut first = true;
208            for s in iter.clone() {
209                if !first {
210                    write!(f, ", ")?;
211                }
212                write!(f, "\"{}\"", s)?;
213                first = false;
214            }
215            Ok(())
216        } else if let Some(iter) = self.as_clock_names() {
217            write!(f, "clock-names = ")?;
218            let mut first = true;
219            for s in iter.clone() {
220                if !first {
221                    write!(f, ", ")?;
222                }
223                write!(f, "\"{}\"", s)?;
224                first = false;
225            }
226            Ok(())
227        } else if self.is_dma_coherent() {
228            write!(f, "dma-coherent")
229        } else if let Some(s) = self.as_str() {
230            // 检查是否有多个字符串
231            if self.data().iter().filter(|&&b| b == 0).count() > 1 {
232                write!(f, "{} = ", self.name())?;
233                let mut first = true;
234                for s in self.as_str_iter() {
235                    if !first {
236                        write!(f, ", ")?;
237                    }
238                    write!(f, "\"{}\"", s)?;
239                    first = false;
240                }
241                Ok(())
242            } else {
243                write!(f, "{} = \"{}\"", self.name(), s)
244            }
245        } else if self.len() == 4 {
246            // 单个 u32
247            let v = u32::from_be_bytes(self.data().as_slice().try_into().unwrap());
248            write!(f, "{} = <{:#x}>", self.name(), v)
249        } else {
250            // 原始字节
251            write!(f, "{} = ", self.name())?;
252            format_bytes(f, &self.data())
253        }
254    }
255}
256
257/// 格式化字节数组为 DTS 格式
258fn format_bytes(f: &mut fmt::Formatter<'_>, data: &[u8]) -> fmt::Result {
259    if data.len().is_multiple_of(4) {
260        // 按 u32 格式化
261        write!(f, "<")?;
262        let mut first = true;
263        for chunk in data.chunks(4) {
264            if !first {
265                write!(f, " ")?;
266            }
267            let v = u32::from_be_bytes(chunk.try_into().unwrap());
268            write!(f, "{:#x}", v)?;
269            first = false;
270        }
271        write!(f, ">")
272    } else {
273        // 按字节格式化
274        write!(f, "[")?;
275        for (i, b) in data.iter().enumerate() {
276            if i > 0 {
277                write!(f, " ")?;
278            }
279            write!(f, "{:02x}", b)?;
280        }
281        write!(f, "]")
282    }
283}
284
285/// 属性迭代器
286pub struct PropIter<'a> {
287    reader: Reader<'a>,
288    strings: Bytes<'a>,
289    finished: bool,
290}
291
292impl<'a> PropIter<'a> {
293    pub(crate) fn new(reader: Reader<'a>, strings: Bytes<'a>) -> Self {
294        Self {
295            reader,
296            strings,
297
298            finished: false,
299        }
300    }
301
302    /// 处理错误:输出错误日志并终止迭代
303    fn handle_error(&mut self, err: FdtError) {
304        error!("Property parse error: {}", err);
305        self.finished = true;
306    }
307
308    /// 从 strings block 读取属性名
309    fn read_prop_name(&self, nameoff: u32) -> Result<&'a str, FdtError> {
310        if nameoff as usize >= self.strings.len() {
311            return Err(FdtError::BufferTooSmall {
312                pos: nameoff as usize,
313            });
314        }
315        let bytes = self.strings.slice(nameoff as usize..self.strings.len());
316        let cstr = CStr::from_bytes_until_nul(bytes.as_slice())?;
317        Ok(cstr.to_str()?)
318    }
319
320    fn align4(&mut self) {
321        let pos = self.reader.position();
322        let aligned = (pos + 3) & !3;
323        let skip = aligned - pos;
324        if skip > 0 {
325            let _ = self.reader.read_bytes(skip);
326        }
327    }
328}
329
330impl<'a> Iterator for PropIter<'a> {
331    type Item = Property<'a>;
332
333    fn next(&mut self) -> Option<Self::Item> {
334        if self.finished {
335            return None;
336        }
337
338        loop {
339            let token = match self.reader.read_token() {
340                Ok(t) => t,
341                Err(e) => {
342                    self.handle_error(e);
343                    return None;
344                }
345            };
346
347            match token {
348                Token::Prop => {
349                    // 读取属性长度
350                    let len = match self.reader.read_u32() {
351                        Some(b) => b,
352                        None => {
353                            self.handle_error(FdtError::BufferTooSmall {
354                                pos: self.reader.position(),
355                            });
356                            return None;
357                        }
358                    };
359
360                    // 读取属性名偏移
361                    let nameoff = match self.reader.read_u32() {
362                        Some(b) => b,
363                        None => {
364                            self.handle_error(FdtError::BufferTooSmall {
365                                pos: self.reader.position(),
366                            });
367                            return None;
368                        }
369                    };
370
371                    // 读取属性数据
372                    let prop_data = if len > 0 {
373                        match self.reader.read_bytes(len as _) {
374                            Some(b) => b,
375                            None => {
376                                self.handle_error(FdtError::BufferTooSmall {
377                                    pos: self.reader.position(),
378                                });
379                                return None;
380                            }
381                        }
382                    } else {
383                        Bytes::new(&[])
384                    };
385
386                    // 读取属性名
387                    let name = match self.read_prop_name(nameoff) {
388                        Ok(n) => n,
389                        Err(e) => {
390                            self.handle_error(e);
391                            return None;
392                        }
393                    };
394
395                    // 对齐到 4 字节边界
396                    self.align4();
397
398                    return Some(Property::new(name, prop_data));
399                }
400                Token::BeginNode | Token::EndNode | Token::End => {
401                    // 遇到节点边界,回溯并终止属性迭代
402                    self.reader.backtrack(4);
403                    self.finished = true;
404                    return None;
405                }
406                Token::Nop => {
407                    // 忽略 NOP,继续
408                    continue;
409                }
410                Token::Data(_) => {
411                    // 非法 token
412                    self.handle_error(FdtError::BufferTooSmall {
413                        pos: self.reader.position(),
414                    });
415                    return None;
416                }
417            }
418        }
419    }
420}