fdt/
parsing.rs

1// This Source Code Form is subject to the terms of the Mozilla Public License,
2// v. 2.0. If a copy of the MPL was not distributed with this file, You can
3// obtain one at https://mozilla.org/MPL/2.0/.
4
5use core::convert::TryInto;
6pub struct CStr<'a>(&'a [u8]);
7
8impl<'a> CStr<'a> {
9    pub fn new(data: &'a [u8]) -> Option<Self> {
10        let end = data.iter().position(|&b| b == 0)?;
11        Some(Self(&data[..end]))
12    }
13
14    /// Does not include the null terminating byte
15    pub fn len(&self) -> usize {
16        self.0.len()
17    }
18
19    pub fn as_str(&self) -> Option<&'a str> {
20        core::str::from_utf8(self.0).ok()
21    }
22}
23
24#[derive(Debug, Clone, Copy)]
25#[repr(transparent)]
26pub struct BigEndianU32(u32);
27
28impl BigEndianU32 {
29    pub fn get(self) -> u32 {
30        self.0
31    }
32
33    pub(crate) fn from_bytes(bytes: &[u8]) -> Option<Self> {
34        Some(BigEndianU32(u32::from_be_bytes(bytes.get(..4)?.try_into().unwrap())))
35    }
36}
37
38#[derive(Debug, Clone, Copy)]
39#[repr(transparent)]
40pub struct BigEndianU64(u64);
41
42impl BigEndianU64 {
43    pub fn get(&self) -> u64 {
44        self.0
45    }
46
47    pub(crate) fn from_bytes(bytes: &[u8]) -> Option<Self> {
48        Some(BigEndianU64(u64::from_be_bytes(bytes.get(..8)?.try_into().unwrap())))
49    }
50}
51
52#[derive(Debug, Clone, Copy)]
53pub struct FdtData<'a> {
54    bytes: &'a [u8],
55}
56
57impl<'a> FdtData<'a> {
58    pub fn new(bytes: &'a [u8]) -> Self {
59        Self { bytes }
60    }
61
62    pub fn u32(&mut self) -> Option<BigEndianU32> {
63        let ret = BigEndianU32::from_bytes(self.bytes)?;
64        self.skip(4);
65
66        Some(ret)
67    }
68
69    pub fn u64(&mut self) -> Option<BigEndianU64> {
70        let ret = BigEndianU64::from_bytes(self.bytes)?;
71        self.skip(8);
72
73        Some(ret)
74    }
75
76    pub fn skip(&mut self, n_bytes: usize) {
77        self.bytes = self.bytes.get(n_bytes..).unwrap_or_default()
78    }
79
80    pub fn remaining(&self) -> &'a [u8] {
81        self.bytes
82    }
83
84    pub fn peek_u32(&self) -> Option<BigEndianU32> {
85        Self::new(self.remaining()).u32()
86    }
87
88    pub fn is_empty(&self) -> bool {
89        self.remaining().is_empty()
90    }
91
92    pub fn skip_nops(&mut self) {
93        while let Some(crate::node::FDT_NOP) = self.peek_u32().map(|n| n.get()) {
94            let _ = self.u32();
95        }
96    }
97
98    pub fn take(&mut self, bytes: usize) -> Option<&'a [u8]> {
99        if self.bytes.len() >= bytes {
100            let ret = &self.bytes[..bytes];
101            self.skip(bytes);
102
103            return Some(ret);
104        }
105
106        None
107    }
108}