1 // Copyright 2023, 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 //! Error types used in libgbl.
16 
17 use crate::GblOpsError;
18 use avb::{DescriptorError, SlotVerifyError};
19 use core::ffi::{FromBytesUntilNulError, FromBytesWithNulError};
20 use core::fmt::{Debug, Display, Formatter};
21 use gbl_storage::StorageError;
22 
23 /// Helper type GBL functions will return.
24 pub type Result<T> = core::result::Result<T, IntegrationError>;
25 
26 #[derive(Debug, PartialEq, Eq)]
27 /// Errors originating from GBL native logic.
28 pub enum Error {
29     ArithmeticOverflow,
30     /// Fail to hand off to kernel.
31     BootFailed,
32     /// Generic error
33     Error,
34     /// Missing all images required to boot system
35     MissingImage,
36     /// Functionality is not implemented
37     NotImplemented,
38     /// Some combination of parameters and global state prohibits the operation
39     OperationProhibited,
40     /// Internal error
41     Internal,
42     /// AvbOps were already borrowed. This would happen on second `load_and_verify_image()` call
43     /// unless `reuse()` is called before.
44     AvbOpsBusy,
45     /// Buffers overlap and can cause undefined behavior and data corruption.
46     BufferOverlap,
47 }
48 
49 impl Display for Error {
fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result50     fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
51         match self {
52             Error::ArithmeticOverflow => write!(f, "Arithmetic Overflow"),
53             Error::BootFailed => write!(f, "Failed to boot"),
54             Error::Error => write!(f, "Generic error"),
55             Error::MissingImage => write!(f, "Missing image required to boot system"),
56             Error::NotImplemented => write!(f, "Functionality is not implemented"),
57             Error::OperationProhibited => write!(f, "Operation is prohibited"),
58             Error::Internal => write!(f, "Internal error"),
59             Error::AvbOpsBusy => write!(f, "AvbOps were already borrowed"),
60             Error::BufferOverlap => write!(f, "Buffers overlap"),
61         }
62     }
63 }
64 
65 /// A helper macro for declaring a composite enum type that simply wraps other types as entries.
66 /// It auto-generate `From<...>` implementation for each entry type. The type for each entry must
67 /// be different from each other. i.e.:
68 ///
69 /// ```rust
70 ///   composite_enum! {
71 ///       pub enum MyEnum {
72 ///           Usize(usize),
73 ///           I64(i64),
74 ///       }
75 ///   }
76 /// ```
77 ///
78 /// expands to
79 ///
80 /// ```rust
81 ///   pub enum MyEnum {
82 ///       Usize(usize),
83 ///       I64(i64),
84 ///   }
85 ///
86 ///   impl From<usize> for MyEnum {
87 ///       fn from(ent: usize) -> MyEnum {
88 ///           MyEnum::Usize(ent)
89 ///       }
90 ///   }
91 ///
92 ///   impl From<i64> for MyEnum {
93 ///       fn from(ent: i64) -> MyEnum {
94 ///           MyEnum::I64(ent)
95 ///       }
96 ///   }
97 /// ```
98 #[macro_export]
99 macro_rules! composite_enum {
100     (
101         $(#[$outer:meta])*
102         $vis:vis enum $name:ident {
103             $(
104                 $(#[$inner:ident $($args:tt)*])*
105                 $ent:ident($ent_t:ty)
106             ),*
107             $(,)*
108         }
109     ) => {
110         // Copy over enum declaration as it is.
111         $(#[$outer])*
112         $vis enum $name {
113             $(
114                 $(#[$inner $($args)*])*
115                 $ent($ent_t)
116             ),*
117         }
118 
119         // Generate `From<...>` implementation.
120         composite_enum!{$name,  $($ent($ent_t)),*}
121     };
122     // `From<>` implementation generation. Base case.
123     ($name:ident, $ent:ident($ent_t:ty)) => {
124         impl From<$ent_t> for $name {
125             fn from(ent: $ent_t) -> $name {
126                 $name::$ent(ent)
127             }
128         }
129     };
130     // `From<>` implementation generation. Recursive case.
131     ($name:ident, $ent:ident($ent_t:ty), $($next:ident($next_t:ty)),+) => {
132         composite_enum!{$name, $ent($ent_t)}
133         composite_enum!{$name, $($next($next_t)),*}
134     };
135 }
136 
137 composite_enum! {
138     /// Top level error type that integrates errors from various dependency libraries.
139     #[derive(Debug, PartialEq, Eq)]
140     pub enum IntegrationError {
141         /// Failed to get descriptor from AvbMeta
142         AvbDescriptorError(DescriptorError),
143         /// Avb slot verification failed.
144         /// SlotVerifyError is used without verify data.
145         AvbSlotVerifyError(SlotVerifyError<'static>),
146         GblNativeError(Error),
147         GblOpsError(GblOpsError),
148         FromBytesUntilNulError(FromBytesUntilNulError),
149         FromBytesWithNulError(FromBytesWithNulError),
150         StorageError(StorageError),
151         SafeMathError(safemath::Error),
152     }
153 }
154 
155 impl Display for IntegrationError {
fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result156     fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
157         write!(f, "{:?}", self)
158     }
159 }
160