Skip to content

Commit adf3c90

Browse files
wip: Add global system table pointer
1 parent 2063566 commit adf3c90

File tree

13 files changed

+1575
-144
lines changed

13 files changed

+1575
-144
lines changed

uefi-macros/src/lib.rs

+58
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,64 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
248248
result.into()
249249
}
250250

251+
/// TODO
252+
#[proc_macro_attribute]
253+
pub fn main(args: TokenStream, input: TokenStream) -> TokenStream {
254+
let mut errors = TokenStream2::new();
255+
256+
if !args.is_empty() {
257+
errors.append_all(err!(
258+
TokenStream2::from(args),
259+
"Entry attribute accepts no arguments"
260+
));
261+
}
262+
263+
let f = parse_macro_input!(input as ItemFn);
264+
265+
if let Some(ref abi) = f.sig.abi {
266+
errors.append_all(err!(abi, "Entry method must have no ABI modifier"));
267+
}
268+
if let Some(asyncness) = f.sig.asyncness {
269+
errors.append_all(err!(asyncness, "Entry method should not be async"));
270+
}
271+
if let Some(constness) = f.sig.constness {
272+
errors.append_all(err!(constness, "Entry method should not be const"));
273+
}
274+
if !f.sig.generics.params.is_empty() {
275+
errors.append_all(err!(
276+
f.sig.generics.params,
277+
"Entry method should not be generic"
278+
));
279+
}
280+
281+
// TODO: validate no fn args, validate return type
282+
283+
// show most errors at once instead of one by one
284+
if !errors.is_empty() {
285+
return errors.into();
286+
}
287+
288+
let fn_ident = &f.sig.ident;
289+
let result = quote! {
290+
#f
291+
292+
// TODO: non-conflicting name?
293+
#[export_name = "efi_main"]
294+
fn efi_main(image: ::uefi::Handle, system_table: *mut ::core::ffi::c_void) -> ::uefi::Status {
295+
unsafe {
296+
::uefi::boot::set_image_handle(image);
297+
::uefi::system::set_system_table(system_table.cast());
298+
match #fn_ident() {
299+
Ok(()) => Status::SUCCESS,
300+
Err(err) => err.status(),
301+
}
302+
}
303+
}
304+
305+
};
306+
result.into()
307+
}
308+
251309
/// Builds a `CStr8` literal at compile time from a string literal.
252310
///
253311
/// This will throw a compile error if an invalid character is in the passed string.

uefi-services/src/lib.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use cfg_if::cfg_if;
4343
use uefi::prelude::*;
4444
use uefi::table::boot::{EventType, Tpl};
4545
use uefi::table::{Boot, SystemTable};
46-
use uefi::{Event, Result};
46+
use uefi::{system, Event, Result};
4747

4848
/// Reference to the system table.
4949
///
@@ -74,6 +74,12 @@ pub fn system_table() -> NonNull<SystemTable<Boot>> {
7474
}
7575
}
7676

77+
/// TODO
78+
pub fn init_v2() -> Result<Option<Event>> {
79+
let mut st = system::system_table_boot();
80+
init(&mut st)
81+
}
82+
7783
/// Initialize the UEFI utility library.
7884
///
7985
/// This must be called as early as possible,

uefi-test-runner/src/bin/shell_launcher.rs

+20-28
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,14 @@ use uefi::proto::device_path::build::{self, DevicePathBuilder};
1818
use uefi::proto::device_path::{DevicePath, DeviceSubType, DeviceType, LoadedImageDevicePath};
1919
use uefi::proto::loaded_image::LoadedImage;
2020
use uefi::table::boot::LoadImageSource;
21-
use uefi::Status;
21+
use uefi::{boot, Result, Status};
2222

