use core::marker::PhantomData;
use core::slice;
use crate::proto::console::text;
use crate::{CStr16, Char16, Handle, Result, ResultExt, Status};
use super::boot::{BootServices, MemoryDescriptor};
use super::runtime::RuntimeServices;
use super::{cfg, Header, Revision};
pub trait SystemTableView {}
pub struct Boot;
impl SystemTableView for Boot {}
pub struct Runtime;
impl SystemTableView for Runtime {}
#[repr(transparent)]
pub struct SystemTable<View: SystemTableView> {
table: &'static SystemTableImpl,
_marker: PhantomData<View>,
}
impl<View: SystemTableView> SystemTable<View> {
pub fn firmware_vendor(&self) -> &CStr16 {
unsafe { CStr16::from_ptr(self.table.fw_vendor) }
}
pub fn firmware_revision(&self) -> Revision {
self.table.fw_revision
}
pub fn uefi_revision(&self) -> Revision {
self.table.header.revision
}
pub fn config_table(&self) -> &[cfg::ConfigTableEntry] {
unsafe { slice::from_raw_parts(self.table.cfg_table, self.table.nr_cfg) }
}
}
#[allow(clippy::mut_from_ref)]
impl SystemTable<Boot> {
pub fn stdin(&self) -> &mut text::Input {
unsafe { &mut *self.table.stdin }
}
pub fn stdout(&self) -> &mut text::Output {
let stdout_ptr = self.table.stdout as *const _ as *mut _;
unsafe { &mut *stdout_ptr }
}
pub fn stderr(&self) -> &mut text::Output {
let stderr_ptr = self.table.stderr as *const _ as *mut _;
unsafe { &mut *stderr_ptr }
}
pub fn runtime_services(&self) -> &RuntimeServices {
self.table.runtime
}
pub fn boot_services(&self) -> &BootServices {
unsafe { &*self.table.boot }
}
pub fn exit_boot_services(
self,
image: Handle,
mmap_buf: &mut [u8],
) -> Result<(
SystemTable<Runtime>,
impl ExactSizeIterator<Item = &MemoryDescriptor> + Clone,
)> {
unsafe {
let boot_services = self.boot_services();
loop {
let mmap_buf = &mut *(mmap_buf as *mut [u8]);
let mmap_comp = boot_services.memory_map(mmap_buf)?;
let (mmap_status, (mmap_key, mmap_iter)) = mmap_comp.split();
let result = boot_services.exit_boot_services(image, mmap_key);
if result.status() == Status::INVALID_PARAMETER {
continue;
} else {
return result.map(|comp| {
let st = SystemTable {
table: self.table,
_marker: PhantomData,
};
comp.map(|_| (st, mmap_iter)).with_status(mmap_status)
});
}
}
}
}
pub unsafe fn unsafe_clone(&self) -> Self {
SystemTable {
table: self.table,
_marker: PhantomData,
}
}
}
impl SystemTable<Runtime> {
pub unsafe fn runtime_services(&self) -> &RuntimeServices {
self.table.runtime
}
}
#[repr(C)]
struct SystemTableImpl {
header: Header,
fw_vendor: *const Char16,
fw_revision: Revision,
stdin_handle: Handle,
stdin: *mut text::Input,
stdout_handle: Handle,
stdout: *mut text::Output<'static>,
stderr_handle: Handle,
stderr: *mut text::Output<'static>,
runtime: &'static RuntimeServices,
boot: *const BootServices,
nr_cfg: usize,
cfg_table: *const cfg::ConfigTableEntry,
}
impl<View: SystemTableView> super::Table for SystemTable<View> {
const SIGNATURE: u64 = 0x5453_5953_2049_4249;
}