devicetree/fdt/
header.rs

1use log::{
2    info,
3    debug,
4    error
5};
6
7use crate::{
8    utils, 
9    DeviceTreeError
10};
11
12/// FDT Header Magic Number
13const FDT_MAGIC: u32 = 0xd00dfeed;
14
15/// Version Number 
16/// 
17/// Note: The version is 17 if using the structure as defined in https://github.com/devicetree-org/devicetree-specification/releases/tag/v0.4-rc1
18const VERSION_NUMBER: u32 = 17;
19
20pub struct FdtHeader {
21    /// The magic value, shall be 0xd00dfeed (big-endian).
22	magic: u32,
23    /// The total size in bytes of the devicetree data structure.
24    totalsize: u32,
25    /// The offset in bytes of the structure block from the beginning of the header.
26    off_dt_struct: u32,
27    /// The offset in bytes of the strings block from the beginning of the header.
28    off_dt_strings: u32,
29    /// The offset in bytes of the memory reservation block from the beginning of the header.
30    off_mem_rsvmap: u32,
31    /// The version of the devicetree data structure.
32    version: u32,
33    /// The lowest version of the devicetree data structure with which the version used is backwards compatible.
34    last_comp_version: u32,
35    /// The physical ID of the system’s boot CPU.
36    /// It shall be identical to the physical ID given in the reg property of that CPU node within the devicetree.
37    boot_cpuid_phys: u32,
38    /// The length in bytes of the strings block section of the devicetree blob.
39    size_dt_strings: u32,
40    /// the length in bytes of the structure block section of the devicetree blob.
41    size_dt_struct: u32
42}
43
44impl FdtHeader {
45    pub fn from_bytes(bytes: &mut &[u8]) -> Result<Self, DeviceTreeError> {
46        debug!("Parsing FDT header from bytes.");
47
48        let header = Self {
49            magic: utils::take_be_u32(bytes).unwrap(), 
50            totalsize: utils::take_be_u32(bytes).unwrap(), 
51            off_dt_struct: utils::take_be_u32(bytes).unwrap(), 
52            off_dt_strings: utils::take_be_u32(bytes).unwrap(), 
53            off_mem_rsvmap: utils::take_be_u32(bytes).unwrap(), 
54            version: utils::take_be_u32(bytes).unwrap(), 
55            last_comp_version: utils::take_be_u32(bytes).unwrap(), 
56            boot_cpuid_phys: utils::take_be_u32(bytes).unwrap(), 
57            size_dt_strings: utils::take_be_u32(bytes).unwrap(), 
58            size_dt_struct: utils::take_be_u32(bytes).unwrap() 
59        };
60
61        let check = header.check();
62
63        match check {
64            Ok(_) => {
65                debug!("Valid header!");
66                return Ok(header);
67            },
68            Err(error) => {
69                debug!("Invalid magic number and/or version!");
70                return Err(error);
71            }
72        }
73    }
74
75    pub fn magic_check(&self) -> Result<(), DeviceTreeError> {
76        match self.magic {
77            FDT_MAGIC => Ok(()),
78            bad => Err(DeviceTreeError::BadMagic(bad))
79        }
80    }
81
82    pub fn version_check(&self) -> Result<(), DeviceTreeError> {
83        match self.version {
84            VERSION_NUMBER => Ok(()), 
85            bad => Err(DeviceTreeError::BadVersion(bad))
86        }
87    }
88
89    pub fn check(&self) -> Result<(), DeviceTreeError> {
90        self.magic_check()?;
91        self.version_check()?;
92        Ok(())
93    }
94
95    pub fn totalsize(&self) -> usize {
96        self.totalsize as usize
97    }
98
99    pub fn size_dt_struct(&self) -> usize {
100        self.size_dt_struct as usize
101    }
102
103    pub fn size_dt_strings(&self) -> usize {
104        self.size_dt_strings as usize
105    }
106}