use crate::{error::FirmwareError, impl_const_id};
#[cfg(feature = "sev")]
use crate::launch::linux::sev;
#[cfg(feature = "snp")]
use crate::launch::linux::snp;
#[cfg(any(feature = "sev", feature = "snp"))]
use crate::launch::linux::shared;
use std::{
marker::PhantomData,
os::{raw::c_ulong, unix::io::AsRawFd},
};
use iocuddle::*;
#[cfg(all(feature = "sev", feature = "snp"))]
impl_const_id! {
pub Id => u32;
sev::Init = 0,
sev::EsInit = 1,
sev::LaunchStart<'_> = 2,
sev::LaunchUpdateData<'_> = 3,
sev::LaunchUpdateVmsa = 4,
sev::LaunchSecret<'_> = 5,
sev::LaunchMeasure<'_> = 6,
sev::LaunchFinish = 7,
sev::LaunchAttestation<'_> = 20,
shared::Init2 = 22,
snp::LaunchStart = 100,
snp::LaunchUpdate<'_> = 101,
snp::LaunchFinish<'_> = 102,
}
#[cfg(all(feature = "sev", not(feature = "snp")))]
impl_const_id! {
pub Id => u32;
sev::Init = 0,
sev::EsInit = 1,
sev::LaunchStart<'_> = 2,
sev::LaunchUpdateData<'_> = 3,
sev::LaunchUpdateVmsa = 4,
sev::LaunchSecret<'_> = 5,
sev::LaunchMeasure<'_> = 6,
sev::LaunchFinish = 7,
sev::LaunchAttestation<'_> = 20,
shared::Init2 = 22
}
#[cfg(all(not(feature = "sev"), feature = "snp"))]
impl_const_id! {
pub Id => u32;
shared::Init2 = 22,
snp::LaunchStart = 100,
snp::LaunchUpdate<'_> = 101,
snp::LaunchFinish<'_> = 102,
}
const KVM: Group = Group::new(0xAE);
const ENC_OP: Ioctl<WriteRead, &c_ulong> = unsafe { KVM.write_read(0xBA) };
#[cfg(feature = "snp")]
pub const KVM_MEMORY_ATTRIBUTE_PRIVATE: u64 = 1 << 3;
#[cfg(feature = "sev")]
#[deprecated(note = "Init2 should be used instead")]
pub const _INIT: Ioctl<WriteRead, &Command<sev::Init>> = unsafe { ENC_OP.lie() };
#[cfg(feature = "sev")]
#[deprecated(note = "Init2 should be used instead")]
pub const _ES_INIT: Ioctl<WriteRead, &Command<sev::EsInit>> = unsafe { ENC_OP.lie() };
#[cfg(feature = "sev")]
pub const LAUNCH_START: Ioctl<WriteRead, &Command<sev::LaunchStart>> = unsafe { ENC_OP.lie() };
#[cfg(feature = "sev")]
pub const LAUNCH_UPDATE_DATA: Ioctl<WriteRead, &Command<sev::LaunchUpdateData>> =
unsafe { ENC_OP.lie() };
#[cfg(feature = "sev")]
pub const LAUNCH_UPDATE_VMSA: Ioctl<WriteRead, &Command<sev::LaunchUpdateVmsa>> =
unsafe { ENC_OP.lie() };
#[cfg(feature = "sev")]
pub const LAUNCH_SECRET: Ioctl<WriteRead, &Command<sev::LaunchSecret>> = unsafe { ENC_OP.lie() };
#[cfg(feature = "sev")]
pub const LAUNCH_MEASUREMENT: Ioctl<WriteRead, &Command<sev::LaunchMeasure>> =
unsafe { ENC_OP.lie() };
#[cfg(feature = "sev")]
pub const LAUNCH_FINISH: Ioctl<WriteRead, &Command<sev::LaunchFinish>> = unsafe { ENC_OP.lie() };
#[cfg(feature = "sev")]
pub const LAUNCH_ATTESTATION: Ioctl<WriteRead, &Command<sev::LaunchAttestation>> =
unsafe { ENC_OP.lie() };
#[cfg(any(feature = "sev", feature = "snp"))]
pub const ENC_REG_REGION: Ioctl<Write, &KvmEncRegion> =
unsafe { KVM.read::<KvmEncRegion>(0xBB).lie() };
#[cfg(feature = "snp")]
pub const SET_MEMORY_ATTRIBUTES: Ioctl<Write, &KvmSetMemoryAttributes> =
unsafe { KVM.write::<KvmSetMemoryAttributes>(0xd2) };
#[cfg(any(feature = "sev", feature = "snp"))]
pub const INIT2: Ioctl<WriteRead, &Command<shared::Init2>> = unsafe { ENC_OP.lie() };
#[cfg(feature = "snp")]
pub const SNP_LAUNCH_START: Ioctl<WriteRead, &Command<snp::LaunchStart>> = unsafe { ENC_OP.lie() };
#[cfg(feature = "snp")]
pub const SNP_LAUNCH_UPDATE: Ioctl<WriteRead, &Command<snp::LaunchUpdate>> =
unsafe { ENC_OP.lie() };
#[cfg(feature = "snp")]
pub const SNP_LAUNCH_FINISH: Ioctl<WriteRead, &Command<snp::LaunchFinish>> =
unsafe { ENC_OP.lie() };
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
pub struct KvmEncRegion<'a> {
addr: u64,
size: u64,
phantom: PhantomData<&'a [u8]>,
}
impl<'a> KvmEncRegion<'a> {
pub fn new(data: &'a [u8]) -> Self {
Self {
addr: data.as_ptr() as _,
size: data.len() as _,
phantom: PhantomData,
}
}
pub fn register(&mut self, vm_fd: &mut impl AsRawFd) -> std::io::Result<std::os::raw::c_uint> {
ENC_REG_REGION.ioctl(vm_fd, self)
}
}
#[cfg(feature = "snp")]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
pub struct KvmSetMemoryAttributes {
addr: u64,
size: u64,
attributes: u64,
flags: u64,
}
#[cfg(feature = "snp")]
impl KvmSetMemoryAttributes {
pub fn new(data: u64, len: u64, attributes: u64) -> Self {
Self {
addr: data,
size: len,
attributes,
flags: 0,
}
}
#[cfg(feature = "snp")]
pub fn set_attributes(
&mut self,
vm_fd: &mut impl AsRawFd,
) -> std::io::Result<std::os::raw::c_uint> {
SET_MEMORY_ATTRIBUTES.ioctl(vm_fd, self)
}
}
#[repr(C)]
pub struct Command<'a, T: Id> {
code: u32,
data: u64,
error: u32,
sev_fd: u32,
_phantom: PhantomData<&'a T>,
}
impl<'a, T: Id> Command<'a, T> {
#[cfg(feature = "sev")]
pub fn from_mut(sev: &'a impl AsRawFd, subcmd: &'a mut T) -> Self {
Self {
code: T::ID,
data: subcmd as *mut T as _,
error: 0,
sev_fd: sev.as_raw_fd() as _,
_phantom: PhantomData,
}
}
pub fn from(sev: &'a impl AsRawFd, subcmd: &'a T) -> Self {
Self {
code: T::ID,
data: subcmd as *const T as _,
error: 0,
sev_fd: sev.as_raw_fd() as _,
_phantom: PhantomData,
}
}
pub fn encapsulate(&self) -> FirmwareError {
FirmwareError::from(self.error)
}
}