diff options
Diffstat (limited to 'OvmfPkg/VirtioBlkDxe/VirtioBlk.c')
-rw-r--r-- | OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c index 862957ce04..75f85ca6e0 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c @@ -843,6 +843,37 @@ VirtioBlkUninit ( /**
+ Event notification function enqueued by ExitBootServices().
+
+ @param[in] Event Event whose notification function is being invoked.
+
+ @param[in] Context Pointer to the VBLK_DEV structure.
+
+**/
+
+STATIC
+VOID
+EFIAPI
+VirtioBlkExitBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ VBLK_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);
+}
+
+/**
+
After we've pronounced support for a specific device in
DriverBindingSupported(), we start managing said device (passed in by the
Driver Exeuction Environment) with the following service.
@@ -901,6 +932,12 @@ VirtioBlkDriverBindingStart ( goto CloseVirtIo;
}
+ Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
+ &VirtioBlkExitBoot, Dev, &Dev->ExitBoot);
+ if (EFI_ERROR (Status)) {
+ goto UninitDev;
+ }
+
//
// Setup complete, attempt to export the driver instance's BlockIo interface.
//
@@ -909,11 +946,14 @@ VirtioBlkDriverBindingStart ( &gEfiBlockIoProtocolGuid, EFI_NATIVE_INTERFACE,
&Dev->BlockIo);
if (EFI_ERROR (Status)) {
- goto UninitDev;
+ goto CloseExitBoot;
}
return EFI_SUCCESS;
+CloseExitBoot:
+ gBS->CloseEvent (Dev->ExitBoot);
+
UninitDev:
VirtioBlkUninit (Dev);
@@ -987,6 +1027,8 @@ VirtioBlkDriverBindingStop ( return Status;
}
+ gBS->CloseEvent (Dev->ExitBoot);
+
VirtioBlkUninit (Dev);
gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
|