use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
use crate::consts;
use crate::firmware::ovmf::x86_64::{GUID_SIZE, parse_data};
use crate::firmware::{Result, error};
pub const GUID_SEV_ES_RESET_BLOCK: [u8; GUID_SIZE] = [
0xde, 0x71, 0xf7, 0x00, 0x7e, 0x1a, 0xcb, 0x4f, 0x89, 0x0e, 0x68, 0xc7, 0x7e, 0x2f, 0xb4, 0x4e,
];
pub const GUID_SEV_METADATA: [u8; GUID_SIZE] = [
0x66, 0x65, 0x88, 0xdc, 0x4a, 0x98, 0x98, 0x47, 0xA7, 0x5e, 0x55, 0x85, 0xa7, 0xbf, 0x67, 0xcc,
];
pub const SEV_SIGNATURE: u32 = u32::from_le_bytes(*b"ASEV");
#[derive(Debug, KnownLayout, Immutable, FromBytes, IntoBytes)]
#[repr(C)]
pub struct SevMetaData {
pub signature: u32,
pub len: u32,
pub version: u32,
pub num_desc: u32,
}
consts! {
#[derive(KnownLayout, Immutable, FromBytes, IntoBytes)]
pub struct SevDescType(u32) {
SNP_DESC_MEM = 1;
SNP_SECRETS = 2;
CPUID = 3;
}
}
#[derive(Debug, KnownLayout, Immutable, FromBytes, IntoBytes)]
#[repr(C)]
pub struct SevMetadataDesc {
pub base: u32,
pub len: u32,
pub type_: SevDescType,
}
#[repr(C)]
#[derive(Debug, Clone, PartialEq, Eq, KnownLayout, Immutable, FromBytes, IntoBytes)]
pub struct SnpCpuidFunc {
pub eax_in: u32,
pub ecx_in: u32,
pub xcr0_in: u64,
pub xss_in: u64,
pub eax: u32,
pub ebx: u32,
pub ecx: u32,
pub edx: u32,
pub reserved: u64,
}
#[repr(C)]
#[derive(Debug, Clone, KnownLayout, Immutable, FromBytes, IntoBytes)]
pub struct SnpCpuidInfo {
pub count: u32,
pub _reserved1: u32,
pub _reserved2: u64,
pub entries: [SnpCpuidFunc; 64],
}
pub fn parse_sev_ap_eip(data: &[u8]) -> Result<u32> {
let Some(ap_eip) = parse_data(data, &GUID_SEV_ES_RESET_BLOCK) else {
return error::MissingMetadata {
name: "SevEsResetBlock",
}
.fail();
};
let Ok(ap_eip) = u32::read_from_bytes(ap_eip) else {
return error::InvalidLayout.fail();
};
Ok(ap_eip)
}
pub fn parse_desc(data: &[u8]) -> Result<&[SevMetadataDesc]> {
let Some(offset_r) = parse_data(data, &GUID_SEV_METADATA) else {
return error::MissingMetadata {
name: "SevMetadata",
}
.fail();
};
let Ok(offset_r) = u32::read_from_bytes(offset_r) else {
return error::InvalidLayout.fail();
};
let offset = data.len() - offset_r as usize;
let Ok((metadata, remain)) = SevMetaData::ref_from_prefix(&data[offset..]) else {
return error::InvalidLayout.fail();
};
if metadata.signature != SEV_SIGNATURE {
return error::MissingAmdSevSignature {
got: metadata.signature,
}
.fail();
};
let Ok((entries, _)) =
<[SevMetadataDesc]>::ref_from_prefix_with_elems(remain, metadata.num_desc as usize)
else {
return error::InvalidLayout.fail();
};
Ok(entries)
}