Skip to content

Commit cbe87cc

Browse files
committed
uefi: process: Fixes from PR
- Update system table crc32 - Fix unsound use of Box - Free exit data - Code improvements Signed-off-by: Ayush Singh <[email protected]>
1 parent 1490a7d commit cbe87cc

File tree

2 files changed

+81
-62
lines changed

2 files changed

+81
-62
lines changed

library/std/src/sys/pal/uefi/helpers.rs

+4-10
Original file line numberDiff line numberDiff line change
@@ -292,13 +292,13 @@ impl Drop for DevicePath {
292292
}
293293
}
294294

295-
pub(crate) struct Protocol<T> {
295+
pub(crate) struct OwnedProtocol<T> {
296296
guid: r_efi::efi::Guid,
297297
handle: NonNull<crate::ffi::c_void>,
298298
protocol: Box<T>,
299299
}
300300

301-
impl<T> Protocol<T> {
301+
impl<T> OwnedProtocol<T> {
302302
const fn new(
303303
guid: r_efi::efi::Guid,
304304
handle: NonNull<crate::ffi::c_void>,
@@ -337,7 +337,7 @@ impl<T> Protocol<T> {
337337
}
338338
}
339339

340-
impl<T> Drop for Protocol<T> {
340+
impl<T> Drop for OwnedProtocol<T> {
341341
fn drop(&mut self) {
342342
if let Some(bt) = boot_services() {
343343
let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
@@ -352,14 +352,8 @@ impl<T> Drop for Protocol<T> {
352352
}
353353
}
354354

355-
impl<T> AsRef<T> for Protocol<T> {
355+
impl<T> AsRef<T> for OwnedProtocol<T> {
356356
fn as_ref(&self) -> &T {
357357
&self.protocol
358358
}
359359
}
360-
361-
impl<T> AsMut<T> for Protocol<T> {
362-
fn as_mut(&mut self) -> &mut T {
363-
&mut self.protocol
364-
}
365-
}

library/std/src/sys/pal/uefi/process.rs

+77-52
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub struct StdioPipes {
3535
pub stderr: Option<AnonPipe>,
3636
}
3737

38+
#[derive(Copy, Clone)]
3839
pub enum Stdio {
3940
Inherit,
4041
Null,
@@ -96,14 +97,14 @@ impl Command {
9697

9798
fn create_pipe(
9899
s: Stdio,
99-
) -> io::Result<Option<helpers::Protocol<uefi_command_internal::PipeProtocol>>> {
100+
) -> io::Result<Option<helpers::OwnedProtocol<uefi_command_internal::PipeProtocol>>> {
100101
match s {
101-
Stdio::MakePipe => helpers::Protocol::create(
102+
Stdio::MakePipe => helpers::OwnedProtocol::create(
102103
uefi_command_internal::PipeProtocol::new(),
103104
simple_text_output::PROTOCOL_GUID,
104105
)
105106
.map(Some),
106-
Stdio::Null => helpers::Protocol::create(
107+
Stdio::Null => helpers::OwnedProtocol::create(
107108
uefi_command_internal::PipeProtocol::null(),
108109
simple_text_output::PROTOCOL_GUID,
109110
)
@@ -116,36 +117,24 @@ impl Command {
116117
let mut cmd = uefi_command_internal::Command::load_image(&self.prog)?;
117118

118119
/* Setup Stdout */
119-
let stdout: Option<helpers::Protocol<uefi_command_internal::PipeProtocol>> =
120-
match self.stdout.take() {
121-
Some(s) => Self::create_pipe(s),
122-
None => helpers::Protocol::create(
123-
uefi_command_internal::PipeProtocol::new(),
124-
simple_text_output::PROTOCOL_GUID,
125-
)
126-
.map(Some),
127-
}?;
128-
match stdout {
129-
Some(stdout) => cmd.stdout_init(stdout),
130-
None => cmd.stdout_inherit(),
120+
let stdout = self.stdout.unwrap_or(Stdout::MakePipe);
121+
let stdout = Self::create_pipe(stdout)?;
122+
if let Some(con) = stdout {
123+
cmd.stdout_init(con)
124+
} else {
125+
cmd.stdout_inherit()
131126
};
132127

133128
/* Setup Stderr */
134-
let stderr: Option<helpers::Protocol<uefi_command_internal::PipeProtocol>> =
135-
match self.stderr.take() {
136-
Some(s) => Self::create_pipe(s),
137-
None => helpers::Protocol::create(
138-
uefi_command_internal::PipeProtocol::new(),
139-
simple_text_output::PROTOCOL_GUID,
140-
)
141-
.map(Some),
142-
}?;
143-
match stderr {
144-
Some(stderr) => cmd.stderr_init(stderr),
145-
None => cmd.stderr_inherit(),
129+
let stderr = self.stderr.unwrap_or(Stdout::MakePipe);
130+
let stderr = Self::create_pipe(stderr)?;
131+
if let Some(con) = stderr {
132+
cmd.stderr_init(con)
133+
} else {
134+
cmd.stderr_inherit()
146135
};
147136

148-
/* No reason to set args if only program name is preset */
137+
// No reason to set args if only program name is preset
149138
if !self.args.is_empty() {
150139
let args = self.args.iter().fold(OsString::from(&self.prog), |mut acc, arg| {
151140
acc.push(" ");
@@ -341,8 +330,8 @@ mod uefi_command_internal {
341330

342331
pub struct Command {
343332
handle: NonNull<crate::ffi::c_void>,
344-
stdout: Option<helpers::Protocol<PipeProtocol>>,
345-
stderr: Option<helpers::Protocol<PipeProtocol>>,
333+
stdout: Option<helpers::OwnedProtocol<PipeProtocol>>,
334+
stderr: Option<helpers::OwnedProtocol<PipeProtocol>>,
346335
st: Box<r_efi::efi::SystemTable>,
347336
args: Option<Vec<u16>>,
348337
}
@@ -382,45 +371,52 @@ mod uefi_command_internal {
382371

383372
let loaded_image: NonNull<loaded_image::Protocol> =
384373
helpers::open_protocol(child_handle, loaded_image::PROTOCOL_GUID).unwrap();
385-
let mut st: Box<r_efi::efi::SystemTable> =
374+
let st: Box<r_efi::efi::SystemTable> =
386375
Box::new(unsafe { crate::ptr::read((*loaded_image.as_ptr()).system_table) });
387376

388-
unsafe {
389-
(*loaded_image.as_ptr()).system_table = st.as_mut();
390-
}
391-
392377
Ok(Self::new(child_handle, st))
393378
}
394379
}
395380

396-
pub fn start_image(&self) -> io::Result<r_efi::efi::Status> {
381+
pub fn start_image(&mut self) -> io::Result<r_efi::efi::Status> {
382+
self.update_st_crc32()?;
383+
384+
// Use our system table instead of the default one
385+
let loaded_image: NonNull<loaded_image::Protocol> =
386+
helpers::open_protocol(self.handle, loaded_image::PROTOCOL_GUID).unwrap();
387+
unsafe {
388+
(*loaded_image.as_ptr()).system_table = self.st.as_mut();
389+
}
390+
397391
let boot_services: NonNull<r_efi::efi::BootServices> = boot_services()
398392
.ok_or_else(|| const_io_error!(io::ErrorKind::NotFound, "Boot Services not found"))?
399393
.cast();
400-
let mut exit_data_size: MaybeUninit<usize> = MaybeUninit::uninit();
394+
let mut exit_data_size: usize = 0;
401395
let mut exit_data: MaybeUninit<*mut u16> = MaybeUninit::uninit();
402396

403397
let r = unsafe {
404398
((*boot_services.as_ptr()).start_image)(
405399
self.handle.as_ptr(),
406-
exit_data_size.as_mut_ptr(),
400+
&mut exit_data_size,
407401
exit_data.as_mut_ptr(),
408402
)
409403
};
410404

411405
// Drop exitdata
412-
unsafe {
413-
exit_data_size.assume_init_drop();
414-
exit_data.assume_init_drop();
406+
if exit_data_size != 0 {
407+
unsafe {
408+
let exit_data = exit_data.assume_init();
409+
((*boot_services.as_ptr()).free_pool)(exit_data as *mut crate::ffi::c_void);
410+
}
415411
}
416412

417413
Ok(r)
418414
}
419415

420-
pub fn stdout_init(&mut self, mut protocol: helpers::Protocol<PipeProtocol>) {
416+
pub fn stdout_init(&mut self, protocol: helpers::OwnedProtocol<PipeProtocol>) {
421417
self.st.console_out_handle = protocol.handle().as_ptr();
422418
self.st.con_out =
423-
protocol.as_mut() as *mut PipeProtocol as *mut simple_text_output::Protocol;
419+
protocol.as_ref() as *const PipeProtocol as *mut simple_text_output::Protocol;
424420

425421
self.stdout = Some(protocol);
426422
}
@@ -432,10 +428,10 @@ mod uefi_command_internal {
432428
self.st.con_out = unsafe { (*st.as_ptr()).con_out };
433429
}
434430

435-
pub fn stderr_init(&mut self, mut protocol: helpers::Protocol<PipeProtocol>) {
431+
pub fn stderr_init(&mut self, protocol: helpers::OwnedProtocol<PipeProtocol>) {
436432
self.st.standard_error_handle = protocol.handle().as_ptr();
437433
self.st.std_err =
438-
protocol.as_mut() as *mut PipeProtocol as *mut simple_text_output::Protocol;
434+
protocol.as_ref() as *const PipeProtocol as *mut simple_text_output::Protocol;
439435

440436
self.stderr = Some(protocol);
441437
}
@@ -476,6 +472,30 @@ mod uefi_command_internal {
476472

477473
self.args = Some(args);
478474
}
475+
476+
fn update_st_crc32(&mut self) -> io::Result<()> {
477+
let bt: NonNull<r_efi::efi::BootServices> = boot_services().unwrap().cast();
478+
let st_size = self.st.hdr.header_size as usize;
479+
let mut crc32: u32 = 0;
480+
481+
// Set crc to 0 before calcuation
482+
self.st.hdr.crc32 = 0;
483+
484+
let r = unsafe {
485+
((*bt.as_ptr()).calculate_crc32)(
486+
self.st.as_mut() as *mut r_efi::efi::SystemTable as *mut crate::ffi::c_void,
487+
st_size,
488+
&mut crc32,
489+
)
490+
};
491+
492+
if r.is_error() {
493+
Err(io::Error::from_raw_os_error(r.as_usize()))
494+
} else {
495+
self.st.hdr.crc32 = crc32;
496+
Ok(())
497+
}
498+
}
479499
}
480500

481501
impl Drop for Command {
@@ -501,13 +521,12 @@ mod uefi_command_internal {
501521
set_cursor_position: simple_text_output::ProtocolSetCursorPosition,
502522
enable_cursor: simple_text_output::ProtocolEnableCursor,
503523
mode: *mut simple_text_output::Mode,
504-
_mode: Box<simple_text_output::Mode>,
505524
_buffer: Vec<u16>,
506525
}
507526

508527
impl PipeProtocol {
509528
pub fn new() -> Self {
510-
let mut mode = Box::new(simple_text_output::Mode {
529+
let mode = Box::new(simple_text_output::Mode {
511530
max_mode: 0,
512531
mode: 0,
513532
attribute: 0,
@@ -525,14 +544,13 @@ mod uefi_command_internal {
525544
clear_screen: Self::clear_screen,
526545
set_cursor_position: Self::set_cursor_position,
527546
enable_cursor: Self::enable_cursor,
528-
mode: mode.as_mut(),
529-
_mode: mode,
547+
mode: Box::into_raw(mode),
530548
_buffer: Vec::new(),
531549
}
532550
}
533551

534552
pub fn null() -> Self {
535-
let mut mode = Box::new(simple_text_output::Mode {
553+
let mode = Box::new(simple_text_output::Mode {
536554
max_mode: 0,
537555
mode: 0,
538556
attribute: 0,
@@ -550,8 +568,7 @@ mod uefi_command_internal {
550568
clear_screen: Self::clear_screen,
551569
set_cursor_position: Self::set_cursor_position,
552570
enable_cursor: Self::enable_cursor,
553-
mode: mode.as_mut(),
554-
_mode: mode,
571+
mode: Box::into_raw(mode),
555572
_buffer: Vec::new(),
556573
}
557574
}
@@ -660,4 +677,12 @@ mod uefi_command_internal {
660677
r_efi::efi::Status::UNSUPPORTED
661678
}
662679
}
680+
681+
impl Drop for PipeProtocol {
682+
fn drop(&mut self) {
683+
unsafe {
684+
let _ = Box::from_raw(self.mode);
685+
}
686+
}
687+
}
663688
}

0 commit comments

Comments
 (0)