Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ syn = { version = "2" }
uart_16550 = { version = "^0.3.2" }
uefi_corosensei = { version = "0.1.3", default-features = false, registry = "patina-fw" }
uuid = { version = "1.8", default-features = false }
utf16_lit = { version = "2.0.2" }
x86_64 = { version = "=0.15.2", default-features = false }

# dev dependencies
Expand Down
1 change: 1 addition & 0 deletions components/patina_adv_logger/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mu_pi = { workspace = true }
r-efi = { workspace = true }
spin = { workspace = true }
mu_rust_helpers = { workspace = true }
utf16_lit = { workspace = true }

# Only used for CLI
clap = { workspace = true, features = ['derive'], optional = true }
Expand Down
108 changes: 102 additions & 6 deletions components/patina_adv_logger/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,25 @@ use alloc::boxed::Box;
use core::{ffi::c_void, ptr};
use mu_pi::hob::{Hob, PhaseHandoffInformationTable};
use patina_sdk::{
boot_services::{BootServices, StandardBootServices},
boot_services::{BootServices, StandardBootServices, event::EventType, tpl::Tpl},
component::IntoComponent,
error::{EfiError, Result},
runtime_services::{RuntimeServices, StandardRuntimeServices},
serial::SerialIO,
uefi_protocol::ProtocolInterface,
variable_policy::{BasicVariablePolicy, VariablePolicy, VariablePolicyProtocol},
};
use r_efi::efi;
use r_efi::efi::{self, Guid};

use crate::{
logger::AdvancedLogger,
memory_log::{self, AdvLoggerInfo},
memory_log::{self, ADV_LOGGER_HOB_GUID, ADV_LOGGER_LOCATOR_VAR_NAME, AdvLoggerInfo},
protocol::AdvancedLoggerProtocol,
};

const VARIABLE_WRITE_ARCH_PROTOCOL_GUID: Guid =
Guid::from_fields(0x6441f818, 0x6362, 0x4e44, 0xb5, 0x70, &[0x7d, 0xba, 0x31, 0xdd, 0x24, 0x53]);

