uefi: process: Fixes from PR
- Update system table crc32 - Fix unsound use of Box - Free exit data - Code improvements - Introduce OwnedTable - Update r-efi to latest version - Use extended_varargs_abi_support for install_multiple_protocol_interfaces and uninstall_multiple_protocol_interfaces - Fix comments - Stub out args implementation Signed-off-by: Ayush Singh <ayushdevel1325@gmail.com>
This commit is contained in:
parent
56e2a57505
commit
e2903989da
@ -56,7 +56,7 @@ hermit-abi = { version = "0.4.0", features = ['rustc-dep-of-std'], public = true
|
||||
wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }
|
||||
|
||||
[target.'cfg(target_os = "uefi")'.dependencies]
|
||||
r-efi = { version = "4.2.0", features = ['rustc-dep-of-std'] }
|
||||
r-efi = { version = "4.5.0", features = ['rustc-dep-of-std'] }
|
||||
r-efi-alloc = { version = "1.0.0", features = ['rustc-dep-of-std'] }
|
||||
|
||||
[features]
|
||||
|
@ -293,6 +293,7 @@
|
||||
#![feature(doc_masked)]
|
||||
#![feature(doc_notable_trait)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(extended_varargs_abi_support)]
|
||||
#![feature(f128)]
|
||||
#![feature(f16)]
|
||||
#![feature(if_let_guard)]
|
||||
|
@ -21,6 +21,12 @@
|
||||
use crate::sync::atomic::{AtomicPtr, Ordering};
|
||||
use crate::sys_common::wstr::WStrUnits;
|
||||
|
||||
type BootInstallMultipleProtocolInterfaces =
|
||||
unsafe extern "efiapi" fn(_: *mut r_efi::efi::Handle, _: ...) -> r_efi::efi::Status;
|
||||
|
||||
type BootUninstallMultipleProtocolInterfaces =
|
||||
unsafe extern "efiapi" fn(_: r_efi::efi::Handle, _: ...) -> r_efi::efi::Status;
|
||||
|
||||
const BOOT_SERVICES_UNAVAILABLE: io::Error =
|
||||
const_io_error!(io::ErrorKind::Other, "Boot Services are no longer available");
|
||||
|
||||
@ -231,6 +237,13 @@ fn inner(
|
||||
protocol: NonNull<r_efi::protocols::device_path_from_text::Protocol>,
|
||||
) -> io::Result<DevicePath> {
|
||||
let path_vec = p.encode_wide().chain(Some(0)).collect::<Vec<u16>>();
|
||||
if path_vec[..path_vec.len() - 1].contains(&0) {
|
||||
return Err(const_io_error!(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"strings passed to UEFI cannot contain NULs",
|
||||
));
|
||||
}
|
||||
|
||||
let path =
|
||||
unsafe { ((*protocol.as_ptr()).convert_text_to_device_path)(path_vec.as_ptr()) };
|
||||
|
||||
@ -267,17 +280,9 @@ fn inner(
|
||||
"DevicePathFromText Protocol not found"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<r_efi::protocols::device_path::Protocol> for DevicePath {
|
||||
fn as_ref(&self) -> &r_efi::protocols::device_path::Protocol {
|
||||
unsafe { self.0.as_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<r_efi::protocols::device_path::Protocol> for DevicePath {
|
||||
fn as_mut(&mut self) -> &mut r_efi::protocols::device_path::Protocol {
|
||||
unsafe { self.0.as_mut() }
|
||||
pub(crate) fn as_ptr(&self) -> *mut r_efi::protocols::device_path::Protocol {
|
||||
self.0.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,44 +297,42 @@ fn drop(&mut self) {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Protocol<T> {
|
||||
pub(crate) struct OwnedProtocol<T> {
|
||||
guid: r_efi::efi::Guid,
|
||||
handle: NonNull<crate::ffi::c_void>,
|
||||
protocol: Box<T>,
|
||||
protocol: *mut T,
|
||||
}
|
||||
|
||||
impl<T> Protocol<T> {
|
||||
const fn new(
|
||||
guid: r_efi::efi::Guid,
|
||||
handle: NonNull<crate::ffi::c_void>,
|
||||
protocol: Box<T>,
|
||||
) -> Self {
|
||||
Self { guid, handle, protocol }
|
||||
}
|
||||
|
||||
pub(crate) fn create(protocol: T, mut guid: r_efi::efi::Guid) -> io::Result<Self> {
|
||||
let boot_services: NonNull<r_efi::efi::BootServices> =
|
||||
impl<T> OwnedProtocol<T> {
|
||||
// FIXME: Consider using unsafe trait for matching protocol with guid
|
||||
pub(crate) unsafe fn create(protocol: T, mut guid: r_efi::efi::Guid) -> io::Result<Self> {
|
||||
let bt: NonNull<r_efi::efi::BootServices> =
|
||||
boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
|
||||
let mut protocol = Box::new(protocol);
|
||||
let protocol: *mut T = Box::into_raw(Box::new(protocol));
|
||||
let mut handle: r_efi::efi::Handle = crate::ptr::null_mut();
|
||||
|
||||
// FIXME: Move into r-efi once extended_varargs_abi_support is stablized
|
||||
let func: BootInstallMultipleProtocolInterfaces =
|
||||
unsafe { crate::mem::transmute((*bt.as_ptr()).install_multiple_protocol_interfaces) };
|
||||
|
||||
let r = unsafe {
|
||||
((*boot_services.as_ptr()).install_protocol_interface)(
|
||||
func(
|
||||
&mut handle,
|
||||
&mut guid,
|
||||
r_efi::efi::NATIVE_INTERFACE,
|
||||
protocol.as_mut() as *mut T as *mut crate::ffi::c_void,
|
||||
&mut guid as *mut _ as *mut crate::ffi::c_void,
|
||||
protocol as *mut crate::ffi::c_void,
|
||||
crate::ptr::null_mut() as *mut crate::ffi::c_void,
|
||||
)
|
||||
};
|
||||
|
||||
if r.is_error() {
|
||||
drop(unsafe { Box::from_raw(protocol) });
|
||||
return Err(crate::io::Error::from_raw_os_error(r.as_usize()));
|
||||
};
|
||||
|
||||
let handle = NonNull::new(handle)
|
||||
.ok_or(io::const_io_error!(io::ErrorKind::Uncategorized, "found null handle"))?;
|
||||
|
||||
Ok(Self::new(guid, handle, protocol))
|
||||
Ok(Self { guid, handle, protocol })
|
||||
}
|
||||
|
||||
pub(crate) fn handle(&self) -> NonNull<crate::ffi::c_void> {
|
||||
@ -337,29 +340,79 @@ pub(crate) fn handle(&self) -> NonNull<crate::ffi::c_void> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for Protocol<T> {
|
||||
impl<T> Drop for OwnedProtocol<T> {
|
||||
fn drop(&mut self) {
|
||||
// Do not deallocate a runtime protocol
|
||||
if let Some(bt) = boot_services() {
|
||||
let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
|
||||
unsafe {
|
||||
((*bt.as_ptr()).uninstall_protocol_interface)(
|
||||
// FIXME: Move into r-efi once extended_varargs_abi_support is stablized
|
||||
let func: BootUninstallMultipleProtocolInterfaces = unsafe {
|
||||
crate::mem::transmute((*bt.as_ptr()).uninstall_multiple_protocol_interfaces)
|
||||
};
|
||||
let status = unsafe {
|
||||
func(
|
||||
self.handle.as_ptr(),
|
||||
&mut self.guid,
|
||||
self.protocol.as_mut() as *mut T as *mut crate::ffi::c_void,
|
||||
&mut self.guid as *mut _ as *mut crate::ffi::c_void,
|
||||
self.protocol as *mut crate::ffi::c_void,
|
||||
crate::ptr::null_mut() as *mut crate::ffi::c_void,
|
||||
)
|
||||
};
|
||||
|
||||
// Leak the protocol in case uninstall fails
|
||||
if status == r_efi::efi::Status::SUCCESS {
|
||||
let _ = unsafe { Box::from_raw(self.protocol) };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsRef<T> for Protocol<T> {
|
||||
impl<T> AsRef<T> for OwnedProtocol<T> {
|
||||
fn as_ref(&self) -> &T {
|
||||
&self.protocol
|
||||
unsafe { self.protocol.as_ref().unwrap() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsMut<T> for Protocol<T> {
|
||||
fn as_mut(&mut self) -> &mut T {
|
||||
&mut self.protocol
|
||||
pub(crate) struct OwnedTable<T> {
|
||||
layout: crate::alloc::Layout,
|
||||
ptr: *mut T,
|
||||
}
|
||||
|
||||
impl<T> OwnedTable<T> {
|
||||
pub(crate) fn from_table_header(hdr: &r_efi::efi::TableHeader) -> Self {
|
||||
let header_size = hdr.header_size as usize;
|
||||
let layout = crate::alloc::Layout::from_size_align(header_size, 8).unwrap();
|
||||
let ptr = unsafe { crate::alloc::alloc(layout) as *mut T };
|
||||
Self { layout, ptr }
|
||||
}
|
||||
|
||||
pub(crate) const fn as_ptr(&self) -> *const T {
|
||||
self.ptr
|
||||
}
|
||||
|
||||
pub(crate) const fn as_mut_ptr(&self) -> *mut T {
|
||||
self.ptr
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnedTable<r_efi::efi::SystemTable> {
|
||||
pub(crate) fn from_table(tbl: *const r_efi::efi::SystemTable) -> Self {
|
||||
let hdr = unsafe { (*tbl).hdr };
|
||||
|
||||
let owned_tbl = Self::from_table_header(&hdr);
|
||||
unsafe {
|
||||
crate::ptr::copy_nonoverlapping(
|
||||
tbl as *const u8,
|
||||
owned_tbl.as_mut_ptr() as *mut u8,
|
||||
hdr.header_size as usize,
|
||||
)
|
||||
};
|
||||
|
||||
owned_tbl
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for OwnedTable<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { crate::alloc::dealloc(self.ptr as *mut u8, self.layout) };
|
||||
}
|
||||
}
|
||||
|
@ -20,9 +20,9 @@
|
||||
// Command
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Command {
|
||||
prog: OsString,
|
||||
args: Vec<OsString>,
|
||||
stdout: Option<Stdio>,
|
||||
stderr: Option<Stdio>,
|
||||
}
|
||||
@ -35,6 +35,7 @@ pub struct StdioPipes {
|
||||
pub stderr: Option<AnonPipe>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Stdio {
|
||||
Inherit,
|
||||
Null,
|
||||
@ -43,11 +44,12 @@ pub enum Stdio {
|
||||
|
||||
impl Command {
|
||||
pub fn new(program: &OsStr) -> Command {
|
||||
Command { prog: program.to_os_string(), args: Vec::new(), stdout: None, stderr: None }
|
||||
Command { prog: program.to_os_string(), stdout: None, stderr: None }
|
||||
}
|
||||
|
||||
pub fn arg(&mut self, arg: &OsStr) {
|
||||
self.args.push(arg.to_os_string());
|
||||
// FIXME: Implement arguments as reverse of parsing algorithm
|
||||
pub fn arg(&mut self, _arg: &OsStr) {
|
||||
panic!("unsupported")
|
||||
}
|
||||
|
||||
pub fn env_mut(&mut self) -> &mut CommandEnv {
|
||||
@ -75,7 +77,7 @@ pub fn get_program(&self) -> &OsStr {
|
||||
}
|
||||
|
||||
pub fn get_args(&self) -> CommandArgs<'_> {
|
||||
CommandArgs { iter: self.args.iter() }
|
||||
panic!("unsupported")
|
||||
}
|
||||
|
||||
pub fn get_envs(&self) -> CommandEnvs<'_> {
|
||||
@ -96,65 +98,47 @@ pub fn spawn(
|
||||
|
||||
fn create_pipe(
|
||||
s: Stdio,
|
||||
) -> io::Result<Option<helpers::Protocol<uefi_command_internal::PipeProtocol>>> {
|
||||
) -> io::Result<Option<helpers::OwnedProtocol<uefi_command_internal::PipeProtocol>>> {
|
||||
match s {
|
||||
Stdio::MakePipe => helpers::Protocol::create(
|
||||
uefi_command_internal::PipeProtocol::new(),
|
||||
simple_text_output::PROTOCOL_GUID,
|
||||
)
|
||||
Stdio::MakePipe => unsafe {
|
||||
helpers::OwnedProtocol::create(
|
||||
uefi_command_internal::PipeProtocol::new(),
|
||||
simple_text_output::PROTOCOL_GUID,
|
||||
)
|
||||
}
|
||||
.map(Some),
|
||||
Stdio::Null => helpers::Protocol::create(
|
||||
uefi_command_internal::PipeProtocol::null(),
|
||||
simple_text_output::PROTOCOL_GUID,
|
||||
)
|
||||
Stdio::Null => unsafe {
|
||||
helpers::OwnedProtocol::create(
|
||||
uefi_command_internal::PipeProtocol::null(),
|
||||
simple_text_output::PROTOCOL_GUID,
|
||||
)
|
||||
}
|
||||
.map(Some),
|
||||
Stdio::Inherit => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
||||
let mut cmd = uefi_command_internal::Command::load_image(&self.prog)?;
|
||||
let mut cmd = uefi_command_internal::Image::load_image(&self.prog)?;
|
||||
|
||||
/* Setup Stdout */
|
||||
let stdout: Option<helpers::Protocol<uefi_command_internal::PipeProtocol>> =
|
||||
match self.stdout.take() {
|
||||
Some(s) => Self::create_pipe(s),
|
||||
None => helpers::Protocol::create(
|
||||
uefi_command_internal::PipeProtocol::new(),
|
||||
simple_text_output::PROTOCOL_GUID,
|
||||
)
|
||||
.map(Some),
|
||||
}?;
|
||||
match stdout {
|
||||
Some(stdout) => cmd.stdout_init(stdout),
|
||||
None => cmd.stdout_inherit(),
|
||||
// Setup Stdout
|
||||
let stdout = self.stdout.unwrap_or(Stdio::MakePipe);
|
||||
let stdout = Self::create_pipe(stdout)?;
|
||||
if let Some(con) = stdout {
|
||||
cmd.stdout_init(con)
|
||||
} else {
|
||||
cmd.stdout_inherit()
|
||||
};
|
||||
|
||||
/* Setup Stderr */
|
||||
let stderr: Option<helpers::Protocol<uefi_command_internal::PipeProtocol>> =
|
||||
match self.stderr.take() {
|
||||
Some(s) => Self::create_pipe(s),
|
||||
None => helpers::Protocol::create(
|
||||
uefi_command_internal::PipeProtocol::new(),
|
||||
simple_text_output::PROTOCOL_GUID,
|
||||
)
|
||||
.map(Some),
|
||||
}?;
|
||||
match stderr {
|
||||
Some(stderr) => cmd.stderr_init(stderr),
|
||||
None => cmd.stderr_inherit(),
|
||||
// Setup Stderr
|
||||
let stderr = self.stderr.unwrap_or(Stdio::MakePipe);
|
||||
let stderr = Self::create_pipe(stderr)?;
|
||||
if let Some(con) = stderr {
|
||||
cmd.stderr_init(con)
|
||||
} else {
|
||||
cmd.stderr_inherit()
|
||||
};
|
||||
|
||||
/* No reason to set args if only program name is preset */
|
||||
if !self.args.is_empty() {
|
||||
let args = self.args.iter().fold(OsString::from(&self.prog), |mut acc, arg| {
|
||||
acc.push(" ");
|
||||
acc.push(arg);
|
||||
acc
|
||||
});
|
||||
cmd.set_args(&args);
|
||||
}
|
||||
|
||||
let stat = cmd.start_image()?;
|
||||
|
||||
let stdout = cmd.stdout()?;
|
||||
@ -194,16 +178,6 @@ fn from(_file: File) -> Stdio {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Command {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.prog.fmt(f)?;
|
||||
for arg in &self.args {
|
||||
arg.fmt(f)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub struct ExitStatus(r_efi::efi::Status);
|
||||
@ -326,6 +300,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod uefi_command_internal {
|
||||
use r_efi::protocols::{loaded_image, simple_text_output};
|
||||
|
||||
@ -337,26 +312,20 @@ mod uefi_command_internal {
|
||||
use crate::os::uefi::ffi::{OsStrExt, OsStringExt};
|
||||
use crate::ptr::NonNull;
|
||||
use crate::slice;
|
||||
use crate::sys::pal::uefi::helpers::OwnedTable;
|
||||
use crate::sys_common::wstr::WStrUnits;
|
||||
|
||||
pub struct Command {
|
||||
pub struct Image {
|
||||
handle: NonNull<crate::ffi::c_void>,
|
||||
stdout: Option<helpers::Protocol<PipeProtocol>>,
|
||||
stderr: Option<helpers::Protocol<PipeProtocol>>,
|
||||
st: Box<r_efi::efi::SystemTable>,
|
||||
stdout: Option<helpers::OwnedProtocol<PipeProtocol>>,
|
||||
stderr: Option<helpers::OwnedProtocol<PipeProtocol>>,
|
||||
st: OwnedTable<r_efi::efi::SystemTable>,
|
||||
args: Option<Vec<u16>>,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
const fn new(
|
||||
handle: NonNull<crate::ffi::c_void>,
|
||||
st: Box<r_efi::efi::SystemTable>,
|
||||
) -> Self {
|
||||
Self { handle, stdout: None, stderr: None, st, args: None }
|
||||
}
|
||||
|
||||
impl Image {
|
||||
pub fn load_image(p: &OsStr) -> io::Result<Self> {
|
||||
let mut path = helpers::DevicePath::from_text(p)?;
|
||||
let path = helpers::DevicePath::from_text(p)?;
|
||||
let boot_services: NonNull<r_efi::efi::BootServices> = boot_services()
|
||||
.ok_or_else(|| const_io_error!(io::ErrorKind::NotFound, "Boot Services not found"))?
|
||||
.cast();
|
||||
@ -367,7 +336,7 @@ pub fn load_image(p: &OsStr) -> io::Result<Self> {
|
||||
((*boot_services.as_ptr()).load_image)(
|
||||
r_efi::efi::Boolean::FALSE,
|
||||
image_handle.as_ptr(),
|
||||
path.as_mut(),
|
||||
path.as_ptr(),
|
||||
crate::ptr::null_mut(),
|
||||
0,
|
||||
child_handle.as_mut_ptr(),
|
||||
@ -382,69 +351,93 @@ pub fn load_image(p: &OsStr) -> io::Result<Self> {
|
||||
|
||||
let loaded_image: NonNull<loaded_image::Protocol> =
|
||||
helpers::open_protocol(child_handle, loaded_image::PROTOCOL_GUID).unwrap();
|
||||
let mut st: Box<r_efi::efi::SystemTable> =
|
||||
Box::new(unsafe { crate::ptr::read((*loaded_image.as_ptr()).system_table) });
|
||||
let st = OwnedTable::from_table(unsafe { (*loaded_image.as_ptr()).system_table });
|
||||
|
||||
unsafe {
|
||||
(*loaded_image.as_ptr()).system_table = st.as_mut();
|
||||
}
|
||||
|
||||
Ok(Self::new(child_handle, st))
|
||||
Ok(Self { handle: child_handle, stdout: None, stderr: None, st, args: None })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_image(&self) -> io::Result<r_efi::efi::Status> {
|
||||
pub fn start_image(&mut self) -> io::Result<r_efi::efi::Status> {
|
||||
self.update_st_crc32()?;
|
||||
|
||||
// Use our system table instead of the default one
|
||||
let loaded_image: NonNull<loaded_image::Protocol> =
|
||||
helpers::open_protocol(self.handle, loaded_image::PROTOCOL_GUID).unwrap();
|
||||
unsafe {
|
||||
(*loaded_image.as_ptr()).system_table = self.st.as_mut_ptr();
|
||||
}
|
||||
|
||||
let boot_services: NonNull<r_efi::efi::BootServices> = boot_services()
|
||||
.ok_or_else(|| const_io_error!(io::ErrorKind::NotFound, "Boot Services not found"))?
|
||||
.cast();
|
||||
let mut exit_data_size: MaybeUninit<usize> = MaybeUninit::uninit();
|
||||
let mut exit_data_size: usize = 0;
|
||||
let mut exit_data: MaybeUninit<*mut u16> = MaybeUninit::uninit();
|
||||
|
||||
let r = unsafe {
|
||||
((*boot_services.as_ptr()).start_image)(
|
||||
self.handle.as_ptr(),
|
||||
exit_data_size.as_mut_ptr(),
|
||||
&mut exit_data_size,
|
||||
exit_data.as_mut_ptr(),
|
||||
)
|
||||
};
|
||||
|
||||
// Drop exitdata
|
||||
unsafe {
|
||||
exit_data_size.assume_init_drop();
|
||||
exit_data.assume_init_drop();
|
||||
if exit_data_size != 0 {
|
||||
unsafe {
|
||||
let exit_data = exit_data.assume_init();
|
||||
((*boot_services.as_ptr()).free_pool)(exit_data as *mut crate::ffi::c_void);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
pub fn stdout_init(&mut self, mut protocol: helpers::Protocol<PipeProtocol>) {
|
||||
self.st.console_out_handle = protocol.handle().as_ptr();
|
||||
self.st.con_out =
|
||||
protocol.as_mut() as *mut PipeProtocol as *mut simple_text_output::Protocol;
|
||||
fn set_stdout(
|
||||
&mut self,
|
||||
handle: r_efi::efi::Handle,
|
||||
protocol: *mut simple_text_output::Protocol,
|
||||
) {
|
||||
unsafe {
|
||||
(*self.st.as_mut_ptr()).console_out_handle = handle;
|
||||
(*self.st.as_mut_ptr()).con_out = protocol;
|
||||
}
|
||||
}
|
||||
|
||||
fn set_stderr(
|
||||
&mut self,
|
||||
handle: r_efi::efi::Handle,
|
||||
protocol: *mut simple_text_output::Protocol,
|
||||
) {
|
||||
unsafe {
|
||||
(*self.st.as_mut_ptr()).standard_error_handle = handle;
|
||||
(*self.st.as_mut_ptr()).std_err = protocol;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stdout_init(&mut self, protocol: helpers::OwnedProtocol<PipeProtocol>) {
|
||||
self.set_stdout(
|
||||
protocol.handle().as_ptr(),
|
||||
protocol.as_ref() as *const PipeProtocol as *mut simple_text_output::Protocol,
|
||||
);
|
||||
self.stdout = Some(protocol);
|
||||
}
|
||||
|
||||
pub fn stdout_inherit(&mut self) {
|
||||
let st: NonNull<r_efi::efi::SystemTable> = system_table().cast();
|
||||
|
||||
self.st.console_out_handle = unsafe { (*st.as_ptr()).console_out_handle };
|
||||
self.st.con_out = unsafe { (*st.as_ptr()).con_out };
|
||||
unsafe { self.set_stdout((*st.as_ptr()).console_out_handle, (*st.as_ptr()).con_out) }
|
||||
}
|
||||
|
||||
pub fn stderr_init(&mut self, mut protocol: helpers::Protocol<PipeProtocol>) {
|
||||
self.st.standard_error_handle = protocol.handle().as_ptr();
|
||||
self.st.std_err =
|
||||
protocol.as_mut() as *mut PipeProtocol as *mut simple_text_output::Protocol;
|
||||
|
||||
pub fn stderr_init(&mut self, protocol: helpers::OwnedProtocol<PipeProtocol>) {
|
||||
self.set_stderr(
|
||||
protocol.handle().as_ptr(),
|
||||
protocol.as_ref() as *const PipeProtocol as *mut simple_text_output::Protocol,
|
||||
);
|
||||
self.stderr = Some(protocol);
|
||||
}
|
||||
|
||||
pub fn stderr_inherit(&mut self) {
|
||||
let st: NonNull<r_efi::efi::SystemTable> = system_table().cast();
|
||||
|
||||
self.st.standard_error_handle = unsafe { (*st.as_ptr()).standard_error_handle };
|
||||
self.st.std_err = unsafe { (*st.as_ptr()).std_err };
|
||||
unsafe { self.set_stderr((*st.as_ptr()).standard_error_handle, (*st.as_ptr()).std_err) }
|
||||
}
|
||||
|
||||
pub fn stderr(&self) -> io::Result<Vec<u8>> {
|
||||
@ -476,9 +469,37 @@ pub fn set_args(&mut self, args: &OsStr) {
|
||||
|
||||
self.args = Some(args);
|
||||
}
|
||||
|
||||
fn update_st_crc32(&mut self) -> io::Result<()> {
|
||||
let bt: NonNull<r_efi::efi::BootServices> = boot_services().unwrap().cast();
|
||||
let st_size = unsafe { (*self.st.as_ptr()).hdr.header_size as usize };
|
||||
let mut crc32: u32 = 0;
|
||||
|
||||
// Set crc to 0 before calcuation
|
||||
unsafe {
|
||||
(*self.st.as_mut_ptr()).hdr.crc32 = 0;
|
||||
}
|
||||
|
||||
let r = unsafe {
|
||||
((*bt.as_ptr()).calculate_crc32)(
|
||||
self.st.as_mut_ptr() as *mut crate::ffi::c_void,
|
||||
st_size,
|
||||
&mut crc32,
|
||||
)
|
||||
};
|
||||
|
||||
if r.is_error() {
|
||||
Err(io::Error::from_raw_os_error(r.as_usize()))
|
||||
} else {
|
||||
unsafe {
|
||||
(*self.st.as_mut_ptr()).hdr.crc32 = crc32;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Command {
|
||||
impl Drop for Image {
|
||||
fn drop(&mut self) {
|
||||
if let Some(bt) = boot_services() {
|
||||
let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
|
||||
@ -501,13 +522,12 @@ pub struct PipeProtocol {
|
||||
set_cursor_position: simple_text_output::ProtocolSetCursorPosition,
|
||||
enable_cursor: simple_text_output::ProtocolEnableCursor,
|
||||
mode: *mut simple_text_output::Mode,
|
||||
_mode: Box<simple_text_output::Mode>,
|
||||
_buffer: Vec<u16>,
|
||||
}
|
||||
|
||||
impl PipeProtocol {
|
||||
pub fn new() -> Self {
|
||||
let mut mode = Box::new(simple_text_output::Mode {
|
||||
let mode = Box::new(simple_text_output::Mode {
|
||||
max_mode: 0,
|
||||
mode: 0,
|
||||
attribute: 0,
|
||||
@ -525,14 +545,13 @@ pub fn new() -> Self {
|
||||
clear_screen: Self::clear_screen,
|
||||
set_cursor_position: Self::set_cursor_position,
|
||||
enable_cursor: Self::enable_cursor,
|
||||
mode: mode.as_mut(),
|
||||
_mode: mode,
|
||||
mode: Box::into_raw(mode),
|
||||
_buffer: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn null() -> Self {
|
||||
let mut mode = Box::new(simple_text_output::Mode {
|
||||
let mode = Box::new(simple_text_output::Mode {
|
||||
max_mode: 0,
|
||||
mode: 0,
|
||||
attribute: 0,
|
||||
@ -550,8 +569,7 @@ pub fn null() -> Self {
|
||||
clear_screen: Self::clear_screen,
|
||||
set_cursor_position: Self::set_cursor_position,
|
||||
enable_cursor: Self::enable_cursor,
|
||||
mode: mode.as_mut(),
|
||||
_mode: mode,
|
||||
mode: Box::into_raw(mode),
|
||||
_buffer: Vec::new(),
|
||||
}
|
||||
}
|
||||
@ -660,4 +678,12 @@ extern "efiapi" fn enable_cursor(
|
||||
r_efi::efi::Status::UNSUPPORTED
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for PipeProtocol {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let _ = Box::from_raw(self.mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user