blob: d671647f49f05b4309585efabf39398be09fec37 [file] [log] [blame]
Pierre-Clément Tosi99a76902023-12-21 10:30:37 +00001// Copyright 2024, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Rust types related to the libfdt C integer results.
16
Elie Kheirallahea5dd522024-11-26 22:16:01 +000017use core::error;
Pierre-Clément Tosi91be1902024-01-22 21:15:19 +000018use core::ffi::{c_int, c_uint};
Pierre-Clément Tosi99a76902023-12-21 10:30:37 +000019use core::fmt;
20use core::result;
21
22/// Error type corresponding to libfdt error codes.
23#[derive(Clone, Copy, Debug, Eq, PartialEq)]
24pub enum FdtError {
25 /// FDT_ERR_NOTFOUND
26 NotFound,
27 /// FDT_ERR_EXISTS
28 Exists,
29 /// FDT_ERR_NOSPACE
30 NoSpace,
31 /// FDT_ERR_BADOFFSET
32 BadOffset,
33 /// FDT_ERR_BADPATH
34 BadPath,
35 /// FDT_ERR_BADPHANDLE
36 BadPhandle,
37 /// FDT_ERR_BADSTATE
38 BadState,
39 /// FDT_ERR_TRUNCATED
40 Truncated,
41 /// FDT_ERR_BADMAGIC
42 BadMagic,
43 /// FDT_ERR_BADVERSION
44 BadVersion,
45 /// FDT_ERR_BADSTRUCTURE
46 BadStructure,
47 /// FDT_ERR_BADLAYOUT
48 BadLayout,
49 /// FDT_ERR_INTERNAL
50 Internal,
51 /// FDT_ERR_BADNCELLS
52 BadNCells,
53 /// FDT_ERR_BADVALUE
54 BadValue,
55 /// FDT_ERR_BADOVERLAY
56 BadOverlay,
57 /// FDT_ERR_NOPHANDLES
58 NoPhandles,
59 /// FDT_ERR_BADFLAGS
60 BadFlags,
61 /// FDT_ERR_ALIGNMENT
62 Alignment,
63 /// Unexpected error code
64 Unknown(i32),
65}
66
67impl fmt::Display for FdtError {
68 /// Prints error messages from libfdt.h documentation.
69 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70 match self {
71 Self::NotFound => write!(f, "The requested node or property does not exist"),
72 Self::Exists => write!(f, "Attempted to create an existing node or property"),
73 Self::NoSpace => write!(f, "Insufficient buffer space to contain the expanded tree"),
74 Self::BadOffset => write!(f, "Structure block offset is out-of-bounds or invalid"),
75 Self::BadPath => write!(f, "Badly formatted path"),
76 Self::BadPhandle => write!(f, "Invalid phandle length or value"),
77 Self::BadState => write!(f, "Received incomplete device tree"),
78 Self::Truncated => write!(f, "Device tree or sub-block is improperly terminated"),
79 Self::BadMagic => write!(f, "Device tree header missing its magic number"),
80 Self::BadVersion => write!(f, "Device tree has a version which can't be handled"),
81 Self::BadStructure => write!(f, "Device tree has a corrupt structure block"),
82 Self::BadLayout => write!(f, "Device tree sub-blocks in unsupported order"),
83 Self::Internal => write!(f, "libfdt has failed an internal assertion"),
84 Self::BadNCells => write!(f, "Bad format or value of #address-cells or #size-cells"),
85 Self::BadValue => write!(f, "Unexpected property value"),
86 Self::BadOverlay => write!(f, "Overlay cannot be applied"),
87 Self::NoPhandles => write!(f, "Device tree doesn't have any phandle available anymore"),
88 Self::BadFlags => write!(f, "Invalid flag or invalid combination of flags"),
89 Self::Alignment => write!(f, "Device tree base address is not 8-byte aligned"),
90 Self::Unknown(e) => write!(f, "Unknown libfdt error '{e}'"),
91 }
92 }
93}
94
Elie Kheirallahea5dd522024-11-26 22:16:01 +000095impl error::Error for FdtError {}
96
Pierre-Clément Tosi99a76902023-12-21 10:30:37 +000097/// Result type with FdtError enum.
98pub type Result<T> = result::Result<T, FdtError>;
99
Pierre-Clément Tosi38304eb2024-01-11 22:37:54 +0000100#[derive(Clone, Copy, Debug, Eq, PartialEq)]
101pub(crate) struct FdtRawResult(c_int);
102
103impl From<c_int> for FdtRawResult {
104 fn from(value: c_int) -> Self {
105 Self(value)
106 }
107}
108
109impl TryFrom<FdtRawResult> for c_int {
110 type Error = FdtError;
111
112 fn try_from(res: FdtRawResult) -> Result<Self> {
113 use libfdt_bindgen::{
114 FDT_ERR_ALIGNMENT, FDT_ERR_BADFLAGS, FDT_ERR_BADLAYOUT, FDT_ERR_BADMAGIC,
115 FDT_ERR_BADNCELLS, FDT_ERR_BADOFFSET, FDT_ERR_BADOVERLAY, FDT_ERR_BADPATH,
116 FDT_ERR_BADPHANDLE, FDT_ERR_BADSTATE, FDT_ERR_BADSTRUCTURE, FDT_ERR_BADVALUE,
117 FDT_ERR_BADVERSION, FDT_ERR_EXISTS, FDT_ERR_INTERNAL, FDT_ERR_NOPHANDLES,
118 FDT_ERR_NOSPACE, FDT_ERR_NOTFOUND, FDT_ERR_TRUNCATED,
119 };
120 match res.0 {
121 x if x >= 0 => Ok(x),
122 x if x == -(FDT_ERR_NOTFOUND as c_int) => Err(FdtError::NotFound),
123 x if x == -(FDT_ERR_EXISTS as c_int) => Err(FdtError::Exists),
124 x if x == -(FDT_ERR_NOSPACE as c_int) => Err(FdtError::NoSpace),
125 x if x == -(FDT_ERR_BADOFFSET as c_int) => Err(FdtError::BadOffset),
126 x if x == -(FDT_ERR_BADPATH as c_int) => Err(FdtError::BadPath),
127 x if x == -(FDT_ERR_BADPHANDLE as c_int) => Err(FdtError::BadPhandle),
128 x if x == -(FDT_ERR_BADSTATE as c_int) => Err(FdtError::BadState),
129 x if x == -(FDT_ERR_TRUNCATED as c_int) => Err(FdtError::Truncated),
130 x if x == -(FDT_ERR_BADMAGIC as c_int) => Err(FdtError::BadMagic),
131 x if x == -(FDT_ERR_BADVERSION as c_int) => Err(FdtError::BadVersion),
132 x if x == -(FDT_ERR_BADSTRUCTURE as c_int) => Err(FdtError::BadStructure),
133 x if x == -(FDT_ERR_BADLAYOUT as c_int) => Err(FdtError::BadLayout),
134 x if x == -(FDT_ERR_INTERNAL as c_int) => Err(FdtError::Internal),
135 x if x == -(FDT_ERR_BADNCELLS as c_int) => Err(FdtError::BadNCells),
136 x if x == -(FDT_ERR_BADVALUE as c_int) => Err(FdtError::BadValue),
137 x if x == -(FDT_ERR_BADOVERLAY as c_int) => Err(FdtError::BadOverlay),
138 x if x == -(FDT_ERR_NOPHANDLES as c_int) => Err(FdtError::NoPhandles),
139 x if x == -(FDT_ERR_BADFLAGS as c_int) => Err(FdtError::BadFlags),
140 x if x == -(FDT_ERR_ALIGNMENT as c_int) => Err(FdtError::Alignment),
141 x => Err(FdtError::Unknown(x)),
142 }
143 }
144}
145
146impl TryFrom<FdtRawResult> for Option<c_int> {
147 type Error = FdtError;
148
149 fn try_from(res: FdtRawResult) -> Result<Self> {
150 match res.try_into() {
151 Ok(n) => Ok(Some(n)),
152 Err(FdtError::NotFound) => Ok(None),
153 Err(e) => Err(e),
154 }
155 }
156}
157
Pierre-Clément Tosi91be1902024-01-22 21:15:19 +0000158impl TryFrom<FdtRawResult> for c_uint {
159 type Error = FdtError;
160
161 fn try_from(res: FdtRawResult) -> Result<Self> {
162 Ok(c_int::try_from(res)?.try_into().unwrap())
163 }
164}
165
166impl TryFrom<FdtRawResult> for usize {
167 type Error = FdtError;
168
169 fn try_from(res: FdtRawResult) -> Result<Self> {
170 Ok(c_int::try_from(res)?.try_into().unwrap())
171 }
172}
173
174impl TryFrom<FdtRawResult> for Option<usize> {
175 type Error = FdtError;
176
177 fn try_from(res: FdtRawResult) -> Result<Self> {
178 match res.try_into() {
179 Ok(n) => Ok(Some(n)),
180 Err(FdtError::NotFound) => Ok(None),
181 Err(e) => Err(e),
182 }
183 }
184}
185
Pierre-Clément Tosi38304eb2024-01-11 22:37:54 +0000186impl TryFrom<FdtRawResult> for () {
187 type Error = FdtError;
188
189 fn try_from(res: FdtRawResult) -> Result<Self> {
190 match res.try_into()? {
191 0 => Ok(()),
192 n => Err(FdtError::Unknown(n)),
193 }
Pierre-Clément Tosi99a76902023-12-21 10:30:37 +0000194 }
195}