Skip to content

Commit 9bce39c

Browse files
authored
Move to non-enum Status for type safety reasons (#51)
1 parent 1ce8da3 commit 9bce39c

File tree

14 files changed

+169
-124
lines changed

14 files changed

+169
-124
lines changed

src/error/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use core::result;
22

3+
/// Definition of UEFI's standard status codes
34
mod status;
45
pub use self::status::Status;
56

src/error/status.rs

Lines changed: 96 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -5,120 +5,154 @@ use super::Result;
55
use core::ops;
66
use ucs2;
77

8-
const HIGHEST_BIT_SET: usize = !((!0_usize) >> 1);
9-
10-
/// Status codes are returned by UEFI interfaces
11-
/// to indicate whether an operation completed successfully.
8+
/// UEFI uses status codes in order to report successes, errors, and warnings.
9+
///
10+
/// Unfortunately, the spec allows and encourages implementation-specific
11+
/// non-portable status codes. Therefore, these cannot be modeled as a Rust
12+
/// enum, as injecting an unknown value in a Rust enum is undefined behaviour.
13+
///
14+
/// For lack of a better option, we therefore model them as a newtype of usize.
1215
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
13-
#[repr(usize)]
16+
#[repr(transparent)]
1417
#[must_use]
15-
pub enum Status {
18+
pub struct Status(usize);
19+
20+
/// Macro to make implementation of status codes easier
21+
macro_rules! status_codes {
22+
( $( $(#[$attr:meta])*
23+
$status:ident = $code:expr, )*
24+
) => {
25+
#[allow(unused)]
26+
impl Status {
27+
$( $(#[$attr])*
28+
pub const $status: Status = Status($code); )*
29+
}
30+
}
31+
}
32+
//
33+
status_codes! {
1634
/// The operation completed successfully.
17-
Success,
18-
/// The string contained characters that the device could not render and were skipped.
19-
WarnUnknownGlyph,
35+
SUCCESS = 0,
36+
/// The string contained characters that could not be rendered and were skipped.
37+
WARN_UNKNOWN_GLYPH = 1,
2038
/// The handle was closed, but the file was not deleted.
21-
WarnDeleteFailure,
39+
WARN_DELETE_FAILURE = 2,
2240
/// The handle was closed, but the data to the file was not flushed properly.
23-
WarnWriteFailure,
24-
/// The resulting buffer was too small,
25-
/// and the data was truncated to the buffer size.
26-
WarnBufferTooSmall,
27-
/// The data has not been updated within the timeframe
28-
/// set by local policy for this type of data.
29-
WarnStaleData,
41+
WARN_WRITE_FAILURE = 3,
42+
/// The resulting buffer was too small, and the data was truncated.
43+
WARN_BUFFER_TOO_SMALL = 4,
44+
/// The data has not been updated within the timeframe set by local policy.
45+
WARN_STALE_DATA = 5,
3046
/// The resulting buffer contains UEFI-compliant file system.
31-
WarnFileSystem,
47+
WARN_FILE_SYSTEM = 6,
3248
/// The operation will be processed across a system reset.
33-
WarnResetRequired,
49+
WARN_RESET_REQUIRED = 7,
50+
}
51+
52+
/// Bit indicating that a status code is an error
53+
const ERROR_BIT: usize = 1 << (core::mem::size_of::<usize>() * 8 - 1);
54+
55+
/// Macro to make implementation of error codes easier
56+
macro_rules! error_codes {
57+
( $( $(#[$attr:meta])*
58+
$status:ident = $error_code:expr, )*
59+
) => {
60+
status_codes! { $(
61+
$(#[$attr])*
62+
$status = $error_code | ERROR_BIT,
63+
)* }
64+
}
65+
}
66+
//
67+
error_codes! {
3468
/// The image failed to load.
35-
LoadError = 1 | HIGHEST_BIT_SET,
69+
LOAD_ERROR = 1,
3670
/// A parameter was incorrect.
37-
InvalidParameter,
71+
INVALID_PARAMETER = 2,
3872
/// The operation is not supported.
39-
Unsupported,
73+
UNSUPPORTED = 3,
4074
/// The buffer was not the proper size for the request.
41-
BadBufferSize,
75+
BAD_BUFFER_SIZE = 4,
4276
/// The buffer is not large enough to hold the requested data.
4377
/// The required buffer size is returned in the appropriate parameter.
44-
BufferTooSmall,
78+
BUFFER_TOO_SMALL = 5,
4579
/// There is no data pending upon return.
46-
NotReady,
80+
NOT_READY = 6,
4781
/// The physical device reported an error while attempting the operation.
48-
DeviceError,
82+
DEVICE_ERROR = 7,
4983
/// The device cannot be written to.
50-
WriteProtected,
84+
WRITE_PROTECTED = 8,
5185
/// A resource has run out.
52-
OutOfResources,
53-
/// An inconstancy was detected on the file system causing the operating to fail.
54-
VolumeCorrupted,
86+
OUT_OF_RESOURCES = 9,
87+
/// An inconstency was detected on the file system.
88+
VOLUME_CORRUPTED = 10,
5589
/// There is no more space on the file system.
56-
VolumeFull,
90+
VOLUME_FULL = 11,
5791
/// The device does not contain any medium to perform the operation.
58-
NoMedia,
92+
NO_MEDIA = 12,
5993
/// The medium in the device has changed since the last access.
60-
MediaChanged,
94+
MEDIA_CHANGED = 13,
6195
/// The item was not found.
62-
NotFound,
96+
NOT_FOUND = 14,
6397
/// Access was denied.
64-
AccessDenied,
98+
ACCESS_DENIED = 15,
6599
/// The server was not found or did not respond to the request.
66-
NoResponse,
100+
NO_RESPONSE = 16,
67101
/// A mapping to a device does not exist.
68-
NoMapping,
102+
NO_MAPPING = 17,
69103
/// The timeout time expired.
70-
Timeout,
104+
TIMEOUT = 18,
71105
/// The protocol has not been started.
72-
NotStarted,
106+
NOT_STARTED = 19,
73107
/// The protocol has already been started.
74-
AlreadyStarted,
108+
ALREADY_STARTED = 20,
75109
/// The operation was aborted.
76-
Aborted,
110+
ABORTED = 21,
77111
/// An ICMP error occurred during the network operation.
78-
IcmpError,
112+
ICMP_ERROR = 22,
79113
/// A TFTP error occurred during the network operation.
80-
TftpError,
114+
TFTP_ERROR = 23,
81115
/// A protocol error occurred during the network operation.
82-
ProtocolError,
116+
PROTOCOL_ERROR = 24,
83117
/// The function encountered an internal version that was
84118
/// incompatible with a version requested by the caller.
85-
IncompatibleVersion,
119+
INCOMPATIBLE_VERSION = 25,
86120
/// The function was not performed due to a security violation.
87-
SecurityViolation,
121+
SECURITY_VIOLATION = 26,
88122
/// A CRC error was detected.
89-
CrcError,
123+
CRC_ERROR = 27,
90124
/// Beginning or end of media was reached
91-
EndOfMedia,
125+
END_OF_MEDIA = 28,
92126
/// The end of the file was reached.
93-
EndOfFile = 31 | HIGHEST_BIT_SET,
127+
END_OF_FILE = 31,
94128
/// The language specified was invalid.
95-
InvalidLanguage,
129+
INVALID_LANGUAGE = 32,
96130
/// The security status of the data is unknown or compromised and
97131
/// the data must be updated or replaced to restore a valid security status.
98-
CompromisedData,
132+
COMPROMISED_DATA = 33,
99133
/// There is an address conflict address allocation
100-
IpAddressConflict,
134+
IP_ADDRESS_CONFLICT = 34,
101135
/// A HTTP error occurred during the network operation.
102-
HttpError,
136+
HTTP_ERROR = 35,
103137
}
104138

105139
impl Status {
106140
/// Returns true if status code indicates success.
107141
#[inline]
108142
pub fn is_success(self) -> bool {
109-
self == Status::Success
143+
self == Status::SUCCESS
110144
}
111145

112146
/// Returns true if status code indicates a warning.
113147
#[inline]
114148
pub fn is_warning(self) -> bool {
115-
(self as usize) & HIGHEST_BIT_SET == 0
149+
(self != Status::SUCCESS) && (self.0 & ERROR_BIT == 0)
116150
}
117151

118152
/// Returns true if the status code indicates an error.
119153
#[inline]
120154
pub fn is_error(self) -> bool {
121-
(self as usize) & HIGHEST_BIT_SET != 0
155+
self.0 & ERROR_BIT != 0
122156
}
123157

124158
/// Converts this status code into a result with a given value.
@@ -127,6 +161,7 @@ impl Status {
127161
where
128162
F: FnOnce() -> T,
129163
{
164+
// FIXME: Is that the best way to handle warnings?
130165
if self.is_success() {
131166
Ok(f())
132167
} else {
@@ -155,18 +190,18 @@ impl ops::Try for Status {
155190
}
156191

157192
fn from_ok(_: Self::Ok) -> Self {
158-
Status::Success
193+
Status::SUCCESS
159194
}
160195
}
161196

162197
impl From<ucs2::Error> for Status {
163198
fn from(other: ucs2::Error) -> Self {
164199
use ucs2::Error;
165200
match other {
166-
Error::InvalidData => Status::CompromisedData,
167-
Error::BufferUnderflow => Status::BadBufferSize,
168-
Error::BufferOverflow => Status::BufferTooSmall,
169-
Error::MultiByte => Status::Unsupported,
201+
Error::InvalidData => Status::INVALID_PARAMETER,
202+
Error::BufferUnderflow => Status::BAD_BUFFER_SIZE,
203+
Error::BufferOverflow => Status::BUFFER_TOO_SMALL,
204+
Error::MultiByte => Status::UNSUPPORTED,
170205
}
171206
}
172207
}

src/proto/console/gop.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ impl GraphicsOutput {
110110
width,
111111
height,
112112
0,
113-
).into()
113+
)
114+
.into()
114115
}
115116
BltOp::VideoToBltBuffer {
116117
buffer,
@@ -132,7 +133,8 @@ impl GraphicsOutput {
132133
width,
133134
height,
134135
0,
135-
).into(),
136+
)
137+
.into(),
136138
BltRegion::SubRectangle {
137139
coords: (dest_x, dest_y),
138140
px_stride,
@@ -147,7 +149,8 @@ impl GraphicsOutput {
147149
width,
148150
height,
149151
px_stride * core::mem::size_of::<BltPixel>(),
150-
).into(),
152+
)
153+
.into(),
151154
}
152155
}
153156
BltOp::BufferToVideo {
@@ -170,7 +173,8 @@ impl GraphicsOutput {
170173
width,
171174
height,
172175
0,
173-
).into(),
176+
)
177+
.into(),
174178
BltRegion::SubRectangle {
175179
coords: (src_x, src_y),
176180
px_stride,
@@ -185,7 +189,8 @@ impl GraphicsOutput {
185189
width,
186190
height,
187191
px_stride * core::mem::size_of::<BltPixel>(),
188-
).into(),
192+
)
193+
.into(),
189194
}
190195
}
191196
BltOp::VideoToVideo {
@@ -197,7 +202,8 @@ impl GraphicsOutput {
197202
self.check_framebuffer_region((dest_x, dest_y), (width, height));
198203
(self.blt)(
199204
self, 0usize, 3, src_x, src_y, dest_x, dest_y, width, height, 0,
200-
).into()
205+
)
206+
.into()
201207
}
202208
}
203209
}

src/proto/console/pointer/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ impl Pointer {
3737
let mut pointer_state = unsafe { mem::uninitialized() };
3838

3939
match (self.get_state)(self, &mut pointer_state) {
40-
Status::Success => Ok(Some(pointer_state)),
41-
Status::NotReady => Ok(None),
40+
Status::SUCCESS => Ok(Some(pointer_state)),
41+
Status::NOT_READY => Ok(None),
4242
error => Err(error),
4343
}
4444
}

src/proto/console/serial.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ impl Serial {
6060
mode.parity,
6161
mode.data_bits as u8,
6262
mode.stop_bits,
63-
).into()
63+
)
64+
.into()
6465
}
6566

