firmware_uefi/
resolver.rs1use crate::UefiDevice;
7use crate::UefiRuntimeDeps;
8use async_trait::async_trait;
9use chipset_device_resources::GPE0_LINE_SET;
10use chipset_device_resources::IRQ_LINE_SET;
11use chipset_device_resources::ResolveChipsetDeviceHandleParams;
12use chipset_device_resources::ResolvedChipsetDevice;
13use chipset_resources::CmosRtcTimeSourceHandleKind;
14use firmware_uefi_resources::ResolvedUefiWatchdogPlatform;
15use firmware_uefi_resources::UefiCommandSet;
16use firmware_uefi_resources::UefiDeviceHandle;
17use firmware_uefi_resources::UefiLoggerHandleKind;
18use firmware_uefi_resources::UefiVsmConfigHandleKind;
19use firmware_uefi_resources::UefiWatchdogPlatformHandleKind;
20use hcl_compat_uefi_nvram_storage::HclCompatNvram;
21use thiserror::Error;
22use vm_resource::AsyncResolveResource;
23use vm_resource::ResolveError;
24use vm_resource::ResourceResolver;
25use vm_resource::declare_static_async_resolver;
26use vm_resource::kind::ChipsetDeviceHandleKind;
27use vm_resource::kind::NonVolatileStoreKind;
28
29pub struct UefiDeviceResolver;
31
32declare_static_async_resolver! {
33 UefiDeviceResolver,
34 (ChipsetDeviceHandleKind, UefiDeviceHandle),
35}
36
37#[derive(Debug, Error)]
39pub enum ResolveUefiDeviceError {
40 #[error("failed to resolve UEFI logger")]
42 ResolveLogger(#[source] ResolveError),
43 #[error("failed to resolve UEFI NVRAM storage")]
45 ResolveNvramStorage(#[source] ResolveError),
46 #[error("failed to resolve UEFI watchdog platform")]
48 ResolveWatchdogPlatform(#[source] ResolveError),
49 #[error("failed to resolve UEFI VSM configuration")]
51 ResolveVsmConfig(#[source] ResolveError),
52 #[error("failed to resolve UEFI time source")]
54 ResolveTimeSource(#[source] ResolveError),
55 #[error("failed to initialize UEFI device")]
57 Init(#[from] crate::UefiInitError),
58}
59
60const GPE0_LINE_GENERATION_ID: u32 = 0;
63const GENERATION_ID_IRQ: u32 = 3;
66
67#[async_trait]
68impl AsyncResolveResource<ChipsetDeviceHandleKind, UefiDeviceHandle> for UefiDeviceResolver {
69 type Output = ResolvedChipsetDevice;
70 type Error = ResolveUefiDeviceError;
71
72 async fn resolve(
73 &self,
74 resolver: &ResourceResolver,
75 resource: UefiDeviceHandle,
76 input: ResolveChipsetDeviceHandleParams<'_>,
77 ) -> Result<Self::Output, Self::Error> {
78 let UefiDeviceHandle {
79 config,
80 storage_quirks,
81 generation_id_recv,
82 logger,
83 nvram_storage,
84 watchdog_platform,
85 vsm_config,
86 time_source,
87 } = resource;
88
89 let logger = resolver
90 .resolve::<UefiLoggerHandleKind, _>(logger, ())
91 .await
92 .map_err(ResolveUefiDeviceError::ResolveLogger)?
93 .0;
94 let nvram_storage = resolver
95 .resolve::<NonVolatileStoreKind, _>(nvram_storage, &())
96 .await
97 .map_err(ResolveUefiDeviceError::ResolveNvramStorage)?
98 .0;
99 let ResolvedUefiWatchdogPlatform {
100 platform: watchdog_platform,
101 watchdog_recv,
102 } = resolver
103 .resolve::<UefiWatchdogPlatformHandleKind, _>(watchdog_platform, &())
104 .await
105 .map_err(ResolveUefiDeviceError::ResolveWatchdogPlatform)?;
106 let vsm_config = if let Some(vsm_config) = vsm_config {
107 Some(
108 resolver
109 .resolve::<UefiVsmConfigHandleKind, _>(vsm_config, ())
110 .await
111 .map_err(ResolveUefiDeviceError::ResolveVsmConfig)?
112 .0,
113 )
114 } else {
115 None
116 };
117 let time_source = resolver
118 .resolve::<CmosRtcTimeSourceHandleKind, _>(time_source, ())
119 .await
120 .map_err(ResolveUefiDeviceError::ResolveTimeSource)?
121 .0;
122
123 let notify_interrupt = match config.command_set {
124 UefiCommandSet::X64 => {
125 input
126 .configure
127 .new_line(GPE0_LINE_SET, "genid", GPE0_LINE_GENERATION_ID)
128 }
129 UefiCommandSet::Aarch64 => {
130 input
131 .configure
132 .new_line(IRQ_LINE_SET, "genid", GENERATION_ID_IRQ)
133 }
134 };
135
136 let nvram_storage = Box::new(HclCompatNvram::new(
137 vmm_core::emuplat::hcl_compat_uefi_nvram_storage::VmgsStorageBackendAdapter(
138 nvram_storage,
139 ),
140 storage_quirks,
141 ));
142
143 let gm = input.encrypted_guest_memory.clone();
144 let runtime_deps = UefiRuntimeDeps {
145 gm: gm.clone(),
146 nvram_storage,
147 logger,
148 vmtime: input.vmtime,
149 watchdog_platform,
150 watchdog_recv,
151 generation_id_deps: generation_id::GenerationIdRuntimeDeps {
152 generation_id_recv,
153 gm,
154 notify_interrupt,
155 },
156 vsm_config,
157 time_source,
158 };
159
160 let device = UefiDevice::new(runtime_deps, config, input.is_restoring).await?;
161 Ok(device.into())
162 }
163}