Skip to content

Commit e918445

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 bba9b48 commit e918445

File tree

2 files changed

+91
-76
lines changed

2 files changed

+91
-76
lines changed

Diff for: library/std/src/sys/pal/uefi/helpers.rs

+14-24
Original file line numberDiff line numberDiff line change
@@ -292,33 +292,25 @@ 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>,
298-
protocol: Box<T>,
298+
protocol: *mut T,
299299
}
300300

301-
impl<T> Protocol<T> {
302-
const fn new(
303-
guid: r_efi::efi::Guid,
304-
handle: NonNull<crate::ffi::c_void>,
305-
protocol: Box<T>,
306-
) -> Self {
307-
Self { guid, handle, protocol }
308-
}
309-
301+
impl<T> OwnedProtocol<T> {
310302
pub(crate) fn create(protocol: T, mut guid: r_efi::efi::Guid) -> io::Result<Self> {
311303
let boot_services: NonNull<r_efi::efi::BootServices> =
312304
boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
313-
let mut protocol = Box::new(protocol);
305+
let protocol: *mut T = Box::into_raw(Box::new(protocol));
314306
let mut handle: r_efi::efi::Handle = crate::ptr::null_mut();
315307

316308
let r = unsafe {
317309
((*boot_services.as_ptr()).install_protocol_interface)(
318310
&mut handle,
319311
&mut guid,
320312
r_efi::efi::NATIVE_INTERFACE,
321-
protocol.as_mut() as *mut T as *mut crate::ffi::c_void,
313+
protocol as *mut crate::ffi::c_void,
322314
)
323315
};
324316

@@ -329,37 +321,35 @@ impl<T> Protocol<T> {
329321
let handle = NonNull::new(handle)
330322
.ok_or(io::const_io_error!(io::ErrorKind::Uncategorized, "found null handle"))?;
331323

332-
Ok(Self::new(guid, handle, protocol))
324+
Ok(Self { guid, handle, protocol })
333325
}
334326

335327
pub(crate) fn handle(&self) -> NonNull<crate::ffi::c_void> {
336328
self.handle
337329
}
338330
}
339331

340-
impl<T> Drop for Protocol<T> {
332+
impl<T> Drop for OwnedProtocol<T> {
341333
fn drop(&mut self) {
342334
if let Some(bt) = boot_services() {
343335
let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
344336
unsafe {
345337
((*bt.as_ptr()).uninstall_protocol_interface)(
346338
self.handle.as_ptr(),
347339
&mut self.guid,
348-
self.protocol.as_mut() as *mut T as *mut crate::ffi::c_void,
340+
self.protocol as *mut crate::ffi::c_void,
349341
)
350342
};
351343
}
352-
}
353-
}
354344

355-
impl<T> AsRef<T> for Protocol<T> {
356-
fn as_ref(&self) -> &T {
357-
&self.protocol
345+
let _ = unsafe { Box::from_raw(self.protocol) };
358346
}
359347
}
360348

361-
impl<T> AsMut<T> for Protocol<T> {
362-
fn as_mut(&mut self) -> &mut T {
363-
&mut self.protocol
349+
impl<T> AsRef<T> for OwnedProtocol<T> {
350+
fn as_ref(&self) -> &T {
351+
unsafe {
352+
self.protocol.as_ref().unwrap()
353+
}
364354
}
365355
}

Diff for: 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(Stdio::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(Stdio::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)