Skip to content

Commit

Permalink
Use RawOsError for UEFI
Browse files Browse the repository at this point in the history
Some changes from this commit will probably be converted to its own PR.

Signed-off-by: Ayush Singh <[email protected]>
  • Loading branch information
Ayush1325 committed Sep 21, 2023
1 parent e492d9c commit d5a1806
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 178 deletions.
1 change: 1 addition & 0 deletions library/std/src/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,5 @@ pub fn log_wrapper<F: Fn(f64) -> f64>(n: f64, log_fn: F) -> f64 {
log_fn(n)
}

#[cfg(not(target_os = "uefi"))]
pub type RawOsError = i32;
176 changes: 4 additions & 172 deletions library/std/src/sys/uefi/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub(crate) fn locate_handles(mut guid: Guid) -> io::Result<Vec<NonNull<crate::ff
)
};

if r.is_error() { Err(status_to_io_error(r)) } else { Ok(()) }
if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
}

let boot_services = boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
Expand Down Expand Up @@ -99,181 +99,13 @@ pub(crate) fn open_protocol<T>(
};

if r.is_error() {
Err(status_to_io_error(r))
Err(crate::io::Error::from_raw_os_error(r.as_usize()))
} else {
NonNull::new(unsafe { protocol.assume_init() })
.ok_or(const_io_error!(io::ErrorKind::Other, "null protocol"))
}
}

