Cleanup of UEFI code
This commit is contained in:
+15
-140
@@ -1,6 +1,5 @@
|
||||
use alloc::{
|
||||
string::String,
|
||||
vec::Vec,
|
||||
};
|
||||
use core::{mem, ptr, slice};
|
||||
use orbclient::{Color, Renderer};
|
||||
@@ -22,9 +21,6 @@ use self::paging::paging;
|
||||
|
||||
mod memory_map;
|
||||
mod paging;
|
||||
mod partitions;
|
||||
|
||||
static KERNEL: &'static str = "\\redox_bootloader\\kernel";
|
||||
|
||||
static KERNEL_OFFSET: u64 = 0xFFFF_FF00_0000_0000;
|
||||
|
||||
@@ -63,52 +59,12 @@ unsafe fn exit_boot_services(key: usize) {
|
||||
}
|
||||
|
||||
unsafe fn enter() -> ! {
|
||||
let entry_fn: extern "C" fn(dtb: u64) -> ! = mem::transmute((
|
||||
let entry_fn: extern "C" fn(dtb: u64) -> ! = mem::transmute(
|
||||
KERNEL_PHYSICAL + KERNEL_ENTRY - KERNEL_OFFSET
|
||||
));
|
||||
);
|
||||
entry_fn(DTB_PHYSICAL);
|
||||
}
|
||||
|
||||
fn get_correct_block_io() -> Result<DiskEfi> {
|
||||
// Get all BlockIo handles.
|
||||
let mut handles = vec! [uefi::Handle(0); 128];
|
||||
let mut size = handles.len() * mem::size_of::<uefi::Handle>();
|
||||
|
||||
(std::system_table().BootServices.LocateHandle)(uefi::boot::LocateSearchType::ByProtocol, &uefi::guid::BLOCK_IO_GUID, 0, &mut size, handles.as_mut_ptr())?;
|
||||
|
||||
let max_size = size / mem::size_of::<uefi::Handle>();
|
||||
let actual_size = std::cmp::min(handles.len(), max_size);
|
||||
|
||||
// Return the handle that seems bootable.
|
||||
for handle in handles.into_iter().take(actual_size) {
|
||||
let block_io = DiskEfi::handle_protocol(handle)?;
|
||||
if !block_io.0.Media.LogicalPartition {
|
||||
continue;
|
||||
}
|
||||
|
||||
let part = partitions::PartitionProto::handle_protocol(handle)?.0;
|
||||
if part.sys == 1 {
|
||||
continue;
|
||||
}
|
||||
assert_eq!({part.rev}, partitions::PARTITION_INFO_PROTOCOL_REVISION);
|
||||
if part.ty == partitions::PartitionProtoDataTy::Gpt as u32 {
|
||||
let gpt = unsafe { part.info.gpt };
|
||||
assert_ne!(gpt.part_ty_guid, partitions::ESP_GUID, "detected esp partition again");
|
||||
if gpt.part_ty_guid == partitions::REDOX_FS_GUID || gpt.part_ty_guid == partitions::LINUX_FS_GUID {
|
||||
return Ok(block_io);
|
||||
}
|
||||
} else if part.ty == partitions::PartitionProtoDataTy::Mbr as u32 {
|
||||
let mbr = unsafe { part.info.mbr };
|
||||
if mbr.ty == 0x83 {
|
||||
return Ok(block_io);
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
panic!("Couldn't find handle for partition");
|
||||
}
|
||||
|
||||
static DTB_GUID: Guid = Guid(0xb1b621d5, 0xf19c, 0x41a5, [0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0]);
|
||||
|
||||
fn find_dtb() -> Result<()> {
|
||||
@@ -127,10 +83,19 @@ fn find_dtb() -> Result<()> {
|
||||
}
|
||||
|
||||
fn redoxfs() -> Result<redoxfs::FileSystem<DiskEfi>> {
|
||||
// TODO: Scan multiple partitions for a kernel.
|
||||
// TODO: pass block_opt for performance reasons
|
||||
redoxfs::FileSystem::open(get_correct_block_io()?, None)
|
||||
.map_err(|_| Error::DeviceError)
|
||||
for (i, block_io) in DiskEfi::all().into_iter().enumerate() {
|
||||
if !block_io.0.Media.LogicalPartition {
|
||||
continue;
|
||||
}
|
||||
|
||||
match redoxfs::FileSystem::open(block_io, Some(0)) {
|
||||
Ok(ok) => return Ok(ok),
|
||||
Err(err) => {
|
||||
log::error!("Failed to open RedoxFS on block I/O {}: {}", i, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!("Failed to find RedoxFS");
|
||||
}
|
||||
|
||||
const MB: usize = 1024 * 1024;
|
||||
@@ -252,98 +217,8 @@ fn inner() -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
fn select_mode(output: &mut Output) -> Result<u32> {
|
||||
loop {
|
||||
for i in 0..output.0.Mode.MaxMode {
|
||||
let mut mode_ptr = ::core::ptr::null_mut();
|
||||
let mut mode_size = 0;
|
||||
(output.0.QueryMode)(output.0, i, &mut mode_size, &mut mode_ptr)?;
|
||||
|
||||
let mode = unsafe { &mut *mode_ptr };
|
||||
let w = mode.HorizontalResolution;
|
||||
let h = mode.VerticalResolution;
|
||||
|
||||
print!("\r{}x{}: Is this OK? (y)es/(n)o", w, h);
|
||||
|
||||
if key(true)? == Key::Character('y') {
|
||||
println!("");
|
||||
|
||||
return Ok(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pretty_pipe<T, F: FnMut() -> Result<T>>(f: F) -> Result<T> {
|
||||
let mut output = Output::one()?;
|
||||
let mut display = Display::new(&mut output);
|
||||
let mut display = ScaledDisplay::new(&mut display);
|
||||
|
||||
{
|
||||
let bg = Color::rgb(0x4a, 0xa3, 0xfd);
|
||||
|
||||
display.set(bg);
|
||||
|
||||
{
|
||||
let prompt = format!(
|
||||
"Redox Bootloader {} {}",
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
env!("TARGET").split('-').next().unwrap_or("")
|
||||
);
|
||||
let mut x = (display.width() as i32 - prompt.len() as i32 * 8)/2;
|
||||
let y = display.height() as i32 - 32;
|
||||
for c in prompt.chars() {
|
||||
display.char(x, y, c, Color::rgb(0xff, 0xff, 0xff));
|
||||
x += 8;
|
||||
}
|
||||
}
|
||||
|
||||
display.sync();
|
||||
}
|
||||
|
||||
{
|
||||
let cols = 80;
|
||||
let off_x = (display.width() as i32 - cols as i32 * 8)/2;
|
||||
let off_y = 16;
|
||||
let rows = (display.height() as i32 - 64 - off_y - 1) as usize/16;
|
||||
display.rect(off_x, off_y, cols as u32 * 8, rows as u32 * 16, Color::rgb(0, 0, 0));
|
||||
display.sync();
|
||||
|
||||
let mut text = TextDisplay::new(display);
|
||||
text.off_x = off_x;
|
||||
text.off_y = off_y;
|
||||
text.cols = cols;
|
||||
text.rows = rows;
|
||||
text.pipe(f)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() -> Result<()> {
|
||||
inner()?;
|
||||
|
||||
/* TODO
|
||||
if let Ok(mut output) = Output::one() {
|
||||
let mut splash = Image::new(0, 0);
|
||||
{
|
||||
println!("Loading Splash...");
|
||||
if let Ok(image) = image::bmp::parse(&SPLASHBMP) {
|
||||
splash = image;
|
||||
}
|
||||
println!(" Done");
|
||||
}
|
||||
|
||||
/* TODO
|
||||
let mode = pretty_pipe(&splash, || {
|
||||
select_mode(&mut output)
|
||||
})?;
|
||||
(output.0.SetMode)(output.0, mode)?;
|
||||
*/
|
||||
|
||||
pretty_pipe(&splash, inner)?;
|
||||
} else {
|
||||
inner()?;
|
||||
}
|
||||
*/
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
use std::proto::Protocol;
|
||||
|
||||
#[repr(packed)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct PartitionProtoInfoMbr {
|
||||
pub boot: u8,
|
||||
pub chs_start: [u8; 3],
|
||||
pub ty: u8,
|
||||
pub chs_end: [u8; 3],
|
||||
pub start_lba: u32,
|
||||
pub lba_size: u32,
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct PartitionProtoInfoGpt {
|
||||
pub part_ty_guid: [u8; 16],
|
||||
pub uniq_guid: [u8; 16],
|
||||
pub start_lba: u64,
|
||||
pub end_lba: u64,
|
||||
pub attrs: u64,
|
||||
pub name: [u16; 36],
|
||||
// reserved until end of block
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub union PartitionProtoDataInfo {
|
||||
pub mbr: PartitionProtoInfoMbr,
|
||||
pub gpt: PartitionProtoInfoGpt,
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct PartitionProtoData {
|
||||
pub rev: u32,
|
||||
pub ty: u32,
|
||||
pub sys: u8,
|
||||
pub resv: [u8; 7],
|
||||
pub info: PartitionProtoDataInfo,
|
||||
}
|
||||
|
||||
pub const PARTITION_INFO_PROTOCOL_REVISION: u32 = 0x1000;
|
||||
pub const ESP_GUID: [u8; 16] = [0x28, 0x73, 0x2a, 0xc1, 0x1f, 0xf8, 0xd2, 0x11, 0xba, 0x4b, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b]; // c12a7328-f81f-11d2-bA4b-00a0c93ec93b
|
||||
pub const LINUX_FS_GUID: [u8; 16] = [0xaf, 0x3d, 0xc6, 0xf, 0x83, 0x84, 0x72, 0x47, 0x8e, 0x79, 0x3d, 0x69, 0xd8, 0x47, 0x7d, 0xe4]; // 0fc63daf-8483-4772-8e79-3d69d8477de4
|
||||
pub const REDOX_FS_GUID: [u8; 16] = [0xfd, 0x98, 0x78, 0x52, 0xe3, 0xff, 0xc2, 0x42, 0xe3, 0x96, 0x10, 0x5b, 0xa6, 0x3f, 0x5a, 0xbf]; // 527898fd-ffe3-42c2-96e3-bf5a3fa65b10
|
||||
|
||||
#[repr(u32)]
|
||||
pub enum PartitionProtoDataTy {
|
||||
Other = 0,
|
||||
Mbr = 1,
|
||||
Gpt = 2,
|
||||
}
|
||||
|
||||
pub struct PartitionProto(pub &'static mut PartitionProtoData);
|
||||
|
||||
impl Protocol<PartitionProtoData> for PartitionProto {
|
||||
fn guid() -> uefi::guid::Guid {
|
||||
uefi::guid::Guid(0x8cf2f62c, 0xbc9b, 0x4821, [0x80, 0x8d, 0xec, 0x9e, 0xc4, 0x21, 0xa1, 0xa0])
|
||||
}
|
||||
fn new(inner: &'static mut PartitionProtoData) -> Self {
|
||||
Self(inner)
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ use self::paging::{paging_create, paging_enter};
|
||||
|
||||
mod memory_map;
|
||||
mod paging;
|
||||
mod partitions;
|
||||
|
||||
static PHYS_OFFSET: u64 = 0xFFFF800000000000;
|
||||
|
||||
@@ -88,46 +87,6 @@ unsafe fn enter() -> ! {
|
||||
entry_fn(&args);
|
||||
}
|
||||
|
||||
fn get_correct_block_io() -> Result<DiskEfi> {
|
||||
// Get all BlockIo handles.
|
||||
let mut handles = vec! [uefi::Handle(0); 128];
|
||||
let mut size = handles.len() * mem::size_of::<uefi::Handle>();
|
||||
|
||||
(std::system_table().BootServices.LocateHandle)(uefi::boot::LocateSearchType::ByProtocol, &uefi::guid::BLOCK_IO_GUID, 0, &mut size, handles.as_mut_ptr())?;
|
||||
|
||||
let max_size = size / mem::size_of::<uefi::Handle>();
|
||||
let actual_size = std::cmp::min(handles.len(), max_size);
|
||||
|
||||
// Return the handle that seems bootable.
|
||||
for handle in handles.into_iter().take(actual_size) {
|
||||
let block_io = DiskEfi::handle_protocol(handle)?;
|
||||
if !block_io.0.Media.LogicalPartition {
|
||||
continue;
|
||||
}
|
||||
|
||||
let part = partitions::PartitionProto::handle_protocol(handle)?.0;
|
||||
if part.sys == 1 {
|
||||
continue;
|
||||
}
|
||||
assert_eq!({part.rev}, partitions::PARTITION_INFO_PROTOCOL_REVISION);
|
||||
if part.ty == partitions::PartitionProtoDataTy::Gpt as u32 {
|
||||
let gpt = unsafe { part.info.gpt };
|
||||
assert_ne!(gpt.part_ty_guid, partitions::ESP_GUID, "detected esp partition again");
|
||||
if gpt.part_ty_guid == partitions::REDOX_FS_GUID || gpt.part_ty_guid == partitions::LINUX_FS_GUID {
|
||||
return Ok(block_io);
|
||||
}
|
||||
} else if part.ty == partitions::PartitionProtoDataTy::Mbr as u32 {
|
||||
let mbr = unsafe { part.info.mbr };
|
||||
if mbr.ty == 0x83 {
|
||||
return Ok(block_io);
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
panic!("Couldn't find handle for partition");
|
||||
}
|
||||
|
||||
struct Invalid;
|
||||
|
||||
fn validate_rsdp(address: usize, v2: bool) -> core::result::Result<usize, Invalid> {
|
||||
@@ -202,10 +161,19 @@ fn find_acpi_table_pointers() -> Result<()> {
|
||||
}
|
||||
|
||||
fn redoxfs() -> Result<redoxfs::FileSystem<DiskEfi>> {
|
||||
// TODO: Scan multiple partitions for a kernel.
|
||||
// TODO: pass block_opt for performance reasons
|
||||
redoxfs::FileSystem::open(get_correct_block_io()?, None)
|
||||
.map_err(|_| Error::DeviceError)
|
||||
for (i, block_io) in DiskEfi::all().into_iter().enumerate() {
|
||||
if !block_io.0.Media.LogicalPartition {
|
||||
continue;
|
||||
}
|
||||
|
||||
match redoxfs::FileSystem::open(block_io, Some(0)) {
|
||||
Ok(ok) => return Ok(ok),
|
||||
Err(err) => {
|
||||
log::error!("Failed to open RedoxFS on block I/O {}: {}", i, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!("Failed to find RedoxFS");
|
||||
}
|
||||
|
||||
const MB: usize = 1024 * 1024;
|
||||
@@ -434,7 +402,7 @@ fn select_mode(output: &mut Output) -> Result<()> {
|
||||
|
||||
let mut row = 0;
|
||||
let mut col = 0;
|
||||
for (i, w, h, text) in modes.iter() {
|
||||
for (i, _w, _h, text) in modes.iter() {
|
||||
if row >= rows as i32 {
|
||||
col += 1;
|
||||
row = 0;
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
use std::proto::Protocol;
|
||||
|
||||
#[repr(packed)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct PartitionProtoInfoMbr {
|
||||
pub boot: u8,
|
||||
pub chs_start: [u8; 3],
|
||||
pub ty: u8,
|
||||
pub chs_end: [u8; 3],
|
||||
pub start_lba: u32,
|
||||
pub lba_size: u32,
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct PartitionProtoInfoGpt {
|
||||
pub part_ty_guid: [u8; 16],
|
||||
pub uniq_guid: [u8; 16],
|
||||
pub start_lba: u64,
|
||||
pub end_lba: u64,
|
||||
pub attrs: u64,
|
||||
pub name: [u16; 36],
|
||||
// reserved until end of block
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub union PartitionProtoDataInfo {
|
||||
pub mbr: PartitionProtoInfoMbr,
|
||||
pub gpt: PartitionProtoInfoGpt,
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct PartitionProtoData {
|
||||
pub rev: u32,
|
||||
pub ty: u32,
|
||||
pub sys: u8,
|
||||
pub resv: [u8; 7],
|
||||
pub info: PartitionProtoDataInfo,
|
||||
}
|
||||
|
||||
pub const PARTITION_INFO_PROTOCOL_REVISION: u32 = 0x1000;
|
||||
pub const ESP_GUID: [u8; 16] = [0x28, 0x73, 0x2a, 0xc1, 0x1f, 0xf8, 0xd2, 0x11, 0xba, 0x4b, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b]; // c12a7328-f81f-11d2-bA4b-00a0c93ec93b
|
||||
pub const LINUX_FS_GUID: [u8; 16] = [0xaf, 0x3d, 0xc6, 0xf, 0x83, 0x84, 0x72, 0x47, 0x8e, 0x79, 0x3d, 0x69, 0xd8, 0x47, 0x7d, 0xe4]; // 0fc63daf-8483-4772-8e79-3d69d8477de4
|
||||
pub const REDOX_FS_GUID: [u8; 16] = [0xfd, 0x98, 0x78, 0x52, 0xe3, 0xff, 0xc2, 0x42, 0xe3, 0x96, 0x10, 0x5b, 0xa6, 0x3f, 0x5a, 0xbf]; // 527898fd-ffe3-42c2-96e3-bf5a3fa65b10
|
||||
|
||||
#[repr(u32)]
|
||||
pub enum PartitionProtoDataTy {
|
||||
Other = 0,
|
||||
Mbr = 1,
|
||||
Gpt = 2,
|
||||
}
|
||||
|
||||
pub struct PartitionProto(pub &'static mut PartitionProtoData);
|
||||
|
||||
impl Protocol<PartitionProtoData> for PartitionProto {
|
||||
fn guid() -> uefi::guid::Guid {
|
||||
uefi::guid::Guid(0x8cf2f62c, 0xbc9b, 0x4821, [0x80, 0x8d, 0xec, 0x9e, 0xc4, 0x21, 0xa1, 0xa0])
|
||||
}
|
||||
fn new(inner: &'static mut PartitionProtoData) -> Self {
|
||||
Self(inner)
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ mod arch;
|
||||
mod disk;
|
||||
mod display;
|
||||
mod key;
|
||||
pub mod null;
|
||||
pub mod text;
|
||||
|
||||
fn set_max_mode(output: &uefi::text::TextOutput) -> Result<()> {
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
use core::mem;
|
||||
use core::ops::Deref;
|
||||
use std::boxed::Box;
|
||||
use uefi::Handle;
|
||||
use uefi::boot::InterfaceType;
|
||||
use uefi::guid::SIMPLE_TEXT_OUTPUT_GUID;
|
||||
use uefi::status::{Result, Status};
|
||||
use uefi::text::TextOutputMode;
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_snake_case)]
|
||||
pub struct NullDisplay {
|
||||
pub Reset: extern "win64" fn(&mut NullDisplay, bool) -> Status,
|
||||
pub OutputString: extern "win64" fn(&mut NullDisplay, *const u16) -> Status,
|
||||
pub TestString: extern "win64" fn(&mut NullDisplay, *const u16) -> Status,
|
||||
pub QueryMode: extern "win64" fn(&mut NullDisplay, usize, &mut usize, &mut usize) -> Status,
|
||||
pub SetMode: extern "win64" fn(&mut NullDisplay, usize) -> Status,
|
||||
pub SetAttribute: extern "win64" fn(&mut NullDisplay, usize) -> Status,
|
||||
pub ClearScreen: extern "win64" fn(&mut NullDisplay) -> Status,
|
||||
pub SetCursorPosition: extern "win64" fn(&mut NullDisplay, usize, usize) -> Status,
|
||||
pub EnableCursor: extern "win64" fn(&mut NullDisplay, bool) -> Status,
|
||||
pub Mode: &'static TextOutputMode,
|
||||
|
||||
pub mode: Box<TextOutputMode>,
|
||||
}
|
||||
|
||||
extern "win64" fn reset(_output: &mut NullDisplay, _extra: bool) -> Status {
|
||||
Status(0)
|
||||
}
|
||||
|
||||
extern "win64" fn output_string(_output: &mut NullDisplay, _string: *const u16) -> Status {
|
||||
Status(0)
|
||||
}
|
||||
|
||||
extern "win64" fn test_string(_output: &mut NullDisplay, _string: *const u16) -> Status {
|
||||
Status(0)
|
||||
}
|
||||
|
||||
extern "win64" fn query_mode(_output: &mut NullDisplay, _mode: usize, columns: &mut usize, rows: &mut usize) -> Status {
|
||||
*columns = 80;
|
||||
*rows = 30;
|
||||
Status(0)
|
||||
}
|
||||
|
||||
extern "win64" fn set_mode(_output: &mut NullDisplay, _mode: usize) -> Status {
|
||||
Status(0)
|
||||
}
|
||||
|
||||
extern "win64" fn set_attribute(output: &mut NullDisplay, attribute: usize) -> Status {
|
||||
output.mode.Attribute = attribute as i32;
|
||||
Status(0)
|
||||
}
|
||||
|
||||
extern "win64" fn clear_screen(_output: &mut NullDisplay) -> Status {
|
||||
Status(0)
|
||||
}
|
||||
|
||||
extern "win64" fn set_cursor_position(output: &mut NullDisplay, column: usize, row: usize) -> Status {
|
||||
output.mode.CursorColumn = column as i32;
|
||||
output.mode.CursorRow = row as i32;
|
||||
Status(0)
|
||||
}
|
||||
|
||||
extern "win64" fn enable_cursor(output: &mut NullDisplay, enable: bool) -> Status {
|
||||
output.mode.CursorVisible = enable;
|
||||
Status(0)
|
||||
}
|
||||
|
||||
impl NullDisplay {
|
||||
pub fn new() -> NullDisplay {
|
||||
let mode = Box::new(TextOutputMode {
|
||||
MaxMode: 0,
|
||||
Mode: 0,
|
||||
Attribute: 0,
|
||||
CursorColumn: 0,
|
||||
CursorRow: 0,
|
||||
CursorVisible: false,
|
||||
});
|
||||
|
||||
NullDisplay {
|
||||
Reset: reset,
|
||||
OutputString: output_string,
|
||||
TestString: test_string,
|
||||
QueryMode: query_mode,
|
||||
SetMode: set_mode,
|
||||
SetAttribute: set_attribute,
|
||||
ClearScreen: clear_screen,
|
||||
SetCursorPosition: set_cursor_position,
|
||||
EnableCursor: enable_cursor,
|
||||
Mode: unsafe { mem::transmute(&*mode.deref()) },
|
||||
|
||||
mode: mode
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pipe<T, F: FnMut() -> Result<T>>(&mut self, mut f: F) -> Result<T> {
|
||||
let uefi = unsafe { std::system_table_mut() };
|
||||
|
||||
let stdout = self as *mut _;
|
||||
let mut stdout_handle = Handle(0);
|
||||
(uefi.BootServices.InstallProtocolInterface)(&mut stdout_handle, &SIMPLE_TEXT_OUTPUT_GUID, InterfaceType::Native, stdout as usize)?;
|
||||
|
||||
let old_stdout_handle = uefi.ConsoleOutHandle;
|
||||
let old_stdout = uefi.ConsoleOut as *mut _;
|
||||
let old_stderr_handle = uefi.ConsoleErrorHandle;
|
||||
let old_stderr = uefi.ConsoleError as *mut _;
|
||||
|
||||
uefi.ConsoleOutHandle = stdout_handle;
|
||||
uefi.ConsoleOut = unsafe { mem::transmute(&mut *stdout) };
|
||||
uefi.ConsoleErrorHandle = stdout_handle;
|
||||
uefi.ConsoleError = unsafe { mem::transmute(&mut *stdout) };
|
||||
|
||||
let res = f();
|
||||
|
||||
uefi.ConsoleOutHandle = old_stdout_handle;
|
||||
uefi.ConsoleOut = unsafe { mem::transmute(&mut *old_stdout) };
|
||||
uefi.ConsoleErrorHandle = old_stderr_handle;
|
||||
uefi.ConsoleError = unsafe { mem::transmute(&mut *old_stderr) };
|
||||
|
||||
let _ = (uefi.BootServices.UninstallProtocolInterface)(stdout_handle, &SIMPLE_TEXT_OUTPUT_GUID, stdout as usize);
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pipe<T, F: FnMut() -> Result<T>>(f: F) -> Result<T> {
|
||||
NullDisplay::new().pipe(f)
|
||||
}
|
||||
Reference in New Issue
Block a user