]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/VirtioBlkDxe/VirtioBlk.c
OvmfPkg/Virtio: take RingBaseShift in SetQueueAddress()
[mirror_edk2.git] / OvmfPkg / VirtioBlkDxe / VirtioBlk.c
index ead98272a52800654460ff8ebeaae12e1aeaf7b2..bff15fe3add1692f828122e284abe38f0dc1eef7 100644 (file)
@@ -11,6 +11,8 @@
     synchronous requests and EFI_BLOCK_IO_PROTOCOL for now.\r
 \r
   Copyright (C) 2012, Red Hat, Inc.\r
+  Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>\r
 \r
   This program and the accompanying materials are licensed and made available\r
   under the terms and conditions of the BSD License which accompanies this\r
 \r
 **/\r
 \r
-#include <IndustryStandard/Pci.h>\r
 #include <IndustryStandard/VirtioBlk.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/UefiLib.h>\r
+#include <Library/VirtioLib.h>\r
 \r
 #include "VirtioBlk.h"\r
 \r
-/**\r
-\r
-  Write a word into Region 0 of the device specified by PciIo.\r
-\r
-  Region 0 must be an iomem region. This is an internal function for the\r
-  VIRTIO_CFG_WRITE() macro below.\r
-\r
-  @param[in] PciIo        Target PCI device.\r
-\r
-  @param[in] FieldOffset  Destination offset.\r
-\r
-  @param[in] FieldSize    Destination field size, must be in { 1, 2, 4, 8 }.\r
-\r
-  @param[in] Value        Little endian value to write, converted to UINT64.\r
-                          The least significant FieldSize bytes will be used.\r
-\r
-\r
-  @return  Status code returned by PciIo->Io.Write().\r
-\r
-**/\r
-STATIC\r
-EFIAPI\r
-EFI_STATUS\r
-VirtioWrite (\r
-  IN EFI_PCI_IO_PROTOCOL *PciIo,\r
-  IN UINTN               FieldOffset,\r
-  IN UINTN               FieldSize,\r
-  IN UINT64              Value\r
-  )\r
-{\r
-  UINTN                     Count;\r
-  EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
-\r
-  Count = 1;\r
-  switch (FieldSize) {\r
-    case 1:\r
-      Width = EfiPciIoWidthUint8;\r
-      break;\r
-\r
-    case 2:\r
-      Width = EfiPciIoWidthUint16;\r
-      break;\r
-\r
-    case 8:\r
-      Count = 2;\r
-      // fall through\r
-\r
-    case 4:\r
-      Width = EfiPciIoWidthUint32;\r
-      break;\r
-\r
-    default:\r
-      ASSERT (FALSE);\r
-  }\r
-\r
-  return PciIo->Io.Write (\r
-                     PciIo,\r
-                     Width,\r
-                     PCI_BAR_IDX0,\r
-                     FieldOffset,\r
-                     Count,\r
-                     &Value\r
-                     );\r
-}\r
-\r
-\r
-/**\r
-\r
-  Read a word from Region 0 of the device specified by PciIo.\r
-\r
-  Region 0 must be an iomem region. This is an internal function for the\r
-  VIRTIO_CFG_READ() macro below.\r
-\r
-  @param[in] PciIo        Source PCI device.\r
-\r
-  @param[in] FieldOffset  Source offset.\r
-\r
-  @param[in] FieldSize    Source field size, must be in { 1, 2, 4, 8 }.\r
-\r
-  @param[in] BufferSize   Number of bytes available in the target buffer. Must\r
-                          equal FieldSize.\r
-\r
-  @param[out] Buffer      Target buffer.\r
-\r
-\r
-  @return  Status code returned by PciIo->Io.Read().\r
-\r
-**/\r
-STATIC\r
-EFIAPI\r
-EFI_STATUS\r
-VirtioRead (\r
-  IN  EFI_PCI_IO_PROTOCOL *PciIo,\r
-  IN  UINTN               FieldOffset,\r
-  IN  UINTN               FieldSize,\r
-  IN  UINTN               BufferSize,\r
-  OUT VOID                *Buffer\r
-  )\r
-{\r
-  UINTN                     Count;\r
-  EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
-\r
-  ASSERT (FieldSize == BufferSize);\r
-\r
-  Count = 1;\r
-  switch (FieldSize) {\r
-    case 1:\r
-      Width = EfiPciIoWidthUint8;\r
-      break;\r
-\r
-    case 2:\r
-      Width = EfiPciIoWidthUint16;\r
-      break;\r
-\r
-    case 8:\r
-      Count = 2;\r
-      // fall through\r
-\r
-    case 4:\r
-      Width = EfiPciIoWidthUint32;\r
-      break;\r
-\r
-    default:\r
-      ASSERT (FALSE);\r
-  }\r
-\r
-  return PciIo->Io.Read (\r
-                     PciIo,\r
-                     Width,\r
-                     PCI_BAR_IDX0,\r
-                     FieldOffset,\r
-                     Count,\r
-                     Buffer\r
-                     );\r
-}\r
-\r
-\r
 /**\r
 \r
   Convenience macros to read and write region 0 IO space elements of the\r
-  virtio-blk PCI device, for configuration purposes.\r
+  virtio-blk device, for configuration purposes.\r
 \r
   The following macros make it possible to specify only the "core parameters"\r
   for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE()\r
   returns, the transaction will have been completed.\r
 \r
-  @param[in] Dev       Pointer to the VBLK_DEV structure whose PCI IO space\r
-                       we're accessing. Dev->PciIo must be valid.\r
+  @param[in] Dev       Pointer to the VBLK_DEV structure whose VirtIo space\r
+                       we're accessing. Dev->VirtIo must be valid.\r
 \r
   @param[in] Field     A field name from VBLK_HDR, identifying the virtio-blk\r
                        configuration item to access.\r
@@ -192,23 +57,24 @@ VirtioRead (
                        one of UINT8, UINT16, UINT32, UINT64.\r
 \r
 \r
-  @return  Status code returned by VirtioWrite() / VirtioRead().\r
+  @return  Status code returned by Virtio->WriteDevice() /\r
+           Virtio->ReadDevice().\r
 \r
 **/\r
 \r
