guest_emulation_device/
resolver.rs1use crate::GuestEmulationDevice;
5use async_trait::async_trait;
6use disk_backend::resolve::ResolveDiskParameters;
7use get_protocol::SecureBootTemplateType;
8use get_protocol::dps_json::GuestStateLifetime;
9use get_resources::ged::GuestEmulationDeviceHandle;
10use get_resources::ged::GuestFirmwareConfig;
11use get_resources::ged::GuestSecureBootTemplateType;
12use get_resources::ged::PcatBootDevice;
13use get_resources::ged::UefiConsoleMode;
14use power_resources::PowerRequestHandleKind;
15use thiserror::Error;
16use vm_resource::AsyncResolveResource;
17use vm_resource::IntoResource;
18use vm_resource::PlatformResource;
19use vm_resource::ResolveError;
20use vm_resource::ResourceResolver;
21use vm_resource::declare_static_async_resolver;
22use vm_resource::kind::VmbusDeviceHandleKind;
23use vmbus_channel::resources::ResolveVmbusDeviceHandleParams;
24use vmbus_channel::resources::ResolvedVmbusDevice;
25use vmbus_channel::simple::SimpleDeviceWrapper;
26use vmgs_resources::VmgsResource;
27
28pub struct GuestEmulationDeviceResolver;
29
30declare_static_async_resolver! {
31 GuestEmulationDeviceResolver,
32 (VmbusDeviceHandleKind, GuestEmulationDeviceHandle),
33}
34
35#[derive(Debug, Error)]
36pub enum Error {
37 #[error("failed to resolve framebuffer")]
38 Framebuffer(#[source] ResolveError),
39 #[error("failed to resolve power request")]
40 Power(#[source] ResolveError),
41 #[error("failed to resolve vmgs disk")]
42 Vmgs(#[source] ResolveError),
43}
44
45#[async_trait]
46impl AsyncResolveResource<VmbusDeviceHandleKind, GuestEmulationDeviceHandle>
47 for GuestEmulationDeviceResolver
48{
49 type Output = ResolvedVmbusDevice;
50 type Error = Error;
51
52 async fn resolve(
53 &self,
54 resolver: &ResourceResolver,
55 resource: GuestEmulationDeviceHandle,
56 input: ResolveVmbusDeviceHandleParams<'_>,
57 ) -> Result<Self::Output, Self::Error> {
58 let framebuffer_control = if let Some(framebuffer) = resource.framebuffer {
59 Some(
60 resolver
61 .resolve(framebuffer, ())
62 .await
63 .map_err(Error::Framebuffer)?
64 .0,
65 )
66 } else {
67 None
68 };
69
70 let halt = resolver
71 .resolve::<PowerRequestHandleKind, _>(PlatformResource.into_resource(), ())
72 .await
73 .map_err(Error::Power)?;
74
75 let (vmgs_disk, guest_state_lifetime) = match resource.vmgs {
76 VmgsResource::Disk(disk) => (Some(disk), GuestStateLifetime::Default),
77 VmgsResource::ReprovisionOnFailure(disk) => {
78 (Some(disk), GuestStateLifetime::ReprovisionOnFailure)
79 }
80 VmgsResource::Reprovision(disk) => (Some(disk), GuestStateLifetime::Reprovision),
81 VmgsResource::Ephemeral => (None, GuestStateLifetime::Ephemeral),
82 };
83
84 let vmgs_disk = if let Some(disk) = vmgs_disk {
85 Some(
86 resolver
87 .resolve(
88 disk,
89 ResolveDiskParameters {
90 read_only: false,
91 _async_trait_workaround: &(),
92 },
93 )
94 .await
95 .map_err(Error::Vmgs)?
96 .0,
97 )
98 } else {
99 None
100 };
101
102 let device = GuestEmulationDevice::new(
103 crate::GuestConfig {
104 firmware: match resource.firmware {
105 GuestFirmwareConfig::Uefi {
106 enable_vpci_boot,
107 firmware_debug,
108 disable_frontpage,
109 console_mode,
110 default_boot_always_attempt,
111 } => crate::GuestFirmwareConfig::Uefi {
112 enable_vpci_boot,
113 firmware_debug,
114 disable_frontpage,
115 console_mode: match console_mode {
116 UefiConsoleMode::Default => get_protocol::UefiConsoleMode::DEFAULT,
117 UefiConsoleMode::COM1 => get_protocol::UefiConsoleMode::COM1,
118 UefiConsoleMode::COM2 => get_protocol::UefiConsoleMode::COM2,
119 UefiConsoleMode::None => get_protocol::UefiConsoleMode::NONE,
120 },
121 default_boot_always_attempt,
122 },
123 GuestFirmwareConfig::Pcat { boot_order } => crate::GuestFirmwareConfig::Pcat {
124 boot_order: boot_order.map(|x| match x {
125 PcatBootDevice::Floppy => {
126 get_protocol::dps_json::PcatBootDevice::Floppy
127 }
128 PcatBootDevice::HardDrive => {
129 get_protocol::dps_json::PcatBootDevice::HardDrive
130 }
131 PcatBootDevice::Optical => {
132 get_protocol::dps_json::PcatBootDevice::Optical
133 }
134 PcatBootDevice::Network => {
135 get_protocol::dps_json::PcatBootDevice::Network
136 }
137 }),
138 },
139 },
140 com1: resource.com1,
141 com2: resource.com2,
142 vmbus_redirection: resource.vmbus_redirection,
143 enable_tpm: resource.enable_tpm,
144 vtl2_settings: resource.vtl2_settings,
145 secure_boot_enabled: resource.secure_boot_enabled,
146 secure_boot_template: match resource.secure_boot_template {
147 GuestSecureBootTemplateType::None => {
148 SecureBootTemplateType::SECURE_BOOT_DISABLED
149 }
150 GuestSecureBootTemplateType::MicrosoftWindows => {
151 SecureBootTemplateType::MICROSOFT_WINDOWS
152 }
153 GuestSecureBootTemplateType::MicrosoftUefiCertificateAuthoritiy => {
154 SecureBootTemplateType::MICROSOFT_UEFI_CERTIFICATE_AUTHORITY
155 }
156 },
157 enable_battery: resource.enable_battery,
158 no_persistent_secrets: resource.no_persistent_secrets,
159 guest_state_lifetime,
160 },
161 halt,
162 resource.firmware_event_send,
163 resource.guest_request_recv,
164 framebuffer_control,
165 vmgs_disk,
166 resource.igvm_attest_test_config,
167 );
168 Ok(SimpleDeviceWrapper::new(input.driver_source.simple(), device).into())
169 }
170}