/// C struct for the internal Advanced Logger protocol for the component.
#[repr(C)]
struct AdvancedLoggerProtocolInternal<S>
Expand Down Expand Up @@ -112,7 +118,7 @@ where
///
/// Installs the Advanced Logger Protocol for use by non-local components.
///
fn entry_point(self, bs: StandardBootServices) -> Result<()> {
fn entry_point(self, bs: StandardBootServices, rs: StandardRuntimeServices) -> Result<()> {
let log_info = match self.adv_logger.get_log_info() {
Some(log_info) => log_info,
None => {
Expand All @@ -131,13 +137,103 @@ where
match bs.install_protocol_interface(None, &mut protocol.protocol) {
Err(status) => {
log::error!("Failed to install Advanced Logger protocol! Status = {:#x?}", status);
Err(EfiError::ProtocolError)
return Err(EfiError::ProtocolError);
}
Ok(_) => {
log::info!("Advanced Logger protocol installed.");
Ok(())
}
}

// Create an event to write the AdvLoggerLocator variable once the variable write architectural protocol
// is available
match bs.create_event(
EventType::NOTIFY_SIGNAL,
Tpl::CALLBACK,
Some(variable_write_registered),
Box::new((bs.clone(), rs.clone(), address)),
) {
Err(status) => {
log::error!("Failed to create create variable write registered event! Status = {:#x?}", status);
}
Ok(event) => {
if let Err(status) = bs.register_protocol_notify(&VARIABLE_WRITE_ARCH_PROTOCOL_GUID, event) {
log::error!("Failed to register protocol notify for variable write event! Status = {:#x?}", status);
}
}
};

// Create an event to lock the AdvancedLoggerLocator variable if/when the variable policy protocol is
// available
match bs.create_event::<Box<StandardBootServices>>(
EventType::NOTIFY_SIGNAL,
Tpl::CALLBACK,
Some(variable_policy_registered),
Box::new(bs.clone()),
) {
Err(status) => {
log::error!("Failed to create create variable policy registered event! Status = {:#x?}", status);
}
Ok(event) => {
if let Err(status) = bs.register_protocol_notify(&VariablePolicyProtocol::PROTOCOL_GUID, event) {
log::error!("Failed to register protocol notify for variable write event! Status = {:#x?}", status);
}
}
};

Ok(())
}
}

/// Event callback triggered when the variable write architectural protocol is installed that will
/// write the "AdvancedLoggerLocator" variable.
extern "efiapi" fn variable_write_registered(
event: *mut c_void,
ctx: Box<(StandardBootServices, StandardRuntimeServices, u64)>,
) {
let (bs, rs, address) = *ctx;

// Always close the event to prevent a double-free when ctx is dropped
let _ = bs.close_event(event);

// Write the AdvLoggerLocator variable
if let Err(status) = rs.set_variable(
ADV_LOGGER_LOCATOR_VAR_NAME,
&ADV_LOGGER_HOB_GUID,
r_efi::system::VARIABLE_RUNTIME_ACCESS | r_efi::system::VARIABLE_BOOTSERVICE_ACCESS,
&address.to_le_bytes(),
) {
log::error!("Failed to set the advanced logger locator variable. Status = {:#x?}", status);
}
}

/// Event callback triggered when the variable write architectural protocol is installed that will
/// register a Mu variable protection policy on the "AdvancedLoggerLocator" variable.
extern "efiapi" fn variable_policy_registered(event: *mut c_void, bs: Box<StandardBootServices>) {
// Always close the event to prevent a double-free when bs is dropped
let _ = bs.close_event(event);

// Set the policy on the AdvLoggerLocator variable
match unsafe { bs.locate_protocol::<VariablePolicyProtocol>(None) } {
Ok(protocol) => {
// Match policy from Mu's AdvLoggerPkg implementation
if let Err(status) = protocol.register_variable_policy(&VariablePolicy::LockOnCreate(
BasicVariablePolicy::new_exact_match(
Some(ADV_LOGGER_LOCATOR_VAR_NAME),
ADV_LOGGER_HOB_GUID,
Some(size_of::<efi::PhysicalAddress>() as u32),
Some(r_efi::system::VARIABLE_RUNTIME_ACCESS | r_efi::system::VARIABLE_BOOTSERVICE_ACCESS),
)
.unwrap(),
)) {
log::error!(
"Failed to set variable policy on advanced logger locator variable. Status = {:#x?}",
status
)
}
}
Err(status) => {
log::error!("Failed to locate variable policy protocol! Status = {:#x?}", status)
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions components/patina_adv_logger/src/memory_log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ use core::{
};
use patina_sdk::error::{EfiError, Result};
use r_efi::efi;
use utf16_lit::utf16_null;

// { 0x4d60cfb5, 0xf481, 0x4a98, {0x9c, 0x81, 0xbf, 0xf8, 0x64, 0x60, 0xc4, 0x3e }}
pub const ADV_LOGGER_HOB_GUID: efi::Guid =
efi::Guid::from_fields(0x4d60cfb5, 0xf481, 0x4a98, 0x9c, 0x81, &[0xbf, 0xf8, 0x64, 0x60, 0xc4, 0x3e]);

pub const ADV_LOGGER_LOCATOR_VAR_NAME: &[u16] = &utf16_null!("AdvLoggerLocator");

// UEFI Debug Levels
pub const DEBUG_LEVEL_ERROR: u32 = 0x80000000;
pub const DEBUG_LEVEL_WARNING: u32 = 0x00000002;
Expand Down
2 changes: 2 additions & 0 deletions sdk/patina_sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ num-traits = { workspace = true }
fallible-streaming-iterator = { workspace = true }
linkme = { workspace = true }
scroll = { workspace = true }
uuid = {workspace = true}

[target.'cfg(target_arch="x86_64")'.dependencies]
x86_64 = { workspace = true, features = ["instructions"] }
Expand All @@ -41,6 +42,7 @@ uart_16550 = { workspace = true }
[dev-dependencies]
criterion = { workspace = true }
mockall = { workspace = true }
utf16_lit = { workspace = true }

[features]
core = ['alloc']
Expand Down
1 change: 1 addition & 0 deletions sdk/patina_sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ pub mod serial;
pub mod test;
pub mod tpl_mutex;
pub mod uefi_protocol;
pub mod variable_policy;
Loading
Loading