Rebase to master

- Update Example
- Add thread_parking to sys::uefi
- Fix unsafe in unsafe errors
- Improve docs
- Improve os/exit
- Some asserts
- Switch back to atomics

Signed-off-by: Ayush Singh <ayushdevel1325@gmail.com>
This commit is contained in:
Ayush Singh 2023-05-21 14:26:59 +05:30 committed by Ayush Singh
parent 40c3dacc76
commit c7e5f3ca08
No known key found for this signature in database
GPG key ID: 05CEF5C789E55A74
10 changed files with 111 additions and 63 deletions

View file

@ -60,13 +60,14 @@ pub(crate) fn locate_handles(mut guid: Guid) -> io::Result<Vec<NonNull<crate::ff
}
// The returned buf_len is in bytes
let mut buf: Vec<r_efi::efi::Handle> =
Vec::with_capacity(buf_len / size_of::<r_efi::efi::Handle>());
assert_eq!(buf_len % size_of::<r_efi::efi::Handle>(), 0);
let num_of_handles = buf_len / size_of::<r_efi::efi::Handle>();
let mut buf: Vec<r_efi::efi::Handle> = Vec::with_capacity(num_of_handles);
match inner(&mut guid, boot_services, &mut buf_len, buf.as_mut_ptr()) {
Ok(()) => {
// This is safe because the call will succeed only if buf_len >= required length.
// Also, on success, the `buf_len` is updated with the size of bufferv (in bytes) written
unsafe { buf.set_len(buf_len / size_of::<r_efi::efi::Handle>()) };
unsafe { buf.set_len(num_of_handles) };
Ok(buf.into_iter().filter_map(|x| NonNull::new(x)).collect())
}
Err(e) => Err(e),
@ -114,16 +115,15 @@ pub(crate) fn create_event(
) -> io::Result<NonNull<crate::ffi::c_void>> {
let boot_services: NonNull<efi::BootServices> =
boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
let mut exit_boot_service_event: r_efi::efi::Event = crate::ptr::null_mut();
let mut event: r_efi::efi::Event = crate::ptr::null_mut();
let r = unsafe {
let create_event = (*boot_services.as_ptr()).create_event;
(create_event)(signal, tpl, handler, context, &mut exit_boot_service_event)
(create_event)(signal, tpl, handler, context, &mut event)
};
if r.is_error() {
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"))
NonNull::new(event).ok_or(const_io_error!(io::ErrorKind::Other, "null protocol"))
}
}

View file

@ -12,7 +12,6 @@
//! [`OsStr`]: crate::ffi::OsStr
//! [`OsString`]: crate::ffi::OsString
#![deny(unsafe_op_in_unsafe_fn)]
pub mod alloc;
#[path = "../unsupported/args.rs"]
pub mod args;
@ -43,6 +42,8 @@ pub mod stdio;
pub mod thread;
#[path = "../unsupported/thread_local_key.rs"]
pub mod thread_local_key;
#[path = "../unsupported/thread_parking.rs"]
pub mod thread_parking;
#[path = "../unsupported/time.rs"]
pub mod time;
@ -53,18 +54,17 @@ mod tests;
pub type RawOsError = usize;
use crate::cell::Cell;
use crate::io as std_io;
use crate::os::uefi;
use crate::ptr::NonNull;
use crate::sync::atomic::{AtomicPtr, Ordering};
pub mod memchr {
pub use core::slice::memchr::{memchr, memrchr};
}
thread_local! {
static EXIT_BOOT_SERVICE_EVENT: Cell<Option<NonNull<crate::ffi::c_void>>> = Cell::new(None);
}
static EXIT_BOOT_SERVICE_EVENT: AtomicPtr<crate::ffi::c_void> =
AtomicPtr::new(crate::ptr::null_mut());
/// # SAFETY
/// - must be called only once during runtime initialization.
@ -75,8 +75,6 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
let image_handle = unsafe { NonNull::new(*argv as *mut crate::ffi::c_void).unwrap() };
let system_table = unsafe { NonNull::new(*argv.add(1) as *mut crate::ffi::c_void).unwrap() };
unsafe { uefi::env::init_globals(image_handle, system_table) };
// Enable boot services once GLOBALS are initialized
uefi::env::enable_boot_services();
// Register exit boot services handler
match helpers::create_event(
@ -86,7 +84,17 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
crate::ptr::null_mut(),
) {
Ok(x) => {
EXIT_BOOT_SERVICE_EVENT.set(Some(x));
if EXIT_BOOT_SERVICE_EVENT
.compare_exchange(
crate::ptr::null_mut(),
x.as_ptr(),
Ordering::Release,
Ordering::Acquire,
)
.is_err()
{
abort_internal();
};
}
Err(_) => abort_internal(),
}
@ -96,7 +104,9 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
/// this is not guaranteed to run, for example when the program aborts.
/// - must be called only once during runtime cleanup.
pub unsafe fn cleanup() {
if let Some(exit_boot_service_event) = EXIT_BOOT_SERVICE_EVENT.take() {
if let Some(exit_boot_service_event) =
NonNull::new(EXIT_BOOT_SERVICE_EVENT.swap(crate::ptr::null_mut(), Ordering::Acquire))
{
let _ = unsafe { helpers::close_event(exit_boot_service_event) };
}
}
@ -159,7 +169,9 @@ pub fn decode_error_kind(code: RawOsError) -> crate::io::ErrorKind {
}
pub fn abort_internal() -> ! {
if let Some(exit_boot_service_event) = EXIT_BOOT_SERVICE_EVENT.take() {
if let Some(exit_boot_service_event) =
NonNull::new(EXIT_BOOT_SERVICE_EVENT.load(Ordering::Acquire))
{
let _ = unsafe { helpers::close_event(exit_boot_service_event) };
}
@ -226,3 +238,7 @@ fn get_random() -> Option<(u64, u64)> {
extern "efiapi" fn exit_boot_service_handler(_e: r_efi::efi::Event, _ctx: *mut crate::ffi::c_void) {
uefi::env::disable_boot_services();
}
pub fn is_interrupted(_code: RawOsError) -> bool {
false
}

View file

@ -4,15 +4,16 @@ use crate::ffi::{OsStr, OsString};
use crate::fmt;
use crate::io;
use crate::marker::PhantomData;
use crate::os::uefi;
use crate::path::{self, PathBuf};
use crate::ptr::NonNull;
use r_efi::efi::Status;
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) {
@ -160,12 +161,7 @@ impl fmt::Display for JoinPathsError {
}
}
impl StdError for JoinPathsError {
#[allow(deprecated)]
fn description(&self) -> &str {
"not supported on this platform yet"
}
}
impl StdError for JoinPathsError {}
pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
@ -173,6 +169,14 @@ pub fn current_exe() -> io::Result<PathBuf> {
pub struct Env(!);
impl Env {
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
let Self(inner) = self;
match *inner {}
}
}
impl Iterator for Env {
type Item = (OsString, OsString);
fn next(&mut self) -> Option<(OsString, OsString)> {
@ -180,6 +184,13 @@ impl Iterator for Env {
}
}
impl fmt::Debug for Env {
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self(inner) = self;
match *inner {}
}
}
pub fn env() -> Env {
panic!("not supported on this platform")
}
@ -204,7 +215,20 @@ pub fn home_dir() -> Option<PathBuf> {
None
}
pub fn exit(_code: i32) -> ! {
pub fn exit(code: i32) -> ! {
if let (Some(boot_services), Some(handle)) =
(uefi::env::boot_services(), uefi::env::try_image_handle())
{
let boot_services: NonNull<r_efi::efi::BootServices> = boot_services.cast();
let _ = unsafe {
((*boot_services.as_ptr()).exit)(
handle.as_ptr(),
Status::from_usize(code as usize),
0,
crate::ptr::null_mut(),
)
};
}
crate::intrinsics::abort()
}