Skip to content

Commit

Permalink
Merge pull request rust-osdev#1278 from nicholasbishop/bishop-connect…
Browse files Browse the repository at this point in the history
…-controller

boot: Add freestanding connect_controller and disconnect_controller
  • Loading branch information
phip1611 authored Aug 1, 2024
2 parents 71ebba1 + ff48052 commit 6f98341
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 5 deletions.
7 changes: 3 additions & 4 deletions uefi-test-runner/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ fn send_request_helper(serial: &mut Serial, request: HostRequest) -> Result {
/// This must be called after opening the serial protocol in exclusive mode, as
/// that breaks the connection to the console, which in turn prevents logs from
/// getting to the host.
fn reconnect_serial_to_console(boot_services: &BootServices, serial_handle: Handle) {
fn reconnect_serial_to_console(serial_handle: Handle) {
let mut storage = Vec::new();
// Create a device path that specifies the terminal type.
let terminal_guid = if cfg!(target_arch = "aarch64") {
Expand All @@ -160,8 +160,7 @@ fn reconnect_serial_to_console(boot_services: &BootServices, serial_handle: Hand
.finalize()
.unwrap();

boot_services
.connect_controller(serial_handle, None, Some(terminal_device_path), true)
uefi::boot::connect_controller(serial_handle, None, Some(terminal_device_path), true)
.expect("failed to reconnect serial to console");
}

Expand Down Expand Up @@ -198,7 +197,7 @@ fn send_request_to_host(bt: &BootServices, request: HostRequest) {
// device, which was broken when we opened the protocol in exclusive
// mode above.
drop(serial);
reconnect_serial_to_console(bt, serial_handle);
reconnect_serial_to_console(serial_handle);

if let Err(err) = res {
panic!("request failed: \"{request:?}\": {:?}", err.status());
Expand Down
2 changes: 1 addition & 1 deletion uefi-test-runner/src/proto/console/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub unsafe fn test(bt: &BootServices) {
// device, which was broken when we opened the protocol in exclusive
// mode above.
drop(serial);
reconnect_serial_to_console(bt, handle);
reconnect_serial_to_console(handle);

if let Err(err) = res {
panic!("serial test failed: {:?}", err.status());
Expand Down
67 changes: 67 additions & 0 deletions uefi/src/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//! These functions will panic if called after exiting boot services.

use crate::data_types::PhysicalAddress;
use crate::proto::device_path::DevicePath;
use crate::proto::{Protocol, ProtocolPointer};
use core::ffi::c_void;
use core::ops::{Deref, DerefMut};
Expand Down Expand Up @@ -161,6 +162,72 @@ pub unsafe fn free_pool(ptr: NonNull<u8>) -> Result {
unsafe { (bt.free_pool)(ptr.as_ptr()) }.to_result()
}

/// Connect one or more drivers to a controller.
///
/// Usually one disconnects and then reconnects certain drivers
/// to make them rescan some state that changed, e.g. reconnecting
/// a block handle after your app modified disk partitions.
///
/// # Errors
///
/// * [`Status::NOT_FOUND`]: there are no driver-binding protocol instances
/// present in the system, or no drivers are connected to `controller`.
/// * [`Status::SECURITY_VIOLATION`]: the caller does not have permission to
/// start drivers associated with `controller`.
pub fn connect_controller(
controller: Handle,
driver_image: Option<Handle>,
remaining_device_path: Option<&DevicePath>,
recursive: bool,
) -> Result {
let bt = boot_services_raw_panicking();
let bt = unsafe { bt.as_ref() };

unsafe {
(bt.connect_controller)(
controller.as_ptr(),
Handle::opt_to_ptr(driver_image),
remaining_device_path
.map(|dp| dp.as_ffi_ptr())
.unwrap_or(ptr::null())
.cast(),
recursive,
)
}
.to_result_with_err(|_| ())
}

/// Disconnect one or more drivers from a controller.
///
/// See also [`connect_controller`].
///
/// # Errors
///
/// * [`Status::INVALID_PARAMETER`]: `driver_image` is set but does not manage
/// `controller`, or does not support the driver binding protocol, or one of
/// the handles is invalid.
/// * [`Status::OUT_OF_RESOURCES`]: not enough resources available to disconnect
/// drivers.
/// * [`Status::DEVICE_ERROR`]: the controller could not be disconnected due to
/// a device error.
pub fn disconnect_controller(
controller: Handle,
driver_image: Option<Handle>,
child: Option<Handle>,
) -> Result {
let bt = boot_services_raw_panicking();
let bt = unsafe { bt.as_ref() };

unsafe {
(bt.disconnect_controller)(
controller.as_ptr(),
Handle::opt_to_ptr(driver_image),
Handle::opt_to_ptr(child),
)
}
.to_result_with_err(|_| ())
}

/// Returns an array of handles that support the requested protocol in a
/// pool-allocated buffer.
///
Expand Down

0 comments on commit 6f98341

Please sign in to comment.