diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index c598def9fb2a8..d547f57693305 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -114,4 +114,5 @@ pub fn log_wrapper f64>(n: f64, log_fn: F) -> f64 { log_fn(n) } +#[cfg(not(target_os = "uefi"))] pub type RawOsError = i32; diff --git a/library/std/src/sys/uefi/helpers.rs b/library/std/src/sys/uefi/helpers.rs index ea1c68a90ef83..2e1bcb369447e 100644 --- a/library/std/src/sys/uefi/helpers.rs +++ b/library/std/src/sys/uefi/helpers.rs @@ -43,7 +43,7 @@ pub(crate) fn locate_handles(mut guid: Guid) -> io::Result( }; 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, @@ -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")) @@ -305,5 +137,5 @@ pub(crate) unsafe fn close_event(evt: NonNull) -> 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(()) } } diff --git a/library/std/src/sys/uefi/mod.rs b/library/std/src/sys/uefi/mod.rs index 27f76f04c05aa..85d00caf14911 100644 --- a/library/std/src/sys/uefi/mod.rs +++ b/library/std/src/sys/uefi/mod.rs @@ -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; @@ -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; @@ -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, } } diff --git a/library/std/src/sys/uefi/os.rs b/library/std/src/sys/uefi/os.rs new file mode 100644 index 0000000000000..cd489d8f7f9c6 --- /dev/null +++ b/library/std/src/sys/uefi/os.rs @@ -0,0 +1,213 @@ +use super::{unsupported, RawOsError}; +use crate::error::Error as StdError; +use crate::ffi::{OsStr, OsString}; +use crate::fmt; +use crate::io; +use crate::marker::PhantomData; +use crate::path::{self, PathBuf}; + +pub fn errno() -> RawOsError { + 0 +} + +pub fn error_string(errno: RawOsError) -> String { + use r_efi::efi::Status; + + // Keep the List in Alphabetical Order + // The Messages are taken from UEFI Specification Appendix D - Status Codes + match r_efi::efi::Status::from_usize(errno) { + Status::ABORTED => "The operation was aborted.".to_owned(), + Status::ACCESS_DENIED => "Access was denied.".to_owned(), + Status::ALREADY_STARTED => "The protocol has already been started.".to_owned(), + Status::BAD_BUFFER_SIZE => "The buffer was not the proper size for the request.".to_owned(), + Status::BUFFER_TOO_SMALL => { + "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.".to_owned() + } + Status::COMPROMISED_DATA => { + "The security status of the data is unknown or compromised and the data must be updated or replaced to restore a valid security status.".to_owned() + } + Status::CONNECTION_FIN => { + "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.".to_owned() + } + Status::CONNECTION_REFUSED => { + "The receiving or transmission operation fails because this connection is refused.".to_owned() + } + Status::CONNECTION_RESET => { + "The connect fails because the connection is reset either by instance itself or the communication peer.".to_owned() + } + Status::CRC_ERROR => "A CRC error was detected.".to_owned(), + Status::DEVICE_ERROR => "The physical device reported an error while attempting the operation.".to_owned() + , + Status::END_OF_FILE => { + "The end of the file was reached.".to_owned() + } + Status::END_OF_MEDIA => { + "Beginning or end of media was reached".to_owned() + } + Status::HOST_UNREACHABLE => { + "The remote host is not reachable.".to_owned() + } + Status::HTTP_ERROR => { + "A HTTP error occurred during the network operation.".to_owned() + } + Status::ICMP_ERROR => { + "An ICMP error occurred during the network operation.".to_owned() + } + Status::INCOMPATIBLE_VERSION => { + "The function encountered an internal version that was incompatible with a version requested by the caller.".to_owned() + } + Status::INVALID_LANGUAGE => { + "The language specified was invalid.".to_owned() + } + Status::INVALID_PARAMETER => { + "A parameter was incorrect.".to_owned() + } + Status::IP_ADDRESS_CONFLICT => { + "There is an address conflict address allocation".to_owned() + } + Status::LOAD_ERROR => { + "The image failed to load.".to_owned() + } + Status::MEDIA_CHANGED => { + "The medium in the device has changed since the last access.".to_owned() + } + Status::NETWORK_UNREACHABLE => { + "The network containing the remote host is not reachable.".to_owned() + } + Status::NO_MAPPING => { + "A mapping to a device does not exist.".to_owned() + } + Status::NO_MEDIA => { + "The device does not contain any medium to perform the operation.".to_owned() + } + Status::NO_RESPONSE => { + "The server was not found or did not respond to the request.".to_owned() + } + Status::NOT_FOUND => "The item was not found.".to_owned(), + Status::NOT_READY => { + "There is no data pending upon return.".to_owned() + } + Status::NOT_STARTED => { + "The protocol has not been started.".to_owned() + } + Status::OUT_OF_RESOURCES => { + "A resource has run out.".to_owned() + } + Status::PROTOCOL_ERROR => { + "A protocol error occurred during the network operation.".to_owned() + } + Status::PROTOCOL_UNREACHABLE => { + "An ICMP protocol unreachable error is received.".to_owned() + } + Status::SECURITY_VIOLATION => { + "The function was not performed due to a security violation.".to_owned() + } + Status::TFTP_ERROR => { + "A TFTP error occurred during the network operation.".to_owned() + } + Status::TIMEOUT => "The timeout time expired.".to_owned(), + Status::UNSUPPORTED => { + "The operation is not supported.".to_owned() + } + Status::VOLUME_FULL => { + "There is no more space on the file system.".to_owned() + } + Status::VOLUME_CORRUPTED => { + "An inconstancy was detected on the file system causing the operating to fail.".to_owned() + } + Status::WRITE_PROTECTED => { + "The device cannot be written to.".to_owned() + } + _ => format!("Status: {}", errno), + } +} + +pub fn getcwd() -> io::Result { + unsupported() +} + +pub fn chdir(_: &path::Path) -> io::Result<()> { + unsupported() +} + +pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); + +pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { + panic!("unsupported") +} + +impl<'a> Iterator for SplitPaths<'a> { + type Item = PathBuf; + fn next(&mut self) -> Option { + self.0 + } +} + +#[derive(Debug)] +pub struct JoinPathsError; + +pub fn join_paths(_paths: I) -> Result +where + I: Iterator, + T: AsRef, +{ + Err(JoinPathsError) +} + +impl fmt::Display for JoinPathsError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + "not supported on this platform yet".fmt(f) + } +} + +impl StdError for JoinPathsError { + #[allow(deprecated)] + fn description(&self) -> &str { + "not supported on this platform yet" + } +} + +pub fn current_exe() -> io::Result { + unsupported() +} + +pub struct Env(!); + +impl Iterator for Env { + type Item = (OsString, OsString); + fn next(&mut self) -> Option<(OsString, OsString)> { + self.0 + } +} + +pub fn env() -> Env { + panic!("not supported on this platform") +} + +pub fn getenv(_: &OsStr) -> Option { + None +} + +pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { + Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform")) +} + +pub fn unsetenv(_: &OsStr) -> io::Result<()> { + Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform")) +} + +pub fn temp_dir() -> PathBuf { + panic!("no filesystem on this platform") +} + +pub fn home_dir() -> Option { + None +} + +pub fn exit(_code: i32) -> ! { + crate::intrinsics::abort() +} + +pub fn getpid() -> u32 { + panic!("no pids on this platform") +}