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#[derive(Debug, Clone, Copy, PartialEq)]
87pub struct RawReg<'a> {
88 pub address: &'a [u8],
91 pub size: &'a [u8],
94}
95#[derive(Debug, Clone, Copy)]
96#[repr(C)]
97pub struct FdtHeader {
98 pub magic: Fdt32,
100 pub totalsize: Fdt32,
102 pub off_dt_struct: Fdt32,
104 pub off_dt_strings: Fdt32,
106 pub off_mem_rsvmap: Fdt32,
109 pub version: Fdt32,
111 pub last_comp_version: Fdt32,
113 pub boot_cpuid_phys: Fdt32,
115 pub size_dt_strings: Fdt32,
117 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 pub address: u64,
222 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#[derive(Clone)]
244pub struct FdtRange<'a> {
245 data_child: &'a [u8],
246 data_parent: &'a [u8],
247 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 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}