mirror of
https://github.com/rust-lang/rust
synced 2024-10-14 12:33:57 +00:00
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:
parent
40c3dacc76
commit
c7e5f3ca08
|
@ -421,7 +421,7 @@ fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
entry_type: EntryFnType,
|
entry_type: EntryFnType,
|
||||||
) -> Bx::Function {
|
) -> Bx::Function {
|
||||||
// The entry function is either `int main(void)` or `int main(int argc, char **argv)`, or
|
// The entry function is either `int main(void)` or `int main(int argc, char **argv)`, or
|
||||||
// `Status efi_main(Handle hd, SystemTable *st)` depending on the target.
|
// `usize efi_main(void *handle, void *system_table)` depending on the target.
|
||||||
let llfty = if cx.sess().target.os.contains("uefi") {
|
let llfty = if cx.sess().target.os.contains("uefi") {
|
||||||
cx.type_func(&[cx.type_ptr(), cx.type_ptr()], cx.type_isize())
|
cx.type_func(&[cx.type_ptr(), cx.type_ptr()], cx.type_isize())
|
||||||
} else if cx.sess().target.main_needs_argc_argv {
|
} else if cx.sess().target.main_needs_argc_argv {
|
||||||
|
@ -508,10 +508,9 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
let param_handle = bx.get_param(0);
|
let param_handle = bx.get_param(0);
|
||||||
let param_system_table = bx.get_param(1);
|
let param_system_table = bx.get_param(1);
|
||||||
let arg_argc = bx.const_int(cx.type_isize(), 2);
|
let arg_argc = bx.const_int(cx.type_isize(), 2);
|
||||||
let arg_argv = bx.alloca(cx.type_array(cx.type_i8p(), 2), Align::ONE);
|
let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), Align::ONE);
|
||||||
bx.store(param_handle, arg_argv, Align::ONE);
|
bx.store(param_handle, arg_argv, Align::ONE);
|
||||||
let arg_argv_el1 =
|
let arg_argv_el1 = bx.gep(cx.type_ptr(), arg_argv, &[bx.const_int(cx.type_int(), 1)]);
|
||||||
bx.gep(cx.type_ptr_to(cx.type_i8()), arg_argv, &[bx.const_int(cx.type_int(), 1)]);
|
|
||||||
bx.store(param_system_table, arg_argv_el1, Align::ONE);
|
bx.store(param_system_table, arg_argv_el1, Align::ONE);
|
||||||
(arg_argc, arg_argv)
|
(arg_argc, arg_argv)
|
||||||
} else if cx.sess().target.main_needs_argc_argv {
|
} else if cx.sess().target.main_needs_argc_argv {
|
||||||
|
@ -566,11 +565,7 @@ pub fn allocator_kind_for_codegen(tcx: TyCtxt<'_>) -> Option<AllocatorKind> {
|
||||||
use rustc_middle::middle::dependency_format::Linkage;
|
use rustc_middle::middle::dependency_format::Linkage;
|
||||||
list.iter().any(|&linkage| linkage == Linkage::Dynamic)
|
list.iter().any(|&linkage| linkage == Linkage::Dynamic)
|
||||||
});
|
});
|
||||||
if any_dynamic_crate {
|
if any_dynamic_crate { None } else { tcx.allocator_kind(()) }
|
||||||
None
|
|
||||||
} else {
|
|
||||||
tcx.allocator_kind(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn codegen_crate<B: ExtraBackendMethods>(
|
pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||||
|
|
|
@ -44,7 +44,7 @@ unsafe fn abort() -> ! {
|
||||||
}
|
}
|
||||||
} else if #[cfg(any(target_os = "hermit",
|
} else if #[cfg(any(target_os = "hermit",
|
||||||
all(target_vendor = "fortanix", target_env = "sgx"),
|
all(target_vendor = "fortanix", target_env = "sgx"),
|
||||||
target_os = "xous"
|
target_os = "xous",
|
||||||
target_os = "uefi",
|
target_os = "uefi",
|
||||||
))] {
|
))] {
|
||||||
unsafe fn abort() -> ! {
|
unsafe fn abort() -> ! {
|
||||||
|
|
|
@ -52,7 +52,6 @@ fn main() {
|
||||||
// - mipsel-sony-psp
|
// - mipsel-sony-psp
|
||||||
// - nvptx64-nvidia-cuda
|
// - nvptx64-nvidia-cuda
|
||||||
// - arch=avr
|
// - arch=avr
|
||||||
// - tvos (aarch64-apple-tvos, x86_64-apple-tvos)
|
|
||||||
// - JSON targets
|
// - JSON targets
|
||||||
// - Any new targets that have not been explicitly added above.
|
// - Any new targets that have not been explicitly added above.
|
||||||
println!("cargo:rustc-cfg=feature=\"restricted-std\"");
|
println!("cargo:rustc-cfg=feature=\"restricted-std\"");
|
||||||
|
|
|
@ -263,6 +263,7 @@
|
||||||
#![cfg_attr(target_os = "xous", feature(slice_ptr_len))]
|
#![cfg_attr(target_os = "xous", feature(slice_ptr_len))]
|
||||||
//
|
//
|
||||||
// Language features:
|
// Language features:
|
||||||
|
// tidy-alphabetical-start
|
||||||
#![feature(alloc_error_handler)]
|
#![feature(alloc_error_handler)]
|
||||||
#![feature(allocator_internals)]
|
#![feature(allocator_internals)]
|
||||||
#![feature(allow_internal_unsafe)]
|
#![feature(allow_internal_unsafe)]
|
||||||
|
|
|
@ -142,7 +142,6 @@ pub mod windows {}
|
||||||
#[cfg(target_os = "tvos")]
|
#[cfg(target_os = "tvos")]
|
||||||
#[path = "ios/mod.rs"]
|
#[path = "ios/mod.rs"]
|
||||||
pub(crate) mod tvos;
|
pub(crate) mod tvos;
|
||||||
#[cfg(target_os = "uefi")]
|
|
||||||
#[cfg(any(target_os = "uefi", doc))]
|
#[cfg(any(target_os = "uefi", doc))]
|
||||||
pub mod uefi;
|
pub mod uefi;
|
||||||
#[cfg(target_os = "vita")]
|
#[cfg(target_os = "vita")]
|
||||||
|
|
|
@ -2,23 +2,22 @@
|
||||||
|
|
||||||
#![unstable(feature = "uefi_std", issue = "100499")]
|
#![unstable(feature = "uefi_std", issue = "100499")]
|
||||||
|
|
||||||
use crate::{cell::Cell, ffi::c_void, ptr::NonNull};
|
use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
|
||||||
|
use crate::{ffi::c_void, ptr::NonNull};
|
||||||
|
|
||||||
// Since UEFI is single-threaded, making the global variables thread local should be safe.
|
static SYSTEM_TABLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_mut());
|
||||||
thread_local! {
|
static IMAGE_HANDLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_mut());
|
||||||
// Flag to check if BootServices are still valid.
|
// Flag to check if BootServices are still valid.
|
||||||
// Start with assuming that they are not available
|
// Start with assuming that they are not available
|
||||||
static BOOT_SERVICES_FLAG: Cell<bool> = Cell::new(false);
|
static BOOT_SERVICES_FLAG: AtomicBool = AtomicBool::new(false);
|
||||||
// Position 0 = SystemTable
|
|
||||||
// Position 1 = ImageHandle
|
|
||||||
static GLOBALS: Cell<Option<(NonNull<c_void>, NonNull<c_void>)>> = Cell::new(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Initializes the global System Table and Image Handle pointers.
|
/// Initializes the global System Table and Image Handle pointers.
|
||||||
///
|
///
|
||||||
/// The standard library requires access to the UEFI System Table and the Application Image Handle
|
/// The standard library requires access to the UEFI System Table and the Application Image Handle
|
||||||
/// to operate. Those are provided to UEFI Applications via their application entry point. By
|
/// to operate. Those are provided to UEFI Applications via their application entry point. By
|
||||||
/// calling `init_globals()`, those pointers are retained by the standard library for future use.
|
/// calling `init_globals()`, those pointers are retained by the standard library for future use.
|
||||||
|
/// Thus this function must be called before any of the standard library services are used.
|
||||||
|
///
|
||||||
/// The pointers are never exposed to any entity outside of this application and it is guaranteed
|
/// The pointers are never exposed to any entity outside of this application and it is guaranteed
|
||||||
/// that, once the application exited, these pointers are never dereferenced again.
|
/// that, once the application exited, these pointers are never dereferenced again.
|
||||||
///
|
///
|
||||||
|
@ -26,9 +25,26 @@
|
||||||
/// application. In particular, UEFI Boot Services must not be exited while an application with the
|
/// application. In particular, UEFI Boot Services must not be exited while an application with the
|
||||||
/// standard library is loaded.
|
/// standard library is loaded.
|
||||||
///
|
///
|
||||||
/// This function must not be called more than once.
|
/// # SAFETY
|
||||||
pub unsafe fn init_globals(handle: NonNull<c_void>, system_table: NonNull<c_void>) {
|
/// Calling this function more than once will panic
|
||||||
GLOBALS.set(Some((system_table, handle)));
|
pub(crate) unsafe fn init_globals(handle: NonNull<c_void>, system_table: NonNull<c_void>) {
|
||||||
|
IMAGE_HANDLE
|
||||||
|
.compare_exchange(
|
||||||
|
crate::ptr::null_mut(),
|
||||||
|
handle.as_ptr(),
|
||||||
|
Ordering::Release,
|
||||||
|
Ordering::Acquire,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
SYSTEM_TABLE
|
||||||
|
.compare_exchange(
|
||||||
|
crate::ptr::null_mut(),
|
||||||
|
system_table.as_ptr(),
|
||||||
|
Ordering::Release,
|
||||||
|
Ordering::Acquire,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
BOOT_SERVICES_FLAG.store(true, Ordering::Release)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the SystemTable Pointer.
|
/// Get the SystemTable Pointer.
|
||||||
|
@ -50,7 +66,7 @@ pub fn image_handle() -> NonNull<c_void> {
|
||||||
/// Get the BootServices Pointer.
|
/// Get the BootServices Pointer.
|
||||||
/// This function also checks if `ExitBootServices` has already been called.
|
/// This function also checks if `ExitBootServices` has already been called.
|
||||||
pub fn boot_services() -> Option<NonNull<c_void>> {
|
pub fn boot_services() -> Option<NonNull<c_void>> {
|
||||||
if BOOT_SERVICES_FLAG.get() {
|
if BOOT_SERVICES_FLAG.load(Ordering::Acquire) {
|
||||||
let system_table: NonNull<r_efi::efi::SystemTable> = try_system_table()?.cast();
|
let system_table: NonNull<r_efi::efi::SystemTable> = try_system_table()?.cast();
|
||||||
let boot_services = unsafe { (*system_table.as_ptr()).boot_services };
|
let boot_services = unsafe { (*system_table.as_ptr()).boot_services };
|
||||||
NonNull::new(boot_services).map(|x| x.cast())
|
NonNull::new(boot_services).map(|x| x.cast())
|
||||||
|
@ -62,19 +78,15 @@ pub fn boot_services() -> Option<NonNull<c_void>> {
|
||||||
/// Get the SystemTable Pointer.
|
/// Get the SystemTable Pointer.
|
||||||
/// This function is mostly intended for places where panic is not an option
|
/// This function is mostly intended for places where panic is not an option
|
||||||
pub(crate) fn try_system_table() -> Option<NonNull<c_void>> {
|
pub(crate) fn try_system_table() -> Option<NonNull<c_void>> {
|
||||||
GLOBALS.get().map(|x| x.0)
|
NonNull::new(SYSTEM_TABLE.load(Ordering::Acquire))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the SystemHandle Pointer.
|
/// Get the SystemHandle Pointer.
|
||||||
/// This function is mostly intended for places where panicking is not an option
|
/// This function is mostly intended for places where panicking is not an option
|
||||||
pub(crate) fn try_image_handle() -> Option<NonNull<c_void>> {
|
pub(crate) fn try_image_handle() -> Option<NonNull<c_void>> {
|
||||||
GLOBALS.get().map(|x| x.1)
|
NonNull::new(IMAGE_HANDLE.load(Ordering::Acquire))
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn enable_boot_services() {
|
|
||||||
BOOT_SERVICES_FLAG.set(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn disable_boot_services() {
|
pub(crate) fn disable_boot_services() {
|
||||||
BOOT_SERVICES_FLAG.set(false);
|
BOOT_SERVICES_FLAG.store(false, Ordering::Release)
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,13 +60,14 @@ fn inner(
|
||||||
}
|
}
|
||||||
|
|
||||||
// The returned buf_len is in bytes
|
// The returned buf_len is in bytes
|
||||||
let mut buf: Vec<r_efi::efi::Handle> =
|
assert_eq!(buf_len % size_of::<r_efi::efi::Handle>(), 0);
|
||||||
Vec::with_capacity(buf_len / size_of::<r_efi::efi::Handle>());
|
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()) {
|
match inner(&mut guid, boot_services, &mut buf_len, buf.as_mut_ptr()) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
// This is safe because the call will succeed only if buf_len >= required length.
|
// 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
|
// 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())
|
Ok(buf.into_iter().filter_map(|x| NonNull::new(x)).collect())
|
||||||
}
|
}
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
|
@ -114,16 +115,15 @@ pub(crate) fn create_event(
|
||||||
) -> io::Result<NonNull<crate::ffi::c_void>> {
|
) -> io::Result<NonNull<crate::ffi::c_void>> {
|
||||||
let boot_services: NonNull<efi::BootServices> =
|
let boot_services: NonNull<efi::BootServices> =
|
||||||
boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
|
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 r = unsafe {
|
||||||
let create_event = (*boot_services.as_ptr()).create_event;
|
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() {
|
if r.is_error() {
|
||||||
Err(crate::io::Error::from_raw_os_error(r.as_usize()))
|
Err(crate::io::Error::from_raw_os_error(r.as_usize()))
|
||||||
} else {
|
} else {
|
||||||
NonNull::new(exit_boot_service_event)
|
NonNull::new(event).ok_or(const_io_error!(io::ErrorKind::Other, "null protocol"))
|
||||||
.ok_or(const_io_error!(io::ErrorKind::Other, "null protocol"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
//! [`OsStr`]: crate::ffi::OsStr
|
//! [`OsStr`]: crate::ffi::OsStr
|
||||||
//! [`OsString`]: crate::ffi::OsString
|
//! [`OsString`]: crate::ffi::OsString
|
||||||
|
|
||||||
#![deny(unsafe_op_in_unsafe_fn)]
|
|
||||||
pub mod alloc;
|
pub mod alloc;
|
||||||
#[path = "../unsupported/args.rs"]
|
#[path = "../unsupported/args.rs"]
|
||||||
pub mod args;
|
pub mod args;
|
||||||
|
@ -43,6 +42,8 @@
|
||||||
pub mod thread;
|
pub mod thread;
|
||||||
#[path = "../unsupported/thread_local_key.rs"]
|
#[path = "../unsupported/thread_local_key.rs"]
|
||||||
pub mod thread_local_key;
|
pub mod thread_local_key;
|
||||||
|
#[path = "../unsupported/thread_parking.rs"]
|
||||||
|
pub mod thread_parking;
|
||||||
#[path = "../unsupported/time.rs"]
|
#[path = "../unsupported/time.rs"]
|
||||||
pub mod time;
|
pub mod time;
|
||||||
|
|
||||||
|
@ -53,18 +54,17 @@
|
||||||
|
|
||||||
pub type RawOsError = usize;
|
pub type RawOsError = usize;
|
||||||
|
|
||||||
use crate::cell::Cell;
|
|
||||||
use crate::io as std_io;
|
use crate::io as std_io;
|
||||||
use crate::os::uefi;
|
use crate::os::uefi;
|
||||||
use crate::ptr::NonNull;
|
use crate::ptr::NonNull;
|
||||||
|
use crate::sync::atomic::{AtomicPtr, Ordering};
|
||||||
|
|
||||||
pub mod memchr {
|
pub mod memchr {
|
||||||
pub use core::slice::memchr::{memchr, memrchr};
|
pub use core::slice::memchr::{memchr, memrchr};
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_local! {
|
static EXIT_BOOT_SERVICE_EVENT: AtomicPtr<crate::ffi::c_void> =
|
||||||
static EXIT_BOOT_SERVICE_EVENT: Cell<Option<NonNull<crate::ffi::c_void>>> = Cell::new(None);
|
AtomicPtr::new(crate::ptr::null_mut());
|
||||||
}
|
|
||||||
|
|
||||||
/// # SAFETY
|
/// # SAFETY
|
||||||
/// - must be called only once during runtime initialization.
|
/// - 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 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() };
|
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) };
|
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
|
// Register exit boot services handler
|
||||||
match helpers::create_event(
|
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(),
|
crate::ptr::null_mut(),
|
||||||
) {
|
) {
|
||||||
Ok(x) => {
|
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(),
|
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.
|
/// this is not guaranteed to run, for example when the program aborts.
|
||||||
/// - must be called only once during runtime cleanup.
|
/// - must be called only once during runtime cleanup.
|
||||||
pub unsafe fn 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) };
|
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() -> ! {
|
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) };
|
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) {
|
extern "efiapi" fn exit_boot_service_handler(_e: r_efi::efi::Event, _ctx: *mut crate::ffi::c_void) {
|
||||||
uefi::env::disable_boot_services();
|
uefi::env::disable_boot_services();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_interrupted(_code: RawOsError) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
|
@ -4,15 +4,16 @@
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::marker::PhantomData;
|
use crate::marker::PhantomData;
|
||||||
|
use crate::os::uefi;
|
||||||
use crate::path::{self, PathBuf};
|
use crate::path::{self, PathBuf};
|
||||||
|
use crate::ptr::NonNull;
|
||||||
|
use r_efi::efi::Status;
|
||||||
|
|
||||||
pub fn errno() -> RawOsError {
|
pub fn errno() -> RawOsError {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error_string(errno: RawOsError) -> String {
|
pub fn error_string(errno: RawOsError) -> String {
|
||||||
use r_efi::efi::Status;
|
|
||||||
|
|
||||||
// Keep the List in Alphabetical Order
|
// Keep the List in Alphabetical Order
|
||||||
// The Messages are taken from UEFI Specification Appendix D - Status Codes
|
// The Messages are taken from UEFI Specification Appendix D - Status Codes
|
||||||
match r_efi::efi::Status::from_usize(errno) {
|
match r_efi::efi::Status::from_usize(errno) {
|
||||||
|
@ -160,12 +161,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StdError for JoinPathsError {
|
impl StdError for JoinPathsError {}
|
||||||
#[allow(deprecated)]
|
|
||||||
fn description(&self) -> &str {
|
|
||||||
"not supported on this platform yet"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_exe() -> io::Result<PathBuf> {
|
pub fn current_exe() -> io::Result<PathBuf> {
|
||||||
unsupported()
|
unsupported()
|
||||||
|
@ -173,6 +169,14 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
||||||
|
|
||||||
pub struct Env(!);
|
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 {
|
impl Iterator for Env {
|
||||||
type Item = (OsString, OsString);
|
type Item = (OsString, OsString);
|
||||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||||
|
@ -180,6 +184,13 @@ fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Env {
|
||||||
|
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let Self(inner) = self;
|
||||||
|
match *inner {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn env() -> Env {
|
pub fn env() -> Env {
|
||||||
panic!("not supported on this platform")
|
panic!("not supported on this platform")
|
||||||
}
|
}
|
||||||
|
@ -204,7 +215,20 @@ pub fn home_dir() -> Option<PathBuf> {
|
||||||
None
|
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()
|
crate::intrinsics::abort()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,9 @@ cargo +custom build --target x86_64-unknown-uefi
|
||||||
```
|
```
|
||||||
|
|
||||||
```rust,ignore (platform-specific)
|
```rust,ignore (platform-specific)
|
||||||
use r_efi::efi;
|
#![feature(uefi_std)]
|
||||||
|
|
||||||
|
use r_efi::{efi, protocols::simple_text_output};
|
||||||
use std::{
|
use std::{
|
||||||
ffi::OsString,
|
ffi::OsString,
|
||||||
os::uefi::{env, ffi::OsStrExt}
|
os::uefi::{env, ffi::OsStrExt}
|
||||||
|
@ -290,7 +292,7 @@ pub fn main() {
|
||||||
let r =
|
let r =
|
||||||
unsafe {
|
unsafe {
|
||||||
let con_out: *mut simple_text_output::Protocol = (*st).con_out;
|
let con_out: *mut simple_text_output::Protocol = (*st).con_out;
|
||||||
let output_string: extern "efiapi" fn(_: *mut simple_text_output::Protocol, *mut u16) = (*con_out).output_string;
|
let output_string: extern "efiapi" fn(_: *mut simple_text_output::Protocol, *mut u16) -> efi::Status = (*con_out).output_string;
|
||||||
output_string(con_out, s.as_ptr() as *mut efi::Char16)
|
output_string(con_out, s.as_ptr() as *mut efi::Char16)
|
||||||
};
|
};
|
||||||
assert!(!r.is_error())
|
assert!(!r.is_error())
|
||||||
|
@ -298,6 +300,6 @@ pub fn main() {
|
||||||
```
|
```
|
||||||
|
|
||||||
### BootServices
|
### BootServices
|
||||||
The current implementation of std make `BootServices` unavailable once `ExitBootServices` is called. Refer to [Runtime Drivers](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/7_driver_entry_point/711_runtime_drivers) for more information regarding how to handle switching from using physical addresses to using virtual addresses.
|
The current implementation of std makes `BootServices` unavailable once `ExitBootServices` is called. Refer to [Runtime Drivers](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/7_driver_entry_point/711_runtime_drivers) for more information regarding how to handle switching from using physical addresses to using virtual addresses.
|
||||||
|
|
||||||
Note: It should be noted that it is upto the user to drop all allocated memory before `ExitBootServices` is called.
|
Note: It should be noted that it is up to the user to drop all allocated memory before `ExitBootServices` is called.
|
||||||
|
|
Loading…
Reference in a new issue