use super::Header;
use crate::mem::MemoryDescriptor;
use crate::mem::PhysicalAddress;
use crate::prelude::*;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(transparent)]
pub struct CapsuleFlags(u32);
impl CapsuleFlags {
pub const PERSIST_ACROSS_RESET: Self = Self(1 << 16);
pub const POPULATE_SYSTEM_TABLE: Self = Self(1 << 17);
pub const INITIATE_RESET: Self = Self(1 << 18);
}
#[derive(Debug)]
#[repr(C)]
pub struct CapsuleHeader {
pub CapsuleGuid: Guid,
pub HeaderSize: u32,
pub Flags: CapsuleFlags,
pub CapsuleImageSize: u32,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(transparent)]
pub struct ResetType(u32);
impl ResetType {
pub const COLD: Self = Self(0);
pub const WARM: Self = Self(1);
pub const SHUTDOWN: Self = Self(2);
pub const PLATFORM_SPECIFIC: Self = Self(3);
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C)]
pub struct Time {
pub Year: u16,
pub Month: u8,
pub Day: u8,
pub Hour: u8,
pub Minute: u8,
pub Second: u8,
_Pad1: u8,
pub Nanosecond: u32,
pub TimeZone: i16,
pub Daylight: u8,
_Pad2: u8,
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C)]
pub struct TimeCapabilities {
pub Resolution: u32,
pub Accuracy: u32,
pub SetsToZero: bool,
}
#[repr(transparent)]
pub struct VariableAttributes(u32);
impl VariableAttributes {
pub const NON_VOLATILE: Self = Self(1 << 0);
pub const BOOTSERVICE_ACCESS: Self = Self(1 << 1);
pub const RUNTIME_ACCESS: Self = Self(1 << 2);
pub const HARDWARE_ERROR_RECORD: Self = Self(1 << 3);
pub const AUTHENTICATED_WRITE_ACCESS: Self = Self(1 << 4);
pub const TIME_BASED_AUTHENTICATED_WRITE_ACCESS: Self = Self(1 << 5);
pub const APPEND_WRITE: Self = Self(1 << 6);
pub const ENHANCED_AUTHENTICATED_ACCESS: Self = Self(1 << 7);
}
#[rustfmt::skip]
#[repr(C)]
pub struct RuntimeServices {
pub Hdr: Header,
pub GetTime: extern "efiapi" fn(*mut Time, *mut TimeCapabilities) -> Status,
pub SetTime: extern "efiapi" fn(*const Time) -> Status,
pub GetWakeupTime: extern "efiapi" fn(*mut bool, *mut bool, *mut Time) -> Status,
pub SetWakeupTime: extern "efiapi" fn(bool, *const Time) -> Status,
pub SetVirtualAddressMap: extern "efiapi" fn(usize, usize, u32, *const MemoryDescriptor) -> Status,
pub ConvertPointer: extern "efiapi" fn(usize, *mut *const u8) -> Status,
pub GetVariable: extern "efiapi" fn(*const u16, *const Guid, *mut VariableAttributes, *mut usize, *mut u8) -> Status,
pub GetNextVariableName: extern "efiapi" fn(*mut usize, *mut u16, *mut Guid) -> Status,
pub SetVariable: extern "efiapi" fn(*const u16, *const Guid, VariableAttributes, usize, *const u8) -> Status,
pub GetNextHighMonotonicCount: extern "efiapi" fn(*mut u32) -> Status,
pub ResetSystem: extern "efiapi" fn(ResetType, Status, usize, *const u8),
pub UpdateCapsule: extern "efiapi" fn(*const *const CapsuleHeader, usize, *const PhysicalAddress) -> Status,
pub QueryCapsuleCapabilities: extern "efiapi" fn() -> Status,
pub QueryVariableInfo: extern "efiapi" fn(VariableAttributes, *mut u64, *mut u64, *mut u64) -> Status,
}
impl RuntimeServices {
pub fn header(&self) -> &Header {
&self.Hdr
}
pub fn get_time(&self) -> Result<Time> {
let mut time = Time::default();
let status = (self.GetTime)(&mut time, core::ptr::null_mut());
match status {
Status::SUCCESS => Ok(time),
e => Err(e),
}
}
pub fn get_time_capabilities(&self) -> Result<TimeCapabilities> {
let mut time = Time::default();
let mut caps = TimeCapabilities::default();
let status = (self.GetTime)(&mut time, &mut caps);
match status {
Status::SUCCESS => Ok(caps),
e => Err(e),
}
}
pub fn set_time(&mut self, time: &Time) -> Result<()> {
(self.SetTime)(time).into()
}
pub fn get_wakeup_time(&self) -> Result<(bool, bool, Time)> {
let mut enabled = false;
let mut pending = false;
let mut time = Time::default();
let status = (self.GetWakeupTime)(&mut enabled, &mut pending, &mut time);
match status {
Status::SUCCESS => Ok((enabled, pending, time)),
e => Err(e),
}
}
pub fn set_wakeup_time(&mut self, time: &Time) -> Result<()> {
(self.SetWakeupTime)(true, time).into()
}
pub fn disable_wakeup_time(&mut self) -> Result<()> {
(self.SetWakeupTime)(false, core::ptr::null()).into()
}
pub fn set_virtual_address_map(
&self,
map_size: usize,
desc_size: usize,
desc_version: u32,
vmap: &MemoryDescriptor,
) -> Result<()> {
(self.SetVirtualAddressMap)(map_size, desc_size, desc_version, vmap).into()
}
pub fn convert_pointer(&self, disp: usize, addr: *const u8) -> Result<*const u8> {
let mut ptr = addr;
let status = (self.ConvertPointer)(disp, &mut ptr);
match status {
Status::SUCCESS => Ok(ptr),
e => Err(e),
}
}
pub fn set_variable(
&self,
name: &u16,
guid: &Guid,
attrs: VariableAttributes,
data: &[u8],
) -> Result<()> {
(self.SetVariable)(name, guid, attrs, data.len(), data.as_ptr()).into()
}
pub fn get_next_high_monotonic_count(&self) -> Result<u32> {
let mut count: u32 = 0;
let status = (self.GetNextHighMonotonicCount)(&mut count);
match status {
Status::SUCCESS => Ok(count),
err => Err(err),
}
}
pub fn reset_system(&self, kind: ResetType, status: Status, reset_data: Option<&[u8]>) {
let (size, data) = match reset_data {
Some(dat) => (dat.len(), dat.as_ptr()),
None => (0, core::ptr::null()),
};
(self.ResetSystem)(kind, status, size, data);
}
pub fn query_variable_info(&self, attr: VariableAttributes) -> Result<(u64, u64, u64)> {
let mut storage_max_sz = 0;
let mut storage_remaining = 0;
let mut var_max_sz = 0;
let status = (self.QueryVariableInfo)(
attr,
&mut storage_max_sz,
&mut storage_remaining,
&mut var_max_sz,
);
match status {
Status::SUCCESS => Ok((storage_max_sz, storage_remaining, var_max_sz)),
e => Err(e),
}
}
}