Skip to main content

get_resources/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Resource definitions for the GET family of devices.
5
6#![forbid(unsafe_code)]
7
8/// Guest Emulation Log device resources.
9pub mod gel {
10    use mesh::MeshPayload;
11    use vm_resource::ResourceId;
12    use vm_resource::kind::VmbusDeviceHandleKind;
13
14    /// Handle to a guest emulation log device.
15    #[derive(MeshPayload)]
16    pub struct GuestEmulationLogHandle;
17
18    impl ResourceId<VmbusDeviceHandleKind> for GuestEmulationLogHandle {
19        const ID: &'static str = "gel";
20    }
21}
22
23/// Guest crash device resources.
24pub mod crash {
25    use mesh::MeshPayload;
26    use mesh::rpc::FailableRpc;
27    use std::fs::File;
28    use vm_resource::ResourceId;
29    use vm_resource::kind::VmbusDeviceHandleKind;
30
31    /// Handle to a guest crash dump device.
32    #[derive(MeshPayload)]
33    pub struct GuestCrashDeviceHandle {
34        /// A channel the device can use to get a file to write a dump to.
35        pub request_dump: mesh::Sender<FailableRpc<mesh::OneshotReceiver<()>, File>>,
36        /// The maximum size of the dump that the device will write.
37        pub max_dump_size: u64,
38    }
39
40    impl ResourceId<VmbusDeviceHandleKind> for GuestCrashDeviceHandle {
41        const ID: &'static str = "guest_crash_device";
42    }
43}
44
45/// Guest Emulation Device resources.
46pub mod ged {
47    use inspect::Inspect;
48    use mesh::MeshPayload;
49    use mesh::error::RemoteError;
50    use mesh::payload::Protobuf;
51    use mesh::rpc::Rpc;
52    use thiserror::Error;
53    use vm_resource::Resource;
54    use vm_resource::ResourceId;
55    use vm_resource::kind::FramebufferHandleKind;
56    use vm_resource::kind::VmbusDeviceHandleKind;
57    use vmgs_resources::VmgsResource;
58
59    /// A resource handle for a guest emulation device.
60    #[derive(MeshPayload)]
61    pub struct GuestEmulationDeviceHandle {
62        /// The firmware configuration for the guest.
63        pub firmware: GuestFirmwareConfig,
64        /// Enable COM1 for VTL0 and the VMBUS redirector in VTL2.
65        pub com1: bool,
66        /// Enable COM2 for VTL0 and the VMBUS redirector in VTL2.
67        pub com2: bool,
68        /// Only allow guest to host serial traffic
69        pub serial_tx_only: bool,
70        /// Enable vmbus redirection.
71        pub vmbus_redirection: bool,
72        /// The TPM reference implementation version to expose to the guest.
73        pub tpm_version: Option<GedTpmVersion>,
74        /// Encoded VTL2 settings.
75        pub vtl2_settings: Option<Vec<u8>>,
76        /// The disk to back the GET's VMGS interface.
77        pub vmgs: VmgsResource,
78        /// Framebuffer device control.
79        pub framebuffer: Option<Resource<FramebufferHandleKind>>,
80        /// Access to VTL2 functionality.
81        pub guest_request_recv: mesh::Receiver<GuestEmulationRequest>,
82        /// Notification of firmware events.
83        pub firmware_event_send: Option<mesh::Sender<FirmwareEvent>>,
84        /// Optional Petri observer for IPMI SEL notifications already received over GET.
85        pub ipmi_sel_event_send: Option<mesh::Sender<IpmiSelEvent>>,
86        /// Enable secure boot.
87        pub secure_boot_enabled: bool,
88        /// The secure boot template type.
89        pub secure_boot_template: GuestSecureBootTemplateType,
90        /// Enable battery.
91        pub enable_battery: bool,
92        /// Enable the IPMI KCS interface.
93        pub enable_ipmi: bool,
94        /// Suppress attestation and disable TPM state persistence.
95        pub no_persistent_secrets: bool,
96        /// Test configuration for IGVM Attest message.
97        pub igvm_attest_test_config: Option<IgvmAttestTestConfig>,
98        /// Send the test seed for GspById requests
99        pub test_gsp_by_id: bool,
100        /// EFI diagnostics log level
101        pub efi_diagnostics_log_level: EfiDiagnosticsLogLevelType,
102        /// Force UEFI to bounce-buffer all DMA traffic.
103        pub force_dma_bounce_enabled: bool,
104        /// Enable hibernation.
105        pub enable_hibernation: bool,
106        /// SMBIOS identity overrides delivered to the guest firmware.
107        pub smbios: smbios_defs::SmbiosConfig,
108    }
109
110    /// An IPMI SEL notification received from OpenHCL.
111    #[derive(Debug, Clone, Copy, MeshPayload, PartialEq, Eq)]
112    pub struct IpmiSelEvent {
113        /// BMC-assigned SEL record identifier.
114        pub record_id: u16,
115        /// Completed SEL record.
116        pub record: ipmi_protocol::SelRecord,
117    }
118
119    /// The firmware and chipset configuration for the guest.
120    #[derive(MeshPayload)]
121    pub enum GuestFirmwareConfig {
122        /// Boot from UEFI with Hyper-V generation 2 devices.
123        Uefi {
124            /// Tell UEFI to consider booting from VPCI.
125            enable_vpci_boot: bool,
126            /// Enable UEFI firmware debugging for VTL0.
127            firmware_debug: bool,
128            /// Enable UEFI memory protections for VTL0.
129            enable_memory_protections: bool,
130            /// Disable the UEFI frontpage which will cause the VM to shutdown instead when unable to boot.
131            disable_frontpage: bool,
132            /// Where to send UEFI console output
133            console_mode: UefiConsoleMode,
134            /// Perform a default boot even if boot entries exist and fail
135            default_boot_always_attempt: bool,
136        },
137        /// Boot from PC/AT BIOS with Hyper-V generation 1 devices.
138        Pcat {
139            /// The boot order for the PC/AT firmware.
140            boot_order: [PcatBootDevice; 4],
141        },
142    }
143
144    /// UEFI Console Mode
145    #[derive(MeshPayload, Clone, Debug, Copy)]
146    pub enum UefiConsoleMode {
147        /// video+kbd (having a head)
148        Default = 0,
149        /// headless with COM1 serial console
150        COM1 = 1,
151        /// headless with COM2 serial console
152        COM2 = 2,
153        /// headless
154        None = 3,
155    }
156
157    /// The guest's secure boot template type to use.
158    #[derive(MeshPayload, Clone, Debug, Copy)]
159    pub enum GuestSecureBootTemplateType {
160        /// No template specified.
161        None,
162        /// The microsoft windows template.
163        MicrosoftWindows,
164        /// The Microsoft UEFI certificate authority template.
165        MicrosoftUefiCertificateAuthority,
166    }
167
168    /// The guest's EFI diagnostics log level type to use.
169    #[derive(MeshPayload, Clone, Debug, Copy, Default)]
170    pub enum EfiDiagnosticsLogLevelType {
171        /// Default log level
172        #[default]
173        Default,
174        /// Include INFO logs
175        Info,
176        /// All logs
177        Full,
178    }
179
180    /// The TPM reference implementation version to expose to the guest.
181    #[derive(MeshPayload, Clone, Debug, Copy, PartialEq)]
182    pub enum GedTpmVersion {
183        /// TPM reference implementation version 1.38
184        V138,
185        /// TPM reference implementation version 1.85
186        V185,
187    }
188
189    /// The boot devices for a PC/AT BIOS.
190    #[derive(MeshPayload, Debug, Clone, Copy, PartialEq)]
191    pub enum PcatBootDevice {
192        /// Boot from a floppy disk.
193        Floppy,
194        /// Boot from a hard drive.
195        HardDrive,
196        /// Boot from an optical drive.
197        Optical,
198        /// Boot from the network.
199        Network,
200    }
201
202    impl ResourceId<VmbusDeviceHandleKind> for GuestEmulationDeviceHandle {
203        const ID: &'static str = "ged";
204    }
205
206    /// Define servicing behavior.
207    #[derive(MeshPayload, Default)]
208    pub struct GuestServicingFlags {
209        /// Retain memory for NVMe devices.
210        pub nvme_keepalive: bool,
211        /// Retain memory for MANA devices.
212        pub mana_keepalive: bool,
213    }
214
215    /// Actions a client can request that the Guest Emulation
216    /// Device perform.
217    #[derive(MeshPayload)]
218    pub enum GuestEmulationRequest {
219        /// Wait for VTL2 to connect to the GET.
220        WaitForConnect(Rpc<(), ()>),
221        /// Wait for VTL2 to start VTL0.
222        WaitForVtl0Start(Rpc<(), Result<(), Vtl0StartError>>),
223        /// Save VTL2 state.
224        SaveGuestVtl2State(Rpc<GuestServicingFlags, Result<(), SaveRestoreError>>),
225        /// Update the VTL2 settings.
226        ModifyVtl2Settings(Rpc<Vec<u8>, Result<(), ModifyVtl2SettingsError>>),
227    }
228
229    /// An error waiting to start VTL0.
230    #[derive(Debug, Error, Clone, MeshPayload)]
231    #[error("guest reported VTL0 start error: {0}")]
232    pub struct Vtl0StartError(pub String);
233
234    /// The various errors that can occur during a save or restore
235    /// operation for guest VTL2 state.
236    #[derive(Debug, Error, MeshPayload)]
237    #[expect(missing_docs)]
238    pub enum SaveRestoreError {
239        #[error("an operation is in progress")]
240        OperationInProgress,
241        #[error("vmbus io error")]
242        Io(#[source] RemoteError),
243        #[error("guest error")]
244        GuestError,
245    }
246
247    /// An error that can occur during a VTL2 settings update.
248    #[derive(Debug, Error, MeshPayload)]
249    #[expect(missing_docs)]
250    pub enum ModifyVtl2SettingsError {
251        #[error("large settings not supported")]
252        LargeSettingsNotSupported,
253        #[error("an operation is already in progress")]
254        OperationInProgress,
255        #[error("guest error: {0}")]
256        Guest(String),
257    }
258
259    /// Firmware events generated by the guest.
260    ///
261    /// TODO: For now, these mainly represent UEFI events without the corresponding extra information. This should be
262    ///       rethought when OpenVMM supports Linux Direct, IGVM, and other types.
263    #[derive(Debug, Protobuf, PartialEq, Eq, Copy, Clone)]
264    pub enum FirmwareEvent {
265        /// Boot was successful.
266        BootSuccess,
267        /// Boot failed.
268        BootFailed,
269        /// No boot device could be found.
270        NoBootDevice,
271        /// A boot attempt was made.
272        BootAttempt,
273    }
274
275    /// Configuration for the GED's IGVM Attest request handler in test
276    /// scenarios.
277    ///
278    /// Non-extended variants (`AkCertRequestFailureAndRetry`,
279    /// `AkCertPersistentAcrossBoot`) are used by OpenVMM-hosted tests
280    /// that invoke the GED directly.  Extended variants and the
281    /// `KeyReleaseFailure*` variants are used by Hyper-V tests via
282    /// the `test_igvm_agent_rpc_server`, where the Hyper-V boot
283    /// sequence (including `initial_reboot`) generates extra IGVM
284    /// attest requests before the test code runs.
285    #[derive(Debug, MeshPayload, Copy, Clone, Inspect)]
286    pub enum IgvmAttestTestConfig {
287        /// Config for testing AK cert retry after failure.
288        ///
289        /// Plan: two failures then one success.  Used by OpenVMM-hosted
290        /// tests where no extra boot-time requests occur.
291        AkCertRequestFailureAndRetry,
292        /// Config for testing AK cert retry after failure — extended
293        /// plan for Hyper-V tests.
294        ///
295        /// Hyper-V VMs go through an `initial_reboot` and may generate
296        /// multiple background AK cert requests during the initial boot
297        /// and the reboot.  The extra failure actions absorb those
298        /// requests so the final success action is available when the
299        /// guest test code runs.
300        AkCertRequestFailureAndRetryExtended,
301        /// Config for testing AK cert persistency across boots.
302        ///
303        /// Plan: one success then always-no-response.  Used by
304        /// OpenVMM-hosted tests where no extra boot-time requests occur.
305        AkCertPersistentAcrossBoot,
306        /// Config for testing AK cert persistency across boots —
307        /// extended plan for Hyper-V tests.
308        ///
309        /// Hyper-V VMs go through an `initial_reboot` that can consume
310        /// the first success action before the test code runs.  The
311        /// extra `RespondSuccess` ensures the cert is still provisioned
312        /// after the reboot, so the subsequent boot can validate that
313        /// the cert is served from the persistent cache.
314        AkCertPersistentAcrossBootExtended,
315        /// Config for testing the `skip_hw_unsealing` signal from the
316        /// IGVM agent.
317        ///
318        /// When the agent responds with `skip_hw_unsealing`, the
319        /// attestation code skips the hardware unsealing step even if
320        /// the hardware key protector and derived keys are available.
321        /// This causes `initialize_platform_security` to fall through
322        /// to a scheme-specific error (KP / GSP / GspById), making
323        /// VMGS unlock fail.
324        KeyReleaseFailureSkipHwUnsealing,
325        /// Config for testing key release failure without the
326        /// `skip_hw_unsealing` signal.
327        ///
328        /// When the agent responds with a plain failure (no skip
329        /// signal), the attestation code falls back to hardware
330        /// unsealing using the hardware key protector saved on the
331        /// previous successful boot.  The VM should boot normally.
332        KeyReleaseFailure,
333        /// Config for testing a host/agent-requested TPM state refresh.
334        ///
335        /// The agent's GSP RPC reports `state_refresh_request`, which
336        /// drives `refresh_tpm_seeds` in OpenHCL and causes the vTPM
337        /// seeds (and therefore the AK) to be regenerated on the next
338        /// boot.  AK cert requests are served so the guest has a valid
339        /// AK to read across boots.
340        StateRefresh,
341    }
342}