fdt_raw/
fdt.rs

1use core::fmt;
2
3use crate::{FdtError, MemoryReservation, data::Bytes, header::Header, iter::FdtIter};
4
5/// Memory reservation block iterator
6pub struct MemoryReservationIter<'a> {
7    data: &'a [u8],
8    offset: usize,
9}
10
11impl<'a> Iterator for MemoryReservationIter<'a> {
12    type Item = MemoryReservation;
13
14    fn next(&mut self) -> Option<Self::Item> {
15        // 确保我们有足够的数据来读取地址和大小(各8字节)
16        if self.offset + 16 > self.data.len() {
17            return None;
18        }
19
20        // 读取地址(8字节,大端序)
21        let address_bytes = &self.data[self.offset..self.offset + 8];
22        let address = u64::from_be_bytes(address_bytes.try_into().unwrap());
23        self.offset += 8;
24
25        // 读取大小(8字节,大端序)
26        let size_bytes = &self.data[self.offset..self.offset + 8];
27        let size = u64::from_be_bytes(size_bytes.try_into().unwrap());
28        self.offset += 8;
29
30        // 检查是否到达终止符(地址和大小都为0)
31        if address == 0 && size == 0 {
32            return None;
33        }
34
35        Some(MemoryReservation { address, size })
36    }
37}
38
39/// 写入缩进(使用空格)
40fn write_indent(f: &mut fmt::Formatter<'_>, count: usize, ch: &str) -> fmt::Result {
41    for _ in 0..count {
42        write!(f, "{}", ch)?;
43    }
44    Ok(())
45}
46
47#[derive(Clone)]
48pub struct Fdt<'a> {
49    header: Header,
50    pub(crate) data: Bytes<'a>,
51}
52
53impl<'a> Fdt<'a> {
54    /// Create a new `Fdt` from byte slice.
55    pub fn from_bytes(data: &'a [u8]) -> Result<Fdt<'a>, FdtError> {
56        let header = Header::from_bytes(data)?;
57        if data.len() < header.totalsize as usize {
58            return Err(FdtError::BufferTooSmall {
59                pos: header.totalsize as usize,
60            });
61        }
62        let buffer = Bytes::new(data);
63
64        Ok(Fdt {
65            header,
66            data: buffer,
67        })
68    }
69
70    /// Create a new `Fdt` from a raw pointer and size in bytes.
71    ///
72    /// # Safety
73    ///
74    /// The caller must ensure that the pointer is valid and points to a
75    /// memory region of at least `size` bytes that contains a valid device tree
76    /// blob.
77    pub unsafe fn from_ptr(ptr: *mut u8) -> Result<Fdt<'a>, FdtError> {
78        let header = unsafe { Header::from_ptr(ptr)? };
79
80        let data_slice = unsafe { core::slice::from_raw_parts(ptr, header.totalsize as _) };
81        let data = Bytes::new(data_slice);
82
83        Ok(Fdt { header, data })
84    }
85
86    pub fn header(&self) -> &Header {
87        &self.header
88    }
89
90    pub fn as_slice(&self) -> &'a [u8] {
91        self.data.as_slice()
92    }
93
94    pub fn all_nodes(&self) -> FdtIter<'a> {
95        FdtIter::new(self.clone())
96    }
97
98    /// Get an iterator over memory reservation entries
99    pub fn memory_reservations(&self) -> MemoryReservationIter<'a> {
100        MemoryReservationIter {
101            data: self.data.as_slice(),
102            offset: self.header.off_mem_rsvmap as usize,
103        }
104    }
105}
106
107impl fmt::Display for Fdt<'_> {
108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109        writeln!(f, "/dts-v1/;")?;
110        writeln!(f)?;
111
112        let mut prev_level = 0;
113
114        for node in self.all_nodes() {
115            let level = node.level();
116
117            // 关闭前一层级的节点
118            while prev_level > level {
119                prev_level -= 1;
120                write_indent(f, prev_level, "    ")?;
121                writeln!(f, "}};\n")?;
122            }
123
124            write_indent(f, level, "    ")?;
125            let name = if node.name().is_empty() {
126                "/"
127            } else {
128                node.name()
129            };
130
131            // 打印节点头部
132            writeln!(f, "{} {{", name)?;
133
134            // 打印属性
135            for prop in node.properties() {
136                write_indent(f, level + 1, "    ")?;
137                writeln!(f, "{};", prop)?;
138            }
139
140            prev_level = level + 1;
141        }
142
143        // 关闭剩余的节点
144        while prev_level > 0 {
145            prev_level -= 1;
146            write_indent(f, prev_level, "    ")?;
147            writeln!(f, "}};\n")?;
148        }
149
150        Ok(())
151    }
152}
153
154impl fmt::Debug for Fdt<'_> {
155    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156        writeln!(f, "Fdt {{")?;
157        writeln!(f, "\theader: {:?}", self.header)?;
158        writeln!(f, "\tnodes:")?;
159
160        for node in self.all_nodes() {
161            let level = node.level();
162            // 基础缩进 2 个 tab,每层再加 1 个 tab
163            write_indent(f, level + 2, "\t")?;
164
165            let name = if node.name().is_empty() {
166                "/"
167            } else {
168                node.name()
169            };
170
171            // 打印节点名称和基本信息
172            writeln!(
173                f,
174                "[{}] address_cells={}, size_cells={}",
175                name, node.address_cells, node.size_cells
176            )?;
177
178            // 打印属性
179            for prop in node.properties() {
180                write_indent(f, level + 3, "\t")?;
181                if let Some(v) = prop.as_address_cells() {
182                    writeln!(f, "#address-cells: {}", v)?;
183                } else if let Some(v) = prop.as_size_cells() {
184                    writeln!(f, "#size-cells: {}", v)?;
185                } else if let Some(v) = prop.as_interrupt_cells() {
186                    writeln!(f, "#interrupt-cells: {}", v)?;
187                } else if let Some(s) = prop.as_status() {
188                    writeln!(f, "status: {:?}", s)?;
189                } else if let Some(p) = prop.as_phandle() {
190                    writeln!(f, "phandle: {}", p)?;
191                } else {
192                    // 默认处理未知属性
193                    if prop.is_empty() {
194                        writeln!(f, "{}", prop.name())?;
195                    } else if let Some(s) = prop.as_str() {
196                        writeln!(f, "{}: \"{}\"", prop.name(), s)?;
197                    } else if prop.len() == 4 {
198                        let v = u32::from_be_bytes(prop.data().as_slice().try_into().unwrap());
199                        writeln!(f, "{}: {:#x}", prop.name(), v)?;
200                    } else {
201                        writeln!(f, "{}: <{} bytes>", prop.name(), prop.len())?;
202                    }
203                }
204            }
205        }
206
207        writeln!(f, "}}")
208    }
209}
210
211#[cfg(test)]
212mod tests {
213    use super::*;
214    use heapless::Vec;
215
216    #[test]
217    fn test_memory_reservation_iterator() {
218        // 创建一个简单的测试数据:一个内存保留条目 + 终止符
219        let mut test_data = [0u8; 32];
220
221        // 地址: 0x80000000, 大小: 0x10000000 (256MB)
222        test_data[0..8].copy_from_slice(&0x80000000u64.to_be_bytes());
223        test_data[8..16].copy_from_slice(&0x10000000u64.to_be_bytes());
224        // 终止符: address=0, size=0
225        test_data[16..24].copy_from_slice(&0u64.to_be_bytes());
226        test_data[24..32].copy_from_slice(&0u64.to_be_bytes());
227
228        let iter = MemoryReservationIter {
229            data: &test_data,
230            offset: 0,
231        };
232
233        let reservations: Vec<MemoryReservation, 4> = iter.collect();
234        assert_eq!(reservations.len(), 1);
235        assert_eq!(reservations[0].address, 0x80000000);
236        assert_eq!(reservations[0].size, 0x10000000);
237    }
238
239    #[test]
240    fn test_empty_memory_reservation_iterator() {
241        // 只有终止符
242        let mut test_data = [0u8; 16];
243        test_data[0..8].copy_from_slice(&0u64.to_be_bytes());
244        test_data[8..16].copy_from_slice(&0u64.to_be_bytes());
245
246        let iter = MemoryReservationIter {
247            data: &test_data,
248            offset: 0,
249        };
250
251        let reservations: Vec<MemoryReservation, 4> = iter.collect();
252        assert_eq!(reservations.len(), 0);
253    }
254}