1#![cfg(target_os = "linux")]
11#![forbid(unsafe_code)]
12
13pub mod api;
14pub mod error;
15pub mod resolver;
16
17mod client;
18mod process_loop;
19mod worker;
20
21pub use client::GuestEmulationTransportClient;
22
23#[derive(Debug, thiserror::Error)]
25#[error("failed to initialize GET worker")]
26pub struct SpawnGetError(#[source] process_loop::FatalError);
27
28#[derive(Debug, thiserror::Error)]
32#[error("encountered fatal GET error")]
33pub struct FatalGetError(#[source] process_loop::FatalError);
34
35pub async fn spawn_get_worker(
38 driver: impl pal_async::driver::SpawnDriver,
39) -> Result<
40 (
41 GuestEmulationTransportClient,
42 pal_async::task::Task<Result<(), FatalGetError>>,
43 ),
44 SpawnGetError,
45> {
46 let (worker, task) = worker::GuestEmulationTransportWorker::new(driver)
47 .await
48 .map_err(SpawnGetError)?;
49 Ok((worker.new_client(), task))
50}
51
52#[cfg(any(feature = "test_utilities", test))]
53#[expect(missing_docs)]
54pub mod test_utilities {
55 use super::*;
56 use crate::worker::GuestEmulationTransportWorker;
57 use client::GuestEmulationTransportClient;
58 use get_protocol::ProtocolVersion;
59 use guest_emulation_device::IgvmAgentTestPlan;
60 use guest_emulation_device::test_utilities::TestGedClient;
61 use guest_emulation_device::test_utilities::TestGetResponses;
62 use mesh::Receiver;
63 use pal_async::task::Spawn;
64 use pal_async::task::Task;
65
66 pub const DEFAULT_SIZE: usize = 4194816; #[cfg_attr(not(test), expect(dead_code))]
69 pub struct TestGet {
70 pub client: GuestEmulationTransportClient,
71 pub(crate) gen_id: Receiver<[u8; 16]>,
72 pub(crate) guest_task: Task<Result<(), FatalGetError>>,
73 pub(crate) test_ged_client: TestGedClient,
74 }
75
76 pub async fn new_transport_pair(
82 spawn: impl Spawn,
83 ged_responses: Option<Vec<TestGetResponses>>,
84 version: ProtocolVersion,
85 guest_memory: Option<guestmem::GuestMemory>,
86 igvm_agent_script: Option<IgvmAgentTestPlan>,
87 ) -> TestGet {
88 let (host_vmbus, guest_vmbus) = vmbus_async::pipe::connected_message_pipes(
89 get_protocol::MAX_MESSAGE_SIZE + vmbus_ring::PAGE_SIZE,
90 );
91
92 let test_ged_client = guest_emulation_device::test_utilities::create_host_channel(
93 &spawn,
94 host_vmbus,
95 ged_responses,
96 version,
97 guest_memory,
98 igvm_agent_script,
99 );
100
101 let (guest_transport, guest_task) =
103 GuestEmulationTransportWorker::with_pipe(&spawn, guest_vmbus)
104 .await
105 .unwrap();
106
107 let client = guest_transport.new_client();
108
109 TestGet {
110 gen_id: client.take_generation_id_recv().await.unwrap(),
111 client,
112 guest_task,
113 test_ged_client,
114 }
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::test_utilities::*;
121 use super::worker::GuestEmulationTransportWorker;
122 use crate::process_loop::FatalError;
123 use get_protocol::ProtocolVersion;
124 use get_protocol::VmgsIoStatus;
125 use get_protocol::test_utilities::TEST_VMGS_SECTOR_SIZE;
126 use guest_emulation_device::test_utilities::Event;
127 use guest_emulation_device::test_utilities::TestGetResponses;
128 use pal_async::DefaultDriver;
129 use pal_async::async_test;
130 use pal_async::task::Spawn;
131 use std::sync::Arc;
132 use std::sync::atomic::AtomicUsize;
133 use std::sync::atomic::Ordering;
134 use test_with_tracing::test;
135 use vmbus_async::async_dgram::AsyncRecvExt;
136 use vmbus_async::async_dgram::AsyncSendExt;
137 use zerocopy::FromZeros;
138 use zerocopy::IntoBytes;
139
140 #[async_test]
141 async fn test_version_negotiation_failed(driver: DefaultDriver) {
142 let (mut host_vmbus, guest_vmbus) =
143 vmbus_async::pipe::connected_message_pipes(get_protocol::MAX_MESSAGE_SIZE);
144
145 let host_task = driver.spawn("host task", async move {
146 for protocol in [ProtocolVersion::NICKEL_REV2] {
147 let mut version_request = get_protocol::VersionRequest::new_zeroed();
148 let len = version_request.as_bytes().len();
149 assert_eq!(
150 len,
151 host_vmbus
152 .recv(version_request.as_mut_bytes())
153 .await
154 .unwrap()
155 );
156
157 assert_eq!(
158 version_request.message_header.message_id(),
159 get_protocol::HostRequests::VERSION
160 );
161 assert_eq!(version_request.version, protocol);
162
163 let version_response = get_protocol::VersionResponse::new(false);
165
166 host_vmbus.send(version_response.as_bytes()).await.unwrap();
167 }
168 });
169
170 let transport = GuestEmulationTransportWorker::with_pipe(driver, guest_vmbus).await;
171
172 match transport.unwrap_err() {
173 FatalError::VersionNegotiationFailed => {}
174 e => panic!("Wrong error type returned: {}", e),
175 }
176
177 host_task.await;
178 }
179
180 #[async_test]
181 async fn test_all_basic(driver: DefaultDriver) {
182 let time_zone = 5;
183 let utc = 3;
184
185 let time_response = TestGetResponses::new(Event::Response(
186 get_protocol::TimeResponse::new(0, utc, time_zone, false)
187 .as_bytes()
188 .to_vec(),
189 ));
190
191 let vmgs_device_info_response = TestGetResponses::new(Event::Response(
192 get_protocol::VmgsGetDeviceInfoResponse::new(VmgsIoStatus::SUCCESS, 1, 2, 3, 4)
193 .as_bytes()
194 .to_vec(),
195 ));
196
197 let flush_response = TestGetResponses::new(Event::Response(
198 get_protocol::VmgsFlushResponse::new(VmgsIoStatus::SUCCESS)
199 .as_bytes()
200 .to_vec(),
201 ));
202
203 let guest_state_protection = TestGetResponses::new(Event::Response(
204 get_protocol::GuestStateProtectionResponse {
205 message_header: get_protocol::HeaderGeneric::new(
206 get_protocol::HostRequests::GUEST_STATE_PROTECTION,
207 ),
208 encrypted_gsp: get_protocol::GspCiphertextContent::new_zeroed(),
209 decrypted_gsp: [get_protocol::GspCleartextContent::new_zeroed();
210 get_protocol::NUMBER_GSP as usize],
211 extended_status_flags: get_protocol::GspExtendedStatusFlags::new()
212 .with_state_refresh_request(true),
213 }
214 .as_bytes()
215 .to_vec(),
216 ));
217
218 let gsp_id = TestGetResponses::new(Event::Response(
219 get_protocol::GuestStateProtectionByIdResponse {
220 message_header: get_protocol::HeaderGeneric::new(
221 get_protocol::HostRequests::GUEST_STATE_PROTECTION_BY_ID,
222 ),
223 seed: get_protocol::GspCleartextContent::new_zeroed(),
224 extended_status_flags: get_protocol::GspExtendedStatusFlags::new()
225 .with_no_registry_file(true)
226 .with_state_refresh_request(true),
227 }
228 .as_bytes()
229 .to_vec(),
230 ));
231
232 let igvm_attest = TestGetResponses::new(Event::Response(
233 get_protocol::IgvmAttestResponse {
234 message_header: get_protocol::HeaderGeneric::new(
235 get_protocol::HostRequests::IGVM_ATTEST,
236 ),
237 length: 512,
238 }
239 .as_bytes()
240 .to_vec(),
241 ));
242
243 let ged_responses = vec![
244 time_response,
245 vmgs_device_info_response,
246 flush_response,
247 guest_state_protection,
248 gsp_id,
249 igvm_attest,
250 ];
251
252 let get = new_transport_pair(
253 driver,
254 Some(ged_responses),
255 ProtocolVersion::NICKEL_REV2,
256 None,
257 None,
258 )
259 .await;
260
261 let result = get.client.host_time().await;
262
263 assert_eq!(result.utc, utc);
264 assert_eq!(result.time_zone, time_zone);
265
266 let response = get.client.vmgs_get_device_info().await.unwrap();
267 assert_eq!(response.capacity, 1);
268 assert_eq!(response.bytes_per_logical_sector, 2);
269 assert_eq!(response.bytes_per_physical_sector, 3);
270 assert_eq!(response.maximum_transfer_size_bytes, 4);
271
272 get.client.vmgs_flush().await.unwrap();
273
274 let gsp_response = get
275 .client
276 .guest_state_protection_data(
277 [get_protocol::GspCiphertextContent::new_zeroed();
278 get_protocol::NUMBER_GSP as usize],
279 get_protocol::GspExtendedStatusFlags::new().with_state_refresh_request(true),
280 )
281 .await;
282
283 assert_eq!(
284 gsp_response.extended_status_flags,
285 get_protocol::GspExtendedStatusFlags::new().with_state_refresh_request(true)
286 );
287
288 let gsp_id_response = get
289 .client
290 .guest_state_protection_data_by_id()
291 .await
292 .unwrap();
293
294 assert_eq!(
295 gsp_id_response.extended_status_flags,
296 get_protocol::GspExtendedStatusFlags::new()
297 .with_no_registry_file(true)
298 .with_state_refresh_request(true)
299 );
300 }
301
302 #[async_test]
303 async fn test_vmgs_basic_write(driver: DefaultDriver) {
304 let vmgs_write_response = TestGetResponses::new(Event::Response(
305 get_protocol::VmgsWriteResponse::new(VmgsIoStatus::SUCCESS)
306 .as_bytes()
307 .to_vec(),
308 ));
309
310 let vmgs_read_response = TestGetResponses::new(Event::Response(
311 get_protocol::VmgsReadResponse::new(VmgsIoStatus::SUCCESS)
312 .as_bytes()
313 .to_vec(),
314 ));
315 let ged_responses = vec![vmgs_write_response, vmgs_read_response];
316
317 let get = new_transport_pair(
318 driver,
319 Some(ged_responses),
320 ProtocolVersion::NICKEL_REV2,
321 None,
322 None,
323 )
324 .await;
325 let buf = (0..512).map(|x| x as u8).collect::<Vec<u8>>();
326 get.client
327 .vmgs_write(0, buf.clone(), TEST_VMGS_SECTOR_SIZE)
328 .await
329 .unwrap();
330
331 let read_buf = get
332 .client
333 .vmgs_read(0, 1, TEST_VMGS_SECTOR_SIZE)
334 .await
335 .unwrap();
336 assert_eq!(read_buf, buf);
337 }
338
339 #[async_test]
340 async fn different_get_versions_nickel(driver: DefaultDriver) {
341 let json = get_protocol::dps_json::DevicePlatformSettingsV2Json {
343 v1: get_protocol::dps_json::HclDevicePlatformSettings {
344 com1: get_protocol::dps_json::HclUartSettings {
345 enable_port: true,
346 debugger_mode: false,
347 enable_vmbus_redirector: true,
348 },
349 com2: get_protocol::dps_json::HclUartSettings {
350 enable_port: false,
351 debugger_mode: false,
352 enable_vmbus_redirector: false,
353 },
354 enable_firmware_debugging: true,
355 enable_ipmi: true,
356 ..Default::default()
357 },
358 v2: get_protocol::dps_json::HclDevicePlatformSettingsV2 {
359 r#static: get_protocol::dps_json::HclDevicePlatformSettingsV2Static {
360 legacy_memory_map: true,
361 pxe_ip_v6: true,
362 ..Default::default()
363 },
364 ..Default::default()
365 },
366 };
367 let json_data = serde_json::to_vec(&json).unwrap();
368
369 let mut dps_response = get_protocol::DevicePlatformSettingsResponseV2Rev1::new_zeroed();
370 dps_response.message_header = get_protocol::HeaderGeneric::new(
371 get_protocol::HostRequests::DEVICE_PLATFORM_SETTINGS_V2_REV1,
372 );
373 dps_response.size = json_data.len() as u32;
374 dps_response.payload_state = get_protocol::LargePayloadState::END;
375
376 let device_platform_settings = TestGetResponses::new(Event::Response(
377 [dps_response.as_bytes().to_vec(), json_data].concat(),
378 ));
379
380 let ged_responses = vec![device_platform_settings];
381
382 let get = new_transport_pair(
383 driver,
384 Some(ged_responses),
385 ProtocolVersion::NICKEL_REV2,
386 None,
387 None,
388 )
389 .await;
390
391 let dps = get.client.device_platform_settings().await.unwrap();
392 assert_eq!(dps.general.tpm_enabled, false);
393 assert_eq!(dps.general.com1_enabled, true);
394 assert_eq!(dps.general.secure_boot_enabled, false);
395 assert!(dps.general.ipmi_enabled);
396
397 assert_eq!(dps.general.legacy_memory_map, true);
398 assert_eq!(dps.general.pxe_ip_v6, true);
399 assert_eq!(dps.general.nvdimm_count, 0);
400
401 assert_eq!(dps.general.generation_id, Some([0; 16]));
402 }
403
404 #[async_test]
405 async fn test_send_notification(driver: DefaultDriver) {
406 let vmgs_read_response = TestGetResponses::new(Event::Response(
409 get_protocol::VmgsReadResponse::new(VmgsIoStatus::SUCCESS)
410 .as_bytes()
411 .to_vec(),
412 ));
413 let ged_responses = vec![TestGetResponses::default(), vmgs_read_response];
414
415 let get = new_transport_pair(
416 driver,
417 Some(ged_responses),
418 ProtocolVersion::NICKEL_REV2,
419 None,
420 None,
421 )
422 .await;
423
424 get.client
425 .event_log(get_protocol::EventLogId::NO_BOOT_DEVICE);
426
427 let read_buf = get
428 .client
429 .vmgs_read(0, 1, TEST_VMGS_SECTOR_SIZE)
430 .await
431 .unwrap();
432
433 assert_eq!(read_buf[0], 5);
434 }
435
436 #[async_test]
437 async fn test_send_ipmi_sel_notification(driver: DefaultDriver) {
438 let record_id = 0x1234;
439 let record = [
440 0x34, 0x12, 0x02, 0x78, 0x56, 0x34, 0x12, 0x20, 0x00, 0x04, 0x01, 0x6f, 0xaa, 0xbb,
441 0xcc, 0xdd,
442 ];
443 let expected = get_protocol::IpmiSelNotification::new(record_id, record)
444 .as_bytes()
445 .to_vec();
446
447 let vmgs_read_response = TestGetResponses::new(Event::Response(
448 get_protocol::VmgsReadResponse::new(VmgsIoStatus::SUCCESS)
449 .as_bytes()
450 .to_vec(),
451 ));
452 let ged_responses = vec![TestGetResponses::default(), vmgs_read_response];
453
454 let get = new_transport_pair(
455 driver,
456 Some(ged_responses),
457 ProtocolVersion::NICKEL_REV2,
458 None,
459 None,
460 )
461 .await;
462
463 get.client.ipmi_sel(record_id, record);
464
465 let read_buf = get
466 .client
467 .vmgs_read(0, 1, TEST_VMGS_SECTOR_SIZE)
468 .await
469 .unwrap();
470
471 assert_eq!(&read_buf[..expected.len()], expected.as_slice());
472 }
473
474 #[async_test]
475 async fn notification_in_between_requests(driver: DefaultDriver) {
476 let time_response = TestGetResponses::new(Event::Response(
477 get_protocol::UpdateGenerationId::new([1; 16])
478 .as_bytes()
479 .to_vec(),
480 ))
481 .add_response(Event::Response(
482 get_protocol::TimeResponse::new(0, 1, 2, false)
483 .as_bytes()
484 .to_vec(),
485 ));
486
487 let ged_responses = vec![time_response];
488
489 let mut get = new_transport_pair(
490 driver,
491 Some(ged_responses),
492 ProtocolVersion::NICKEL_REV2,
493 None,
494 None,
495 )
496 .await;
497
498 let result = get.client.host_time().await;
499
500 let gen_id = get.gen_id.recv().await.unwrap();
501
502 assert_eq!(gen_id, [1; 16]);
503
504 assert_eq!(result.utc, 1);
505 assert_eq!(result.time_zone, 2);
506 }
507
508 fn post_live_migration_time_response(notifications: usize) -> TestGetResponses {
512 let mut responses = TestGetResponses::default();
513 for _ in 0..notifications {
514 responses = responses.add_response(Event::Response(
515 get_protocol::PostLiveMigrationNotification {
516 message_header: get_protocol::HeaderGeneric::new(
517 get_protocol::GuestNotifications::NOTIFY_POST_LIVE_MIGRATION,
518 ),
519 }
520 .as_bytes()
521 .to_vec(),
522 ));
523 }
524 responses.add_response(Event::Response(
525 get_protocol::TimeResponse::new(0, 1, 2, false)
526 .as_bytes()
527 .to_vec(),
528 ))
529 }
530
531 #[async_test]
532 async fn post_live_migration_before_registration_is_coalesced(driver: DefaultDriver) {
533 for early_notifications in [1, 32] {
534 let mut get = new_transport_pair(
535 driver.clone(),
536 Some(vec![
537 post_live_migration_time_response(early_notifications),
538 post_live_migration_time_response(0),
539 post_live_migration_time_response(0),
540 post_live_migration_time_response(1),
541 ]),
542 ProtocolVersion::NICKEL_REV2,
543 None,
544 None,
545 )
546 .await;
547
548 get.client.host_time().await;
551 let calls = Arc::new(AtomicUsize::new(0));
552 let callback_calls = calls.clone();
553 get.client
554 .set_post_live_migration_callback(Box::new(move || {
555 callback_calls.fetch_add(1, Ordering::SeqCst);
556 }));
557 get.client.host_time().await;
558 assert_eq!(calls.load(Ordering::SeqCst), 1);
559
560 let replacement_calls = Arc::new(AtomicUsize::new(0));
562 let callback_calls = replacement_calls.clone();
563 get.client
564 .set_post_live_migration_callback(Box::new(move || {
565 callback_calls.fetch_add(1, Ordering::SeqCst);
566 }));
567 get.client.host_time().await;
568 assert_eq!(replacement_calls.load(Ordering::SeqCst), 0);
569 get.client.host_time().await;
570 assert_eq!(replacement_calls.load(Ordering::SeqCst), 1);
571 assert_eq!(calls.load(Ordering::SeqCst), 1);
572 }
573 }
574
575 #[async_test]
576 async fn post_live_migration_after_registration_is_delivered(driver: DefaultDriver) {
577 let mut get = new_transport_pair(
578 driver,
579 Some(vec![
580 post_live_migration_time_response(0),
581 post_live_migration_time_response(2),
582 ]),
583 ProtocolVersion::NICKEL_REV2,
584 None,
585 None,
586 )
587 .await;
588 let calls = Arc::new(AtomicUsize::new(0));
589 let callback_calls = calls.clone();
590 get.client
591 .set_post_live_migration_callback(Box::new(move || {
592 callback_calls.fetch_add(1, Ordering::SeqCst);
593 }));
594 get.client.host_time().await;
595 assert_eq!(calls.load(Ordering::SeqCst), 0);
596 get.client.host_time().await;
597 assert_eq!(calls.load(Ordering::SeqCst), 2);
598 }
599
600 #[async_test]
601 async fn host_send_multiple_response(driver: DefaultDriver) {
602 let time_response = TestGetResponses::new(Event::Response(
603 get_protocol::TimeResponse::new(0, 1, 2, false)
604 .as_bytes()
605 .to_vec(),
606 ))
607 .add_response(Event::Response(
608 get_protocol::TimeResponse::new(0, 1, 2, false)
609 .as_bytes()
610 .to_vec(),
611 ));
612
613 let ged_responses = vec![time_response];
614
615 let get = new_transport_pair(
616 driver,
617 Some(ged_responses),
618 ProtocolVersion::NICKEL_REV2,
619 None,
620 None,
621 )
622 .await;
623
624 let result = get.client.host_time().await;
625
626 assert_eq!(result.utc, 1);
627 assert_eq!(result.time_zone, 2);
628
629 assert!(futures::poll!(get.guest_task).is_pending());
631 }
632
633 #[async_test]
634 async fn host_send_mismatched_multiple_response(driver: DefaultDriver) {
635 let responses = TestGetResponses::new(Event::Response(
636 get_protocol::VpciDeviceControlResponse::new(
637 get_protocol::VpciDeviceControlStatus::SUCCESS,
638 )
639 .as_bytes()
640 .to_vec(),
641 ))
642 .add_response(Event::Response(
643 get_protocol::TimeResponse::new(0, 1, 2, false)
644 .as_bytes()
645 .to_vec(),
646 ))
647 .add_response(Event::Response(
648 get_protocol::VpciDeviceControlResponse::new(
649 get_protocol::VpciDeviceControlStatus::SUCCESS,
650 )
651 .as_bytes()
652 .to_vec(),
653 ));
654
655 let ged_responses = vec![responses];
656
657 let get = new_transport_pair(
658 driver,
659 Some(ged_responses),
660 ProtocolVersion::NICKEL_REV2,
661 None,
662 None,
663 )
664 .await;
665
666 let time_req = get.client.host_time();
667
668 let result = time_req.await;
669 assert_eq!(result.utc, 1);
670 assert_eq!(result.time_zone, 2);
671 }
672
673 #[async_test]
674 async fn host_send_mismatched_multiple_request_response(driver: DefaultDriver) {
675 let responses = TestGetResponses::new(Event::Response(
676 get_protocol::TimeResponse::new(0, 1, 2, false)
677 .as_bytes()
678 .to_vec(),
679 ))
680 .add_response(Event::Response(
681 get_protocol::VpciDeviceControlResponse::new(
682 get_protocol::VpciDeviceControlStatus::SUCCESS,
683 )
684 .as_bytes()
685 .to_vec(),
686 ))
687 .add_response(Event::Response(
688 get_protocol::TimeResponse::new(0, 1, 2, false)
689 .as_bytes()
690 .to_vec(),
691 ))
692 .add_response(Event::Response(
693 get_protocol::VpciDeviceControlResponse::new(
694 get_protocol::VpciDeviceControlStatus::SUCCESS,
695 )
696 .as_bytes()
697 .to_vec(),
698 ));
699
700 let ged_responses = vec![responses];
701
702 let get = new_transport_pair(
703 driver,
704 Some(ged_responses),
705 ProtocolVersion::NICKEL_REV2,
706 None,
707 None,
708 )
709 .await;
710
711 let time_req = get.client.host_time();
712 let mut vpci_req = std::pin::pin!(get.client.offer_vpci_device(guid::Guid::new_random()));
713
714 assert!(futures::poll!(&mut vpci_req).is_pending());
716
717 let result = time_req.await;
719 assert_eq!(result.utc, 1);
720 assert_eq!(result.time_zone, 2);
721
722 vpci_req.await.unwrap();
724 }
725
726 #[async_test]
727 async fn host_send_incorrect_response(driver: DefaultDriver) {
728 let time_response = TestGetResponses::new(Event::Response(
729 get_protocol::TimeResponse::new(0, 1, 2, false)
730 .as_bytes()
731 .to_vec(),
732 ));
733
734 let ged_responses = vec![time_response];
735
736 let get = new_transport_pair(
737 driver.clone(),
738 Some(ged_responses),
739 ProtocolVersion::NICKEL_REV2,
740 None,
741 None,
742 )
743 .await;
744
745 let _never_returns = driver.spawn("badness", async move {
746 let _ = get.client.vmgs_get_device_info().await;
747 });
748
749 let internal_error = get.guest_task.await;
750
751 assert!(matches!(
752 internal_error.map_err(|x| x.0),
753 Err(FatalError::ResponseHeaderMismatchId(_, _))
754 ));
755 }
756
757 #[async_test]
758 async fn test_send_halt_reason(driver: DefaultDriver) {
759 let power_off_check =
760 TestGetResponses::new(Event::Halt(power_resources::PowerRequest::PowerOff));
761 let reset_check = TestGetResponses::new(Event::Halt(power_resources::PowerRequest::Reset));
762
763 let vmgs_device_info_response = TestGetResponses::new(Event::Response(
764 get_protocol::VmgsGetDeviceInfoResponse::new(VmgsIoStatus::SUCCESS, 1, 2, 3, 4)
765 .as_bytes()
766 .to_vec(),
767 ));
768
769 let ged_responses = vec![power_off_check, reset_check, vmgs_device_info_response];
770
771 let get = new_transport_pair(
772 driver,
773 Some(ged_responses),
774 ProtocolVersion::NICKEL_REV2,
775 None,
776 None,
777 )
778 .await;
779
780 get.client.send_power_off();
781 get.client.send_reset();
782
783 let response = get.client.vmgs_get_device_info().await.unwrap();
788 assert_eq!(response.capacity, 1);
789 assert_eq!(response.bytes_per_logical_sector, 2);
790 assert_eq!(response.bytes_per_physical_sector, 3);
791 assert_eq!(response.maximum_transfer_size_bytes, 4);
792 }
793
794 #[async_test]
795 async fn test_send_multiple_host_request(driver: DefaultDriver) {
796 let time_response = TestGetResponses::new(Event::Response(
797 get_protocol::TimeResponse::new(0, 1, 2, false)
798 .as_bytes()
799 .to_vec(),
800 ));
801
802 let ged_responses = vec![
803 time_response.clone(),
804 time_response.clone(),
805 time_response.clone(),
806 time_response.clone(),
807 time_response.clone(),
808 time_response,
809 ];
810
811 let get = new_transport_pair(
812 driver.clone(),
813 Some(ged_responses),
814 ProtocolVersion::NICKEL_REV2,
815 None,
816 None,
817 )
818 .await;
819
820 let mut tasks = Vec::new();
821
822 for i in 0..6 {
823 let client = get.client.clone();
824 tasks.push(driver.spawn(
825 format!("task {}", i),
826 async move { client.host_time().await },
827 ));
828 }
829
830 for task in tasks {
834 let time = task.await;
835 assert_eq!(time.utc, 1);
836 assert_eq!(time.time_zone, 2);
837 }
838 }
839 #[async_test]
840 async fn test_vpci_control(driver: DefaultDriver) {
841 let bus_id = guid::Guid::new_random();
842 let vpci_offer_response = TestGetResponses::new(Event::Response(
843 get_protocol::VpciDeviceControlResponse::new(
844 get_protocol::VpciDeviceControlStatus::SUCCESS,
845 )
846 .as_bytes()
847 .to_vec(),
848 ));
849
850 let vpci_revoke_response = TestGetResponses::new(Event::Response(
851 get_protocol::VpciDeviceControlResponse::new(
852 get_protocol::VpciDeviceControlStatus::SUCCESS,
853 )
854 .as_bytes()
855 .to_vec(),
856 ));
857
858 let vpci_bind_response = TestGetResponses::new(Event::Response(
859 get_protocol::VpciDeviceBindingChangeResponse::new(
860 bus_id,
861 get_protocol::VpciDeviceControlStatus::SUCCESS,
862 )
863 .as_bytes()
864 .to_vec(),
865 ));
866
867 let vpci_unbind_response = TestGetResponses::new(Event::Response(
868 get_protocol::VpciDeviceBindingChangeResponse::new(
869 bus_id,
870 get_protocol::VpciDeviceControlStatus::SUCCESS,
871 )
872 .as_bytes()
873 .to_vec(),
874 ));
875
876 let ged_responses = vec![
877 vpci_offer_response,
878 vpci_revoke_response,
879 vpci_bind_response,
880 vpci_unbind_response,
881 ];
882
883 let get = new_transport_pair(
884 driver,
885 Some(ged_responses),
886 ProtocolVersion::NICKEL_REV2,
887 None,
888 None,
889 )
890 .await;
891 get.client.offer_vpci_device(bus_id).await.unwrap();
892 get.client.revoke_vpci_device(bus_id).await.unwrap();
893 get.client
894 .report_vpci_device_binding_state(bus_id, true)
895 .await
896 .unwrap();
897 get.client
898 .report_vpci_device_binding_state(bus_id, false)
899 .await
900 .unwrap();
901
902 get.client.connect_to_vpci_event_source(bus_id).await;
903 get.client.disconnect_from_vpci_event_source(bus_id);
904 }
905
906 #[ignore]
908 #[async_test]
909 async fn test_save_guest_vtl2_state(driver: DefaultDriver) {
910 let mut get =
911 new_transport_pair(driver, None, ProtocolVersion::NICKEL_REV2, None, None).await;
912
913 get.test_ged_client.test_save_guest_vtl2_state().await;
914 }
915
916 #[async_test]
917 async fn test_load_firmware(driver: DefaultDriver) {
918 let get = new_transport_pair(driver, None, ProtocolVersion::NICKEL_REV2, None, None).await;
922
923 let entry_offset = get.client.load_firmware(0x0107).await.unwrap();
924 assert_eq!(entry_offset, 0);
925 }
926}