Done and committed in SVN rev14980 and rev14981.

Thanks Laszlo, Jordan and Mark for your feedbacks and support.

> -----Original Message-----
> From: Jordan Justen [mailto:jljus...@gmail.com]
> Sent: 11 December 2013 17:02
> To: Laszlo Ersek; Olivier Martin
> Cc: edk2-devel@lists.sourceforge.net
> Subject: Re: [edk2] [PATCH v5 0/8] OvmfPkg/Arm*Pkg: Introduce and use
> the new VIRTIO_DEVICE_PROTOCOL protocol
> 
> 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.cl
> ktrk
> > _______________________________________________
> > 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