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::ffi::{c_int, c_uint}; 18 use core::fmt; 19 use core::result; 20 21 /// Error type corresponding to libfdt error codes. 22 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 23 pub enum FdtError { 24 /// FDT_ERR_NOTFOUND 25 NotFound, 26 /// FDT_ERR_EXISTS 27 Exists, 28 /// FDT_ERR_NOSPACE 29 NoSpace, 30 /// FDT_ERR_BADOFFSET 31 BadOffset, 32 /// FDT_ERR_BADPATH 33 BadPath, 34 /// FDT_ERR_BADPHANDLE 35 BadPhandle, 36 /// FDT_ERR_BADSTATE 37 BadState, 38 /// FDT_ERR_TRUNCATED 39 Truncated, 40 /// FDT_ERR_BADMAGIC 41 BadMagic, 42 /// FDT_ERR_BADVERSION 43 BadVersion, 44 /// FDT_ERR_BADSTRUCTURE 45 BadStructure, 46 /// FDT_ERR_BADLAYOUT 47 BadLayout, 48 /// FDT_ERR_INTERNAL 49 Internal, 50 /// FDT_ERR_BADNCELLS 51 BadNCells, 52 /// FDT_ERR_BADVALUE 53 BadValue, 54 /// FDT_ERR_BADOVERLAY 55 BadOverlay, 56 /// FDT_ERR_NOPHANDLES 57 NoPhandles, 58 /// FDT_ERR_BADFLAGS 59 BadFlags, 60 /// FDT_ERR_ALIGNMENT 61 Alignment, 62 /// Unexpected error code 63 Unknown(i32), 64 } 65 66 impl fmt::Display for FdtError { 67 /// Prints error messages from libfdt.h documentation. fmt(&self, f: &mut fmt::Formatter) -> fmt::Result68 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 69 match self { 70 Self::NotFound => write!(f, "The requested node or property does not exist"), 71 Self::Exists => write!(f, "Attempted to create an existing node or property"), 72 Self::NoSpace => write!(f, "Insufficient buffer space to contain the expanded tree"), 73 Self::BadOffset => write!(f, "Structure block offset is out-of-bounds or invalid"), 74 Self::BadPath => write!(f, "Badly formatted path"), 75 Self::BadPhandle => write!(f, "Invalid phandle length or value"), 76 Self::BadState => write!(f, "Received incomplete device tree"), 77 Self::Truncated => write!(f, "Device tree or sub-block is improperly terminated"), 78 Self::BadMagic => write!(f, "Device tree header missing its magic number"), 79 Self::BadVersion => write!(f, "Device tree has a version which can't be handled"), 80 Self::BadStructure => write!(f, "Device tree has a corrupt structure block"), 81 Self::BadLayout => write!(f, "Device tree sub-blocks in unsupported order"), 82 Self::Internal => write!(f, "libfdt has failed an internal assertion"), 83 Self::BadNCells => write!(f, "Bad format or value of #address-cells or #size-cells"), 84 Self::BadValue => write!(f, "Unexpected property value"), 85 Self::BadOverlay => write!(f, "Overlay cannot be applied"), 86 Self::NoPhandles => write!(f, "Device tree doesn't have any phandle available anymore"), 87 Self::BadFlags => write!(f, "Invalid flag or invalid combination of flags"), 88 Self::Alignment => write!(f, "Device tree base address is not 8-byte aligned"), 89 Self::Unknown(e) => write!(f, "Unknown libfdt error '{e}'"), 90 } 91 } 92 } 93 94 /// Result type with FdtError enum. 95 pub type Result<T> = result::Result<T, FdtError>; 96 97 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 98 pub(crate) struct FdtRawResult(c_int); 99 100 impl From<c_int> for FdtRawResult { from(value: c_int) -> Self101 fn from(value: c_int) -> Self { 102 Self(value) 103 } 104 } 105 106 impl TryFrom<FdtRawResult> for c_int { 107 type Error = FdtError; 108 try_from(res: FdtRawResult) -> Result<Self>109 fn try_from(res: FdtRawResult) -> Result<Self> { 110 use libfdt_bindgen::{ 111 FDT_ERR_ALIGNMENT, FDT_ERR_BADFLAGS, FDT_ERR_BADLAYOUT, FDT_ERR_BADMAGIC, 112 FDT_ERR_BADNCELLS, FDT_ERR_BADOFFSET, FDT_ERR_BADOVERLAY, FDT_ERR_BADPATH, 113 FDT_ERR_BADPHANDLE, FDT_ERR_BADSTATE, FDT_ERR_BADSTRUCTURE, FDT_ERR_BADVALUE, 114 FDT_ERR_BADVERSION, FDT_ERR_EXISTS, FDT_ERR_INTERNAL, FDT_ERR_NOPHANDLES, 115 FDT_ERR_NOSPACE, FDT_ERR_NOTFOUND, FDT_ERR_TRUNCATED, 116 }; 117 match res.0 { 118 x if x >= 0 => Ok(x), 119 x if x == -(FDT_ERR_NOTFOUND as c_int) => Err(FdtError::NotFound), 120 x if x == -(FDT_ERR_EXISTS as c_int) => Err(FdtError::Exists), 121 x if x == -(FDT_ERR_NOSPACE as c_int) => Err(FdtError::NoSpace), 122 x if x == -(FDT_ERR_BADOFFSET as c_int) => Err(FdtError::BadOffset), 123 x if x == -(FDT_ERR_BADPATH as c_int) => Err(FdtError::BadPath), 124 x if x == -(FDT_ERR_BADPHANDLE as c_int) => Err(FdtError::BadPhandle), 125 x if x == -(FDT_ERR_BADSTATE as c_int) => Err(FdtError::BadState), 126 x if x == -(FDT_ERR_TRUNCATED as c_int) => Err(FdtError::Truncated), 127 x if x == -(FDT_ERR_BADMAGIC as c_int) => Err(FdtError::BadMagic), 128 x if x == -(FDT_ERR_BADVERSION as c_int) => Err(FdtError::BadVersion), 129 x if x == -(FDT_ERR_BADSTRUCTURE as c_int) => Err(FdtError::BadStructure), 130 x if x == -(FDT_ERR_BADLAYOUT as c_int) => Err(FdtError::BadLayout), 131 x if x == -(FDT_ERR_INTERNAL as c_int) => Err(FdtError::Internal), 132 x if x == -(FDT_ERR_BADNCELLS as c_int) => Err(FdtError::BadNCells), 133 x if x == -(FDT_ERR_BADVALUE as c_int) => Err(FdtError::BadValue), 134 x if x == -(FDT_ERR_BADOVERLAY as c_int) => Err(FdtError::BadOverlay), 135 x if x == -(FDT_ERR_NOPHANDLES as c_int) => Err(FdtError::NoPhandles), 136 x if x == -(FDT_ERR_BADFLAGS as c_int) => Err(FdtError::BadFlags), 137 x if x == -(FDT_ERR_ALIGNMENT as c_int) => Err(FdtError::Alignment), 138 x => Err(FdtError::Unknown(x)), 139 } 140 } 141 } 142 143 impl TryFrom<FdtRawResult> for Option<c_int> { 144 type Error = FdtError; 145 try_from(res: FdtRawResult) -> Result<Self>146 fn try_from(res: FdtRawResult) -> Result<Self> { 147 match res.try_into() { 148 Ok(n) => Ok(Some(n)), 149 Err(FdtError::NotFound) => Ok(None), 150 Err(e) => Err(e), 151 } 152 } 153 } 154 155 impl TryFrom<FdtRawResult> for c_uint { 156 type Error = FdtError; 157 try_from(res: FdtRawResult) -> Result<Self>158 fn try_from(res: FdtRawResult) -> Result<Self> { 159 Ok(c_int::try_from(res)?.try_into().unwrap()) 160 } 161 } 162 163 impl TryFrom<FdtRawResult> for usize { 164 type Error = FdtError; 165 try_from(res: FdtRawResult) -> Result<Self>166 fn try_from(res: FdtRawResult) -> Result<Self> { 167 Ok(c_int::try_from(res)?.try_into().unwrap()) 168 } 169 } 170 171 impl TryFrom<FdtRawResult> for Option<usize> { 172 type Error = FdtError; 173 try_from(res: FdtRawResult) -> Result<Self>174 fn try_from(res: FdtRawResult) -> Result<Self> { 175 match res.try_into() { 176 Ok(n) => Ok(Some(n)), 177 Err(FdtError::NotFound) => Ok(None), 178 Err(e) => Err(e), 179 } 180 } 181 } 182 183 impl TryFrom<FdtRawResult> for () { 184 type Error = FdtError; 185 try_from(res: FdtRawResult) -> Result<Self>186 fn try_from(res: FdtRawResult) -> Result<Self> { 187 match res.try_into()? { 188 0 => Ok(()), 189 n => Err(FdtError::Unknown(n)), 190 } 191 } 192 } 193