devicetree/fdt/
parsing.rs

1use core::ffi::CStr;
2use alloc::{
3    rc::Rc,
4    vec::Vec,
5};
6use log::{
7    info,
8    debug,
9    error
10};
11
12use super::header::FdtHeader;
13use crate::{
14    utils,
15    DeviceTree, 
16    DeviceTreeError, 
17    DeviceTreeBlob,
18    tree::{
19        node::{
20            DeviceTreeNode, 
21            AddChild
22        }, 
23        prop::DeviceTreeProperty,
24    }
25};
26use super::blob::{
27    FdtReserveEntry,
28    FdtPropDescribe,
29    FdtStructBlock,
30    FdtStringsBlock,
31    Token
32};
33
34/* FDT Token */
35const FDT_BEGIN_NODE: u32 = 0x00000001;
36const FDT_END_NODE: u32 = 0x00000002;
37const FDT_PROP: u32 = 0x00000003;
38const FDT_NOP: u32 = 0x00000004;
39const FDT_END: u32 = 0x00000009;
40
41impl DeviceTree {
42    pub fn from_bytes(bytes: &mut &[u8]) -> Result<Self, DeviceTreeError> {
43        let mut dtb = DeviceTreeBlob::from_bytes(bytes)?;
44
45        dtb.to_tree()
46    }
47}
48
49impl<'a> DeviceTreeBlob<'a> {
50    pub fn from_bytes(bytes: &mut &'a [u8]) -> Result<Self, DeviceTreeError> {
51        info!("Device-Tree-Blob located at {:#x}", bytes as *const _ as usize);
52
53        let header = FdtHeader::from_bytes(bytes)?;
54
55        let mut memory_reservation_vec: Vec<FdtReserveEntry> = Vec::new();
56
57        while let Some(entry) = FdtReserveEntry::from_bytes(bytes) {
58            if !entry.end_of_list() {
59                debug!("Adding reserved memory entry.");
60                memory_reservation_vec.push(entry);
61            } else {
62                debug!("End of adding reserved memory entry.");
63                break;
64            }
65        }
66
67        let structure_block_size = header.size_dt_struct();
68        let string_block_size = header.size_dt_strings();
69
70        Ok( Self {
71            header: header,
72            memory_reservation_block: memory_reservation_vec,
73            structure_block: FdtStructBlock::from_bytes(bytes.take(..structure_block_size).unwrap()),
74            strings_block: FdtStringsBlock::from_bytes(bytes.take(..string_block_size).unwrap()) 
75        })
76    }
77
78    pub fn to_tree(&mut self) -> Result<DeviceTree, DeviceTreeError> {
79        self.structure_block.parsing(&self.strings_block)
80    }
81
82    pub fn structure_block(&self) -> &FdtStructBlock {
83        &self.structure_block
84    }
85
86    pub fn strings_block(&self) -> &FdtStringsBlock {
87        &self.strings_block
88    }
89}
90
91
92impl FdtReserveEntry {
93    pub fn from_bytes(bytes: &mut &[u8]) -> Option<Self> {
94        Some( Self {
95            address: utils::take_be_u64(bytes)?,
96            size: utils::take_be_u64(bytes)?
97        })
98    }
99
100    /// Return true if both address and size are equal to zero, which means that the list of reservation block is terminated here
101    pub fn end_of_list(&self) -> bool {
102        self.address == 0 && self.size == 0
103    }
104}
105
106impl FdtPropDescribe {
107    pub fn from_bytes(bytes: &mut &[u8]) -> Option<Self> {
108        Some( Self {
109            len: utils::take_be_u32(bytes)?,
110            name_off: utils::take_be_u32(bytes)? 
111        })
112    }
113
114    pub fn len(&self) -> usize {
115        self.len as usize
116    }
117
118    pub fn name_off(&self) -> usize {
119        self.name_off as usize
120    }
121}
122
123impl core::fmt::Display for FdtPropDescribe {
124    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
125        write!(f, "len: {}, name_offset: {}", self.len, self.name_off)
126    }
127}
128
129impl<'a> FdtStructBlock<'a> {
130    pub fn from_bytes(bytes: &'a [u8]) -> Self {
131        Self(bytes)
132    }
133
134    pub fn bytes(&self) -> &[u8] {
135        self.0
136    }
137
138    pub fn parsing(&mut self, strings_block: &FdtStringsBlock) -> Result<DeviceTree, DeviceTreeError> {
139        debug!("Converting dtb to tree structure.");
140
141        let mut current = DeviceTreeNode::new_wrap();
142
143        current.borrow_mut().set_name("root");
144
145        let mut bytes = self.0;
146
147        loop {
148            let token = Token::from_bytes(&mut bytes)?;
149
150            match token {
151                Token::TokenBeginNode => { 
152                    let name = utils::take_utf8_until_nul_aligned(&mut bytes, 4).unwrap();
153    
154                    if name.is_empty() {
155                        debug!("Adding root node.");
156                        continue;
157                    }
158    
159                    let next = DeviceTreeNode::new_wrap();
160
161                    current.add_child(name, Rc::clone(&next));
162
163                    current = Rc::clone(&next);
164                }
165                Token::TokenProp => {
166                    let prop_describe = FdtPropDescribe::from_bytes(&mut bytes).unwrap();
167        
168                    let name = strings_block.find(prop_describe.name_off()).unwrap();
169
170                    let mut raw_value = utils::take_aligned(&mut bytes, prop_describe.len(), 4).unwrap();
171        
172                    let prop = DeviceTreeProperty::from_bytes(name, &mut raw_value);
173
174                    current.borrow_mut().add_prop(prop);
175                }
176                Token::TokenEndNode => {
177                    debug!("End of node '{}'.", current.borrow().name());
178
179                    if !current.borrow().has_parent() {
180                        break;
181                    }
182
183                    let parent = Rc::clone(&current.borrow().parent().unwrap());
184
185                    current = Rc::clone(&parent);
186                }
187                Token::TokenEnd => {
188                    break;
189                }
190                _ => ()
191            }
192        }
193
194        debug!("End of parsing.");
195
196        Ok(DeviceTree::new(current))
197    }
198}
199
200impl<'a> FdtStringsBlock<'a> {
201    pub fn from_bytes(bytes: &'a [u8]) -> Self {
202        Self(bytes)
203    }
204
205    pub fn find(&self, offset: usize) -> Result<&str, DeviceTreeError> {
206        if offset > self.0.len() {
207            return Err(DeviceTreeError::BadStringsBlockOffset);
208        }
209
210        let find = self.0.get(offset..).unwrap();
211
212        let name = CStr::from_bytes_until_nul(find).unwrap().to_str().unwrap();
213
214        Ok(name)
215    }
216}
217
218impl Token {
219    pub fn from_bytes(bytes: &mut &[u8]) -> Result<Self, DeviceTreeError> {
220        match utils::take_be_u32(bytes).unwrap() {
221            FDT_BEGIN_NODE => Ok(Self::TokenBeginNode),
222            FDT_END_NODE => Ok(Self::TokenEndNode),
223            FDT_PROP => Ok(Self::TokenProp), 
224            FDT_NOP => Ok(Self::TokenNop),
225            FDT_END => Ok(Self::TokenEnd),
226            _ => Err(DeviceTreeError::NotAToken)
227        }
228    }
229
230    pub fn is_begin_node(self) -> bool {
231        self == Self::TokenBeginNode
232    }
233
234    pub fn is_end_node(self) -> bool {
235        self == Self::TokenEndNode
236    }
237
238    pub fn is_prop(self) -> bool {
239        self == Self::TokenProp
240    }
241
242    pub fn is_nop(self) -> bool {
243        self == Self::TokenNop 
244    }
245
246    pub fn is_end(self) -> bool {
247        self == Self::TokenEnd
248    }
249}
250
251impl core::fmt::Display for Token {
252    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
253        match self {
254            Self::TokenBeginNode => write!(f, "TOKEN_BEGIN_NODE"),
255            Self::TokenEndNode => write!(f, "TOKEN_END_NODE"),
256            Self::TokenProp => write!(f, "TOKEN_PROP"),
257            Self::TokenNop => write!(f, "TOKEN_NOP"),
258            Self::TokenEnd => write!(f, "TOKEN_END"),
259        }
260    }
261}