#[doc(hidden)]
macro_rules! impl_const_id {
(
$(#[$outer:meta])*
$visibility:vis $trait:ident => $id_ty:ty;
$(
$iocty:ty = $val:expr
),* $(,)*
) => {
$(#[$outer])*
$visibility trait $trait {
$(#[$outer])*
const ID: $id_ty;
}
$(
impl $trait for $iocty {
const ID: $id_ty = $val;
}
)*
};
}
pub mod firmware;
pub mod launch;
use std::fmt::{Debug, Display, Formatter};
use std::{error, io};
#[derive(Debug)]
pub enum Indeterminate<T: Debug> {
Known(T),
Unknown,
}
impl<T: Debug + Display> Display for Indeterminate<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Indeterminate::Known(e) => {
write!(f, "{}", e)
}
Indeterminate::Unknown => {
write!(f, "Unknown Error",)
}
}
}
}
impl<T: Debug + Display> error::Error for Indeterminate<T> {}
#[derive(Debug)]
pub enum Error {
Io(io::Error),
InvalidPlatformState,
InvalidGuestState,
InvalidConfig,
InvalidLen,
AlreadyOwned,
InvalidCertificate,
PolicyFailure,
Inactive,
InvalidAddress,
BadSignature,
BadMeasurement,
AsidOwned,
InvalidAsid,
WbinvdRequired,
DfFlushRequired,
InvalidGuest,
InvalidCommand,
Active,
HardwarePlatform,
HardwareUnsafe,
Unsupported,
InvalidParam,
ResourceLimit,
SecureDataInvalid,
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let err_description = match self {
Error::Io(_) => "I/O Error",
Error::InvalidPlatformState => "Invalid platform state",
Error::InvalidGuestState => "Invalid guest state",
Error::InvalidConfig => "Platform configuration invalid",
Error::InvalidLen => "Memory buffer too small",
Error::AlreadyOwned => "Platform is already owned",
Error::InvalidCertificate => "Invalid certificate",
Error::PolicyFailure => "Policy failure",
Error::Inactive => "Guest is inactive",
Error::InvalidAddress => "Provided address is invalid",
Error::BadSignature => "Provided signature is invalid",
Error::BadMeasurement => "Provided measurement is invalid",
Error::AsidOwned => "ASID is already owned",
Error::InvalidAsid => "ASID is invalid",
Error::WbinvdRequired => "WBINVD instruction required",
Error::DfFlushRequired => "DF_FLUSH invocation required",
Error::InvalidGuest => "Guest handle is invalid",
Error::InvalidCommand => "Issued command is invalid",
Error::Active => "Guest is active",
Error::HardwarePlatform => {
"Hardware condition occured, safe to re-allocate parameter buffers"
}
Error::HardwareUnsafe => {
"Hardware condition occured, unsafe to re-allocate parameter buffers"
}
Error::Unsupported => "Feature is unsupported",
Error::InvalidParam => "Given parameter is invalid",
Error::ResourceLimit => {
"SEV firmware has run out of required resources to carry out command"
}
Error::SecureDataInvalid => "SEV platform observed a failed integrity check",
};
write!(f, "{}", err_description)
}
}
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
Error::Io(e) => Some(e),
_ => None,
}
}
}
impl From<io::Error> for Error {
#[inline]
fn from(error: io::Error) -> Error {
Error::Io(error)
}
}
impl From<io::Error> for Indeterminate<Error> {
#[inline]
fn from(error: io::Error) -> Indeterminate<Error> {
Indeterminate::Known(error.into())
}
}
impl From<Indeterminate<Error>> for io::Error {
#[inline]
fn from(indeterminate: Indeterminate<Error>) -> io::Error {
match indeterminate {
Indeterminate::Known(e) => io::Error::new(io::ErrorKind::Other, e),
Indeterminate::Unknown => io::Error::new(io::ErrorKind::Other, "unknown SEV error"),
}
}
}
impl From<u32> for Indeterminate<Error> {
#[inline]
fn from(error: u32) -> Indeterminate<Error> {
Indeterminate::Known(match error {
0 => io::Error::last_os_error().into(),
1 => Error::InvalidPlatformState,
2 => Error::InvalidGuestState,
3 => Error::InvalidConfig,
4 => Error::InvalidLen,
5 => Error::AlreadyOwned,
6 => Error::InvalidCertificate,
7 => Error::PolicyFailure,
8 => Error::Inactive,
9 => Error::InvalidAddress,
10 => Error::BadSignature,
11 => Error::BadMeasurement,
12 => Error::AsidOwned,
13 => Error::InvalidAsid,
14 => Error::WbinvdRequired,
15 => Error::DfFlushRequired,
16 => Error::InvalidGuest,
17 => Error::InvalidCommand,
18 => Error::Active,
19 => Error::HardwarePlatform,
20 => Error::HardwareUnsafe,
21 => Error::Unsupported,
22 => Error::InvalidParam,
23 => Error::ResourceLimit,
24 => Error::SecureDataInvalid,
_ => return Indeterminate::Unknown,
})
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct Version {
pub major: u8,
pub minor: u8,
}
impl std::fmt::Display for Version {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}.{}", self.major, self.minor)
}
}
#[cfg(test)]
mod tests {
struct A;
struct B;
struct C;
impl_const_id! {
Id => usize;
A = 1,
B = 2,
C = 3,
}
#[test]
fn test_const_id_macro() {
assert_eq!(A::ID, 1);
assert_eq!(B::ID, 2);
assert_eq!(C::ID, 3);
}
}