Skip to content

Commit 4f7ff72

Browse files
committed
Fixes from PR
1. Make Event *mut c_void. 2. Better error messages. 3. Use OnceLock instead of OnceCell in tcp4 4. Fix File::create_new 5. Performance improvements in `sys::args` and `sys::time::Instant` 6. Only use 2 events in tcp4 now. 7. Fix incorrect uses of `size_of_val`. 8. Fix UEFI CI Signed-off-by: Ayush Singh <[email protected]>
1 parent 195633a commit 4f7ff72

File tree

8 files changed

+227
-219
lines changed

8 files changed

+227
-219
lines changed

library/std/src/sys/uefi/args.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::env::current_exe;
55
use crate::ffi::OsString;
66
use crate::fmt;
77
use crate::path::PathBuf;
8+
use crate::sync::OnceLock;
89
use crate::sys_common::args::{parse_lp_cmd_line, WStrUnits};
910
use crate::vec;
1011
use r_efi::efi::protocols::loaded_image;
@@ -16,19 +17,22 @@ pub struct Args {
1617
// Get the Supplied arguments for loaded image.
1718
// Uses EFI_LOADED_IMAGE_PROTOCOL
1819
pub fn args() -> Args {
19-
match common::get_current_handle_protocol::<loaded_image::Protocol>(loaded_image::PROTOCOL_GUID)
20-
{
21-
Some(x) => {
22-
let lp_cmd_line = unsafe { (*x.as_ptr()).load_options as *const u16 };
23-
let parsed_args_list =
20+
static ARGUMENTS: OnceLock<Vec<OsString>> = OnceLock::new();
21+
// Caching the arguments the first time they are parsed.
22+
let vec_args = ARGUMENTS.get_or_init(|| {
23+
match common::get_current_handle_protocol::<loaded_image::Protocol>(
24+
loaded_image::PROTOCOL_GUID,
25+
) {
26+
Some(x) => {
27+
let lp_cmd_line = unsafe { (*x.as_ptr()).load_options as *const u16 };
2428
parse_lp_cmd_line(unsafe { WStrUnits::new(lp_cmd_line) }, || {
2529
current_exe().map(PathBuf::into_os_string).unwrap_or_else(|_| OsString::new())
26-
});
27-
28-
Args { parsed_args_list: parsed_args_list.into_iter() }
30+
})
31+
}
32+
None => Vec::new(),
2933
}
30-
None => Args { parsed_args_list: Vec::new().into_iter() },
31-
}
34+
});
35+
Args { parsed_args_list: vec_args.clone().into_iter() }
3236
}
3337

