1use super::process_loop::msg;
5use super::process_loop::msg::IgvmAttestRequestData;
6use crate::api::GuestSaveRequest;
7use crate::api::platform_settings;
8use chipset_resources::battery::HostBatteryUpdate;
9use cvm_tracing::CVM_ALLOWED;
10use get_protocol::RegisterState;
11use get_protocol::TripleFaultType;
12use guid::Guid;
13use inspect::Inspect;
14use mesh::MeshPayload;
15use mesh::rpc::Rpc;
16use mesh::rpc::RpcSend;
17use std::sync::Arc;
18use user_driver::DmaClient;
19use vpci::bus_control::VpciBusEvent;
20use zerocopy::IntoBytes;
21
22#[derive(Debug)]
24enum LogOpType {
25 BeginGspCallback,
26 GspCallback,
27}
28
29#[derive(Inspect, Debug, Clone, MeshPayload)]
36pub struct GuestEmulationTransportClient {
37 #[inspect(flatten)]
38 control: ProcessLoopControl,
39 #[inspect(debug)]
40 #[mesh(encoding = "mesh::payload::encoding::ZeroCopyEncoding")]
41 version: get_protocol::ProtocolVersion,
42}
43
44#[derive(Debug, Inspect, Clone, MeshPayload)]
45struct ProcessLoopControl(#[inspect(flatten, send = "msg::Msg::Inspect")] mesh::Sender<msg::Msg>);
46
47impl ProcessLoopControl {
48 async fn call<I, R: 'static + Send>(
49 &self,
50 msg: impl FnOnce(Rpc<I, R>) -> msg::Msg,
51 input: I,
52 ) -> R {
53 match self.0.call(msg, input).await {
54 Ok(val) => val,
55 Err(e) => {
60 tracing::error!(
61 error = &e as &dyn std::error::Error,
62 "fatal error: GET process loop not available. waiting to get blown away..."
63 );
64 std::future::pending::<()>().await;
65 unreachable!()
66 }
67 }
68 }
69
70 fn notify(&self, msg: msg::Msg) {
71 self.0.send(msg);
72 }
73}
74
75pub struct ModifyVtl2SettingsRequest(
76 pub Rpc<Vec<u8>, Result<(), Vec<underhill_config::Vtl2SettingsErrorInfo>>>,
77);
78
79impl GuestEmulationTransportClient {
80 pub(crate) fn new(
81 control: mesh::Sender<msg::Msg>,
82 version: get_protocol::ProtocolVersion,
83 ) -> GuestEmulationTransportClient {
84 GuestEmulationTransportClient {
85 control: ProcessLoopControl(control),
86 version,
87 }
88 }
89
90 pub fn version(&self) -> crate::api::ProtocolVersion {
93 self.version
94 }
95
96 pub async fn vmgs_read(
102 &self,
103 sector_offset: u64,
104 sector_count: u32,
105 sector_size: u32,
106 ) -> Result<Vec<u8>, crate::error::VmgsIoError> {
107 self.control
108 .call(
109 msg::Msg::VmgsRead,
110 msg::VmgsReadInput {
111 sector_offset,
112 sector_count,
113 sector_size,
114 },
115 )
116 .await
117 .map_err(|e| crate::error::VmgsIoError(e.0.status))
118 }
119
120 pub async fn vmgs_write(
129 &self,
130 sector_offset: u64,
131 buf: Vec<u8>,
132 sector_size: u32,
133 ) -> Result<(), crate::error::VmgsIoError> {
134 self.control
135 .call(
136 msg::Msg::VmgsWrite,
137 msg::VmgsWriteInput {
138 sector_offset,
139 buf,
140 sector_size,
141 },
142 )
143 .await
144 .map_err(|e| crate::error::VmgsIoError(e.0.status))
145 }
146
147 pub async fn vmgs_get_device_info(
149 &self,
150 ) -> Result<crate::api::VmgsGetDeviceInfo, crate::error::VmgsIoError> {
151 let response = self.control.call(msg::Msg::VmgsGetDeviceInfo, ()).await.0;
152
153 if response.status != get_protocol::VmgsIoStatus::SUCCESS {
154 return Err(crate::error::VmgsIoError(response.status));
155 }
156
157 let maximum_transfer_size_bytes = response
158 .maximum_transfer_size_bytes
159 .min(get_protocol::MAX_PAYLOAD_SIZE as u32);
160
161 if maximum_transfer_size_bytes != response.maximum_transfer_size_bytes {
162 tracing::warn!(
163 host_value = response.maximum_transfer_size_bytes,
164 clamped_value = maximum_transfer_size_bytes,
165 "VMGS maximum transfer size was clamped due to protocol limitations",
166 );
167 }
168
169 Ok(crate::api::VmgsGetDeviceInfo {
170 status: response.status,
171 capacity: response.capacity,
172 bytes_per_logical_sector: response.bytes_per_logical_sector,
173 bytes_per_physical_sector: response.bytes_per_physical_sector,
174 maximum_transfer_size_bytes,
175 })
176 }
177
178 pub async fn vmgs_flush(&self) -> Result<(), crate::error::VmgsIoError> {
180 let response = self.control.call(msg::Msg::VmgsFlush, ()).await.0;
181
182 if response.status != get_protocol::VmgsIoStatus::SUCCESS {
183 return Err(crate::error::VmgsIoError(response.status));
184 }
185
186 Ok(())
187 }
188
189 pub async fn device_platform_settings(
193 &self,
194 ) -> Result<platform_settings::DevicePlatformSettings, crate::error::DevicePlatformSettingsError>
195 {
196 let json = self
197 .control
198 .call(msg::Msg::DevicePlatformSettingsV2, ())
199 .await;
200
201 let json =
202 serde_json::from_slice::<get_protocol::dps_json::DevicePlatformSettingsV2Json>(&json)
203 .map_err(crate::error::DevicePlatformSettingsError::BadJson)?;
204
205 let vtl2_settings = if let Some(settings) = &json.v2.r#static.vtl2_settings {
206 Some(
207 underhill_config::Vtl2Settings::read_from(settings, Default::default())
208 .map_err(crate::error::DevicePlatformSettingsError::BadVtl2Settings)?,
209 )
210 } else {
211 None
212 };
213
214 Ok(platform_settings::DevicePlatformSettings {
215 smbios: platform_settings::Smbios {
216 serial_number: json.v1.serial_number,
217 base_board_serial_number: json.v1.base_board_serial_number,
218 chassis_serial_number: json.v1.chassis_serial_number,
219 chassis_asset_tag: json.v1.chassis_asset_tag,
220
221 system_manufacturer: json.v2.r#static.smbios.system_manufacturer,
222 system_product_name: json.v2.r#static.smbios.system_product_name,
223 system_version: json.v2.r#static.smbios.system_version,
224 system_sku_number: json.v2.r#static.smbios.system_sku_number,
225 system_family: json.v2.r#static.smbios.system_family,
226 bios_lock_string: json.v2.r#static.smbios.bios_lock_string,
227 memory_device_serial_number: json.v2.r#static.smbios.memory_device_serial_number,
228 processor_manufacturer: json.v2.dynamic.smbios.processor_manufacturer,
229 processor_version: json.v2.dynamic.smbios.processor_version,
230 processor_id: json.v2.dynamic.smbios.processor_id,
231 external_clock: json.v2.dynamic.smbios.external_clock,
232 max_speed: json.v2.dynamic.smbios.max_speed,
233 current_speed: json.v2.dynamic.smbios.current_speed,
234 processor_characteristics: json.v2.dynamic.smbios.processor_characteristics,
235 processor_family2: json.v2.dynamic.smbios.processor_family2,
236 processor_type: json.v2.dynamic.smbios.processor_type,
237 voltage: json.v2.dynamic.smbios.voltage,
238 status: json.v2.dynamic.smbios.status,
239 processor_upgrade: json.v2.dynamic.smbios.processor_upgrade,
240 },
241 general: platform_settings::General {
242 secure_boot_enabled: json.v1.secure_boot_enabled,
243 secure_boot_template: {
244 use crate::api::platform_settings::SecureBootTemplateType;
245 use get_protocol::dps_json::HclSecureBootTemplateId;
246
247 match json.v1.secure_boot_template_id {
248 HclSecureBootTemplateId::None => SecureBootTemplateType::None,
249 HclSecureBootTemplateId::MicrosoftWindows => {
250 SecureBootTemplateType::MicrosoftWindows
251 }
252 HclSecureBootTemplateId::MicrosoftUEFICertificateAuthority => {
253 SecureBootTemplateType::MicrosoftUefiCertificateAuthority
254 }
255 }
256 },
257 bios_guid: json.v1.bios_guid,
258 console_mode: {
259 use crate::api::platform_settings::UefiConsoleMode;
260
261 match get_protocol::UefiConsoleMode(json.v1.console_mode) {
262 get_protocol::UefiConsoleMode::DEFAULT => UefiConsoleMode::Default,
263 get_protocol::UefiConsoleMode::COM1 => UefiConsoleMode::COM1,
264 get_protocol::UefiConsoleMode::COM2 => UefiConsoleMode::COM2,
265 get_protocol::UefiConsoleMode::NONE => UefiConsoleMode::None,
266 o => {
267 return Err(
268 crate::error::DevicePlatformSettingsError::InvalidConsoleMode(o),
269 );
270 }
271 }
272 },
273 battery_enabled: json.v1.enable_battery,
274 processor_idle_enabled: json.v1.enable_processor_idle,
275 tpm_enabled: json.v1.enable_tpm,
276 ipmi_enabled: json.v1.enable_ipmi,
277 com1_enabled: json.v1.com1.enable_port,
278 com1_debugger_mode: json.v1.com1.debugger_mode,
279 com1_vmbus_redirector: json.v1.com1.enable_vmbus_redirector,
280 com2_enabled: json.v1.com2.enable_port,
281 com2_debugger_mode: json.v1.com2.debugger_mode,
282 com2_vmbus_redirector: json.v1.com2.enable_vmbus_redirector,
283 firmware_debugging_enabled: json.v1.enable_firmware_debugging,
284 hibernation_enabled: json.v1.enable_hibernation,
285
286 suppress_attestation: Some(json.v2.r#static.no_persistent_secrets),
287 generation_id: {
288 let mut gen_id = [0; 16];
289 gen_id[..8].copy_from_slice(&json.v2.dynamic.generation_id_low.to_ne_bytes());
290 gen_id[8..].copy_from_slice(&json.v2.dynamic.generation_id_high.to_ne_bytes());
291 Some(gen_id)
292 },
293
294 legacy_memory_map: json.v2.r#static.legacy_memory_map,
295 pause_after_boot_failure: json.v2.r#static.pause_after_boot_failure,
296 pxe_ip_v6: json.v2.r#static.pxe_ip_v6,
297 measure_additional_pcrs: json.v2.r#static.measure_additional_pcrs,
298 disable_frontpage: json.v2.r#static.disable_frontpage,
299 disable_sha384_pcr: json.v2.r#static.disable_sha384_pcr,
300 media_present_enabled_by_default: json.v2.r#static.media_present_enabled_by_default,
301 vpci_boot_enabled: json.v2.r#static.vpci_boot_enabled,
302 vpci_instance_filter: json.v2.r#static.vpci_instance_filter,
303 memory_protection_mode: {
304 use crate::api::platform_settings::MemoryProtectionMode;
305
306 match json.v2.r#static.memory_protection_mode {
307 0b00 => MemoryProtectionMode::Disabled,
308 0b01 => MemoryProtectionMode::Default,
309 0b10 => MemoryProtectionMode::Strict,
310 0b11 => MemoryProtectionMode::Relaxed,
311 o => return Err(
312 crate::error::DevicePlatformSettingsError::InvalidMemoryProtectionMode(
313 o,
314 ),
315 ),
316 }
317 },
318 default_boot_always_attempt: json.v2.r#static.default_boot_always_attempt,
319 nvdimm_count: json.v2.dynamic.nvdimm_count,
320 psp_enabled: json.v2.dynamic.enable_psp,
321 vmbus_redirection_enabled: json.v2.r#static.vmbus_redirection_enabled,
322 always_relay_host_mmio: json.v2.r#static.always_relay_host_mmio,
323 vtl2_settings,
324 watchdog_enabled: json.v2.r#static.watchdog_enabled,
325 num_lock_enabled: json.v2.r#static.num_lock_enabled,
326 pcat_boot_device_order: json.v2.r#static.pcat_boot_device_order.unwrap_or({
327 use crate::api::platform_settings::PcatBootDevice;
328 [
329 PcatBootDevice::Floppy,
330 PcatBootDevice::Optical,
331 PcatBootDevice::HardDrive,
332 PcatBootDevice::Network,
333 ]
334 }),
335 is_servicing_scenario: json.v2.dynamic.is_servicing_scenario,
336 firmware_mode_is_pcat: json.v2.r#static.firmware_mode_is_pcat,
337 imc_enabled: json.v2.r#static.imc_enabled,
338 cxl_memory_enabled: json.v2.r#static.cxl_memory_enabled,
339 efi_diagnostics_log_level: json.v2.r#static.efi_diagnostics_log_level,
340 guest_state_lifetime: json.v2.r#static.guest_state_lifetime,
341 guest_state_encryption_policy: json.v2.r#static.guest_state_encryption_policy,
342 management_vtl_features: json.v2.r#static.management_vtl_features,
343 force_dma_bounce_enabled: json.v2.r#static.force_dma_bounce_enabled,
344 hardware_sealing_policy: json.v2.r#static.hardware_sealing_policy_id,
345 },
346 acpi_tables: json.v2.dynamic.acpi_tables,
347 })
348 }
349
350 pub async fn guest_state_protection_data(
352 &self,
353 encrypted_gsp: [crate::api::GspCiphertextContent; crate::api::NUMBER_GSP as usize],
354 gsp_extended_status: crate::api::GspExtendedStatusFlags,
355 ) -> crate::api::GuestStateProtection {
356 let mut buffer = [0; get_protocol::GSP_CLEARTEXT_MAX as usize * 2];
357 let start_time = std::time::SystemTime::now();
358 getrandom::fill(&mut buffer).expect("rng failure");
359
360 tracing::info!(
361 CVM_ALLOWED,
362 op_type = ?LogOpType::BeginGspCallback,
363 "Getting guest state protection data"
364 );
365
366 let gsp_request = get_protocol::GuestStateProtectionRequest::new(
367 buffer,
368 encrypted_gsp,
369 gsp_extended_status,
370 );
371
372 let response = self
373 .control
374 .call(msg::Msg::GuestStateProtection, Box::new(gsp_request.into()))
375 .await
376 .0;
377
378 tracing::info!(
379 CVM_ALLOWED,
380 op_type = ?LogOpType::GspCallback,
381 latency = std::time::SystemTime::now()
382 .duration_since(start_time)
383 .map_or(0, |d| d.as_millis()),
384 "Got guest state protection data"
385 );
386
387 crate::api::GuestStateProtection {
388 encrypted_gsp: response.encrypted_gsp,
389 decrypted_gsp: response.decrypted_gsp,
390 extended_status_flags: response.extended_status_flags,
391 new_gsp: gsp_request.new_gsp,
392 }
393 }
394
395 pub fn set_gpa_allocator(&mut self, gpa_allocator: Arc<dyn DmaClient>) {
401 self.control
402 .notify(msg::Msg::SetGpaAllocator(gpa_allocator.into()));
403 }
404
405 pub fn set_debug_interrupt_callback(&mut self, callback: Box<dyn Fn(u8) + Send + Sync>) {
407 self.control
408 .notify(msg::Msg::SetDebugInterruptCallback(callback.into()));
409 }
410
411 pub fn set_post_live_migration_callback(&mut self, callback: Box<dyn Fn() + Send + Sync>) {
417 self.control
418 .notify(msg::Msg::SetPostLiveMigrationCallback(callback.into()));
419 }
420
421 pub async fn igvm_attest(
423 &self,
424 agent_data: Vec<u8>,
425 report: Vec<u8>,
426 response_buffer_len: usize,
427 ) -> Result<crate::api::IgvmAttest, crate::error::IgvmAttestError> {
428 let request = IgvmAttestRequestData {
429 agent_data,
430 report,
431 response_buffer_len,
432 };
433
434 let response = self
435 .control
436 .call(msg::Msg::IgvmAttest, Box::new(request))
437 .await?;
438
439 Ok(crate::api::IgvmAttest { response })
440 }
441
442 pub fn send_power_off(&self) {
447 tracing::info!("powering off...");
448 self.control
449 .notify(msg::Msg::PowerState(msg::PowerState::PowerOff));
450 }
451
452 pub fn send_hibernate(&self) {
457 tracing::info!("hibernating...");
458 self.control
459 .notify(msg::Msg::PowerState(msg::PowerState::Hibernate));
460 }
461
462 pub fn send_reset(&self) {
467 tracing::info!("resetting...");
468 self.control
469 .notify(msg::Msg::PowerState(msg::PowerState::Reset));
470 }
471
472 pub fn event_log(&self, event_log_id: crate::api::EventLogId) {
485 self.control.notify(msg::Msg::EventLog(event_log_id.into()));
486 }
487
488 pub fn ipmi_sel(&self, record_id: u16, record: ipmi_protocol::SelRecord) {
492 self.control.notify(msg::Msg::IpmiSel { record_id, record });
493 }
494
495 pub async fn event_log_flush(&self) {
498 self.control.call(msg::Msg::FlushWrites, ()).await
499 }
500
501 pub async fn event_log_fatal(&self, event_log_id: crate::api::EventLogId) {
510 self.control.notify(msg::Msg::EventLog(event_log_id.into()));
511 self.control.call(msg::Msg::FlushWrites, ()).await
512 }
513
514 pub async fn host_time(&self) -> crate::api::Time {
516 let response = self.control.call(msg::Msg::HostTime, ()).await;
517 crate::api::Time {
518 utc: response.0.utc,
519 time_zone: response.0.time_zone,
520 }
521 }
522
523 pub async fn guest_state_protection_data_by_id(
525 &self,
526 ) -> Result<crate::api::GuestStateProtectionById, crate::error::GuestStateProtectionByIdError>
527 {
528 let response = self
529 .control
530 .call(msg::Msg::GuestStateProtectionById, ())
531 .await
532 .0;
533
534 if response.seed.length > response.seed.buffer.len() as u32 {
535 return Err(crate::error::GuestStateProtectionByIdError(
536 response.seed.length,
537 response.seed.buffer.len() as u32,
538 ));
539 }
540
541 Ok(crate::api::GuestStateProtectionById {
542 seed: response.seed,
543 extended_status_flags: response.extended_status_flags,
544 })
545 }
546
547 pub async fn complete_start_vtl0(&self, error_msg: Option<String>) {
549 if self.version >= get_protocol::ProtocolVersion::NICKEL_REV2 {
550 self.control
551 .call(msg::Msg::CompleteStartVtl0, error_msg.clone())
552 .await;
553
554 if let Some(error_msg) = error_msg {
555 mesh::CancelContext::new()
562 .with_timeout(std::time::Duration::from_mins(2))
563 .until_cancelled(std::future::pending::<()>())
564 .await
565 .unwrap_or_else(|_| {
566 panic!(
567 "should have been terminated after reporting start failure: {error_msg}"
568 )
569 });
570 }
571 }
572 }
573
574 pub async fn map_framebuffer(&self, gpa: u64) -> Result<(), crate::error::MapFramebufferError> {
576 let response = self.control.call(msg::Msg::MapFramebuffer, gpa).await.0;
577 match response.status {
578 get_protocol::MapFramebufferStatus::SUCCESS => Ok(()),
579 _ => Err(crate::error::MapFramebufferError(response.status)),
580 }
581 }
582
583 pub async fn unmap_framebuffer(&self) -> Result<(), crate::error::UnmapFramebufferError> {
585 let response = self.control.call(msg::Msg::UnmapFramebuffer, ()).await.0;
586 match response.status {
587 get_protocol::UnmapFramebufferStatus::SUCCESS => Ok(()),
588 _ => Err(crate::error::UnmapFramebufferError(response.status)),
589 }
590 }
591
592 pub async fn offer_vpci_device(
594 &self,
595 bus_instance_id: Guid,
596 ) -> Result<(), crate::error::VpciControlError> {
597 let response = self
598 .control
599 .call(
600 msg::Msg::VpciDeviceControl,
601 msg::VpciDeviceControlInput {
602 code: get_protocol::VpciDeviceControlCode::OFFER.into(),
603 bus_instance_id,
604 },
605 )
606 .await
607 .0;
608 if response.status != get_protocol::VpciDeviceControlStatus::SUCCESS {
609 Err(crate::error::VpciControlError(response.status))
610 } else {
611 Ok(())
612 }
613 }
614
615 pub async fn revoke_vpci_device(
617 &self,
618 bus_instance_id: Guid,
619 ) -> Result<(), crate::error::VpciControlError> {
620 let response = self
621 .control
622 .call(
623 msg::Msg::VpciDeviceControl,
624 msg::VpciDeviceControlInput {
625 code: get_protocol::VpciDeviceControlCode::REVOKE.into(),
626 bus_instance_id,
627 },
628 )
629 .await
630 .0;
631 if response.status != get_protocol::VpciDeviceControlStatus::SUCCESS {
632 Err(crate::error::VpciControlError(response.status))
633 } else {
634 Ok(())
635 }
636 }
637
638 pub async fn report_vpci_device_binding_state(
640 &self,
641 bus_instance_id: Guid,
642 binding_state: bool,
643 ) -> Result<(), crate::error::VpciControlError> {
644 let response = self
645 .control
646 .call(
647 msg::Msg::VpciDeviceBindingChange,
648 msg::VpciDeviceBindingChangeInput {
649 bus_instance_id,
650 binding_state,
651 },
652 )
653 .await
654 .0;
655 if response.status != get_protocol::VpciDeviceControlStatus::SUCCESS {
656 Err(crate::error::VpciControlError(response.status))
657 } else {
658 Ok(())
659 }
660 }
661
662 pub async fn connect_to_vpci_event_source(
665 &self,
666 bus_instance_id: Guid,
667 ) -> mesh::Receiver<VpciBusEvent> {
668 let (sender, receiver) = mesh::channel();
669 self.control
670 .call(
671 msg::Msg::VpciListenerRegistration,
672 msg::VpciListenerRegistrationInput {
673 bus_instance_id,
674 sender,
675 },
676 )
677 .await;
678 receiver
679 }
680
681 pub fn disconnect_from_vpci_event_source(&self, bus_instance_id: Guid) {
683 self.control
684 .notify(msg::Msg::VpciListenerDeregistration(bus_instance_id));
685 }
686
687 pub async fn take_vtl2_settings_recv(
689 &self,
690 ) -> Option<mesh::Receiver<ModifyVtl2SettingsRequest>> {
691 self.control
692 .call(msg::Msg::TakeVtl2SettingsReceiver, ())
693 .await
694 .0
695 }
696
697 pub async fn take_generation_id_recv(&self) -> Option<mesh::Receiver<[u8; 16]>> {
699 self.control.call(msg::Msg::TakeGenIdReceiver, ()).await
700 }
701
702 pub async fn take_battery_status_recv(&self) -> Option<mesh::Receiver<HostBatteryUpdate>> {
704 self.control
705 .call(msg::Msg::TakeBatteryStatusReceiver, ())
706 .await
707 }
708
709 pub async fn vga_proxy_pci_read(&self, offset: u16) -> u32 {
711 let response = self.control.call(msg::Msg::VgaProxyPciRead, offset).await.0;
712 response.value
713 }
714
715 pub async fn vga_proxy_pci_write(&self, offset: u16, value: u32) {
717 self.control
718 .call(
719 msg::Msg::VgaProxyPciWrite,
720 msg::VgaProxyPciWriteInput { offset, value },
721 )
722 .await;
723 }
724
725 pub async fn create_ram_gpa_range(
727 &self,
728 slot: u32,
729 gpa_start: u64,
730 gpa_count: u64,
731 gpa_offset: u64,
732 flags: crate::api::CreateRamGpaRangeFlags,
733 ) -> Result<crate::api::RemoteRamGpaRangeHandle, crate::error::CreateRamGpaRangeError> {
734 let response = self
735 .control
736 .call(
737 msg::Msg::CreateRamGpaRange,
738 msg::CreateRamGpaRangeInput {
739 slot,
740 gpa_start,
741 gpa_count,
742 gpa_offset,
743 flags: flags.into(),
744 },
745 )
746 .await
747 .0;
748 if response.status != get_protocol::CreateRamGpaRangeStatus::SUCCESS {
749 Err(crate::error::CreateRamGpaRangeError(response.status))
750 } else {
751 Ok(crate::api::RemoteRamGpaRangeHandle::from_raw(slot))
752 }
753 }
754
755 pub async fn reset_ram_gpa_range(&self, handle: crate::api::RemoteRamGpaRangeHandle) {
758 self.control
759 .call(msg::Msg::ResetRamGpaRange, handle.as_raw())
760 .await;
761 }
762
763 pub async fn load_firmware(
774 &self,
775 firmware_token: u64,
776 ) -> Result<u64, crate::error::LoadFirmwareError> {
777 let response = self
778 .control
779 .call(msg::Msg::LoadFirmware, firmware_token)
780 .await
781 .0;
782 if response.status != get_protocol::LoadFirmwareStatus::SUCCESS {
783 Err(crate::error::LoadFirmwareError(response.status))
784 } else {
785 Ok(response.entry_point_image_offset)
786 }
787 }
788
789 pub async fn get_saved_state_from_host(
792 &self,
793 ) -> Result<Vec<u8>, crate::error::SaveRestoreOperationFailure> {
794 self.control
795 .call(msg::Msg::GetVtl2SavedStateFromHost, ())
796 .await
797 .map_err(|()| crate::error::SaveRestoreOperationFailure {})
798 }
799
800 pub async fn report_restore_result_to_host(&self, success: bool) {
805 self.control
806 .notify(msg::Msg::ReportRestoreResultToHost(success));
807 }
808
809 pub async fn take_save_request_recv(&self) -> Option<mesh::Receiver<GuestSaveRequest>> {
813 self.control
814 .call(msg::Msg::TakeSaveRequestReceiver, ())
815 .await
816 }
817
818 pub async fn send_servicing_state(
823 &self,
824 data: Vec<u8>,
825 ) -> Result<(), crate::error::SaveRestoreOperationFailure> {
826 self.control
827 .call(msg::Msg::SendServicingState, Ok(data))
828 .await
829 .map_err(|()| crate::error::SaveRestoreOperationFailure {})
830 }
831
832 pub async fn send_servicing_failure(
837 &self,
838 err: impl ToString,
839 ) -> Result<(), crate::error::SaveRestoreOperationFailure> {
840 self.control
841 .call(msg::Msg::SendServicingState, Err(err.to_string()))
842 .await
843 .map_err(|()| crate::error::SaveRestoreOperationFailure {})
844 }
845
846 pub fn notify_of_vtl_crash(
848 &self,
849 vp_index: u32,
850 last_vtl: u8,
851 control: u64,
852 parameters: [u64; get_protocol::VTL_CRASH_PARAMETERS],
853 ) {
854 self.control.notify(msg::Msg::VtlCrashNotification(
855 get_protocol::VtlCrashNotification::new(vp_index, last_vtl, control, parameters).into(),
856 ));
857 }
858
859 pub fn triple_fault(
861 &self,
862 vp_index: u32,
863 fault_type: TripleFaultType,
864 reg_state: Vec<RegisterState>,
865 ) {
866 let mut payload = vec![];
867
868 let notification = get_protocol::TripleFaultNotification::new(
869 vp_index,
870 fault_type,
871 reg_state.len() as u32,
872 );
873 payload.extend_from_slice(notification.as_bytes());
874 payload.extend_from_slice(reg_state.as_bytes());
875
876 self.control
877 .notify(msg::Msg::TripleFaultNotification(payload));
878 }
879}