-#define VIRTIO_CFG_WRITE(Dev, Field, Value)  (VirtioWrite (             \\r
-                                                (Dev)->PciIo,           \\r
-                                                OFFSET_OF_VBLK (Field), \\r
-                                                SIZE_OF_VBLK (Field),   \\r
-                                                (Value)                 \\r
+#define VIRTIO_CFG_WRITE(Dev, Field, Value)  ((Dev)->VirtIo->WriteDevice ( \\r
+                                                (Dev)->VirtIo,             \\r
+                                                OFFSET_OF_VBLK (Field),    \\r
+                                                SIZE_OF_VBLK (Field),      \\r
+                                                (Value)                    \\r
                                                 ))\r
 \r
-#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead (              \\r
-                                                (Dev)->PciIo,           \\r
-                                                OFFSET_OF_VBLK (Field), \\r
-                                                SIZE_OF_VBLK (Field),   \\r
-                                                sizeof *(Pointer),      \\r
-                                                (Pointer)               \\r
+#define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice (  \\r
+                                                (Dev)->VirtIo,             \\r
+                                                OFFSET_OF_VBLK (Field),    \\r
+                                                SIZE_OF_VBLK (Field),      \\r
+                                                sizeof *(Pointer),         \\r
+                                                (Pointer)                  \\r
                                                 ))\r
 \r
 \r
@@ -314,66 +180,6 @@ VerifyReadWriteRequest (
 }\r
 \r
 \r
