diff options
Diffstat (limited to 'gbl/libgbl/src/error.rs')
-rw-r--r-- | gbl/libgbl/src/error.rs | 144 |
1 files changed, 95 insertions, 49 deletions
diff --git a/gbl/libgbl/src/error.rs b/gbl/libgbl/src/error.rs index 5855d50..b4aa1f6 100644 --- a/gbl/libgbl/src/error.rs +++ b/gbl/libgbl/src/error.rs @@ -14,16 +14,21 @@ //! Error types used in libgbl. +use crate::GblOpsError; use avb::{DescriptorError, SlotVerifyError}; use core::ffi::{FromBytesUntilNulError, FromBytesWithNulError}; use core::fmt::{Debug, Display, Formatter}; +use gbl_storage::StorageError; /// Helper type GBL functions will return. -pub type Result<T> = core::result::Result<T, Error>; +pub type Result<T> = core::result::Result<T, IntegrationError>; #[derive(Debug, PartialEq)] -/// Error values that can be returned by function in this library +/// Errors originating from GBL native logic. pub enum Error { + ArithmeticOverflow, + /// Fail to hand off to kernel. + BootFailed, /// Generic error Error, /// Missing all images required to boot system @@ -37,73 +42,114 @@ pub enum Error { /// AvbOps were already borrowed. This would happen on second `load_and_verify_image()` call /// unless `reuse()` is called before. AvbOpsBusy, - /// Failed to get descriptor from AvbMeta - AvbDescriptorError(DescriptorError), - /// Avb slot verification failed. - /// SlotVerifyError is used without verify data. - AvbSlotVerifyError(SlotVerifyError<'static>), } -// Unfortunately thiserror is not available in `no_std` world. -// Thus `Display` implementation is required. impl Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { match self { + Error::ArithmeticOverflow => write!(f, "Arithmetic Overflow"), + Error::BootFailed => write!(f, "Failed to boot"), Error::Error => write!(f, "Generic error"), Error::MissingImage => write!(f, "Missing image required to boot system"), Error::NotImplemented => write!(f, "Functionality is not implemented"), Error::OperationProhibited => write!(f, "Operation is prohibited"), Error::Internal => write!(f, "Internal error"), Error::AvbOpsBusy => write!(f, "AvbOps were already borrowed"), - Error::AvbDescriptorError(error) => { - write!(f, "Failed to get descriptor from AvbMeta: {:?}", error) - } - Error::AvbSlotVerifyError(error) => { - write!(f, "Avb slot verification failed: {}", error) - } } } } -impl From<DescriptorError> for Error { - fn from(value: DescriptorError) -> Self { - Error::AvbDescriptorError(value) - } -} - -impl<'a> From<SlotVerifyError<'a>> for Error { - fn from(value: SlotVerifyError<'a>) -> Self { - Error::AvbSlotVerifyError(value.without_verify_data()) - } -} +/// A helper macro for declaring a composite enum type that simply wraps other types as entries. +/// It auto-generate `From<...>` implementation for each entry type. The type for each entry must +/// be different from each other. i.e.: +/// +/// ```rust +/// composite_enum! { +/// pub enum MyEnum { +/// Usize(usize), +/// I64(i64), +/// } +/// } +/// ``` +/// +/// expands to +/// +/// ```rust +/// pub enum MyEnum { +/// Usize(usize), +/// I64(i64), +/// } +/// +/// impl From<usize> for MyEnum { +/// fn from(ent: usize) -> MyEnum { +/// MyEnum::Usize(ent) +/// } +/// } +/// +/// impl From<i64> for MyEnum { +/// fn from(ent: i64) -> MyEnum { +/// MyEnum::I64(ent) +/// } +/// } +/// ``` +#[macro_export] +macro_rules! composite_enum { + ( + $(#[$outer:meta])* + $vis:vis enum $name:ident { + $( + $(#[$inner:ident $($args:tt)*])* + $ent:ident($ent_t:ty) + ),* + $(,)* + } + ) => { + // Copy over enum declaration as it is. + $(#[$outer])* + $vis enum $name { + $( + $(#[$inner $($args)*])* + $ent($ent_t) + ),* + } -impl From<FromBytesUntilNulError> for Error { - fn from(e: FromBytesUntilNulError) -> Self { - Error::Internal - } + // Generate `From<...>` implementation. + composite_enum!{$name, $($ent($ent_t)),*} + }; + // `From<>` implementation generation. Base case. + ($name:ident, $ent:ident($ent_t:ty)) => { + impl From<$ent_t> for $name { + fn from(ent: $ent_t) -> $name { + $name::$ent(ent) + } + } + }; + // `From<>` implementation generation. Recursive case. + ($name:ident, $ent:ident($ent_t:ty), $($next:ident($next_t:ty)),+) => { + composite_enum!{$name, $ent($ent_t)} + composite_enum!{$name, $($next($next_t)),*} + }; } -impl From<FromBytesWithNulError> for Error { - fn from(e: FromBytesWithNulError) -> Self { - Error::Internal +composite_enum! { + /// Top level error type that integrates errors from various dependency libraries. + #[derive(Debug)] + pub enum IntegrationError { + /// Failed to get descriptor from AvbMeta + AvbDescriptorError(DescriptorError), + /// Avb slot verification failed. + /// SlotVerifyError is used without verify data. + AvbSlotVerifyError(SlotVerifyError<'static>), + GblNativeError(Error), + GblOpsError(GblOpsError), + FromBytesUntilNulError(FromBytesUntilNulError), + FromBytesWithNulError(FromBytesWithNulError), + StorageError(StorageError), } } -#[cfg(test)] -mod tests { - use crate::*; - use avb::{DescriptorError, SlotVerifyError}; - - #[test] - fn test_error_output_formats() { - assert_eq!("Generic error", format!("{}", Error::Error)); - assert_eq!( - format!("Avb slot verification failed: {}", SlotVerifyError::Io), - format!("{}", Error::AvbSlotVerifyError(SlotVerifyError::Io)) - ); - assert_eq!( - format!("Failed to get descriptor from AvbMeta: {:?}", DescriptorError::InvalidValue), - format!("{}", Error::AvbDescriptorError(DescriptorError::InvalidValue)) - ); +impl Display for IntegrationError { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "{:?}", self) } } |