2323
/// Get the device path of the shell app. This is the same as the
2424
/// currently-loaded image's device path, but with the file path part changed.
25-
fn get_shell_app_device_path<'a>(
26-
boot_services: &BootServices,
27-
storage: &'a mut Vec<u8>,
28-
) -> &'a DevicePath {
29-
let loaded_image_device_path = boot_services
30-
.open_protocol_exclusive::<LoadedImageDevicePath>(boot_services.image_handle())
31-
.expect("failed to open LoadedImageDevicePath protocol");
25+
fn get_shell_app_device_path(storage: &mut Vec<u8>) -> &DevicePath {
26+
let loaded_image_device_path =
27+
boot::open_protocol_exclusive::<LoadedImageDevicePath>(boot::image_handle())
28+
.expect("failed to open LoadedImageDevicePath protocol");
3229

3330
let mut builder = DevicePathBuilder::with_vec(storage);
3431
for node in loaded_image_device_path.node_iter() {
@@ -45,29 +42,26 @@ fn get_shell_app_device_path<'a>(
4542
builder.finalize().unwrap()
4643
}
4744

48-
#[entry]
49-
fn efi_main(image: Handle, mut st: SystemTable<Boot>) -> Status {
50-
uefi_services::init(&mut st).unwrap();
51-
let boot_services = st.boot_services();
45+
#[uefi::main]
46+
fn main() -> Result {
47+
uefi_services::init_v2().unwrap();
5248

5349
let mut storage = Vec::new();
54-
let shell_image_path = get_shell_app_device_path(boot_services, &mut storage);
50+
let shell_image_path = get_shell_app_device_path(&mut storage);
5551

5652
// Load the shell app.
57-
let shell_image_handle = boot_services
58-
.load_image(
59-
image,
60-
LoadImageSource::FromDevicePath {
61-
device_path: shell_image_path,
62-
from_boot_manager: false,
63-
},
64-
)
65-
.expect("failed to load shell app");
53+
let shell_image_handle = boot::load_image(
54+
boot::image_handle(),
55+
LoadImageSource::FromDevicePath {
56+
device_path: shell_image_path,
57+
from_boot_manager: false,
58+
},
59+
)
60+
.expect("failed to load shell app");
6661

6762
// Set the command line passed to the shell app so that it will run the
6863
// test-runner app. This automatically turns off the five-second delay.
69-
let mut shell_loaded_image = boot_services
70-
.open_protocol_exclusive::<LoadedImage>(shell_image_handle)
64+
let mut shell_loaded_image = boot::open_protocol_exclusive::<LoadedImage>(shell_image_handle)
7165
.expect("failed to open LoadedImage protocol");
7266
let load_options = cstr16!(r"shell.efi test_runner.efi arg1 arg2");
7367
unsafe {
@@ -78,9 +72,7 @@ fn efi_main(image: Handle, mut st: SystemTable<Boot>) -> Status {
7872
}
7973

8074
info!("launching the shell app");
81-
boot_services
82-
.start_image(shell_image_handle)
83-
.expect("failed to launch the shell app");
75+
boot::start_image(shell_image_handle).expect("failed to launch the shell app");
8476

85-
Status::SUCCESS
77+
Ok(())
8678
}

uefi-test-runner/src/boot/memory.rs

+11-14
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
1-
use uefi::table::boot::{AllocateType, BootServices, MemoryType};
1+
use uefi::boot;
2+
use uefi::table::boot::{AllocateType, MemoryType};
23

34
use alloc::vec::Vec;
45

5-
pub fn test(bt: &BootServices) {
6+
pub fn test() {
67
info!("Testing memory functions");
78

8-
allocate_pages(bt);
9+
allocate_pages();
910
vec_alloc();
1011
alloc_alignment();
1112

12-
memory_map(bt);
13+
memory_map();
1314
}
1415

15-
fn allocate_pages(bt: &BootServices) {
16+
fn allocate_pages() {
1617
info!("Allocating some pages of memory");
1718

1819
let ty = AllocateType::AnyPages;
1920
let mem_ty = MemoryType::LOADER_DATA;
20-
let pgs = bt
21-
.allocate_pages(ty, mem_ty, 1)
22-
.expect("Failed to allocate a page of memory");
21+
let pgs = boot::allocate_pages(ty, mem_ty, 1).expect("Failed to allocate a page of memory");
2322

2423
assert_eq!(pgs % 4096, 0, "Page pointer is not page-aligned");
2524

@@ -31,7 +30,7 @@ fn allocate_pages(bt: &BootServices) {
3130
buf[4095] = 0x23;
3231

3332
// Clean up to avoid memory leaks.
34-
bt.free_pages(pgs, 1).unwrap();
33+
boot::free_pages(pgs, 1).unwrap();
3534
}
3635

3736
// Simple test to ensure our custom allocator works with the `alloc` crate.
@@ -57,21 +56,19 @@ fn alloc_alignment() {
5756
assert_eq!(value.as_ptr() as usize % 0x100, 0, "Wrong alignment");
5857
}
5958

60-
fn memory_map(bt: &BootServices) {
59+
fn memory_map() {
6160
info!("Testing memory map functions");
6261

6362
// Get the memory descriptor size and an estimate of the memory map size
64-
let sizes = bt.memory_map_size();
63+
let sizes = boot::memory_map_size();
6564

6665
// 2 extra descriptors should be enough.
6766
let buf_sz = sizes.map_size + 2 * sizes.entry_size;
6867

6968
// We will use vectors for convenience.
7069
let mut buffer = vec![0_u8; buf_sz];
7170

72-
let mut memory_map = bt
73-
.memory_map(&mut buffer)
74-
.expect("Failed to retrieve UEFI memory map");
71+
let mut memory_map = boot::memory_map(&mut buffer).expect("Failed to retrieve UEFI memory map");
7572

7673
memory_map.sort();
7774

0 commit comments

Comments
 (0)