|  | 
| 1 | 1 | use r_efi::efi::protocols::{device_path, loaded_image_device_path}; | 
| 2 | 2 | use r_efi::efi::Status; | 
| 3 | 3 | 
 | 
| 4 |  | -use super::{helpers, unsupported, RawOsError}; | 
|  | 4 | +use super::{helpers, unsupported_err, RawOsError}; | 
| 5 | 5 | use crate::error::Error as StdError; | 
| 6 | 6 | use crate::ffi::{OsStr, OsString}; | 
| 7 | 7 | use crate::marker::PhantomData; | 
| @@ -125,11 +125,32 @@ pub fn error_string(errno: RawOsError) -> String { | 
| 125 | 125 | } | 
| 126 | 126 | 
 | 
| 127 | 127 | pub fn getcwd() -> io::Result<PathBuf> { | 
| 128 |  | -    unsupported() | 
|  | 128 | +    match uefi_shell::open_shell() { | 
|  | 129 | +        Some(shell) => { | 
|  | 130 | +            // SAFETY: path_ptr is managed by UEFI shell and should not be deallocated | 
|  | 131 | +            let path_ptr = unsafe { ((*shell.as_ptr()).get_cur_dir)(crate::ptr::null_mut()) }; | 
|  | 132 | +            helpers::os_string_from_raw(path_ptr) | 
|  | 133 | +                .map(PathBuf::from) | 
|  | 134 | +                .ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path")) | 
|  | 135 | +        } | 
|  | 136 | +        None => { | 
|  | 137 | +            let mut t = current_exe()?; | 
|  | 138 | +            // SAFETY: This should never fail since the disk prefix will be present even for root | 
|  | 139 | +            // executables | 
|  | 140 | +            assert!(t.pop()); | 
|  | 141 | +            Ok(t) | 
|  | 142 | +        } | 
|  | 143 | +    } | 
| 129 | 144 | } | 
| 130 | 145 | 
 | 
| 131 |  | -pub fn chdir(_: &path::Path) -> io::Result<()> { | 
| 132 |  | -    unsupported() | 
|  | 146 | +pub fn chdir(p: &path::Path) -> io::Result<()> { | 
|  | 147 | +    let shell = uefi_shell::open_shell().ok_or(unsupported_err())?; | 
|  | 148 | + | 
|  | 149 | +    let mut p = helpers::os_string_to_raw(p.as_os_str()) | 
|  | 150 | +        .ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))?; | 
|  | 151 | + | 
|  | 152 | +    let r = unsafe { ((*shell.as_ptr()).set_cur_dir)(crate::ptr::null_mut(), p.as_mut_ptr()) }; | 
|  | 153 | +    if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } | 
| 133 | 154 | } | 
| 134 | 155 | 
 | 
| 135 | 156 | pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); | 
| @@ -239,3 +260,37 @@ pub fn exit(code: i32) -> ! { | 
| 239 | 260 | pub fn getpid() -> u32 { | 
| 240 | 261 |     panic!("no pids on this platform") | 
| 241 | 262 | } | 
|  | 263 | + | 
|  | 264 | +mod uefi_shell { | 
|  | 265 | +    use r_efi::protocols::shell; | 
|  | 266 | + | 
|  | 267 | +    use super::super::helpers; | 
|  | 268 | +    use crate::ptr::NonNull; | 
|  | 269 | +    use crate::sync::atomic::{AtomicPtr, Ordering}; | 
|  | 270 | + | 
|  | 271 | +    pub fn open_shell() -> Option<NonNull<shell::Protocol>> { | 
|  | 272 | +        static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> = | 
|  | 273 | +            AtomicPtr::new(crate::ptr::null_mut()); | 
|  | 274 | + | 
|  | 275 | +        if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) { | 
|  | 276 | +            if let Ok(protocol) = helpers::open_protocol::<shell::Protocol>( | 
|  | 277 | +                handle, | 
|  | 278 | +                r_efi::protocols::shell::PROTOCOL_GUID, | 
|  | 279 | +            ) { | 
|  | 280 | +                return Some(protocol); | 
|  | 281 | +            } | 
|  | 282 | +        } | 
|  | 283 | + | 
|  | 284 | +        let handles = helpers::locate_handles(shell::PROTOCOL_GUID).ok()?; | 
|  | 285 | +        for handle in handles { | 
|  | 286 | +            if let Ok(protocol) = | 
|  | 287 | +                helpers::open_protocol::<shell::Protocol>(handle, shell::PROTOCOL_GUID) | 
|  | 288 | +            { | 
|  | 289 | +                LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release); | 
|  | 290 | +                return Some(protocol); | 
|  | 291 | +            } | 
|  | 292 | +        } | 
|  | 293 | + | 
|  | 294 | +        None | 
|  | 295 | +    } | 
|  | 296 | +} | 
0 commit comments