Skip to content

Add handle_protocol_mut #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
11 changes: 10 additions & 1 deletion src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use void::CVoid;
/// Type for EFI_HANDLE.
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct Handle(*mut CVoid);
pub struct Handle(pub(crate) *mut CVoid);

impl default::Default for Handle {
fn default() -> Handle { Handle(ptr::null_mut()) }
Expand Down Expand Up @@ -178,6 +178,15 @@ pub enum MemoryType {
PalCode = 13,
}

/// Type for EFI_ALLOCATE_TYPE
#[derive(PartialEq, PartialOrd, Debug, Clone, Copy)]
#[repr(C)]
pub enum AllocateType {
AnyPages = 0,
MaxAddress = 1,
Address = 2,
}

/// UEFI Time structure.
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
Expand Down
106 changes: 99 additions & 7 deletions src/bootservices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,24 @@ use core::ptr;
use core::mem;

use void::{NotYetDef, CVoid};
use base::{Event, Handle, Handles, MemoryType, Status};
use base::{AllocateType, Event, Handle, Handles, MemoryType, Status};
use event::{EventType, EventNotify, TimerDelay};
use task::TPL;
use protocol::{DevicePathProtocol, Protocol, get_current_image};
use guid;
use table;

bitflags! {
pub struct OpenProtocolAttributes: u32 {
const BY_HANDLE_PROTOCOL = 0x01;
const GET_PROTOCOL = 0x02;
const TEST_PROTOCOL = 0x04;
const BY_CHILD_CONTROLLER = 0x08;
const BY_DRIVER = 0x10;
const EXCLUSIVE = 0x20;
}
}

#[repr(C)]
pub enum LocateSearchType {
AllHandles = 0,
Expand All @@ -22,8 +33,8 @@ pub struct BootServices {
header: table::TableHeader,
raise_tpl: *const NotYetDef,
restore_tpl: *const NotYetDef,
allocate_pages: *const NotYetDef,
free_pages: *const NotYetDef,
allocate_pages: unsafe extern "win64" fn(allocate_type: AllocateType, pool_type: MemoryType, pages: usize, memory: *mut *mut CVoid) -> Status,
free_pages: unsafe extern "win64" fn(memory: *mut CVoid, pages: usize) -> Status,
get_memory_map: *const NotYetDef,
allocate_pool: unsafe extern "win64" fn(pool_type: MemoryType, size: usize, out: *mut *mut u8) -> Status,
free_pool: unsafe extern "win64" fn(*mut CVoid),
Expand All @@ -41,7 +52,7 @@ pub struct BootServices {
__reserved: *const NotYetDef,
register_protocol_notify: *const NotYetDef,
locate_handle: *const NotYetDef,
locate_device_path: *const NotYetDef,
locate_device_path: unsafe extern "win64" fn(protocol: &guid::Guid, device_path: *mut *const DevicePathProtocol, device: &mut Handle) -> Status,
install_configuration_table: *const NotYetDef,
load_image: unsafe extern "win64" fn(boot_policy: u8, parent_image_handle: Handle, device_path: *const DevicePathProtocol, source_buffer: *const CVoid, source_size: usize, image_handle: *mut Handle) -> Status,
start_image: unsafe extern "win64" fn(image_handle: Handle, exit_data_size: *mut usize, exit_data: *mut *const u16) -> Status,
Expand All @@ -53,21 +64,38 @@ pub struct BootServices {
set_watchdog_timer: unsafe extern "win64" fn(timeout: usize, code: u64, data_size: usize, data: *const u16) -> Status,
connect_controller: *const NotYetDef,
disconnect_controller: *const NotYetDef,
open_protocol: *const NotYetDef,
open_protocol: unsafe extern "win64" fn(handle: Handle, protocol: &guid::Guid, interface: &mut *const CVoid, agent_handle: Handle, controller_handle: Handle, attributes: u32) -> Status,
close_protocol: unsafe extern "win64" fn(handle: Handle, protocol: &guid::Guid, agent_handle: Handle, controller_handle: Handle) -> Status,
open_protocol_information: *const NotYetDef,
protocols_per_handle: *const NotYetDef,
locate_handle_buffer: unsafe extern "win64" fn(search_type: LocateSearchType, protocol: &guid::Guid, search_key: *const CVoid, nhandles: *mut usize, handles: *mut *mut CVoid) -> Status,
locate_protocol: unsafe extern "win64" fn(protocol: &guid::Guid, registration: *const CVoid, interface: &mut *mut CVoid) -> Status,
install_multiple_protocol_interfaces: *const NotYetDef,
uninstall_multiple_protocol_interfaces: *const NotYetDef,
calculate_crc32: *const NotYetDef,
calculate_crc32: unsafe extern "win64" fn(data: *const CVoid, data_size: usize, crc32: &mut u32) -> Status,
copy_mem: unsafe extern "win64" fn(*mut CVoid, *mut CVoid, usize),
set_mem: unsafe extern "win64" fn(*mut CVoid, usize, u8),
create_event_ex: *const NotYetDef,
}

impl BootServices {
pub fn allocate_pages(&self, pages: usize) -> Result<*mut CVoid, Status> {
let mut ptr: *mut CVoid = ptr::null_mut();

let result = unsafe { (self.allocate_pages)(AllocateType::AnyPages, get_current_image().image_data_type, pages, &mut ptr) };
if result != Status::Success {
return Err(result);
}

Ok(ptr)
}

pub fn free_pages<T>(&self, p: *const T, pages: usize) {
unsafe {
(self.free_pages)(p as *mut CVoid, pages);
}
}

/// Allocate `size` bytes of memory using type `T`.
pub fn allocate_pool<T>(&self, size: usize) -> Result<*mut T, Status> {
let mut ptr: *mut u8 = 0 as *mut u8;
Expand Down Expand Up @@ -131,10 +159,41 @@ impl BootServices {
}
}

let r = unsafe { mem::transmute::<*mut CVoid, &'static T>(ptr) };
let r = unsafe { &*(ptr as *const T) };
Ok(r)
}

pub fn handle_protocol_mut<T: Protocol>(&self, handle: Handle) -> Result<&'static mut T, Status> {
let mut ptr : *mut CVoid = 0 as *mut CVoid;
let guid = T::guid();


unsafe {
let status = (self.handle_protocol)(handle, guid, &mut ptr);
if status != Status::Success {
return Err(status);
}
}

let r = unsafe { &mut *(ptr as *mut T) };
Ok(r)
}

/// Queries a handle to determine if it supports a specified protocol. If the protocol is
/// supported by the handle, it opens the protocol on behalf of the calling agent.
pub fn open_protocol<T: Protocol>(&self, handle: Handle, agent_handle: Handle, controller_handle: Handle, attributes: OpenProtocolAttributes) -> Result<&'static T, Status> {
let mut ptr: *const CVoid = ptr::null();
let guid = T::guid();

unsafe {
let status = (self.open_protocol)(handle, guid, &mut ptr, agent_handle, controller_handle, attributes.bits());
match status {
Status::Success => Ok(mem::transmute(ptr.as_ref().unwrap())),
e => Err(e)
}
}
}

// TODO: for the love of types, fix me
pub fn close_protocol<T: Protocol>(&self, handle: Handle, agent_handle: Handle, controller_handle: Handle) -> Status {
let guid = T::guid();
Expand All @@ -159,6 +218,21 @@ impl BootServices {
return Ok(Handles::new(handles as *mut Handle, nhandles));
}

/// Retrieves the closest device on `device_path` to `device_path` that supports the given
/// protocol.
pub fn locate_device_path<T: Protocol>(&self, device_path: &DevicePathProtocol) -> Result<(Handle, Option<&DevicePathProtocol>), Status> {
let mut out: Handle = Handle::default();
let mut device_path_out = device_path as *const DevicePathProtocol;
let guid = T::guid();

let res = unsafe { (self.locate_device_path)(&guid, &mut device_path_out, &mut out) };
if res != Status::Success {
return Err(res);
}

unsafe { Ok((out, device_path_out.as_ref())) }
}

/// Load an image by device path and return its handle.
pub fn load_image(&self, boot_policy: bool, parent_image_handle: Handle, device_path: *const DevicePathProtocol) -> Result<Handle, Status> {
self.load_image_buffer(boot_policy, parent_image_handle, device_path, 0 as *const CVoid, 0)
Expand Down Expand Up @@ -230,6 +304,24 @@ impl BootServices {
}
}

/// Calculate the CRC-32 checksum of some data.
pub fn calculate_crc32<T: Sized>(&self, data: &T) -> Result<u32, Status> {
self.calculate_crc32_sized(data, mem::size_of::<T>())
}

/// Calculate the CRC-32 checksum of some data, using the provided length.
pub fn calculate_crc32_sized<T>(&self, data: *const T, size: usize) -> Result<u32, Status> {
let mut crc32 = 0;

let result =
unsafe { (self.calculate_crc32)(data as *const CVoid, size, &mut crc32) };
if result != Status::Success {
return Err(result);
}

Ok(crc32)
}

/// Copy memory, similar to memcpy.
pub fn copy_mem(&self, dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
unsafe {
Expand Down
2 changes: 1 addition & 1 deletion src/guid.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use core::fmt;

/// Type for EFI_GUID.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct Guid(pub u32, pub u16, pub u16, pub [u8; 8]);

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ pub use guid::*;

pub use systemtable::*;

pub use bootservices::BootServices;
pub use bootservices::*;

pub use runtimeservices::{ResetType, RuntimeServices};

Expand Down
Loading