use core::{mem, ptr, slice};
use r_efi::efi;
use crate::pi::protocols::status_code::{
self, EfiStatusCodeData, EfiStatusCodeType, EfiStatusCodeValue, ReportStatusCode,
};
use super::ProtocolInterface;
#[repr(transparent)]
pub struct StatusCodeRuntimeProtocol {
protocol: status_code::Protocol,
}
unsafe impl ProtocolInterface for StatusCodeRuntimeProtocol {
const PROTOCOL_GUID: crate::BinaryGuid = status_code::PROTOCOL_GUID;
}
impl StatusCodeRuntimeProtocol {
pub fn new(report_status_code: ReportStatusCode) -> Self {
Self { protocol: status_code::Protocol { report_status_code } }
}
pub fn report_status_code_with_data<T>(
&self,
status_code_type: EfiStatusCodeType,
status_code_value: EfiStatusCodeValue,
instance: u32,
caller_id: &efi::Guid,
data_type: efi::Guid,
data: T,
) -> Result<(), efi::Status>
where
T: Sized,
{
let header = EfiStatusCodeData {
header_size: mem::size_of::<EfiStatusCodeData>() as u16,
size: mem::size_of::<T>() as u16,
r#type: data_type,
};
let mut data_buffer = [any_as_u8_slice(&header), any_as_u8_slice(&data)].concat();
let data_ptr: *mut EfiStatusCodeData = data_buffer.as_mut_ptr() as *mut EfiStatusCodeData;
let status =
(self.protocol.report_status_code)(status_code_type, status_code_value, instance, caller_id, data_ptr);
if status.is_error() { Err(status) } else { Ok(()) }
}
pub fn report_status_code(
&self,
status_code_type: EfiStatusCodeType,
status_code_value: EfiStatusCodeValue,
instance: u32,
caller_id: &efi::Guid,
) -> Result<(), efi::Status> {
let status = (self.protocol.report_status_code)(
status_code_type,
status_code_value,
instance,
caller_id,
ptr::null_mut(),
);
if status.is_error() { Err(status) } else { Ok(()) }
}
}
fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
unsafe { slice::from_raw_parts((p as *const T) as *const u8, mem::size_of::<T>()) }
}