fdt_parser/
define.rs

1use core::{
2    fmt::{Debug, Display},
3    ptr::NonNull,
4};
5
6use crate::{
7    error::*,
8    read::{FdtReader, U32Array},
9};
10
11#[derive(Debug, PartialEq, Eq, Clone, Copy)]
12pub enum Token {
13    BeginNode,
14    EndNode,
15    Prop,
16    Nop,
17    End,
18    Data,
19}
20impl From<u32> for Token {
21    fn from(value: u32) -> Self {
22        match value {
23            0x1 => Token::BeginNode,
24            0x2 => Token::EndNode,
25            0x3 => Token::Prop,
26            0x4 => Token::Nop,
27            0x9 => Token::End,
28            _ => Token::Data,
29        }
30    }
31}
32
33#[derive(Debug, Clone, Copy)]
34#[repr(transparent)]
35pub struct Fdt32([u8; 4]);
36
37impl Fdt32 {
38    pub const fn new() -> Self {
39        Self([0; 4])
40    }
41
42    pub fn get(self) -> u32 {
43        u32::from_be_bytes(self.0)
44    }
45}
46
47impl From<&[u8]> for Fdt32 {
48    fn from(value: &[u8]) -> Self {
49        Fdt32(value.get(..4).unwrap().try_into().unwrap())
50    }
51}
52
53impl Default for Fdt32 {
54    fn default() -> Self {
55        Self::new()
56    }
57}
58
59#[derive(Debug, Clone, Copy)]
60#[repr(transparent)]
61pub struct Fdt64([u8; 8]);
62
63impl Fdt64 {
64    pub const fn new() -> Self {
65        Self([0; 8])
66    }
67
68    pub fn get(&self) -> u64 {
69        u64::from_be_bytes(self.0)
70    }
71}
72impl From<&[u8]> for Fdt64 {
73    fn from(value: &[u8]) -> Self {
74        Self(value.get(..8).unwrap().try_into().unwrap())
75    }
76}
77impl Default for Fdt64 {
78    fn default() -> Self {
79        Self::new()
80    }
81}
82
83/// A raw `reg` property value set
84#[derive(Debug, Clone, Copy, PartialEq)]
85pub struct RawReg<'a> {
86    /// Big-endian encoded bytes making up the address portion of the property.
87    /// Length will always be a multiple of 4 bytes.
88    pub address: &'a [u8],
89    /// Big-endian encoded bytes making up the size portion of the property.
90    /// Length will always be a multiple of 4 bytes.
91    pub size: &'a [u8],
92}
93#[derive(Debug, Clone, Copy)]
94#[repr(C)]
95pub struct FdtHeader {
96    /// FDT header magic
97    pub magic: Fdt32,
98    /// Total size in bytes of the FDT structure
99    pub totalsize: Fdt32,
100    /// Offset in bytes from the start of the header to the structure block
101    pub off_dt_struct: Fdt32,
102    /// Offset in bytes from the start of the header to the strings block
103    pub off_dt_strings: Fdt32,
104    /// Offset in bytes from the start of the header to the memory reservation
105    /// block
106    pub off_mem_rsvmap: Fdt32,
107    /// FDT version
108    pub version: Fdt32,
109    /// Last compatible FDT version
110    pub last_comp_version: Fdt32,
111    /// System boot CPU ID
112    pub boot_cpuid_phys: Fdt32,
113    /// Length in bytes of the strings block
114    pub size_dt_strings: Fdt32,
115    /// Length in bytes of the struct block
116    pub size_dt_struct: Fdt32,
117}
118
119impl FdtHeader {
120    pub(crate) fn valid_magic(&self) -> FdtResult<'static> {
121        if self.magic.get() == 0xd00dfeed {
122            Ok(())
123        } else {
124            Err(FdtError::BadMagic)
125        }
126    }
127
128    pub(crate) fn struct_range(&self) -> core::ops::Range<usize> {
129        let start = self.off_dt_struct.get() as usize;
130        let end = start + self.size_dt_struct.get() as usize;
131
132        start..end
133    }
134
135    pub(crate) fn strings_range(&self) -> core::ops::Range<usize> {
136        let start = self.off_dt_strings.get() as usize;
137        let end = start + self.size_dt_strings.get() as usize;
138        start..end
139    }
140
141    pub fn from_bytes(bytes: &[u8]) -> FdtResult<'static, Self> {
142        if bytes.len() < size_of::<FdtHeader>() {
143            return Err(FdtError::Eof);
144        }
145
146        unsafe {
147            let ptr: *const FdtHeader = bytes.as_ptr().cast();
148            Ok(ptr.read())
149        }
150    }
151
152    pub fn from_ptr(ptr: NonNull<u8>) -> FdtResult<'static, Self> {
153        let ptr: NonNull<FdtHeader> = ptr.cast();
154        unsafe { Ok(*ptr.as_ref()) }
155    }
156}
157
158impl Display for FdtHeader {
159    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
160        f.debug_struct("FdtHeader")
161            .field("size", &self.totalsize.get())
162            .field("version", &self.version.get())
163            .field("last_comp_version", &self.last_comp_version.get())
164            .finish()
165    }
166}
167
168#[repr(C)]
169pub(crate) struct FdtReserveEntry {
170    pub address: u64,
171    pub size: u64,
172}
173impl FdtReserveEntry {
174    pub fn new(address: u64, size: u64) -> Self {
175        Self { address, size }
176    }
177}
178
179impl From<FdtReserveEntry> for MemoryRegion {
180    fn from(value: FdtReserveEntry) -> Self {
181        Self {
182            address: value.address as usize as _,
183            size: value.size as _,
184        }
185    }
186}
187
188#[derive(Clone, Copy)]
189pub struct MemoryRegion {
190    pub address: *mut u8,
191    pub size: usize,
192}
193
194impl Debug for MemoryRegion {
195    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
196        f.write_fmt(format_args!(
197            "MemoryRegion {{ address: {:p}, size: {:#x} }}",
198            self.address, self.size
199        ))
200    }
201}
202
203#[derive(Clone, Copy)]
204pub struct FdtReg {
205    /// parent bus address
206    pub address: u64,
207    /// child bus address
208    pub child_bus_address: u64,
209    pub size: Option<usize>,
210}
211
212impl Debug for FdtReg {
213    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
214        f.write_fmt(format_args!("<{:#x}", self.address))?;
215        if self.child_bus_address != self.address {
216            f.write_fmt(format_args!("({:#x})", self.child_bus_address))?;
217        }
218        f.write_fmt(format_args!(", "))?;
219        if let Some(s) = self.size {
220            f.write_fmt(format_args!("{:#x}>", s))
221        } else {
222            f.write_str("None>")
223        }
224    }
225}
226
227/// Range mapping child bus addresses to parent bus addresses
228#[derive(Clone)]
229pub struct FdtRange<'a> {
230    data_child: &'a [u8],
231    data_parent: &'a [u8],
232    /// Size of range
233    pub size: u64,
234}
235
236impl<'a> FdtRange<'a> {
237    pub fn child_bus_address(&self) -> U32Array<'a> {
238        U32Array::new(self.data_child)
239    }
240
241    pub fn parent_bus_address(&self) -> U32Array<'a> {
242        U32Array::new(self.data_parent)
243    }
244}
245
246impl Debug for FdtRange<'_> {
247    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
248        f.write_str("Range {{ child_bus_address: [ ")?;
249        for addr in self.child_bus_address() {
250            f.write_fmt(format_args!("{:#x} ", addr))?;
251        }
252        f.write_str("], parent_bus_address: [ ")?;
253        for addr in self.parent_bus_address() {
254            f.write_fmt(format_args!("{:#x} ", addr))?;
255        }
256        f.write_fmt(format_args!("], size: {:#x}", self.size))
257    }
258}
259
260#[derive(Clone)]
261pub struct FdtRangeSilce<'a> {
262    address_cell: u8,
263    address_cell_parent: u8,
264    size_cell: u8,
265    reader: FdtReader<'a>,
266}
267
268impl<'a> FdtRangeSilce<'a> {
269    pub(crate) fn new(
270        address_cell: u8,
271        address_cell_parent: u8,
272        size_cell: u8,
273        reader: FdtReader<'a>,
274    ) -> Self {
275        Self {
276            address_cell,
277            address_cell_parent,
278            size_cell,
279            reader,
280        }
281    }
282
283    pub fn iter(&self) -> FdtRangeIter<'a> {
284        FdtRangeIter { s: self.clone() }
285    }
286}
287#[derive(Clone)]
288pub struct FdtRangeIter<'a> {
289    s: FdtRangeSilce<'a>,
290}
291
292impl<'a> Iterator for FdtRangeIter<'a> {
293    type Item = FdtRange<'a>;
294
295    fn next(&mut self) -> Option<Self::Item> {
296        let child_address_bytes = self.s.address_cell as usize * size_of::<u32>();
297        let data_child = self.s.reader.take(child_address_bytes)?;
298
299        let parent_address_bytes = self.s.address_cell_parent as usize * size_of::<u32>();
300        let data_parent = self.s.reader.take(parent_address_bytes)?;
301
302        // let child_bus_address = self.s.reader.take_by_cell_size(self.s.address_cell)?;
303        // let parent_bus_address = self
304        //     .s
305        //     .reader
306        //     .take_by_cell_size(self.s.address_cell_parent)?;
307        let size = self.s.reader.take_by_cell_size(self.s.size_cell)?;
308        Some(FdtRange {
309            size,
310            data_child,
311            data_parent,
312        })
313    }
314}
315
316#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
317#[repr(transparent)]
318pub struct Phandle(u32);
319
320impl From<u32> for Phandle {
321    fn from(value: u32) -> Self {
322        Self(value)
323    }
324}
325impl Phandle {
326    pub fn as_usize(&self) -> usize {
327        self.0 as usize
328    }
329}
330
331impl Display for Phandle {
332    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
333        write!(f, "<{:#x}>", self.0)
334    }
335}