uefi/
status.rs

1// SPDX-License-Identifier: MIT
2
3//! # Status codes
4//!
5//! Status codes for UEFI interfaces.
6//!
7//! Most `usize` values can represent a valid status, but only a few are
8//! defined by the UEFI specification. Ranges are reserved for use by the UEFI
9//! specification itself, the [Platform Initialization specification][PI Spec],
10//! and OEM usage. On a 64-bit platform, these ranges are:
11//!
12//! | Start                   | End                     | Usage         |
13//! | ----------------------- | ----------------------- | ------------- |
14//! | `0x0000_0000_0000_0000` | `0x1FFF_FFFF_FFFF_FFFF` | UEFI warnings |
15//! | `0x2000_0000_0000_0000` | `0x3FFF_FFFF_FFFF_FFFF` | PI warnings   |
16//! | `0x4000_0000_0000_0000` | `0x7FFF_FFFF_FFFF_FFFF` | OEM warnings  |
17//! | `0x8000_0000_0000_0000` | `0x9FFF_FFFF_FFFF_FFFF` | UEFI errors   |
18//! | `0xA000_0000_0000_0000` | `0xBFFF_FFFF_FFFF_FFFF` | PI errors     |
19//! | `0xC000_0000_0000_0000` | `0xCFFF_FFFF_FFFF_FFFF` | OEM errors    |
20//!
21//! Error codes always have the highest bit set, while success and warnings
22//! always have the highest bit cleared.
23//!
24//! ## References
25//!
26//! - [UEFI Specification, Version 2.9][UEFI Spec]: Appendix D - Status Codes
27//!
28//! [PI Spec]: https://uefi.org/sites/default/files/resources/PI_Spec_1_7_A_final_May1.pdf
29//! [UEFI Spec]: https://uefi.org/sites/default/files/resources/UEFI_Spec_2_9_2021_03_18.pdf
30
31use core::fmt;
32
33/// A value that represents success, a warning, or an error.
34#[must_use]
35#[repr(transparent)]
36#[derive(Copy, Clone, Debug, Eq, PartialEq)]
37pub struct Status(pub usize);
38
39impl Status {
40    pub const ERROR_BIT: usize = 1 << (usize::BITS - 1);
41
42    // Success codes
43    /// The operation completed successfully.
44    pub const SUCCESS: Self = Self(0);
45
46    // Warning codes
47    /// The string contained one or more characters that the device could not
48    /// render and were skipped.
49    pub const WARN_UNKNOWN_GLYPH: Self = Self(1);
50    /// The handle was closed, but the file was not deleted.
51    pub const WARN_DELETE_FAILURE: Self = Self(2);
52    /// The handle was closed, but the data to the file was not flushed.
53    pub const WARN_WRITE_FAILURE: Self = Self(3);
54    /// The resulting buffer was too small, and the data was truncated to fit.
55    pub const WARN_BUFFER_TOO_SMALL: Self = Self(4);
56    /// The data has not been updated without the timeframe set by local policy
57    /// for this type of data.
58    pub const WARN_STALE_DATA: Self = Self(5);
59    /// The resulting buffer contains a UEFI-compliant file system.
60    pub const WARN_FILE_SYSTEM: Self = Self(6);
61    /// The operation will be processed across a system reset.
62    pub const WARN_RESET_REQUIRED: Self = Self(7);
63
64    // Error codes
65    /// The image failed to load.
66    pub const LOAD_ERROR: Self = Self(Self::ERROR_BIT | 1);
67    /// A parameter was incorrect.
68    pub const INVALID_PARAMETER: Self = Self(Self::ERROR_BIT | 2);
69    /// The operation is not supported.
70    pub const UNSUPPORTED: Self = Self(Self::ERROR_BIT | 3);
71    /// The buffer was not the proper size for the request.
72    pub const BAD_BUFFER_SIZE: Self = Self(Self::ERROR_BIT | 4);
73    /// The buffer is not large enough to hold the requested data.
74    pub const BUFFER_TOO_SMALL: Self = Self(Self::ERROR_BIT | 5);
75    /// There is no data pending upon return.
76    pub const NOT_READY: Self = Self(Self::ERROR_BIT | 6);
77    /// The physical device reported an error while attempting the operation.
78    pub const DEVICE_ERROR: Self = Self(Self::ERROR_BIT | 7);
79    /// The device cannot be written to.
80    pub const WRITE_PROTECTED: Self = Self(Self::ERROR_BIT | 8);
81    /// A resource has run out.
82    pub const OUT_OF_RESOURCES: Self = Self(Self::ERROR_BIT | 9);
83    /// An inconsistency was detected on the file system.
84    pub const VOLUME_CORRUPTED: Self = Self(Self::ERROR_BIT | 10);
85    /// There is no more space on the file system.
86    pub const VOLUME_FULL: Self = Self(Self::ERROR_BIT | 11);
87    /// The device does not contain any medium to perform the operation.
88    pub const NO_MEDIA: Self = Self(Self::ERROR_BIT | 12);
89    /// The medium in the device has changed since the last access.
90    pub const MEDIA_CHANGED: Self = Self(Self::ERROR_BIT | 13);
91    /// The item was not found.
92    pub const NOT_FOUND: Self = Self(Self::ERROR_BIT | 14);
93    /// Access was denied.
94    pub const ACCESS_DENIED: Self = Self(Self::ERROR_BIT | 15);
95    /// The server was not found or did not respond to the request.
96    pub const NO_RESPONSE: Self = Self(Self::ERROR_BIT | 16);
97    /// A mapping to a device does not exist.
98    pub const NO_MAPPING: Self = Self(Self::ERROR_BIT | 17);
99    /// The timeout time expired.
100    pub const TIMEOUT: Self = Self(Self::ERROR_BIT | 18);
101    /// The protocol has not been started.
102    pub const NOT_STARTED: Self = Self(Self::ERROR_BIT | 19);
103    /// The protocol has already been started.
104    pub const ALREADY_STARTED: Self = Self(Self::ERROR_BIT | 20);
105    /// The operation was aborted.
106    pub const ABORTED: Self = Self(Self::ERROR_BIT | 21);
107    /// An ICMP error occurred during the network operation.
108    pub const ICMP_ERROR: Self = Self(Self::ERROR_BIT | 22);
109    /// A TFTP error occurred during the network operation.
110    pub const TFTP_ERROR: Self = Self(Self::ERROR_BIT | 23);
111    /// A protocol error occurred during the network operation.
112    pub const PROTOCOL_ERROR: Self = Self(Self::ERROR_BIT | 24);
113    /// The function encountered an internal version that was incompatible with
114    /// a version requested by the caller.
115    pub const INCOMPATIBLE_VERSION: Self = Self(Self::ERROR_BIT | 25);
116    /// The function was not performed due to a security violation.
117    pub const SECURITY_VIOLATION: Self = Self(Self::ERROR_BIT | 26);
118    /// A CRC error was detected.
119    pub const CRC_ERROR: Self = Self(Self::ERROR_BIT | 27);
120    /// Beginning or end of media was reached.
121    pub const END_OF_MEDIA: Self = Self(Self::ERROR_BIT | 28);
122    // No meaning defined for 29-30.
123    /// The end of the file was reached.
124    pub const END_OF_FILE: Self = Self(Self::ERROR_BIT | 31);
125    /// The language specified was invalid.
126    pub const INVALID_LANGUAGE: Self = Self(Self::ERROR_BIT | 32);
127    /// The security status of the data is unknown or compromised and the data
128    /// must be updated or replaced to restore a valid security status.
129    pub const COMPROMISED_DATA: Self = Self(Self::ERROR_BIT | 33);
130    /// There is an address conflict allocation.
131    pub const IP_ADDRESS_CONFLICT: Self = Self(Self::ERROR_BIT | 34);
132    /// An HTTP error occurred during the network operation.
133    pub const HTTP_ERROR: Self = Self(Self::ERROR_BIT | 35);
134
135    /// Returns true if the value represents a success.
136    pub fn is_success(&self) -> bool {
137        self == &Self::SUCCESS
138    }
139
140    /// Returns true if the value represents an error.
141    pub fn is_error(&self) -> bool {
142        (self.0 & Self::ERROR_BIT) == Self::ERROR_BIT
143    }
144
145    /// Returns true if the value represents a warning.
146    pub fn is_warning(&self) -> bool {
147        !self.is_error() && !self.is_success()
148    }
149}
150
151impl From<usize> for Status {
152    fn from(value: usize) -> Self {
153        Self(value)
154    }
155}
156
157impl fmt::Display for Status {
158    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159        match *self {
160            Self::SUCCESS => write!(f, "success"),
161
162            Self::WARN_UNKNOWN_GLYPH => write!(f, "unknown glyph"),
163            Self::WARN_DELETE_FAILURE => write!(f, "delete failure"),
164            Self::WARN_WRITE_FAILURE => write!(f, "write failure"),
165            Self::WARN_STALE_DATA => write!(f, "stale data"),
166            Self::WARN_FILE_SYSTEM => write!(f, "file system"),
167            Self::WARN_RESET_REQUIRED => write!(f, "reset required"),
168
169            Self::LOAD_ERROR => write!(f, "load error"),
170            Self::INVALID_PARAMETER => write!(f, "invalid paramter"),
171            Self::UNSUPPORTED => write!(f, "unsupported"),
172            Self::BAD_BUFFER_SIZE => write!(f, "bad buffer size"),
173            Self::WARN_BUFFER_TOO_SMALL | Self::BUFFER_TOO_SMALL => write!(f, "buffer too small"),
174            Self::NOT_READY => write!(f, "not ready"),
175            Self::DEVICE_ERROR => write!(f, "device error"),
176            Self::WRITE_PROTECTED => write!(f, "write protected"),
177            Self::OUT_OF_RESOURCES => write!(f, "out of resources"),
178            Self::VOLUME_CORRUPTED => write!(f, "volume corrupted"),
179            Self::VOLUME_FULL => write!(f, "volume full"),
180            Self::NO_MEDIA => write!(f, "no media"),
181            Self::MEDIA_CHANGED => write!(f, "media changed"),
182            Self::NOT_FOUND => write!(f, "not found"),
183            Self::ACCESS_DENIED => write!(f, "acccess denied"),
184            Self::NO_RESPONSE => write!(f, "no response"),
185            Self::NO_MAPPING => write!(f, "no mapping"),
186            Self::TIMEOUT => write!(f, "timeout"),
187            Self::NOT_STARTED => write!(f, "not started"),
188            Self::ALREADY_STARTED => write!(f, "already started"),
189            Self::ABORTED => write!(f, "aborted"),
190            Self::ICMP_ERROR => write!(f, "ICMP error"),
191            Self::TFTP_ERROR => write!(f, "TFTP error"),
192            Self::PROTOCOL_ERROR => write!(f, "protocol error"),
193            Self::INCOMPATIBLE_VERSION => write!(f, "incompatible version"),
194            Self::SECURITY_VIOLATION => write!(f, "security violation"),
195            Self::CRC_ERROR => write!(f, "CRC error"),
196            Self::END_OF_MEDIA => write!(f, "end of media"),
197            Self::END_OF_FILE => write!(f, "end of file"),
198            Self::INVALID_LANGUAGE => write!(f, "invalid language"),
199            Self::COMPROMISED_DATA => write!(f, "compromised data"),
200            Self::IP_ADDRESS_CONFLICT => write!(f, "IP address conflict"),
201            Self::HTTP_ERROR => write!(f, "HTTP error"),
202
203            _ => write!(f, "{:#X}", self.0),
204        }
205    }
206}
207
208impl fmt::LowerHex for Status {
209    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
210        fmt::LowerHex::fmt(&self.0, f)
211    }
212}
213
214impl fmt::UpperHex for Status {
215    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
216        fmt::UpperHex::fmt(&self.0, f)
217    }
218}
219
220pub type Result<T> = core::result::Result<T, Status>;
221
222impl From<Status> for Result<()> {
223    fn from(status: Status) -> Self {
224        match status {
225            Status::SUCCESS => Ok(()),
226            e => Err(e),
227        }
228    }
229}
230
231impl<T> From<Result<T>> for Status {
232    fn from(res: Result<T>) -> Self {
233        match res {
234            Ok(_) => Status::SUCCESS,
235            Err(e) => e,
236        }
237    }
238}