-/**\r
-\r
-  Append a contiguous buffer for transmission / reception via the virtio ring.\r
-\r
-  This function implements the following sections from virtio-0.9.5:\r
-  - 2.4.1.1 Placing Buffers into the Descriptor Table\r
-  - 2.4.1.2 Updating the Available Ring\r
-\r
-  Free space is taken as granted, since this driver supports only synchronous\r
-  requests and host side status is processed in lock-step with request\r
-  submission. VirtioBlkInit() verifies the ring size in advance.\r
-\r
-  @param[in out] Ring           The virtio ring to append the buffer to, as a\r
-                                descriptor.\r
-\r
-  @param [in] BufferPhysAddr    (Guest pseudo-physical) start address of the\r
-                                transmit / receive buffer\r
-\r
-  @param [in] BufferSize        Number of bytes to transmit or receive.\r
-\r
-  @param [in] Flags             A bitmask of VRING_DESC_F_* flags. The caller\r
-                                computes this mask dependent on further buffers\r
-                                to append and transfer direction.\r
-                                VRING_DESC_F_INDIRECT is unsupported. The\r
-                                VRING_DESC.Next field is always set, but the\r
-                                host only interprets it dependent on\r
-                                VRING_DESC_F_NEXT.\r
-\r
-  @param [in] HeadIdx           The index identifying the head buffer (first\r
-                                buffer appended) belonging to this same\r
-                                request.\r
-\r
-  @param [in out] NextAvailIdx  On input, the index identifying the next\r
-                                descriptor available to carry the buffer. On\r
-                                output, incremented by one, modulo 2^16.\r
-\r
-**/\r
-\r
-STATIC\r
-VOID\r
-EFIAPI\r
-AppendDesc (\r
-  IN OUT          VRING  *Ring,\r
-  IN              UINTN  BufferPhysAddr,\r
-  IN              UINT32 BufferSize,\r
-  IN              UINT16 Flags,\r
-  IN              UINT16 HeadIdx,\r
-  IN OUT          UINT16 *NextAvailIdx\r
-  )\r
-{\r
-  volatile VRING_DESC *Desc;\r
-\r
-  Desc        = &Ring->Desc[*NextAvailIdx % Ring->QueueSize];\r
-  Desc->Addr  = BufferPhysAddr;\r
-  Desc->Len   = BufferSize;\r
-  Desc->Flags = Flags;\r
-  Ring->Avail.Ring[(*NextAvailIdx)++ % Ring->QueueSize] =\r
-    HeadIdx % Ring->QueueSize;\r
-  Desc->Next  = *NextAvailIdx % Ring->QueueSize;\r
-}\r
 \r
 \r
 /**\r
@@ -424,7 +230,7 @@ AppendDesc (
 \r
   @retval EFI_SUCCESS          Transfer complete.\r
 \r
-  @retval EFI_DEVICE_ERROR     Failed to notify host side via PCI write, or\r
+  @retval EFI_DEVICE_ERROR     Failed to notify host side via VirtIo write, or\r
                                unable to parse host response, or host response\r
                                is not VIRTIO_BLK_S_OK.\r
 \r
@@ -444,9 +250,7 @@ SynchronousRequest (
   UINT32                  BlockSize;\r
   volatile VIRTIO_BLK_REQ Request;\r
   volatile UINT8          HostStatus;\r
-  UINT16                  FirstAvailIdx;\r
-  UINT16                  NextAvailIdx;\r
-  UINTN                   PollPeriodUsecs;\r
+  DESC_INDICES            Indices;\r
 \r
   BlockSize = Dev->BlockIoMedia.BlockSize;\r
 \r
@@ -469,13 +273,9 @@ SynchronousRequest (
                    (BufferSize == 0 ? VIRTIO_BLK_T_FLUSH : VIRTIO_BLK_T_OUT) :\r
                    VIRTIO_BLK_T_IN;\r
   Request.IoPrio = 0;\r
-  Request.Sector = Lba * (BlockSize / 512);\r
+  Request.Sector = MultU64x32(Lba, BlockSize / 512);\r
 \r
-  //\r
-  // Prepare for virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device.\r
-  // We're going to poll the answer, the host should not send an interrupt.\r
-  //\r
-  *Dev->Ring.Avail.Flags = (UINT16) VRING_AVAIL_F_NO_INTERRUPT;\r
+  VirtioPrepare (&Dev->Ring, &Indices);\r
 \r
   //\r
   // preset a host status for ourselves that we do not accept as success\r
@@ -488,17 +288,11 @@ SynchronousRequest (
   //\r
   ASSERT (Dev->Ring.QueueSize >= 3);\r
 \r
-  //\r
-  // Implement virtio-0.9.5, 2.4.1 Supplying Buffers to the Device.\r
-  //\r
-  FirstAvailIdx = *Dev->Ring.Avail.Idx;\r
-  NextAvailIdx  = FirstAvailIdx;\r
-\r
   //\r
   // virtio-blk header in first desc\r
   //\r
-  AppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request, VRING_DESC_F_NEXT,\r
-    FirstAvailIdx, &NextAvailIdx);\r
+  VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,\r
+    VRING_DESC_F_NEXT, &Indices);\r
 \r
   //\r
   // data buffer for read/write in second desc\r
@@ -517,52 +311,23 @@ SynchronousRequest (
     //\r
     // VRING_DESC_F_WRITE is interpreted from the host's point of view.\r
     //\r
-    AppendDesc (&Dev->Ring, (UINTN) Buffer, (UINT32) BufferSize,\r
+    VirtioAppendDesc (&Dev->Ring, (UINTN) Buffer, (UINT32) BufferSize,\r
       VRING_DESC_F_NEXT | (RequestIsWrite ? 0 : VRING_DESC_F_WRITE),\r
-      FirstAvailIdx, &NextAvailIdx);\r
+      &Indices);\r
   }\r
 \r
   //\r
   // host status in last (second or third) desc\r
   //\r
-  AppendDesc (&Dev->Ring, (UINTN) &HostStatus, sizeof HostStatus,\r
-    VRING_DESC_F_WRITE, FirstAvailIdx, &NextAvailIdx);\r
-\r
-  //\r
-  // virtio-0.9.5, 2.4.1.3 Updating the Index Field\r
-  //\r
-  MemoryFence();\r
-  *Dev->Ring.Avail.Idx = NextAvailIdx;\r
-\r
-  //\r
-  // virtio-0.9.5, 2.4.1.4 Notifying the Device -- gratuitous notifications are\r
-  // OK. virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).\r
-  //\r
-  MemoryFence();\r
-  if (EFI_ERROR (VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueNotify, 0))) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
+  VirtioAppendDesc (&Dev->Ring, (UINTN) &HostStatus, sizeof HostStatus,\r
+    VRING_DESC_F_WRITE, &Indices);\r
 \r
   //\r
-  // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device\r
-  // Wait until the host processes and acknowledges our 3-part descriptor\r
-  // chain. The condition we use for polling is greatly simplified and relies\r
-  // on synchronous, the lock-step progress.\r
+  // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).\r
   //\r
-  // Keep slowing down until we reach a poll period of slightly above 1 ms.\r
-  //\r
-  PollPeriodUsecs = 1;\r
-  MemoryFence();\r
-  while (*Dev->Ring.Used.Idx != NextAvailIdx) {\r
-    gBS->Stall (PollPeriodUsecs); // calls AcpiTimerLib::MicroSecondDelay\r
-\r
-    if (PollPeriodUsecs < 1024) {\r
-      PollPeriodUsecs *= 2;\r
-    }\r
-    MemoryFence();\r
-  }\r
-\r
-  if (HostStatus == VIRTIO_BLK_S_OK) {\r
+  if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices,\r
+        NULL) == EFI_SUCCESS &&\r
+      HostStatus == VIRTIO_BLK_S_OK) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
@@ -737,11 +502,6 @@ VirtioBlkFlushBlocks (
       underlying device\r
     - 9 Driver Binding Protocol -- for exporting ourselves\r
 \r
-  Specs relevant in the specific sense:\r
-  - UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol\r
-  - Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design\r
-    Guidelines, 18.3 PCI drivers.\r
-\r
   @param[in]  This                The EFI_DRIVER_BINDING_PROTOCOL object\r
                                   incorporating this driver (independently of\r
                                   any device).\r
@@ -753,11 +513,11 @@ VirtioBlkFlushBlocks (
 \r
   @retval EFI_SUCCESS      The driver supports the device being probed.\r
 \r
-  @retval EFI_UNSUPPORTED  Based on virtio-blk PCI discovery, we do not support\r
+  @retval EFI_UNSUPPORTED  Based on virtio-blk discovery, we do not support\r
                            the device.\r
 \r
   @return                  Error codes from the OpenProtocol() boot service or\r
-                           the PciIo protocol.\r
+                           the VirtIo protocol.\r
 \r
 **/\r
 \r