pub(crate) fn status_to_io_error(s: r_efi::efi::Status) -> io::Error {
use io::ErrorKind;
use r_efi::efi::Status;

// Keep the List in Alphabetical Order
// The Messages are taken from UEFI Specification Appendix D - Status Codes
match s {
Status::ABORTED => {
const_io_error!(ErrorKind::ConnectionAborted, "The operation was aborted.")
}
Status::ACCESS_DENIED => {
const_io_error!(ErrorKind::PermissionDenied, "Access was denied.")
}
Status::ALREADY_STARTED => {
const_io_error!(ErrorKind::Other, "The protocol has already been started.")
}
Status::BAD_BUFFER_SIZE => {
const_io_error!(
ErrorKind::InvalidData,
"The buffer was not the proper size for the request."
)
}
Status::BUFFER_TOO_SMALL => {
const_io_error!(
ErrorKind::FileTooLarge,
"The buffer is not large enough to hold the requested data. The required buffer size is returned in the appropriate parameter when this error occurs."
)
}
Status::COMPROMISED_DATA => {
const_io_error!(
ErrorKind::Other,
"The security status of the data is unknown or compromised and the data must be updated or replaced to restore a valid security status."
)
}
Status::CONNECTION_FIN => {
const_io_error!(
ErrorKind::Other,
"The receiving operation fails because the communication peer has closed the connection and there is no more data in the receive buffer of the instance."
)
}
Status::CONNECTION_REFUSED => {
const_io_error!(
ErrorKind::ConnectionRefused,
"The receiving or transmission operation fails because this connection is refused."
)
}
Status::CONNECTION_RESET => {
const_io_error!(
ErrorKind::ConnectionReset,
"The connect fails because the connection is reset either by instance itself or the communication peer."
)
}
Status::CRC_ERROR => const_io_error!(ErrorKind::Other, "A CRC error was detected."),
Status::DEVICE_ERROR => const_io_error!(
ErrorKind::Other,
"The physical device reported an error while attempting the operation."
),
Status::END_OF_FILE => {
const_io_error!(ErrorKind::UnexpectedEof, "The end of the file was reached.")
}
Status::END_OF_MEDIA => {
const_io_error!(ErrorKind::Other, "Beginning or end of media was reached")
}
Status::HOST_UNREACHABLE => {
const_io_error!(ErrorKind::HostUnreachable, "The remote host is not reachable.")
}
Status::HTTP_ERROR => {
const_io_error!(ErrorKind::Other, "A HTTP error occurred during the network operation.")
}
Status::ICMP_ERROR => {
const_io_error!(
ErrorKind::Other,
"An ICMP error occurred during the network operation."
)
}
Status::INCOMPATIBLE_VERSION => {
const_io_error!(
ErrorKind::Other,
"The function encountered an internal version that was incompatible with a version requested by the caller."
)
}
Status::INVALID_LANGUAGE => {
const_io_error!(ErrorKind::InvalidData, "The language specified was invalid.")
}
Status::INVALID_PARAMETER => {
const_io_error!(ErrorKind::InvalidInput, "A parameter was incorrect.")
}
Status::IP_ADDRESS_CONFLICT => {
const_io_error!(ErrorKind::AddrInUse, "There is an address conflict address allocation")
}
Status::LOAD_ERROR => {
const_io_error!(ErrorKind::Other, "The image failed to load.")
}
Status::MEDIA_CHANGED => {
const_io_error!(
ErrorKind::Other,
"The medium in the device has changed since the last access."
)
}
Status::NETWORK_UNREACHABLE => {
const_io_error!(
ErrorKind::NetworkUnreachable,
"The network containing the remote host is not reachable."
)
}
Status::NO_MAPPING => {
const_io_error!(ErrorKind::Other, "A mapping to a device does not exist.")
}
Status::NO_MEDIA => {
const_io_error!(
ErrorKind::Other,
"The device does not contain any medium to perform the operation."
)
}
Status::NO_RESPONSE => {
const_io_error!(
ErrorKind::HostUnreachable,
"The server was not found or did not respond to the request."
)
}
Status::NOT_FOUND => const_io_error!(ErrorKind::NotFound, "The item was not found."),
Status::NOT_READY => {
const_io_error!(ErrorKind::ResourceBusy, "There is no data pending upon return.")
}
Status::NOT_STARTED => {
const_io_error!(ErrorKind::Other, "The protocol has not been started.")
}
Status::OUT_OF_RESOURCES => {
const_io_error!(ErrorKind::OutOfMemory, "A resource has run out.")
}
Status::PROTOCOL_ERROR => {
const_io_error!(
ErrorKind::Other,
"A protocol error occurred during the network operation."
)
}
Status::PROTOCOL_UNREACHABLE => {
const_io_error!(ErrorKind::Other, "An ICMP protocol unreachable error is received.")
}
Status::SECURITY_VIOLATION => {
const_io_error!(
ErrorKind::PermissionDenied,
"The function was not performed due to a security violation."
)
}
Status::TFTP_ERROR => {
const_io_error!(ErrorKind::Other, "A TFTP error occurred during the network operation.")
}
Status::TIMEOUT => const_io_error!(ErrorKind::TimedOut, "The timeout time expired."),
Status::UNSUPPORTED => {
const_io_error!(ErrorKind::Unsupported, "The operation is not supported.")
}
Status::VOLUME_FULL => {
const_io_error!(ErrorKind::StorageFull, "There is no more space on the file system.")
}
Status::VOLUME_CORRUPTED => {
const_io_error!(
ErrorKind::Other,
"An inconstancy was detected on the file system causing the operating to fail."
)
}
Status::WRITE_PROTECTED => {
const_io_error!(ErrorKind::ReadOnlyFilesystem, "The device cannot be written to.")
}
_ => io::Error::new(ErrorKind::Uncategorized, format!("Status: {}", s.as_usize())),
}
}

