]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/VirtioScsiDxe/VirtioScsi.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / VirtioScsiDxe / VirtioScsi.c
index 66f6d31d74b3be684d06c6cc843941d80d0b25b8..d44f9ebca7db0ab43b4cead6b3e4734edb6aa4cd 100644 (file)
     unreasonable for now.\r
 \r
   Copyright (C) 2012, Red Hat, Inc.\r
-  Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2012 - 2018, 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
-  distribution. The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
-  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
-#include <IndustryStandard/Pci.h>\r
 #include <IndustryStandard/VirtioScsi.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
 \r
 /**\r
 \r
-  Convenience macros to read and write region 0 IO space elements of the\r
-  virtio-scsi PCI device, for configuration purposes.\r
+  Convenience macros to read and write configuration elements of the\r
+  virtio-scsi VirtIo device.\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 VSCSI_DEV structure whose PCI IO space\r
-                       we're accessing. Dev->PciIo must be valid.\r
+  @param[in] Dev       Pointer to the VSCSI_DEV structure.\r
 \r
   @param[in] Field     A field name from VSCSI_HDR, identifying the virtio-scsi\r
                        configuration item to access.\r
                        one of UINT8, UINT16, UINT32, UINT64.\r
 \r
 \r
-  @return  Status codes returned by VirtioWrite() / VirtioRead().\r
+  @return  Status codes returned by Virtio->WriteDevice() / Virtio->ReadDevice().\r
 \r
 **/\r
 \r
-#define VIRTIO_CFG_WRITE(Dev, Field, Value)  (VirtioWrite (              \\r
-                                                (Dev)->PciIo,            \\r
-                                                OFFSET_OF_VSCSI (Field), \\r
-                                                SIZE_OF_VSCSI (Field),   \\r
-                                                (Value)                  \\r
+#define VIRTIO_CFG_WRITE(Dev, Field, Value)  ((Dev)->VirtIo->WriteDevice (  \\r
+                                                (Dev)->VirtIo,              \\r
+                                                OFFSET_OF_VSCSI (Field),    \\r
+                                                SIZE_OF_VSCSI (Field),      \\r
+                                                (Value)                     \\r
                                                 ))\r
 \r
-#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead (               \\r
-                                                (Dev)->PciIo,            \\r
-                                                OFFSET_OF_VSCSI (Field), \\r
-                                                SIZE_OF_VSCSI (Field),   \\r
-                                                sizeof *(Pointer),       \\r
-                                                (Pointer)                \\r
+#define VIRTIO_CFG_READ(Dev, Field, Pointer)  ((Dev)->VirtIo->ReadDevice (  \\r
+                                                (Dev)->VirtIo,              \\r
+                                                OFFSET_OF_VSCSI (Field),    \\r
+                                                SIZE_OF_VSCSI (Field),      \\r
+                                                sizeof *(Pointer),          \\r
+                                                (Pointer)                   \\r
                                                 ))\r
 \r
-\r
 //\r
 // UEFI Spec 2.3.1 + Errata C, 14.7 Extended SCSI Pass Thru Protocol specifies\r
 // the PassThru() interface. Beside returning a status code, the function must\r
 // set some fields in the EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET in/out\r
 // parameter on return. The following is a full list of those fields, for\r
 // easier validation of PopulateRequest(), ParseResponse(), and\r
-// VirtioScsiPassThru() below.\r
+// ReportHostAdapterError() below.\r
 //\r
 // - InTransferLength\r
 // - OutTransferLength\r
