Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions components/patina_mm/src/component/communicator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
mod comm_buffer_update;

use crate::{
config::{CommunicateBuffer, EfiMmCommunicateHeader, MmCommunicationConfiguration},
config::{CommunicateBuffer, MmCommunicationConfiguration},
service::SwMmiTrigger,
};
use patina::{
Expand All @@ -26,8 +26,9 @@ use patina::{
Storage, component,
service::{IntoService, Service},
},
management_mode::EfiMmCommunicateHeader,
};
extern crate alloc;

use alloc::{boxed::Box, vec::Vec};

use core::{
Expand Down Expand Up @@ -373,14 +374,16 @@ mod tests {
communicator::{MmCommunicator, MockMmExecutor},
sw_mmi_manager::SwMmiManager,
},
config::{CommunicateBuffer, MmCommBufferStatus, MmCommunicationConfiguration},
config::{CommunicateBuffer, MmCommunicationConfiguration},
};
use patina::{
component::{IntoComponent, Storage},
management_mode::MmCommBufferStatus,
};
use patina::component::{IntoComponent, Storage};

use core::{cell::RefCell, pin::Pin};

extern crate alloc;
use alloc::vec::Vec;
use std::vec::Vec;

/// Simple MM Executor for unit tests that simulates MM handlers echoing request data back as the response
struct EchoMmExecutor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,16 @@
//!
//! SPDX-License-Identifier: Apache-2.0

use crate::{
component::communicator::MmCommunicator,
config::CommunicateBuffer,
protocol::mm_comm_buffer_update::{self, MmCommBufferUpdateProtocol},
};
use crate::{component::communicator::MmCommunicator, config::CommunicateBuffer};
use patina::{
base::UEFI_PAGE_SIZE,
boot_services::{BootServices, StandardBootServices, event::EventType, tpl::Tpl},
management_mode::protocol::mm_comm_buffer_update::{self, MmCommBufferUpdateProtocol},
};
use zerocopy::FromBytes;

use core::sync::atomic::{AtomicBool, AtomicPtr, Ordering};

extern crate alloc;
use alloc::boxed::Box;

/// Context for the MM Comm Buffer Update Protocol notify callback
Expand Down Expand Up @@ -289,8 +285,7 @@ mod tests {
};
use patina::boot_services::StandardBootServices;

extern crate alloc;
use alloc::{boxed::Box, vec};
use alloc::boxed::Box;

/// Helper to create a test protocol notify context without boot services
fn create_test_context(
Expand Down
111 changes: 5 additions & 106 deletions components/patina_mm/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,51 +18,14 @@
//!
//! SPDX-License-Identifier: Apache-2.0
//!
extern crate alloc;
use alloc::vec::Vec;
use core::{fmt, pin::Pin, ptr::NonNull};

use patina::{BinaryGuid, Guid, base::UEFI_PAGE_MASK};
use zerocopy_derive::*;

/// MM Communication Buffer Status
///
/// Shared structure between DXE and MM environments to communicate the status
/// of MM communication operations. This structure is written by DXE before
/// triggering an MMI and read/written by MM during MMI processing.
///
/// This is a structure currently used in some MM Supervisor MM implementations.
#[derive(Debug, Clone, Copy, FromBytes, IntoBytes, Immutable, KnownLayout)]
#[repr(C, packed)]
pub struct MmCommBufferStatus {
/// Whether the data in the fixed MM communication buffer is valid when entering from non-MM to MM.
/// Must be set to TRUE before triggering MMI, will be set to FALSE by MM after processing.
pub is_comm_buffer_valid: u8,

/// The channel used to communicate with MM.
/// FALSE = user buffer, TRUE = supervisor buffer
pub talk_to_supervisor: u8,

/// The return status when returning from MM to non-MM.
pub return_status: u64,

/// The size in bytes of the output buffer when returning from MM to non-MM.
pub return_buffer_size: u64,
}

impl Default for MmCommBufferStatus {
#[coverage(off)]
fn default() -> Self {
Self::new()
}
}

impl MmCommBufferStatus {
/// Create a new mailbox status with all fields zeroed
pub const fn new() -> Self {
Self { is_comm_buffer_valid: 0, talk_to_supervisor: 0, return_status: 0, return_buffer_size: 0 }
}
}
use patina::{
BinaryGuid, Guid,
base::UEFI_PAGE_MASK,
management_mode::{EfiMmCommunicateHeader, MmCommBufferStatus},
};

/// Management Mode (MM) Configuration
///
Expand Down Expand Up @@ -119,70 +82,6 @@ impl fmt::Display for MmCommunicationConfiguration {
}
}

