1use crate::raw;
19use num_enum::{FromPrimitive, IntoPrimitive};
20use std::fmt;
21
22pub type Result<T> = std::result::Result<T, Error>;
36
37pub(crate) fn teec_check(code: raw::TEEC_Result) -> Result<()> {
40 match code {
41 raw::TEEC_SUCCESS => Ok(()),
42 code => Err(Error::from_raw_error(code)),
43 }
44}
45
46pub(crate) fn teec_check_with_origin(code: raw::TEEC_Result, origin: u32) -> Result<()> {
49 match code {
50 raw::TEEC_SUCCESS => Ok(()),
51 code => Err(Error::from_raw_error(code).with_origin(origin.into())),
52 }
53}
54
55#[derive(Clone)]
60pub struct Error {
61 kind: ErrorKind,
62 origin: Option<ErrorOrigin>,
63}
64
65#[derive(
68 Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, FromPrimitive, IntoPrimitive,
69)]
70#[repr(u32)]
71pub enum ErrorKind {
72 Generic = raw::TEEC_ERROR_GENERIC,
74 AccessDenied = raw::TEEC_ERROR_ACCESS_DENIED,
76 Cancel = raw::TEEC_ERROR_CANCEL,
78 AccessConflict = raw::TEEC_ERROR_ACCESS_CONFLICT,
80 ExcessData = raw::TEEC_ERROR_EXCESS_DATA,
82 BadFormat = raw::TEEC_ERROR_BAD_FORMAT,
84 BadParameters = raw::TEEC_ERROR_BAD_PARAMETERS,
86 BadState = raw::TEEC_ERROR_BAD_STATE,
88 ItemNotFound = raw::TEEC_ERROR_ITEM_NOT_FOUND,
90 NotImplemented = raw::TEEC_ERROR_NOT_IMPLEMENTED,
92 NotSupported = raw::TEEC_ERROR_NOT_SUPPORTED,
94 NoData = raw::TEEC_ERROR_NO_DATA,
96 OutOfMemory = raw::TEEC_ERROR_OUT_OF_MEMORY,
98 Busy = raw::TEEC_ERROR_BUSY,
100 Communication = raw::TEEC_ERROR_COMMUNICATION,
102 Security = raw::TEEC_ERROR_SECURITY,
104 ShortBuffer = raw::TEEC_ERROR_SHORT_BUFFER,
106 ExternalCancel = raw::TEEC_ERROR_EXTERNAL_CANCEL,
108 TargetDead = raw::TEEC_ERROR_TARGET_DEAD,
110 #[num_enum(catch_all)]
112 Unknown(u32),
113}
114
115impl ErrorKind {
116 pub(crate) fn as_str(&self) -> &'static str {
117 match self {
118 ErrorKind::Generic => "Non-specific cause.",
119 ErrorKind::AccessDenied => "Access privileges are not sufficient.",
120 ErrorKind::Cancel => "The operation was canceled.",
121 ErrorKind::AccessConflict => "Concurrent accesses caused conflict.",
122 ErrorKind::ExcessData => "Too much data for the requested operation was passed.",
123 ErrorKind::BadFormat => "Input data was of invalid format.",
124 ErrorKind::BadParameters => "Input parameters were invalid.",
125 ErrorKind::BadState => "Operation is not valid in the current state.",
126 ErrorKind::ItemNotFound => "The requested data item is not found.",
127 ErrorKind::NotImplemented => {
128 "The requested operation should exist but is not yet implemented."
129 }
130 ErrorKind::NotSupported => {
131 "The requested operation is valid but is not supported in this implementation."
132 }
133 ErrorKind::NoData => "Expected data was missing.",
134 ErrorKind::OutOfMemory => "System ran out of resources.",
135 ErrorKind::Busy => "The system is busy working on something else.",
136 ErrorKind::Communication => "Communication with a remote party failed.",
137 ErrorKind::Security => "A security fault was detected.",
138 ErrorKind::ShortBuffer => "The supplied buffer is too short for the generated output.",
139 ErrorKind::ExternalCancel => "Undocumented.",
140 ErrorKind::TargetDead => "Trusted Application has panicked during the operation.",
141 ErrorKind::Unknown(_) => "Unknown error.",
142 }
143 }
144}
145
146impl Error {
147 pub fn new(kind: ErrorKind) -> Error {
148 kind.into()
149 }
150 pub fn from_raw_error(code: u32) -> Error {
161 ErrorKind::from(code).into()
162 }
163
164 pub fn with_origin(mut self, origin: ErrorOrigin) -> Self {
165 self.origin = Some(origin);
166 self
167 }
168
169 pub fn kind(&self) -> ErrorKind {
179 self.kind
180 }
181
182 pub fn origin(&self) -> Option<ErrorOrigin> {
184 self.origin.clone()
185 }
186
187 pub fn raw_code(&self) -> u32 {
189 self.kind.into()
190 }
191
192 pub fn message(&self) -> &str {
194 self.kind().as_str()
195 }
196}
197
198impl fmt::Debug for Error {
199 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
200 write!(
201 fmt,
202 "{} (error code 0x{:x}, origin 0x{:x})",
203 self.message(),
204 self.raw_code(),
205 self.origin().map(|v| v.into()).unwrap_or(0_u32),
206 )
207 }
208}
209
210impl fmt::Display for Error {
211 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
212 fmt::Debug::fmt(self, f)
213 }
214}
215
216impl std::error::Error for Error {
217 fn description(&self) -> &str {
218 self.message()
219 }
220}
221
222impl From<ErrorKind> for Error {
223 #[inline]
224 fn from(kind: ErrorKind) -> Error {
225 Error { kind, origin: None }
226 }
227}
228
229#[derive(Clone, Debug, Eq, PartialEq, FromPrimitive, IntoPrimitive)]
230#[repr(u32)]
231pub enum ErrorOrigin {
232 API = raw::TEEC_ORIGIN_API,
233 COMMS = raw::TEEC_ORIGIN_COMMS,
234 TEE = raw::TEEC_ORIGIN_TEE,
235 TA = raw::TEEC_ORIGIN_TRUSTED_APP,
236 #[default]
237 UNKNOWN,
238}
239
240#[cfg(test)]
241mod tests {
242 use super::*;
243
244 #[test]
247 fn unknown_raw_code_round_trips() {
248 let code = 0x1234_5678;
249 assert_eq!(ErrorKind::from(code), ErrorKind::Unknown(code));
250 let back: u32 = ErrorKind::Unknown(code).into();
251 assert_eq!(back, code);
252
253 let err = Error::from_raw_error(code);
254 assert_eq!(err.kind(), ErrorKind::Unknown(code));
255 assert_eq!(err.raw_code(), code);
256 }
257}