Skip to content

Commit

Permalink
spdm_transport: generic: refactor IO buffers
Browse files Browse the repository at this point in the history
This allows us to remove alot of repeated code for buffer `set/get`. This
approach uses a heap allocated vector and just passes a reference to
`libspdm` when required.

The associated memory shall be explicitly freed
by taking ownership when the buffers are no longer required. Which can be
done by calling `libspdm_drop_io_buffers()`.

Signed-off-by: Wilfred Mallawa <[email protected]>
  • Loading branch information
twilfredo committed Oct 31, 2024
1 parent 7ad6129 commit 44b76c7
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 683 deletions.
140 changes: 4 additions & 136 deletions src/doe_pci_cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ use std::slice::{from_raw_parts, from_raw_parts_mut};
const SEND_RECEIVE_BUFFER_LEN: usize = LIBSPDM_MAX_SPDM_MSG_SIZE as usize;
const LIBSPDM_STATUS_ERROR_PEER: u32 =
libspdm_status_construct!(LIBSPDM_SEVERITY_ERROR, LIBSPDM_SOURCE_CORE, 0x000a);
static mut SEND_BUFFER: OnceCell<[u8; SEND_RECEIVE_BUFFER_LEN]> = OnceCell::new();
static mut RECEIVE_BUFFER: OnceCell<[u8; SEND_RECEIVE_BUFFER_LEN]> = OnceCell::new();

const DOE_CONTROL: i32 = 0x08;
const DOE_CONTROL_GO: u32 = 1 << 31;
Expand Down Expand Up @@ -180,122 +178,6 @@ unsafe extern "C" fn doe_pci_cfg_receive_message(
0
}

/// # Summary
///
/// A helper function to capture the SEND_BUFFER into `msg_buf_ptr`
///
/// # Parameter
///
/// * `_context`: The SPDM context
/// * `max_msg_size`: Returns the length of the sender buffer
/// * `msg_buf_ptr`: Returns a pointer to the sender buffer (mutable)
///
/// # Returns
///
/// (0) on success
///
/// # Panics
///
/// Panics if the SEND_BUFFER is not available
#[no_mangle]
unsafe extern "C" fn doe_pci_cfg_acquire_sender_buffer(
_context: *mut c_void,
msg_buf_ptr: *mut *mut c_void,
) -> u32 {
let mut buf = SEND_BUFFER.take().unwrap();
let buf_ptr = buf.as_mut_ptr() as *mut _ as *mut c_void;

*msg_buf_ptr = buf_ptr;

0
}

/// # Summary
///
/// A helper function to reset the SEND_BUFFER from `msg_buf_ptr`
///
/// # Parameter
///
/// * `_context`: The SPDM context
/// * `msg_buf_ptr`: A pointer representing the sender buffer.
///
/// # Returns
///
/// (0) on success
///
/// # Panics
///
/// Panics if the `msg_buf_ptr` is invalid or has less elements
/// than `SEND_RECEIVE_BUFFER_LEN`
#[no_mangle]
unsafe extern "C" fn doe_pci_cfg_release_sender_buffer(
_context: *mut c_void,
msg_buf_ptr: *const c_void,
) {
let message = msg_buf_ptr as *const u8;
let msg_buf = from_raw_parts(message, SEND_RECEIVE_BUFFER_LEN);

SEND_BUFFER.set(msg_buf.try_into().unwrap()).unwrap();
}

/// # Summary
///
/// A helper function to capture the RECEIVE_BUFFER into `msg_buf_ptr`
///
/// # Parameter
///
/// * `_context`: The SPDM context
/// * `max_msg_size`: Returns the length of the receiver buffer
/// * `msg_buf_ptr`: Returns a pointer to the receiver buffer (mutable)
///
/// # Returns
///
/// (0) on success
///
/// # Panics
///
/// Panics if the SEND_BUFFER is not available
#[no_mangle]
unsafe extern "C" fn doe_pci_cfg_acquire_receiver_buffer(
_context: *mut c_void,
msg_buf_ptr: *mut *mut c_void,
) -> u32 {
let mut buf = RECEIVE_BUFFER.take().unwrap();
let buf_ptr = buf.as_mut_ptr() as *mut _ as *mut c_void;

*msg_buf_ptr = buf_ptr;

0
}

