Alioth Code Coverage

sev.rs0.00%

1// Copyright 2026 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
16
17use crate::consts;
18use crate::firmware::ovmf::x86_64::{GUID_SIZE, parse_data};
19use crate::firmware::{Result, error};
20
21pub const GUID_SEV_ES_RESET_BLOCK: [u8; GUID_SIZE] = [
22 0xde, 0x71, 0xf7, 0x00, 0x7e, 0x1a, 0xcb, 0x4f, 0x89, 0x0e, 0x68, 0xc7, 0x7e, 0x2f, 0xb4, 0x4e,
23];
24
25pub const GUID_SEV_METADATA: [u8; GUID_SIZE] = [
26 0x66, 0x65, 0x88, 0xdc, 0x4a, 0x98, 0x98, 0x47, 0xA7, 0x5e, 0x55, 0x85, 0xa7, 0xbf, 0x67, 0xcc,
27];
28pub const SEV_SIGNATURE: u32 = u32::from_le_bytes(*b"ASEV");
29
30#[derive(Debug, KnownLayout, Immutable, FromBytes, IntoBytes)]
31#[repr(C)]
32pub struct SevMetaData {
33 pub signature: u32,
34 pub len: u32,
35 pub version: u32,
36 pub num_desc: u32,
37}
38
39consts! {
40 #[derive(KnownLayout, Immutable, FromBytes, IntoBytes)]
41 pub struct SevDescType(u32) {
42 SNP_DESC_MEM = 1;
43 SNP_SECRETS = 2;
44 CPUID = 3;
45 }
46}
47
48#[derive(Debug, KnownLayout, Immutable, FromBytes, IntoBytes)]
49#[repr(C)]
50pub struct SevMetadataDesc {
51 pub base: u32,
52 pub len: u32,
53 pub type_: SevDescType,
54}
55
56#[repr(C)]
57#[derive(Debug, Clone, PartialEq, Eq, KnownLayout, Immutable, FromBytes, IntoBytes)]
58pub struct SnpCpuidFunc {
59 pub eax_in: u32,
60 pub ecx_in: u32,
61 pub xcr0_in: u64,
62 pub xss_in: u64,
63 pub eax: u32,
64 pub ebx: u32,
65 pub ecx: u32,
66 pub edx: u32,
67 pub reserved: u64,
68}
69
70#[repr(C)]
71#[derive(Debug, Clone, KnownLayout, Immutable, FromBytes, IntoBytes)]
72pub struct SnpCpuidInfo {
73 pub count: u32,
74 pub _reserved1: u32,
75 pub _reserved2: u64,
76 pub entries: [SnpCpuidFunc; 64],
77}
78
79pub fn parse_sev_ap_eip(data: &[u8]) -> Result<u32> {
80 let Some(ap_eip) = parse_data(data, &GUID_SEV_ES_RESET_BLOCK) else {
81 return error::MissingMetadata {
82 name: "SevEsResetBlock",
83 }
84 .fail();
85 };
86 let Ok(ap_eip) = u32::read_from_bytes(ap_eip) else {
87 return error::InvalidLayout.fail();
88 };
89 Ok(ap_eip)
90}
91
92pub fn parse_desc(data: &[u8]) -> Result<&[SevMetadataDesc]> {
93 let Some(offset_r) = parse_data(data, &GUID_SEV_METADATA) else {
94 return error::MissingMetadata {
95 name: "SevMetadata",
96 }
97 .fail();
98 };
99 let Ok(offset_r) = u32::read_from_bytes(offset_r) else {
100 return error::InvalidLayout.fail();
101 };
102 let offset = data.len() - offset_r as usize;
103 let Ok((metadata, remain)) = SevMetaData::ref_from_prefix(&data[offset..]) else {
104 return error::InvalidLayout.fail();
105 };
106 if metadata.signature != SEV_SIGNATURE {
107 return error::MissingAmdSevSignature {
108 got: metadata.signature,
109 }
110 .fail();
111 };
112 let Ok((entries, _)) =
113 <[SevMetadataDesc]>::ref_from_prefix_with_elems(remain, metadata.num_desc as usize)
114 else {
115 return error::InvalidLayout.fail();
116 };
117 Ok(entries)
118}
119