/// UEFI MM Communicate Header
///
/// A standard header that must be present at the beginning of any MM communication buffer.
///
/// ## Notes
///
/// - This only supports V1 and V2 of the MM Communicate header format.
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct EfiMmCommunicateHeader {
/// Allows for disambiguation of the message format.
/// Used to identify the registered MM handlers that should be given the message.
header_guid: patina::BinaryGuid,
/// The size of Data (in bytes) and does not include the size of the header.
message_length: usize,
}

impl EfiMmCommunicateHeader {
/// Create a new communicate header with the specified GUID and message length.
pub fn new(header_guid: Guid, message_length: usize) -> Self {
Self { header_guid: header_guid.to_efi_guid().into(), message_length }
}

/// Returns the communicate header as a slice of bytes using safe conversion.
///
/// Useful if byte-level access to the header structure is needed.
pub fn as_bytes(&self) -> &[u8] {
// SAFETY: EfiMmCommunicateHeader is repr(C) with well-defined layout and size
unsafe { core::slice::from_raw_parts(self as *const _ as *const u8, Self::size()) }
}

/// Returns the size of the header in bytes.
pub const fn size() -> usize {
core::mem::size_of::<Self>()
}

/// Get the header GUID from the communication buffer.
///
/// Returns `Some(guid)` if the buffer has been properly initialized with a GUID,
/// or `None` if the buffer is not initialized.
///
/// # Returns
///
/// The GUID from the communication header if available.
///
/// # Errors
///
/// Returns an error if the communication buffer header cannot be read.
pub fn header_guid(&self) -> Guid<'_> {
Guid::from_ref(&self.header_guid)
}

/// Returns the message length from this communicate header.
///
/// The length represents the size of the message data that follows the header.
///
/// # Returns
///
/// The length in bytes of the message data (excluding the header size).
pub const fn message_length(&self) -> usize {
self.message_length
}
}

/// MM Communicator Service Status Codes
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum CommunicateBufferStatus {
Expand Down
3 changes: 2 additions & 1 deletion components/patina_mm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
#![cfg_attr(all(not(feature = "std"), not(test), not(feature = "mockall")), no_std)]
#![feature(coverage_attribute)]

extern crate alloc;

pub mod component;
pub mod config;
pub mod protocol;
pub mod service;
Original file line number Diff line number Diff line change
Expand Up @@ -11,52 +11,16 @@ use patina::base::SIZE_4KB;
/// Standard test buffer size
pub const TEST_BUFFER_SIZE: usize = SIZE_4KB;

/// MM Supervisor constants and definitions
/// MM Supervisor constants and definitions for testing
///
/// Note: These values are only used for testing. They're not meant to be
/// accurate or used in production code.
pub mod mm_supv {
/// Supervisor signature bytes
pub const SIGNATURE: [u8; 4] = [b'M', b'S', b'U', b'P'];

/// Communication protocol revision
pub const REVISION: u32 = 1;

/// Request signature as a DWORD
pub const REQUEST_SIGNATURE: u32 = 0x5055534D; // 'MSUP'

/// Supervisor version
/// Mock supervisor version for testing
pub const VERSION: u32 = 0x00130008;

/// Supervisor patch level
/// Mock supervisor patch level for testing
pub const PATCH_LEVEL: u32 = 0x00010001;

/// Maximum request level supported
pub const MAX_REQUEST_LEVEL: u64 = 0x0000000000000004; // COMM_UPDATE

/// Request type constants
pub mod requests {
/// Request for unblocking memory regions
pub const UNBLOCK_MEM: u32 = 0x0001;

/// Request to fetch security policy
pub const FETCH_POLICY: u32 = 0x0002;

/// Request version information
pub const VERSION_INFO: u32 = 0x0003;

/// Request to update the communication buffer address
pub const COMM_UPDATE: u32 = 0x0004;
}

/// Response code constants
pub mod responses {
/// Operation completed successfully
pub const SUCCESS: u64 = 0;

/// Operation failed with error
pub const ERROR: u64 = 0xFFFFFFFFFFFFFFFF;
}
}

/// Test GUIDs for different handlers
Expand Down
Loading
Loading