use crate::protocol::device_path::DevicePathProtocol;
use crate::table::Header;
use crate::{
Boolean, Char16, Event, Guid, Handle, PhysicalAddress, Status, VirtualAddress, newtype_enum,
};
use bitflags::bitflags;
use core::ffi::c_void;
use core::ops::RangeInclusive;
newtype_enum! {
pub enum AllocateType: u32 => {
ANY_PAGES = 0,
MAX_ADDRESS = 1,
ADDRESS = 2,
MAX_ALLOCATE_TYPE = 3,
}
}
#[derive(Debug)]
#[repr(C)]
pub struct BootServices {
pub header: Header,
pub raise_tpl: unsafe extern "efiapi" fn(new_tpl: Tpl) -> Tpl,
pub restore_tpl: unsafe extern "efiapi" fn(old_tpl: Tpl),
pub allocate_pages: unsafe extern "efiapi" fn(
alloc_ty: AllocateType,
mem_ty: MemoryType,
count: usize,
addr: *mut PhysicalAddress,
) -> Status,
pub free_pages: unsafe extern "efiapi" fn(addr: PhysicalAddress, pages: usize) -> Status,
pub get_memory_map: unsafe extern "efiapi" fn(
size: *mut usize,
map: *mut MemoryDescriptor,
key: *mut usize,
desc_size: *mut usize,
desc_version: *mut u32,
) -> Status,
pub allocate_pool: unsafe extern "efiapi" fn(
pool_type: MemoryType,
size: usize,
buffer: *mut *mut u8,
) -> Status,
pub free_pool: unsafe extern "efiapi" fn(buffer: *mut u8) -> Status,
pub create_event: unsafe extern "efiapi" fn(
ty: EventType,
notify_tpl: Tpl,
notify_func: Option<EventNotifyFn>,
notify_ctx: *mut c_void,
out_event: *mut Event,
) -> Status,
pub set_timer:
unsafe extern "efiapi" fn(event: Event, ty: TimerDelay, trigger_time: u64) -> Status,
pub wait_for_event: unsafe extern "efiapi" fn(
number_of_events: usize,
events: *mut Event,
out_index: *mut usize,
) -> Status,
pub signal_event: unsafe extern "efiapi" fn(event: Event) -> Status,
pub close_event: unsafe extern "efiapi" fn(event: Event) -> Status,
pub check_event: unsafe extern "efiapi" fn(event: Event) -> Status,
pub install_protocol_interface: unsafe extern "efiapi" fn(
handle: *mut Handle,
guid: *const Guid,
interface_type: InterfaceType,
interface: *const c_void,
) -> Status,
pub reinstall_protocol_interface: unsafe extern "efiapi" fn(
handle: Handle,
protocol: *const Guid,
old_interface: *const c_void,
new_interface: *const c_void,
) -> Status,
pub uninstall_protocol_interface: unsafe extern "efiapi" fn(
handle: Handle,
protocol: *const Guid,
interface: *const c_void,
) -> Status,
pub handle_protocol: unsafe extern "efiapi" fn(
handle: Handle,
proto: *const Guid,
out_proto: *mut *mut c_void,
) -> Status,
pub reserved: *mut c_void,
pub register_protocol_notify: unsafe extern "efiapi" fn(
protocol: *const Guid,
event: Event,
registration: *mut *const c_void,
) -> Status,
pub locate_handle: unsafe extern "efiapi" fn(
search_ty: i32,
proto: *const Guid,
key: *const c_void,
buf_sz: *mut usize,
buf: *mut Handle,
) -> Status,
pub locate_device_path: unsafe extern "efiapi" fn(
proto: *const Guid,
device_path: *mut *const DevicePathProtocol,
out_handle: *mut Handle,
) -> Status,
pub install_configuration_table:
unsafe extern "efiapi" fn(guid_entry: *const Guid, table_ptr: *const c_void) -> Status,
pub load_image: unsafe extern "efiapi" fn(
boot_policy: Boolean,
parent_image_handle: Handle,
device_path: *const DevicePathProtocol,
source_buffer: *const u8,
source_size: usize,
image_handle: *mut Handle,
) -> Status,
pub start_image: unsafe extern "efiapi" fn(
image_handle: Handle,
exit_data_size: *mut usize,
exit_data: *mut *mut Char16,
) -> Status,
pub exit: unsafe extern "efiapi" fn(
image_handle: Handle,
exit_status: Status,
exit_data_size: usize,
exit_data: *mut Char16,
) -> !,
pub unload_image: unsafe extern "efiapi" fn(image_handle: Handle) -> Status,
pub exit_boot_services:
unsafe extern "efiapi" fn(image_handle: Handle, map_key: usize) -> Status,
pub get_next_monotonic_count: unsafe extern "efiapi" fn(count: *mut u64) -> Status,
pub stall: unsafe extern "efiapi" fn(microseconds: usize) -> Status,
pub set_watchdog_timer: unsafe extern "efiapi" fn(
timeout: usize,
watchdog_code: u64,
data_size: usize,
watchdog_data: *const u16,
) -> Status,
pub connect_controller: unsafe extern "efiapi" fn(
controller: Handle,
driver_image: Handle,
remaining_device_path: *const DevicePathProtocol,
recursive: Boolean,
) -> Status,
pub disconnect_controller: unsafe extern "efiapi" fn(
controller: Handle,
driver_image: Handle,
child: Handle,
) -> Status,
pub open_protocol: unsafe extern "efiapi" fn(
handle: Handle,
protocol: *const Guid,
interface: *mut *mut c_void,
agent_handle: Handle,
controller_handle: Handle,
attributes: u32,
) -> Status,
pub close_protocol: unsafe extern "efiapi" fn(
handle: Handle,
protocol: *const Guid,
agent_handle: Handle,
controller_handle: Handle,
) -> Status,
pub open_protocol_information: unsafe extern "efiapi" fn(
handle: Handle,
protocol: *const Guid,
entry_buffer: *mut *const OpenProtocolInformationEntry,
entry_count: *mut usize,
) -> Status,
pub protocols_per_handle: unsafe extern "efiapi" fn(
handle: Handle,
protocol_buffer: *mut *mut *const Guid,
protocol_buffer_count: *mut usize,
) -> Status,
pub locate_handle_buffer: unsafe extern "efiapi" fn(
search_ty: i32,
proto: *const Guid,
key: *const c_void,
no_handles: *mut usize,
buf: *mut *mut Handle,
) -> Status,
pub locate_protocol: unsafe extern "efiapi" fn(
proto: *const Guid,
registration: *mut c_void,
out_proto: *mut *mut c_void,
) -> Status,
pub install_multiple_protocol_interfaces:
unsafe extern "C" fn(handle: *mut Handle, ...) -> Status,
pub uninstall_multiple_protocol_interfaces: unsafe extern "C" fn(handle: Handle, ...) -> Status,
pub calculate_crc32:
unsafe extern "efiapi" fn(data: *const c_void, data_size: usize, crc32: *mut u32) -> Status,
pub copy_mem: unsafe extern "efiapi" fn(dest: *mut u8, src: *const u8, len: usize),
pub set_mem: unsafe extern "efiapi" fn(buffer: *mut u8, len: usize, value: u8),
pub create_event_ex: unsafe extern "efiapi" fn(
ty: EventType,
notify_tpl: Tpl,
notify_fn: Option<EventNotifyFn>,
notify_ctx: *mut c_void,
event_group: *mut Guid,
out_event: *mut Event,
) -> Status,
}
bitflags! {
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct EventType: u32 {
const TIMER = 0x8000_0000;
const RUNTIME = 0x4000_0000;
const NOTIFY_WAIT = 0x0000_0100;
const NOTIFY_SIGNAL = 0x0000_0200;
const SIGNAL_EXIT_BOOT_SERVICES = 0x0000_0201;
const SIGNAL_VIRTUAL_ADDRESS_CHANGE = 0x6000_0202;
}
}
newtype_enum! {
pub enum InterfaceType: u32 => {
NATIVE_INTERFACE = 0,
}}
pub type EventNotifyFn = unsafe extern "efiapi" fn(event: Event, context: *mut c_void);
bitflags! {
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MemoryAttribute: u64 {
const UNCACHEABLE = 0x1;
const WRITE_COMBINE = 0x2;
const WRITE_THROUGH = 0x4;
const WRITE_BACK = 0x8;
const UNCACHABLE_EXPORTED = 0x10;
const WRITE_PROTECT = 0x1000;
const READ_PROTECT = 0x2000;
const EXECUTE_PROTECT = 0x4000;
const NON_VOLATILE = 0x8000;
const MORE_RELIABLE = 0x10000;
const READ_ONLY = 0x20000;
const SPECIAL_PURPOSE = 0x4_0000;
const CPU_CRYPTO = 0x8_0000;
const RUNTIME = 0x8000_0000_0000_0000;
const ISA_VALID = 0x4000_0000_0000_0000;
const ISA_MASK = 0x0FFF_F000_0000_0000;
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct MemoryDescriptor {
pub ty: MemoryType,
pub phys_start: PhysicalAddress,
pub virt_start: VirtualAddress,
pub page_count: u64,
pub att: MemoryAttribute,
}
impl MemoryDescriptor {
pub const VERSION: u32 = 1;
}
impl Default for MemoryDescriptor {
fn default() -> Self {
Self {
ty: MemoryType::RESERVED,
phys_start: 0,
virt_start: 0,
page_count: 0,
att: MemoryAttribute::empty(),
}
}
}
newtype_enum! {
pub enum MemoryType: u32 => {
RESERVED = 0,
LOADER_CODE = 1,
LOADER_DATA = 2,
BOOT_SERVICES_CODE = 3,
BOOT_SERVICES_DATA = 4,
RUNTIME_SERVICES_CODE = 5,
RUNTIME_SERVICES_DATA = 6,
CONVENTIONAL = 7,
UNUSABLE = 8,
ACPI_RECLAIM = 9,
ACPI_NON_VOLATILE = 10,
MMIO = 11,
MMIO_PORT_SPACE = 12,
PAL_CODE = 13,
PERSISTENT_MEMORY = 14,
UNACCEPTED = 15,
MAX = 16,
}}
impl MemoryType {
pub const RESERVED_FOR_OEM: RangeInclusive<u32> = 0x7000_0000..=0x7fff_ffff;
pub const RESERVED_FOR_OS_LOADER: RangeInclusive<u32> = 0x8000_0000..=0xffff_ffff;
#[must_use]
pub const fn custom(value: u32) -> Self {
assert!(value >= 0x80000000);
Self(value)
}
}
#[derive(Debug)]
#[repr(C)]
pub struct OpenProtocolInformationEntry {
pub agent_handle: Handle,
pub controller_handle: Handle,
pub attributes: u32,
pub open_count: u32,
}
newtype_enum! {
pub enum Tpl: usize => {
APPLICATION = 4,
CALLBACK = 8,
NOTIFY = 16,
HIGH_LEVEL = 31,
}}
pub const PAGE_SIZE: usize = 4096;
newtype_enum! {
pub enum TimerDelay: i32 => {
CANCEL = 0,
PERIODIC = 1,
RELATIVE = 2,
}
}