|
1 | 1 | use r_efi::efi::Status; |
2 | 2 | use r_efi::efi::protocols::{device_path, loaded_image_device_path}; |
3 | 3 |
|
4 | | -usesuper::{RawOsError, helpers,unsupported}; |
| 4 | +usesuper::{RawOsError, helpers,unsupported_err}; |
5 | 5 | usecrate::error::ErrorasStdError; |
6 | 6 | usecrate::ffi::{OsStr,OsString}; |
7 | 7 | usecrate::marker::PhantomData; |
@@ -125,11 +125,32 @@ pub fn error_string(errno: RawOsError) -> String { |
125 | 125 | } |
126 | 126 |
|
127 | 127 | pubfngetcwd() -> 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 | +letmut 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 | | -pubfnchdir(_:&path::Path) -> io::Result<()>{ |
132 | | -unsupported() |
| 146 | +pubfnchdir(p:&path::Path) -> io::Result<()>{ |
| 147 | +let shell = uefi_shell::open_shell().ok_or(unsupported_err())?; |
| 148 | + |
| 149 | +letmut 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 | pubstructSplitPaths<'a>(!,PhantomData<&'a()>); |
@@ -239,3 +260,37 @@ pub fn exit(code: i32) -> ! { |
239 | 260 | pubfngetpid() -> u32{ |
240 | 261 | panic!("no pids on this platform") |
241 | 262 | } |
| 263 | + |
| 264 | +mod uefi_shell { |
| 265 | +use r_efi::protocols::shell; |
| 266 | + |
| 267 | +usesuper::super::helpers; |
| 268 | +usecrate::ptr::NonNull; |
| 269 | +usecrate::sync::atomic::{AtomicPtr,Ordering}; |
| 270 | + |
| 271 | +pubfnopen_shell() -> Option<NonNull<shell::Protocol>>{ |
| 272 | +staticLAST_VALID_HANDLE:AtomicPtr<crate::ffi::c_void> = |
| 273 | +AtomicPtr::new(crate::ptr::null_mut()); |
| 274 | + |
| 275 | +ifletSome(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)){ |
| 276 | +ifletOk(protocol) = helpers::open_protocol::<shell::Protocol>( |
| 277 | + handle, |
| 278 | + r_efi::protocols::shell::PROTOCOL_GUID, |
| 279 | +){ |
| 280 | +returnSome(protocol); |
| 281 | +} |
| 282 | +} |
| 283 | + |
| 284 | +let handles = helpers::locate_handles(shell::PROTOCOL_GUID).ok()?; |
| 285 | +for handle in handles { |
| 286 | +ifletOk(protocol) = |
| 287 | + helpers::open_protocol::<shell::Protocol>(handle, shell::PROTOCOL_GUID) |
| 288 | +{ |
| 289 | +LAST_VALID_HANDLE.store(handle.as_ptr(),Ordering::Release); |
| 290 | +returnSome(protocol); |
| 291 | +} |
| 292 | +} |
| 293 | + |
| 294 | +None |
| 295 | +} |
| 296 | +} |
0 commit comments