devicetree/fdt/
parsing.rs1use 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
34const 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 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(¤t.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}