Skip to content

Commit e29c78d

Browse files
committed
Add Protocol trait and a number of Protocol implementations
1 parent d661b50 commit e29c78d

File tree

13 files changed

+460
-3
lines changed

13 files changed

+460
-3
lines changed

src/exec.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use uefi::Handle;
2+
use uefi::status::Result;
3+
4+
use crate::ffi::wstr;
5+
use crate::fs::load;
6+
use crate::loaded_image::LoadedImage;
7+
use crate::proto::Protocol;
8+
9+
pub fn exec_data(data: &[u8], name: &str, args: &[&str]) -> Result<usize> {
10+
let handle = crate::handle();
11+
let st = crate::system_table();
12+
13+
let mut image_handle = Handle(0);
14+
(st.BootServices.LoadImage)(false, handle, 0, data.as_ptr(), data.len(), &mut image_handle)?;
15+
16+
let mut cmdline = format!("\"{}\"", name);
17+
for arg in args.iter() {
18+
cmdline.push_str(" \"");
19+
cmdline.push_str(arg);
20+
cmdline.push_str("\"");
21+
}
22+
cmdline.push('\0');
23+
24+
let wcmdline = wstr(&cmdline);
25+
26+
if let Ok(loaded_image) = LoadedImage::handle_protocol(image_handle) {
27+
loaded_image.0.LoadOptionsSize = (wcmdline.len() as u32) * 2;
28+
loaded_image.0.LoadOptions = wcmdline.as_ptr();
29+
}
30+
31+
let mut exit_size = 0;
32+
let mut exit_ptr = ::core::ptr::null_mut();
33+
let ret = (st.BootServices.StartImage)(image_handle, &mut exit_size, &mut exit_ptr)?;
34+
35+
Ok(ret)
36+
}
37+
38+
pub fn exec_path(path: &str, args: &[&str]) -> Result<usize> {
39+
let data = load(path)?;
40+
exec_data(&data, path, args)
41+
}

src/ffi.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use core::char;
2+
3+
pub fn wstr(string: &str) -> Vec<u16> {
4+
let mut wstring = vec![];
5+
6+
for c in string.chars() {
7+
wstring.push(c as u16);
8+
}
9+
wstring.push(0);
10+
11+
wstring
12+
}
13+
14+
pub fn nstr(wstring: *const u16) -> String {
15+
let mut string = String::new();
16+
17+
let mut i = 0;
18+
loop {
19+
let w = unsafe { *wstring.offset(i) };
20+
i += 1;
21+
if w == 0 {
22+
break;
23+
}
24+
let c = unsafe { char::from_u32_unchecked(w as u32) };
25+
string.push(c);
26+
}
27+
28+
string
29+
}

src/fs.rs

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

src/lib.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,24 @@ pub use core::hint;
7878

7979
/* } */
8080

81+
// Re-export uefi and uefi_alloc
8182
pub use uefi;
8283
pub use uefi_alloc;
8384

84-
pub mod io;
85-
pub mod math;
86-
pub mod panic;
85+
// Runtime support
8786
pub mod rt;
8887

88+
// Public modules
89+
pub mod exec;
90+
pub mod ffi;
91+
pub mod fs;
92+
pub mod io;
93+
pub mod loaded_image;
94+
pub mod pointer;
95+
pub mod proto;
96+
pub mod shell;
97+
pub mod vars;
98+
8999
#[global_allocator]
90100
static ALLOCATOR: uefi_alloc::Allocator = uefi_alloc::Allocator;
91101

src/loaded_image.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use uefi::guid::{Guid, LOADED_IMAGE_PROTOCOL_GUID};
2+
use uefi::loaded_image::LoadedImage as UefiLoadedImage;
3+
4+
use crate::proto::Protocol;
5+
6+
pub struct LoadedImage(pub &'static mut UefiLoadedImage);
7+
8+
impl Protocol<UefiLoadedImage> for LoadedImage {
9+
fn guid() -> Guid {
10+
LOADED_IMAGE_PROTOCOL_GUID
11+
}
12+
13+
fn new(inner: &'static mut UefiLoadedImage) -> Self {
14+
LoadedImage(inner)
15+
}
16+
}

src/pointer.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use uefi::guid::{Guid, SIMPLE_POINTER_GUID};
2+
use uefi::pointer::SimplePointer;
3+
4+
use crate::proto::Protocol;
5+
6+
pub struct Pointer(pub &'static mut SimplePointer);
7+
8+
impl Protocol<SimplePointer> for Pointer {
9+
fn guid() -> Guid {
10+
SIMPLE_POINTER_GUID
11+
}
12+
13+
fn new(inner: &'static mut SimplePointer) -> Self {
14+
Pointer(inner)
15+
}
16+
}

src/proto.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use core::mem;
2+
use uefi::Handle;
3+
use uefi::boot::LocateSearchType;
4+
use uefi::guid::Guid;
5+
use uefi::status::Result;
6+
7+
use crate::system_table;
8+
9+
pub trait Protocol<T: 'static> {
10+
fn guid() -> Guid;
11+
12+
fn new(fs: &'static mut T) -> Self where Self: Sized;
13+
14+
fn locate_protocol() -> Result<Self> where Self: Sized {
15+
let guid = Self::guid();
16+
let mut interface = 0;
17+
(system_table().BootServices.LocateProtocol)(&guid, 0, &mut interface)?;
18+
19+
Ok(Self::new(unsafe { &mut *(interface as *mut T) }))
20+
}
21+
22+
fn handle_protocol(handle: Handle) -> Result<Self> where Self: Sized {
23+
let guid = Self::guid();
24+
let mut interface = 0;
25+
(system_table().BootServices.HandleProtocol)(handle, &guid, &mut interface)?;
26+
27+
Ok(Self::new(unsafe { &mut *(interface as *mut T) }))
28+
}
29+
30+
fn locate_handle() -> Result<Vec<Self>> where Self: Sized {
31+
let guid = Self::guid();
32+
let mut handles = Vec::with_capacity(256);
33+
let mut len = handles.capacity() * mem::size_of::<Handle>();
34+
(system_table().BootServices.LocateHandle)(LocateSearchType::ByProtocol, &guid, 0, &mut len, handles.as_mut_ptr())?;
35+
unsafe { handles.set_len(len / mem::size_of::<Handle>()); }
36+
37+
let mut instances = Vec::new();
38+
for handle in handles {
39+
if let Ok(instance) = Self::handle_protocol(handle) {
40+
instances.push(instance);
41+
}
42+
}
43+
Ok(instances)
44+
}
45+
46+
fn one() -> Result<Self> where Self: Sized {
47+
Self::locate_protocol()
48+
}
49+
50+
fn all() -> Vec<Self> where Self: Sized {
51+
Self::locate_handle().unwrap_or(Vec::new())
52+
}
53+
}
File renamed without changes.

src/rt/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub mod math;
2+
pub mod panic;
3+
pub mod start;
File renamed without changes.

0 commit comments

Comments
 (0)