use super::types::*;
use crate::impl_const_id;
use crate::error::FirmwareError;
use std::marker::PhantomData;
use iocuddle::*;
#[cfg(all(feature = "sev", feature = "snp"))]
impl_const_id! {
pub Id => u32;
PlatformReset = 0x0,
PlatformStatus = 0x1,
PekGen = 0x2,
PekCsr<'_> = 0x3,
PdhGen = 0x4,
PdhCertExport<'_> = 0x5,
PekCertImport<'_> = 0x6,
GetId<'_> = 0x8,
SnpPlatformStatus = 0x9,
SnpCommit = 0xA,
SnpSetConfig = 0xB,
SnpVlekLoad = 0xC,
}
#[cfg(all(feature = "sev", not(feature = "snp")))]
impl_const_id! {
pub Id => u32;
PlatformReset = 0x0,
PlatformStatus = 0x1,
PekGen = 0x2,
PekCsr<'_> = 0x3,
PdhGen = 0x4,
PdhCertExport<'_> = 0x5,
PekCertImport<'_> = 0x6,
GetId<'_> = 0x8,
}
#[cfg(all(not(feature = "sev"), feature = "snp"))]
impl_const_id! {
pub Id => u32;
GetId<'_> = 0x8,
SnpPlatformStatus = 0x9,
SnpCommit = 0xA,
SnpSetConfig = 0xB,
SnpVlekLoad = 0xC,
}
const SEV: Group = Group::new(b'S');
#[cfg(feature = "sev")]
pub const PLATFORM_RESET: Ioctl<WriteRead, &Command<PlatformReset>> = unsafe { SEV.write_read(0) };
#[cfg(feature = "sev")]
pub const PLATFORM_STATUS: Ioctl<WriteRead, &Command<PlatformStatus>> =
unsafe { SEV.write_read(0) };
#[cfg(feature = "sev")]
pub const PEK_GEN: Ioctl<WriteRead, &Command<PekGen>> = unsafe { SEV.write_read(0) };
#[cfg(feature = "sev")]
pub const PEK_CSR: Ioctl<WriteRead, &Command<PekCsr<'_>>> = unsafe { SEV.write_read(0) };
#[cfg(feature = "sev")]
pub const PDH_GEN: Ioctl<WriteRead, &Command<PdhGen>> = unsafe { SEV.write_read(0) };
#[cfg(feature = "sev")]
pub const PDH_CERT_EXPORT: Ioctl<WriteRead, &Command<PdhCertExport<'_>>> =
unsafe { SEV.write_read(0) };
#[cfg(feature = "sev")]
pub const PEK_CERT_IMPORT: Ioctl<WriteRead, &Command<PekCertImport<'_>>> =
unsafe { SEV.write_read(0) };
#[cfg(any(feature = "sev", feature = "snp"))]
pub const GET_ID: Ioctl<WriteRead, &Command<GetId<'_>>> = unsafe { SEV.write_read(0) };
#[cfg(feature = "snp")]
pub const SNP_PLATFORM_STATUS: Ioctl<WriteRead, &Command<SnpPlatformStatus>> =
unsafe { SEV.write_read(0) };
#[cfg(feature = "snp")]
pub const SNP_COMMIT: Ioctl<WriteRead, &Command<SnpCommit>> = unsafe { SEV.write_read(0) };
#[cfg(feature = "snp")]
pub const SNP_SET_CONFIG: Ioctl<WriteRead, &Command<SnpSetConfig>> = unsafe { SEV.write_read(0) };
#[cfg(feature = "snp")]
pub const SNP_VLEK_LOAD: Ioctl<WriteRead, &Command<SnpVlekLoad>> = unsafe { SEV.write_read(0) };
#[repr(C, packed)]
pub struct Command<'a, T: Id> {
pub code: u32,
pub data: u64,
pub error: u32,
_phantom: PhantomData<&'a T>,
}
impl<'a, T: Id> Command<'a, T> {
pub fn from_mut(subcmd: &'a mut T) -> Self {
Command {
code: T::ID,
data: subcmd as *mut T as u64,
error: 0,
_phantom: PhantomData,
}
}
#[cfg(feature = "sev")]
pub fn from(subcmd: &'a T) -> Self {
Command {
code: T::ID,
data: subcmd as *const T as u64,
error: 0,
_phantom: PhantomData,
}
}
pub fn encapsulate(&self) -> FirmwareError {
FirmwareError::from(self.error)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_command_get_id() {
let mut id = [0u8; 64];
let mut data = GetId::new(&mut id);
let cmd = Command::<GetId>::from_mut(&mut data);
let code = cmd.code;
let error = cmd.error;
assert_eq!(code, GetId::ID);
assert_eq!(error, 0);
}
#[cfg(feature = "sev")]
mod sev_specific_tests {
use super::super::*;
#[test]
fn test_command_platform_status() {
let mut data = PlatformStatus::default();
let cmd = Command::<PlatformStatus>::from_mut(&mut data);
let code = cmd.code;
let error = cmd.error;
assert_eq!(code, PlatformStatus::ID);
assert_eq!(error, 0);
}
#[test]
fn test_command_platform_status_non_mut() {
let data = PlatformStatus::default();
let cmd = Command::<PlatformStatus>::from(&data);
let code = cmd.code;
let error = cmd.error;
assert_eq!(code, PlatformStatus::ID);
assert_eq!(error, 0);
}
#[test]
fn test_command_error_encapsulation() {
let cmd = Command::<PlatformStatus> {
code: PlatformStatus::ID,
error: 0,
data: 0,
_phantom: PhantomData,
};
let error = cmd.encapsulate();
assert!(matches!(error, FirmwareError::IoError(_)));
}
}
}