aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib
diff options
context:
space:
mode:
Diffstat (limited to 'roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib')
-rw-r--r--roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c221
-rw-r--r--roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h171
-rw-r--r--roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c349
-rw-r--r--roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf37
4 files changed, 778 insertions, 0 deletions
diff --git a/roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c b/roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
new file mode 100644
index 000000000..2f20272c1
--- /dev/null
+++ b/roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
@@ -0,0 +1,221 @@
+/** @file
+
+ This driver produces Virtio Device Protocol instances for Virtio Mmio devices.
+
+ Copyright (C) 2013, ARM Ltd.
+ Copyright (C) 2017, AMD Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include "VirtioMmioDevice.h"
+
+STATIC CONST VIRTIO_DEVICE_PROTOCOL mMmioDeviceProtocolTemplate = {
+ 0, // Revision
+ 0, // SubSystemDeviceId
+ VirtioMmioGetDeviceFeatures, // GetDeviceFeatures
+ VirtioMmioSetGuestFeatures, // SetGuestFeatures
+ VirtioMmioSetQueueAddress, // SetQueueAddress
+ VirtioMmioSetQueueSel, // SetQueueSel
+ VirtioMmioSetQueueNotify, // SetQueueNotify
+ VirtioMmioSetQueueAlignment, // SetQueueAlign
+ VirtioMmioSetPageSize, // SetPageSize
+ VirtioMmioGetQueueSize, // GetQueueNumMax
+ VirtioMmioSetQueueSize, // SetQueueNum
+ VirtioMmioGetDeviceStatus, // GetDeviceStatus
+ VirtioMmioSetDeviceStatus, // SetDeviceStatus
+ VirtioMmioDeviceWrite, // WriteDevice
+ VirtioMmioDeviceRead, // ReadDevice
+ VirtioMmioAllocateSharedPages, // AllocateSharedPages
+ VirtioMmioFreeSharedPages, // FreeSharedPages
+ VirtioMmioMapSharedBuffer, // MapSharedBuffer
+ VirtioMmioUnmapSharedBuffer // UnmapSharedBuffer
+};
+
+/**
+
+ 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((DEBUG_WARN, "VirtioMmioInit: Warning: The VendorId (0x%X) does not "
+ "match the VirtIo VendorId (0x%X).\n",
+ VendorId, VIRTIO_VENDOR_ID));
+ }
+
+ 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);
+ FreePool (MmioDevice);
+
+ return EFI_SUCCESS;
+}
diff --git a/roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h b/roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
new file mode 100644
index 000000000..785876c75
--- /dev/null
+++ b/roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
@@ -0,0 +1,171 @@
+/** @file
+
+ Internal definitions for the VirtIo MMIO Device driver
+
+ Copyright (C) 2013, ARM Ltd
+ Copyright (C) 2017, AMD Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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>
+#include <Library/MemoryAllocationLib.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 UINT64 *DeviceFeatures
+ );
+
+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 (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT16 QueueSize
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetDeviceStatus (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT8 DeviceStatus
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetQueueNotify (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT16 QueueNotify
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetQueueSel (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT16 Sel
+ );
+
+EFI_STATUS
+VirtioMmioSetQueueAddress (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN VRING *Ring,
+ IN UINT64 RingBaseShift
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetQueueAlignment (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT32 Alignment
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetPageSize (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT32 PageSize
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetGuestFeatures (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT64 Features
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioAllocateSharedPages (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINTN NumPages,
+ OUT VOID **HostAddress
+ );
+
+VOID
+EFIAPI
+VirtioMmioFreeSharedPages (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINTN NumPages,
+ IN VOID *HostAddress
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioMapSharedBuffer (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN VIRTIO_MAP_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioUnmapSharedBuffer (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+#endif // _VIRTIO_MMIO_DEVICE_INTERNAL_H_
diff --git a/roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c b/roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
new file mode 100644
index 000000000..454f00882
--- /dev/null
+++ b/roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
@@ -0,0 +1,349 @@
+/** @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.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "VirtioMmioDevice.h"
+
+EFI_STATUS
+EFIAPI
+VirtioMmioGetDeviceFeatures (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ OUT UINT64 *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
+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 (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT16 QueueSize
+ )
+{
+ VIRTIO_MMIO_DEVICE *Device;
+
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM, QueueSize);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetDeviceStatus (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN 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 (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN 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 (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN 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 (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT32 PageSize
+ )
+{
+ VIRTIO_MMIO_DEVICE *Device;
+
+ if (PageSize != EFI_PAGE_SIZE) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE, PageSize);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetQueueSel (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN 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 (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN VRING *Ring,
+ IN UINT64 RingBaseShift
+ )
+{
+ VIRTIO_MMIO_DEVICE *Device;
+
+ ASSERT (RingBaseShift == 0);
+
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN,
+ (UINT32)((UINTN)Ring->Base >> EFI_PAGE_SHIFT));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioMmioSetGuestFeatures (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINT64 Features
+ )
+{
+ VIRTIO_MMIO_DEVICE *Device;
+
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ if (Features > MAX_UINT32) {
+ return EFI_UNSUPPORTED;
+ }
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES,
+ (UINT32)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 != 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 != 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;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioMmioAllocateSharedPages (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINTN NumPages,
+ OUT VOID **HostAddress
+ )
+{
+ VOID *Buffer;
+
+ Buffer = AllocatePages (NumPages);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *HostAddress = Buffer;
+ return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+VirtioMmioFreeSharedPages (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN UINTN NumPages,
+ IN VOID *HostAddress
+ )
+{
+ FreePages (HostAddress, NumPages);
+}
+
+EFI_STATUS
+EFIAPI
+VirtioMmioMapSharedBuffer (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN VIRTIO_MAP_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ *DeviceAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
+ *Mapping = NULL;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioMmioUnmapSharedBuffer (
+ IN VIRTIO_DEVICE_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf b/roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
new file mode 100644
index 000000000..0736f89d6
--- /dev/null
+++ b/roms/edk2/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
@@ -0,0 +1,37 @@
+## @file
+# This driver produces the VirtIo Device Protocol instances for VirtIo Mmio
+# Device
+#
+# Copyright (C) 2013, ARM Ltd
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[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
+ VirtioMmioDevice.h
+ VirtioMmioDeviceFunctions.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ IoLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiLib
+
+[Protocols]
+ gVirtioDeviceProtocolGuid ## PRODUCES