@@ -286,8 +286,13 @@ pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
286286 unsupported ( )
287287}
288288
289- pub fn exists ( _path : & Path ) -> io:: Result < bool > {
290- unsupported ( )
289+ pub fn exists ( path : & Path ) -> io:: Result < bool > {
290+ let f = uefi_fs:: File :: from_path ( path, r_efi:: protocols:: file:: MODE_READ , 0 ) ;
291+ match f {
292+ Ok ( _) => Ok ( true ) ,
293+ Err ( e) if e. kind ( ) == io:: ErrorKind :: NotFound => Ok ( false ) ,
294+ Err ( e) => Err ( e) ,
295+ }
291296}
292297
293298pub fn readlink ( _p : & Path ) -> io:: Result < PathBuf > {
@@ -317,3 +322,122 @@ pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
317322pub fn copy ( _from : & Path , _to : & Path ) -> io:: Result < u64 > {
318323 unsupported ( )
319324}
325+
326+ mod uefi_fs {
327+ use r_efi:: protocols:: { device_path, file, simple_file_system} ;
328+
329+ use crate :: boxed:: Box ;
330+ use crate :: io;
331+ use crate :: mem:: MaybeUninit ;
332+ use crate :: path:: Path ;
333+ use crate :: ptr:: NonNull ;
334+ use crate :: sys:: helpers;
335+
336+ pub ( crate ) struct File ( NonNull < file:: Protocol > ) ;
337+
338+ impl File {
339+ pub ( crate ) fn from_path ( path : & Path , open_mode : u64 , attr : u64 ) -> io:: Result < Self > {
340+ let absoulte = crate :: path:: absolute ( path) ?;
341+
342+ let p = helpers:: OwnedDevicePath :: from_text ( absoulte. as_os_str ( ) ) ?;
343+ let ( vol, mut path_remaining) = Self :: open_volume_from_device_path ( p. borrow ( ) ) ?;
344+
345+ vol. open ( & mut path_remaining, open_mode, attr)
346+ }
347+
348+ fn open_volume_from_device_path (
349+ path : helpers:: BorrowedDevicePath < ' _ > ,
350+ ) -> io:: Result < ( Self , Box < [ u16 ] > ) > {
351+ let handles = match helpers:: locate_handles ( simple_file_system:: PROTOCOL_GUID ) {
352+ Ok ( x) => x,
353+ Err ( e) => return Err ( e) ,
354+ } ;
355+ for handle in handles {
356+ let volume_device_path: NonNull < device_path:: Protocol > =
357+ match helpers:: open_protocol ( handle, device_path:: PROTOCOL_GUID ) {
358+ Ok ( x) => x,
359+ Err ( _) => continue ,
360+ } ;
361+ let volume_device_path = helpers:: BorrowedDevicePath :: new ( volume_device_path) ;
362+
363+ if let Some ( left_path) = path_best_match ( & volume_device_path, & path) {
364+ return Ok ( ( Self :: open_volume ( handle) ?, left_path) ) ;
365+ }
366+ }
367+
368+ Err ( io:: const_error!( io:: ErrorKind :: NotFound , "Volume Not Found" ) )
369+ }
370+
371+ // Open volume on device_handle using SIMPLE_FILE_SYSTEM_PROTOCOL
372+ fn open_volume ( device_handle : NonNull < crate :: ffi:: c_void > ) -> io:: Result < Self > {
373+ let simple_file_system_protocol = helpers:: open_protocol :: < simple_file_system:: Protocol > (
374+ device_handle,
375+ simple_file_system:: PROTOCOL_GUID ,
376+ ) ?;
377+
378+ let mut file_protocol: MaybeUninit < * mut file:: Protocol > = MaybeUninit :: uninit ( ) ;
379+ let r = unsafe {
380+ ( ( * simple_file_system_protocol. as_ptr ( ) ) . open_volume ) (
381+ simple_file_system_protocol. as_ptr ( ) ,
382+ file_protocol. as_mut_ptr ( ) ,
383+ )
384+ } ;
385+ if r. is_error ( ) {
386+ return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
387+ }
388+
389+ // Since no error was returned, file protocol should be non-NULL.
390+ let p = NonNull :: new ( unsafe { file_protocol. assume_init ( ) } ) . unwrap ( ) ;
391+ Ok ( Self ( p) )
392+ }
393+
394+ fn open ( & self , path : & mut [ u16 ] , open_mode : u64 , attr : u64 ) -> io:: Result < Self > {
395+ let file_ptr = self . 0 . as_ptr ( ) ;
396+ let mut file_opened: MaybeUninit < * mut file:: Protocol > = MaybeUninit :: uninit ( ) ;
397+
398+ let r = unsafe {
399+ ( ( * file_ptr) . open ) (
400+ file_ptr,
401+ file_opened. as_mut_ptr ( ) ,
402+ path. as_mut_ptr ( ) ,
403+ open_mode,
404+ attr,
405+ )
406+ } ;
407+
408+ if r. is_error ( ) {
409+ return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
410+ }
411+
412+ // Since no error was returned, file protocol should be non-NULL.
413+ let p = NonNull :: new ( unsafe { file_opened. assume_init ( ) } ) . unwrap ( ) ;
414+ Ok ( File ( p) )
415+ }
416+ }
417+
418+ impl Drop for File {
419+ fn drop ( & mut self ) {
420+ let file_ptr = self . 0 . as_ptr ( ) ;
421+ let _ = unsafe { ( ( * self . 0 . as_ptr ( ) ) . close ) ( file_ptr) } ;
422+ }
423+ }
424+
425+ fn path_best_match < ' a > (
426+ source : & helpers:: BorrowedDevicePath < ' a > ,
427+ target : & helpers:: BorrowedDevicePath < ' a > ,
428+ ) -> Option < Box < [ u16 ] > > {
429+ let mut source_iter = source. iter ( ) . take_while ( |x| !x. is_end_instance ( ) ) ;
430+ let mut target_iter = target. iter ( ) . take_while ( |x| !x. is_end_instance ( ) ) ;
431+
432+ loop {
433+ match ( source_iter. next ( ) , target_iter. next ( ) ) {
434+ ( Some ( x) , Some ( y) ) if x == y => continue ,
435+ ( None , Some ( y) ) => {
436+ let p = y. to_path ( ) . to_text ( ) . ok ( ) ?;
437+ return helpers:: os_string_to_raw ( & p) ;
438+ }
439+ _ => return None ,
440+ }
441+ }
442+ }
443+ }
0 commit comments