summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Kinney <steven.kinney@linaro.org>2013-11-20 16:42:40 -0600
committerSteven Kinney <steven.kinney@linaro.org>2013-11-20 16:42:40 -0600
commit5b7afff892fdaf87dcde2d5d926774718662822d (patch)
treefe337805dcc03f471bf5658b6cb5d409dc3321e0
parent5eea14ca2868314e4af2e50a2c64d7987b3b3e71 (diff)
parent6a90696e53f829e790a8ab67a8040dfd6707f313 (diff)
Merge branch 'linaro-topic-virtio' into linaro-tracking-2013.11linaro-uefi-2013.11-rc3
-rw-r--r--ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.c73
-rw-r--r--ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.inf35
-rw-r--r--ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4-foundation.dsc10
-rw-r--r--ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4-foundation.fdf6
-rw-r--r--ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4.dsc10
-rw-r--r--ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4.fdf8
-rw-r--r--OvmfPkg/Include/IndustryStandard/Virtio.h66
-rw-r--r--OvmfPkg/Include/IndustryStandard/VirtioBlk.h21
-rw-r--r--OvmfPkg/Include/IndustryStandard/VirtioNet.h14
-rw-r--r--OvmfPkg/Include/IndustryStandard/VirtioScsi.h27
-rw-r--r--OvmfPkg/Include/Library/VirtioLib.h77
-rw-r--r--OvmfPkg/Include/Library/VirtioMmioDeviceLib.h65
-rw-r--r--OvmfPkg/Include/Protocol/VirtioDevice.h376
-rw-r--r--OvmfPkg/Library/VirtioLib/VirtioLib.c158
-rw-r--r--OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c204
-rw-r--r--OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h147
-rw-r--r--OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c304
-rw-r--r--OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf43
-rw-r--r--OvmfPkg/OvmfPkg.dec1
-rw-r--r--OvmfPkg/OvmfPkgIa32.dsc1
-rw-r--r--OvmfPkg/OvmfPkgIa32.fdf1
-rw-r--r--OvmfPkg/OvmfPkgIa32X64.dsc1
-rw-r--r--OvmfPkg/OvmfPkgIa32X64.fdf1
-rw-r--r--OvmfPkg/OvmfPkgX64.dsc1
-rw-r--r--OvmfPkg/OvmfPkgX64.fdf1
-rw-r--r--OvmfPkg/VirtioBlkDxe/VirtioBlk.c185
-rw-r--r--OvmfPkg/VirtioBlkDxe/VirtioBlk.h32
-rw-r--r--OvmfPkg/VirtioBlkDxe/VirtioBlk.inf4
-rw-r--r--OvmfPkg/VirtioNetDxe/ComponentName.c6
-rw-r--r--OvmfPkg/VirtioNetDxe/DriverBinding.c130
-rw-r--r--OvmfPkg/VirtioNetDxe/Events.c2
-rw-r--r--OvmfPkg/VirtioNetDxe/SnpGetStatus.c2
-rw-r--r--OvmfPkg/VirtioNetDxe/SnpInitialize.c37
-rw-r--r--OvmfPkg/VirtioNetDxe/SnpReceive.c12
-rw-r--r--OvmfPkg/VirtioNetDxe/SnpShutdown.c2
-rw-r--r--OvmfPkg/VirtioNetDxe/SnpTransmit.c12
-rw-r--r--OvmfPkg/VirtioNetDxe/VirtioNet.h26
-rw-r--r--OvmfPkg/VirtioNetDxe/VirtioNet.inf2
-rw-r--r--OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c667
-rw-r--r--OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h166
-rw-r--r--OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf43
-rw-r--r--OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c285
-rw-r--r--OvmfPkg/VirtioScsiDxe/VirtioScsi.c173
-rw-r--r--OvmfPkg/VirtioScsiDxe/VirtioScsi.h24
-rw-r--r--OvmfPkg/VirtioScsiDxe/VirtioScsi.inf2
45 files changed, 2813 insertions, 650 deletions
diff --git a/ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.c b/ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.c
new file mode 100644
index 0000000000..8982568c52
--- /dev/null
+++ b/ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.c
@@ -0,0 +1,73 @@
+/** @file
+
+ Copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
+
+ 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
+
+typedef struct {
+ VENDOR_DEVICE_PATH Vendor;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} VIRTIO_BLK_DEVICE_PATH;
+
+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,
+ &mVirtioBlockDevicePath);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Declare the Virtio BlockIo device
+ Status = VirtioMmioInstallDevice (ARM_FVP_BASE_VIRTIO_BLOCK_BASE, ImageHandle);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "ArmFvpDxe: Failed to install Virtio block device\n"));
+ }
+
+ return Status;
+}
diff --git a/ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.inf b/ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.inf
new file mode 100644
index 0000000000..893fd8d41d
--- /dev/null
+++ b/ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.inf
@@ -0,0 +1,35 @@
+#/** @file
+#
+# Copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
+#
+# 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 = 0x00010006
+ BASE_NAME = ArmFvpDxe
+ FILE_GUID = fe61bb5f-1b67-4c24-b346-73db42e873e5
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = ArmFvpInitialise
+
+[Sources.common]
+ ArmFvpDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ VirtioMmioDeviceLib
+ BaseMemoryLib
diff --git a/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4-foundation.dsc b/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4-foundation.dsc
index 6ed5649ed0..29dbbafef7 100644
--- a/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4-foundation.dsc
+++ b/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4-foundation.dsc
@@ -34,6 +34,10 @@
ArmCpuLib|ArmPkg/Drivers/ArmCpuLib/ArmCortexAEMv8Lib/ArmCortexAEMv8Lib.inf
ArmPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressFoundationLib.inf
+ # Virtio Support
+ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
+ VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
+
ArmPlatformSysConfigLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfigLib.inf
TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
@@ -238,6 +242,12 @@
ArmPkg/Filesystem/SemihostFs/SemihostFs.inf
#
+ # Platform Driver
+ #
+ ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.inf
+ OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+
+ #
# FAT filesystem + GPT/MBR partitioning
#
MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
diff --git a/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4-foundation.fdf b/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4-foundation.fdf
index 6c84f522f2..9981daf58f 100644
--- a/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4-foundation.fdf
+++ b/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4-foundation.fdf
@@ -168,6 +168,12 @@ READ_LOCK_STATUS = TRUE
INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
#
+ # Platform Driver
+ #
+ INF ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.inf
+ INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+
+ #
# UEFI application (Shell Embedded Boot Loader)
#
INF ShellBinPkg/UefiShell/UefiShell.inf
diff --git a/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4.dsc b/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4.dsc
index 7cbdb643d1..cf5823d9ad 100644
--- a/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4.dsc
+++ b/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4.dsc
@@ -40,6 +40,10 @@
TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
+ # VirtIo Support
+ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
+ VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
+
[LibraryClasses.common.SEC]
ArmLib|ArmPkg/Library/ArmLib/AArch64/AArch64LibSec.inf
ArmPlatformSecLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressSecLibRTSM/ArmVExpressSecLib.inf
@@ -267,6 +271,12 @@
ArmPlatformPkg/Drivers/PL180MciDxe/PL180MciDxe.inf
#
+ # Platform Driver
+ #
+ ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.inf
+ OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+
+ #
# FAT filesystem + GPT/MBR partitioning
#
MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
diff --git a/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4.fdf b/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4.fdf
index 531415d0da..af1b0fa97d 100644
--- a/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4.fdf
+++ b/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-RTSM-AEMv8Ax4.fdf
@@ -176,7 +176,13 @@ READ_LOCK_STATUS = TRUE
#
INF EmbeddedPkg/Universal/MmcDxe/MmcDxe.inf
INF ArmPlatformPkg/Drivers/PL180MciDxe/PL180MciDxe.inf
-
+
+ #
+ # Platform Driver
+ #
+ INF ArmPlatformPkg/ArmVExpressPkg/ArmFvpDxe/ArmFvpDxe.inf
+ INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+
#
# UEFI application (Shell Embedded Boot Loader)
#
diff --git a/OvmfPkg/Include/IndustryStandard/Virtio.h b/OvmfPkg/Include/IndustryStandard/Virtio.h
index 622a8deef0..75c5a9c85a 100644
--- a/OvmfPkg/Include/IndustryStandard/Virtio.h
+++ b/OvmfPkg/Include/IndustryStandard/Virtio.h
@@ -4,6 +4,7 @@
specification.
Copyright (C) 2012, Red Hat, Inc.
+ Portion of Copyright (C) 2013, ARM Ltd.
This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
@@ -35,6 +36,53 @@
#define VIRTIO_SUBSYSTEM_MAC80211_WLAN 10
//
+// Virtio IDs
+//
+#define VIRTIO_VENDOR_ID 0x1AF4
+#define VIRTIO_MMIO_MAGIC 0x74726976 // "virt"
+
+
+//
+// VirtIo Device Specific Configuration Offsets
+//
+#define VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI 20
+#define VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI_WITH_MSI_X 24
+#define VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO 0x100
+
+// PCI VirtIo Header Offsets
+//
+#define VIRTIO_PCI_OFFSET_DEVICE_FEATURES 0x00
+#define VIRTIO_PCI_OFFSET_GUEST_FEATURES 0x04
+#define VIRTIO_PCI_OFFSET_QUEUE_ADDRESS 0x08
+#define VIRTIO_PCI_OFFSET_QUEUE_SIZE 0x0C
+#define VIRTIO_PCI_OFFSET_QUEUE_SELECT 0x0E
+#define VIRTIO_PCI_OFFSET_QUEUE_NOTIFY 0x10
+#define VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS 0x12
+#define VIRTIO_PCI_OFFSET_QUEUE_DEVICE_ISR 0x13
+
+//
+// MMIO VirtIo Header Offsets
+//
+#define VIRTIO_MMIO_OFFSET_MAGIC 0x00
+#define VIRTIO_MMIO_OFFSET_VERSION 0x04
+#define VIRTIO_MMIO_OFFSET_DEVICE_ID 0x08
+#define VIRTIO_MMIO_OFFSET_VENDOR_ID 0x0C
+#define VIRTIO_MMIO_OFFSET_HOST_FEATURES 0x10
+#define VIRTIO_MMIO_OFFSET_HOST_FEATURES_SEL 0x14
+#define VIRTIO_MMIO_OFFSET_GUEST_FEATURES 0x20
+#define VIRTIO_MMIO_OFFSET_GUEST_FEATURES_SEL 0x24
+#define VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE 0x28
+#define VIRTIO_MMIO_OFFSET_QUEUE_SEL 0x30
+#define VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX 0x34
+#define VIRTIO_MMIO_OFFSET_QUEUE_NUM 0x38
+#define VIRTIO_MMIO_OFFSET_QUEUE_ALIGN 0x3C
+#define VIRTIO_MMIO_OFFSET_QUEUE_PFN 0x40
+#define VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY 0x50
+#define VIRTIO_MMIO_OFFSET_INTERRUPT_STATUS 0x60
+#define VIRTIO_MMIO_OFFSET_INTERRUPT_ACK 0x64
+#define VIRTIO_MMIO_OFFSET_STATUS 0x70
+
+//
// Data in the communication area is defined as packed and accessed as
// volatile.
//
@@ -107,24 +155,6 @@ typedef struct {
UINT16 QueueSize;
} VRING;
-
-//
-// virtio-0.9.5, 2.2.2 Virtio Header -- no MSI-X
-//
-#pragma pack(1)
-typedef struct {
- UINT32 VhdrDeviceFeatureBits;
- UINT32 VhdrGuestFeatureBits;
- UINT32 VhdrQueueAddress;
- UINT16 VhdrQueueSize;
- UINT16 VhdrQueueSelect;
- UINT16 VhdrQueueNotify;
- UINT8 VhdrDeviceStatus;
- UINT8 VhdrISR;
-} VIRTIO_HDR;
-#pragma pack()
-
-
//
// virtio-0.9.5, 2.2.2.1 Device Status
//
diff --git a/OvmfPkg/Include/IndustryStandard/VirtioBlk.h b/OvmfPkg/Include/IndustryStandard/VirtioBlk.h
index b71f224b65..55f6548edc 100644
--- a/OvmfPkg/Include/IndustryStandard/VirtioBlk.h
+++ b/OvmfPkg/Include/IndustryStandard/VirtioBlk.h
@@ -26,19 +26,18 @@
//
#pragma pack(1)
typedef struct {
- VIRTIO_HDR Generic;
- UINT64 VhdrCapacity;
- UINT32 VhdrSizeMax;
- UINT32 VhdrSegMax;
- UINT16 VhdrCylinders;
- UINT8 VhdrHeads;
- UINT8 VhdrSectors;
- UINT32 VhdrBlkSize;
-} VBLK_HDR;
+ UINT64 Capacity;
+ UINT32 SizeMax;
+ UINT32 SegMax;
+ UINT16 Cylinders;
+ UINT8 Heads;
+ UINT8 Sectors;
+ UINT32 BlkSize;
+} VIRTIO_BLK_CONFIG;
#pragma pack()
-#define OFFSET_OF_VBLK(Field) OFFSET_OF (VBLK_HDR, Field)
-#define SIZE_OF_VBLK(Field) (sizeof ((VBLK_HDR *) 0)->Field)
+#define OFFSET_OF_VBLK(Field) OFFSET_OF (VIRTIO_BLK_CONFIG, Field)
+#define SIZE_OF_VBLK(Field) (sizeof ((VIRTIO_BLK_CONFIG *) 0)->Field)
#define VIRTIO_BLK_F_BARRIER BIT0
#define VIRTIO_BLK_F_SIZE_MAX BIT1
diff --git a/OvmfPkg/Include/IndustryStandard/VirtioNet.h b/OvmfPkg/Include/IndustryStandard/VirtioNet.h
index 03dfeb2c59..90d9702cba 100644
--- a/OvmfPkg/Include/IndustryStandard/VirtioNet.h
+++ b/OvmfPkg/Include/IndustryStandard/VirtioNet.h
@@ -1,5 +1,4 @@
/** @file
-
Virtio Network Device specific type and macro definitions corresponding to
the virtio-0.9.5 specification.
@@ -25,14 +24,13 @@
//
#pragma pack(1)
typedef struct {
- VIRTIO_HDR Generic;
- UINT8 VhdrMac[6];
- UINT16 VhdrLinkStatus;
-} VNET_HDR;
+ UINT8 Mac[6];
+ UINT16 LinkStatus;
+} VIRTIO_NET_CONFIG;
#pragma pack()
-#define OFFSET_OF_VNET(Field) OFFSET_OF (VNET_HDR, Field)
-#define SIZE_OF_VNET(Field) (sizeof ((VNET_HDR *) 0)->Field)
+#define OFFSET_OF_VNET(Field) OFFSET_OF (VIRTIO_NET_CONFIG, Field)
+#define SIZE_OF_VNET(Field) (sizeof ((VIRTIO_NET_CONFIG *) 0)->Field)
//
// Queue Identifiers
@@ -91,7 +89,7 @@ typedef struct {
#define VIRTIO_NET_HDR_GSO_ECN BIT7
//
-// Link Status Bits in VNET_HDR.VhdrLinkStatus
+// Link Status Bits in VIRTIO_NET_CONFIG.LinkStatus
//
#define VIRTIO_NET_S_LINK_UP BIT0
#define VIRTIO_NET_S_ANNOUNCE BIT1
diff --git a/OvmfPkg/Include/IndustryStandard/VirtioScsi.h b/OvmfPkg/Include/IndustryStandard/VirtioScsi.h
index 59ce97e070..884e4d642a 100644
--- a/OvmfPkg/Include/IndustryStandard/VirtioScsi.h
+++ b/OvmfPkg/Include/IndustryStandard/VirtioScsi.h
@@ -26,22 +26,21 @@
//
#pragma pack(1)
typedef struct {
- VIRTIO_HDR Generic;
- UINT32 VhdrNumQueues;
- UINT32 VhdrSegMax;
- UINT32 VhdrMaxSectors;
- UINT32 VhdrCmdPerLun;
- UINT32 VhdrEventInfoSize;
- UINT32 VhdrSenseSize;
- UINT32 VhdrCdbSize;
- UINT16 VhdrMaxChannel;
- UINT16 VhdrMaxTarget;
- UINT32 VhdrMaxLun;
-} VSCSI_HDR;
+ UINT32 NumQueues;
+ UINT32 SegMax;
+ UINT32 MaxSectors;
+ UINT32 CmdPerLun;
+ UINT32 EventInfoSize;
+ UINT32 SenseSize;
+ UINT32 CdbSize;
+ UINT16 MaxChannel;
+ UINT16 MaxTarget;
+ UINT32 MaxLun;
+} VIRTIO_SCSI_CONFIG;
#pragma pack()
-#define OFFSET_OF_VSCSI(Field) OFFSET_OF (VSCSI_HDR, Field)
-#define SIZE_OF_VSCSI(Field) (sizeof ((VSCSI_HDR *) 0)->Field)
+#define OFFSET_OF_VSCSI(Field) OFFSET_OF (VIRTIO_SCSI_CONFIG, Field)
+#define SIZE_OF_VSCSI(Field) (sizeof ((VIRTIO_SCSI_CONFIG *) 0)->Field)
#define VIRTIO_SCSI_F_INOUT BIT0
#define VIRTIO_SCSI_F_HOTPLUG BIT1
diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h
index 51303491d0..e61a5090eb 100644
--- a/OvmfPkg/Include/Library/VirtioLib.h
+++ b/OvmfPkg/Include/Library/VirtioLib.h
@@ -17,71 +17,10 @@
#ifndef _VIRTIO_LIB_H_
#define _VIRTIO_LIB_H_
-#include <Protocol/PciIo.h>
+#include <Protocol/VirtioDevice.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().
-
-**/
-EFI_STATUS
-EFIAPI
-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().
-
-**/
-EFI_STATUS
-EFIAPI
-VirtioRead (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINTN FieldOffset,
- IN UINTN FieldSize,
- IN UINTN BufferSize,
- OUT VOID *Buffer
- );
-
/**
@@ -218,7 +157,7 @@ VirtioAppendDesc (
Notify the host about the descriptor chain just built, and wait until the
host processes it.
- @param[in] PciIo The target virtio PCI device to notify.
+ @param[in] VirtIo The target virtio device to notify.
@param[in] VirtQueueId Identifies the queue for the target device.
@@ -229,7 +168,7 @@ VirtioAppendDesc (
of the descriptor chain.
- @return Error code from VirtioWrite() if it fails.
+ @return Error code from VirtioWriteDevice() if it fails.
@retval EFI_SUCCESS Otherwise, the host processed all descriptors.
@@ -237,10 +176,10 @@ VirtioAppendDesc (
EFI_STATUS
EFIAPI
VirtioFlush (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINT16 VirtQueueId,
- IN OUT VRING *Ring,
- IN DESC_INDICES *Indices
+ 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
new file mode 100644
index 0000000000..73e5a9e8d3
--- /dev/null
+++ b/OvmfPkg/Include/Library/VirtioMmioDeviceLib.h
@@ -0,0 +1,65 @@
+/** @file
+
+ Definitions for the VirtIo MMIO Device Library
+
+ Copyright (C) 2013, ARM Ltd
+
+ 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_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.
+
+ @retval EFI_SUCCESS The VirtIo Device has been installed
+ successfully.
+
+ @retval EFI_OUT_OF_RESOURCES The function failed too allocate memory require
+ 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
+ );
+
+/**
+
+ Uninstall the VirtIo Device
+
+ @param[in] Handle Handle of the device where the VirtIo Device protocol
+ should have been installed.
+
+ @retval EFI_SUCCESS The device has been un-initialized successfully.
+
+ @return Status code returned by UninstallProtocolInterface
+ Boot Service function.
+
+**/
+EFI_STATUS
+VirtioMmioUninstallDevice (
+ IN EFI_HANDLE Handle
+ );
+
+#endif // _VIRTIO_MMIO_DEVICE_LIB_H_
diff --git a/OvmfPkg/Include/Protocol/VirtioDevice.h b/OvmfPkg/Include/Protocol/VirtioDevice.h
new file mode 100644
index 0000000000..cecac0541a
--- /dev/null
+++ b/OvmfPkg/Include/Protocol/VirtioDevice.h
@@ -0,0 +1,376 @@
+/** @file
+ Virtio Device
+
+ Copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
+
+ 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))
+
+#define VIRTIO_DEVICE_PROTOCOL_GUID { \
+ 0xfa920010, 0x6785, 0x4941, {0xb6, 0xec, 0x49, 0x8c, 0x57, 0x9f, 0x16, 0x0a }\
+ }
+
+typedef struct _VIRTIO_DEVICE_PROTOCOL VIRTIO_DEVICE_PROTOCOL;
+
+/**
+
+ Read a word from the device-specific I/O region of the Virtio Header.
+
+ @param[in] This This instance of VIRTIO_DEVICE_PROTOCOL
+
+ @param[in] FieldOffset Source offset.
+
+ @param[in] FieldSize Source field size in bytes, 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.
+
+ @retval EFI_SUCCESS The data was read successfully.
+ @retval EFI_UNSUPPORTED The underlying IO device doesn't support the
+ provided address offset and read size.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VIRTIO_DEVICE_READ) (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+
+ Write a word to the device-specific I/O region of the Virtio Header.
+
+ @param[in] This This instance of VIRTIO_DEVICE_PROTOCOL
+
+ @param[in] FieldOffset Destination offset.
+
+ @param[in] FieldSize Destination field size in bytes,
+ must be in {1, 2, 4, 8}.
+
+ @param[out] Value Value to write.
+
+ @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.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VIRTIO_DEVICE_WRITE) (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINT64 Value
+ );
+
+/**
+ Read the device features field from the Virtio Header.
+
+ @param[in] This This instance of VIRTIO_DEVICE_PROTOCOL
+
+ @param[out] DeviceFeatures The 32-bit device features field.
+
+ @retval EFI_SUCCESS The data was read successfully.
+ @retval EFI_UNSUPPORTED The underlying IO device doesn't support the
+ provided address offset and read size.
+ @retval EFI_INVALID_PARAMETER DeviceFeatures is NULL
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VIRTIO_GET_DEVICE_FEATURES) (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT32 *DeviceFeatures
+ );
+
+/**
+ Write the guest features field in the Virtio Header.
+
+ @param[in] This This instance of VIRTIO_DEVICE_PROTOCOL
+
+ @param[in] Features The 32-bit guest guest features field
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VIRTIO_SET_GUEST_FEATURES) (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT32 Features
+ );
+
+/**
+ Read the queue address field from the Virtio Header.
+
+ QueueAddress is the address of the virtqueue divided by 4096.
+
+ @param[in] This This instance of VIRTIO_DEVICE_PROTOCOL
+
+ @param[out] QueueAddress The 32-bit queue address field.
+
+ @retval EFI_SUCCESS The data was read successfully.
+ @retval EFI_UNSUPPORTED The underlying IO device doesn't support the
+ provided address offset and read size.
+ @retval EFI_INVALID_PARAMETER QueueAddress is NULL
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VIRTIO_GET_QUEUE_ADDRESS) (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT32 *QueueAddress
+ );
+
+/**
+ Write the queue address field in the Virtio Header.
+
+ The parameter Address must be the base address of the virtqueue divided
+ by 4096.
+
+ @param[in] This This instance of VIRTIO_DEVICE_PROTOCOL
+
+ @param[in] Address The 32-bit Queue Address 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_QUEUE_ADDRESS) (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT32 Address
+ );
+
+/**
+
+ Write the queue select field in the Virtio Header.
+
+ Writing to the queue select field sets the index of the queue to which
+ operations such as SetQueueAlign and GetQueueNumMax apply.
+
+ @param[in] This This instance of VIRTIO_DEVICE_PROTOCOL
+
+ @param[in] Index The index of the queue to select
+
+ @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_QUEUE_SEL) (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT16 Index
+ );
+
+/**
+
+ Write the queue notify field in the Virtio Header.
+
+ @param[in] This This instance of VIRTIO_DEVICE_PROTOCOL
+
+ @param[in] Address The 32-bit Queue Notify 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_QUEUE_NOTIFY) (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT16 Index
+ );
+
+/**
+ Write the queue alignment field in the Virtio Header.
+
+ The queue to which the alignment applies is selected by the Queue Select
+ field.
+
+ Note: This operation is not implemented by the VirtIo over PCI. The PCI
+ implementation of this protocol returns EFI_SUCCESS.
+
+ @param[in] This This instance of VIRTIO_DEVICE_PROTOCOL
+
+ @param[in] Alignment The alignment boundary of the Used Ring in bytes.
+ Must be a power of 2.
+
+ @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_QUEUE_ALIGN) (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT32 Alignment
+ );
+
+/**
+ Write the guest page size.
+
+ Note: This operation is not implemented by the VirtIo over PCI. The PCI
+ implementation of this protocol returns EFI_SUCCESS.
+
+ @param[in] This This instance of VIRTIO_DEVICE_PROTOCOL
+
+ @param[in] PageSize Size of the Guest page in bytes.
+ Must be a power of 2.
+
+ @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_PAGE_SIZE) (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT32 PageSize
+ );
+
+/**
+
+ Get the size of the virtqueue selected by the queue select field.
+
+ See Virtio spec Section 2.3
+
+ @param[in] This This instance of VIRTIO_DEVICE_PROTOCOL
+
+ @param[out] QueueNumMax The size of the virtqueue in bytes.
+ Always a power of 2.
+
+ @retval EFI_SUCCESS The data was read successfully.
+ @retval EFI_UNSUPPORTED The underlying IO device doesn't support the
+ provided address offset and read size.
+ @retval EFI_INVALID_PARAMETER QueueNumMax is NULL
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VIRTIO_GET_QUEUE_NUM_MAX) (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT16 *QueueNumMax
+ );
+
+/**
+
+ Write to the QueueNum field in the Virtio Header.
+
+ This function only applies to Virtio-MMIO and may be a stub for other
+ implementations. See Virtio Spec appendix X.
+
+ @param[in] This This instance of VIRTIO_DEVICE_PROTOCOL
+
+ @param[in] QueueSize The number of elements in the queue.
+
+ @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_QUEUE_NUM) (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT16 QueueSize
+ );
+
+/**
+
+ Get the DeviceStatus field from the Virtio Header.
+
+ @param[in] This This instance of VIRTIO_DEVICE_PROTOCOL
+
+ @param[out] DeviceStatus The 8-bit value for the Device status field
+
+ @retval EFI_SUCCESS The data was read successfully.
+ @retval EFI_UNSUPPORTED The underlying IO device doesn't support the
+ provided address offset and read size.
+ @retval EFI_INVALID_PARAMETER DeviceStatus is NULL
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VIRTIO_GET_DEVICE_STATUS) (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT8 *DeviceStatus
+ );
+
+/**
+
+ Write the DeviceStatus field in the Virtio Header.
+
+ @param[in] This This instance of VIRTIO_DEVICE_PROTOCOL
+
+ @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
+///
+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;
+ VIRTIO_SET_PAGE_SIZE SetPageSize;
+
+ VIRTIO_GET_QUEUE_NUM_MAX GetQueueNumMax;
+ VIRTIO_SET_QUEUE_NUM SetQueueNum;
+
+ VIRTIO_GET_DEVICE_STATUS GetDeviceStatus;
+ VIRTIO_SET_DEVICE_STATUS SetDeviceStatus;
+
+ // Functions to read/write Device Specific headers
+ VIRTIO_DEVICE_WRITE WriteDevice;
+ VIRTIO_DEVICE_READ ReadDevice;
+};
+
+extern EFI_GUID gVirtioDeviceProtocolGuid;
+
+#endif
diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
index 959bc5da87..1550318d81 100644
--- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
+++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
@@ -3,6 +3,7 @@
Utility functions used by virtio device drivers.
Copyright (C) 2012, Red Hat, Inc.
+ Portion of Copyright (C) 2013, ARM Ltd.
This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
@@ -14,7 +15,6 @@
**/
-#include <IndustryStandard/Pci22.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
@@ -26,143 +26,6 @@
/**
- 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().
-
-**/
-EFI_STATUS
-EFIAPI
-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 EFI_INVALID_PARAMETER;
- }
-
- 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().
-
-**/
-EFI_STATUS
-EFIAPI
-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 EFI_INVALID_PARAMETER;
- }
-
- 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)
@@ -376,7 +239,7 @@ VirtioAppendDesc (
Notify the host about the descriptor chain just built, and wait until the
host processes it.
- @param[in] PciIo The target virtio PCI device to notify.
+ @param[in] VirtIo The target virtio device to notify.
@param[in] VirtQueueId Identifies the queue for the target device.
@@ -387,7 +250,7 @@ VirtioAppendDesc (
of the descriptor chain.
- @return Error code from VirtioWrite() if it fails.
+ @return Error code from VirtioWriteDevice() if it fails.
@retval EFI_SUCCESS Otherwise, the host processed all descriptors.
@@ -395,10 +258,10 @@ VirtioAppendDesc (
EFI_STATUS
EFIAPI
VirtioFlush (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINT16 VirtQueueId,
- IN OUT VRING *Ring,
- IN DESC_INDICES *Indices
+ IN VIRTIO_DEVICE_PROTOCOL *VirtIo,
+ IN UINT16 VirtQueueId,
+ IN OUT VRING *Ring,
+ IN DESC_INDICES *Indices
)
{
UINT16 NextAvailIdx;
@@ -427,12 +290,7 @@ VirtioFlush (
// OK.
//
MemoryFence();
- Status = VirtioWrite (
- PciIo,
- OFFSET_OF (VIRTIO_HDR, VhdrQueueNotify),
- sizeof (UINT16),
- VirtQueueId
- );
+ Status = VirtIo->SetQueueNotify (VirtIo, VirtQueueId);
if (EFI_ERROR (Status)) {
return Status;
}
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
new file mode 100644
index 0000000000..f763db5fb8
--- /dev/null
+++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
@@ -0,0 +1,204 @@
+/** @file
+
+ This driver produces Virtio Device Protocol instances for Virtio Mmio devices.
+
+ Copyright (C) 2013, ARM Ltd.
+
+ 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/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include "VirtioMmioDevice.h"
+
+static VIRTIO_DEVICE_PROTOCOL mMmioDeviceProtocolTemplate = {
+ 0, // Revision
+ 0, // SubSystemDeviceId
+ VirtioMmioGetDeviceFeatures, // GetDeviceFeatures
+ VirtioMmioSetGuestFeatures, // SetGuestFeatures
+ VirtioMmioGetQueueAddress, // GetQueueAddress
+ VirtioMmioSetQueueAddress, // SetQueueAddress
+ VirtioMmioSetQueueSel, // SetQueueSel
+ VirtioMmioSetQueueNotify, // SetQueueNotify
+ VirtioMmioSetQueueAlignment, // SetQueueAlign
+ VirtioMmioSetPageSize, // SetPageSize
+ VirtioMmioGetQueueSize, // GetQueueNumMax
+ VirtioMmioSetQueueSize, // SetQueueNum
+ VirtioMmioGetDeviceStatus, // GetDeviceStatus
+ VirtioMmioSetDeviceStatus, // SetDeviceStatus
+ VirtioMmioDeviceWrite, // WriteDevice
+ VirtioMmioDeviceRead // ReadDevice
+};
+
+/**
+
+ Initialize the VirtIo MMIO Device
+
+ @param[in] BaseAddress Base Address of the VirtIo MMIO Device
+
+ @param[in, out] Device The driver instance to configure.
+
+ @retval EFI_SUCCESS Setup complete.
+
+ @retval EFI_UNSUPPORTED The driver is not a VirtIo MMIO device.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+VirtioMmioInit (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN OUT VIRTIO_MMIO_DEVICE *Device
+ )
+{
+ UINT32 MagicValue;
+ UINT32 VendorId;
+ UINT32 Version;
+
+ // Initialize VirtIo Mmio Device
+ CopyMem (&Device->VirtioDevice, &mMmioDeviceProtocolTemplate,
+ sizeof (VIRTIO_DEVICE_PROTOCOL));
+ Device->BaseAddress = BaseAddress;
+ Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5);
+ Device->VirtioDevice.SubSystemDeviceId =
+ MmioRead32 (BaseAddress + VIRTIO_MMIO_OFFSET_DEVICE_ID);
+
+ // Double-check MMIO-specific values
+ MagicValue = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_MAGIC);
+ if (MagicValue != VIRTIO_MMIO_MAGIC) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Version = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VERSION);
+ if (Version != 1) {
+ return EFI_UNSUPPORTED;
+ }
+
+ // Double-check MMIO-specific values
+ VendorId = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VENDOR_ID);
+ if (VendorId != VIRTIO_VENDOR_ID) {
+ // The ARM Base and Foundation Models do not report a valid VirtIo VendorId.
+ // They return a value of 0x0 for the VendorId.
+ DEBUG((EFI_D_WARN, "VirtioMmioInit: Warning: The VendorId (0x%X) does not "
+ "match the VirtIo VendorId (0x%X).\n",
+ VendorId, VIRTIO_VENDOR_ID));
+ //return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Uninitialize the internals of a virtio-mmio device that has been successfully
+ set up with VirtioMmioInit().
+
+ @param[in, out] Device The device to clean up.
+
+**/
+
+STATIC
+VOID
+EFIAPI
+VirtioMmioUninit (
+ IN VIRTIO_MMIO_DEVICE *Device
+ )
+{
+ // Note: This function mirrors VirtioMmioInit() that does not allocate any
+ // resources - there's nothing to free here.
+}
+
+EFI_STATUS
+VirtioMmioInstallDevice (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ VIRTIO_MMIO_DEVICE *VirtIo;
+
+ if (!BaseAddress) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Handle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Allocate VIRTIO_MMIO_DEVICE
+ VirtIo = AllocateZeroPool (sizeof (VIRTIO_MMIO_DEVICE));
+ if (VirtIo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ VirtIo->Signature = VIRTIO_MMIO_DEVICE_SIGNATURE;
+
+ Status = VirtioMmioInit (BaseAddress, VirtIo);
+ if (EFI_ERROR (Status)) {
+ goto FreeVirtioMem;
+ }
+
+ // Install VIRTIO_DEVICE_PROTOCOL to Handle
+ Status = gBS->InstallProtocolInterface (&Handle,
+ &gVirtioDeviceProtocolGuid, EFI_NATIVE_INTERFACE,
+ &VirtIo->VirtioDevice);
+ if (EFI_ERROR (Status)) {
+ goto UninitVirtio;
+ }
+
+ return EFI_SUCCESS;
+
+UninitVirtio:
+ VirtioMmioUninit (VirtIo);
+
+FreeVirtioMem:
+ FreePool (VirtIo);
+ return Status;
+}
+
+EFI_STATUS
+VirtioMmioUninstallDevice (
+ IN EFI_HANDLE DeviceHandle
+ )
+{
+ VIRTIO_DEVICE_PROTOCOL *VirtioDevice;
+ VIRTIO_MMIO_DEVICE *MmioDevice;
+ EFI_STATUS Status;
+
+ Status = gBS->OpenProtocol (
+ DeviceHandle, // candidate device
+ &gVirtioDeviceProtocolGuid, // retrieve the VirtIo iface
+ (VOID **)&VirtioDevice, // target pointer
+ DeviceHandle, // requestor driver identity
+ DeviceHandle, // requesting lookup for dev.
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added
+ );
+ 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);
+
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
new file mode 100644
index 0000000000..188d873ae1
--- /dev/null
+++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
@@ -0,0 +1,147 @@
+/** @file
+
+ Internal definitions for the VirtIo MMIO Device driver
+
+ Copyright (C) 2013, ARM Ltd
+
+ 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_MMIO_DEVICE_INTERNAL_H_
+#define _VIRTIO_MMIO_DEVICE_INTERNAL_H_
+
+#include <Protocol/VirtioDevice.h>
+
+#include <IndustryStandard/Virtio.h>
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/UefiLib.h>
+#include <Library/VirtioMmioDeviceLib.h>
+
+#define VIRTIO_MMIO_DEVICE_SIGNATURE SIGNATURE_32 ('V', 'M', 'I', 'O')
+
+typedef struct {
+ UINT32 Signature;
+ VIRTIO_DEVICE_PROTOCOL VirtioDevice;
+ PHYSICAL_ADDRESS BaseAddress;
+} VIRTIO_MMIO_DEVICE;
+
+#define VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE(Device) \
+ CR (Device, VIRTIO_MMIO_DEVICE, VirtioDevice, VIRTIO_MMIO_DEVICE_SIGNATURE)
+
+#define VIRTIO_CFG_WRITE(Device, Offset, Val) \
+ (MmioWrite32 (Device->BaseAddress + (Offset), Val))
+#define VIRTIO_CFG_READ(Device, Offset) \
+ (MmioRead32 (Device->BaseAddress + (Offset)))
+
+EFI_STATUS
+EFIAPI
+VirtioMmioDeviceRead (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINTN FieldOFfset,
+ IN UINTN FieldSize,
+ IN UINTN BufferSize,
+ OUT VOID* Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioDeviceWrite (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINT64 Value
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioGetDeviceFeatures (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT32 *DeviceFeatures
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioGetQueueAddress (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT32 *QueueAddress
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioGetQueueSize (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT16 *QueueNumMax
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioGetDeviceStatus (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT8 *DeviceStatus
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetQueueSize (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT16 QueueSize
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetDeviceStatus (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT8 DeviceStatus
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetQueueNotify (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT16 QueueNotify
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetQueueSel (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT16 Sel
+ );
+
+EFI_STATUS
+VirtioMmioSetQueueAddress (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT32 Address
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetQueueAlignment (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT32 Alignment
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetPageSize (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT32 PageSize
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetGuestFeatures (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT32 Features
+ );
+
+#endif // _VIRTIO_MMIO_DEVICE_INTERNAL_H_
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
new file mode 100644
index 0000000000..fa76f8ffce
--- /dev/null
+++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
@@ -0,0 +1,304 @@
+/** @file
+
+ This driver produces Virtio Device Protocol instances for Virtio MMIO devices.
+
+ Copyright (C) 2012, Red Hat, Inc.
+ Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
+ Copyright (C) 2013, ARM Ltd.
+
+ 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 "VirtioMmioDevice.h"
+
+EFI_STATUS
+EFIAPI
+VirtioMmioGetDeviceFeatures (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT32 *DeviceFeatures
+ )
+{
+ VIRTIO_MMIO_DEVICE *Device;
+
+ if (DeviceFeatures == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ 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) {
+
+ }
+
+ 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;
+
+ if (QueueNumMax == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ *QueueNumMax = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX) & 0xFFFF;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioMmioGetDeviceStatus (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT8 *DeviceStatus
+ )
+{
+ VIRTIO_MMIO_DEVICE *Device;
+
+ if (DeviceStatus == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ *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);
+}
+
+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;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetQueueNotify (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT16 QueueNotify
+ )
+{
+ VIRTIO_MMIO_DEVICE *Device;
+
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY, QueueNotify);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetQueueAlignment (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT32 Alignment
+ )
+{
+ VIRTIO_MMIO_DEVICE *Device;
+
+ 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);
+
+ 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;
+
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_SEL, Sel);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+VirtioMmioSetQueueAddress (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT32 Address
+ )
+{
+ VIRTIO_MMIO_DEVICE *Device;
+
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN, Address);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetGuestFeatures (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT32 Features
+ )
+{
+ VIRTIO_MMIO_DEVICE *Device;
+
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES, Features);
+
+ return EFI_SUCCESS;
+}
+
+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;
+}
+
+EFI_STATUS
+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/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
new file mode 100644
index 0000000000..0758375aa5
--- /dev/null
+++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
@@ -0,0 +1,43 @@
+## @file
+# This driver produces the VirtIo Device Protocol instances for VirtIo Mmio
+# Device
+#
+# Copyright (C) 2013, ARM Ltd
+#
+# 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 = 0x00010006
+ BASE_NAME = VirtioMmioDeviceLib
+ FILE_GUID = 3b6ed966-b5d1-46a8-965b-867ff22d9c89
+ MODULE_TYPE = UEFI_DRIVER
+ 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/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index d874f0c44f..11c44534aa 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -44,6 +44,7 @@
gEfiXenInfoGuid = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}}
[Protocols]
+ gVirtioDeviceProtocolGuid = {0xfa920010, 0x6785, 0x4941, {0xb6, 0xec, 0x49, 0x8c, 0x57, 0x9f, 0x16, 0x0a}}
gBlockMmioProtocolGuid = {0x6b558ce3, 0x69e5, 0x4c67, {0xa6, 0x34, 0xf7, 0xfe, 0x72, 0xad, 0xbe, 0x84}}
[PcdsFixedAtBuild]
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index dd8270b119..c57822bdd4 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -408,6 +408,7 @@
}
OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
+ OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index df4f2276ee..b13cf05899 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -181,6 +181,7 @@ INF MdeModulePkg/Universal/Metronome/Metronome.inf
INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
INF OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
+INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
INF OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 8c665504c3..171cbe2b7a 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -415,6 +415,7 @@
}
OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
+ OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index d93a7ff2e5..9965c3cf5a 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -181,6 +181,7 @@ INF MdeModulePkg/Universal/Metronome/Metronome.inf
INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
INF OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
+INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
INF OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 5ab3d63747..08c81e4a5b 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -413,6 +413,7 @@
}
OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
+ OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index deee977271..e2420c5cfa 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -181,6 +181,7 @@ INF MdeModulePkg/Universal/Metronome/Metronome.inf
INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
INF OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
+INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
INF OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index 17b9f71d63..08edf23fce 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -23,7 +23,6 @@
**/
-#include <IndustryStandard/Pci.h>
#include <IndustryStandard/VirtioBlk.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
@@ -37,14 +36,14 @@
/**
Convenience macros to read and write region 0 IO space elements of the
- virtio-blk PCI device, for configuration purposes.
+ virtio-blk device, for configuration purposes.
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 VBLK_DEV structure whose PCI IO space
- we're accessing. Dev->PciIo must be valid.
+ @param[in] Dev Pointer to the VBLK_DEV structure whose VirtIo space
+ we're accessing. Dev->VirtIo must be valid.
@param[in] Field A field name from VBLK_HDR, identifying the virtio-blk
configuration item to access.
@@ -57,23 +56,23 @@
one of UINT8, UINT16, UINT32, UINT64.
- @return Status code returned by VirtioWrite() / VirtioRead().
+ @return Status code returned by Virtio->WriteDevice() / Virtio->ReadDevice().
**/
-#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWrite ( \
- (Dev)->PciIo, \
- OFFSET_OF_VBLK (Field), \
- SIZE_OF_VBLK (Field), \
- (Value) \
+#define VIRTIO_CFG_WRITE(Dev, Field, Value) ((Dev)->VirtIo->WriteDevice ( \
+ (Dev)->VirtIo, \
+ OFFSET_OF_VBLK (Field), \
+ SIZE_OF_VBLK (Field), \
+ (Value) \
))
-#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead ( \
- (Dev)->PciIo, \
- OFFSET_OF_VBLK (Field), \
- SIZE_OF_VBLK (Field), \
- sizeof *(Pointer), \
- (Pointer) \
+#define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \
+ (Dev)->VirtIo, \
+ OFFSET_OF_VBLK (Field), \
+ SIZE_OF_VBLK (Field), \
+ sizeof *(Pointer), \
+ (Pointer) \
))
@@ -229,7 +228,7 @@ VerifyReadWriteRequest (
@retval EFI_SUCCESS Transfer complete.
- @retval EFI_DEVICE_ERROR Failed to notify host side via PCI write, or
+ @retval EFI_DEVICE_ERROR Failed to notify host side via VirtIo write, or
unable to parse host response, or host response
is not VIRTIO_BLK_S_OK.
@@ -324,7 +323,7 @@ SynchronousRequest (
//
// virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
//
- if (VirtioFlush (Dev->PciIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS &&
+ if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS &&
HostStatus == VIRTIO_BLK_S_OK) {
return EFI_SUCCESS;
}
@@ -500,11 +499,6 @@ VirtioBlkFlushBlocks (
underlying device
- 9 Driver Binding Protocol -- for exporting ourselves
- Specs relevant in the specific sense:
- - UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol
- - Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design
- Guidelines, 18.3 PCI drivers.
-
@param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
incorporating this driver (independently of
any device).
@@ -516,11 +510,11 @@ VirtioBlkFlushBlocks (
@retval EFI_SUCCESS The driver supports the device being probed.
- @retval EFI_UNSUPPORTED Based on virtio-blk PCI discovery, we do not support
+ @retval EFI_UNSUPPORTED Based on virtio-blk discovery, we do not support
the device.
@return Error codes from the OpenProtocol() boot service or
- the PciIo protocol.
+ the VirtIo protocol.
**/
@@ -533,56 +527,36 @@ VirtioBlkDriverBindingSupported (
)
{
EFI_STATUS Status;
- EFI_PCI_IO_PROTOCOL *PciIo;
- PCI_TYPE00 Pci;
+ VIRTIO_DEVICE_PROTOCOL *VirtIo;
//
- // Attempt to open the device with the PciIo set of interfaces. On success,
- // the protocol is "instantiated" for the PCI device. Covers duplicate open
+ // Attempt to open the device with the VirtIo set of interfaces. On success,
+ // the protocol is "instantiated" for the VirtIo device. Covers duplicate open
// attempts (EFI_ALREADY_STARTED).
//
Status = gBS->OpenProtocol (
DeviceHandle, // candidate device
- &gEfiPciIoProtocolGuid, // for generic PCI access
- (VOID **)&PciIo, // handle to instantiate
+ &gVirtioDeviceProtocolGuid, // for generic VirtIo access
+ (VOID **)&VirtIo, // handle to instantiate
This->DriverBindingHandle, // requestor driver identity
DeviceHandle, // ControllerHandle, according to
// the UEFI Driver Model
- EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to
+ EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to
// the device; to be released
);
if (EFI_ERROR (Status)) {
return Status;
}
- //
- // Read entire PCI configuration header for more extensive check ahead.
- //
- Status = PciIo->Pci.Read (
- PciIo, // (protocol, device)
- // handle
- EfiPciIoWidthUint32, // access width & copy
- // mode
- 0, // Offset
- sizeof Pci / sizeof (UINT32), // Count
- &Pci // target buffer
- );
-
- if (Status == EFI_SUCCESS) {
- //
- // virtio-0.9.5, 2.1 PCI Discovery
- //
- Status = (Pci.Hdr.VendorId == 0x1AF4 &&
- Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F &&
- Pci.Hdr.RevisionID == 0x00 &&
- Pci.Device.SubsystemID == VIRTIO_SUBSYSTEM_BLOCK_DEVICE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
+ if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_BLOCK_DEVICE) {
+ Status = EFI_UNSUPPORTED;
}
//
- // We needed PCI IO access only transitorily, to see whether we support the
+ // We needed VirtIo access only transitorily, to see whether we support the
// device or not.
//
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
return Status;
}
@@ -594,8 +568,8 @@ VirtioBlkDriverBindingSupported (
device.
@param[in out] Dev The driver instance to configure. The caller is
- responsible for Dev->PciIo's validity (ie. working IO
- access to the underlying virtio-blk PCI device).
+ responsible for Dev->VirtIo's validity (ie. working IO
+ access to the underlying virtio-blk device).
@retval EFI_SUCCESS Setup complete.
@@ -626,31 +600,40 @@ VirtioBlkInit (
// Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
//
NextDevStat = 0; // step 1 -- reset device
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
goto Failed;
}
NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ 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 = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ 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;
+ }
+
+ //
// step 4a -- retrieve and validate features
//
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);
+ Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
if (EFI_ERROR (Status)) {
goto Failed;
}
- Status = VIRTIO_CFG_READ (Dev, VhdrCapacity, &NumSectors);
+
+ Status = VIRTIO_CFG_READ (Dev, Capacity, &NumSectors);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -660,7 +643,7 @@ VirtioBlkInit (
}
if (Features & VIRTIO_BLK_F_BLK_SIZE) {
- Status = VIRTIO_CFG_READ (Dev, VhdrBlkSize, &BlockSize);
+ Status = VIRTIO_CFG_READ (Dev, BlkSize, &BlockSize);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -681,11 +664,11 @@ VirtioBlkInit (
//
// step 4b -- allocate virtqueue
//
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect, 0);
+ Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, 0);
if (EFI_ERROR (Status)) {
goto Failed;
}
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize);
+ Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -700,22 +683,31 @@ VirtioBlkInit (
}
//
+ // Additional steps for MMIO: align the queue appropriately, and set the size
+ Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
+ 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.
//
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueAddress,
- (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);
+ 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 = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits, 0);
+ Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, 0);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
@@ -724,7 +716,7 @@ VirtioBlkInit (
// step 6 -- initialization complete
//
NextDevStat |= VSTAT_DRIVER_OK;
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
@@ -758,10 +750,10 @@ ReleaseQueue:
Failed:
//
// Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
- // Status. PCI IO access failure here should not mask the original error.
+ // Status. VirtIo access failure here should not mask the original error.
//
NextDevStat |= VSTAT_FAILED;
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
return Status; // reached only via Failed above
}
@@ -788,7 +780,7 @@ VirtioBlkUninit (
// VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
// the old comms area.
//
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
VirtioRingUninit (&Dev->Ring);
@@ -815,13 +807,13 @@ VirtioBlkUninit (
@retval EFI_SUCCESS Driver instance has been created and
- initialized for the virtio-blk PCI device, it
+ initialized for the virtio-blk device, it
is now accessibla via EFI_BLOCK_IO_PROTOCOL.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
@return Error codes from the OpenProtocol() boot
- service, the PciIo protocol, VirtioBlkInit(),
+ service, the VirtIo protocol, VirtioBlkInit(),
or the InstallProtocolInterface() boot service.
**/
@@ -842,43 +834,23 @@ VirtioBlkDriverBindingStart (
return EFI_OUT_OF_RESOURCES;
}
- Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
- (VOID **)&Dev->PciIo, This->DriverBindingHandle,
+ Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
+ (VOID **)&Dev->VirtIo, This->DriverBindingHandle,
DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
if (EFI_ERROR (Status)) {
goto FreeVirtioBlk;
}
- //
- // We must retain and ultimately restore the original PCI attributes of the
- // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /
- // 18.3.2 Start() and Stop().
- //
- // The third parameter ("Attributes", input) is ignored by the Get operation.
- // The fourth parameter ("Result", output) is ignored by the Enable and Set
- // operations.
- //
- // For virtio-blk we only need IO space access.
- //
- Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet,
- 0, &Dev->OriginalPciAttributes);
- if (EFI_ERROR (Status)) {
- goto ClosePciIo;
- }
-
- Status = Dev->PciIo->Attributes (Dev->PciIo,
- EfiPciIoAttributeOperationEnable,
- EFI_PCI_IO_ATTRIBUTE_IO, NULL);
- if (EFI_ERROR (Status)) {
- goto ClosePciIo;
+ if (Dev->VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_BLOCK_DEVICE) {
+ return EFI_UNSUPPORTED;
}
//
- // PCI IO access granted, configure virtio-blk device.
+ // VirtIo access granted, configure virtio-blk device.
//
Status = VirtioBlkInit (Dev);
if (EFI_ERROR (Status)) {
- goto RestorePciAttributes;
+ goto CloseVirtIo;
}
//
@@ -897,12 +869,8 @@ VirtioBlkDriverBindingStart (
UninitDev:
VirtioBlkUninit (Dev);
-RestorePciAttributes:
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,
- Dev->OriginalPciAttributes, NULL);
-
-ClosePciIo:
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+CloseVirtIo:
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
FreeVirtioBlk:
@@ -973,10 +941,7 @@ VirtioBlkDriverBindingStop (
VirtioBlkUninit (Dev);
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,
- Dev->OriginalPciAttributes, NULL);
-
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
FreePool (Dev);
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.h b/OvmfPkg/VirtioBlkDxe/VirtioBlk.h
index d22570def9..43dd5064d4 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.h
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.h
@@ -21,7 +21,6 @@
#include <Protocol/BlockIo.h>
#include <Protocol/ComponentName.h>
#include <Protocol/DriverBinding.h>
-#include <Protocol/PciIo.h>
#include <IndustryStandard/Virtio.h>
@@ -34,14 +33,13 @@ typedef struct {
// at various call depths. The table to the right should make it easier to
// track them.
//
- // field init function init dpth
- // ---------------------- ------------------ ---------
- UINT32 Signature; // DriverBindingStart 0
- EFI_PCI_IO_PROTOCOL *PciIo; // DriverBindingStart 0
- UINT64 OriginalPciAttributes; // DriverBindingStart 0
- VRING Ring; // VirtioRingInit 2
- EFI_BLOCK_IO_PROTOCOL BlockIo; // VirtioBlkInit 1
- EFI_BLOCK_IO_MEDIA BlockIoMedia; // VirtioBlkInit 1
+ // field init function init dpth
+ // --------------------- ------------------ ---------
+ UINT32 Signature; // DriverBindingStart 0
+ VIRTIO_DEVICE_PROTOCOL *VirtIo; // DriverBindingStart 0
+ VRING Ring; // VirtioRingInit 2
+ EFI_BLOCK_IO_PROTOCOL BlockIo; // VirtioBlkInit 1
+ EFI_BLOCK_IO_MEDIA BlockIoMedia; // VirtioBlkInit 1
} VBLK_DEV;
#define VIRTIO_BLK_FROM_BLOCK_IO(BlockIoPointer) \
@@ -66,11 +64,6 @@ typedef struct {
underlying device
- 9 Driver Binding Protocol -- for exporting ourselves
- Specs relevant in the specific sense:
- - UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol
- - Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design
- Guidelines, 18.3 PCI drivers.
-
@param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
incorporating this driver (independently of
any device).
@@ -82,11 +75,10 @@ typedef struct {
@retval EFI_SUCCESS The driver supports the device being probed.
- @retval EFI_UNSUPPORTED Based on virtio-blk PCI discovery, we do not support
+ @retval EFI_UNSUPPORTED Based on virtio-blk discovery, we do not support
the device.
- @return Error codes from the OpenProtocol() boot service or
- the PciIo protocol.
+ @return Error codes from the OpenProtocol() boot service.
**/
@@ -117,14 +109,14 @@ VirtioBlkDriverBindingSupported (
@retval EFI_SUCCESS Driver instance has been created and
- initialized for the virtio-blk PCI device, it
+ initialized for the virtio-blk device, it
is now accessibla via EFI_BLOCK_IO_PROTOCOL.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
@return Error codes from the OpenProtocol() boot
- service, the PciIo protocol, VirtioBlkInit(),
- or the InstallProtocolInterface() boot service.
+ service, VirtioBlkInit(), or the
+ InstallProtocolInterface() boot service.
**/
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
index 6dffc3a22a..86266b26c4 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
@@ -38,5 +38,5 @@
VirtioLib
[Protocols]
- gEfiBlockIoProtocolGuid ## BY_START
- gEfiPciIoProtocolGuid ## TO_START
+ gEfiBlockIoProtocolGuid ## BY_START
+ gVirtioDeviceProtocolGuid ## TO_START
diff --git a/OvmfPkg/VirtioNetDxe/ComponentName.c b/OvmfPkg/VirtioNetDxe/ComponentName.c
index a291405ee6..1a43448fd4 100644
--- a/OvmfPkg/VirtioNetDxe/ComponentName.c
+++ b/OvmfPkg/VirtioNetDxe/ComponentName.c
@@ -139,20 +139,20 @@ VirtioNetGetControllerName (
}
//
- // confirm that the device is managed by this driver, using the PCI IO
+ // confirm that the device is managed by this driver, using the VirtIo
// Protocol
//
Status = EfiTestManagedDevice (
ControllerHandle,
gVirtioNetDriverBinding.DriverBindingHandle,
- &gEfiPciIoProtocolGuid
+ &gVirtioDeviceProtocolGuid
);
if (EFI_ERROR (Status)) {
return Status;
}
//
- // we don't give different names to the bus (= parent, = PCI) handle and the
+ // we don't give different names to the bus (= parent) handle and the
// child (= MAC) handle
//
return LookupUnicodeString2 (
diff --git a/OvmfPkg/VirtioNetDxe/DriverBinding.c b/OvmfPkg/VirtioNetDxe/DriverBinding.c
index c9259ab339..f92a447f00 100644
--- a/OvmfPkg/VirtioNetDxe/DriverBinding.c
+++ b/OvmfPkg/VirtioNetDxe/DriverBinding.c
@@ -15,7 +15,6 @@
**/
-#include <IndustryStandard/Pci.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DevicePathLib.h>
#include <Library/MemoryAllocationLib.h>
@@ -50,7 +49,7 @@
unused.
@retval EFI_UNSUPPORTED The host doesn't supply a MAC address.
- @return Status codes from Dev->PciIo->Io.Read(),
+ @return Status codes from Dev->VirtIo->Io.Read(),
VIRTIO_CFG_READ() and VIRTIO_CFG_WRITE().
@retval EFI_SUCCESS Configuration values retrieved.
*/
@@ -74,19 +73,19 @@ VirtioNetGetFeatures (
// Initialization Sequence), but don't complete setting it up.
//
NextDevStat = 0; // step 1 -- reset device
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
return Status;
}
NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
goto YieldDevice;
}
NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
goto YieldDevice;
}
@@ -94,7 +93,7 @@ VirtioNetGetFeatures (
//
// step 4a -- retrieve and validate features
//
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);
+ Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
if (EFI_ERROR (Status)) {
goto YieldDevice;
}
@@ -106,13 +105,12 @@ VirtioNetGetFeatures (
Status = EFI_UNSUPPORTED;
goto YieldDevice;
}
- Status = Dev->PciIo->Io.Read (Dev->PciIo, // PciIo
- EfiPciIoWidthUint8, // Width
- PCI_BAR_IDX0, // BarIndex
- OFFSET_OF_VNET (VhdrMac), // Offset
- SIZE_OF_VNET (VhdrMac), // Count
- MacAddress // Buffer
- );
+ 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;
@@ -126,7 +124,7 @@ VirtioNetGetFeatures (
}
else {
*MediaPresentSupported = TRUE;
- Status = VIRTIO_CFG_READ (Dev, VhdrLinkStatus, &LinkStatus);
+ Status = VIRTIO_CFG_READ (Dev, LinkStatus, &LinkStatus);
if (EFI_ERROR (Status)) {
goto YieldDevice;
}
@@ -134,7 +132,7 @@ VirtioNetGetFeatures (
}
YieldDevice:
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus,
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo,
EFI_ERROR (Status) ? VSTAT_FAILED : 0);
return Status;
@@ -207,9 +205,9 @@ VirtioNetSnpPopulate (
Dev->Snp.Mode = &Dev->Snm;
Dev->Snm.State = EfiSimpleNetworkStopped;
- Dev->Snm.HwAddressSize = SIZE_OF_VNET (VhdrMac);
- Dev->Snm.MediaHeaderSize = SIZE_OF_VNET (VhdrMac) + // dst MAC
- SIZE_OF_VNET (VhdrMac) + // src MAC
+ Dev->Snm.HwAddressSize = SIZE_OF_VNET (Mac);
+ Dev->Snm.MediaHeaderSize = SIZE_OF_VNET (Mac) + // dst MAC
+ SIZE_OF_VNET (Mac) + // src MAC
2; // Ethertype
Dev->Snm.MaxPacketSize = 1500;
Dev->Snm.NvRamSize = 0;
@@ -222,7 +220,7 @@ VirtioNetSnpPopulate (
Dev->Snm.MacAddressChangeable = FALSE;
Dev->Snm.MultipleTxSupported = TRUE;
- ASSERT (SIZE_OF_VNET (VhdrMac) <= sizeof (EFI_MAC_ADDRESS));
+ ASSERT (SIZE_OF_VNET (Mac) <= sizeof (EFI_MAC_ADDRESS));
Status = VirtioNetGetFeatures (Dev, &Dev->Snm.CurrentAddress,
&Dev->Snm.MediaPresentSupported, &Dev->Snm.MediaPresent);
@@ -230,8 +228,8 @@ VirtioNetSnpPopulate (
goto CloseWaitForPacket;
}
CopyMem (&Dev->Snm.PermanentAddress, &Dev->Snm.CurrentAddress,
- SIZE_OF_VNET (VhdrMac));
- SetMem (&Dev->Snm.BroadcastAddress, SIZE_OF_VNET (VhdrMac), 0xFF);
+ SIZE_OF_VNET (Mac));
+ SetMem (&Dev->Snm.BroadcastAddress, SIZE_OF_VNET (Mac), 0xFF);
//
// VirtioNetExitBoot() is queued by ExitBootServices(); its purpose is to
@@ -348,31 +346,36 @@ VirtioNetDriverBindingSupported (
)
{
EFI_STATUS Status;
- EFI_PCI_IO_PROTOCOL *PciIo;
- PCI_TYPE00 Pci;
-
- Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
- (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER);
+ VIRTIO_DEVICE_PROTOCOL *VirtIo;
+
+ //
+ // Attempt to open the device with the VirtIo set of interfaces. On success,
+ // the protocol is "instantiated" for the VirtIo device. Covers duplicate open
+ // attempts (EFI_ALREADY_STARTED).
+ //
+ Status = gBS->OpenProtocol (
+ DeviceHandle, // candidate device
+ &gVirtioDeviceProtocolGuid, // for generic VirtIo access
+ (VOID **)&VirtIo, // handle to instantiate
+ This->DriverBindingHandle, // requestor driver identity
+ DeviceHandle, // ControllerHandle, according to
+ // the UEFI Driver Model
+ EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to
+ // the device; to be released
+ );
if (EFI_ERROR (Status)) {
return Status;
}
- Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0,
- sizeof Pci / sizeof (UINT32), &Pci);
+ if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_NETWORK_CARD) {
+ Status = EFI_UNSUPPORTED;
+ }
//
- // virtio-0.9.5, 2.1 PCI Discovery:
- // the network device has Subsystem Device ID 1
+ // We needed VirtIo access only transitorily, to see whether we support the
+ // device or not.
//
- if (Status == EFI_SUCCESS) {
- Status = (Pci.Hdr.VendorId == 0x1AF4 &&
- Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F &&
- Pci.Hdr.RevisionID == 0x00 &&
- Pci.Device.SubsystemID == VIRTIO_SUBSYSTEM_NETWORK_CARD) ? EFI_SUCCESS : EFI_UNSUPPORTED;
- }
-
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
return Status;
}
@@ -438,7 +441,7 @@ VirtioNetDriverBindingStart (
VNET_DEV *Dev;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
MAC_ADDR_DEVICE_PATH MacNode;
- VOID *ChildPciIo;
+ VOID *ChildVirtIo;
//
// allocate space for the driver instance
@@ -449,30 +452,15 @@ VirtioNetDriverBindingStart (
}
Dev->Signature = VNET_SIG;
- //
- // get PCI access to the device and keep it open
- //
- Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
- (VOID **)&Dev->PciIo, This->DriverBindingHandle,
+ Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
+ (VOID **)&Dev->VirtIo, This->DriverBindingHandle,
DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
if (EFI_ERROR (Status)) {
goto FreeVirtioNet;
}
- //
- // save original PCI attributes and enable IO space access
- //
- Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet,
- 0, &Dev->OrigPciAttributes);
- if (EFI_ERROR (Status)) {
- goto ClosePciIo;
- }
-
- Status = Dev->PciIo->Attributes (Dev->PciIo,
- EfiPciIoAttributeOperationEnable,
- EFI_PCI_IO_ATTRIBUTE_IO, NULL);
- if (EFI_ERROR (Status)) {
- goto ClosePciIo;
+ if (Dev->VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_NETWORK_CARD) {
+ return EFI_UNSUPPORTED;
}
//
@@ -481,11 +469,11 @@ VirtioNetDriverBindingStart (
//
Status = VirtioNetSnpPopulate (Dev);
if (EFI_ERROR (Status)) {
- goto RestorePciAttributes;
+ goto CloseVirtIo;
}
//
- // get the device path of the virtio-net PCI device -- one-shot open
+ // get the device path of the virtio-net device -- one-shot open
//
Status = gBS->OpenProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid,
(VOID **)&DevicePath, This->DriverBindingHandle,
@@ -523,11 +511,11 @@ VirtioNetDriverBindingStart (
}
//
- // make a note that we keep this device open with PciIo for the sake of this
+ // make a note that we keep this device open with VirtIo for the sake of this
// child
//
- Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
- &ChildPciIo, This->DriverBindingHandle,
+ Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
+ &ChildVirtIo, This->DriverBindingHandle,
Dev->MacHandle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
if (EFI_ERROR (Status)) {
goto UninstallMultiple;
@@ -547,12 +535,8 @@ FreeMacDevicePath:
Evacuate:
VirtioNetSnpEvacuate (Dev);
-RestorePciAttributes:
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,
- Dev->OrigPciAttributes, NULL);
-
-ClosePciIo:
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+CloseVirtIo:
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
FreeVirtioNet:
@@ -637,7 +621,7 @@ VirtioNetDriverBindingStop (
Status = EFI_DEVICE_ERROR;
}
else {
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, Dev->MacHandle);
gBS->UninstallMultipleProtocolInterfaces (Dev->MacHandle,
&gEfiDevicePathProtocolGuid, Dev->MacDevicePath,
@@ -645,8 +629,6 @@ VirtioNetDriverBindingStop (
NULL);
FreePool (Dev->MacDevicePath);
VirtioNetSnpEvacuate (Dev);
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,
- Dev->OrigPciAttributes, NULL);
FreePool (Dev);
}
@@ -657,7 +639,7 @@ VirtioNetDriverBindingStop (
//
// release remaining resources, tied directly to the parent handle
//
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
return EFI_SUCCESS;
diff --git a/OvmfPkg/VirtioNetDxe/Events.c b/OvmfPkg/VirtioNetDxe/Events.c
index b9d7bbf6c6..4889580f3a 100644
--- a/OvmfPkg/VirtioNetDxe/Events.c
+++ b/OvmfPkg/VirtioNetDxe/Events.c
@@ -86,6 +86,6 @@ VirtioNetExitBoot (
Dev = Context;
if (Dev->Snm.State == EfiSimpleNetworkInitialized) {
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
}
}
diff --git a/OvmfPkg/VirtioNetDxe/SnpGetStatus.c b/OvmfPkg/VirtioNetDxe/SnpGetStatus.c
index adb57cf8fe..b920115616 100644
--- a/OvmfPkg/VirtioNetDxe/SnpGetStatus.c
+++ b/OvmfPkg/VirtioNetDxe/SnpGetStatus.c
@@ -90,7 +90,7 @@ VirtioNetGetStatus (
if (Dev->Snm.MediaPresentSupported) {
UINT16 LinkStatus;
- Status = VIRTIO_CFG_READ (Dev, VhdrLinkStatus, &LinkStatus);
+ Status = VIRTIO_CFG_READ (Dev, LinkStatus, &LinkStatus);
if (EFI_ERROR (Status)) {
goto Exit;
}
diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
index 6cee014072..4352ab96b6 100644
--- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
+++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
@@ -57,14 +57,15 @@ VirtioNetInitRing (
//
// step 4b -- allocate selected queue
//
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect, Selector);
+ Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, Selector);
if (EFI_ERROR (Status)) {
return Status;
}
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize);
+ Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);
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
@@ -80,8 +81,8 @@ VirtioNetInitRing (
//
// step 4c -- report GPFN (guest-physical frame number) of queue
//
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueAddress,
- (UINTN) Ring->Base >> EFI_PAGE_SHIFT);
+ Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,
+ (UINTN) Ring->Base >> EFI_PAGE_SHIFT);
if (EFI_ERROR (Status)) {
VirtioRingUninit (Ring);
}
@@ -287,10 +288,9 @@ VirtioNetInitRx (
// virtio-0.9.5, 2.4.1.4 Notifying the Device
//
MemoryFence ();
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueNotify, VIRTIO_NET_Q_RX);
-
+ Status = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX);
if (EFI_ERROR (Status)) {
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
FreePool (Dev->RxBuf);
}
@@ -366,25 +366,34 @@ VirtioNetInitialize (
// virtio-0.9.5 spec, 2.2.1 Device Initialization Sequence.
//
NextDevStat = VSTAT_ACK; // step 2 -- acknowledge device presence
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ 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 = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ 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;
+ }
+
+ //
// step 4a -- retrieve features. Note that we're past validating required
// features in VirtioNetGetFeatures().
//
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);
+ 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));
@@ -406,7 +415,7 @@ VirtioNetInitialize (
// step 5 -- keep only the features we want
//
Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS;
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits, Features);
+ Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
if (EFI_ERROR (Status)) {
goto ReleaseTxRing;
}
@@ -415,7 +424,7 @@ VirtioNetInitialize (
// step 6 -- virtio-net initialization complete
//
NextDevStat |= VSTAT_DRIVER_OK;
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
goto ReleaseTxRing;
}
@@ -441,7 +450,7 @@ ReleaseTxAux:
VirtioNetShutdownTx (Dev);
AbortDevice:
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
ReleaseTxRing:
VirtioRingUninit (&Dev->TxRing);
@@ -453,7 +462,7 @@ DeviceFailed:
//
// restore device status invariant for the EfiSimpleNetworkStarted state
//
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
InitFailed:
gBS->RestoreTPL (OldTpl);
diff --git a/OvmfPkg/VirtioNetDxe/SnpReceive.c b/OvmfPkg/VirtioNetDxe/SnpReceive.c
index 87c6ca9b4b..ce87978f1f 100644
--- a/OvmfPkg/VirtioNetDxe/SnpReceive.c
+++ b/OvmfPkg/VirtioNetDxe/SnpReceive.c
@@ -147,14 +147,14 @@ VirtioNetReceive (
CopyMem (Buffer, RxPtr, RxLen);
if (DestAddr != NULL) {
- CopyMem (DestAddr, RxPtr, SIZE_OF_VNET (VhdrMac));
+ CopyMem (DestAddr, RxPtr, SIZE_OF_VNET (Mac));
}
- RxPtr += SIZE_OF_VNET (VhdrMac);
+ RxPtr += SIZE_OF_VNET (Mac);
if (SrcAddr != NULL) {
- CopyMem (SrcAddr, RxPtr, SIZE_OF_VNET (VhdrMac));
+ CopyMem (SrcAddr, RxPtr, SIZE_OF_VNET (Mac));
}
- RxPtr += SIZE_OF_VNET (VhdrMac);
+ RxPtr += SIZE_OF_VNET (Mac);
if (Protocol != NULL) {
*Protocol = (UINT16) ((RxPtr[0] << 8) | RxPtr[1]);
@@ -177,9 +177,7 @@ RecycleDesc:
*Dev->RxRing.Avail.Idx = AvailIdx;
MemoryFence ();
- NotifyStatus = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueNotify,
- VIRTIO_NET_Q_RX);
-
+ NotifyStatus = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX);
if (!EFI_ERROR (Status)) { // earlier error takes precedence
Status = NotifyStatus;
}
diff --git a/OvmfPkg/VirtioNetDxe/SnpShutdown.c b/OvmfPkg/VirtioNetDxe/SnpShutdown.c
index 42aeca1676..c05a22f659 100644
--- a/OvmfPkg/VirtioNetDxe/SnpShutdown.c
+++ b/OvmfPkg/VirtioNetDxe/SnpShutdown.c
@@ -63,7 +63,7 @@ VirtioNetShutdown (
break;
}
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
VirtioNetShutdownRx (Dev);
VirtioNetShutdownTx (Dev);
VirtioRingUninit (&Dev->TxRing);
diff --git a/OvmfPkg/VirtioNetDxe/SnpTransmit.c b/OvmfPkg/VirtioNetDxe/SnpTransmit.c
index ff922ca021..b2a364b968 100644
--- a/OvmfPkg/VirtioNetDxe/SnpTransmit.c
+++ b/OvmfPkg/VirtioNetDxe/SnpTransmit.c
@@ -127,15 +127,15 @@ VirtioNetTransmit (
goto Exit;
}
Ptr = Buffer;
- ASSERT (SIZE_OF_VNET (VhdrMac) <= sizeof (EFI_MAC_ADDRESS));
+ ASSERT (SIZE_OF_VNET (Mac) <= sizeof (EFI_MAC_ADDRESS));
- CopyMem (Ptr, DestAddr, SIZE_OF_VNET (VhdrMac));
- Ptr += SIZE_OF_VNET (VhdrMac);
+ CopyMem (Ptr, DestAddr, SIZE_OF_VNET (Mac));
+ Ptr += SIZE_OF_VNET (Mac);
CopyMem (Ptr,
(SrcAddr == NULL) ? &Dev->Snm.CurrentAddress : SrcAddr,
- SIZE_OF_VNET (VhdrMac));
- Ptr += SIZE_OF_VNET (VhdrMac);
+ SIZE_OF_VNET (Mac));
+ Ptr += SIZE_OF_VNET (Mac);
*Ptr++ = (UINT8) (*Protocol >> 8);
*Ptr++ = (UINT8) *Protocol;
@@ -161,7 +161,7 @@ VirtioNetTransmit (
*Dev->TxRing.Avail.Idx = AvailIdx;
MemoryFence ();
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueNotify, VIRTIO_NET_Q_TX);
+ Status = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_TX);
Exit:
gBS->RestoreTPL (OldTpl);
diff --git a/OvmfPkg/VirtioNetDxe/VirtioNet.h b/OvmfPkg/VirtioNetDxe/VirtioNet.h
index 8c21bcdfa2..a0e0b4337c 100644
--- a/OvmfPkg/VirtioNetDxe/VirtioNet.h
+++ b/OvmfPkg/VirtioNetDxe/VirtioNet.h
@@ -24,7 +24,6 @@
#include <Protocol/ComponentName2.h>
#include <Protocol/DevicePath.h>
#include <Protocol/DriverBinding.h>
-#include <Protocol/PciIo.h>
#include <Protocol/SimpleNetwork.h>
#define VNET_SIG SIGNATURE_32 ('V', 'N', 'E', 'T')
@@ -75,8 +74,7 @@ typedef struct {
// field init function
// ------------------ ------------------------------
UINT32 Signature; // VirtioNetDriverBindingStart
- EFI_PCI_IO_PROTOCOL *PciIo; // VirtioNetDriverBindingStart
- UINT64 OrigPciAttributes; // VirtioNetDriverBindingStart
+ VIRTIO_DEVICE_PROTOCOL *VirtIo; // VirtioNetDriverBindingStart
EFI_SIMPLE_NETWORK_PROTOCOL Snp; // VirtioNetSnpPopulate
EFI_SIMPLE_NETWORK_MODE Snm; // VirtioNetSnpPopulate
EFI_EVENT ExitBoot; // VirtioNetSnpPopulate
@@ -109,19 +107,19 @@ typedef struct {
#define VIRTIO_NET_FROM_SNP(SnpPointer) \
CR (SnpPointer, VNET_DEV, Snp, VNET_SIG)
-#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWrite ( \
- (Dev)->PciIo, \
- OFFSET_OF_VNET (Field), \
- SIZE_OF_VNET (Field), \
- (Value) \
+#define VIRTIO_CFG_WRITE(Dev, Field, Value) ((Dev)->VirtIo->WriteDevice ( \
+ (Dev)->VirtIo, \
+ OFFSET_OF_VNET (Field), \
+ SIZE_OF_VNET (Field), \
+ (Value) \
))
-#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead ( \
- (Dev)->PciIo, \
- OFFSET_OF_VNET (Field), \
- SIZE_OF_VNET (Field), \
- sizeof *(Pointer), \
- (Pointer) \
+#define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \
+ (Dev)->VirtIo, \
+ OFFSET_OF_VNET (Field), \
+ SIZE_OF_VNET (Field), \
+ sizeof *(Pointer), \
+ (Pointer) \
))
//
diff --git a/OvmfPkg/VirtioNetDxe/VirtioNet.inf b/OvmfPkg/VirtioNetDxe/VirtioNet.inf
index 408a54112a..dea01f3b9a 100644
--- a/OvmfPkg/VirtioNetDxe/VirtioNet.inf
+++ b/OvmfPkg/VirtioNetDxe/VirtioNet.inf
@@ -57,4 +57,4 @@
[Protocols]
gEfiSimpleNetworkProtocolGuid ## BY_START
gEfiDevicePathProtocolGuid ## BY_START
- gEfiPciIoProtocolGuid ## TO_START
+ gVirtioDeviceProtocolGuid ## TO_START
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
new file mode 100644
index 0000000000..b120d5f2ca
--- /dev/null
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
@@ -0,0 +1,667 @@
+/** @file
+
+ This driver produces Virtio Device Protocol instances for Virtio PCI devices.
+
+ Copyright (C) 2012, Red Hat, Inc.
+ Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
+ Copyright (C) 2013, ARM Ltd.
+
+ 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/Pci.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include "VirtioPciDevice.h"
+
+STATIC VIRTIO_DEVICE_PROTOCOL mDeviceProtocolTemplate = {
+ 0, // Revision
+ 0, // SubSystemDeviceId
+ VirtioPciGetDeviceFeatures, // GetDeviceFeatures
+ VirtioPciSetGuestFeatures, // SetGuestFeatures
+ VirtioPciGetQueueAddress, // GetQueueAddress
+ VirtioPciSetQueueAddress, // SetQueueAddress
+ VirtioPciSetQueueSel, // SetQueueSel
+ VirtioPciSetQueueNotify, // SetQueueNotify
+ VirtioPciSetQueueAlignment, // SetQueueAlignment
+ VirtioPciSetPageSize, // SetPageSize
+ VirtioPciGetQueueSize, // GetQueueNumMax
+ VirtioPciSetQueueSize, // SetQueueNum
+ VirtioPciGetDeviceStatus, // GetDeviceStatus
+ VirtioPciSetDeviceStatus, // SetDeviceStatus
+ VirtioPciDeviceWrite, // WriteDevice
+ VirtioPciDeviceRead // ReadDevice
+};
+
+/**
+
+ 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 PCI
+ implementation of the protocol.
+
+ @param[in] Dev Virtio 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().
+
+**/
+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);
+
+ PciIo = Dev->PciIo;
+ Count = BufferSize / FieldSize;
+
+ 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;
+ // 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,
+ Buffer
+ );
+}
+
+/**
+
+ 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 PCI
+ implementation of the protocol.
+
+ @param[in] Dev Virtio 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().
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioPciIoWrite (
+ IN VIRTIO_PCI_DEVICE *Dev,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINT64 Value
+ )
+{
+ UINTN Count;
+ EFI_PCI_IO_PROTOCOL_WIDTH Width;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ PciIo = Dev->PciIo;
+ 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 writes 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;
+ // fall through
+
+ case 4:
+ Width = EfiPciIoWidthUint32;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PciIo->Io.Write (
+ PciIo,
+ Width,
+ PCI_BAR_IDX0,
+ FieldOffset,
+ Count,
+ &Value
+ );
+}
+
+/**
+
+ Device probe function for this driver.
+
+ The DXE core calls this function for any given device in order to see if the
+ driver can drive the device.
+
+ @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
+ incorporating this driver (independently of
+ any device).
+
+ @param[in] DeviceHandle The device to probe.
+
+ @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
+
+
+ @retval EFI_SUCCESS The driver supports the device being probed.
+
+ @retval EFI_UNSUPPORTED Based on virtio-pci discovery, we do not support
+ the device.
+
+ @return Error codes from the OpenProtocol() boot service or
+ the PciIo protocol.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+VirtioPciDeviceBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE DeviceHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ //
+ // Attempt to open the device with the PciIo set of interfaces. On success,
+ // the protocol is "instantiated" for the PCI device. Covers duplicate open
+ // attempts (EFI_ALREADY_STARTED).
+ //
+ Status = gBS->OpenProtocol (
+ DeviceHandle, // candidate device
+ &gEfiPciIoProtocolGuid, // for generic PCI access
+ (VOID **)&PciIo, // handle to instantiate
+ This->DriverBindingHandle, // requestor driver identity
+ DeviceHandle, // ControllerHandle, according to
+ // the UEFI Driver Model
+ EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to
+ // the device; to be released
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Read entire PCI configuration header for more extensive check ahead.
+ //
+ Status = PciIo->Pci.Read (
+ PciIo, // (protocol, device)
+ // handle
+ EfiPciIoWidthUint32, // access width & copy
+ // mode
+ 0, // Offset
+ sizeof Pci / sizeof (UINT32), // Count
+ &Pci // target buffer
+ );
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // virtio-0.9.5, 2.1 PCI Discovery
+ //
+ if ((Pci.Hdr.VendorId == VIRTIO_VENDOR_ID) &&
+ (Pci.Hdr.DeviceId >= 0x1000) &&
+ (Pci.Hdr.DeviceId <= 0x103F) &&
+ (Pci.Hdr.RevisionID == 0x00)) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // We needed PCI IO access only transitorily, to see whether we support the
+ // device or not.
+ //
+ gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle, DeviceHandle);
+
+ return Status;
+}
+
+/**
+
+ Initialize the VirtIo PCI Device
+
+ @param[in, out] Dev The driver instance to configure. The caller is
+ responsible for Device->PciIo's validity (ie. working IO
+ access to the underlying virtio-pci device).
+
+ @retval EFI_SUCCESS Setup complete.
+
+ @retval EFI_UNSUPPORTED The underlying IO device doesn't support the
+ provided address offset and read size.
+
+ @return Error codes from PciIo->Pci.Read().
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+VirtioPciInit (
+ IN OUT VIRTIO_PCI_DEVICE *Device
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ ASSERT (Device != NULL);
+ PciIo = Device->PciIo;
+ ASSERT (PciIo != NULL);
+ ASSERT (PciIo->Pci.Read != NULL);
+
+ Status = PciIo->Pci.Read (
+ PciIo, // (protocol, device)
+ // handle
+ EfiPciIoWidthUint32, // access width & copy
+ // mode
+ 0, // Offset
+ sizeof (Pci) / sizeof (UINT32), // Count
+ &Pci // target buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Copy protocol template
+ CopyMem (&Device->VirtioDevice, &mDeviceProtocolTemplate,
+ sizeof (VIRTIO_DEVICE_PROTOCOL));
+
+ // Initialize the protocol interface attributes
+ Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5);
+ Device->VirtioDevice.SubSystemDeviceId = Pci.Device.SubsystemID;
+
+ // Note: We don't support the MSI-X capability. If we did,
+ // the offset would become 24 after enabling MSI-X.
+ Device->DeviceSpecificConfigurationOffset =
+ VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI;
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Uninitialize the internals of a virtio-pci device that has been successfully
+ set up with VirtioPciInit().
+
+ @param[in, out] Dev The device to clean up.
+
+**/
+
+STATIC
+VOID
+EFIAPI
+VirtioPciUninit (
+ IN OUT VIRTIO_PCI_DEVICE *Device
+ )
+{
+ // Note: This function mirrors VirtioPciInit() that does not allocate any
+ // resources - there's nothing to free here.
+}
+
+/**
+
+ After we've pronounced support for a specific device in
+ DriverBindingSupported(), we start managing said device (passed in by the
+ Driver Exeuction Environment) with the following service.
+
+ See DriverBindingSupported() for specification references.
+
+ @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
+ incorporating this driver (independently of
+ any device).
+
+ @param[in] DeviceHandle The supported device to drive.
+
+ @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
+
+
+ @retval EFI_SUCCESS Driver instance has been created and
+ initialized for the virtio-pci device, it
+ is now accessible via VIRTIO_DEVICE_PROTOCOL.
+
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
+
+ @return Error codes from the OpenProtocol() boot
+ service, the PciIo protocol, VirtioPciInit(),
+ or the InstallProtocolInterface() boot service.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+VirtioPciDeviceBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE DeviceHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ VIRTIO_PCI_DEVICE *Device;
+ EFI_STATUS Status;
+
+ Device = (VIRTIO_PCI_DEVICE *) AllocateZeroPool (sizeof *Device);
+ if (Device == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+ (VOID **)&Device->PciIo, This->DriverBindingHandle,
+ DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
+ if (EFI_ERROR (Status)) {
+ goto FreeVirtioPci;
+ }
+
+ //
+ // We must retain and ultimately restore the original PCI attributes of the
+ // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /
+ // 18.3.2 Start() and Stop().
+ //
+ // The third parameter ("Attributes", input) is ignored by the Get operation.
+ // The fourth parameter ("Result", output) is ignored by the Enable and Set
+ // operations.
+ //
+ // For virtio-pci we only need IO space access.
+ //
+ Status = Device->PciIo->Attributes (Device->PciIo,
+ EfiPciIoAttributeOperationGet, 0, &Device->OriginalPciAttributes);
+ if (EFI_ERROR (Status)) {
+ goto ClosePciIo;
+ }
+
+ Status = Device->PciIo->Attributes (Device->PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_IO_ATTRIBUTE_IO, NULL);
+ if (EFI_ERROR (Status)) {
+ goto ClosePciIo;
+ }
+
+ //
+ // PCI IO access granted, configure protocol instance
+ //
+
+ Status = VirtioPciInit (Device);
+ if (EFI_ERROR (Status)) {
+ goto RestorePciAttributes;
+ }
+
+ //
+ // Setup complete, attempt to export the driver instance's VirtioDevice
+ // interface.
+ //
+ Device->Signature = VIRTIO_PCI_DEVICE_SIGNATURE;
+ Status = gBS->InstallProtocolInterface (&DeviceHandle,
+ &gVirtioDeviceProtocolGuid, EFI_NATIVE_INTERFACE,
+ &Device->VirtioDevice);
+ if (EFI_ERROR (Status)) {
+ goto UninitDev;
+ }
+
+ return EFI_SUCCESS;
+
+UninitDev:
+ VirtioPciUninit (Device);
+
+RestorePciAttributes:
+ Device->PciIo->Attributes (Device->PciIo, EfiPciIoAttributeOperationSet,
+ Device->OriginalPciAttributes, NULL);
+
+ClosePciIo:
+ gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle, DeviceHandle);
+
+FreeVirtioPci:
+ FreePool (Device);
+
+ return Status;
+}
+
+/**
+
+ Stop driving the Virtio PCI device
+
+ @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
+ incorporating this driver (independently of any
+ device).
+
+ @param[in] DeviceHandle Stop driving this device.
+
+ @param[in] NumberOfChildren Since this function belongs to a device driver
+ only (as opposed to a bus driver), the caller
+ environment sets NumberOfChildren to zero, and
+ we ignore it.
+
+ @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
+
+ @retval EFI_SUCCESS Driver instance has been stopped and the PCI
+ configuration attributes have been restored.
+
+ @return Error codes from the OpenProtocol() or
+ CloseProtocol(), UninstallProtocolInterface()
+ boot services.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+VirtioPciDeviceBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE DeviceHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ VIRTIO_DEVICE_PROTOCOL *VirtioDevice;
+ VIRTIO_PCI_DEVICE *Device;
+
+ Status = gBS->OpenProtocol (
+ DeviceHandle, // candidate device
+ &gVirtioDeviceProtocolGuid, // retrieve the VirtIo iface
+ (VOID **)&VirtioDevice, // target pointer
+ This->DriverBindingHandle, // requestor driver identity
+ DeviceHandle, // requesting lookup for dev.
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Device = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice);
+
+ //
+ // Handle Stop() requests for in-use driver instances gracefully.
+ //
+ Status = gBS->UninstallProtocolInterface (DeviceHandle,
+ &gVirtioDeviceProtocolGuid, &Device->VirtioDevice);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ VirtioPciUninit (Device);
+
+ Device->PciIo->Attributes (Device->PciIo, EfiPciIoAttributeOperationSet,
+ Device->OriginalPciAttributes, NULL);
+
+ Status = gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle, DeviceHandle);
+
+ FreePool (Device);
+
+ return Status;
+}
+
+
+//
+// The static object that groups the Supported() (ie. probe), Start() and
+// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
+// C, 10.1 EFI Driver Binding Protocol.
+//
+STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
+ &VirtioPciDeviceBindingSupported,
+ &VirtioPciDeviceBindingStart,
+ &VirtioPciDeviceBindingStop,
+ 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
+ NULL, // ImageHandle, to be overwritten by
+ // EfiLibInstallDriverBindingComponentName2() in VirtioPciEntryPoint()
+ NULL // DriverBindingHandle, ditto
+};
+
+
+//
+// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
+// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
+// in English, for display on standard console devices. This is recommended for
+// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
+// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
+//
+STATIC
+EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
+ { "eng;en", L"Virtio PCI Driver" },
+ { NULL, NULL }
+};
+
+STATIC
+EFI_COMPONENT_NAME_PROTOCOL gComponentName;
+
+EFI_STATUS
+EFIAPI
+VirtioPciGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gComponentName) // Iso639Language
+ );
+}
+
+EFI_STATUS
+EFIAPI
+VirtioPciGetDeviceName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE DeviceHandle,
+ IN EFI_HANDLE ChildHandle,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
+ &VirtioPciGetDriverName,
+ &VirtioPciGetDeviceName,
+ "eng" // SupportedLanguages, ISO 639-2 language codes
+};
+
+STATIC
+EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &VirtioPciGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &VirtioPciGetDeviceName,
+ "en" // SupportedLanguages, RFC 4646 language codes
+};
+
+
+//
+// Entry point of this driver.
+//
+EFI_STATUS
+EFIAPI
+VirtioPciDeviceEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gDriverBinding,
+ ImageHandle,
+ &gComponentName,
+ &gComponentName2
+ );
+}
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
new file mode 100644
index 0000000000..bbad164f6f
--- /dev/null
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
@@ -0,0 +1,166 @@
+/** @file
+
+ Internal definitions for the VirtIo PCI Device driver
+
+ Copyright (C) 2013, ARM Ltd
+
+ 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_PCI_DEVICE_DXE_H_
+#define _VIRTIO_PCI_DEVICE_DXE_H_
+
+#include <Protocol/ComponentName.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/VirtioDevice.h>
+
+#include <IndustryStandard/Virtio.h>
+
+#define VIRTIO_PCI_DEVICE_SIGNATURE SIGNATURE_32 ('V', 'P', 'C', 'I')
+
+typedef struct {
+ UINT32 Signature;
+ VIRTIO_DEVICE_PROTOCOL VirtioDevice;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 OriginalPciAttributes;
+ UINT32 DeviceSpecificConfigurationOffset;
+} VIRTIO_PCI_DEVICE;
+
+#define VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE(Device) \
+ CR (Device, VIRTIO_PCI_DEVICE, VirtioDevice, VIRTIO_PCI_DEVICE_SIGNATURE)
+
+
+EFI_STATUS
+EFIAPI
+VirtioPciIoRead (
+ IN VIRTIO_PCI_DEVICE *Dev,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciIoWrite (
+ IN VIRTIO_PCI_DEVICE *Dev,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINT64 Value
+ );
+
+/********************************************
+ * PCI Functions for VIRTIO_DEVICE_PROTOCOL
+ *******************************************/
+EFI_STATUS
+EFIAPI
+VirtioPciDeviceRead (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciDeviceWrite (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINT64 Value
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciGetDeviceFeatures (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT32 *DeviceFeatures
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciGetQueueAddress (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT32 *QueueAddress
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciGetQueueSize (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT16 *QueueNumMax
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciSetQueueAlignment (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT32 Alignment
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciSetPageSize (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT32 PageSize
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciGetDeviceStatus (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT8 *DeviceStatus
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciSetGuestFeatures (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT32 Features
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciSetQueueAddress (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT32 Address
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciSetQueueSel (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT16 Sel
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciSetQueueNotify (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT16 Index
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciSetQueueSize (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT16 Size
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciSetDeviceStatus (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT8 DeviceStatus
+ );
+
+#endif // _VIRTIO_PCI_DEVICE_DXE_H_
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
new file mode 100644
index 0000000000..90a5dbc2b0
--- /dev/null
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
@@ -0,0 +1,43 @@
+## @file
+# This driver produces the VirtIo Device Protocol instances for VirtIo PCI
+# Device
+#
+# Copyright (C) 2013, ARM Ltd
+#
+# 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 = 0x00010006
+ BASE_NAME = VirtioPciDeviceDxe
+ FILE_GUID = 83dd3b39-7caf-4fac-a542-e050b767e3a7
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = VirtioPciDeviceEntryPoint
+
+[Sources]
+ VirtioPciDevice.c
+ VirtioPciFunctions.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gEfiPciIoProtocolGuid ## TO_START
+ gVirtioDeviceProtocolGuid ## BY_START
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
new file mode 100644
index 0000000000..e9e48b945c
--- /dev/null
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
@@ -0,0 +1,285 @@
+/** @file
+
+ This driver produces Virtio Device Protocol instances for Virtio PCI devices.
+
+ Copyright (C) 2012, Red Hat, Inc.
+ Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
+ Copyright (C) 2013, ARM Ltd.
+
+ 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/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.
+
+ The function implements the ReadDevice protocol member of
+ VIRTIO_DEVICE_PROTOCOL.
+
+ @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().
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioPciDeviceRead (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ VIRTIO_PCI_DEVICE *Dev;
+
+ Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ return VirtioPciIoRead (Dev,
+ Dev->DeviceSpecificConfigurationOffset + FieldOffset,
+ FieldSize, BufferSize, Buffer);
+}
+
+/**
+
+ Write a word into Region 0 of the device specified by VirtIo Device protocol.
+
+ @param[in] This VirtIo Device protocol.
+
+ @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().
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioPciDeviceWrite (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINT64 Value
+ )
+{
+ VIRTIO_PCI_DEVICE *Dev;
+
+ Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ return VirtioPciIoWrite (Dev,
+ Dev->DeviceSpecificConfigurationOffset + FieldOffset, FieldSize, Value);
+}
+
+EFI_STATUS
+EFIAPI
+VirtioPciGetDeviceFeatures (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT32 *DeviceFeatures
+ )
+{
+ VIRTIO_PCI_DEVICE *Dev;
+
+ if (DeviceFeatures == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_DEVICE_FEATURES, sizeof (UINT32),
+ sizeof (UINT32), DeviceFeatures);
+}
+
+EFI_STATUS
+EFIAPI
+VirtioPciGetQueueAddress (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT32 *QueueAddress
+ )
+{
+ VIRTIO_PCI_DEVICE *Dev;
+
+ if (QueueAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),
+ sizeof (UINT32), QueueAddress);
+}
+
+EFI_STATUS
+EFIAPI
+VirtioPciGetQueueSize (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT16 *QueueNumMax
+ )
+{
+ VIRTIO_PCI_DEVICE *Dev;
+
+ if (QueueNumMax == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_SIZE, sizeof (UINT16),
+ sizeof (UINT16), QueueNumMax);
+}
+
+EFI_STATUS
+EFIAPI
+VirtioPciGetDeviceStatus (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT8 *DeviceStatus
+ )
+{
+ VIRTIO_PCI_DEVICE *Dev;
+
+ if (DeviceStatus == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
+ sizeof (UINT8), sizeof (UINT8), DeviceStatus);
+}
+
+EFI_STATUS
+EFIAPI
+VirtioPciSetGuestFeatures (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT32 Features
+ )
+{
+ VIRTIO_PCI_DEVICE *Dev;
+
+ Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_GUEST_FEATURES,
+ sizeof (UINT32), Features);
+}
+
+EFI_STATUS
+EFIAPI
+VirtioPciSetQueueAddress (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT32 Address
+ )
+{
+ VIRTIO_PCI_DEVICE *Dev;
+
+ Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),
+ Address);
+}
+
+EFI_STATUS
+EFIAPI
+VirtioPciSetQueueSel (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT16 Sel
+ )
+{
+ VIRTIO_PCI_DEVICE *Dev;
+
+ Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_SELECT, sizeof (UINT16),
+ Sel);
+}
+
+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;
+}
+
+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);
+}
+
+EFI_STATUS
+EFIAPI
+VirtioPciSetQueueSize (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT16 Size
+ )
+{
+ //
+ // This function is only applicable in Virtio-MMIO.
+ // (The QueueSize field is read-only in Virtio proper (PCI))
+ //
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioPciSetDeviceStatus (
+ VIRTIO_DEVICE_PROTOCOL *This,
+ UINT8 DeviceStatus
+ )
+{
+ VIRTIO_PCI_DEVICE *Dev;
+
+ Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
+ sizeof (UINT8), DeviceStatus);
+}
diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
index b836fb3e6a..3b6c3ade82 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
@@ -38,7 +38,6 @@
**/
-#include <IndustryStandard/Pci.h>
#include <IndustryStandard/VirtioScsi.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
@@ -52,14 +51,13 @@
/**
Convenience macros to read and write region 0 IO space elements of the
- virtio-scsi PCI device, for configuration purposes.
+ virtio-scsi VirtIo device, for configuration purposes.
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 VSCSI_DEV structure whose PCI IO space
- we're accessing. Dev->PciIo must be valid.
+ @param[in] Dev Pointer to the VirtIo Device Protocol
@param[in] Field A field name from VSCSI_HDR, identifying the virtio-scsi
configuration item to access.
@@ -72,23 +70,23 @@
one of UINT8, UINT16, UINT32, UINT64.
- @return Status codes returned by VirtioWrite() / VirtioRead().
+ @return Status codes returned by Virtio->WriteDevice() / Virtio->ReadDevice().
**/
-#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWrite ( \
- (Dev)->PciIo, \
- OFFSET_OF_VSCSI (Field), \
- SIZE_OF_VSCSI (Field), \
- (Value) \
+#define VIRTIO_CFG_WRITE(Dev, Field, Value) ((Dev)->VirtIo->WriteDevice ( \
+ (Dev)->VirtIo, \
+ OFFSET_OF_VSCSI (Field), \
+ SIZE_OF_VSCSI (Field), \
+ (Value) \
))
-#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead ( \
- (Dev)->PciIo, \
- OFFSET_OF_VSCSI (Field), \
- SIZE_OF_VSCSI (Field), \
- sizeof *(Pointer), \
- (Pointer) \
+#define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \
+ (Dev)->VirtIo, \
+ OFFSET_OF_VSCSI (Field), \
+ SIZE_OF_VSCSI (Field), \
+ sizeof *(Pointer), \
+ (Pointer) \
))
@@ -471,7 +469,7 @@ VirtioScsiPassThru (
// EFI_NOT_READY would save us the effort, but it would also suggest that the
// caller retry.
//
- if (VirtioFlush (Dev->PciIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring,
+ if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring,
&Indices) != EFI_SUCCESS) {
Packet->InTransferLength = 0;
Packet->OutTransferLength = 0;
@@ -718,33 +716,41 @@ VirtioScsiInit (
// Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
//
NextDevStat = 0; // step 1 -- reset device
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
goto Failed;
}
NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ 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 = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ 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;
+ }
+
+ //
// step 4a -- retrieve and validate features
//
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &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, VhdrMaxChannel, &MaxChannel);
+ Status = VIRTIO_CFG_READ (Dev, MaxChannel, &MaxChannel);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -756,7 +762,7 @@ VirtioScsiInit (
goto Failed;
}
- Status = VIRTIO_CFG_READ (Dev, VhdrNumQueues, &NumQueues);
+ Status = VIRTIO_CFG_READ (Dev, NumQueues, &NumQueues);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -765,7 +771,7 @@ VirtioScsiInit (
goto Failed;
}
- Status = VIRTIO_CFG_READ (Dev, VhdrMaxTarget, &Dev->MaxTarget);
+ Status = VIRTIO_CFG_READ (Dev, MaxTarget, &Dev->MaxTarget);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -773,7 +779,7 @@ VirtioScsiInit (
Dev->MaxTarget = PcdGet16 (PcdVirtioScsiMaxTargetLimit);
}
- Status = VIRTIO_CFG_READ (Dev, VhdrMaxLun, &Dev->MaxLun);
+ Status = VIRTIO_CFG_READ (Dev, MaxLun, &Dev->MaxLun);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -781,7 +787,7 @@ VirtioScsiInit (
Dev->MaxLun = PcdGet32 (PcdVirtioScsiMaxLunLimit);
}
- Status = VIRTIO_CFG_READ (Dev, VhdrMaxSectors, &Dev->MaxSectors);
+ Status = VIRTIO_CFG_READ (Dev, MaxSectors, &Dev->MaxSectors);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -797,12 +803,11 @@ VirtioScsiInit (
//
// step 4b -- allocate request virtqueue
//
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect,
- VIRTIO_SCSI_REQUEST_QUEUE);
+ Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE);
if (EFI_ERROR (Status)) {
goto Failed;
}
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize);
+ Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -823,8 +828,8 @@ VirtioScsiInit (
// step 4c -- Report GPFN (guest-physical frame number) of queue. If anything
// fails from here on, we must release the ring resources.
//
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueAddress,
- (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);
+ Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,
+ (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
@@ -834,8 +839,8 @@ VirtioScsiInit (
// the known (or unknown) VIRTIO_SCSI_F_* or VIRTIO_F_* capabilities (see
// virtio-0.9.5, Appendices B and I), except bidirectional transfers.
//
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits,
- Features & VIRTIO_SCSI_F_INOUT);
+ Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo,
+ Features & VIRTIO_SCSI_F_INOUT);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
@@ -844,11 +849,11 @@ VirtioScsiInit (
// We expect these maximum sizes from the host. Since they are
// guest-negotiable, ask for them rather than just checking them.
//
- Status = VIRTIO_CFG_WRITE (Dev, VhdrCdbSize, VIRTIO_SCSI_CDB_SIZE);
+ Status = VIRTIO_CFG_WRITE (Dev, CdbSize, VIRTIO_SCSI_CDB_SIZE);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
- Status = VIRTIO_CFG_WRITE (Dev, VhdrSenseSize, VIRTIO_SCSI_SENSE_SIZE);
+ Status = VIRTIO_CFG_WRITE (Dev, SenseSize, VIRTIO_SCSI_SENSE_SIZE);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
@@ -857,7 +862,7 @@ VirtioScsiInit (
// step 6 -- initialization complete
//
NextDevStat |= VSTAT_DRIVER_OK;
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
@@ -901,10 +906,10 @@ ReleaseQueue:
Failed:
//
// Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
- // Status. PCI IO access failure here should not mask the original error.
+ // Status. VirtIo access failure here should not mask the original error.
//
NextDevStat |= VSTAT_FAILED;
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
Dev->InOutSupported = FALSE;
Dev->MaxTarget = 0;
@@ -928,7 +933,7 @@ VirtioScsiUninit (
// VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
// the old comms area.
//
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
Dev->InOutSupported = FALSE;
Dev->MaxTarget = 0;
@@ -953,11 +958,8 @@ VirtioScsiUninit (
// The implementation follows:
// - Driver Writer's Guide for UEFI 2.3.1 v1.01
// - 5.1.3.4 OpenProtocol() and CloseProtocol()
-// - 18 PCI Driver Design Guidelines
-// - 18.3 PCI drivers
// - UEFI Spec 2.3.1 + Errata C
// - 6.3 Protocol Handler Services
-// - 13.4 EFI PCI I/O Protocol
//
EFI_STATUS
@@ -968,57 +970,37 @@ VirtioScsiDriverBindingSupported (
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
- EFI_STATUS Status;
- EFI_PCI_IO_PROTOCOL *PciIo;
- PCI_TYPE00 Pci;
+ EFI_STATUS Status;
+ VIRTIO_DEVICE_PROTOCOL *VirtIo;
//
- // Attempt to open the device with the PciIo set of interfaces. On success,
- // the protocol is "instantiated" for the PCI device. Covers duplicate open
+ // Attempt to open the device with the VirtIo set of interfaces. On success,
+ // the protocol is "instantiated" for the VirtIo device. Covers duplicate open
// attempts (EFI_ALREADY_STARTED).
//
Status = gBS->OpenProtocol (
DeviceHandle, // candidate device
- &gEfiPciIoProtocolGuid, // for generic PCI access
- (VOID **)&PciIo, // handle to instantiate
+ &gVirtioDeviceProtocolGuid, // for generic VirtIo access
+ (VOID **)&VirtIo, // handle to instantiate
This->DriverBindingHandle, // requestor driver identity
DeviceHandle, // ControllerHandle, according to
// the UEFI Driver Model
- EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to
+ EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to
// the device; to be released
);
if (EFI_ERROR (Status)) {
return Status;
}
- //
- // Read entire PCI configuration header for more extensive check ahead.
- //
- Status = PciIo->Pci.Read (
- PciIo, // (protocol, device)
- // handle
- EfiPciIoWidthUint32, // access width & copy
- // mode
- 0, // Offset
- sizeof Pci / sizeof (UINT32), // Count
- &Pci // target buffer
- );
-
- if (Status == EFI_SUCCESS) {
- //
- // virtio-0.9.5, 2.1 PCI Discovery
- //
- Status = (Pci.Hdr.VendorId == 0x1AF4 &&
- Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F &&
- Pci.Hdr.RevisionID == 0x00 &&
- Pci.Device.SubsystemID == VIRTIO_SUBSYSTEM_SCSI_HOST) ? EFI_SUCCESS : EFI_UNSUPPORTED;
+ if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_SCSI_HOST) {
+ Status = EFI_UNSUPPORTED;
}
//
- // We needed PCI IO access only transitorily, to see whether we support the
+ // We needed VirtIo access only transitorily, to see whether we support the
// device or not.
//
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
return Status;
}
@@ -1040,43 +1022,19 @@ VirtioScsiDriverBindingStart (
return EFI_OUT_OF_RESOURCES;
}
- Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
- (VOID **)&Dev->PciIo, This->DriverBindingHandle,
+ Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
+ (VOID **)&Dev->VirtIo, This->DriverBindingHandle,
DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
if (EFI_ERROR (Status)) {
goto FreeVirtioScsi;
}
//
- // We must retain and ultimately restore the original PCI attributes of the
- // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /
- // 18.3.2 Start() and Stop().
- //
- // The third parameter ("Attributes", input) is ignored by the Get operation.
- // The fourth parameter ("Result", output) is ignored by the Enable and Set
- // operations.
- //
- // For virtio-scsi we only need IO space access.
- //
- Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet,
- 0, &Dev->OriginalPciAttributes);
- if (EFI_ERROR (Status)) {
- goto ClosePciIo;
- }
-
- Status = Dev->PciIo->Attributes (Dev->PciIo,
- EfiPciIoAttributeOperationEnable,
- EFI_PCI_IO_ATTRIBUTE_IO, NULL);
- if (EFI_ERROR (Status)) {
- goto ClosePciIo;
- }
-
- //
- // PCI IO access granted, configure virtio-scsi device.
+ // VirtIo access granted, configure virtio-scsi device.
//
Status = VirtioScsiInit (Dev);
if (EFI_ERROR (Status)) {
- goto RestorePciAttributes;
+ goto CloseVirtIo;
}
//
@@ -1096,12 +1054,8 @@ VirtioScsiDriverBindingStart (
UninitDev:
VirtioScsiUninit (Dev);
-RestorePciAttributes:
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,
- Dev->OriginalPciAttributes, NULL);
-
-ClosePciIo:
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+CloseVirtIo:
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
FreeVirtioScsi:
@@ -1149,10 +1103,7 @@ VirtioScsiDriverBindingStop (
VirtioScsiUninit (Dev);
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,
- Dev->OriginalPciAttributes, NULL);
-
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
FreePool (Dev);
diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.h b/OvmfPkg/VirtioScsiDxe/VirtioScsi.h
index f5220b2215..42d8ed765f 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.h
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.h
@@ -20,7 +20,6 @@
#include <Protocol/ComponentName.h>
#include <Protocol/DriverBinding.h>
-#include <Protocol/PciIo.h>
#include <Protocol/ScsiPassThruExt.h>
#include <IndustryStandard/Virtio.h>
@@ -49,18 +48,17 @@ typedef struct {
// at various call depths. The table to the right should make it easier to
// track them.
//
- // field init function init depth
- // ---------------------- ------------------ ----------
- UINT32 Signature; // DriverBindingStart 0
- EFI_PCI_IO_PROTOCOL *PciIo; // DriverBindingStart 0
- UINT64 OriginalPciAttributes; // DriverBindingStart 0
- BOOLEAN InOutSupported; // VirtioScsiInit 1
- UINT16 MaxTarget; // VirtioScsiInit 1
- UINT32 MaxLun; // VirtioScsiInit 1
- UINT32 MaxSectors; // VirtioScsiInit 1
- VRING Ring; // VirtioRingInit 2
- EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru; // VirtioScsiInit 1
- EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode; // VirtioScsiInit 1
+ // field init function init depth
+ // ---------------- ------------------ ----------
+ UINT32 Signature; // DriverBindingStart 0
+ VIRTIO_DEVICE_PROTOCOL *VirtIo; // DriverBindingStart 0
+ BOOLEAN InOutSupported; // VirtioScsiInit 1
+ UINT16 MaxTarget; // VirtioScsiInit 1
+ UINT32 MaxLun; // VirtioScsiInit 1
+ UINT32 MaxSectors; // VirtioScsiInit 1
+ VRING Ring; // VirtioRingInit 2
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru; // VirtioScsiInit 1
+ EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode; // VirtioScsiInit 1
} VSCSI_DEV;
#define VIRTIO_SCSI_FROM_PASS_THRU(PassThruPointer) \
diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.inf b/OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
index 8209c50275..e98780db8a 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
@@ -40,7 +40,7 @@
[Protocols]
gEfiExtScsiPassThruProtocolGuid ## BY_START
- gEfiPciIoProtocolGuid ## TO_START
+ gVirtioDeviceProtocolGuid ## TO_START
[Pcd]
gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxTargetLimit ## CONSUMES