guest_emulation_device/
resolver.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use 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}