@@ -160,32 +152,32 @@ PopulateRequest (
   OUT    volatile VIRTIO_SCSI_REQ                             *Request\r
   )\r
 {\r
-  UINTN Idx;\r
+  UINTN  Idx;\r
 \r
   if (\r
       //\r
       // bidirectional transfer was requested, but the host doesn't support it\r
       //\r
-      (Packet->InTransferLength > 0 && Packet->OutTransferLength > 0 &&\r
+      ((Packet->InTransferLength > 0) && (Packet->OutTransferLength > 0) &&\r
        !Dev->InOutSupported) ||\r
 \r
       //\r
       // a target / LUN was addressed that's impossible to encode for the host\r
       //\r
-      Target > 0xFF || Lun >= 0x4000 ||\r
+      (Target > 0xFF) || (Lun >= 0x4000) ||\r
 \r
       //\r
       // Command Descriptor Block bigger than VIRTIO_SCSI_CDB_SIZE\r
       //\r
-      Packet->CdbLength > VIRTIO_SCSI_CDB_SIZE ||\r
+      (Packet->CdbLength > VIRTIO_SCSI_CDB_SIZE) ||\r
 \r
       //\r
       // From virtio-0.9.5, 2.3.2 Descriptor Table:\r
       // "no descriptor chain may be more than 2^32 bytes long in total".\r
       //\r
-      (UINT64) Packet->InTransferLength + Packet->OutTransferLength > SIZE_1GB\r
-      ) {\r
-\r
+      ((UINT64)Packet->InTransferLength + Packet->OutTransferLength > SIZE_1GB)\r
+      )\r
+  {\r
     //\r
     // this error code doesn't require updates to the Packet output fields\r
     //\r
@@ -196,35 +188,35 @@ PopulateRequest (
       //\r
       // addressed invalid device\r
       //\r
-      Target > Dev->MaxTarget || Lun > Dev->MaxLun ||\r
+      (Target > Dev->MaxTarget) || (Lun > Dev->MaxLun) ||\r
 \r
       //\r
       // invalid direction (there doesn't seem to be a macro for the "no data\r
       // transferred" "direction", eg. for TEST UNIT READY)\r
       //\r
-      Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||\r
+      (Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL) ||\r
 \r
       //\r
       // trying to receive, but destination pointer is NULL, or contradicting\r
       // transfer direction\r
       //\r
-      (Packet->InTransferLength > 0 &&\r
-       (Packet->InDataBuffer == NULL ||\r
-        Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE\r
-        )\r
-       ) ||\r
+      ((Packet->InTransferLength > 0) &&\r
+       ((Packet->InDataBuffer == NULL) ||\r
+        (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE)\r
+       )\r
+      ) ||\r
 \r
       //\r
       // trying to send, but source pointer is NULL, or contradicting transfer\r
       // direction\r
       //\r
-      (Packet->OutTransferLength > 0 &&\r
-       (Packet->OutDataBuffer == NULL ||\r
-        Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ\r
-        )\r
+      ((Packet->OutTransferLength > 0) &&\r
+       ((Packet->OutDataBuffer == NULL) ||\r
+        (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ)\r
        )\r
-      ) {\r
-\r
+      )\r
+      )\r
+  {\r
     //\r
     // this error code doesn't require updates to the Packet output fields\r
     //\r
@@ -236,16 +228,17 @@ PopulateRequest (
   // then the combined size of a bidirectional request will not exceed the\r
   // virtio-scsi device's transfer limit either.\r
   //\r
-  if (ALIGN_VALUE (Packet->OutTransferLength, 512) / 512\r
-        > Dev->MaxSectors / 2 ||\r
-      ALIGN_VALUE (Packet->InTransferLength,  512) / 512\r
-        > Dev->MaxSectors / 2) {\r
+  if ((ALIGN_VALUE (Packet->OutTransferLength, 512) / 512\r
+       > Dev->MaxSectors / 2) ||\r
+      (ALIGN_VALUE (Packet->InTransferLength, 512) / 512\r
+       > Dev->MaxSectors / 2))\r
+  {\r
     Packet->InTransferLength  = (Dev->MaxSectors / 2) * 512;\r
     Packet->OutTransferLength = (Dev->MaxSectors / 2) * 512;\r
     Packet->HostAdapterStatus =\r
-                        EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;\r
-    Packet->TargetStatus      = EFI_EXT_SCSI_STATUS_TARGET_GOOD;\r
-    Packet->SenseDataLength   = 0;\r
+      EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;\r
+    Packet->TargetStatus    = EFI_EXT_SCSI_STATUS_TARGET_GOOD;\r
+    Packet->SenseDataLength = 0;\r
     return EFI_BAD_BUFFER_SIZE;\r
   }\r
 \r
@@ -254,22 +247,21 @@ PopulateRequest (
   // Device Operation: request queues\r
   //\r
   Request->Lun[0] = 1;\r
-  Request->Lun[1] = (UINT8) Target;\r
-  Request->Lun[2] = (UINT8) ((Lun >> 8) | 0x40);\r
-  Request->Lun[3] = (UINT8) Lun;\r
+  Request->Lun[1] = (UINT8)Target;\r
+  Request->Lun[2] = (UINT8)(((UINT32)Lun >> 8) | 0x40);\r
+  Request->Lun[3] = (UINT8)Lun;\r
 \r
   //\r
   // CopyMem() would cast away the "volatile" qualifier before access, which is\r
   // undefined behavior (ISO C99 6.7.3p5)\r
   //\r
   for (Idx = 0; Idx < Packet->CdbLength; ++Idx) {\r
-    Request->Cdb[Idx] = ((UINT8 *) Packet->Cdb)[Idx];\r
+    Request->Cdb[Idx] = ((UINT8 *)Packet->Cdb)[Idx];\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
 \r
   Parse the virtio-scsi device's response, translate it to an EFI status code,\r
@@ -295,22 +287,23 @@ STATIC
 EFI_STATUS\r
 EFIAPI\r
 ParseResponse (\r
-  IN OUT                EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,\r
-  IN     CONST volatile VIRTIO_SCSI_RESP                           *Response\r
+  IN OUT                EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *Packet,\r
+  IN     CONST volatile VIRTIO_SCSI_RESP                            *Response\r
   )\r
 {\r
-  UINTN ResponseSenseLen;\r
-  UINTN Idx;\r
+  UINTN  ResponseSenseLen;\r
+  UINTN  Idx;\r
 \r
   //\r
   // return sense data (length and contents) in all cases, truncated if needed\r
   //\r
   ResponseSenseLen = MIN (Response->SenseLen, VIRTIO_SCSI_SENSE_SIZE);\r
   if (Packet->SenseDataLength > ResponseSenseLen) {\r
-    Packet->SenseDataLength = (UINT8) ResponseSenseLen;\r
+    Packet->SenseDataLength = (UINT8)ResponseSenseLen;\r
   }\r
+\r
   for (Idx = 0; Idx < Packet->SenseDataLength; ++Idx) {\r
-    ((UINT8 *) Packet->SenseData)[Idx] = Response->Sense[Idx];\r
+    ((UINT8 *)Packet->SenseData)[Idx] = Response->Sense[Idx];\r
   }\r
 \r
   //\r
@@ -328,9 +321,8 @@ ParseResponse (
   //  V  @ OutTransferLength + InTransferLength    -+- @ 0\r
   //\r
   if (Response->Residual <= Packet->InTransferLength) {\r
-    Packet->InTransferLength  -= Response->Residual;\r
-  }\r
-  else {\r
+    Packet->InTransferLength -= Response->Residual;\r
+  } else {\r
     Packet->OutTransferLength -= Response->Residual - Packet->InTransferLength;\r
     Packet->InTransferLength   = 0;\r
   }\r
@@ -345,49 +337,78 @@ ParseResponse (
   // response code\r
   //\r
   switch (Response->Response) {\r
-  case VIRTIO_SCSI_S_OK:\r
-    Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;\r
-    return EFI_SUCCESS;\r
+    case VIRTIO_SCSI_S_OK:\r
+      Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;\r
+      return EFI_SUCCESS;\r
 \r
-  case VIRTIO_SCSI_S_OVERRUN:\r
-    Packet->HostAdapterStatus =\r
-                        EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;\r
-    break;\r
+    case VIRTIO_SCSI_S_OVERRUN:\r
+      Packet->HostAdapterStatus =\r
+        EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;\r
+      break;\r
 \r
-  case VIRTIO_SCSI_S_BAD_TARGET:\r
-    //\r
-    // This is non-intuitive but explicitly required by the\r
-    // EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() specification for\r
-    // disconnected (but otherwise valid) target / LUN addresses.\r
-    //\r
-    Packet->HostAdapterStatus =\r
-                              EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;\r
-    return EFI_TIMEOUT;\r
+    case VIRTIO_SCSI_S_BAD_TARGET:\r
+      //\r
+      // This is non-intuitive but explicitly required by the\r
+      // EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() specification for\r
+      // disconnected (but otherwise valid) target / LUN addresses.\r
+      //\r
+      Packet->HostAdapterStatus =\r
+        EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;\r
+      return EFI_TIMEOUT;\r
 \r
-  case VIRTIO_SCSI_S_RESET:\r
-    Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET;\r
-    break;\r
+    case VIRTIO_SCSI_S_RESET:\r
+      Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET;\r
+      break;\r
 \r
-  case VIRTIO_SCSI_S_BUSY:\r
-    Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;\r
-    return EFI_NOT_READY;\r
+    case VIRTIO_SCSI_S_BUSY:\r
+      Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;\r
+      return EFI_NOT_READY;\r
 \r
-  //\r
-  // Lump together the rest. The mapping for VIRTIO_SCSI_S_ABORTED is\r
-  // intentional as well, not an oversight.\r
-  //\r
-  case VIRTIO_SCSI_S_ABORTED:\r
-  case VIRTIO_SCSI_S_TRANSPORT_FAILURE:\r
-  case VIRTIO_SCSI_S_TARGET_FAILURE:\r
-  case VIRTIO_SCSI_S_NEXUS_FAILURE:\r
-  case VIRTIO_SCSI_S_FAILURE:\r
-  default:\r
-    Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r
+    //\r
+    // Lump together the rest. The mapping for VIRTIO_SCSI_S_ABORTED is\r
+    // intentional as well, not an oversight.\r
+    //\r
+    case VIRTIO_SCSI_S_ABORTED:\r
+    case VIRTIO_SCSI_S_TRANSPORT_FAILURE:\r
+    case VIRTIO_SCSI_S_TARGET_FAILURE:\r
+    case VIRTIO_SCSI_S_NEXUS_FAILURE:\r
+    case VIRTIO_SCSI_S_FAILURE:\r
+    default:\r
+      Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r
   }\r
 \r
   return EFI_DEVICE_ERROR;\r
 }\r
 \r
+/**\r
+\r
+  The function can be used to create a fake host adapter error.\r
+\r
+  When VirtioScsiPassThru() is failed due to some reasons then this function\r
+  can be called to construct a host adapter error.\r
+\r
+  @param[out] Packet  The Extended SCSI Pass Thru Protocol packet that the host\r
+                      adapter error shall be placed in.\r
+\r
+\r
+  @retval EFI_DEVICE_ERROR  The function returns this status code\r
+                            unconditionally, to be propagated by\r
+                            VirtioScsiPassThru().\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ReportHostAdapterError (\r
+  OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *Packet\r
+  )\r
+{\r
+  Packet->InTransferLength  = 0;\r
+  Packet->OutTransferLength = 0;\r
+  Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r
+  Packet->TargetStatus      = EFI_EXT_SCSI_STATUS_TARGET_GOOD;\r
+  Packet->SenseDataLength   = 0;\r
+  return EFI_DEVICE_ERROR;\r
+}\r
 \r
 //\r
 // The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL\r
@@ -399,48 +420,178 @@ ParseResponse (
 EFI_STATUS\r
 EFIAPI\r
 VirtioScsiPassThru (\r
-  IN     EFI_EXT_SCSI_PASS_THRU_PROTOCOL            *This,\r
-  IN     UINT8                                      *Target,\r
-  IN     UINT64                                     Lun,\r
-  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,\r
-  IN     EFI_EVENT                                  Event   OPTIONAL\r
+  IN     EFI_EXT_SCSI_PASS_THRU_PROTOCOL             *This,\r
+  IN     UINT8                                       *Target,\r
+  IN     UINT64                                      Lun,\r
+  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *Packet,\r
+  IN     EFI_EVENT                                   Event   OPTIONAL\r
   )\r
 {\r
-  VSCSI_DEV                 *Dev;\r
-  UINT16                    TargetValue;\r
-  EFI_STATUS                Status;\r
-  volatile VIRTIO_SCSI_REQ  Request;\r
-  volatile VIRTIO_SCSI_RESP Response;\r
-  DESC_INDICES              Indices;\r
-\r
-  //\r
-  // Zero-initialization of Request & Response with "= { 0 };" doesn't build\r
-  // with gcc-4.4: "undefined reference to `memset'". Direct SetMem() is not\r
-  // allowed as it would cast away the volatile qualifier. Work it around.\r
-  //\r
-  union {\r
-    VIRTIO_SCSI_REQ  Request;\r
-    VIRTIO_SCSI_RESP Response;\r
-  } Zero;\r
-\r
-  SetMem (&Zero, sizeof Zero, 0x00);\r
-  Request  = Zero.Request;\r
-  Response = Zero.Response;\r
+  VSCSI_DEV                  *Dev;\r
+  UINT16                     TargetValue;\r
+  EFI_STATUS                 Status;\r
+  volatile VIRTIO_SCSI_REQ   Request;\r
+  volatile VIRTIO_SCSI_RESP  *Response;\r
+  VOID                       *ResponseBuffer;\r
+  DESC_INDICES               Indices;\r
+  VOID                       *RequestMapping;\r
+  VOID                       *ResponseMapping;\r
+  VOID                       *InDataMapping;\r
+  VOID                       *OutDataMapping;\r
+  EFI_PHYSICAL_ADDRESS       RequestDeviceAddress;\r
+  EFI_PHYSICAL_ADDRESS       ResponseDeviceAddress;\r
+  EFI_PHYSICAL_ADDRESS       InDataDeviceAddress;\r
+  EFI_PHYSICAL_ADDRESS       OutDataDeviceAddress;\r
+  VOID                       *InDataBuffer;\r
+  UINTN                      InDataNumPages;\r
+  BOOLEAN                    OutDataBufferIsMapped;\r
+\r
+  //\r
+  // Set InDataMapping,OutDataMapping,InDataDeviceAddress and OutDataDeviceAddress to\r
+  // suppress incorrect compiler/analyzer warnings.\r
+  //\r
+  InDataMapping        = NULL;\r
+  OutDataMapping       = NULL;\r
+  InDataDeviceAddress  = 0;\r
+  OutDataDeviceAddress = 0;\r
+\r
+  ZeroMem ((VOID *)&Request, sizeof (Request));\r
 \r
   Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);\r
   CopyMem (&TargetValue, Target, sizeof TargetValue);\r
 \r
+  InDataBuffer          = NULL;\r
+  OutDataBufferIsMapped = FALSE;\r
+  InDataNumPages        = 0;\r
+\r
   Status = PopulateRequest (Dev, TargetValue, Lun, Packet, &Request);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  VirtioPrepare (&Dev->Ring, &Indices);\r
+  //\r
+  // Map the virtio-scsi Request header buffer\r
+  //\r
+  Status = VirtioMapAllBytesInSharedBuffer (\r
+             Dev->VirtIo,\r
+             VirtioOperationBusMasterRead,\r
+             (VOID *)&Request,\r
+             sizeof Request,\r
+             &RequestDeviceAddress,\r
+             &RequestMapping\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return ReportHostAdapterError (Packet);\r
+  }\r
+\r
+  //\r
+  // Map the input buffer\r
+  //\r
+  if (Packet->InTransferLength > 0) {\r
+    //\r
+    // Allocate a intermediate input buffer. This is mainly to handle the\r
+    // following case:\r
+    //  * caller submits a bi-directional request\r
+    //  * we perform the request fine\r
+    //  * but we fail to unmap the "InDataMapping"\r
+    //\r
+    // In that case simply returning the EFI_DEVICE_ERROR is not sufficient. In\r
+    // addition to the error code we also need to update Packet fields\r
+    // accordingly so that we report the full loss of the incoming transfer.\r
+    //\r
+    // We allocate a temporary buffer and map it with BusMasterCommonBuffer. If\r
+    // the Virtio request is successful then we copy the data from temporary\r
+    // buffer into Packet->InDataBuffer.\r
+    //\r
+    InDataNumPages = EFI_SIZE_TO_PAGES ((UINTN)Packet->InTransferLength);\r
+    Status         = Dev->VirtIo->AllocateSharedPages (\r
+                                    Dev->VirtIo,\r
+                                    InDataNumPages,\r
+                                    &InDataBuffer\r
+                                    );\r
+    if (EFI_ERROR (Status)) {\r
+      Status = ReportHostAdapterError (Packet);\r
+      goto UnmapRequestBuffer;\r
+    }\r
+\r
+    ZeroMem (InDataBuffer, Packet->InTransferLength);\r
+\r
+    Status = VirtioMapAllBytesInSharedBuffer (\r
+               Dev->VirtIo,\r
+               VirtioOperationBusMasterCommonBuffer,\r
+               InDataBuffer,\r
+               Packet->InTransferLength,\r
+               &InDataDeviceAddress,\r
+               &InDataMapping\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      Status = ReportHostAdapterError (Packet);\r
+      goto FreeInDataBuffer;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Map the output buffer\r
+  //\r
+  if (Packet->OutTransferLength > 0) {\r
+    Status = VirtioMapAllBytesInSharedBuffer (\r
+               Dev->VirtIo,\r
+               VirtioOperationBusMasterRead,\r
+               Packet->OutDataBuffer,\r
+               Packet->OutTransferLength,\r
+               &OutDataDeviceAddress,\r
+               &OutDataMapping\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      Status = ReportHostAdapterError (Packet);\r
+      goto UnmapInDataBuffer;\r
+    }\r
+\r
+    OutDataBufferIsMapped = TRUE;\r
+  }\r
+\r
+  //\r
+  // Response header is bi-direction (we preset with host status and expect\r
+  // the device to update it). Allocate a response buffer which can be mapped\r
+  // to access equally by both processor and device.\r
+  //\r
+  Status = Dev->VirtIo->AllocateSharedPages (\r
+                          Dev->VirtIo,\r
+                          EFI_SIZE_TO_PAGES (sizeof *Response),\r
+                          &ResponseBuffer\r
+                          );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = ReportHostAdapterError (Packet);\r
+    goto UnmapOutDataBuffer;\r
+  }\r
+\r
+  Response = ResponseBuffer;\r
+\r
+  ZeroMem ((VOID *)Response, sizeof (*Response));\r
 \r
   //\r
   // preset a host status for ourselves that we do not accept as success\r
   //\r
-  Response.Response = VIRTIO_SCSI_S_FAILURE;\r
+  Response->Response = VIRTIO_SCSI_S_FAILURE;\r
+\r
+  //\r
+  // Map the response buffer with BusMasterCommonBuffer so that response\r
+  // buffer can be accessed by both host and device.\r
+  //\r
+  Status = VirtioMapAllBytesInSharedBuffer (\r
+             Dev->VirtIo,\r
+             VirtioOperationBusMasterCommonBuffer,\r
+             ResponseBuffer,\r
+             sizeof (*Response),\r
+             &ResponseDeviceAddress,\r
+             &ResponseMapping\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = ReportHostAdapterError (Packet);\r
+    goto FreeResponseBuffer;\r
+  }\r
+\r
+  VirtioPrepare (&Dev->Ring, &Indices);\r
 \r
   //\r
   // ensured by VirtioScsiInit() -- this predicate, in combination with the\r
@@ -451,63 +602,121 @@ VirtioScsiPassThru (
   //\r
   // enqueue Request\r
   //\r
-  VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,\r
-    VRING_DESC_F_NEXT, &Indices);\r
+  VirtioAppendDesc (\r
+    &Dev->Ring,\r
+    RequestDeviceAddress,\r
+    sizeof Request,\r
+    VRING_DESC_F_NEXT,\r
+    &Indices\r
+    );\r
 \r
   //\r
   // enqueue "dataout" if any\r
   //\r
   if (Packet->OutTransferLength > 0) {\r
-    VirtioAppendDesc (&Dev->Ring, (UINTN) Packet->OutDataBuffer,\r
-      Packet->OutTransferLength, VRING_DESC_F_NEXT, &Indices);\r
+    VirtioAppendDesc (\r
+      &Dev->Ring,\r
+      OutDataDeviceAddress,\r
+      Packet->OutTransferLength,\r
+      VRING_DESC_F_NEXT,\r
+      &Indices\r
+      );\r
   }\r
 \r
   //\r
   // enqueue Response, to be written by the host\r
   //\r
-  VirtioAppendDesc (&Dev->Ring, (UINTN) &Response, sizeof Response,\r
-    VRING_DESC_F_WRITE | (Packet->InTransferLength > 0 ?\r
-                          VRING_DESC_F_NEXT : 0),\r
-    &Indices);\r
+  VirtioAppendDesc (\r
+    &Dev->Ring,\r
+    ResponseDeviceAddress,\r
+    sizeof *Response,\r
+    VRING_DESC_F_WRITE | (Packet->InTransferLength > 0 ? VRING_DESC_F_NEXT : 0),\r
+    &Indices\r
+    );\r
 \r
   //\r
   // enqueue "datain" if any, to be written by the host\r
   //\r
   if (Packet->InTransferLength > 0) {\r
-    VirtioAppendDesc (&Dev->Ring, (UINTN) Packet->InDataBuffer,\r
-      Packet->InTransferLength, VRING_DESC_F_WRITE, &Indices);\r
+    VirtioAppendDesc (\r
+      &Dev->Ring,\r
+      InDataDeviceAddress,\r
+      Packet->InTransferLength,\r
+      VRING_DESC_F_WRITE,\r
+      &Indices\r
+      );\r
   }\r
 \r
   // If kicking the host fails, we must fake a host adapter error.\r
   // EFI_NOT_READY would save us the effort, but it would also suggest that the\r
   // caller retry.\r
   //\r
-  if (VirtioFlush (Dev->PciIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring,\r
-        &Indices) != EFI_SUCCESS) {\r
-    Packet->InTransferLength  = 0;\r
-    Packet->OutTransferLength = 0;\r
-    Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r
-    Packet->TargetStatus      = EFI_EXT_SCSI_STATUS_TARGET_GOOD;\r
-    Packet->SenseDataLength   = 0;\r
-    return EFI_DEVICE_ERROR;\r
+  if (VirtioFlush (\r
+        Dev->VirtIo,\r
+        VIRTIO_SCSI_REQUEST_QUEUE,\r
+        &Dev->Ring,\r
+        &Indices,\r
+        NULL\r
+        ) != EFI_SUCCESS)\r
+  {\r
+    Status = ReportHostAdapterError (Packet);\r
+    goto UnmapResponseBuffer;\r
   }\r
 \r
-  return ParseResponse (Packet, &Response);\r
-}\r
+  Status = ParseResponse (Packet, Response);\r
+\r
+  //\r
+  // If virtio request was successful and it was a CPU read request then we\r
+  // have used an intermediate buffer. Copy the data from intermediate buffer\r
+  // to the final buffer.\r
+  //\r
+  if (InDataBuffer != NULL) {\r
+    CopyMem (Packet->InDataBuffer, InDataBuffer, Packet->InTransferLength);\r
+  }\r
 \r
+UnmapResponseBuffer:\r
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, ResponseMapping);\r
+\r
+FreeResponseBuffer:\r
+  Dev->VirtIo->FreeSharedPages (\r
+                 Dev->VirtIo,\r
+                 EFI_SIZE_TO_PAGES (sizeof *Response),\r
+                 ResponseBuffer\r
+                 );\r
+\r
+UnmapOutDataBuffer:\r
+  if (OutDataBufferIsMapped) {\r
+    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, OutDataMapping);\r
+  }\r
+\r
+UnmapInDataBuffer:\r
+  if (InDataBuffer != NULL) {\r
+    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, InDataMapping);\r
+  }\r
+\r
+FreeInDataBuffer:\r
+  if (InDataBuffer != NULL) {\r
+    Dev->VirtIo->FreeSharedPages (Dev->VirtIo, InDataNumPages, InDataBuffer);\r
+  }\r
+\r
+UnmapRequestBuffer:\r
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RequestMapping);\r
+\r
+  return Status;\r
+}\r
 \r
 EFI_STATUS\r
 EFIAPI\r
 VirtioScsiGetNextTargetLun (\r
-  IN     EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
-  IN OUT UINT8                           **TargetPointer,\r
-  IN OUT UINT64                          *Lun\r
+  IN     EFI_EXT_SCSI_PASS_THRU_PROTOCOL  *This,\r
+  IN OUT UINT8                            **TargetPointer,\r
+  IN OUT UINT64                           *Lun\r
   )\r
 {\r
-  UINT8     *Target;\r
-  UINTN     Idx;\r
-  UINT16    LastTarget;\r
-  VSCSI_DEV *Dev;\r
+  UINT8      *Target;\r
+  UINTN      Idx;\r
+  UINT16     LastTarget;\r
+  VSCSI_DEV  *Dev;\r
 \r
   //\r
   // the TargetPointer input parameter is unnecessarily a pointer-to-pointer\r
@@ -517,8 +726,9 @@ VirtioScsiGetNextTargetLun (
   //\r
   // Search for first non-0xFF byte. If not found, return first target & LUN.\r
   //\r
-  for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx)\r
-    ;\r
+  for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx) {\r
+  }\r
+\r
   if (Idx == TARGET_MAX_BYTES) {\r
     SetMem (Target, TARGET_MAX_BYTES, 0x00);\r
     *Lun = 0;\r
@@ -534,7 +744,7 @@ VirtioScsiGetNextTargetLun (
   // increment (target, LUN) pair if valid on input\r
   //\r
   Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);\r
-  if (LastTarget > Dev->MaxTarget || *Lun > Dev->MaxLun) {\r
+  if ((LastTarget > Dev->MaxTarget) || (*Lun > Dev->MaxLun)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -553,19 +763,18 @@ VirtioScsiGetNextTargetLun (
   return EFI_NOT_FOUND;\r
 }\r
 \r
-\r
 EFI_STATUS\r
 EFIAPI\r
 VirtioScsiBuildDevicePath (\r
-  IN     EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
-  IN     UINT8                           *Target,\r
-  IN     UINT64                          Lun,\r
-  IN OUT EFI_DEVICE_PATH_PROTOCOL        **DevicePath\r
+  IN     EFI_EXT_SCSI_PASS_THRU_PROTOCOL  *This,\r
+  IN     UINT8                            *Target,\r
+  IN     UINT64                           Lun,\r
+  IN OUT EFI_DEVICE_PATH_PROTOCOL         **DevicePath\r
   )\r
 {\r
-  UINT16           TargetValue;\r
-  VSCSI_DEV        *Dev;\r
-  SCSI_DEVICE_PATH *ScsiDevicePath;\r
+  UINT16            TargetValue;\r
+  VSCSI_DEV         *Dev;\r
+  SCSI_DEVICE_PATH  *ScsiDevicePath;\r
 \r
   if (DevicePath == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -573,7 +782,7 @@ VirtioScsiBuildDevicePath (
 \r
   CopyMem (&TargetValue, Target, sizeof TargetValue);\r
   Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);\r
-  if (TargetValue > Dev->MaxTarget || Lun > Dev->MaxLun || Lun > 0xFFFF) {\r
+  if ((TargetValue > Dev->MaxTarget) || (Lun > Dev->MaxLun) || (Lun > 0xFFFF)) {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
@@ -584,43 +793,45 @@ VirtioScsiBuildDevicePath (
 \r
   ScsiDevicePath->Header.Type      = MESSAGING_DEVICE_PATH;\r
   ScsiDevicePath->Header.SubType   = MSG_SCSI_DP;\r
-  ScsiDevicePath->Header.Length[0] = (UINT8)  sizeof *ScsiDevicePath;\r
-  ScsiDevicePath->Header.Length[1] = (UINT8) (sizeof *ScsiDevicePath >> 8);\r
+  ScsiDevicePath->Header.Length[0] = (UINT8)sizeof *ScsiDevicePath;\r
+  ScsiDevicePath->Header.Length[1] = (UINT8)(sizeof *ScsiDevicePath >> 8);\r
   ScsiDevicePath->Pun              = TargetValue;\r
-  ScsiDevicePath->Lun              = (UINT16) Lun;\r
+  ScsiDevicePath->Lun              = (UINT16)Lun;\r
 \r
   *DevicePath = &ScsiDevicePath->Header;\r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 EFI_STATUS\r
 EFIAPI\r
 VirtioScsiGetTargetLun (\r
-  IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
-  IN  EFI_DEVICE_PATH_PROTOCOL        *DevicePath,\r
-  OUT UINT8                           **TargetPointer,\r
-  OUT UINT64                          *Lun\r
+  IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL  *This,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL         *DevicePath,\r
+  OUT UINT8                            **TargetPointer,\r
+  OUT UINT64                           *Lun\r
   )\r
 {\r
-  SCSI_DEVICE_PATH *ScsiDevicePath;\r
-  VSCSI_DEV        *Dev;\r
-  UINT8            *Target;\r
+  SCSI_DEVICE_PATH  *ScsiDevicePath;\r
+  VSCSI_DEV         *Dev;\r
+  UINT8             *Target;\r
 \r
-  if (DevicePath == NULL || TargetPointer == NULL || *TargetPointer == NULL ||\r
-      Lun == NULL) {\r
+  if ((DevicePath == NULL) || (TargetPointer == NULL) || (*TargetPointer == NULL) ||\r
+      (Lun == NULL))\r
+  {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (DevicePath->Type    != MESSAGING_DEVICE_PATH ||\r
-      DevicePath->SubType != MSG_SCSI_DP) {\r
+  if ((DevicePath->Type    != MESSAGING_DEVICE_PATH) ||\r
+      (DevicePath->SubType != MSG_SCSI_DP))\r
+  {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  ScsiDevicePath = (SCSI_DEVICE_PATH *) DevicePath;\r
-  Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);\r
-  if (ScsiDevicePath->Pun > Dev->MaxTarget ||\r
-      ScsiDevicePath->Lun > Dev->MaxLun) {\r
+  ScsiDevicePath = (SCSI_DEVICE_PATH *)DevicePath;\r
+  Dev            = VIRTIO_SCSI_FROM_PASS_THRU (This);\r
+  if ((ScsiDevicePath->Pun > Dev->MaxTarget) ||\r
+      (ScsiDevicePath->Lun > Dev->MaxLun))\r
+  {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
@@ -637,40 +848,37 @@ VirtioScsiGetTargetLun (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 EFI_STATUS\r
 EFIAPI\r
 VirtioScsiResetChannel (\r
-  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This\r
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL  *This\r
   )\r
 {\r
   return EFI_UNSUPPORTED;\r
 }\r
 \r
-\r
 EFI_STATUS\r
 EFIAPI\r
 VirtioScsiResetTargetLun (\r
-  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
-  IN UINT8                           *Target,\r
-  IN UINT64                          Lun\r
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL  *This,\r
+  IN UINT8                            *Target,\r
+  IN UINT64                           Lun\r
   )\r
 {\r
   return EFI_UNSUPPORTED;\r
 }\r
 \r
-\r
 EFI_STATUS\r
 EFIAPI\r
 VirtioScsiGetNextTarget (\r
-  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
-  IN OUT UINT8                       **TargetPointer\r
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL  *This,\r
+  IN OUT UINT8                        **TargetPointer\r
   )\r
 {\r
-  UINT8     *Target;\r
-  UINTN     Idx;\r
-  UINT16    LastTarget;\r
-  VSCSI_DEV *Dev;\r
+  UINT8      *Target;\r
+  UINTN      Idx;\r
+  UINT16     LastTarget;\r
+  VSCSI_DEV  *Dev;\r
 \r
   //\r
   // the TargetPointer input parameter is unnecessarily a pointer-to-pointer\r
@@ -680,8 +888,9 @@ VirtioScsiGetNextTarget (
   //\r
   // Search for first non-0xFF byte. If not found, return first target.\r
   //\r
-  for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx)\r
-    ;\r
+  for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx) {\r
+  }\r
+\r
   if (Idx == TARGET_MAX_BYTES) {\r
     SetMem (Target, TARGET_MAX_BYTES, 0x00);\r
     return EFI_SUCCESS;\r
@@ -709,39 +918,46 @@ VirtioScsiGetNextTarget (
   return EFI_NOT_FOUND;\r
 }\r
 \r
-\r
 STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 VirtioScsiInit (\r
-  IN OUT VSCSI_DEV *Dev\r
+  IN OUT VSCSI_DEV  *Dev\r
   )\r
 {\r
-  UINT8      NextDevStat;\r
-  EFI_STATUS Status;\r
-\r
-  UINT32     Features;\r
-  UINT16     MaxChannel; // for validation only\r
-  UINT32     NumQueues;  // for validation only\r
-  UINT16     QueueSize;\r
+  UINT8       NextDevStat;\r
+  EFI_STATUS  Status;\r
+  UINT64      RingBaseShift;\r
+  UINT64      Features;\r
+  UINT16      MaxChannel; // for validation only\r
+  UINT32      NumQueues;  // for validation only\r
+  UINT16      QueueSize;\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
@@ -749,16 +965,18 @@ VirtioScsiInit (
   //\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
-  Dev->InOutSupported = !!(Features & VIRTIO_SCSI_F_INOUT);\r
 \r
-  Status = VIRTIO_CFG_READ (Dev, VhdrMaxChannel, &MaxChannel);\r
+  Dev->InOutSupported = (BOOLEAN)((Features & VIRTIO_SCSI_F_INOUT) != 0);\r
+\r
+  Status = VIRTIO_CFG_READ (Dev, MaxChannel, &MaxChannel);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
+\r
   if (MaxChannel != 0) {\r
     //\r
     // this driver is for a single-channel virtio-scsi HBA\r
@@ -767,35 +985,39 @@ VirtioScsiInit (
     goto Failed;\r
   }\r
 \r
-  Status = VIRTIO_CFG_READ (Dev, VhdrNumQueues, &NumQueues);\r
+  Status = VIRTIO_CFG_READ (Dev, NumQueues, &NumQueues);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
+\r
   if (NumQueues < 1) {\r
     Status = EFI_UNSUPPORTED;\r
     goto Failed;\r
   }\r
 \r
-  Status = VIRTIO_CFG_READ (Dev, VhdrMaxTarget, &Dev->MaxTarget);\r
+  Status = VIRTIO_CFG_READ (Dev, MaxTarget, &Dev->MaxTarget);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
+\r
   if (Dev->MaxTarget > PcdGet16 (PcdVirtioScsiMaxTargetLimit)) {\r
     Dev->MaxTarget = PcdGet16 (PcdVirtioScsiMaxTargetLimit);\r
   }\r
 \r
-  Status = VIRTIO_CFG_READ (Dev, VhdrMaxLun, &Dev->MaxLun);\r
+  Status = VIRTIO_CFG_READ (Dev, MaxLun, &Dev->MaxLun);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
+\r
   if (Dev->MaxLun > PcdGet32 (PcdVirtioScsiMaxLunLimit)) {\r
     Dev->MaxLun = PcdGet32 (PcdVirtioScsiMaxLunLimit);\r
   }\r
 \r
-  Status = VIRTIO_CFG_READ (Dev, VhdrMaxSectors, &Dev->MaxSectors);\r
+  Status = VIRTIO_CFG_READ (Dev, MaxSectors, &Dev->MaxSectors);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
+\r
   if (Dev->MaxSectors < 2) {\r
     //\r
     // We must be able to halve it for bidirectional transfers\r
@@ -805,18 +1027,33 @@ VirtioScsiInit (
     goto Failed;\r
   }\r
 \r
+  Features &= VIRTIO_SCSI_F_INOUT | VIRTIO_F_VERSION_1 |\r
+              VIRTIO_F_IOMMU_PLATFORM;\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 request virtqueue\r
   //\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect,\r
-             VIRTIO_SCSI_REQUEST_QUEUE);\r
+  Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
-  Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize);\r
+\r
+  Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
+\r
   //\r
   // VirtioScsiPassThru() uses at most four descriptors\r
   //\r
@@ -825,52 +1062,82 @@ VirtioScsiInit (
     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
+  // 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 = VirtioRingMap (\r
+             Dev->VirtIo,\r
+             &Dev->Ring,\r
+             &RingBaseShift,\r
+             &Dev->RingMap\r
+             );\r
   if (EFI_ERROR (Status)) {\r
     goto ReleaseQueue;\r
   }\r
 \r
   //\r
-  // step 5 -- Report understood features and guest-tuneables. We want none of\r
-  // the known (or unknown) VIRTIO_SCSI_F_* or VIRTIO_F_* capabilities (see\r
-  // virtio-0.9.5, Appendices B and I), except bidirectional transfers.\r
+  // Additional steps for MMIO: align the queue appropriately, and set the\r
+  // size. If anything fails from here on, we must unmap the ring resources.\r
   //\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits,\r
-             Features & VIRTIO_SCSI_F_INOUT);\r
+  Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);\r
   if (EFI_ERROR (Status)) {\r
-    goto ReleaseQueue;\r
+    goto UnmapQueue;\r
+  }\r
+\r
+  Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);\r
+  if (EFI_ERROR (Status)) {\r
+    goto UnmapQueue;\r
+  }\r
+\r
+  //\r
+  // step 4c -- Report GPFN (guest-physical frame number) of queue.\r
+  //\r
+  Status = Dev->VirtIo->SetQueueAddress (\r
+                          Dev->VirtIo,\r
+                          &Dev->Ring,\r
+                          RingBaseShift\r
+                          );\r
+  if (EFI_ERROR (Status)) {\r
+    goto UnmapQueue;\r
+  }\r
+\r
+  //\r
+  // step 5 -- Report understood features and guest-tuneables.\r
+  //\r
+  if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {\r
+    Features &= ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM);\r
+    Status    = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);\r
+    if (EFI_ERROR (Status)) {\r
+      goto UnmapQueue;\r
+    }\r
   }\r
 \r
   //\r
   // We expect these maximum sizes from the host. Since they are\r
   // guest-negotiable, ask for them rather than just checking them.\r
   //\r
-  Status = VIRTIO_CFG_WRITE (Dev, VhdrCdbSize, VIRTIO_SCSI_CDB_SIZE);\r
+  Status = VIRTIO_CFG_WRITE (Dev, CdbSize, VIRTIO_SCSI_CDB_SIZE);\r
   if (EFI_ERROR (Status)) {\r
-    goto ReleaseQueue;\r
+    goto UnmapQueue;\r
   }\r
-  Status = VIRTIO_CFG_WRITE (Dev, VhdrSenseSize, VIRTIO_SCSI_SENSE_SIZE);\r
+\r
+  Status = VIRTIO_CFG_WRITE (Dev, SenseSize, VIRTIO_SCSI_SENSE_SIZE);\r
   if (EFI_ERROR (Status)) {\r
-    goto ReleaseQueue;\r
+    goto UnmapQueue;\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
+    goto UnmapQueue;\r
   }\r
 \r
   //\r
@@ -906,16 +1173,19 @@ VirtioScsiInit (
 \r
   return EFI_SUCCESS;\r
 \r
+UnmapQueue:\r
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);\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
   Dev->InOutSupported = FALSE;\r
   Dev->MaxTarget      = 0;\r
@@ -925,13 +1195,11 @@ Failed:
   return Status; // reached only via Failed above\r
 }\r
 \r
-\r
-\r
 STATIC\r
 VOID\r
 EFIAPI\r
 VirtioScsiUninit (\r
-  IN OUT VSCSI_DEV *Dev\r
+  IN OUT VSCSI_DEV  *Dev\r
   )\r
 {\r
   //\r
@@ -939,19 +1207,45 @@ VirtioScsiUninit (
   // 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
   Dev->InOutSupported = FALSE;\r
   Dev->MaxTarget      = 0;\r
   Dev->MaxLun         = 0;\r
   Dev->MaxSectors     = 0;\r
 \r
-  VirtioRingUninit (&Dev->Ring);\r
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);\r
+  VirtioRingUninit (Dev->VirtIo, &Dev->Ring);\r
 \r
-  SetMem (&Dev->PassThru,     sizeof Dev->PassThru,     0x00);\r
+  SetMem (&Dev->PassThru, sizeof Dev->PassThru, 0x00);\r
   SetMem (&Dev->PassThruMode, sizeof Dev->PassThruMode, 0x00);\r
 }\r
 \r
+//\r
+// Event notification function enqueued by ExitBootServices().\r
+//\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+VirtioScsiExitBoot (\r
+  IN  EFI_EVENT  Event,\r
+  IN  VOID       *Context\r
+  )\r
+{\r
+  VSCSI_DEV  *Dev;\r
+\r
+  DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));\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
 // Probe, start and stop functions of this driver, called by the DXE core for\r
@@ -964,130 +1258,102 @@ VirtioScsiUninit (
 // The implementation follows:\r
 // - Driver Writer's Guide for UEFI 2.3.1 v1.01\r
 //   - 5.1.3.4 OpenProtocol() and CloseProtocol()\r
-//   - 18      PCI Driver Design Guidelines\r
-//   - 18.3    PCI drivers\r
 // - UEFI Spec 2.3.1 + Errata C\r
 //   -  6.3 Protocol Handler Services\r
-//   - 13.4 EFI PCI I/O Protocol\r
 //\r
 \r
 EFI_STATUS\r
 EFIAPI\r
 VirtioScsiDriverBindingSupported (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
-  IN EFI_HANDLE                  DeviceHandle,\r
-  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   DeviceHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
   )\r
 {\r
-  EFI_STATUS          Status;\r
-  EFI_PCI_IO_PROTOCOL *PciIo;\r
-  PCI_TYPE00          Pci;\r
+  EFI_STATUS              Status;\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
+  // Attempt to open the device with the VirtIo set of interfaces. On success,\r
+  // the protocol is "instantiated" for the VirtIo device. Covers duplicate open\r
   // 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 == 0x08) ? EFI_SUCCESS : EFI_UNSUPPORTED;\r
+  if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_SCSI_HOST) {\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
-         This->DriverBindingHandle, DeviceHandle);\r
+  gBS->CloseProtocol (\r
+         DeviceHandle,\r
+         &gVirtioDeviceProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         DeviceHandle\r
+         );\r
   return Status;\r
 }\r
 \r
-\r
 EFI_STATUS\r
 EFIAPI\r
 VirtioScsiDriverBindingStart (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
-  IN EFI_HANDLE                  DeviceHandle,\r
-  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   DeviceHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
   )\r
 {\r
-  VSCSI_DEV  *Dev;\r
-  EFI_STATUS Status;\r
+  VSCSI_DEV   *Dev;\r
+  EFI_STATUS  Status;\r
 \r
-  Dev = (VSCSI_DEV *) AllocateZeroPool (sizeof *Dev);\r
+  Dev = (VSCSI_DEV *)AllocateZeroPool (sizeof *Dev);\r
   if (Dev == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
-                  (VOID **)&Dev->PciIo, This->DriverBindingHandle,\r
-                  DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);\r
+  Status = gBS->OpenProtocol (\r
+                  DeviceHandle,\r
+                  &gVirtioDeviceProtocolGuid,\r
+                  (VOID **)&Dev->VirtIo,\r
+                  This->DriverBindingHandle,\r
+                  DeviceHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
   if (EFI_ERROR (Status)) {\r
     goto FreeVirtioScsi;\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-scsi device.\r
   //\r
-  // For virtio-scsi 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 = VirtioScsiInit (Dev);\r
   if (EFI_ERROR (Status)) {\r
-    goto ClosePciIo;\r
+    goto CloseVirtIo;\r
   }\r
 \r
-  //\r
-  // PCI IO access granted, configure virtio-scsi device.\r
-  //\r
-  Status = VirtioScsiInit (Dev);\r
+  Status = gBS->CreateEvent (\r
+                  EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
+                  TPL_CALLBACK,\r
+                  &VirtioScsiExitBoot,\r
+                  Dev,\r
+                  &Dev->ExitBoot\r
+                  );\r
   if (EFI_ERROR (Status)) {\r
-    goto RestorePciAttributes;\r
+    goto UninitDev;\r
   }\r
 \r
   //\r
@@ -1095,25 +1361,31 @@ VirtioScsiDriverBindingStart (
   // interface.\r
   //\r
   Dev->Signature = VSCSI_SIG;\r
-  Status = gBS->InstallProtocolInterface (&DeviceHandle,\r
-                  &gEfiExtScsiPassThruProtocolGuid, EFI_NATIVE_INTERFACE,\r
-                  &Dev->PassThru);\r
+  Status         = gBS->InstallProtocolInterface (\r
+                          &DeviceHandle,\r
+                          &gEfiExtScsiPassThruProtocolGuid,\r
+                          EFI_NATIVE_INTERFACE,\r
+                          &Dev->PassThru\r
+                          );\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
   VirtioScsiUninit (Dev);\r
 \r
-RestorePciAttributes:\r
-  Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
-                Dev->OriginalPciAttributes, NULL);\r
-\r
-ClosePciIo:\r
-  gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
-         This->DriverBindingHandle, DeviceHandle);\r
+CloseVirtIo:\r
+  gBS->CloseProtocol (\r
+         DeviceHandle,\r
+         &gVirtioDeviceProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         DeviceHandle\r
+         );\r
 \r
 FreeVirtioScsi:\r
   FreePool (Dev);\r
@@ -1121,19 +1393,18 @@ FreeVirtioScsi:
   return Status;\r
 }\r
 \r
-\r
 EFI_STATUS\r
 EFIAPI\r
 VirtioScsiDriverBindingStop (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
-  IN EFI_HANDLE                  DeviceHandle,\r
-  IN UINTN                       NumberOfChildren,\r
-  IN EFI_HANDLE                  *ChildHandleBuffer\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   DeviceHandle,\r
+  IN UINTN                        NumberOfChildren,\r
+  IN EFI_HANDLE                   *ChildHandleBuffer\r
   )\r
 {\r
-  EFI_STATUS                      Status;\r
-  EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;\r
-  VSCSI_DEV                       *Dev;\r
+  EFI_STATUS                       Status;\r
+  EFI_EXT_SCSI_PASS_THRU_PROTOCOL  *PassThru;\r
+  VSCSI_DEV                        *Dev;\r
 \r
   Status = gBS->OpenProtocol (\r
                   DeviceHandle,                     // candidate device\r
@@ -1152,32 +1423,37 @@ VirtioScsiDriverBindingStop (
   //\r
   // Handle Stop() requests for in-use driver instances gracefully.\r
   //\r
-  Status = gBS->UninstallProtocolInterface (DeviceHandle,\r
-                  &gEfiExtScsiPassThruProtocolGuid, &Dev->PassThru);\r
+  Status = gBS->UninstallProtocolInterface (\r
+                  DeviceHandle,\r
+                  &gEfiExtScsiPassThruProtocolGuid,\r
+                  &Dev->PassThru\r
+                  );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  VirtioScsiUninit (Dev);\r
+  gBS->CloseEvent (Dev->ExitBoot);\r
 \r
-  Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
-                Dev->OriginalPciAttributes, NULL);\r
+  VirtioScsiUninit (Dev);\r
 \r
-  gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
-         This->DriverBindingHandle, DeviceHandle);\r
+  gBS->CloseProtocol (\r
+         DeviceHandle,\r
+         &gVirtioDeviceProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         DeviceHandle\r
+         );\r
 \r
   FreePool (Dev);\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 //\r
 // The static object that groups the Supported() (ie. probe), Start() and\r
 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata\r
 // C, 10.1 EFI Driver Binding Protocol.\r
 //\r
-STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {\r
+STATIC EFI_DRIVER_BINDING_PROTOCOL  gDriverBinding = {\r
   &VirtioScsiDriverBindingSupported,\r
   &VirtioScsiDriverBindingStart,\r
   &VirtioScsiDriverBindingStop,\r
@@ -1187,7 +1463,6 @@ STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
   NULL  // DriverBindingHandle, ditto\r
 };\r
 \r
-\r
 //\r
 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and\r
 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name\r
@@ -1201,20 +1476,20 @@ STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
 //\r
 \r
 STATIC\r
-EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {\r
+EFI_UNICODE_STRING_TABLE  mDriverNameTable[] = {\r
   { "eng;en", L"Virtio SCSI Host Driver" },\r
-  { NULL,     NULL                   }\r
+  { NULL,     NULL                       }\r
 };\r
 \r
 STATIC\r
-EFI_COMPONENT_NAME_PROTOCOL gComponentName;\r
+EFI_COMPONENT_NAME_PROTOCOL  gComponentName;\r
 \r
 EFI_STATUS\r
 EFIAPI\r
 VirtioScsiGetDriverName (\r
-  IN  EFI_COMPONENT_NAME_PROTOCOL *This,\r
-  IN  CHAR8                       *Language,\r
-  OUT CHAR16                      **DriverName\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
   )\r
 {\r
   return LookupUnicodeString2 (\r
@@ -1229,39 +1504,38 @@ VirtioScsiGetDriverName (
 EFI_STATUS\r
 EFIAPI\r
 VirtioScsiGetDeviceName (\r
-  IN  EFI_COMPONENT_NAME_PROTOCOL *This,\r
-  IN  EFI_HANDLE                  DeviceHandle,\r
-  IN  EFI_HANDLE                  ChildHandle,\r
-  IN  CHAR8                       *Language,\r
-  OUT CHAR16                      **ControllerName\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   DeviceHandle,\r
+  IN  EFI_HANDLE                   ChildHandle,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **ControllerName\r
   )\r
 {\r
   return EFI_UNSUPPORTED;\r
 }\r
 \r
 STATIC\r
-EFI_COMPONENT_NAME_PROTOCOL gComponentName = {\r
+EFI_COMPONENT_NAME_PROTOCOL  gComponentName = {\r
   &VirtioScsiGetDriverName,\r
   &VirtioScsiGetDeviceName,\r
   "eng" // SupportedLanguages, ISO 639-2 language codes\r
 };\r
 \r
 STATIC\r
-EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {\r
-  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)     &VirtioScsiGetDriverName,\r
-  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &VirtioScsiGetDeviceName,\r
+EFI_COMPONENT_NAME2_PROTOCOL  gComponentName2 = {\r
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&VirtioScsiGetDriverName,\r
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&VirtioScsiGetDeviceName,\r
   "en" // SupportedLanguages, RFC 4646 language codes\r
 };\r
 \r
-\r
 //\r
 // Entry point of this driver.\r
 //\r
 EFI_STATUS\r
 EFIAPI\r
 VirtioScsiEntryPoint (\r
-  IN EFI_HANDLE       ImageHandle,\r
-  IN EFI_SYSTEM_TABLE *SystemTable\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
   )\r
 {\r
   return EfiLibInstallDriverBindingComponentName2 (\r