X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=OvmfPkg%2FVirtioBlkDxe%2FVirtioBlk.c;h=bff15fe3add1692f828122e284abe38f0dc1eef7;hp=44a05cfb5f8be21a546ed48deb95605fed21ea95;hb=53a4c6047f3ce2ece7bb8db5b9815a1c9227dddb;hpb=e371e7e545b266ce4ae8ff76da6c98616214599f diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c index 44a05cfb5f..bff15fe3ad 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c @@ -11,6 +11,8 @@ synchronous requests and EFI_BLOCK_IO_PROTOCOL for now. Copyright (C) 2012, Red Hat, Inc. + Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 2017, AMD Inc, All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this @@ -22,7 +24,6 @@ **/ -#include #include #include #include @@ -36,14 +37,14 @@ /** Convenience macros to read and write region 0 IO space elements of the - virtio-blk PCI device, for configuration purposes. + virtio-blk device, for configuration purposes. The following macros make it possible to specify only the "core parameters" for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE() returns, the transaction will have been completed. - @param[in] Dev Pointer to the VBLK_DEV structure whose PCI IO space - we're accessing. Dev->PciIo must be valid. + @param[in] Dev Pointer to the VBLK_DEV structure whose VirtIo space + we're accessing. Dev->VirtIo must be valid. @param[in] Field A field name from VBLK_HDR, identifying the virtio-blk configuration item to access. @@ -56,23 +57,24 @@ one of UINT8, UINT16, UINT32, UINT64. - @return Status code returned by VirtioWrite() / VirtioRead(). + @return Status code returned by Virtio->WriteDevice() / + Virtio->ReadDevice(). **/ -#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWrite ( \ - (Dev)->PciIo, \ - OFFSET_OF_VBLK (Field), \ - SIZE_OF_VBLK (Field), \ - (Value) \ +#define VIRTIO_CFG_WRITE(Dev, Field, Value) ((Dev)->VirtIo->WriteDevice ( \ + (Dev)->VirtIo, \ + OFFSET_OF_VBLK (Field), \ + SIZE_OF_VBLK (Field), \ + (Value) \ )) -#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead ( \ - (Dev)->PciIo, \ - OFFSET_OF_VBLK (Field), \ - SIZE_OF_VBLK (Field), \ - sizeof *(Pointer), \ - (Pointer) \ +#define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \ + (Dev)->VirtIo, \ + OFFSET_OF_VBLK (Field), \ + SIZE_OF_VBLK (Field), \ + sizeof *(Pointer), \ + (Pointer) \ )) @@ -228,7 +230,7 @@ VerifyReadWriteRequest ( @retval EFI_SUCCESS Transfer complete. - @retval EFI_DEVICE_ERROR Failed to notify host side via PCI write, or + @retval EFI_DEVICE_ERROR Failed to notify host side via VirtIo write, or unable to parse host response, or host response is not VIRTIO_BLK_S_OK. @@ -271,7 +273,7 @@ SynchronousRequest ( (BufferSize == 0 ? VIRTIO_BLK_T_FLUSH : VIRTIO_BLK_T_OUT) : VIRTIO_BLK_T_IN; Request.IoPrio = 0; - Request.Sector = Lba * (BlockSize / 512); + Request.Sector = MultU64x32(Lba, BlockSize / 512); VirtioPrepare (&Dev->Ring, &Indices); @@ -323,7 +325,8 @@ SynchronousRequest ( // // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D). // - if (VirtioFlush (Dev->PciIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS && + if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, + NULL) == EFI_SUCCESS && HostStatus == VIRTIO_BLK_S_OK) { return EFI_SUCCESS; } @@ -499,11 +502,6 @@ VirtioBlkFlushBlocks ( underlying device - 9 Driver Binding Protocol -- for exporting ourselves - Specs relevant in the specific sense: - - UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol - - Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design - Guidelines, 18.3 PCI drivers. - @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object incorporating this driver (independently of any device). @@ -515,11 +513,11 @@ VirtioBlkFlushBlocks ( @retval EFI_SUCCESS The driver supports the device being probed. - @retval EFI_UNSUPPORTED Based on virtio-blk PCI discovery, we do not support + @retval EFI_UNSUPPORTED Based on virtio-blk discovery, we do not support the device. @return Error codes from the OpenProtocol() boot service or - the PciIo protocol. + the VirtIo protocol. **/ @@ -532,56 +530,36 @@ VirtioBlkDriverBindingSupported ( ) { EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE00 Pci; + VIRTIO_DEVICE_PROTOCOL *VirtIo; // - // Attempt to open the device with the PciIo set of interfaces. On success, - // the protocol is "instantiated" for the PCI device. Covers duplicate open - // attempts (EFI_ALREADY_STARTED). + // Attempt to open the device with the VirtIo set of interfaces. On success, + // the protocol is "instantiated" for the VirtIo device. Covers duplicate + // open attempts (EFI_ALREADY_STARTED). // Status = gBS->OpenProtocol ( DeviceHandle, // candidate device - &gEfiPciIoProtocolGuid, // for generic PCI access - (VOID **)&PciIo, // handle to instantiate + &gVirtioDeviceProtocolGuid, // for generic VirtIo access + (VOID **)&VirtIo, // handle to instantiate This->DriverBindingHandle, // requestor driver identity DeviceHandle, // ControllerHandle, according to // the UEFI Driver Model - EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to + EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to // the device; to be released ); if (EFI_ERROR (Status)) { return Status; } - // - // Read entire PCI configuration header for more extensive check ahead. - // - Status = PciIo->Pci.Read ( - PciIo, // (protocol, device) - // handle - EfiPciIoWidthUint32, // access width & copy - // mode - 0, // Offset - sizeof Pci / sizeof (UINT32), // Count - &Pci // target buffer - ); - - if (Status == EFI_SUCCESS) { - // - // virtio-0.9.5, 2.1 PCI Discovery - // - Status = (Pci.Hdr.VendorId == 0x1AF4 && - Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F && - Pci.Hdr.RevisionID == 0x00 && - Pci.Device.SubsystemID == 0x02) ? EFI_SUCCESS : EFI_UNSUPPORTED; + if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_BLOCK_DEVICE) { + Status = EFI_UNSUPPORTED; } // - // We needed PCI IO access only transitorily, to see whether we support the + // We needed VirtIo access only transitorily, to see whether we support the // device or not. // - gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, + gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, This->DriverBindingHandle, DeviceHandle); return Status; } @@ -593,8 +571,8 @@ VirtioBlkDriverBindingSupported ( device. @param[in out] Dev The driver instance to configure. The caller is - responsible for Dev->PciIo's validity (ie. working IO - access to the underlying virtio-blk PCI device). + responsible for Dev->VirtIo's validity (ie. working IO + access to the underlying virtio-blk device). @retval EFI_SUCCESS Setup complete. @@ -616,28 +594,43 @@ VirtioBlkInit ( UINT8 NextDevStat; EFI_STATUS Status; - UINT32 Features; + UINT64 Features; UINT64 NumSectors; UINT32 BlockSize; + UINT8 PhysicalBlockExp; + UINT8 AlignmentOffset; + UINT32 OptIoSize; UINT16 QueueSize; + PhysicalBlockExp = 0; + AlignmentOffset = 0; + OptIoSize = 0; + // // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence. // NextDevStat = 0; // step 1 -- reset device - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto Failed; } NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto Failed; } NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + + // + // Set Page Size - MMIO VirtIo Specific + // + Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE); if (EFI_ERROR (Status)) { goto Failed; } @@ -645,11 +638,12 @@ VirtioBlkInit ( // // step 4a -- retrieve and validate features // - Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features); + Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features); if (EFI_ERROR (Status)) { goto Failed; } - Status = VIRTIO_CFG_READ (Dev, VhdrCapacity, &NumSectors); + + Status = VIRTIO_CFG_READ (Dev, Capacity, &NumSectors); if (EFI_ERROR (Status)) { goto Failed; } @@ -659,12 +653,12 @@ VirtioBlkInit ( } if (Features & VIRTIO_BLK_F_BLK_SIZE) { - Status = VIRTIO_CFG_READ (Dev, VhdrBlkSize, &BlockSize); + Status = VIRTIO_CFG_READ (Dev, BlkSize, &BlockSize); if (EFI_ERROR (Status)) { goto Failed; } if (BlockSize == 0 || BlockSize % 512 != 0 || - NumSectors % (BlockSize / 512) != 0) { + ModU64x32 (NumSectors, BlockSize / 512) != 0) { // // We can only handle a logical block consisting of whole sectors, // and only a disk composed of whole logical blocks. @@ -677,14 +671,50 @@ VirtioBlkInit ( BlockSize = 512; } + if (Features & VIRTIO_BLK_F_TOPOLOGY) { + Status = VIRTIO_CFG_READ (Dev, Topology.PhysicalBlockExp, + &PhysicalBlockExp); + if (EFI_ERROR (Status)) { + goto Failed; + } + if (PhysicalBlockExp >= 32) { + Status = EFI_UNSUPPORTED; + goto Failed; + } + + Status = VIRTIO_CFG_READ (Dev, Topology.AlignmentOffset, &AlignmentOffset); + if (EFI_ERROR (Status)) { + goto Failed; + } + + Status = VIRTIO_CFG_READ (Dev, Topology.OptIoSize, &OptIoSize); + if (EFI_ERROR (Status)) { + goto Failed; + } + } + + Features &= VIRTIO_BLK_F_BLK_SIZE | VIRTIO_BLK_F_TOPOLOGY | VIRTIO_BLK_F_RO | + VIRTIO_BLK_F_FLUSH | VIRTIO_F_VERSION_1; + + // + // In virtio-1.0, feature negotiation is expected to complete before queue + // discovery, and the device can also reject the selected set of features. + // + if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) { + Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + } + // // step 4b -- allocate virtqueue // - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect, 0); + Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, 0); if (EFI_ERROR (Status)) { goto Failed; } - Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize); + Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize); if (EFI_ERROR (Status)) { goto Failed; } @@ -693,45 +723,57 @@ VirtioBlkInit ( goto Failed; } - Status = VirtioRingInit (QueueSize, &Dev->Ring); + Status = VirtioRingInit (Dev->VirtIo, QueueSize, &Dev->Ring); if (EFI_ERROR (Status)) { goto Failed; } // - // step 4c -- Report GPFN (guest-physical frame number) of queue. If anything - // fails from here on, we must release the ring resources. + // Additional steps for MMIO: align the queue appropriately, and set the + // size. If anything fails from here on, we must release the ring resources. // - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueAddress, - (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT); + Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize); + if (EFI_ERROR (Status)) { + goto ReleaseQueue; + } + + Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE); if (EFI_ERROR (Status)) { goto ReleaseQueue; } // - // step 5 -- Report understood features. There are no virtio-blk specific - // features to negotiate in virtio-0.9.5, plus we do not want any of the - // device-independent (known or unknown) VIRTIO_F_* capabilities (see - // Appendix B). + // step 4c -- Report GPFN (guest-physical frame number) of queue. // - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits, 0); + Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring, 0); if (EFI_ERROR (Status)) { goto ReleaseQueue; } + + // + // step 5 -- Report understood features. + // + if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) { + Features &= ~(UINT64)VIRTIO_F_VERSION_1; + Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features); + if (EFI_ERROR (Status)) { + goto ReleaseQueue; + } + } + // // step 6 -- initialization complete // NextDevStat |= VSTAT_DRIVER_OK; - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto ReleaseQueue; } // - // Populate the exported interface's attributes; see UEFI spec v2.3.1 + - // Errata C, 12.8 EFI Block I/O Protocol. We stick to the lowest possible - // EFI_BLOCK_IO_PROTOCOL revision for now. + // Populate the exported interface's attributes; see UEFI spec v2.4, 12.9 EFI + // Block I/O Protocol. // Dev->BlockIo.Revision = 0; Dev->BlockIo.Media = &Dev->BlockIoMedia; @@ -743,23 +785,42 @@ VirtioBlkInit ( Dev->BlockIoMedia.RemovableMedia = FALSE; Dev->BlockIoMedia.MediaPresent = TRUE; Dev->BlockIoMedia.LogicalPartition = FALSE; - Dev->BlockIoMedia.ReadOnly = !!(Features & VIRTIO_BLK_F_RO); - Dev->BlockIoMedia.WriteCaching = !!(Features & VIRTIO_BLK_F_FLUSH); + Dev->BlockIoMedia.ReadOnly = (BOOLEAN) ((Features & VIRTIO_BLK_F_RO) != 0); + Dev->BlockIoMedia.WriteCaching = (BOOLEAN) ((Features & VIRTIO_BLK_F_FLUSH) != 0); Dev->BlockIoMedia.BlockSize = BlockSize; Dev->BlockIoMedia.IoAlign = 0; - Dev->BlockIoMedia.LastBlock = NumSectors / (BlockSize / 512) - 1; + Dev->BlockIoMedia.LastBlock = DivU64x32 (NumSectors, + BlockSize / 512) - 1; + + DEBUG ((DEBUG_INFO, "%a: LbaSize=0x%x[B] NumBlocks=0x%Lx[Lba]\n", + __FUNCTION__, Dev->BlockIoMedia.BlockSize, + Dev->BlockIoMedia.LastBlock + 1)); + + if (Features & VIRTIO_BLK_F_TOPOLOGY) { + Dev->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3; + + Dev->BlockIoMedia.LowestAlignedLba = AlignmentOffset; + Dev->BlockIoMedia.LogicalBlocksPerPhysicalBlock = 1u << PhysicalBlockExp; + Dev->BlockIoMedia.OptimalTransferLengthGranularity = OptIoSize; + + DEBUG ((DEBUG_INFO, "%a: FirstAligned=0x%Lx[Lba] PhysBlkSize=0x%x[Lba]\n", + __FUNCTION__, Dev->BlockIoMedia.LowestAlignedLba, + Dev->BlockIoMedia.LogicalBlocksPerPhysicalBlock)); + DEBUG ((DEBUG_INFO, "%a: OptimalTransferLengthGranularity=0x%x[Lba]\n", + __FUNCTION__, Dev->BlockIoMedia.OptimalTransferLengthGranularity)); + } return EFI_SUCCESS; ReleaseQueue: - VirtioRingUninit (&Dev->Ring); + VirtioRingUninit (Dev->VirtIo, &Dev->Ring); Failed: // // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device - // Status. PCI IO access failure here should not mask the original error. + // Status. VirtIo access failure here should not mask the original error. // NextDevStat |= VSTAT_FAILED; - VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); return Status; // reached only via Failed above } @@ -786,20 +847,51 @@ VirtioBlkUninit ( // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from // the old comms area. // - VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0); + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); - VirtioRingUninit (&Dev->Ring); + VirtioRingUninit (Dev->VirtIo, &Dev->Ring); SetMem (&Dev->BlockIo, sizeof Dev->BlockIo, 0x00); SetMem (&Dev->BlockIoMedia, sizeof Dev->BlockIoMedia, 0x00); } +/** + + 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. + Driver Execution Environment) with the following service. See DriverBindingSupported() for specification references. @@ -813,13 +905,13 @@ VirtioBlkUninit ( @retval EFI_SUCCESS Driver instance has been created and - initialized for the virtio-blk PCI device, it - is now accessibla via EFI_BLOCK_IO_PROTOCOL. + initialized for the virtio-blk device, it + is now accessible via EFI_BLOCK_IO_PROTOCOL. @retval EFI_OUT_OF_RESOURCES Memory allocation failed. @return Error codes from the OpenProtocol() boot - service, the PciIo protocol, VirtioBlkInit(), + service, the VirtIo protocol, VirtioBlkInit(), or the InstallProtocolInterface() boot service. **/ @@ -840,43 +932,25 @@ VirtioBlkDriverBindingStart ( return EFI_OUT_OF_RESOURCES; } - Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, - (VOID **)&Dev->PciIo, This->DriverBindingHandle, + Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, + (VOID **)&Dev->VirtIo, This->DriverBindingHandle, DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); if (EFI_ERROR (Status)) { goto FreeVirtioBlk; } // - // We must retain and ultimately restore the original PCI attributes of the - // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers / - // 18.3.2 Start() and Stop(). - // - // The third parameter ("Attributes", input) is ignored by the Get operation. - // The fourth parameter ("Result", output) is ignored by the Enable and Set - // operations. - // - // For virtio-blk we only need IO space access. + // VirtIo access granted, configure virtio-blk device. // - Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet, - 0, &Dev->OriginalPciAttributes); - if (EFI_ERROR (Status)) { - goto ClosePciIo; - } - - Status = Dev->PciIo->Attributes (Dev->PciIo, - EfiPciIoAttributeOperationEnable, - EFI_PCI_IO_ATTRIBUTE_IO, NULL); + Status = VirtioBlkInit (Dev); if (EFI_ERROR (Status)) { - goto ClosePciIo; + goto CloseVirtIo; } - // - // PCI IO access granted, configure virtio-blk device. - // - Status = VirtioBlkInit (Dev); + Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK, + &VirtioBlkExitBoot, Dev, &Dev->ExitBoot); if (EFI_ERROR (Status)) { - goto RestorePciAttributes; + goto UninitDev; } // @@ -887,20 +961,19 @@ 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); -RestorePciAttributes: - Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet, - Dev->OriginalPciAttributes, NULL); - -ClosePciIo: - gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, +CloseVirtIo: + gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, This->DriverBindingHandle, DeviceHandle); FreeVirtioBlk: @@ -942,25 +1015,38 @@ VirtioBlkDriverBindingStop ( IN EFI_HANDLE *ChildHandleBuffer ) { - VBLK_DEV *Dev; - EFI_STATUS Status; + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + VBLK_DEV *Dev; - Dev = VIRTIO_BLK_FROM_BLOCK_IO (This); + Status = gBS->OpenProtocol ( + DeviceHandle, // candidate device + &gEfiBlockIoProtocolGuid, // retrieve the BlockIo iface + (VOID **)&BlockIo, // target pointer + This->DriverBindingHandle, // requestor driver identity + DeviceHandle, // requesting lookup for dev. + EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Dev = VIRTIO_BLK_FROM_BLOCK_IO (BlockIo); // - // If DriverBindingStop() is called with the driver instance still in use, - // or any of the parameters are invalid, we've caught a bug. + // Handle Stop() requests for in-use driver instances gracefully. // Status = gBS->UninstallProtocolInterface (DeviceHandle, &gEfiBlockIoProtocolGuid, &Dev->BlockIo); - ASSERT (Status == EFI_SUCCESS); + if (EFI_ERROR (Status)) { + return Status; + } - VirtioBlkUninit (Dev); + gBS->CloseEvent (Dev->ExitBoot); - Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet, - Dev->OriginalPciAttributes, NULL); + VirtioBlkUninit (Dev); - gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, + gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, This->DriverBindingHandle, DeviceHandle); FreePool (Dev); @@ -997,13 +1083,13 @@ STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = { // for unambiguous identification. // -STATIC GLOBAL_REMOVE_IF_UNREFERENCED +STATIC EFI_UNICODE_STRING_TABLE mDriverNameTable[] = { { "eng;en", L"Virtio Block Driver" }, { NULL, NULL } }; -STATIC GLOBAL_REMOVE_IF_UNREFERENCED +STATIC EFI_COMPONENT_NAME_PROTOCOL gComponentName; EFI_STATUS @@ -1036,14 +1122,14 @@ VirtioBlkGetDeviceName ( return EFI_UNSUPPORTED; } -STATIC GLOBAL_REMOVE_IF_UNREFERENCED +STATIC EFI_COMPONENT_NAME_PROTOCOL gComponentName = { &VirtioBlkGetDriverName, &VirtioBlkGetDeviceName, "eng" // SupportedLanguages, ISO 639-2 language codes }; -STATIC GLOBAL_REMOVE_IF_UNREFERENCED +STATIC EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = { (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &VirtioBlkGetDriverName, (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &VirtioBlkGetDeviceName,