fdt_raw/node/prop/
mod.rs

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