uefi_std/
fs.rs

1use core::default::Default;
2use core::{mem, ptr, slice};
3
4use uefi::fs::{File as InnerFile, FileInfo, SimpleFileSystem, FILE_MODE_READ};
5
6use crate::ffi::wstr;
7use crate::prelude::*;
8use crate::proto::Protocol;
9
10pub struct FileSystem(pub &'static mut SimpleFileSystem);
11
12impl Protocol<SimpleFileSystem> for FileSystem {
13    fn guid() -> Guid {
14        SimpleFileSystem::GUID
15    }
16
17    fn new(inner: &'static mut SimpleFileSystem) -> Self {
18        FileSystem(inner)
19    }
20}
21
22impl FileSystem {
23    pub fn root(&mut self) -> Result<Dir> {
24        let mut interface = ptr::null_mut::<InnerFile>();
25        let status = (self.0.OpenVolume)(self.0, &mut interface);
26
27        match status {
28            Status::SUCCESS => Ok(Dir(File(unsafe { &mut *interface }))),
29            _ => Err(status),
30        }
31    }
32}
33
34pub struct File(pub &'static mut InnerFile);
35
36impl File {
37    pub fn info(&mut self) -> Result<FileInfo> {
38        let mut info = FileInfo::default();
39        let buf = unsafe {
40            slice::from_raw_parts_mut(&mut info as *mut _ as *mut u8, mem::size_of_val(&info))
41        };
42        let mut len = buf.len();
43        let status = (self.0.GetInfo)(self.0, &FileInfo::ID, &mut len, buf.as_mut_ptr());
44
45        match status {
46            Status::SUCCESS => Ok(info),
47            _ => Err(status),
48        }
49    }
50
51    pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
52        let mut len = buf.len();
53        let status = (self.0.Read)(self.0, &mut len, buf.as_mut_ptr());
54
55        match status {
56            Status::SUCCESS => Ok(len),
57            _ => Err(status),
58        }
59    }
60
61    pub fn read_to_end(&mut self, vec: &mut Vec<u8>) -> Result<usize> {
62        let mut total = 0;
63
64        loop {
65            let mut buf = [0; 8192];
66
67            let count = self.read(&mut buf)?;
68            if count == 0 {
69                break;
70            }
71
72            vec.extend(&buf[..count]);
73            total += count;
74        }
75
76        Ok(total)
77    }
78
79    pub fn write(&mut self, buf: &[u8]) -> Result<usize> {
80        let mut len = buf.len();
81        let status = (self.0.Write)(self.0, &mut len, buf.as_ptr());
82
83        match status {
84            Status::SUCCESS => Ok(len),
85            _ => Err(status),
86        }
87    }
88}
89
90impl Drop for File {
91    fn drop(&mut self) {
92        let _ = (self.0.Close)(self.0);
93    }
94}
95
96pub struct Dir(pub File);
97
98impl Dir {
99    pub fn open(&mut self, filename: &[u16]) -> Result<File> {
100        let mut interface = ptr::null_mut::<InnerFile>();
101        let status = ((self.0).0.Open)(
102            (self.0).0,
103            &mut interface,
104            filename.as_ptr(),
105            FILE_MODE_READ,
106            0,
107        );
108
109        match status {
110            Status::SUCCESS => Ok(File(unsafe { &mut *interface })),
111            _ => Err(status),
112        }
113    }
114
115    pub fn open_dir(&mut self, filename: &[u16]) -> Result<Dir> {
116        let file = self.open(filename)?;
117        Ok(Dir(file))
118    }
119
120    pub fn read(&mut self) -> Result<Option<FileInfo>> {
121        let mut info = FileInfo::default();
122        let buf = unsafe {
123            slice::from_raw_parts_mut(&mut info as *mut _ as *mut u8, mem::size_of_val(&info))
124        };
125        match self.0.read(buf) {
126            Ok(0) => Ok(None),
127            Ok(_len) => Ok(Some(info)),
128            Err(err) => Err(err),
129        }
130    }
131}
132
133pub fn find(path: &str) -> Result<(usize, File)> {
134    let wpath = wstr(path);
135
136    for (i, fs) in FileSystem::all().iter_mut().enumerate() {
137        // Errors are ignored as they may not be related to opening the matching file
138        if let Ok(mut root) = fs.root() {
139            if let Ok(file) = root.open(&wpath) {
140                return Ok((i, file));
141            }
142        }
143    }
144
145    // If no matching file found (or it failed to open), return NOT_FOUND
146    Err(Status::NOT_FOUND)
147}
148
149pub fn load(path: &str) -> Result<Vec<u8>> {
150    let (_i, mut file) = find(path)?;
151
152    let mut data = vec![];
153    let _count = file.read_to_end(&mut data)?;
154
155    Ok(data)
156}