@@ -770,191 +530,49 @@ VirtioBlkDriverBindingSupported (
   )\r
 {\r
   EFI_STATUS          Status;\r
-  EFI_PCI_IO_PROTOCOL *PciIo;\r
-  PCI_TYPE00          Pci;\r
+  VIRTIO_DEVICE_PROTOCOL *VirtIo;\r
 \r
   //\r
-  // Attempt to open the device with the PciIo set of interfaces. On success,\r
-  // the protocol is "instantiated" for the PCI device. Covers duplicate open\r
-  // attempts (EFI_ALREADY_STARTED).\r
+  // Attempt to open the device with the VirtIo set of interfaces. On success,\r
+  // the protocol is "instantiated" for the VirtIo device. Covers duplicate\r
+  // open attempts (EFI_ALREADY_STARTED).\r
   //\r
   Status = gBS->OpenProtocol (\r
                   DeviceHandle,               // candidate device\r
-                  &gEfiPciIoProtocolGuid,     // for generic PCI access\r
-                  (VOID **)&PciIo,            // handle to instantiate\r
+                  &gVirtioDeviceProtocolGuid, // for generic VirtIo access\r
+                  (VOID **)&VirtIo,           // handle to instantiate\r
                   This->DriverBindingHandle,  // requestor driver identity\r
                   DeviceHandle,               // ControllerHandle, according to\r
                                               // the UEFI Driver Model\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to\r
                                               // the device; to be released\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  //\r
-  // Read entire PCI configuration header for more extensive check ahead.\r
-  //\r
-  Status = PciIo->Pci.Read (\r
-                        PciIo,                        // (protocol, device)\r
-                                                      // handle\r
-                        EfiPciIoWidthUint32,          // access width & copy\r
-                                                      // mode\r
-                        0,                            // Offset\r
-                        sizeof Pci / sizeof (UINT32), // Count\r
-                        &Pci                          // target buffer\r
-                        );\r
-\r
-  if (Status == EFI_SUCCESS) {\r
-    //\r
-    // virtio-0.9.5, 2.1 PCI Discovery\r
-    //\r
-    Status = (Pci.Hdr.VendorId == 0x1AF4 &&\r
-              Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F &&\r
-              Pci.Hdr.RevisionID == 0x00 &&\r
-              Pci.Device.SubsystemID == 0x02) ? EFI_SUCCESS : EFI_UNSUPPORTED;\r
+  if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_BLOCK_DEVICE) {\r
+    Status = EFI_UNSUPPORTED;\r
   }\r
 \r
   //\r
-  // We needed PCI IO access only transitorily, to see whether we support the\r
+  // We needed VirtIo access only transitorily, to see whether we support the\r
   // device or not.\r
   //\r
-  gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+  gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
          This->DriverBindingHandle, DeviceHandle);\r
   return Status;\r
 }\r
 \r
 \r