pub(crate) fn create_event(
signal: u32,
tpl: efi::Tpl,
Expand All @@ -288,7 +120,7 @@ pub(crate) fn create_event(
(create_event)(signal, tpl, handler, context, &mut exit_boot_service_event)
};
if r.is_error() {
Err(status_to_io_error(r))
Err(crate::io::Error::from_raw_os_error(r.as_usize()))
} else {
NonNull::new(exit_boot_service_event)
.ok_or(const_io_error!(io::ErrorKind::Other, "null protocol"))
Expand All @@ -305,5 +137,5 @@ pub(crate) unsafe fn close_event(evt: NonNull<crate::ffi::c_void>) -> io::Result
(close_event)(evt.as_ptr())
};

if r.is_error() { Err(status_to_io_error(r)) } else { Ok(()) }
if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
}
49 changes: 43 additions & 6 deletions library/std/src/sys/uefi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ pub mod locks;
pub mod net;
#[path = "../unsupported/once.rs"]
pub mod once;
#[path = "../unsupported/os.rs"]
pub mod os;
#[path = "../windows/os_str.rs"]
pub mod os_str;
Expand All @@ -52,6 +51,8 @@ mod helpers;
#[cfg(test)]
mod tests;

pub type RawOsError = usize;

use crate::cell::Cell;
use crate::io as std_io;
use crate::os::uefi;
Expand Down Expand Up @@ -110,14 +111,50 @@ pub const fn unsupported_err() -> std_io::Error {
std_io::const_io_error!(std_io::ErrorKind::Unsupported, "operation not supported on UEFI",)
}

pub fn decode_error_kind(code: i32) -> crate::io::ErrorKind {
pub fn decode_error_kind(code: RawOsError) -> crate::io::ErrorKind {
use crate::io::ErrorKind;
use r_efi::efi::Status;

if let Ok(code) = usize::try_from(code) {
helpers::status_to_io_error(Status::from_usize(code)).kind()
} else {
ErrorKind::Uncategorized
match r_efi::efi::Status::from_usize(code) {
Status::ALREADY_STARTED
| Status::COMPROMISED_DATA
| Status::CONNECTION_FIN
| Status::CRC_ERROR
| Status::DEVICE_ERROR
| Status::END_OF_MEDIA
| Status::HTTP_ERROR
| Status::ICMP_ERROR
| Status::INCOMPATIBLE_VERSION
| Status::LOAD_ERROR
| Status::MEDIA_CHANGED
| Status::NO_MAPPING
| Status::NO_MEDIA
| Status::NOT_STARTED
| Status::PROTOCOL_ERROR
| Status::PROTOCOL_UNREACHABLE
| Status::TFTP_ERROR
| Status::VOLUME_CORRUPTED => ErrorKind::Other,
Status::BAD_BUFFER_SIZE | Status::INVALID_LANGUAGE => ErrorKind::InvalidData,
Status::ABORTED => ErrorKind::ConnectionAborted,
Status::ACCESS_DENIED => ErrorKind::PermissionDenied,
Status::BUFFER_TOO_SMALL => ErrorKind::FileTooLarge,
Status::CONNECTION_REFUSED => ErrorKind::ConnectionRefused,
Status::CONNECTION_RESET => ErrorKind::ConnectionReset,
Status::END_OF_FILE => ErrorKind::UnexpectedEof,
Status::HOST_UNREACHABLE => ErrorKind::HostUnreachable,
Status::INVALID_PARAMETER => ErrorKind::InvalidInput,
Status::IP_ADDRESS_CONFLICT => ErrorKind::AddrInUse,
Status::NETWORK_UNREACHABLE => ErrorKind::NetworkUnreachable,
Status::NO_RESPONSE => ErrorKind::HostUnreachable,
Status::NOT_FOUND => ErrorKind::NotFound,
Status::NOT_READY => ErrorKind::ResourceBusy,
Status::OUT_OF_RESOURCES => ErrorKind::OutOfMemory,
Status::SECURITY_VIOLATION => ErrorKind::PermissionDenied,
Status::TIMEOUT => ErrorKind::TimedOut,
Status::UNSUPPORTED => ErrorKind::Unsupported,
Status::VOLUME_FULL => ErrorKind::StorageFull,
Status::WRITE_PROTECTED => ErrorKind::ReadOnlyFilesystem,
_ => ErrorKind::Uncategorized,
}
}

Expand Down
Loading

0 comments on commit d5a1806

Please sign in to comment.