diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c index 2cb3f43bb0..e1e12039b3 100644 --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c @@ -933,7 +933,6 @@ Failed: } - STATIC VOID EFIAPI @@ -960,6 +959,32 @@ VirtioScsiUninit ( } +// +// Event notification function enqueued by ExitBootServices(). +// + +STATIC +VOID +EFIAPI +VirtioScsiExitBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + VSCSI_DEV *Dev; + + // + // Reset the device. This causes the hypervisor to forget about the virtio + // ring. + // + // We allocated said ring in EfiBootServicesData type memory, and code + // executing after ExitBootServices() is permitted to overwrite it. + // + Dev = Context; + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); +} + + // // Probe, start and stop functions of this driver, called by the DXE core for // specific devices. @@ -1050,6 +1075,12 @@ VirtioScsiDriverBindingStart ( goto CloseVirtIo; } + Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK, + &VirtioScsiExitBoot, Dev, &Dev->ExitBoot); + if (EFI_ERROR (Status)) { + goto UninitDev; + } + // // Setup complete, attempt to export the driver instance's PassThru // interface. @@ -1059,11 +1090,14 @@ VirtioScsiDriverBindingStart ( &gEfiExtScsiPassThruProtocolGuid, EFI_NATIVE_INTERFACE, &Dev->PassThru); if (EFI_ERROR (Status)) { - goto UninitDev; + goto CloseExitBoot; } return EFI_SUCCESS; +CloseExitBoot: + gBS->CloseEvent (Dev->ExitBoot); + UninitDev: VirtioScsiUninit (Dev); @@ -1114,6 +1148,8 @@ VirtioScsiDriverBindingStop ( return Status; } + gBS->CloseEvent (Dev->ExitBoot); + VirtioScsiUninit (Dev); gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.h b/OvmfPkg/VirtioScsiDxe/VirtioScsi.h index 0d3181d140..80840d353e 100644 --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.h +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.h @@ -52,6 +52,7 @@ typedef struct { // ---------------- ------------------ ---------- UINT32 Signature; // DriverBindingStart 0 VIRTIO_DEVICE_PROTOCOL *VirtIo; // DriverBindingStart 0 + EFI_EVENT ExitBoot; // DriverBindingStart 0 BOOLEAN InOutSupported; // VirtioScsiInit 1 UINT16 MaxTarget; // VirtioScsiInit 1 UINT32 MaxLun; // VirtioScsiInit 1