-/**\r
-\r
-  Configure a virtio ring.\r
-\r
-  This function sets up internal storage (the guest-host communication area)\r
-  and lays out several "navigation" (ie. no-ownership) pointers to parts of\r
-  that storage.\r
-\r
-  Relevant sections from the virtio-0.9.5 spec:\r
-  - 1.1 Virtqueues,\r
-  - 2.3 Virtqueue Configuration.\r
-\r
-  @param[in]                    The number of descriptors to allocate for the\r
-                                virtio ring, as requested by the host.\r
-\r
-  @param[out] Ring              The virtio ring to set up.\r
-\r
-  @retval EFI_OUT_OF_RESOURCES  AllocatePages() failed to allocate contiguous\r
-                                pages for the requested QueueSize. Fields of\r
-                                Ring have indeterminate value.\r
-\r
-  @retval EFI_SUCCESS           Allocation and setup successful. Ring->Base\r
-                                (and nothing else) is responsible for\r
-                                deallocation.\r
-\r
-**/\r
-\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-VirtioRingInit (\r
-  IN  UINT16 QueueSize,\r
-  OUT VRING  *Ring\r
-  )\r
-{\r
-  UINTN          RingSize;\r
-  volatile UINT8 *RingPagesPtr;\r
-\r
-  RingSize = ALIGN_VALUE (\r
-               sizeof *Ring->Desc            * QueueSize +\r
-               sizeof *Ring->Avail.Flags                 +\r
-               sizeof *Ring->Avail.Idx                   +\r
-               sizeof *Ring->Avail.Ring      * QueueSize +\r
-               sizeof *Ring->Avail.UsedEvent,\r
-               EFI_PAGE_SIZE);\r
-\r
-  RingSize += ALIGN_VALUE (\r
-                sizeof *Ring->Used.Flags                  +\r
-                sizeof *Ring->Used.Idx                    +\r
-                sizeof *Ring->Used.UsedElem   * QueueSize +\r
-                sizeof *Ring->Used.AvailEvent,\r
-                EFI_PAGE_SIZE);\r
-\r
-  Ring->NumPages = EFI_SIZE_TO_PAGES (RingSize);\r
-  Ring->Base = AllocatePages (Ring->NumPages);\r
-  if (Ring->Base == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-  SetMem (Ring->Base, RingSize, 0x00);\r
-  RingPagesPtr = Ring->Base;\r
-\r
-  Ring->Desc = (volatile VOID *) RingPagesPtr;\r
-  RingPagesPtr += sizeof *Ring->Desc * QueueSize;\r
-\r
-  Ring->Avail.Flags = (volatile VOID *) RingPagesPtr;\r
-  RingPagesPtr += sizeof *Ring->Avail.Flags;\r
-\r
-  Ring->Avail.Idx = (volatile VOID *) RingPagesPtr;\r
-  RingPagesPtr += sizeof *Ring->Avail.Idx;\r
-\r
-  Ring->Avail.Ring = (volatile VOID *) RingPagesPtr;\r
-  RingPagesPtr += sizeof *Ring->Avail.Ring * QueueSize;\r
-\r
-  Ring->Avail.UsedEvent = (volatile VOID *) RingPagesPtr;\r
-  RingPagesPtr += sizeof *Ring->Avail.UsedEvent;\r
-\r
-  RingPagesPtr = (volatile UINT8 *) Ring->Base +\r
-                 ALIGN_VALUE (RingPagesPtr - (volatile UINT8 *) Ring->Base,\r
-                   EFI_PAGE_SIZE);\r
-\r
-  Ring->Used.Flags = (volatile VOID *) RingPagesPtr;\r
-  RingPagesPtr += sizeof *Ring->Used.Flags;\r
-\r
-  Ring->Used.Idx = (volatile VOID *) RingPagesPtr;\r
-  RingPagesPtr += sizeof *Ring->Used.Idx;\r
-\r
-  Ring->Used.UsedElem = (volatile VOID *) RingPagesPtr;\r
-  RingPagesPtr += sizeof *Ring->Used.UsedElem * QueueSize;\r
-\r
-  Ring->Used.AvailEvent = (volatile VOID *) RingPagesPtr;\r
-  RingPagesPtr += sizeof *Ring->Used.AvailEvent;\r
-\r
-  Ring->QueueSize = QueueSize;\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-\r
-  Tear down the internal resources of a configured virtio ring.\r
-\r
-  The caller is responsible to stop the host from using this ring before\r
-  invoking this function: the VSTAT_DRIVER_OK bit must be clear in\r
-  VhdrDeviceStatus.\r
-\r
-  @param[out] Ring  The virtio ring to clean up.\r
-\r
-**/\r
-\r
-\r
-STATIC\r
-VOID\r
-EFIAPI\r
-VirtioRingUninit (\r
-  IN OUT VRING *Ring\r
-  )\r
-{\r
-  FreePages (Ring->Base, Ring->NumPages);\r
-  SetMem (Ring, sizeof *Ring, 0x00);\r
-}\r
-\r
-\r
 /**\r
 \r
   Set up all BlockIo and virtio-blk aspects of this driver for the specified\r
   device.\r
 \r
   @param[in out] Dev  The driver instance to configure. The caller is\r
-                      responsible for Dev->PciIo's validity (ie. working IO\r
-                      access to the underlying virtio-blk PCI device).\r
+                      responsible for Dev->VirtIo's validity (ie. working IO\r
+                      access to the underlying virtio-blk device).\r
 \r
   @retval EFI_SUCCESS      Setup complete.\r
 \r
@@ -976,28 +594,43 @@ VirtioBlkInit (
   UINT8      NextDevStat;\r
   EFI_STATUS Status;\r
 \r
-  UINT32     Features;\r
+  UINT64     Features;\r
   UINT64     NumSectors;\r
   UINT32     BlockSize;\r
+  UINT8      PhysicalBlockExp;\r
+  UINT8      AlignmentOffset;\r
+  UINT32     OptIoSize;\r
   UINT16     QueueSize;\r
 \r
+  PhysicalBlockExp = 0;\r
+  AlignmentOffset = 0;\r
+  OptIoSize = 0;\r
+\r
   //\r
   // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.\r
   //\r
   NextDevStat = 0;             // step 1 -- reset device\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+  Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
 \r
   NextDevStat |= VSTAT_ACK;    // step 2 -- acknowledge device presence\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+  Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
 \r
   NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+  Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Failed;\r
+  }\r
+\r
+  //\r
+  // Set Page Size - MMIO VirtIo Specific\r
+  //\r
+  Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
@@ -1005,11 +638,12 @@ VirtioBlkInit (
   //\r
   // step 4a -- retrieve and validate features\r
   //\r
-  Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);\r
+  Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
-  Status = VIRTIO_CFG_READ (Dev, VhdrCapacity, &NumSectors);\r
+\r
+  Status = VIRTIO_CFG_READ (Dev, Capacity, &NumSectors);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
@@ -1019,12 +653,12 @@ VirtioBlkInit (
   }\r
 \r
   if (Features & VIRTIO_BLK_F_BLK_SIZE) {\r
-    Status = VIRTIO_CFG_READ (Dev, VhdrBlkSize, &BlockSize);\r
+    Status = VIRTIO_CFG_READ (Dev, BlkSize, &BlockSize);\r
     if (EFI_ERROR (Status)) {\r
       goto Failed;\r
     }\r
     if (BlockSize == 0 || BlockSize % 512 != 0 ||\r
-        NumSectors % (BlockSize / 512) != 0) {\r
+        ModU64x32 (NumSectors, BlockSize / 512) != 0) {\r
       //\r
       // We can only handle a logical block consisting of whole sectors,\r
       // and only a disk composed of whole logical blocks.\r
@@ -1037,14 +671,50 @@ VirtioBlkInit (
     BlockSize = 512;\r
   }\r
 \r
+  if (Features & VIRTIO_BLK_F_TOPOLOGY) {\r
+    Status = VIRTIO_CFG_READ (Dev, Topology.PhysicalBlockExp,\r
+               &PhysicalBlockExp);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Failed;\r
+    }\r
+    if (PhysicalBlockExp >= 32) {\r
+      Status = EFI_UNSUPPORTED;\r
+      goto Failed;\r
+    }\r
+\r
+    Status = VIRTIO_CFG_READ (Dev, Topology.AlignmentOffset, &AlignmentOffset);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Failed;\r
+    }\r
+\r
+    Status = VIRTIO_CFG_READ (Dev, Topology.OptIoSize, &OptIoSize);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Failed;\r
+    }\r
+  }\r
+\r
+  Features &= VIRTIO_BLK_F_BLK_SIZE | VIRTIO_BLK_F_TOPOLOGY | VIRTIO_BLK_F_RO |\r
+              VIRTIO_BLK_F_FLUSH | VIRTIO_F_VERSION_1;\r
+\r
+  //\r
+  // In virtio-1.0, feature negotiation is expected to complete before queue\r
+  // discovery, and the device can also reject the selected set of features.\r
+  //\r
+  if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) {\r
+    Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Failed;\r
+    }\r
+  }\r
+\r
   //\r
   // step 4b -- allocate virtqueue\r
   //\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect, 0);\r
+  Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, 0);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
-  Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize);\r
+  Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
@@ -1053,45 +723,57 @@ VirtioBlkInit (
     goto Failed;\r
   }\r
 \r
-  Status = VirtioRingInit (QueueSize, &Dev->Ring);\r
+  Status = VirtioRingInit (Dev->VirtIo, QueueSize, &Dev->Ring);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
 \r
   //\r
-  // step 4c -- Report GPFN (guest-physical frame number) of queue. If anything\r
-  // fails from here on, we must release the ring resources.\r
+  // Additional steps for MMIO: align the queue appropriately, and set the\r
+  // size. If anything fails from here on, we must release the ring resources.\r
   //\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueAddress,\r
-             (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);\r
+  Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ReleaseQueue;\r
+  }\r
+\r
+  Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);\r
   if (EFI_ERROR (Status)) {\r
     goto ReleaseQueue;\r
   }\r
 \r
   //\r
-  // step 5 -- Report understood features. There are no virtio-blk specific\r
-  // features to negotiate in virtio-0.9.5, plus we do not want any of the\r
-  // device-independent (known or unknown) VIRTIO_F_* capabilities (see\r
-  // Appendix B).\r
+  // step 4c -- Report GPFN (guest-physical frame number) of queue.\r
   //\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits, 0);\r
+  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring, 0);\r
   if (EFI_ERROR (Status)) {\r
     goto ReleaseQueue;\r
   }\r
 \r
+\r
+  //\r
+  // step 5 -- Report understood features.\r
+  //\r
+  if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {\r
+    Features &= ~(UINT64)VIRTIO_F_VERSION_1;\r
+    Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);\r
+    if (EFI_ERROR (Status)) {\r
+      goto ReleaseQueue;\r
+    }\r
+  }\r
+\r
   //\r
   // step 6 -- initialization complete\r
   //\r
   NextDevStat |= VSTAT_DRIVER_OK;\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+  Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
   if (EFI_ERROR (Status)) {\r
     goto ReleaseQueue;\r
   }\r
 \r
   //\r
-  // Populate the exported interface's attributes; see UEFI spec v2.3.1 +\r
-  // Errata C, 12.8 EFI Block I/O Protocol. We stick to the lowest possible\r
-  // EFI_BLOCK_IO_PROTOCOL revision for now.\r
+  // Populate the exported interface's attributes; see UEFI spec v2.4, 12.9 EFI\r
+  // Block I/O Protocol.\r
   //\r
   Dev->BlockIo.Revision              = 0;\r
   Dev->BlockIo.Media                 = &Dev->BlockIoMedia;\r
@@ -1103,23 +785,42 @@ VirtioBlkInit (
   Dev->BlockIoMedia.RemovableMedia   = FALSE;\r
   Dev->BlockIoMedia.MediaPresent     = TRUE;\r
   Dev->BlockIoMedia.LogicalPartition = FALSE;\r
-  Dev->BlockIoMedia.ReadOnly         = !!(Features & VIRTIO_BLK_F_RO);\r
-  Dev->BlockIoMedia.WriteCaching     = !!(Features & VIRTIO_BLK_F_FLUSH);\r
+  Dev->BlockIoMedia.ReadOnly         = (BOOLEAN) ((Features & VIRTIO_BLK_F_RO) != 0);\r
+  Dev->BlockIoMedia.WriteCaching     = (BOOLEAN) ((Features & VIRTIO_BLK_F_FLUSH) != 0);\r
   Dev->BlockIoMedia.BlockSize        = BlockSize;\r
   Dev->BlockIoMedia.IoAlign          = 0;\r
-  Dev->BlockIoMedia.LastBlock        = NumSectors / (BlockSize / 512) - 1;\r
+  Dev->BlockIoMedia.LastBlock        = DivU64x32 (NumSectors,\r
+                                         BlockSize / 512) - 1;\r
+\r
+  DEBUG ((DEBUG_INFO, "%a: LbaSize=0x%x[B] NumBlocks=0x%Lx[Lba]\n",\r
+    __FUNCTION__, Dev->BlockIoMedia.BlockSize,\r
+    Dev->BlockIoMedia.LastBlock + 1));\r
+\r
+  if (Features & VIRTIO_BLK_F_TOPOLOGY) {\r
+    Dev->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;\r
+\r
+    Dev->BlockIoMedia.LowestAlignedLba = AlignmentOffset;\r
+    Dev->BlockIoMedia.LogicalBlocksPerPhysicalBlock = 1u << PhysicalBlockExp;\r
+    Dev->BlockIoMedia.OptimalTransferLengthGranularity = OptIoSize;\r
+\r
+    DEBUG ((DEBUG_INFO, "%a: FirstAligned=0x%Lx[Lba] PhysBlkSize=0x%x[Lba]\n",\r
+      __FUNCTION__, Dev->BlockIoMedia.LowestAlignedLba,\r
+      Dev->BlockIoMedia.LogicalBlocksPerPhysicalBlock));\r
+    DEBUG ((DEBUG_INFO, "%a: OptimalTransferLengthGranularity=0x%x[Lba]\n",\r
+      __FUNCTION__, Dev->BlockIoMedia.OptimalTransferLengthGranularity));\r
+  }\r
   return EFI_SUCCESS;\r
 \r
 ReleaseQueue:\r
-  VirtioRingUninit (&Dev->Ring);\r
+  VirtioRingUninit (Dev->VirtIo, &Dev->Ring);\r
 \r
 Failed:\r
   //\r
   // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device\r
-  // Status. PCI IO access failure here should not mask the original error.\r
+  // Status. VirtIo access failure here should not mask the original error.\r
   //\r
   NextDevStat |= VSTAT_FAILED;\r
-  VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+  Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
 \r
   return Status; // reached only via Failed above\r
 }\r
@@ -1146,20 +847,51 @@ VirtioBlkUninit (
   // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from\r
   // the old comms area.\r
   //\r
-  VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);\r
+  Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
 \r
-  VirtioRingUninit (&Dev->Ring);\r
+  VirtioRingUninit (Dev->VirtIo, &Dev->Ring);\r
 \r
   SetMem (&Dev->BlockIo,      sizeof Dev->BlockIo,      0x00);\r
   SetMem (&Dev->BlockIoMedia, sizeof Dev->BlockIoMedia, 0x00);\r
 }\r
 \r
 \r
+/**\r
+\r
+  Event notification function enqueued by ExitBootServices().\r
+\r
+  @param[in] Event    Event whose notification function is being invoked.\r
+\r
+  @param[in] Context  Pointer to the VBLK_DEV structure.\r
+\r
+**/\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+VirtioBlkExitBoot (\r
+  IN  EFI_EVENT Event,\r
+  IN  VOID      *Context\r
+  )\r
+{\r
+  VBLK_DEV *Dev;\r
+\r
+  //\r
+  // Reset the device. This causes the hypervisor to forget about the virtio\r
+  // ring.\r
+  //\r
+  // We allocated said ring in EfiBootServicesData type memory, and code\r
+  // executing after ExitBootServices() is permitted to overwrite it.\r
+  //\r
+  Dev = Context;\r
+  Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
+}\r
+\r
 /**\r
 \r
   After we've pronounced support for a specific device in\r
   DriverBindingSupported(), we start managing said device (passed in by the\r
-  Driver Exeuction Environment) with the following service.\r
+  Driver Execution Environment) with the following service.\r
 \r
   See DriverBindingSupported() for specification references.\r
 \r
@@ -1173,13 +905,13 @@ VirtioBlkUninit (
 \r
 \r
   @retval EFI_SUCCESS           Driver instance has been created and\r
-                                initialized  for the virtio-blk PCI device, it\r
-                                is now accessibla via EFI_BLOCK_IO_PROTOCOL.\r
+                                initialized  for the virtio-blk device, it\r
+                                is now accessible via EFI_BLOCK_IO_PROTOCOL.\r
 \r
   @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.\r
 \r
   @return                       Error codes from the OpenProtocol() boot\r
-                                service, the PciIo protocol, VirtioBlkInit(),\r
+                                service, the VirtIo protocol, VirtioBlkInit(),\r
                                 or the InstallProtocolInterface() boot service.\r
 \r
 **/\r
@@ -1200,43 +932,25 @@ VirtioBlkDriverBindingStart (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
-                  (VOID **)&Dev->PciIo, This->DriverBindingHandle,\r
+  Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
+                  (VOID **)&Dev->VirtIo, This->DriverBindingHandle,\r
                   DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);\r
   if (EFI_ERROR (Status)) {\r
     goto FreeVirtioBlk;\r
   }\r
 \r
   //\r
-  // We must retain and ultimately restore the original PCI attributes of the\r
-  // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /\r
-  // 18.3.2 Start() and Stop().\r
-  //\r
-  // The third parameter ("Attributes", input) is ignored by the Get operation.\r
-  // The fourth parameter ("Result", output) is ignored by the Enable and Set\r
-  // operations.\r
+  // VirtIo access granted, configure virtio-blk device.\r
   //\r
-  // For virtio-blk we only need IO space access.\r
-  //\r
-  Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet,\r
-                         0, &Dev->OriginalPciAttributes);\r
-  if (EFI_ERROR (Status)) {\r
-    goto ClosePciIo;\r
-  }\r
-\r
-  Status = Dev->PciIo->Attributes (Dev->PciIo,\r
-                         EfiPciIoAttributeOperationEnable,\r
-                         EFI_PCI_IO_ATTRIBUTE_IO, NULL);\r
+  Status = VirtioBlkInit (Dev);\r
   if (EFI_ERROR (Status)) {\r
-    goto ClosePciIo;\r
+    goto CloseVirtIo;\r
   }\r
 \r
-  //\r
-  // PCI IO access granted, configure virtio-blk device.\r
-  //\r
-  Status = VirtioBlkInit (Dev);\r
+  Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,\r
+                  &VirtioBlkExitBoot, Dev, &Dev->ExitBoot);\r
   if (EFI_ERROR (Status)) {\r
-    goto RestorePciAttributes;\r
+    goto UninitDev;\r
   }\r
 \r
   //\r
