Skip to content

Commit a5e43be

Browse files
committed
Expand sys/os for UEFI
- Implement current_exe() and getcwd() Signed-off-by: Ayush Singh <[email protected]>
1 parent 04521fd commit a5e43be

File tree

2 files changed

+61
-6
lines changed

2 files changed

+61
-6
lines changed

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

+52-3
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@
1010
//! - More information about protocols can be found [here](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/3_foundation/36_protocols_and_handles)
1111
1212
use r_efi::efi::{self, Guid};
13+
use r_efi::protocols::{device_path, device_path_to_text};
1314

15+
use crate::alloc::Layout;
16+
use crate::ffi::OsString;
1417
use crate::mem::{size_of, MaybeUninit};
1518
use crate::os::uefi;
19+
use crate::os::uefi::ffi::OsStringExt;
1620
use crate::ptr::NonNull;
21+
use crate::slice;
22+
use crate::sys_common::wstr::WStrUnits;
1723
use crate::{
1824
io::{self, const_io_error},
1925
os::uefi::env::boot_services,
@@ -142,7 +148,50 @@ pub(crate) unsafe fn close_event(evt: NonNull<crate::ffi::c_void>) -> io::Result
142148

143149
/// Get the Protocol for current system handle.
144150
/// Note: Some protocols need to be manually freed. It is the callers responsibility to do so.
145-
pub(crate) fn image_handle_protocol<T>(protocol_guid: Guid) -> Option<NonNull<T>> {
146-
let system_handle = uefi::env::try_image_handle()?;
147-
open_protocol(system_handle, protocol_guid).ok()
151+
pub(crate) fn image_handle_protocol<T>(protocol_guid: Guid) -> io::Result<NonNull<T>> {
152+
let system_handle = uefi::env::try_image_handle().ok_or(io::const_io_error!(
153+
io::ErrorKind::NotFound,
154+
"Protocol not found in Image handle"
155+
))?;
156+
open_protocol(system_handle, protocol_guid)
157+
}
158+
159+
pub(crate) fn device_path_to_text(path: *mut device_path::Protocol) -> io::Result<OsString> {
160+
let device_path_to_text_handles = locate_handles(device_path_to_text::PROTOCOL_GUID)?;
161+
for handle in device_path_to_text_handles {
162+
let Ok(protocol) = open_protocol::<device_path_to_text::Protocol>(
163+
handle,
164+
device_path_to_text::PROTOCOL_GUID,
165+
) else {
166+
continue;
167+
};
168+
169+
let path_ptr: *mut r_efi::efi::Char16 = unsafe {
170+
((*protocol.as_ptr()).convert_device_path_to_text)(
171+
path,
172+
r_efi::efi::Boolean::FALSE,
173+
r_efi::efi::Boolean::FALSE,
174+
)
175+
};
176+
177+
// SAFETY: Error only occurs if path is NULL. Thus no need to dealloc path_ptr
178+
let path_len = unsafe {
179+
WStrUnits::new(path_ptr)
180+
.ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))?
181+
.count()
182+
};
183+
184+
let path = OsString::from_wide(unsafe { slice::from_raw_parts(path_ptr.cast(), path_len) });
185+
186+
unsafe {
187+
// UEFI Spec says all allocations are 8 byte aligned
188+
crate::alloc::dealloc(
189+
path_ptr.cast(),
190+
Layout::from_size_align_unchecked(path_len * size_of::<u16>(), 8),
191+
);
192+
}
193+
return Ok(path);
194+
}
195+
196+
Err(io::const_io_error!(io::ErrorKind::NotFound, "No device path to text protocol found"))
148197
}

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

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{unsupported, RawOsError};
1+
use super::{helpers, unsupported, RawOsError};
22
use crate::error::Error as StdError;
33
use crate::ffi::{OsStr, OsString};
44
use crate::fmt;
@@ -7,6 +7,7 @@ use crate::marker::PhantomData;
77
use crate::os::uefi;
88
use crate::path::{self, PathBuf};
99
use crate::ptr::NonNull;
10+
use r_efi::efi::protocols::{device_path, loaded_image_device_path};
1011
use r_efi::efi::Status;
1112

1213
pub fn errno() -> RawOsError {
@@ -124,7 +125,9 @@ pub fn error_string(errno: RawOsError) -> String {
124125
}
125126

126127
pub fn getcwd() -> io::Result<PathBuf> {
127-
unsupported()
128+
let mut p = current_exe()?;
129+
p.pop();
130+
Ok(p)
128131
}
129132

130133
pub fn chdir(_: &path::Path) -> io::Result<()> {
@@ -164,7 +167,10 @@ impl fmt::Display for JoinPathsError {
164167
impl StdError for JoinPathsError {}
165168

166169
pub fn current_exe() -> io::Result<PathBuf> {
167-
unsupported()
170+
let protocol = helpers::image_handle_protocol::<device_path::Protocol>(
171+
loaded_image_device_path::PROTOCOL_GUID,
172+
)?;
173+
helpers::device_path_to_text(protocol.as_ptr()).map(PathBuf::from)
168174
}
169175

170176
pub struct Env(!);

0 commit comments

Comments
 (0)