6667
/// Sets the device's new control bits.
@@ -88,7 +89,7 @@ impl Serial {
8889
let status = (self.write)(self, &mut buffer_size, data.as_ptr());
8990

9091
match status {
91-
Status::Success | Status::Timeout => Ok(buffer_size),
92+
Status::SUCCESS | Status::TIMEOUT => Ok(buffer_size),
9293
err => Err(err),
9394
}
9495
}
@@ -104,7 +105,7 @@ impl Serial {
104105
let status = (self.read)(self, &mut buffer_size, data.as_mut_ptr());
105106

106107
match status {
107-
Status::Success | Status::Timeout => Ok(buffer_size),
108+
Status::SUCCESS | Status::TIMEOUT => Ok(buffer_size),
108109
err => Err(err),
109110
}
110111
}

src/proto/console/text/input.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ impl Input {
3434
let mut key = unsafe { mem::uninitialized() };
3535

3636
match (self.read_key_stroke)(self, &mut key) {
37-
Status::Success => Ok(Some(key)),
38-
Status::NotReady => Ok(None),
37+
Status::SUCCESS => Ok(Some(key)),
38+
Status::NOT_READY => Ok(None),
3939
error => Err(error),
4040
}
4141
}

src/proto/console/text/output.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl Output {
4646
/// some unsupported characters.
4747
pub fn test_string(&mut self, string: *const u16) -> bool {
4848
match (self.test_string)(self, string) {
49-
Status::Success => true,
49+
Status::SUCCESS => true,
5050
_ => false,
5151
}
5252
}
@@ -126,7 +126,7 @@ impl Output {
126126
let bgc = background as usize;
127127

128128
if bgc >= 8 {
129-
Err(Status::DeviceError)
129+
Err(Status::DEVICE_ERROR)
130130
} else {
131131
let attr = ((bgc & 0x7) << 4) | (fgc & 0xF);
132132
(self.set_attribute)(self, attr).into()

0 commit comments

Comments
 (0)