@@ -1247,20 +961,19 @@ VirtioBlkDriverBindingStart (
                   &gEfiBlockIoProtocolGuid, EFI_NATIVE_INTERFACE,\r
                   &Dev->BlockIo);\r
   if (EFI_ERROR (Status)) {\r
-    goto UninitDev;\r
+    goto CloseExitBoot;\r
   }\r
 \r
   return EFI_SUCCESS;\r
 \r
+CloseExitBoot:\r
+  gBS->CloseEvent (Dev->ExitBoot);\r
+\r
 UninitDev:\r
   VirtioBlkUninit (Dev);\r
 \r
-RestorePciAttributes:\r
-  Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
-                Dev->OriginalPciAttributes, NULL);\r
-\r
-ClosePciIo:\r
-  gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+CloseVirtIo:\r
+  gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
          This->DriverBindingHandle, DeviceHandle);\r
 \r
 FreeVirtioBlk:\r
@@ -1302,25 +1015,38 @@ VirtioBlkDriverBindingStop (
   IN EFI_HANDLE                  *ChildHandleBuffer\r
   )\r
 {\r
-  VBLK_DEV   *Dev;\r
-  EFI_STATUS Status;\r
+  EFI_STATUS            Status;\r
+  EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+  VBLK_DEV              *Dev;\r
 \r
-  Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);\r
+  Status = gBS->OpenProtocol (\r
+                  DeviceHandle,                  // candidate device\r
+                  &gEfiBlockIoProtocolGuid,      // retrieve the BlockIo iface\r
+                  (VOID **)&BlockIo,             // target pointer\r
+                  This->DriverBindingHandle,     // requestor driver identity\r
+                  DeviceHandle,                  // requesting lookup for dev.\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Dev = VIRTIO_BLK_FROM_BLOCK_IO (BlockIo);\r
 \r
   //\r
-  // If DriverBindingStop() is called with the driver instance still in use,\r
-  // or any of the parameters are invalid, we've caught a bug.\r
+  // Handle Stop() requests for in-use driver instances gracefully.\r
   //\r
   Status = gBS->UninstallProtocolInterface (DeviceHandle,\r
                   &gEfiBlockIoProtocolGuid, &Dev->BlockIo);\r
-  ASSERT (Status == EFI_SUCCESS);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
-  VirtioBlkUninit (Dev);\r
+  gBS->CloseEvent (Dev->ExitBoot);\r
 \r
-  Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
-                Dev->OriginalPciAttributes, NULL);\r
+  VirtioBlkUninit (Dev);\r
 \r
