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 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 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}