1 // 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 17 use core::error; 18 use core::ffi::{c_int, c_uint}; 19 use core::fmt; 20 use core::result; 21 22 /// Error type corresponding to libfdt error codes. 23 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 24 pub 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 67 impl fmt::Display for FdtError { 68 /// Prints error messages from libfdt.h documentation. fmt(&self, f: &mut fmt::Formatter) -> fmt::Result69 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 95 impl error::Error for FdtError {} 96 97 /// Result type with FdtError enum. 98 pub type Result<T> = result::Result<T, FdtError>; 99 100 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 101 pub(crate) struct FdtRawResult(c_int); 102 103 impl From<c_int> for FdtRawResult { from(value: c_int) -> Self104 fn from(value: c_int) -> Self { 105 Self(value) 106 } 107 } 108 109 impl TryFrom<FdtRawResult> for c_int { 110 type Error = FdtError; 111 try_from(res: FdtRawResult) -> Result<Self>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 146 impl TryFrom<FdtRawResult> for Option<c_int> { 147 type Error = FdtError; 148 try_from(res: FdtRawResult) -> Result<Self>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 158 impl TryFrom<FdtRawResult> for c_uint { 159 type Error = FdtError; 160 try_from(res: FdtRawResult) -> Result<Self>161 fn try_from(res: FdtRawResult) -> Result<Self> { 162 Ok(c_int::try_from(res)?.try_into().unwrap()) 163 } 164 } 165 166 impl TryFrom<FdtRawResult> for usize { 167 type Error = FdtError; 168 try_from(res: FdtRawResult) -> Result<Self>169 fn try_from(res: FdtRawResult) -> Result<Self> { 170 Ok(c_int::try_from(res)?.try_into().unwrap()) 171 } 172 } 173 174 impl TryFrom<FdtRawResult> for Option<usize> { 175 type Error = FdtError; 176 try_from(res: FdtRawResult) -> Result<Self>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 186 impl TryFrom<FdtRawResult> for () { 187 type Error = FdtError; 188 try_from(res: FdtRawResult) -> Result<Self>189 fn try_from(res: FdtRawResult) -> Result<Self> { 190 match res.try_into()? { 191 0 => Ok(()), 192 n => Err(FdtError::Unknown(n)), 193 } 194 } 195 } 196