/// # Summary
///
/// A helper function to reset the RECEIVE_BUFFER from `msg_buf_ptr`
///
/// # Parameter
///
/// * `_context`: The SPDM context
/// * `msg_buf_ptr`: A pointer representing the receiver buffer.
///
/// # Returns
///
/// (0) on success
///
/// # Panics
///
/// Panics if the `msg_buf_ptr` is invalid or has less elements
/// than `SEND_RECEIVE_BUFFER_LEN`
#[no_mangle]
unsafe extern "C" fn doe_pci_cfg_release_receiver_buffer(
_context: *mut c_void,
msg_buf_ptr: *const c_void,
) {
let message = msg_buf_ptr as *const u8;
let msg_buf = from_raw_parts(message, SEND_RECEIVE_BUFFER_LEN);

RECEIVE_BUFFER.set(msg_buf.try_into().unwrap()).unwrap();
}

/// # Summary
///
/// Registers the SPDM `context` for a PCIe DOE backend.
Expand All @@ -314,21 +196,11 @@ unsafe extern "C" fn doe_pci_cfg_release_receiver_buffer(
///
/// Panics if `SEND_BUFFER/RECEIVE_BUFFER` is occupied
pub fn register_device(context: *mut c_void, pcie_vid: u16, pcie_devid: u16) -> Result<(), ()> {
let buffer_send = [0; SEND_RECEIVE_BUFFER_LEN];
let buffer_receive = [0; SEND_RECEIVE_BUFFER_LEN];
let pcie_ids = PcieIdentifiers {
vid: pcie_vid,
devid: pcie_devid,
};
unsafe {
SEND_BUFFER.set(buffer_send).map_err(|e| {
error!("Failed to set send buffer: {e:?}");
()
})?;
RECEIVE_BUFFER.set(buffer_receive).map_err(|e| {
error!("Failed to set receive buffer: {e:?}");
()
})?;
PCIE_IDENTIFIERS.set(pcie_ids).map_err(|e| {
error!("Failed to set device PCIe Identifiers: {e:?}");
()
Expand All @@ -339,15 +211,11 @@ pub fn register_device(context: *mut c_void, pcie_vid: u16, pcie_devid: u16) ->
Some(doe_pci_cfg_send_message),
Some(doe_pci_cfg_receive_message),
);
libspdm_register_device_buffer_func(
io_buffers::libspdm_setup_io_buffers(
context,
SEND_RECEIVE_BUFFER_LEN as u32,
SEND_RECEIVE_BUFFER_LEN as u32,
Some(doe_pci_cfg_acquire_sender_buffer),
Some(doe_pci_cfg_release_sender_buffer),
Some(doe_pci_cfg_acquire_receiver_buffer),
Some(doe_pci_cfg_release_receiver_buffer),
);
SEND_RECEIVE_BUFFER_LEN,
SEND_RECEIVE_BUFFER_LEN,
)?;
}

Ok(())
Expand Down
133 changes: 133 additions & 0 deletions src/io_buffers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
use once_cell::sync::OnceCell;
use std::ffi::c_void;

static mut SEND_BUFFER: OnceCell<Vec<u8>> = OnceCell::new();
static mut RECEIVE_BUFFER: OnceCell<Vec<u8>> = OnceCell::new();

pub fn libspdm_setup_io_buffers(
context: *mut c_void,
send_recv_len: usize,
libsdpm_buff_len: usize,
) -> Result<(), ()> {
let result = std::panic::catch_unwind(|| {
let buffer_send = vec![0; send_recv_len];
let buffer_receive = vec![0; send_recv_len];
(buffer_send, buffer_receive)
});

match result {
Ok(buffers) => {
unsafe {
SEND_BUFFER.set(buffers.0).map_err(|_| {
error!("Failed to set send buffer");
()
})?;
RECEIVE_BUFFER.set(buffers.1).map_err(|_| {
error!("Failed to set receive buffer");
()
})?;
}

unsafe {
libspdm::libspdm_rs::libspdm_register_device_buffer_func(
context,
libsdpm_buff_len as u32,
libsdpm_buff_len as u32,
Some(acquire_sender_buffer),
Some(release_sender_buffer),
Some(acquire_receiver_buffer),
Some(release_receiver_buffer),
)
}
Ok(())
}
Err(_) => {
error!("Failed to allocate transport buffers");
Err(())
}
}
}

/// # Summary
///
/// A helper function to capture the SEND_BUFFER into `msg_buf_ptr`
///
/// # Parameter
///
/// * `_context`: The SPDM context
/// * `max_msg_size`: Returns the length of the sender buffer
/// * `msg_buf_ptr`: Returns a pointer to the sender buffer (mutable)
///
/// # Returns
///
/// (0) on success
///
/// # Panics
///
/// Panics if the SEND_BUFFER is not available
#[no_mangle]
pub unsafe extern "C" fn acquire_sender_buffer(
_context: *mut c_void,
msg_buf_ptr: *mut *mut c_void,
) -> u32 {
if let Some(buffer) = SEND_BUFFER.get() {
let buf_ptr = buffer.as_ptr() as *mut c_void;
*msg_buf_ptr = buf_ptr;
return 0;
}
error!("Sender buffer is lost or not initialized");
return 1;
}

/// # Summary
///
/// A helper function to capture the RECEIVE_BUFFER into `msg_buf_ptr`
///
/// # Parameter
///
/// * `_context`: The SPDM context
/// * `max_msg_size`: Returns the length of the receiver buffer
/// * `msg_buf_ptr`: Returns a pointer to the receiver buffer (mutable)
///
/// # Returns
///
/// (0) on success
///
/// # Panics
///
/// Panics if the SEND_BUFFER is not available
#[no_mangle]
pub unsafe extern "C" fn acquire_receiver_buffer(
_context: *mut c_void,
msg_buf_ptr: *mut *mut c_void,
) -> u32 {
if let Some(buffer) = RECEIVE_BUFFER.get() {
let buf_ptr = buffer.as_ptr() as *mut c_void;
*msg_buf_ptr = buf_ptr;
return 0;
}
error!("Receiver buffer is lost or not initialized");
return 1;
}

/// We are only passing a reference to heap allocated memory, no-op required
#[no_mangle]
pub unsafe extern "C" fn release_receiver_buffer(
_context: *mut c_void,
_msg_buf_ptr: *const c_void,
) {
}

/// We are only passing a reference to heap allocated memory, no-op required
#[no_mangle]
pub unsafe extern "C" fn release_sender_buffer(_context: *mut c_void, _msg_buf_ptr: *const c_void) {
}

/// # Summary
///
/// Take ownership of the IO buffer and drop them out of context allowing the
/// underlying memory to be freed.
pub unsafe fn libspdm_drop_io_buffers() {
if let Some(_) = SEND_BUFFER.take() {}
if let Some(_) = RECEIVE_BUFFER.take() {}
}
2 changes: 2 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub static SOCKET_PATH: &str = "SPDM-Utils-loopback-socket";

mod cli_helpers;
mod doe_pci_cfg;
mod io_buffers;
mod qemu_server;
mod request;
mod socket_client;
Expand Down Expand Up @@ -890,6 +891,7 @@ async fn main() -> Result<(), ()> {
}
}
}
unsafe { io_buffers::libspdm_drop_io_buffers() }
Ok(())
}

Expand Down
Loading

0 comments on commit 44b76c7

Please sign in to comment.