summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>2012-10-12 18:53:58 +0000
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>2012-10-12 18:53:58 +0000
commit263559b87232826552c9e42c1652d9f9488c9870 (patch)
treef0d9f786a62b29531ba232de46abd9548c9a7075
parent6b28fe9ee8957c98b4c70c83560734196f43f92f (diff)
downloadedk2-263559b87232826552c9e42c1652d9f9488c9870.zip
edk2-263559b87232826552c9e42c1652d9f9488c9870.tar.gz
edk2-263559b87232826552c9e42c1652d9f9488c9870.tar.bz2
OvmfPkg: extract VirtioLib from VirtioBlkDxe
Introduce a new library called VirtioLib, for now only collecting the following reusable functions with as little changes as possible: - VirtioWrite() - VirtioRead() - VirtioRingInit() - VirtioRingUninit() - AppendDesc() Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13842 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--OvmfPkg/Include/Library/VirtioLib.h187
-rw-r--r--OvmfPkg/Library/VirtioLib/VirtioLib.c335
-rw-r--r--OvmfPkg/Library/VirtioLib/VirtioLib.inf34
-rw-r--r--OvmfPkg/OvmfPkgIa32.dsc1
-rw-r--r--OvmfPkg/OvmfPkgIa32X64.dsc1
-rw-r--r--OvmfPkg/OvmfPkgX64.dsc1
-rw-r--r--OvmfPkg/VirtioBlkDxe/VirtioBlk.c320
-rw-r--r--OvmfPkg/VirtioBlkDxe/VirtioBlk.inf1
8 files changed, 561 insertions, 319 deletions
diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h
new file mode 100644
index 0000000..95657a7
--- /dev/null
+++ b/OvmfPkg/Include/Library/VirtioLib.h
@@ -0,0 +1,187 @@
+/** @file
+
+ Declarations of utility functions used by virtio device drivers.
+
+ Copyright (C) 2012, Red Hat, Inc.
+
+ 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_LIB_H_
+#define _VIRTIO_LIB_H_
+
+#include <Protocol/PciIo.h>
+#include <IndustryStandard/Virtio.h>
+
+/**
+
+ Write a word into Region 0 of the device specified by PciIo.
+
+ Region 0 must be an iomem region. This is an internal function for the
+ driver-specific VIRTIO_CFG_WRITE() macros.
+
+ @param[in] PciIo Target PCI device.
+
+ @param[in] FieldOffset Destination offset.
+
+ @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
+
+ @param[in] Value Little endian value to write, converted to UINT64.
+ The least significant FieldSize bytes will be used.
+
+
+ @return Status code returned by PciIo->Io.Write().
+
+**/
+EFIAPI
+EFI_STATUS
+VirtioWrite (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINT64 Value
+ );
+
+
+/**
+
+ Read a word from Region 0 of the device specified by PciIo.
+
+ Region 0 must be an iomem region. This is an internal function for the
+ driver-specific VIRTIO_CFG_READ() macros.
+
+ @param[in] PciIo Source PCI device.
+
+ @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().
+
+**/
+EFIAPI
+EFI_STATUS
+VirtioRead (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+
+/**
+
+ Configure a virtio ring.
+
+ This function sets up internal storage (the guest-host communication area)
+ and lays out several "navigation" (ie. no-ownership) pointers to parts of
+ that storage.
+
+ Relevant sections from the virtio-0.9.5 spec:
+ - 1.1 Virtqueues,
+ - 2.3 Virtqueue Configuration.
+
+ @param[in] The number of descriptors to allocate for the
+ virtio ring, as requested by the host.
+
+ @param[out] Ring The virtio ring to set up.
+
+ @retval EFI_OUT_OF_RESOURCES AllocatePages() failed to allocate contiguous
+ pages for the requested QueueSize. Fields of
+ Ring have indeterminate value.
+
+ @retval EFI_SUCCESS Allocation and setup successful. Ring->Base
+ (and nothing else) is responsible for
+ deallocation.
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioRingInit (
+ IN UINT16 QueueSize,
+ OUT VRING *Ring
+ );
+
+
+/**
+
+ Tear down the internal resources of a configured virtio ring.
+
+ The caller is responsible to stop the host from using this ring before
+ invoking this function: the VSTAT_DRIVER_OK bit must be clear in
+ VhdrDeviceStatus.
+
+ @param[out] Ring The virtio ring to clean up.
+
+**/
+VOID
+EFIAPI
+VirtioRingUninit (
+ IN OUT VRING *Ring
+ );
+
+
+/**
+
+ Append a contiguous buffer for transmission / reception via the virtio ring.
+
+ This function implements the following sections from virtio-0.9.5:
+ - 2.4.1.1 Placing Buffers into the Descriptor Table
+ - 2.4.1.2 Updating the Available Ring
+
+ Free space is taken as granted, since the individual drivers support only
+ synchronous requests and host side status is processed in lock-step with
+ request submission. It is the calling driver's responsibility to verify the
+ ring size in advance.
+
+ @param[in out] Ring The virtio ring to append the buffer to, as a
+ descriptor.
+
+ @param [in] BufferPhysAddr (Guest pseudo-physical) start address of the
+ transmit / receive buffer.
+
+ @param [in] BufferSize Number of bytes to transmit or receive.
+
+ @param [in] Flags A bitmask of VRING_DESC_F_* flags. The caller
+ computes this mask dependent on further buffers
+ to append and transfer direction.
+ VRING_DESC_F_INDIRECT is unsupported. The
+ VRING_DESC.Next field is always set, but the
+ host only interprets it dependent on
+ VRING_DESC_F_NEXT.
+
+ @param [in] HeadIdx The index identifying the head buffer (first
+ buffer appended) belonging to this same
+ request.
+
+ @param [in out] NextAvailIdx On input, the index identifying the next
+ descriptor available to carry the buffer. On
+ output, incremented by one, modulo 2^16.
+
+**/
+VOID
+EFIAPI
+AppendDesc (
+ IN OUT VRING *Ring,
+ IN UINTN BufferPhysAddr,
+ IN UINT32 BufferSize,
+ IN UINT16 Flags,
+ IN UINT16 HeadIdx,
+ IN OUT UINT16 *NextAvailIdx
+ );
+
+#endif // _VIRTIO_LIB_H_
diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
new file mode 100644
index 0000000..5808242
--- /dev/null
+++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
@@ -0,0 +1,335 @@
+/** @file
+
+ Utility functions used by virtio device drivers.
+
+ Copyright (C) 2012, Red Hat, Inc.
+
+ 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 <IndustryStandard/Pci22.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Library/VirtioLib.h>
+
+
+/**
+
+ Write a word into Region 0 of the device specified by PciIo.
+
+ Region 0 must be an iomem region. This is an internal function for the
+ driver-specific VIRTIO_CFG_WRITE() macros.
+
+ @param[in] PciIo Target PCI device.
+
+ @param[in] FieldOffset Destination offset.
+
+ @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
+
+ @param[in] Value Little endian value to write, converted to UINT64.
+ The least significant FieldSize bytes will be used.
+
+
+ @return Status code returned by PciIo->Io.Write().
+
+**/
+EFIAPI
+EFI_STATUS
+VirtioWrite (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINT64 Value
+ )
+{
+ UINTN Count;
+ EFI_PCI_IO_PROTOCOL_WIDTH Width;
+
+ Count = 1;
+ switch (FieldSize) {
+ case 1:
+ Width = EfiPciIoWidthUint8;
+ break;
+
+ case 2:
+ Width = EfiPciIoWidthUint16;
+ break;
+
+ case 8:
+ Count = 2;
+ // fall through
+
+ case 4:
+ Width = EfiPciIoWidthUint32;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return PciIo->Io.Write (
+ PciIo,
+ Width,
+ PCI_BAR_IDX0,
+ FieldOffset,
+ Count,
+ &Value
+ );
+}
+
+
+/**
+
+ Read a word from Region 0 of the device specified by PciIo.
+
+ Region 0 must be an iomem region. This is an internal function for the
+ driver-specific VIRTIO_CFG_READ() macros.
+
+ @param[in] PciIo Source PCI device.
+
+ @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().
+
+**/
+EFIAPI
+EFI_STATUS
+VirtioRead (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ UINTN Count;
+ EFI_PCI_IO_PROTOCOL_WIDTH Width;
+
+ ASSERT (FieldSize == BufferSize);
+
+ Count = 1;
+ switch (FieldSize) {
+ case 1:
+ Width = EfiPciIoWidthUint8;
+ break;
+
+ case 2:
+ Width = EfiPciIoWidthUint16;
+ break;
+
+ case 8:
+ Count = 2;
+ // fall through
+
+ case 4:
+ Width = EfiPciIoWidthUint32;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return PciIo->Io.Read (
+ PciIo,
+ Width,
+ PCI_BAR_IDX0,
+ FieldOffset,
+ Count,
+ Buffer
+ );
+}
+
+
+/**
+
+ Configure a virtio ring.
+
+ This function sets up internal storage (the guest-host communication area)
+ and lays out several "navigation" (ie. no-ownership) pointers to parts of
+ that storage.
+
+ Relevant sections from the virtio-0.9.5 spec:
+ - 1.1 Virtqueues,
+ - 2.3 Virtqueue Configuration.
+
+ @param[in] The number of descriptors to allocate for the
+ virtio ring, as requested by the host.
+
+ @param[out] Ring The virtio ring to set up.
+
+ @retval EFI_OUT_OF_RESOURCES AllocatePages() failed to allocate contiguous
+ pages for the requested QueueSize. Fields of
+ Ring have indeterminate value.
+
+ @retval EFI_SUCCESS Allocation and setup successful. Ring->Base
+ (and nothing else) is responsible for
+ deallocation.
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioRingInit (
+ IN UINT16 QueueSize,
+ OUT VRING *Ring
+ )
+{
+ UINTN RingSize;
+ volatile UINT8 *RingPagesPtr;
+
+ RingSize = ALIGN_VALUE (
+ sizeof *Ring->Desc * QueueSize +
+ sizeof *Ring->Avail.Flags +
+ sizeof *Ring->Avail.Idx +
+ sizeof *Ring->Avail.Ring * QueueSize +
+ sizeof *Ring->Avail.UsedEvent,
+ EFI_PAGE_SIZE);
+
+ RingSize += ALIGN_VALUE (
+ sizeof *Ring->Used.Flags +
+ sizeof *Ring->Used.Idx +
+ sizeof *Ring->Used.UsedElem * QueueSize +
+ sizeof *Ring->Used.AvailEvent,
+ EFI_PAGE_SIZE);
+
+ Ring->NumPages = EFI_SIZE_TO_PAGES (RingSize);
+ Ring->Base = AllocatePages (Ring->NumPages);
+ if (Ring->Base == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ SetMem (Ring->Base, RingSize, 0x00);
+ RingPagesPtr = Ring->Base;
+
+ Ring->Desc = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Desc * QueueSize;
+
+ Ring->Avail.Flags = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Avail.Flags;
+
+ Ring->Avail.Idx = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Avail.Idx;
+
+ Ring->Avail.Ring = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Avail.Ring * QueueSize;
+
+ Ring->Avail.UsedEvent = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Avail.UsedEvent;
+
+ RingPagesPtr = (volatile UINT8 *) Ring->Base +
+ ALIGN_VALUE (RingPagesPtr - (volatile UINT8 *) Ring->Base,
+ EFI_PAGE_SIZE);
+
+ Ring->Used.Flags = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Used.Flags;
+
+ Ring->Used.Idx = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Used.Idx;
+
+ Ring->Used.UsedElem = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Used.UsedElem * QueueSize;
+
+ Ring->Used.AvailEvent = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Used.AvailEvent;
+
+ Ring->QueueSize = QueueSize;
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Tear down the internal resources of a configured virtio ring.
+
+ The caller is responsible to stop the host from using this ring before
+ invoking this function: the VSTAT_DRIVER_OK bit must be clear in
+ VhdrDeviceStatus.
+
+ @param[out] Ring The virtio ring to clean up.
+
+**/
+VOID
+EFIAPI
+VirtioRingUninit (
+ IN OUT VRING *Ring
+ )
+{
+ FreePages (Ring->Base, Ring->NumPages);
+ SetMem (Ring, sizeof *Ring, 0x00);
+}
+
+
+/**
+
+ Append a contiguous buffer for transmission / reception via the virtio ring.
+
+ This function implements the following sections from virtio-0.9.5:
+ - 2.4.1.1 Placing Buffers into the Descriptor Table
+ - 2.4.1.2 Updating the Available Ring
+
+ Free space is taken as granted, since the individual drivers support only
+ synchronous requests and host side status is processed in lock-step with
+ request submission. It is the calling driver's responsibility to verify the
+ ring size in advance.
+
+ @param[in out] Ring The virtio ring to append the buffer to, as a
+ descriptor.
+
+ @param [in] BufferPhysAddr (Guest pseudo-physical) start address of the
+ transmit / receive buffer.
+
+ @param [in] BufferSize Number of bytes to transmit or receive.
+
+ @param [in] Flags A bitmask of VRING_DESC_F_* flags. The caller
+ computes this mask dependent on further buffers
+ to append and transfer direction.
+ VRING_DESC_F_INDIRECT is unsupported. The
+ VRING_DESC.Next field is always set, but the
+ host only interprets it dependent on
+ VRING_DESC_F_NEXT.
+
+ @param [in] HeadIdx The index identifying the head buffer (first
+ buffer appended) belonging to this same
+ request.
+
+ @param [in out] NextAvailIdx On input, the index identifying the next
+ descriptor available to carry the buffer. On
+ output, incremented by one, modulo 2^16.
+
+**/
+VOID
+EFIAPI
+AppendDesc (
+ IN OUT VRING *Ring,
+ IN UINTN BufferPhysAddr,
+ IN UINT32 BufferSize,
+ IN UINT16 Flags,
+ IN UINT16 HeadIdx,
+ IN OUT UINT16 *NextAvailIdx
+ )
+{
+ volatile VRING_DESC *Desc;
+
+ Desc = &Ring->Desc[*NextAvailIdx % Ring->QueueSize];
+ Desc->Addr = BufferPhysAddr;
+ Desc->Len = BufferSize;
+ Desc->Flags = Flags;
+ Ring->Avail.Ring[(*NextAvailIdx)++ % Ring->QueueSize] =
+ HeadIdx % Ring->QueueSize;
+ Desc->Next = *NextAvailIdx % Ring->QueueSize;
+}
diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.inf b/OvmfPkg/Library/VirtioLib/VirtioLib.inf
new file mode 100644
index 0000000..cfd93a2
--- /dev/null
+++ b/OvmfPkg/Library/VirtioLib/VirtioLib.inf
@@ -0,0 +1,34 @@
+## @file
+# Library of virtio utility functions.
+#
+# Copyright (C) 2012, Red Hat, Inc.
+#
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = VirtioLib
+ FILE_GUID = 90CED1D9-18F2-47CC-BF24-41EC29406637
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = VirtioLib
+
+[Sources]
+ VirtioLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 16037b3..d0c6329 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -97,6 +97,7 @@
UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
+ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
!ifdef $(SOURCE_DEBUG_ENABLE)
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index f73f079..b442314 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -102,6 +102,7 @@
UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
+ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
!ifdef $(SOURCE_DEBUG_ENABLE)
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 97d4ec8..11f90a4 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -102,6 +102,7 @@
UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
+ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
!ifdef $(SOURCE_DEBUG_ENABLE)
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index ead9827..eeeb4be 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -29,148 +29,12 @@
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
+#include <Library/VirtioLib.h>
#include "VirtioBlk.h"
/**
- Write a word into Region 0 of the device specified by PciIo.
-
- Region 0 must be an iomem region. This is an internal function for the
- VIRTIO_CFG_WRITE() macro below.
-
- @param[in] PciIo Target PCI device.
-
- @param[in] FieldOffset Destination offset.
-
- @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
-
- @param[in] Value Little endian value to write, converted to UINT64.
- The least significant FieldSize bytes will be used.
-
-
- @return Status code returned by PciIo->Io.Write().
-
-**/
-STATIC
-EFIAPI
-EFI_STATUS
-VirtioWrite (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINTN FieldOffset,
- IN UINTN FieldSize,
- IN UINT64 Value
- )
-{
- UINTN Count;
- EFI_PCI_IO_PROTOCOL_WIDTH Width;
-
- Count = 1;
- switch (FieldSize) {
- case 1:
- Width = EfiPciIoWidthUint8;
- break;
-
- case 2:
- Width = EfiPciIoWidthUint16;
- break;
-
- case 8:
- Count = 2;
- // fall through
-
- case 4:
- Width = EfiPciIoWidthUint32;
- break;
-
- default:
- ASSERT (FALSE);
- }
-
- return PciIo->Io.Write (
- PciIo,
- Width,
- PCI_BAR_IDX0,
- FieldOffset,
- Count,
- &Value
- );
-}
-
-
-/**
-
- Read a word from Region 0 of the device specified by PciIo.
-
- Region 0 must be an iomem region. This is an internal function for the
- VIRTIO_CFG_READ() macro below.
-
- @param[in] PciIo Source PCI device.
-
- @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().
-
-**/
-STATIC
-EFIAPI
-EFI_STATUS
-VirtioRead (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINTN FieldOffset,
- IN UINTN FieldSize,
- IN UINTN BufferSize,
- OUT VOID *Buffer
- )
-{
- UINTN Count;
- EFI_PCI_IO_PROTOCOL_WIDTH Width;
-
- ASSERT (FieldSize == BufferSize);
-
- Count = 1;
- switch (FieldSize) {
- case 1:
- Width = EfiPciIoWidthUint8;
- break;
-
- case 2:
- Width = EfiPciIoWidthUint16;
- break;
-
- case 8:
- Count = 2;
- // fall through
-
- case 4:
- Width = EfiPciIoWidthUint32;
- break;
-
- default:
- ASSERT (FALSE);
- }
-
- return PciIo->Io.Read (
- PciIo,
- Width,
- PCI_BAR_IDX0,
- FieldOffset,
- Count,
- Buffer
- );
-}
-
-
-/**
-
Convenience macros to read and write region 0 IO space elements of the
virtio-blk PCI device, for configuration purposes.
@@ -314,66 +178,6 @@ VerifyReadWriteRequest (
}
-/**
-
- Append a contiguous buffer for transmission / reception via the virtio ring.
-
- This function implements the following sections from virtio-0.9.5:
- - 2.4.1.1 Placing Buffers into the Descriptor Table
- - 2.4.1.2 Updating the Available Ring
-
- Free space is taken as granted, since this driver supports only synchronous
- requests and host side status is processed in lock-step with request
- submission. VirtioBlkInit() verifies the ring size in advance.
-
- @param[in out] Ring The virtio ring to append the buffer to, as a
- descriptor.
-
- @param [in] BufferPhysAddr (Guest pseudo-physical) start address of the
- transmit / receive buffer
-
- @param [in] BufferSize Number of bytes to transmit or receive.
-
- @param [in] Flags A bitmask of VRING_DESC_F_* flags. The caller
- computes this mask dependent on further buffers
- to append and transfer direction.
- VRING_DESC_F_INDIRECT is unsupported. The
- VRING_DESC.Next field is always set, but the
- host only interprets it dependent on
- VRING_DESC_F_NEXT.
-
- @param [in] HeadIdx The index identifying the head buffer (first
- buffer appended) belonging to this same
- request.
-
- @param [in out] NextAvailIdx On input, the index identifying the next
- descriptor available to carry the buffer. On
- output, incremented by one, modulo 2^16.
-
-**/
-
-STATIC
-VOID
-EFIAPI
-AppendDesc (
- IN OUT VRING *Ring,
- IN UINTN BufferPhysAddr,
- IN UINT32 BufferSize,
- IN UINT16 Flags,
- IN UINT16 HeadIdx,
- IN OUT UINT16 *NextAvailIdx
- )
-{
- volatile VRING_DESC *Desc;
-
- Desc = &Ring->Desc[*NextAvailIdx % Ring->QueueSize];
- Desc->Addr = BufferPhysAddr;
- Desc->Len = BufferSize;
- Desc->Flags = Flags;
- Ring->Avail.Ring[(*NextAvailIdx)++ % Ring->QueueSize] =
- HeadIdx % Ring->QueueSize;
- Desc->Next = *NextAvailIdx % Ring->QueueSize;
-}
/**
@@ -827,128 +631,6 @@ VirtioBlkDriverBindingSupported (
/**
- Configure a virtio ring.
-
- This function sets up internal storage (the guest-host communication area)
- and lays out several "navigation" (ie. no-ownership) pointers to parts of
- that storage.
-
- Relevant sections from the virtio-0.9.5 spec:
- - 1.1 Virtqueues,
- - 2.3 Virtqueue Configuration.
-
- @param[in] The number of descriptors to allocate for the
- virtio ring, as requested by the host.
-
- @param[out] Ring The virtio ring to set up.
-
- @retval EFI_OUT_OF_RESOURCES AllocatePages() failed to allocate contiguous
- pages for the requested QueueSize. Fields of
- Ring have indeterminate value.
-
- @retval EFI_SUCCESS Allocation and setup successful. Ring->Base
- (and nothing else) is responsible for
- deallocation.
-
-**/
-
-STATIC
-EFI_STATUS
-EFIAPI
-VirtioRingInit (
- IN UINT16 QueueSize,
- OUT VRING *Ring
- )
-{
- UINTN RingSize;
- volatile UINT8 *RingPagesPtr;
-
- RingSize = ALIGN_VALUE (
- sizeof *Ring->Desc * QueueSize +
- sizeof *Ring->Avail.Flags +
- sizeof *Ring->Avail.Idx +
- sizeof *Ring->Avail.Ring * QueueSize +
- sizeof *Ring->Avail.UsedEvent,
- EFI_PAGE_SIZE);
-
- RingSize += ALIGN_VALUE (
- sizeof *Ring->Used.Flags +
- sizeof *Ring->Used.Idx +
- sizeof *Ring->Used.UsedElem * QueueSize +
- sizeof *Ring->Used.AvailEvent,
- EFI_PAGE_SIZE);
-
- Ring->NumPages = EFI_SIZE_TO_PAGES (RingSize);
- Ring->Base = AllocatePages (Ring->NumPages);
- if (Ring->Base == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- SetMem (Ring->Base, RingSize, 0x00);
- RingPagesPtr = Ring->Base;
-
- Ring->Desc = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Desc * QueueSize;
-
- Ring->Avail.Flags = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Avail.Flags;
-
- Ring->Avail.Idx = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Avail.Idx;
-
- Ring->Avail.Ring = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Avail.Ring * QueueSize;
-
- Ring->Avail.UsedEvent = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Avail.UsedEvent;
-
- RingPagesPtr = (volatile UINT8 *) Ring->Base +
- ALIGN_VALUE (RingPagesPtr - (volatile UINT8 *) Ring->Base,
- EFI_PAGE_SIZE);
-
- Ring->Used.Flags = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Used.Flags;
-
- Ring->Used.Idx = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Used.Idx;
-
- Ring->Used.UsedElem = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Used.UsedElem * QueueSize;
-
- Ring->Used.AvailEvent = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Used.AvailEvent;
-
- Ring->QueueSize = QueueSize;
- return EFI_SUCCESS;
-}
-
-
-/**
-
- Tear down the internal resources of a configured virtio ring.
-
- The caller is responsible to stop the host from using this ring before
- invoking this function: the VSTAT_DRIVER_OK bit must be clear in
- VhdrDeviceStatus.
-
- @param[out] Ring The virtio ring to clean up.
-
-**/
-
-
-STATIC
-VOID
-EFIAPI
-VirtioRingUninit (
- IN OUT VRING *Ring
- )
-{
- FreePages (Ring->Base, Ring->NumPages);
- SetMem (Ring, sizeof *Ring, 0x00);
-}
-
-
-/**
-
Set up all BlockIo and virtio-blk aspects of this driver for the specified
device.
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
index 730903d..6dffc3a 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
@@ -35,6 +35,7 @@
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiLib
+ VirtioLib
[Protocols]
gEfiBlockIoProtocolGuid ## BY_START