Patches 1-5 & 8 are committed as r14963-14968.

Olivier, can you review and commit Laszlo's patches 6 & 7 from v5?

Thanks,

-Jordan

On Wed, Nov 27, 2013 at 11:10 AM, Laszlo Ersek <ler...@redhat.com> wrote:
> Testing:
>
> - OvmfPkg, X64:
>   - VirtioNetDxe:
>     - PXE boot on libvirt's virtual network
>     - DataSource socket utility from AppPkg (guest to host)
>   - VirtioBlkDxe: booted
>     - Fedora 19
>     - Windows 2012 R2
>     - Windows 2008 R2 (SeaBIOS CSM build of OVMF)
>   - VirtioScsiDxe: booted
>     - RHEL-6
>
> - ArmVExpress-RTSM-AEMv8Ax4-foundation, Aarch64 Foundation model:
>   - VirtioBlkDxe: booted
>     - Linaro OpenEmbedded 13.10 image (semihosting + virtio-blk)
>     - Linaro OpenEmbedded 13.10 image (virtio-blk only)
>     - Fedora 19 image (with EFI stub, virtio-blk only)
>
> Notes:
> - Kept Olivier's C-u and S-o-b in the first place everywhere.
> - When I touched a patch, I added my changes below Olivier's S-o-b, and
>   added my own C-u and S-o-b too.
> - When I didn't touch a patch, and Jordan was explicitly OK with it (as
>   in, R-b), I added his R-b.
>
> Summary list of changes in v5 (in the order visible in the squashed diff
> below; patches contain broken out v4->v5 lists):
>
> - VirtioMmioDeviceLib.inf: drop UefiDriverEntryPoint library dependency
> - VirtioFlush(): update comment block in VirtioLib.[hc]; error code is
>   propagated from VirtIo->SetQueueNotify().
> - typo fix in VirtioMmioInstallDevice() comment block
> - add disclaimer (two instances) about the protocol being work in
>   progress
> - ensure / document that the VIRTIO_BLK_DEVICE_PATH structure must be
>   packed
> - fix whitespace damage in definition of "mVirtioBlockDevicePath"
> - plug MmioDevice leak in VirtioMmioUninstallDevice()
> - return EFI_INVALID_PARAMETER in VirtioMmioGetQueueAddress() if
>   QueueAddress is NULL
> - VirtioMmioSetQueueSize(): fix return value (it's a status code)
> - VirtioMmioSetPageSize(): check against EFI_PAGE_SIZE with "if" plus
>   EFI_UNSUPPORTED, rather than ASSERT()
> - VirtioMmioDeviceWrite(), VirtioMmioDeviceRead(): remove redundant
>   (FieldSize > 8) checks
> - VirtioBlkInit(): jump to Failed label if SetPageSize() fails
> - VirtioBlkInit(): fixup comment, and add error handling, near
>   SetQueueNum() call
> - VirtioBlkDriverBindingStart(): remove redundant (always false) check
>   for a subsystem device ID different from
>   VIRTIO_SUBSYSTEM_BLOCK_DEVICE; VirtioBlkDriverBindingSupported()
>   handles it already
> - VirtioNetGetFeatures(): update stale comment block
> - VirtioNetGetFeatures(): retrieve MAC address byte for byte (open-coded
>   loop)
> - VirtioNetDriverBindingStart(): remove redundant (always false) check
>   for a subsystem device ID different from
>   VIRTIO_SUBSYSTEM_NETWORK_CARD; VirtioNetDriverBindingSupported()
>   handles it already
> - VirtioNetInitRing(): call SetQueueNum() and SetQueueAlign() for proper
>   MMIO operation
> - VirtioNetInitialize(): fix destination error label for when
>   SetPageSize() fails
> - VirtioPciIoRead(): restore the original requirement that FieldSize
>   equal BufferSize exactly (not only divide it). The looping added in v4
>   did not match the comment block, and the only place that used it in v4
>   (ie. VirtioNetGetFeatures()) needs an open-coded loop anyway (will be
>   done in a later part of v5).
> - updated comment block on VirtioPciDeviceRead()
> - return EFI_UNSUPPORTED instead of failed ASSERT() in
>   VirtioPciSetPageSize()
> - VirtioScsi.c: fix comment block of
>   VIRTIO_CFG_WRITE()/VIRTIO_CFG_READ()
> - VirtioScsiInit(): fix destination error label for when SetPageSize()
>   fails
> - VirtioScsiInit(): call SetQueueNum() and SetQueueAlign() for proper
>   MMIO operation
>
> Changes not visible in the squashed diff (because the end result is the
> same in both v4 and v5):
>
> - ArmPlatformPkg/ArmVExpressPkg: Added the empty 'ArmFvpDxe' platform
>   UEFI driver:
>   - For uniformity, add the empty driver to
>     ArmVExpress-RTSM-AEMv8Ax4-foundation.* too in this patch, not just
>     ArmVExpress-RTSM-AEMv8Ax4.*. V4 added the empty driver to
>     ArmVExpress-RTSM-AEMv8Ax4-foundation.* not sooner than the next
>     patch, fusing it with other (= virtio) functionality. Let's split
>     these changes cleanly.
>
> - ArmPlatformPkg/ArmFvpDxe: Added Virtio Block support:
>   - the platform driver is added to all platform DSC and FDF files in
>     the previous patch; this patch focuses on virtio only
>
> Squashed diff between v4 and v5 (17 lines of context for readability):
>
>> diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf 
>> b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
>> index 126afec..2e266a9 100644
>> --- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
>> +++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
>> @@ -22,22 +22,21 @@
>>    VERSION_STRING                 = 1.0
>>    LIBRARY_CLASS                  = VirtioMmioDeviceLib
>>
>>  [Sources]
>>    VirtioMmioDevice.c
>>    VirtioMmioDeviceFunctions.c
>>
>>  [Packages]
>>    MdePkg/MdePkg.dec
>>    OvmfPkg/OvmfPkg.dec
>>
>>  [LibraryClasses]
>>    BaseMemoryLib
>>    DebugLib
>>    IoLib
>>    MemoryAllocationLib
>>    UefiBootServicesTableLib
>> -  UefiDriverEntryPoint
>>    UefiLib
>>
>>  [Protocols]
>>    gVirtioDeviceProtocolGuid          ## PRODUCES
>> diff --git a/OvmfPkg/Include/Library/VirtioLib.h 
>> b/OvmfPkg/Include/Library/VirtioLib.h
>> index df4fc62..36527a5 100644
>> --- a/OvmfPkg/Include/Library/VirtioLib.h
>> +++ b/OvmfPkg/Include/Library/VirtioLib.h
>> @@ -154,32 +154,32 @@ VirtioAppendDesc (
>>
>>  /**
>>
>>    Notify the host about the descriptor chain just built, and wait until the
>>    host processes it.
>>
>>    @param[in] VirtIo       The target virtio device to notify.
>>
>>    @param[in] VirtQueueId  Identifies the queue for the target device.
>>
>>    @param[in,out] Ring     The virtio ring with descriptors to submit.
>>
>>    @param[in] Indices      Indices->NextDescIdx is not accessed.
>>                            Indices->HeadDescIdx identifies the head 
>> descriptor
>>                            of the descriptor chain.
>>
>>
>> -  @return              Error code from VirtioWriteDevice() if it fails.
>> +  @return              Error code from VirtIo->SetQueueNotify() if it fails.
>>
>>    @retval EFI_SUCCESS  Otherwise, the host processed all descriptors.
>>
>>  **/
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioFlush (
>>    IN     VIRTIO_DEVICE_PROTOCOL *VirtIo,
>>    IN     UINT16                 VirtQueueId,
>>    IN OUT VRING                  *Ring,
>>    IN     DESC_INDICES           *Indices
>>    );
>>
>>  #endif // _VIRTIO_LIB_H_
>> diff --git a/OvmfPkg/Include/Library/VirtioMmioDeviceLib.h 
>> b/OvmfPkg/Include/Library/VirtioMmioDeviceLib.h
>> index ac71014..3f63a65 100644
>> --- a/OvmfPkg/Include/Library/VirtioMmioDeviceLib.h
>> +++ b/OvmfPkg/Include/Library/VirtioMmioDeviceLib.h
>> @@ -9,40 +9,41 @@
>>    distribution. The full text of the license may be found at
>>    http://opensource.org/licenses/bsd-license.php
>>
>>    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 
>> WITHOUT
>>    WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>>
>>  **/
>>
>>  #ifndef _VIRTIO_MMIO_DEVICE_LIB_H_
>>  #define _VIRTIO_MMIO_DEVICE_LIB_H_
>>
>>  /**
>>
>>    Initialize VirtIo Device and Install VIRTIO_DEVICE_PROTOCOL protocol
>>
>>    @param[in] BaseAddress  Base Address of the VirtIo MMIO Device
>>
>> -  @param[in] Handle       Handle of the device the driver should be 
>> attached to.
>> +  @param[in] Handle       Handle of the device the driver should be attached
>> +                          to.
>>
>>    @retval EFI_SUCCESS           The VirtIo Device has been installed
>>                                  successfully.
>>
>> -  @retval EFI_OUT_OF_RESOURCES  The function failed too allocate memory 
>> require
>> +  @retval EFI_OUT_OF_RESOURCES  The function failed to allocate memory 
>> required
>>                                  by the Virtio MMIO device initialization.
>>
>>    @retval EFI_UNSUPPORTED       BaseAddress does not point to a VirtIo MMIO
>>                                  device.
>>
>>    @return                       Status code returned by 
>> InstallProtocolInterface
>>                                  Boot Service function.
>>
>>  **/
>>  EFI_STATUS
>>  VirtioMmioInstallDevice (
>>    IN PHYSICAL_ADDRESS       BaseAddress,
>>    IN EFI_HANDLE             Handle
>>    );
>>
>>  /**
>>
>> diff --git a/OvmfPkg/Include/Protocol/VirtioDevice.h 
>> b/OvmfPkg/Include/Protocol/VirtioDevice.h
>> index 71541f8..a6bb516 100644
>> --- a/OvmfPkg/Include/Protocol/VirtioDevice.h
>> +++ b/OvmfPkg/Include/Protocol/VirtioDevice.h
>> @@ -1,22 +1,25 @@
>>  /** @file
>>    Virtio Device
>>
>>    Copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
>>
>> +  DISCLAIMER: the VIRTIO_DEVICE_PROTOCOL introduced here is a work in 
>> progress,
>> +  and should not be used outside of the EDK II tree.
>> +
>>    This program and the accompanying materials are licensed and made 
>> available
>>    under the terms and conditions of the BSD License which accompanies this
>>    distribution. The full text of the license may be found at
>>    http://opensource.org/licenses/bsd-license.php
>>
>>    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 
>> WITHOUT
>>    WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>>
>>  **/
>>
>>  #ifndef __VIRTIO_DEVICE_H__
>>  #define __VIRTIO_DEVICE_H__
>>
>>  // VirtIo Specification Revision: Major[31:24].Minor[23:16].Revision[15:0
>>  #define VIRTIO_SPEC_REVISION(major,minor,revision) \
>>    ((((major) & 0xFF) << 24) | (((minor) & 0xFF) << 16) | ((revision) & 
>> 0xFFFF))
>>
>> @@ -327,34 +330,37 @@ EFI_STATUS
>>    @param[in] DeviceStatus The 8-bit value for the Device status field
>>
>>    @retval EFI_SUCCESS         The data was written successfully.
>>    @retval EFI_UNSUPPORTED     The underlying IO device doesn't support the
>>                                provided address offset and write size.
>>  **/
>>  typedef
>>  EFI_STATUS
>>  (EFIAPI *VIRTIO_SET_DEVICE_STATUS) (
>>    IN VIRTIO_DEVICE_PROTOCOL  *This,
>>    IN UINT8                   DeviceStatus
>>    );
>>
>>
>>  ///
>>  ///  This protocol provides an abstraction over the VirtIo transport layer
>>  ///
>> +///  DISCLAIMER: this protocol is a work in progress, and should not be used
>> +///  outside of the EDK II tree.
>> +///
>>  struct _VIRTIO_DEVICE_PROTOCOL {
>>    /// VirtIo Specification Revision encoded with VIRTIO_SPEC_REVISION()
>>    UINT32                      Revision;
>>    /// From the Virtio Spec
>>    INT32                       SubSystemDeviceId;
>>
>>    VIRTIO_GET_DEVICE_FEATURES  GetDeviceFeatures;
>>    VIRTIO_SET_GUEST_FEATURES   SetGuestFeatures;
>>
>>    VIRTIO_GET_QUEUE_ADDRESS    GetQueueAddress;
>>    VIRTIO_SET_QUEUE_ADDRESS    SetQueueAddress;
>>
>>    VIRTIO_SET_QUEUE_SEL        SetQueueSel;
>>
>>    VIRTIO_SET_QUEUE_NOTIFY     SetQueueNotify;
>>
>>    VIRTIO_SET_QUEUE_ALIGN      SetQueueAlign;
>> diff --git a/ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.c 
>> b/ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.c
>> index 0cf5b7b..1885b69 100644
>> --- a/ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.c
>> +++ b/ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.c
>> @@ -5,56 +5,58 @@
>>    This program and the accompanying materials
>>    are licensed and made available under the terms and conditions of the BSD 
>> License
>>    which accompanies this distribution.  The full text of the license may be 
>> found at
>>    http://opensource.org/licenses/bsd-license.php
>>
>>    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>>    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
>> IMPLIED.
>>
>>  **/
>>
>>  #include <Library/UefiLib.h>
>>  #include <Library/VirtioMmioDeviceLib.h>
>>  #include <Library/DebugLib.h>
>>  #include <Library/UefiBootServicesTableLib.h>
>>
>>  #define ARM_FVP_BASE_VIRTIO_BLOCK_BASE    0x1c130000
>>
>> +#pragma pack(1)
>>  typedef struct {
>>    VENDOR_DEVICE_PATH                  Vendor;
>>    EFI_DEVICE_PATH_PROTOCOL            End;
>>  } VIRTIO_BLK_DEVICE_PATH;
>> +#pragma pack()
>>
>>  VIRTIO_BLK_DEVICE_PATH mVirtioBlockDevicePath =
>>  {
>>    {
>>      {
>>        HARDWARE_DEVICE_PATH,
>>        HW_VENDOR_DP,
>>        {
>>          (UINT8)( sizeof(VENDOR_DEVICE_PATH) ),
>>          (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8)
>>        }
>>      },
>>      EFI_CALLER_ID_GUID,
>>    },
>>    {
>>      END_DEVICE_PATH_TYPE,
>>      END_ENTIRE_DEVICE_PATH_SUBTYPE,
>> -        {
>> +    {
>>        sizeof (EFI_DEVICE_PATH_PROTOCOL),
>>        0
>>      }
>>    }
>>  };
>>
>>  EFI_STATUS
>>  EFIAPI
>>  ArmFvpInitialise (
>>    IN EFI_HANDLE         ImageHandle,
>>    IN EFI_SYSTEM_TABLE   *SystemTable
>>    )
>>  {
>>    EFI_STATUS              Status;
>>
>>    Status = gBS->InstallProtocolInterface (&ImageHandle,
>>                   &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE,
>> diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c 
>> b/OvmfPkg/Library/VirtioLib/VirtioLib.c
>> index 9bbd141..54cf225 100644
>> --- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
>> +++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
>> @@ -236,35 +236,35 @@ VirtioAppendDesc (
>>
>>  /**
>>
>>    Notify the host about the descriptor chain just built, and wait until the
>>    host processes it.
>>
>>    @param[in] VirtIo       The target virtio device to notify.
>>
>>    @param[in] VirtQueueId  Identifies the queue for the target device.
>>
>>    @param[in,out] Ring     The virtio ring with descriptors to submit.
>>
>>    @param[in] Indices      Indices->NextDescIdx is not accessed.
>>                            Indices->HeadDescIdx identifies the head 
>> descriptor
>>                            of the descriptor chain.
>>
>>
>> -  @return              Error code from VirtioWriteDevice() if it fails.
>> +  @return              Error code from VirtIo->SetQueueNotify() if it fails.
>>
>>    @retval EFI_SUCCESS  Otherwise, the host processed all descriptors.
>>
>>  **/
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioFlush (
>>    IN     VIRTIO_DEVICE_PROTOCOL *VirtIo,
>>    IN     UINT16                 VirtQueueId,
>>    IN OUT VRING                  *Ring,
>>    IN     DESC_INDICES           *Indices
>>    )
>>  {
>>    UINT16     NextAvailIdx;
>>    EFI_STATUS Status;
>>    UINTN      PollPeriodUsecs;
>>
>> diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c 
>> b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
>> index 4d8578e..7543e15 100644
>> --- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
>> +++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
>> @@ -185,20 +185,21 @@ VirtioMmioUninstallDevice (
>>    if (EFI_ERROR (Status)) {
>>      return Status;
>>    }
>>
>>    // Get the MMIO device from the VirtIo Device instance
>>    MmioDevice = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice);
>>
>>    // Uninstall the protocol interface
>>    Status = gBS->UninstallProtocolInterface (DeviceHandle,
>>        &gVirtioDeviceProtocolGuid, &MmioDevice->VirtioDevice
>>        );
>>    if (EFI_ERROR (Status)) {
>>      return Status;
>>    }
>>
>>    // Uninitialize the VirtIo Device
>>    VirtioMmioUninit (MmioDevice);
>> +  FreePool (MmioDevice);
>>
>>    return EFI_SUCCESS;
>>  }
>> diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c 
>> b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
>> index bcba062..068e1ed 100644
>> --- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
>> +++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
>> @@ -34,35 +34,35 @@ VirtioMmioGetDeviceFeatures (
>>    Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
>>
>>    *DeviceFeatures = VIRTIO_CFG_READ (Device, 
>> VIRTIO_MMIO_OFFSET_HOST_FEATURES);
>>
>>    return EFI_SUCCESS;
>>  }
>>
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioMmioGetQueueAddress (
>>    IN  VIRTIO_DEVICE_PROTOCOL *This,
>>    OUT UINT32                 *QueueAddress
>>    )
>>  {
>>    VIRTIO_MMIO_DEVICE *Device;
>>
>>    if (QueueAddress == NULL) {
>> -
>> +    return EFI_INVALID_PARAMETER;
>>    }
>>
>>    Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
>>
>>    *QueueAddress = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN);
>>
>>    return EFI_SUCCESS;
>>  }
>>
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioMmioGetQueueSize (
>>    IN  VIRTIO_DEVICE_PROTOCOL  *This,
>>    OUT UINT16                  *QueueNumMax
>>    )
>>  {
>>    VIRTIO_MMIO_DEVICE *Device;
>> @@ -95,35 +95,37 @@ VirtioMmioGetDeviceStatus (
>>
>>    *DeviceStatus = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_STATUS) & 
>> 0xFF;
>>
>>    return EFI_SUCCESS;
>>  }
>>
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioMmioSetQueueSize (
>>    VIRTIO_DEVICE_PROTOCOL *This,
>>    UINT16                  QueueSize
>>    )
>>  {
>>    VIRTIO_MMIO_DEVICE *Device;
>>
>>    Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
>>
>> -  return VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM, QueueSize);
>> +  VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM, QueueSize);
>> +
>> +  return EFI_SUCCESS;
>>  }
>>
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioMmioSetDeviceStatus (
>>    VIRTIO_DEVICE_PROTOCOL *This,
>>    UINT8                   DeviceStatus
>>    )
>>  {
>>    VIRTIO_MMIO_DEVICE *Device;
>>
>>    Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
>>
>>    VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_STATUS, DeviceStatus);
>>
>>    return EFI_SUCCESS;
>>  }
>> @@ -155,35 +157,37 @@ VirtioMmioSetQueueAlignment (
>>
>>    Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
>>
>>    VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_ALIGN, Alignment);
>>
>>    return EFI_SUCCESS;
>>  }
>>
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioMmioSetPageSize (
>>    VIRTIO_DEVICE_PROTOCOL *This,
>>    UINT32                  PageSize
>>    )
>>  {
>>    VIRTIO_MMIO_DEVICE *Device;
>>
>> -  ASSERT (PageSize == EFI_PAGE_SIZE);
>> +  if (PageSize != EFI_PAGE_SIZE) {
>> +    return EFI_UNSUPPORTED;
>> +  }
>>
>>    Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
>>
>>    VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE, PageSize);
>>
>>    return EFI_SUCCESS;
>>  }
>>
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioMmioSetQueueSel (
>>    VIRTIO_DEVICE_PROTOCOL *This,
>>    UINT16                  Sel
>>    )
>>  {
>>    VIRTIO_MMIO_DEVICE *Device;
>>
>> @@ -226,38 +230,34 @@ VirtioMmioSetGuestFeatures (
>>  }
>>
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioMmioDeviceWrite (
>>    IN VIRTIO_DEVICE_PROTOCOL *This,
>>    IN UINTN                  FieldOffset,
>>    IN UINTN                  FieldSize,
>>    IN UINT64                 Value
>>    )
>>  {
>>    UINTN                     DstBaseAddress;
>>    VIRTIO_MMIO_DEVICE       *Device;
>>
>>    Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
>>
>>    // Double-check fieldsize
>> -  if (FieldSize > 8) {
>> -    return EFI_INVALID_PARAMETER;
>> -  }
>> -
>>    if ((FieldSize != 1) && (FieldSize != 2) &&
>>        (FieldSize != 4) && (FieldSize != 8)) {
>>      return EFI_INVALID_PARAMETER;
>>    }
>>
>>    // Compute base address
>>    DstBaseAddress = Device->BaseAddress +
>>        VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;
>>
>>    //
>>    // The device-specific memory area of Virtio-MMIO can only be written in
>>    // byte accesses. This is not currently in the Virtio spec.
>>    //
>>    MmioWriteBuffer8 (DstBaseAddress, FieldSize, (UINT8*)&Value);
>>
>>    return EFI_SUCCESS;
>>  }
>> @@ -267,38 +267,34 @@ EFIAPI
>>  VirtioMmioDeviceRead (
>>    IN  VIRTIO_DEVICE_PROTOCOL    *This,
>>    IN  UINTN                     FieldOffset,
>>    IN  UINTN                     FieldSize,
>>    IN  UINTN                     BufferSize,
>>    OUT VOID                      *Buffer
>>    )
>>  {
>>    UINTN                     SrcBaseAddress;
>>    VIRTIO_MMIO_DEVICE       *Device;
>>
>>    Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
>>
>>    // Parameter validation
>>    ASSERT (FieldSize == BufferSize);
>>
>>    // Double-check fieldsize
>> -  if (FieldSize > 8) {
>> -    return EFI_INVALID_PARAMETER;
>> -  }
>> -
>>    if ((FieldSize != 1) && (FieldSize != 2) &&
>>        (FieldSize != 4) && (FieldSize != 8)) {
>>      return EFI_INVALID_PARAMETER;
>>    }
>>
>>    // Compute base address
>>    SrcBaseAddress = Device->BaseAddress +
>>        VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;
>>
>>    //
>>    // The device-specific memory area of Virtio-MMIO can only be read in
>>    // byte reads. This is not currently in the Virtio spec.
>>    //
>>    MmioReadBuffer8 (SrcBaseAddress, BufferSize, Buffer);
>>
>>    return EFI_SUCCESS;
>>  }
>> diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c 
>> b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
>> index 0dcb05c..e0be7b0 100644
>> --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
>> +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
>> @@ -608,35 +608,35 @@ VirtioBlkInit (
>>    NextDevStat |= VSTAT_ACK;    // step 2 -- acknowledge device presence
>>    Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
>>    if (EFI_ERROR (Status)) {
>>      goto Failed;
>>    }
>>
>>    NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
>>    Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
>>    if (EFI_ERROR (Status)) {
>>      goto Failed;
>>    }
>>
>>    //
>>    // Set Page Size - MMIO VirtIo Specific
>>    //
>>    Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);
>>    if (EFI_ERROR (Status)) {
>> -    goto ReleaseQueue;
>> +    goto Failed;
>>    }
>>
>>    //
>>    // step 4a -- retrieve and validate features
>>    //
>>    Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
>>    if (EFI_ERROR (Status)) {
>>      goto Failed;
>>    }
>>
>>    Status = VIRTIO_CFG_READ (Dev, Capacity, &NumSectors);
>>    if (EFI_ERROR (Status)) {
>>      goto Failed;
>>    }
>>    if (NumSectors == 0) {
>>      Status = EFI_UNSUPPORTED;
>>      goto Failed;
>> @@ -669,44 +669,49 @@ VirtioBlkInit (
>>      goto Failed;
>>    }
>>    Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);
>>    if (EFI_ERROR (Status)) {
>>      goto Failed;
>>    }
>>    if (QueueSize < 3) { // SynchronousRequest() uses at most three 
>> descriptors
>>      Status = EFI_UNSUPPORTED;
>>      goto Failed;
>>    }
>>
>>    Status = VirtioRingInit (QueueSize, &Dev->Ring);
>>    if (EFI_ERROR (Status)) {
>>      goto Failed;
>>    }
>>
>>    //
>> -  // Additional steps for MMIO: align the queue appropriately, and set the 
>> size
>> -  Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
>> +  // Additional steps for MMIO: align the queue appropriately, and set the
>> +  // size. If anything fails from here on, we must release the ring 
>> resources.
>> +  //
>> +  Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
>> +  if (EFI_ERROR (Status)) {
>> +    goto ReleaseQueue;
>> +  }
>> +
>>    Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);
>>    if (EFI_ERROR (Status)) {
>>      goto ReleaseQueue;
>>    }
>>
>>    //
>> -  // step 4c -- Report GPFN (guest-physical frame number) of queue. If 
>> anything
>> -  // fails from here on, we must release the ring resources.
>> +  // step 4c -- Report GPFN (guest-physical frame number) of queue.
>>    //
>>    Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,
>>        (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);
>>    if (EFI_ERROR (Status)) {
>>      goto ReleaseQueue;
>>    }
>>
>>
>>    //
>>    // step 5 -- Report understood features. There are no virtio-blk specific
>>    // features to negotiate in virtio-0.9.5, plus we do not want any of the
>>    // device-independent (known or unknown) VIRTIO_F_* capabilities (see
>>    // Appendix B).
>>    //
>>    Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, 0);
>>    if (EFI_ERROR (Status)) {
>>      goto ReleaseQueue;
>> @@ -827,38 +832,34 @@ VirtioBlkDriverBindingStart (
>>    )
>>  {
>>    VBLK_DEV   *Dev;
>>    EFI_STATUS Status;
>>
>>    Dev = (VBLK_DEV *) AllocateZeroPool (sizeof *Dev);
>>    if (Dev == NULL) {
>>      return EFI_OUT_OF_RESOURCES;
>>    }
>>
>>    Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
>>                    (VOID **)&Dev->VirtIo, This->DriverBindingHandle,
>>                    DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
>>    if (EFI_ERROR (Status)) {
>>      goto FreeVirtioBlk;
>>    }
>>
>> -  if (Dev->VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_BLOCK_DEVICE) {
>> -    return EFI_UNSUPPORTED;
>> -  }
>> -
>>    //
>>    // VirtIo access granted, configure virtio-blk device.
>>    //
>>    Status = VirtioBlkInit (Dev);
>>    if (EFI_ERROR (Status)) {
>>      goto CloseVirtIo;
>>    }
>>
>>    //
>>    // Setup complete, attempt to export the driver instance's BlockIo 
>> interface.
>>    //
>>    Dev->Signature = VBLK_SIG;
>>    Status = gBS->InstallProtocolInterface (&DeviceHandle,
>>                    &gEfiBlockIoProtocolGuid, EFI_NATIVE_INTERFACE,
>>                    &Dev->BlockIo);
>>    if (EFI_ERROR (Status)) {
>>      goto UninitDev;
>> diff --git a/OvmfPkg/VirtioNetDxe/DriverBinding.c 
>> b/OvmfPkg/VirtioNetDxe/DriverBinding.c
>> index 330f1f3..93995c6 100644
>> --- a/OvmfPkg/VirtioNetDxe/DriverBinding.c
>> +++ b/OvmfPkg/VirtioNetDxe/DriverBinding.c
>> @@ -35,51 +35,51 @@
>>
>>    Only VirtioNetSnpPopulate() may call this function.
>>
>>    If the function fails for any reason, the virtio-net device is moved to
>>    VSTAT_FAILED instead of being reset. This serves only informative purposes
>>    for the host side.
>>
>>    param[in,out] Dev                 The VNET_DEV structure being created for
>>                                      the virtio-net device.
>>    param[out] MacAddress             MAC address configured by the host.
>>    param[out] MediaPresentSupported  Link status is made available by the 
>> host.
>>    param[out] MediaPresent           If link status is made available by the
>>                                      host, the current link status is stored 
>> in
>>                                      *MediaPresent. Otherwise MediaPresent is
>>                                      unused.
>>
>>    @retval EFI_UNSUPPORTED           The host doesn't supply a MAC address.
>> -  @return                           Status codes from 
>> Dev->VirtIo->Io.Read(),
>> -                                    VIRTIO_CFG_READ() and 
>> VIRTIO_CFG_WRITE().
>> +  @return                           Status codes from VirtIo protocol 
>> members.
>>    @retval EFI_SUCCESS               Configuration values retrieved.
>>  */
>>  STATIC
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioNetGetFeatures (
>>    IN OUT  VNET_DEV        *Dev,
>>    OUT     EFI_MAC_ADDRESS *MacAddress,
>>    OUT     BOOLEAN         *MediaPresentSupported,
>>    OUT     BOOLEAN         *MediaPresent
>>    )
>>  {
>>    EFI_STATUS Status;
>>    UINT8      NextDevStat;
>>    UINT32     Features;
>> +  UINTN      MacIdx;
>>    UINT16     LinkStatus;
>>
>>    //
>>    // Interrogate the device for features (virtio-0.9.5, 2.2.1 Device
>>    // Initialization Sequence), but don't complete setting it up.
>>    //
>>    NextDevStat = 0;             // step 1 -- reset device
>>    Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
>>    if (EFI_ERROR (Status)) {
>>      return Status;
>>    }
>>
>>    NextDevStat |= VSTAT_ACK;    // step 2 -- acknowledge device presence
>>    Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
>>    if (EFI_ERROR (Status)) {
>>      goto YieldDevice;
>>    }
>> @@ -91,43 +91,44 @@ VirtioNetGetFeatures (
>>    }
>>
>>    //
>>    // step 4a -- retrieve and validate features
>>    //
>>    Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
>>    if (EFI_ERROR (Status)) {
>>      goto YieldDevice;
>>    }
>>
>>    //
>>    // get MAC address byte-wise
>>    //
>>    if ((Features & VIRTIO_NET_F_MAC) == 0) {
>>      Status = EFI_UNSUPPORTED;
>>      goto YieldDevice;
>>    }
>> -  Status = Dev->VirtIo->ReadDevice (Dev->VirtIo,
>> -                                    OFFSET_OF_VNET (Mac), // Offset
>> -                                    sizeof(UINT8),        // FieldSize
>> -                                    SIZE_OF_VNET (Mac),   // BufferSize
>> -                                    MacAddress            // Buffer
>> -                                    );
>> -
>> -  if (EFI_ERROR (Status)) {
>> -    goto YieldDevice;
>> +  for (MacIdx = 0; MacIdx < SIZE_OF_VNET (Mac); ++MacIdx) {
>> +    Status = Dev->VirtIo->ReadDevice (Dev->VirtIo,
>> +                            OFFSET_OF_VNET (Mac) + MacIdx, // Offset
>> +                            1,                             // FieldSize
>> +                            1,                             // BufferSize
>> +                            &MacAddress->Addr[MacIdx]      // Buffer
>> +                            );
>> +    if (EFI_ERROR (Status)) {
>> +      goto YieldDevice;
>> +    }
>>    }
>>
>>    //
>>    // check if link status is reported, and if so, what the link status is
>>    //
>>    if ((Features & VIRTIO_NET_F_STATUS) == 0) {
>>      *MediaPresentSupported = FALSE;
>>    }
>>    else {
>>      *MediaPresentSupported = TRUE;
>>      Status = VIRTIO_CFG_READ (Dev, LinkStatus, &LinkStatus);
>>      if (EFI_ERROR (Status)) {
>>        goto YieldDevice;
>>      }
>>      *MediaPresent = !!(LinkStatus & VIRTIO_NET_S_LINK_UP);
>>    }
>>
>> @@ -445,38 +446,34 @@ VirtioNetDriverBindingStart (
>>
>>    //
>>    // allocate space for the driver instance
>>    //
>>    Dev = (VNET_DEV *) AllocateZeroPool (sizeof *Dev);
>>    if (Dev == NULL) {
>>      return EFI_OUT_OF_RESOURCES;
>>    }
>>    Dev->Signature = VNET_SIG;
>>
>>    Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
>>                    (VOID **)&Dev->VirtIo, This->DriverBindingHandle,
>>                    DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
>>    if (EFI_ERROR (Status)) {
>>      goto FreeVirtioNet;
>>    }
>>
>> -  if (Dev->VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_NETWORK_CARD) {
>> -    return EFI_UNSUPPORTED;
>> -  }
>> -
>>    //
>>    // now we can run a basic one-shot virtio-net initialization required to
>>    // retrieve the MAC address
>>    //
>>    Status = VirtioNetSnpPopulate (Dev);
>>    if (EFI_ERROR (Status)) {
>>      goto CloseVirtIo;
>>    }
>>
>>    //
>>    // get the device path of the virtio-net device -- one-shot open
>>    //
>>    Status = gBS->OpenProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid,
>>                    (VOID **)&DevicePath, This->DriverBindingHandle,
>>                    DeviceHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
>>    if (EFI_ERROR (Status)) {
>>      goto Evacuate;
>> diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c 
>> b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
>> index 56a55db..8dcf9da 100644
>> --- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
>> +++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
>> @@ -65,41 +65,61 @@ VirtioNetInitRing (
>>    if (EFI_ERROR (Status)) {
>>      return Status;
>>    }
>>
>>    //
>>    // For each packet (RX and TX alike), we need two descriptors:
>>    // one for the virtio-net request header, and another one for the data
>>    //
>>    if (QueueSize < 2) {
>>      return EFI_UNSUPPORTED;
>>    }
>>    Status = VirtioRingInit (QueueSize, Ring);
>>    if (EFI_ERROR (Status)) {
>>      return Status;
>>    }
>>
>>    //
>> +  // Additional steps for MMIO: align the queue appropriately, and set the
>> +  // size. If anything fails from here on, we must release the ring 
>> resources.
>> +  //
>> +  Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
>> +  if (EFI_ERROR (Status)) {
>> +    goto ReleaseQueue;
>> +  }
>> +
>> +  Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);
>> +  if (EFI_ERROR (Status)) {
>> +    goto ReleaseQueue;
>> +  }
>> +
>> +  //
>>    // step 4c -- report GPFN (guest-physical frame number) of queue
>>    //
>>    Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,
>>        (UINTN) Ring->Base >> EFI_PAGE_SHIFT);
>>    if (EFI_ERROR (Status)) {
>> -    VirtioRingUninit (Ring);
>> +    goto ReleaseQueue;
>>    }
>> +
>> +  return EFI_SUCCESS;
>> +
>> +ReleaseQueue:
>> +  VirtioRingUninit (Ring);
>> +
>>    return Status;
>>  }
>>
>>
>>  /**
>>    Set up static scaffolding for the VirtioNetTransmit() and
>>    VirtioNetGetStatus() SNP methods.
>>
>>    This function may only be called by VirtioNetInitialize().
>>
>>    The structures laid out and resources configured include:
>>    - fully populate the TX queue with a static pattern of virtio descriptor
>>      chains,
>>    - tracking of heads of free descriptor chains from the above,
>>    - one common virtio-net request header (never modified by the host) for 
>> all
>>      pending TX packets,
>>    - select polling over TX interrupt.
>> @@ -368,35 +388,35 @@ VirtioNetInitialize (
>>    NextDevStat = VSTAT_ACK;    // step 2 -- acknowledge device presence
>>    Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
>>    if (EFI_ERROR (Status)) {
>>      goto InitFailed;
>>    }
>>
>>    NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
>>    Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
>>    if (EFI_ERROR (Status)) {
>>      goto DeviceFailed;
>>    }
>>
>>    //
>>    // Set Page Size - MMIO VirtIo Specific
>>    //
>>    Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);
>>    if (EFI_ERROR (Status)) {
>> -    goto ReleaseTxRing;
>> +    goto DeviceFailed;
>>    }
>>
>>    //
>>    // step 4a -- retrieve features. Note that we're past validating required
>>    // features in VirtioNetGetFeatures().
>>    //
>>    Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
>>    if (EFI_ERROR (Status)) {
>>      goto DeviceFailed;
>>    }
>>
>>    ASSERT (Features & VIRTIO_NET_F_MAC);
>>    ASSERT (Dev->Snm.MediaPresentSupported ==
>>      !!(Features & VIRTIO_NET_F_STATUS));
>>
>>    //
>>    // step 4b, 4c -- allocate and report virtqueues
>> diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c 
>> b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
>> index c513622..c03a273 100644
>> --- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
>> +++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
>> @@ -66,59 +66,60 @@ STATIC VIRTIO_DEVICE_PROTOCOL mDeviceProtocolTemplate = {
>>    @return  Status code returned by PciIo->Io.Read().
>>
>>  **/
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioPciIoRead (
>>    IN  VIRTIO_PCI_DEVICE         *Dev,
>>    IN  UINTN                     FieldOffset,
>>    IN  UINTN                     FieldSize,
>>    IN  UINTN                     BufferSize,
>>    OUT VOID                      *Buffer
>>    )
>>  {
>>    UINTN                     Count;
>>    EFI_PCI_IO_PROTOCOL_WIDTH Width;
>>    EFI_PCI_IO_PROTOCOL       *PciIo;
>>
>> -  // The BufferSize must be a multiple of FieldSize
>> -  ASSERT ((BufferSize % FieldSize) == 0);
>> +  ASSERT (FieldSize == BufferSize);
>>
>>    PciIo = Dev->PciIo;
>> -  Count = BufferSize / FieldSize;
>> +  Count = 1;
>>
>>    switch (FieldSize) {
>>      case 1:
>>        Width = EfiPciIoWidthUint8;
>>        break;
>>
>>      case 2:
>>        Width = EfiPciIoWidthUint16;
>>        break;
>>
>>      case 8:
>> +      //
>>        // The 64bit PCI I/O is broken down into two 32bit reads to prevent
>>        // any alignment or width issues.
>>        // The UEFI spec says under EFI_PCI_IO_PROTOCOL.Io.Write():
>>        //
>>        // The I/O operations are carried out exactly as requested. The caller
>>        // is responsible for any alignment and I/O width issues which the
>>        // bus, device, platform, or type of I/O might require. For example on
>> -      // some platforms, width requests of EfiPciIoWidthUint64 do not work
>> -      Count = Count * 2;
>> +      // some platforms, width requests of EfiPciIoWidthUint64 do not work.
>> +      //
>> +      Count = 2;
>>        // fall through
>>
>>      case 4:
>>        Width = EfiPciIoWidthUint32;
>>        break;
>>
>>      default:
>>        ASSERT (FALSE);
>>        return EFI_INVALID_PARAMETER;
>>    }
>>
>>    return PciIo->Io.Read (
>>                       PciIo,
>>                       Width,
>>                       PCI_BAR_IDX0,
>>                       FieldOffset,
>>                       Count,
>> diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c 
>> b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
>> index 586bec6..9c40fd9 100644
>> --- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
>> +++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
>> @@ -10,40 +10,40 @@
>>    under the terms and conditions of the BSD License which accompanies this
>>    distribution. The full text of the license may be found at
>>    http://opensource.org/licenses/bsd-license.php
>>
>>    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 
>> WITHOUT
>>    WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>>
>>  **/
>>  #include <Library/BaseMemoryLib.h>
>>  #include <Library/DebugLib.h>
>>  #include <Library/MemoryAllocationLib.h>
>>  #include <Library/UefiBootServicesTableLib.h>
>>  #include <Library/UefiLib.h>
>>  #include "VirtioPciDevice.h"
>>
>>  /**
>>
>> -  Read a word from Region 0 of the device specified by PciIo.
>> +  Read a word from Region 0 of the device specified by VirtIo Device 
>> protocol.
>>
>>    The function implements the ReadDevice protocol member of
>>    VIRTIO_DEVICE_PROTOCOL.
>>
>> -  @param[in] PciIo        Source PCI device.
>> +  @param[in] This         VirtIo Device protocol.
>>
>>    @param[in] FieldOffset  Source offset.
>>
>>    @param[in] FieldSize    Source field size, must be in { 1, 2, 4, 8 }.
>>
>>    @param[in] BufferSize   Number of bytes available in the target buffer. 
>> Must
>>                            equal FieldSize.
>>
>>    @param[out] Buffer      Target buffer.
>>
>>
>>    @return  Status code returned by PciIo->Io.Read().
>>
>>  **/
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioPciDeviceRead (
>> @@ -221,37 +221,35 @@ VirtioPciSetQueueSel (
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioPciSetQueueAlignment (
>>    VIRTIO_DEVICE_PROTOCOL *This,
>>    UINT32                  Alignment
>>    )
>>  {
>>    return EFI_SUCCESS;
>>  }
>>
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioPciSetPageSize (
>>    VIRTIO_DEVICE_PROTOCOL *This,
>>    UINT32                  PageSize
>>    )
>>  {
>> -  ASSERT (PageSize == EFI_PAGE_SIZE);
>> -
>> -  return EFI_SUCCESS;
>> +  return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
>>  }
>>
>>  EFI_STATUS
>>  EFIAPI
>>  VirtioPciSetQueueNotify (
>>    VIRTIO_DEVICE_PROTOCOL *This,
>>    UINT16                 Index
>>    )
>>  {
>>    VIRTIO_PCI_DEVICE *Dev;
>>
>>    Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
>>
>>    return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_NOTIFY, sizeof 
>> (UINT16),
>>        Index);
>>  }
>>
>> diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c 
>> b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
>> index 9702985..267f5f9 100644
>> --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
>> +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
>> @@ -36,42 +36,42 @@
>>    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 
>> WITHOUT
>>    WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>>
>>  **/
>>
>>  #include <IndustryStandard/VirtioScsi.h>
>>  #include <Library/BaseMemoryLib.h>
>>  #include <Library/DebugLib.h>
>>  #include <Library/MemoryAllocationLib.h>
>>  #include <Library/UefiBootServicesTableLib.h>
>>  #include <Library/UefiLib.h>
>>  #include <Library/VirtioLib.h>
>>
>>  #include "VirtioScsi.h"
>>
>>  /**
>>
>> -  Convenience macros to read and write region 0 IO space elements of the
>> -  virtio-scsi VirtIo device, for configuration purposes.
>> +  Convenience macros to read and write configuration elements of the
>> +  virtio-scsi VirtIo device.
>>
>>    The following macros make it possible to specify only the "core 
>> parameters"
>>    for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE()
>>    returns, the transaction will have been completed.
>>
>> -  @param[in] Dev       Pointer to the VirtIo Device Protocol
>> +  @param[in] Dev       Pointer to the VSCSI_DEV structure.
>>
>>    @param[in] Field     A field name from VSCSI_HDR, identifying the 
>> virtio-scsi
>>                         configuration item to access.
>>
>>    @param[in] Value     (VIRTIO_CFG_WRITE() only.) The value to write to the
>>                         selected configuration item.
>>
>>    @param[out] Pointer  (VIRTIO_CFG_READ() only.) The object to receive the
>>                         value read from the configuration item. Its type 
>> must be
>>                         one of UINT8, UINT16, UINT32, UINT64.
>>
>>
>>    @return  Status codes returned by Virtio->WriteDevice() / 
>> Virtio->ReadDevice().
>>
>>  **/
>>
>>  #define VIRTIO_CFG_WRITE(Dev, Field, Value)  ((Dev)->VirtIo->WriteDevice (  
>> \
>> @@ -724,35 +724,35 @@ VirtioScsiInit (
>>    NextDevStat |= VSTAT_ACK;    // step 2 -- acknowledge device presence
>>    Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
>>    if (EFI_ERROR (Status)) {
>>      goto Failed;
>>    }
>>
>>    NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
>>    Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
>>    if (EFI_ERROR (Status)) {
>>      goto Failed;
>>    }
>>
>>    //
>>    // Set Page Size - MMIO VirtIo Specific
>>    //
>>    Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);
>>    if (EFI_ERROR (Status)) {
>> -    goto ReleaseQueue;
>> +    goto Failed;
>>    }
>>
>>    //
>>    // step 4a -- retrieve and validate features
>>    //
>>    Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
>>    if (EFI_ERROR (Status)) {
>>      goto Failed;
>>    }
>>    Dev->InOutSupported = !!(Features & VIRTIO_SCSI_F_INOUT);
>>
>>    Status = VIRTIO_CFG_READ (Dev, MaxChannel, &MaxChannel);
>>    if (EFI_ERROR (Status)) {
>>      goto Failed;
>>    }
>>    if (MaxChannel != 0) {
>>      //
>> @@ -811,36 +811,49 @@ VirtioScsiInit (
>>    if (EFI_ERROR (Status)) {
>>      goto Failed;
>>    }
>>    //
>>    // VirtioScsiPassThru() uses at most four descriptors
>>    //
>>    if (QueueSize < 4) {
>>      Status = EFI_UNSUPPORTED;
>>      goto Failed;
>>    }
>>
>>    Status = VirtioRingInit (QueueSize, &Dev->Ring);
>>    if (EFI_ERROR (Status)) {
>>      goto Failed;
>>    }
>>
>>    //
>> -  // step 4c -- Report GPFN (guest-physical frame number) of queue. If 
>> anything
>> -  // fails from here on, we must release the ring resources.
>> +  // Additional steps for MMIO: align the queue appropriately, and set the
>> +  // size. If anything fails from here on, we must release the ring 
>> resources.
>> +  //
>> +  Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
>> +  if (EFI_ERROR (Status)) {
>> +    goto ReleaseQueue;
>> +  }
>> +
>> +  Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);
>> +  if (EFI_ERROR (Status)) {
>> +    goto ReleaseQueue;
>> +  }
>> +
>> +  //
>> +  // step 4c -- Report GPFN (guest-physical frame number) of queue.
>>    //
>>    Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,
>>        (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);
>>    if (EFI_ERROR (Status)) {
>>      goto ReleaseQueue;
>>    }
>>
>>    //
>>    // step 5 -- Report understood features and guest-tuneables. We want none 
>> of
>>    // the known (or unknown) VIRTIO_SCSI_F_* or VIRTIO_F_* capabilities (see
>>    // virtio-0.9.5, Appendices B and I), except bidirectional transfers.
>>    //
>>    Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo,
>>        Features & VIRTIO_SCSI_F_INOUT);
>>    if (EFI_ERROR (Status)) {
>>      goto ReleaseQueue;
>>    }
>
> Olivier Martin (8):
>   OvmfPkg/VirtioDevice.h: Introduced VIRTIO_DEVICE_PROTOCOL protocol
>   OvmfPkg/VirtioPciDeviceDxe: Implement VIRTIO_DEVICE_PROTOCOL for
>     VirtIo Devices over PCI
>   OvmfPkg/VirtioMmioDeviceLib: Implement VIRTIO_DEVICE_PROTOCOL for
>     VirtIo Devices over MMIO
>   OvmfPkg: Make the VirtIo devices use the new VIRTIO_DEVICE_PROTOCOL
>   OvmfPkg/Virtio.h: Removed definition of VIRTIO_HDR
>   ArmPlatformPkg/ArmVExpressPkg: Added the empty 'ArmFvpDxe' platform
>     UEFI driver
>   ArmPlatformPkg/ArmFvpDxe: Added Virtio Block support
>   OvmfPkg/Virtio: Removed VirtioReadDevice() / VirtIoWriteDevice()
>     functions
>
>  .../ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.inf         |  35 ++
>  .../VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf    |  42 ++
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.inf                 |   4 +-
>  OvmfPkg/VirtioNetDxe/VirtioNet.inf                 |   2 +-
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf  |  43 ++
>  OvmfPkg/VirtioScsiDxe/VirtioScsi.inf               |   2 +-
>  OvmfPkg/Include/IndustryStandard/Virtio.h          |  18 -
>  OvmfPkg/Include/IndustryStandard/VirtioBlk.h       |  21 +-
>  OvmfPkg/Include/IndustryStandard/VirtioNet.h       |  14 +-
>  OvmfPkg/Include/IndustryStandard/VirtioScsi.h      |  27 +-
>  OvmfPkg/Include/Library/VirtioLib.h                |  77 +--
>  OvmfPkg/Include/Library/VirtioMmioDeviceLib.h      |  66 ++
>  OvmfPkg/Include/Protocol/VirtioDevice.h            | 382 ++++++++++++
>  .../Library/VirtioMmioDeviceLib/VirtioMmioDevice.h | 147 +++++
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.h                   |  32 +-
>  OvmfPkg/VirtioNetDxe/VirtioNet.h                   |  26 +-
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h       | 166 +++++
>  OvmfPkg/VirtioScsiDxe/VirtioScsi.h                 |  24 +-
>  .../ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.c           |  75 +++
>  OvmfPkg/Library/VirtioLib/VirtioLib.c              | 158 +----
>  .../Library/VirtioMmioDeviceLib/VirtioMmioDevice.c | 205 +++++++
>  .../VirtioMmioDeviceFunctions.c                    | 300 +++++++++
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.c                   | 194 +++---
>  OvmfPkg/VirtioNetDxe/ComponentName.c               |   6 +-
>  OvmfPkg/VirtioNetDxe/DriverBinding.c               | 137 ++---
>  OvmfPkg/VirtioNetDxe/Events.c                      |   2 +-
>  OvmfPkg/VirtioNetDxe/SnpGetStatus.c                |   2 +-
>  OvmfPkg/VirtioNetDxe/SnpInitialize.c               |  59 +-
>  OvmfPkg/VirtioNetDxe/SnpReceive.c                  |  12 +-
>  OvmfPkg/VirtioNetDxe/SnpShutdown.c                 |   2 +-
>  OvmfPkg/VirtioNetDxe/SnpTransmit.c                 |  12 +-
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c       | 668 
> +++++++++++++++++++++
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c    | 283 +++++++++
>  OvmfPkg/VirtioScsiDxe/VirtioScsi.c                 | 192 +++---
>  .../ArmVExpress-RTSM-AEMv8Ax4-foundation.dsc       |  10 +
>  .../ArmVExpress-RTSM-AEMv8Ax4-foundation.fdf       |   6 +
>  .../ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4.dsc   |  10 +
>  .../ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4.fdf   |   8 +-
>  OvmfPkg/OvmfPkg.dec                                |   1 +
>  OvmfPkg/OvmfPkgIa32.dsc                            |   1 +
>  OvmfPkg/OvmfPkgIa32.fdf                            |   1 +
>  OvmfPkg/OvmfPkgIa32X64.dsc                         |   1 +
>  OvmfPkg/OvmfPkgIa32X64.fdf                         |   1 +
>  OvmfPkg/OvmfPkgX64.dsc                             |   1 +
>  OvmfPkg/OvmfPkgX64.fdf                             |   1 +
>  45 files changed, 2813 insertions(+), 663 deletions(-)
>  create mode 100644 ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.inf
>  create mode 100644 
> OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
>  create mode 100644 OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
>  create mode 100644 OvmfPkg/Include/Library/VirtioMmioDeviceLib.h
>  create mode 100644 OvmfPkg/Include/Protocol/VirtioDevice.h
>  create mode 100644 OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
>  create mode 100644 OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
>  create mode 100644 ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.c
>  create mode 100644 OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
>  create mode 100644 
> OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
>  create mode 100644 OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
>  create mode 100644 OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
>
> --
> 1.8.3.1
>
>
> ------------------------------------------------------------------------------
> Rapidly troubleshoot problems before they affect your business. Most IT
> organizations don't have a clear picture of how application performance
> affects their revenue. With AppDynamics, you get 100% visibility into your
> Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
> http://pubads.g.doubleclick.net/gampad/clk?id=84349351&iu=/4140/ostg.clktrk
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/edk2-devel

------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT 
organizations don't have a clear picture of how application performance 
affects their revenue. With AppDynamics, you get 100% visibility into your 
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to