-  gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+  gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
          This->DriverBindingHandle, DeviceHandle);\r
 \r
   FreePool (Dev);\r
@@ -1357,13 +1083,13 @@ STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
 // for unambiguous identification.\r
 //\r
 \r
-STATIC GLOBAL_REMOVE_IF_UNREFERENCED\r
+STATIC\r
 EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {\r
   { "eng;en", L"Virtio Block Driver" },\r
   { NULL,     NULL                   }\r
 };\r
 \r
-STATIC GLOBAL_REMOVE_IF_UNREFERENCED\r
+STATIC\r
 EFI_COMPONENT_NAME_PROTOCOL gComponentName;\r
 \r
 EFI_STATUS\r
@@ -1396,14 +1122,14 @@ VirtioBlkGetDeviceName (
   return EFI_UNSUPPORTED;\r
 }\r
 \r
-STATIC GLOBAL_REMOVE_IF_UNREFERENCED\r
+STATIC\r
 EFI_COMPONENT_NAME_PROTOCOL gComponentName = {\r
   &VirtioBlkGetDriverName,\r
   &VirtioBlkGetDeviceName,\r
   "eng" // SupportedLanguages, ISO 639-2 language codes\r
 };\r
 \r
-STATIC GLOBAL_REMOVE_IF_UNREFERENCED\r
+STATIC\r
 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {\r
   (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)     &VirtioBlkGetDriverName,\r
   (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &VirtioBlkGetDeviceName,\r