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 @@ -841,6 +841,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 @@ -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, diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.h b/OvmfPkg/VirtioBlkDxe/VirtioBlk.h index 789caf9a37..ca4b7a0ca6 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.h +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.h @@ -37,6 +37,7 @@ typedef struct { // --------------------- ------------------ --------- UINT32 Signature; // DriverBindingStart 0 VIRTIO_DEVICE_PROTOCOL *VirtIo; // DriverBindingStart 0 + EFI_EVENT ExitBoot; // DriverBindingStart 0 VRING Ring; // VirtioRingInit 2 EFI_BLOCK_IO_PROTOCOL BlockIo; // VirtioBlkInit 1 EFI_BLOCK_IO_MEDIA BlockIoMedia; // VirtioBlkInit 1