3438
impl fmt::Debug for Args {

library/std/src/sys/uefi/common.rs

Lines changed: 99 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,10 @@ pub(crate) fn get_current_handle_protocol<T>(protocol_guid: Guid) -> Option<NonN
1717

1818
#[repr(transparent)]
1919
pub(crate) struct Event {
20-
inner: NonNull<crate::ffi::c_void>,
20+
inner: r_efi::efi::Event,
2121
}
2222

2323
impl Event {
24-
#[inline]
25-
fn new(inner: NonNull<crate::ffi::c_void>) -> Self {
26-
Self { inner }
27-
}
28-
29-
#[inline]
30-
fn from_raw_event(ptr: r_efi::efi::Event) -> Option<Self> {
31-
Some(Self::new(NonNull::new(ptr)?))
32-
}
33-
3424
pub(crate) fn create(
3525
event_type: u32,
3626
event_tpl: Tpl,
@@ -55,12 +45,7 @@ impl Event {
5545
)
5646
};
5747

58-
if r.is_error() {
59-
Err(status_to_io_error(r))
60-
} else {
61-
Self::from_raw_event(event)
62-
.ok_or(const_io_error!(io::ErrorKind::Other, "event is null"))
63-
}
48+
if r.is_error() { Err(status_to_io_error(r)) } else { Ok(Self { inner: event }) }
6449
}
6550

6651
pub(crate) fn create_timer() -> io::Result<Event> {
@@ -117,17 +102,17 @@ impl Event {
117102

118103
#[inline]
119104
pub(crate) fn as_raw_event(&self) -> r_efi::efi::Event {
120-
self.inner.as_ptr()
105+
self.inner
121106
}
122107
}
123108

124-
extern "efiapi" fn empty_notify(_: r_efi::efi::Event, _: *mut crate::ffi::c_void) {}
109+
pub(crate) extern "efiapi" fn empty_notify(_: r_efi::efi::Event, _: *mut crate::ffi::c_void) {}
125110

126111
impl Drop for Event {
127112
fn drop(&mut self) {
128113
let boot_services = boot_services();
129114
// Always returns EFI_SUCCESS
130-
let _ = unsafe { ((*boot_services.as_ptr()).close_event)(self.inner.as_ptr()) };
115+
let _ = unsafe { ((*boot_services.as_ptr()).close_event)(self.inner) };
131116
}
132117
}
133118

@@ -296,109 +281,164 @@ pub(crate) fn status_to_io_error(s: r_efi::efi::Status) -> io::Error {
296281
use r_efi::efi::Status;
297282

298283
// Keep the List in Alphabetical Order
284+
// The Messages are taken from UEFI Specification Appendix D - Status Codes
299285
match s {
300286
Status::ABORTED => {
301-
const_io_error!(ErrorKind::ConnectionAborted, "EFI_ABORTED")
287+
const_io_error!(ErrorKind::ConnectionAborted, "The operation was aborted.")
302288
}
303289
Status::ACCESS_DENIED => {
304-
const_io_error!(ErrorKind::PermissionDenied, "EFI_ACCESS_DENIED")
290+
const_io_error!(ErrorKind::PermissionDenied, "Access was denied.")
305291
}
306292
Status::ALREADY_STARTED => {
307-
const_io_error!(ErrorKind::Other, "EFI_ALREADY_STARTED")
293+
const_io_error!(ErrorKind::Other, "The protocol has already been started.")
308294
}
309295
Status::BAD_BUFFER_SIZE => {
310-
const_io_error!(ErrorKind::InvalidData, "EFI_BAD_BUFFER_SIZE")
296+
const_io_error!(
297+
ErrorKind::InvalidData,
298+
"The buffer was not the proper size for the request."
299+
)
311300
}
312301
Status::BUFFER_TOO_SMALL => {
313-
const_io_error!(ErrorKind::FileTooLarge, "EFI_BUFFER_TOO_SMALL")
302+
const_io_error!(
303+
ErrorKind::FileTooLarge,
304+
"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."
305+
)
314306
}
315307
Status::COMPROMISED_DATA => {
316-
const_io_error!(ErrorKind::Other, "EFI_COMPRIMISED_DATA")
308+
const_io_error!(
309+
ErrorKind::Other,
310+
"The security status of the data is unknown or compromised and the data must be updated or replaced to restore a valid security status."
311+
)
317312
}
318313
Status::CONNECTION_FIN => {
319-
const_io_error!(ErrorKind::Other, "EFI_CONNECTION_FIN")
314+
const_io_error!(
315+
ErrorKind::Other,
316+
"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."
317+
)
320318
}
321319
Status::CONNECTION_REFUSED => {
322-
const_io_error!(ErrorKind::ConnectionRefused, "EFI_CONNECTION_REFUSED")
320+
const_io_error!(
321+
ErrorKind::ConnectionRefused,
322+
"The receiving or transmission operation fails because this connection is refused."
323+
)
323324
}
324325
Status::CONNECTION_RESET => {
325-
const_io_error!(ErrorKind::ConnectionReset, "EFI_CONNECTION_RESET")
326+
const_io_error!(
327+
ErrorKind::ConnectionReset,
328+
"The connect fails because the connection is reset either by instance itself or the communication peer."
329+
)
326330
}
327-
Status::CRC_ERROR => const_io_error!(ErrorKind::InvalidData, "EFI_CRC_ERROR"),
328-
Status::DEVICE_ERROR => const_io_error!(ErrorKind::Other, "EFI_DEVICE_ERROR"),
331+
Status::CRC_ERROR => const_io_error!(ErrorKind::Other, "A CRC error was detected."),
332+
Status::DEVICE_ERROR => const_io_error!(
333+
ErrorKind::Other,
334+
"The physical device reported an error while attempting the operation."
335+
),
329336
Status::END_OF_FILE => {
330-
const_io_error!(ErrorKind::UnexpectedEof, "EFI_END_OF_FILE")
337+
const_io_error!(ErrorKind::UnexpectedEof, "The end of the file was reached.")
331338
}
332339
Status::END_OF_MEDIA => {
333-
const_io_error!(ErrorKind::UnexpectedEof, "EFI_END_OF_MEDIA")
340+
const_io_error!(ErrorKind::Other, "Beginning or end of media was reached")
334341
}
335342
Status::HOST_UNREACHABLE => {
336-
const_io_error!(ErrorKind::HostUnreachable, "EFI_HOST_UNREACHABLE")
343+
const_io_error!(ErrorKind::HostUnreachable, "The remote host is not reachable.")
337344
}
338345
Status::HTTP_ERROR => {
339-
const_io_error!(ErrorKind::NetworkUnreachable, "EFI_HTTP_ERROR")
346+
const_io_error!(ErrorKind::Other, "A HTTP error occurred during the network operation.")
340347
}
341348
Status::ICMP_ERROR => {
342-
const_io_error!(ErrorKind::Other, "EFI_ICMP_ERROR")
349+
const_io_error!(
350+
ErrorKind::Other,
351+
"An ICMP error occurred during the network operation."
352+
)
343353
}
344354
Status::INCOMPATIBLE_VERSION => {
345-
const_io_error!(ErrorKind::Other, "EFI_INCOMPATIBLE_VERSION")
355+
const_io_error!(
356+
ErrorKind::Other,
357+
"The function encountered an internal version that was incompatible with a version requested by the caller."
358+
)
346359
}
347360
Status::INVALID_LANGUAGE => {
348-
const_io_error!(ErrorKind::InvalidData, "EFI_INVALID_LANGUAGE")
361+
const_io_error!(ErrorKind::InvalidData, "The language specified was invalid.")
349362
}
350363
Status::INVALID_PARAMETER => {
351-
const_io_error!(ErrorKind::InvalidInput, "EFI_INVALID_PARAMETER")
364+
const_io_error!(ErrorKind::InvalidInput, "A parameter was incorrect.")
352365
}
353366
Status::IP_ADDRESS_CONFLICT => {
354-
const_io_error!(ErrorKind::AddrInUse, "EFI_IP_ADDRESS_CONFLICT")
367+
const_io_error!(ErrorKind::AddrInUse, "There is an address conflict address allocation")
355368
}
356369
Status::LOAD_ERROR => {
357-
const_io_error!(ErrorKind::Other, "EFI_LOAD_ERROR")
370+
const_io_error!(ErrorKind::Other, "The image failed to load.")
358371
}
359372
Status::MEDIA_CHANGED => {
360-
const_io_error!(ErrorKind::StaleNetworkFileHandle, "EFI_MEDIA_CHANGED")
373+
const_io_error!(
374+
ErrorKind::Other,
375+
"The medium in the device has changed since the last access."
376+
)
361377
}
362378
Status::NETWORK_UNREACHABLE => {
363-
const_io_error!(ErrorKind::NetworkUnreachable, "EFI_NETWORK_UNREACHABLE")
379+
const_io_error!(
380+
ErrorKind::NetworkUnreachable,
381+
"The network containing the remote host is not reachable."
382+
)
364383
}
365384
Status::NO_MAPPING => {
366-
const_io_error!(ErrorKind::Other, "EFI_NO_MAPPING")
385+
const_io_error!(ErrorKind::Other, "A mapping to a device does not exist.")
367386
}
368387
Status::NO_MEDIA => {
369-
const_io_error!(ErrorKind::Other, "EFI_NO_MEDIA")
388+
const_io_error!(
389+
ErrorKind::Other,
390+
"The device does not contain any medium to perform the operation."
391+
)
370392
}
371393
Status::NO_RESPONSE => {
372-
const_io_error!(ErrorKind::HostUnreachable, "EFI_NO_RESPONSE")
394+
const_io_error!(
395+
ErrorKind::HostUnreachable,
396+
"The server was not found or did not respond to the request."
397+
)
398+
}
399+
Status::NOT_FOUND => const_io_error!(ErrorKind::NotFound, "The item was not found."),
400+
Status::NOT_READY => {
401+
const_io_error!(ErrorKind::ResourceBusy, "There is no data pending upon return.")
402+
}
403+
Status::NOT_STARTED => {
404+
const_io_error!(ErrorKind::Other, "The protocol has not been started.")
373405
}
374-
Status::NOT_FOUND => const_io_error!(ErrorKind::NotFound, "EFI_NOT_FOUND"),
375-
Status::NOT_READY => const_io_error!(ErrorKind::ResourceBusy, "EFI_NOT_READY"),
376-
Status::NOT_STARTED => const_io_error!(ErrorKind::Other, "EFI_NOT_STARTED"),
377406
Status::OUT_OF_RESOURCES => {
378-
const_io_error!(ErrorKind::OutOfMemory, "EFI_OUT_OF_RESOURCES")
407+
const_io_error!(ErrorKind::OutOfMemory, "A resource has run out.")
379408
}
380409
Status::PROTOCOL_ERROR => {
381-
const_io_error!(ErrorKind::Other, "EFI_PROTOCOL_ERROR")
410+
const_io_error!(
411+
ErrorKind::Other,
412+
"A protocol error occurred during the network operation."
413+
)
382414
}
383415
Status::PROTOCOL_UNREACHABLE => {
384-
const_io_error!(ErrorKind::Other, "EFI_PROTOCOL_UNREACHABLE")
416+
const_io_error!(ErrorKind::Other, "An ICMP protocol unreachable error is received.")
385417
}
386418
Status::SECURITY_VIOLATION => {
387-
const_io_error!(ErrorKind::PermissionDenied, "EFI_SECURITY_VIOLATION")
419+
const_io_error!(
420+
ErrorKind::PermissionDenied,
421+
"The function was not performed due to a security violation."
422+
)
423+
}
424+
Status::TFTP_ERROR => {
425+
const_io_error!(ErrorKind::Other, "A TFTP error occurred during the network operation.")
388426
}
389-
Status::TFTP_ERROR => const_io_error!(ErrorKind::Other, "EFI_TFTP_ERROR"),
390-
Status::TIMEOUT => const_io_error!(ErrorKind::TimedOut, "EFI_TIMEOUT"),
427+
Status::TIMEOUT => const_io_error!(ErrorKind::TimedOut, "The timeout time expired."),
391428
Status::UNSUPPORTED => {
392-
const_io_error!(ErrorKind::Unsupported, "EFI_UNSUPPORTED")
429+
const_io_error!(ErrorKind::Unsupported, "The operation is not supported.")
393430
}
394431
Status::VOLUME_FULL => {
395-
const_io_error!(ErrorKind::StorageFull, "EFI_VOLUME_FULL")
432+
const_io_error!(ErrorKind::StorageFull, "There is no more space on the file system.")
396433
}
397434
Status::VOLUME_CORRUPTED => {
398-
const_io_error!(ErrorKind::Other, "EFI_VOLUME_CORRUPTED")
435+
const_io_error!(
436+
ErrorKind::Other,
437+
"An inconstancy was detected on the file system causing the operating to fail."
438+
)
399439
}
400440
Status::WRITE_PROTECTED => {
401-
const_io_error!(ErrorKind::ReadOnlyFilesystem, "EFI_WRITE_PROTECTED")
441+
const_io_error!(ErrorKind::ReadOnlyFilesystem, "The device cannot be written to.")
402442
}
403443
_ => io::Error::new(ErrorKind::Uncategorized, format!("Status: {}", s.as_usize())),
404444
}

library/std/src/sys/uefi/fs.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -256,16 +256,12 @@ impl OpenOptions {
256256

257257
impl File {
258258
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
259+
if opts.create_new && uefi_fs::FileProtocol::file_exists(path)? {
260+
return Err(io::const_io_error!(io::ErrorKind::AlreadyExists, "File already exists"));
261+
}
259262
let file_opened = uefi_fs::FileProtocol::from_path(path, opts.open_mode, opts.attr)?;
260263
let file = File { ptr: file_opened };
261-
if opts.create_new {
262-
if file.file_attr()?.size != 0 {
263-
return Err(io::const_io_error!(
264-
io::ErrorKind::AlreadyExists,
265-
"File already exists"
266-
));
267-
}
268-
} else if opts.truncate {
264+
if opts.truncate {
269265
file.truncate(0)?;
270266
} else if opts.append {
271267
// If you truncate a file, no need to seek to end
@@ -843,8 +839,8 @@ mod uefi_fs {
843839

844840
let file_name = common::to_ffi_string(file_name);
845841
let old_info = self.get_file_info()?;
846-
let new_size =
847-
crate::mem::size_of::<file::Info>() + crate::mem::size_of_val(&file_name);
842+
let new_size = crate::mem::size_of::<file::Info>()
843+
+ file_name.len() * crate::mem::size_of::<u16>();
848844
let layout = unsafe {
849845
crate::alloc::Layout::from_size_align_unchecked(new_size, POOL_ALIGNMENT)
850846
};
@@ -916,6 +912,19 @@ mod uefi_fs {
916912
}
917913
}
918914

915+
pub(crate) fn file_exists(path: &Path) -> io::Result<bool> {
916+
match FileProtocol::from_path(path, file::MODE_READ, 0) {
917+
Ok(_) => Ok(true),
918+
Err(e) => {
919+
if e.kind() == io::ErrorKind::NotFound {
920+
Ok(false)
921+
} else {
922+
Err(e)
923+
}
924+
}
925+
}
926+
}
927+
919928
// Delete a file.
920929
pub(crate) fn delete(self) -> io::Result<()> {
921930
// Deleting the file makes the pointer invalid. Thus calling drop on it later will

library/std/src/sys/uefi/mod.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -134,22 +134,23 @@ unsafe fn get_random() -> Option<u64> {
134134
None
135135
}
136136

137-
extern "C" {
138-
fn main(argc: isize, argv: *const *const u8) -> isize;
139-
}
140-
141137
// FIXME: Do not generate this in case of `no_main`
142138
#[no_mangle]
143139
pub unsafe extern "efiapi" fn efi_main(
144140
handle: r_efi::efi::Handle,
145141
st: *mut r_efi::efi::SystemTable,
146142
) -> r_efi::efi::Status {
147-
let system_table = NonNull::new(st).unwrap();
148-
let image_handle = NonNull::new(handle).unwrap();
143+
extern "C" {
144+
fn main(argc: isize, argv: *const *const u8) -> isize;
145+
}
146+
147+
let (system_table, image_handle) = match (NonNull::new(st), NonNull::new(handle)) {
148+
(Some(x), Some(y)) => (x, y),
149+
_ => return r_efi::efi::Status::ABORTED,
150+
};
149151
unsafe { uefi::env::init_globals(image_handle, system_table.cast()) };
150152

151153
let res = unsafe { main(0, crate::ptr::null()) };
152-
153154
match usize::try_from(res) {
154155
Ok(x) => r_efi::efi::Status::from_usize(x),
155156
Err(_) => r_efi::efi::Status::ABORTED,

0 commit comments

Comments
 (0)