guest_emulation_transport/
api.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Friendly Rust representations of the data sent over the GET.
5
6// These types are re-exported as-is, in order to avoid requiring consumers of
7// the GET and GED to also import get_protocol.
8pub use get_protocol::CreateRamGpaRangeFlags;
9pub use get_protocol::EventLogId;
10pub use get_protocol::GSP_CIPHERTEXT_MAX;
11pub use get_protocol::GspCiphertextContent;
12pub use get_protocol::GspCleartextContent;
13pub use get_protocol::GspExtendedStatusFlags;
14pub use get_protocol::IGVM_ATTEST_MSG_REQ_AGENT_DATA_MAX_SIZE;
15pub use get_protocol::MAX_TRANSFER_SIZE;
16pub use get_protocol::NUMBER_GSP;
17pub use get_protocol::ProtocolVersion;
18pub use get_protocol::SaveGuestVtl2StateFlags;
19pub use get_protocol::VmgsIoStatus;
20
21use guid::Guid;
22use mesh::MeshPayload;
23use std::time::Duration;
24use zerocopy::FromZeros;
25
26/// Device platform settings.
27#[expect(missing_docs)]
28pub mod platform_settings {
29    pub use get_protocol::dps_json::PcatBootDevice;
30
31    use get_protocol::dps_json::EfiDiagnosticsLogLevelType;
32    use get_protocol::dps_json::GuestStateEncryptionPolicy;
33    use get_protocol::dps_json::GuestStateLifetime;
34    use get_protocol::dps_json::ManagementVtlFeatures;
35    use guid::Guid;
36    use inspect::Inspect;
37
38    /// All available device platform settings.
39    #[derive(Debug, Inspect)]
40    pub struct DevicePlatformSettings {
41        pub smbios: Smbios,
42        pub general: General,
43        #[inspect(with = "inspect::iter_by_index")]
44        pub acpi_tables: Vec<Vec<u8>>,
45    }
46
47    /// All available SMBIOS related config.
48    #[derive(Debug, Inspect)]
49    pub struct Smbios {
50        pub serial_number: Vec<u8>,
51        pub base_board_serial_number: Vec<u8>,
52        pub chassis_serial_number: Vec<u8>,
53        pub chassis_asset_tag: Vec<u8>,
54
55        pub system_manufacturer: Vec<u8>,
56        pub system_product_name: Vec<u8>,
57        pub system_version: Vec<u8>,
58        pub system_sku_number: Vec<u8>,
59        pub system_family: Vec<u8>,
60        pub bios_lock_string: Vec<u8>,
61        pub memory_device_serial_number: Vec<u8>,
62
63        pub processor_manufacturer: Vec<u8>,
64        pub processor_version: Vec<u8>,
65        pub processor_id: u64,
66        pub external_clock: u16,
67        pub max_speed: u16,
68        pub current_speed: u16,
69        pub processor_characteristics: u16,
70        pub processor_family2: u16,
71        pub processor_type: u8,
72        pub voltage: u8,
73        pub status: u8,
74        pub processor_upgrade: u8,
75    }
76
77    /// All available general device platform configuration.
78    // DEVNOTE: "general" is code for "not well organized", so if you've got a
79    // better way to organize these settings, do consider cleaning this up a bit!
80    #[derive(Debug, Inspect)]
81    pub struct General {
82        pub secure_boot_enabled: bool,
83        pub secure_boot_template: SecureBootTemplateType,
84        pub bios_guid: Guid,
85        pub console_mode: UefiConsoleMode,
86        pub battery_enabled: bool,
87        pub processor_idle_enabled: bool,
88        pub tpm_enabled: bool,
89
90        pub com1_enabled: bool,
91        pub com1_debugger_mode: bool,
92        pub com1_vmbus_redirector: bool,
93        pub com2_enabled: bool,
94        pub com2_debugger_mode: bool,
95        pub com2_vmbus_redirector: bool,
96
97        pub firmware_debugging_enabled: bool,
98        pub hibernation_enabled: bool,
99
100        pub suppress_attestation: Option<bool>,
101        pub generation_id: Option<[u8; 16]>,
102
103        pub legacy_memory_map: bool,
104        pub pause_after_boot_failure: bool,
105        pub pxe_ip_v6: bool,
106        pub measure_additional_pcrs: bool,
107        pub disable_frontpage: bool,
108        pub disable_sha384_pcr: bool,
109        pub media_present_enabled_by_default: bool,
110        pub vpci_boot_enabled: bool,
111        pub memory_protection_mode: MemoryProtectionMode,
112        pub default_boot_always_attempt: bool,
113        pub num_lock_enabled: bool,
114        #[inspect(with = "|x| inspect::iter_by_index(x).map_value(inspect::AsDebug)")]
115        pub pcat_boot_device_order: [PcatBootDevice; 4],
116
117        pub vpci_instance_filter: Option<Guid>,
118        pub nvdimm_count: u16,
119        pub psp_enabled: bool,
120
121        pub vmbus_redirection_enabled: bool,
122        pub always_relay_host_mmio: bool,
123        pub vtl2_settings: Option<underhill_config::Vtl2Settings>,
124
125        pub is_servicing_scenario: bool,
126        pub watchdog_enabled: bool,
127        pub firmware_mode_is_pcat: bool,
128        pub imc_enabled: bool,
129        pub cxl_memory_enabled: bool,
130        #[inspect(debug)]
131        pub efi_diagnostics_log_level: EfiDiagnosticsLogLevelType,
132        #[inspect(debug)]
133        pub guest_state_lifetime: GuestStateLifetime,
134        #[inspect(debug)]
135        pub guest_state_encryption_policy: GuestStateEncryptionPolicy,
136        #[inspect(debug)]
137        pub management_vtl_features: ManagementVtlFeatures,
138        pub hv_sint_enabled: bool,
139    }
140
141    #[derive(Copy, Clone, Debug, Inspect)]
142    pub enum MemoryProtectionMode {
143        Disabled = 0,
144        Default = 1,
145        Strict = 2,
146        Relaxed = 3,
147    }
148
149    #[derive(Debug, Inspect)]
150    pub enum UefiConsoleMode {
151        /// video+kbd (having a head)
152        Default = 0,
153        /// headless with COM1 serial console
154        COM1 = 1,
155        /// headless with COM2 serial console
156        COM2 = 2,
157        /// headless
158        None = 3,
159    }
160
161    #[derive(Debug, Inspect)]
162    pub enum SecureBootTemplateType {
163        /// No template to apply.
164        None,
165        /// Apply the Windows only CA.
166        MicrosoftWindows,
167        /// Apply the Microsoft UEFI CA.
168        MicrosoftUefiCertificateAuthority,
169    }
170}
171
172/// Response fields for Guest State Protection sent from the host
173pub struct GuestStateProtection {
174    /// Guest State Protection ciphertext content
175    pub encrypted_gsp: GspCiphertextContent,
176    /// Guest State Protection cleartext content
177    pub decrypted_gsp: [GspCleartextContent; NUMBER_GSP as usize],
178    /// Extended status flags
179    pub extended_status_flags: GspExtendedStatusFlags,
180    /// Randomized new_gsp sent in the GuestStateProtectionRequest message to
181    /// the host
182    pub new_gsp: GspCleartextContent,
183}
184
185/// Response fields for Guest State Protection by ID from the host
186#[derive(Copy, Clone)]
187pub struct GuestStateProtectionById {
188    /// Guest State Protection cleartext content
189    pub seed: GspCleartextContent,
190    /// Extended status flags
191    pub extended_status_flags: GspExtendedStatusFlags,
192}
193
194impl GuestStateProtectionById {
195    /// Construct a blank instance of `GuestStateProtectionById`
196    pub fn new_zeroed() -> GuestStateProtectionById {
197        GuestStateProtectionById {
198            seed: GspCleartextContent::new_zeroed(),
199            extended_status_flags: GspExtendedStatusFlags::new_zeroed(),
200        }
201    }
202}
203
204/// Response for IGVM Attest from the host
205#[derive(Clone)]
206pub struct IgvmAttest {
207    /// Response data
208    pub response: Vec<u8>,
209}
210
211/// Response fields for VMGS Get Device Info from the host
212pub struct VmgsGetDeviceInfo {
213    /// Status of the request
214    pub status: VmgsIoStatus,
215    /// Logical sectors
216    pub capacity: u64,
217    /// Bytes per logical sector
218    pub bytes_per_logical_sector: u16,
219    /// Bytes per physical sector
220    pub bytes_per_physical_sector: u16,
221    /// Maximum transfer size bytes
222    pub maximum_transfer_size_bytes: u32,
223}
224
225/// Response fields from Time from the host
226#[derive(Debug, Copy, Clone)]
227pub struct Time {
228    /// UTC, in 100ns units since Jan 1 1601.
229    ///
230    /// (corresponds to `RtlGetSystemTime()` on the Host)
231    pub utc: i64,
232    /// Time zone (as minutes from UTC)
233    pub time_zone: i16,
234}
235
236impl Time {
237    /// Convert this time to a `jiff::Zoned`.
238    pub fn to_jiff(self) -> jiff::Zoned {
239        const NANOS_IN_SECOND: i64 = 1_000_000_000;
240        const NANOS_100_IN_SECOND: i64 = NANOS_IN_SECOND / 100;
241
242        let windows_epoch_unix_seconds = jiff::civil::date(1601, 1, 1)
243            .at(0, 0, 0, 0)
244            .to_zoned(jiff::tz::TimeZone::UTC)
245            .unwrap()
246            .timestamp();
247
248        let host_time_secs = self.utc / NANOS_100_IN_SECOND;
249        let host_time_nanos = (self.utc % NANOS_100_IN_SECOND) * 100;
250
251        let host_time_utc = jiff::Timestamp::new(
252            windows_epoch_unix_seconds.as_second() + host_time_secs,
253            host_time_nanos as i32,
254        )
255        .unwrap();
256
257        let offset_seconds = -self.time_zone as i32 * 60;
258        let tz = jiff::tz::TimeZone::fixed(jiff::tz::Offset::from_seconds(offset_seconds).unwrap());
259        host_time_utc.to_zoned(tz)
260    }
261}
262
263/// A handle returned by `CreateRamGpaRange`, which can be passed to
264/// `ResetRamGpaRange` in order to reset the associated range.
265#[derive(Debug)]
266pub struct RemoteRamGpaRangeHandle(u32);
267
268impl RemoteRamGpaRangeHandle {
269    /// Return a raw u32 that represents this handle
270    pub fn as_raw(&self) -> u32 {
271        self.0
272    }
273
274    /// Create a new [`RemoteRamGpaRangeHandle`] from a raw u32 previously
275    /// returned from `into_raw`.
276    pub fn from_raw(handle: u32) -> Self {
277        RemoteRamGpaRangeHandle(handle)
278    }
279}
280
281/// Request to save Guest state during servicing.
282#[derive(MeshPayload)]
283pub struct GuestSaveRequest {
284    /// GUID associated with the request.
285    pub correlation_id: Guid,
286    /// When to complete the request.
287    pub timeout_hint: Duration,
288    /// Flags bitfield.
289    #[mesh(encoding = "mesh::payload::encoding::ZeroCopyEncoding")]
290    pub capabilities_flags: SaveGuestVtl2StateFlags,
291}