Skip to main content

csv_rs/
error.rs

1// Copyright (C) Hygon Info Technologies Ltd.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6use openssl::error::ErrorStack;
7use std::{
8    convert::From,
9    error,
10    fmt::{Debug, Display},
11    io,
12};
13
14/// Error conditions returned by the CSV platform or by layers above it
15/// (i.e., the Linux kernel).
16///
17/// These error conditions are documented in the HYGON CSV API spec, but
18/// their documentation has been copied here for completeness.
19#[derive(Debug)]
20#[repr(u32)]
21pub enum Error {
22    /// Something went wrong when communicating with
23    /// kernel or CSV platform
24    IoError(io::Error),
25
26    /// The platform state is invalid for this command.
27    InvalidPlatformState, // 0x0001
28
29    /// The guest state is invalid for this command.
30    InvalidGuestState, // 0x0002
31
32    /// The platform configuration is invalid.
33    InvalidConfig, // 0x0003
34
35    /// A memory buffer is too small.
36    InvalidLen, // 0x0004
37
38    /// The platform is already owned.
39    AlreadyOwned, // 0x0005
40
41    /// The certificate is invalid.
42    InvalidCertificate, // 0x0006
43
44    /// Request is not allowed by guest policy.
45    PolicyFailure, // 0x0007
46
47    /// The guest is inactive.
48    Inactive, // 0x0008
49
50    /// The address provided is invalid.
51    InvalidAddress, // 0x0009
52
53    /// The provided signature is invalid.
54    BadSignature, // 0x000A
55
56    /// The provided measurement is invalid.
57    BadMeasurement, // 0x000B
58
59    /// The ASID is already owned.
60    AsidOwned, // 0x000C
61
62    /// The ASID is invalid.
63    InvalidAsid, // 0x000D
64
65    /// WBINVD instruction required.
66    WbinvdRequired, // 0x000E
67
68    /// `DF_FLUSH` invocation required.
69    DfFlushRequired, // 0x000F
70
71    /// The guest handle is invalid.
72    InvalidGuest, // 0x0010
73
74    /// The command issued is invalid.
75    InvalidCommand, // 0x0011
76
77    /// The guest is active.
78    Active, // 0x0012
79
80    /// A hardware condition has occurred affecting the platform. It is safe
81    /// to re-allocate parameter buffers.
82    HardwarePlatform, // 0x0013
83
84    /// A hardware condition has occurred affecting the platform. Re-allocating
85    /// parameter buffers is not safe.
86    HardwareUnsafe, // 0x0014
87
88    /// Feature is unsupported.
89    Unsupported, // 0x0015
90
91    /// A given parameter is invalid.
92    InvalidParam, // 0x0016
93
94    /// The CSV firmware has run out of a resource required to carry out the
95    /// command.
96    ResourceLimit, // 0x0017
97
98    /// The CSV platform observed a failed integrity check.
99    SecureDataInvalid, // 0x0018
100
101    /// The RMP page size is incorrect.
102    InvalidPageSize, // 0x0019
103
104    /// The RMP page state is incorrect
105    InvalidPageState, // 0x001A
106
107    /// The metadata entry is invalid.
108    InvalidMdataEntry, // 0x001B
109
110    /// The page ownership is incorrect
111    InvalidPageOwner, // 0x001C
112
113    /// The AEAD algorithm would have overflowed
114    AEADOFlow, // 0x001D
115
116    /// A Mailbox mode command was sent while the CSV FW was in Ring Buffer
117    /// mode. Ring Buffer mode has been exited; the Mailbox mode command
118    /// has been ignored. Retry is recommended.
119    RbModeExited = 0x001F, // 0x001F
120
121    /// The RMP must be reinitialized.
122    RMPInitRequired = 0x0020, // 0x0020
123
124    /// SVN of provided image is lower than the committed SVN.
125    BadSvn, // 0x0021
126
127    /// Firmware version anti-rollback.
128    BadVersion, // 0x0022
129
130    /// An invocation of SNP_SHUTDOWN is required to complete this action.
131    ShutdownRequired, // 0x0023
132
133    /// Update of the firmware internal state or a guest context page has failed.
134    UpdateFailed, // 0x0024
135
136    /// Installation of the committed firmware image required
137    RestoreRequired, // 0x0025
138
139    /// The RMP initialization failed.
140    RMPInitFailed, // 0x0026
141
142    /// The key requested is invalid, not present, or not allowed.
143    InvalidKey, // 0x0027
144
145    /// Custom error message (catch-all for unclassified errors)
146    Custom(String), // 0x0028
147
148    /// Unknown error
149    Unknown, // 0x0029
150}
151
152/// There are a number of error conditions that can occur between this
153/// layer all the way down to the CSV platform. Most of these cases have
154/// been enumerated; however, there is a possibility that some error
155/// conditions are not encapsulated here.
156#[derive(Debug)]
157pub enum Indeterminate<T: Debug> {
158    /// The error condition is known.
159    Known(T),
160
161    /// The error condition is unknown.
162    Unknown,
163}
164
165impl std::fmt::Display for Error {
166    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167        let err_description = match self {
168            Error::IoError(_) => "I/O Error",
169            Error::InvalidPlatformState => "Invalid platform state",
170            Error::InvalidGuestState => "Invalid guest state",
171            Error::InvalidConfig => "Platform configuration invalid",
172            Error::InvalidLen => "Memory buffer too small",
173            Error::AlreadyOwned => "Platform is already owned",
174            Error::InvalidCertificate => "Invalid certificate",
175            Error::PolicyFailure => "Policy failure",
176            Error::Inactive => "Guest is inactive",
177            Error::InvalidAddress => "Provided address is invalid",
178            Error::BadSignature => "Provided signature is invalid",
179            Error::BadMeasurement => "Provided measurement is invalid",
180            Error::AsidOwned => "ASID is already owned",
181            Error::InvalidAsid => "ASID is invalid",
182            Error::WbinvdRequired => "WBINVD instruction required",
183            Error::DfFlushRequired => "DF_FLUSH invocation required",
184            Error::InvalidGuest => "Guest handle is invalid",
185            Error::InvalidCommand => "Issued command is invalid",
186            Error::Active => "Guest is active",
187            Error::HardwarePlatform => {
188                "Hardware condition occured, safe to re-allocate parameter buffers"
189            }
190            Error::HardwareUnsafe => {
191                "Hardware condition occured, unsafe to re-allocate parameter buffers"
192            }
193            Error::Unsupported => "Feature is unsupported",
194            Error::InvalidParam => "Given parameter is invalid",
195            Error::ResourceLimit => {
196                "CSV firmware has run out of required resources to carry out command"
197            }
198            Error::SecureDataInvalid => "CSV platform observed a failed integrity check",
199            Error::InvalidPageSize => "The RMP page size is incorrect.",
200            Error::InvalidPageState => "The RMP page state is incorrect.",
201            Error::InvalidMdataEntry => "The metadata entry is invalid.",
202            Error::InvalidPageOwner => "The page ownership is incorrect",
203            Error::AEADOFlow => "The AEAD algorithm would have overflowed.",
204            Error::RbModeExited => "A Mailbox mode command was sent while the CSV FW was in Ring Buffer \
205                                    mode. Ring Buffer mode has been exited; the Mailbox mode command has \
206                                    been ignored. Retry is recommended.",
207            Error::RMPInitRequired => "The RMP must be reinitialized.",
208            Error::BadSvn => "SVN of provided image is lower than the committed SVN",
209            Error::BadVersion => "Firmware version anti-rollback.",
210            Error::ShutdownRequired => "An invocation of SNP_SHUTDOWN is required to complete this action.",
211            Error::UpdateFailed => "Update of the firmware internal state or a guest context page has failed.",
212            Error::RestoreRequired => "Installation of the committed firmware image required.",
213            Error::RMPInitFailed => "The RMP initialization failed.",
214            Error::InvalidKey => "The key requested is invalid, not present, or not allowed",
215            Error::Custom(msg) => msg,
216            Error::Unknown => "Unknown Error",
217        };
218        write!(f, "{err_description}")
219    }
220}
221
222impl error::Error for Error {
223    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
224        match self {
225            Error::IoError(e) => Some(e),
226            _ => None,
227        }
228    }
229}
230
231impl From<io::Error> for Error {
232    #[inline]
233    fn from(error: io::Error) -> Error {
234        Error::IoError(error)
235    }
236}
237
238impl From<ErrorStack> for Error {
239    #[inline]
240    fn from(error: ErrorStack) -> Error {
241        Error::IoError(io::Error::from(error))
242    }
243}
244
245impl error::Error for Indeterminate<Error> {}
246
247impl Display for Indeterminate<Error> {
248    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
249        let err_description = match self {
250            Indeterminate::Known(error) => format!("Known Error: {error}"),
251            Indeterminate::Unknown => "Unknown Error Encountered".to_string(),
252        };
253
254        write!(f, "{err_description}")
255    }
256}
257
258impl From<io::Error> for Indeterminate<Error> {
259    #[inline]
260    fn from(error: io::Error) -> Indeterminate<Error> {
261        Indeterminate::Known(error.into())
262    }
263}
264
265impl From<u32> for Indeterminate<Error> {
266    #[inline]
267    fn from(error: u32) -> Indeterminate<Error> {
268        Indeterminate::Known(match error {
269            0x00 => io::Error::last_os_error().into(),
270            0x01 => Error::InvalidPlatformState,
271            0x02 => Error::InvalidGuestState,
272            0x03 => Error::InvalidConfig,
273            0x04 => Error::InvalidLen,
274            0x05 => Error::AlreadyOwned,
275            0x06 => Error::InvalidCertificate,
276            0x07 => Error::PolicyFailure,
277            0x08 => Error::Inactive,
278            0x09 => Error::InvalidAddress,
279            0x0A => Error::BadSignature,
280            0x0B => Error::BadMeasurement,
281            0x0C => Error::AsidOwned,
282            0x0D => Error::InvalidAsid,
283            0x0E => Error::WbinvdRequired,
284            0x0F => Error::DfFlushRequired,
285            0x10 => Error::InvalidGuest,
286            0x11 => Error::InvalidCommand,
287            0x12 => Error::Active,
288            0x13 => Error::HardwarePlatform,
289            0x14 => Error::HardwareUnsafe,
290            0x15 => Error::Unsupported,
291            0x16 => Error::InvalidParam,
292            0x17 => Error::ResourceLimit,
293            0x18 => Error::SecureDataInvalid,
294            0x19 => Error::InvalidPageSize,
295            0x1A => Error::InvalidPageState,
296            0x1B => Error::InvalidMdataEntry,
297            0x1C => Error::InvalidPageOwner,
298            0x1D => Error::AEADOFlow,
299            0x1F => Error::RbModeExited,
300            0x20 => Error::RMPInitRequired,
301            0x21 => Error::BadSvn,
302            0x22 => Error::BadVersion,
303            0x23 => Error::ShutdownRequired,
304            0x24 => Error::UpdateFailed,
305            0x25 => Error::RestoreRequired,
306            0x26 => Error::RMPInitFailed,
307            0x27 => Error::InvalidKey,
308            0x28 => Error::Custom(format!("Custom error (code: 0x{:X})", error)),
309            _ => return Indeterminate::Unknown,
310        })
311    }
312}
313
314impl From<Indeterminate<Error>> for io::Error {
315    #[inline]
316    fn from(indeterminate: Indeterminate<Error>) -> io::Error {
317        match indeterminate {
318            Indeterminate::Known(e) => io::Error::new(io::ErrorKind::Other, e),
319            Indeterminate::Unknown => io::Error::new(io::ErrorKind::Other, "unknown CSV error"),
320        }
321    }
322}
323
324impl From<Box<dyn std::error::Error + Send + Sync>> for Error {
325    fn from(e: Box<dyn std::error::Error + Send + Sync>) -> Self {
326        Error::Custom(e.to_string())
327    }
328}