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