Created
December 10, 2018 09:45
-
-
Save dvdhrm/eff3a1b2776a2cd4e7f20a7a46bb75b7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Example: Hello World! | |
// | |
// This is an example UEFI application that prints "Hello World!", then waits for key input before | |
// it exits. It serves as base example how to write UEFI applications without any helper modules | |
// other than the UEFI protocol definitions. | |
// | |
// The `efi_main` function serves as entry-point. Depending on your target-configuration, this | |
// entry point might be called differently. If you use the target-configuration shipped with | |
// r-efi, then `efi_main` is the selected PE/COFF entry point. | |
// | |
// Additionally, a panic handler is provided. This is executed by rust on panic. For simplicity, | |
// we simply end up in an infinite loop. For real applications, this method should probably call | |
// into `SystemTable->boot_services->exit()` to exit the UEFI application. Note, however, that | |
// UEFI applications are likely to run in the same address space as the entire firmware. Hence, | |
// halting the machine might be a viable alternative. All that is out-of-scope of this example, | |
// though. | |
// | |
// Lastly, note that UEFI uses UTF-16 strings. Since rust literals are UTF-8, we have to use an | |
// open-coded, zero-terminated, UTF-16 array as argument to `output_string()`. Similarly to the | |
// panic handler, real applications should rather use UTF-16 modules. | |
// | |
#![feature(alloc)] | |
#![feature(alloc_error_handler)] | |
#![no_main] | |
#![no_std] | |
extern crate alloc; | |
use alloc::string::String; | |
use alloc::vec::Vec; | |
use r_efi::efi; | |
#[global_allocator] | |
static GLOBAL_ALLOCATOR: r_efi_alloc::global::Bridge = r_efi_alloc::global::Bridge::new(); | |
#[panic_handler] | |
fn rust_panic_handler(_info: &core::panic::PanicInfo) -> ! { | |
loop {} | |
} | |
#[alloc_error_handler] | |
fn foo(_layout: core::alloc::Layout) -> ! { | |
panic!(); | |
} | |
pub fn efi_run(_h: efi::Handle, st: *mut efi::SystemTable) -> efi::Status { | |
let s: String; | |
let mut v: Vec<u16>; | |
// Create string and convert to UTF-16. | |
s = String::from("Hello World!\n"); | |
v = s.encode_utf16().collect(); | |
v.push(0); | |
// Print "Hello World!". | |
let r = unsafe { | |
((*(*st).con_out).output_string)((*st).con_out, v.as_mut_slice().as_mut_ptr()) | |
}; | |
if r.is_error() { | |
return r; | |
} | |
// Wait for key input, by waiting on the `wait_for_key` event hook. | |
let r = unsafe { | |
let mut x: usize = 0; | |
((*(*st).boot_services).wait_for_event)(1, &mut (*(*st).con_in).wait_for_key, &mut x) | |
}; | |
if r.is_error() { | |
return r; | |
} | |
efi::Status::SUCCESS | |
} | |
// This is the main UEFI entry point, called by the UEFI environment when the application is | |
// spawned. We use it to create an allocator and attach it to the global allocator bridge. Then we | |
// invoke the `efi_run()` function as if it was the main entry-point. | |
// | |
// We call `drop` explicitly on the attachment to guarantee it is kept alive until after the | |
// efi_run() function. | |
// | |
// XXX: We really should figure out how to guarantee @attachment stays alive. Is the compiler | |
// allowed to re-order? Is deinitialization guaranteed to be at the *end* of a block? Does | |
// anybody know whether such guarantees are given by the rust ABI? | |
#[no_mangle] | |
pub extern fn efi_main(h: efi::Handle, st: *mut efi::SystemTable) -> efi::Status { | |
let r; | |
unsafe { | |
let mut allocator = r_efi_alloc::alloc::Allocator::from_system_table( | |
st, | |
efi::MemoryType::LoaderData, | |
); | |
let attachment = GLOBAL_ALLOCATOR.attach(&mut allocator); | |
r = efi_run(h, st); | |
drop(attachment); | |
} | |
r | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment