Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <olivier.mar...@arm.com>
---
 OvmfPkg/Include/Library/VirtioMmioDeviceLib.h      |   48 ++++
 .../Library/VirtioMmioDeviceLib/VirtioMmioDevice.c |  201 +++++++++++++
 .../Library/VirtioMmioDeviceLib/VirtioMmioDevice.h |  160 +++++++++++
 .../VirtioMmioDeviceFunctions.c                    |  297 ++++++++++++++++++++
 .../VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf    |   43 +++
 5 files changed, 749 insertions(+), 0 deletions(-)
 create mode 100644 OvmfPkg/Include/Library/VirtioMmioDeviceLib.h
 create mode 100644 OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
 create mode 100644 OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
 create mode 100644 
OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
 create mode 100644 OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf

diff --git a/OvmfPkg/Include/Library/VirtioMmioDeviceLib.h 
b/OvmfPkg/Include/Library/VirtioMmioDeviceLib.h
new file mode 100644
index 0000000..2168ed7
--- /dev/null
+++ b/OvmfPkg/Include/Library/VirtioMmioDeviceLib.h
@@ -0,0 +1,48 @@
+/** @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_
+
+#include <Protocol/VirtioDevice.h>
+
+#define VIRTIO_MMIO_DEVICE_SIGNATURE SIGNATURE_32 ('V', 'M', 'I', 'O')
+
+typedef struct {
+  UINT32                 Signature;
+  VIRTIO_DEVICE_PROTOCOL VirtioDevice;
+  PHYSICAL_ADDRESS       BaseAddress;
+  EFI_HANDLE             Handle;
+} VIRTIO_MMIO_DEVICE;
+
+#define VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE(Device) \
+        CR (Device, VIRTIO_MMIO_DEVICE, VirtioDevice, 
VIRTIO_MMIO_DEVICE_SIGNATURE)
+#define VIRTIO_MMIO_DEVICE_FROM_HANDLE(Device) \
+        CR (Device, VIRTIO_MMIO_DEVICE, Handle, VIRTIO_MMIO_DEVICE_SIGNATURE)
+
+//  Initialize VirtIo Device and Install VIRTIO_DEVICE_PROTOCOL protocol
+EFI_STATUS
+VirtioMmioInstallDevice (
+  IN PHYSICAL_ADDRESS       BaseAddress,
+  IN EFI_HANDLE             Handle
+  );
+
+EFI_STATUS
+VirtioMmioUninstallDevice (
+  IN EFI_HANDLE             Handle
+  );
+
+#endif // _VIRTIO_MMIO_DEVICE_LIB_H_
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c 
b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
new file mode 100644
index 0000000..945da57
--- /dev/null
+++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
@@ -0,0 +1,201 @@
+/** @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,                                     // SubSystemDeviceId
+    VirtioMmioGetDeviceFeatures,           // GetDeviceFeatures
+    VirtioMmioGetGuestFeatures,            // GetGuestFeatures
+    VirtioMmioSetGuestFeatures,            // SetGuestFeatures
+    VirtioMmioGetQueueAddress,             // GetQueueAddress
+    VirtioMmioSetQueueAddress,             // SetQueueAddress
+    VirtioMmioSetQueueSel,                 // SetQueueSel
+    VirtioMmioSetQueueNotify,              // SetQueueNotify
+    VirtioMmioSetQueueAlignment,           // SetQueueAlign
+    VirtioMmioGetQueueSize,                // GetQueueNumMax
+    VirtioMmioSetQueueSize,                // SetQueueNum
+    VirtioMmioGetDeviceStatus,             // GetDeviceStatus
+    VirtioMmioSetDeviceStatus,             // SetDeviceStatus
+    VirtioMmioDeviceWrite,                 // WriteDevice
+    VirtioMmioDeviceRead                   // ReadDevice
+};
+
+/**
+
+  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-blk PCI device).
+
+  @retval EFI_SUCCESS      Setup complete.
+
+  @retval EFI_UNSUPPORTED  The driver is unable to work with the virtio ring or
+                           virtio-blk attributes the host provides.
+
+  @return                  Error codes from VirtioRingInit() or
+                           VIRTIO_CFG_READ() / VIRTIO_CFG_WRITE().
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+VirtioMmioInit (
+  IN OUT VIRTIO_MMIO_DEVICE *Device
+  )
+{
+  // Set Mmio Page Size
+
+  UINT8      NextDevStat;
+  UINT32     MagicValue;
+  UINT32     Version;
+
+  //
+  // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
+  //
+  NextDevStat = 0;             // step 1 -- reset device
+  VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_STATUS, NextDevStat);
+
+  NextDevStat |= VSTAT_ACK;    // step 2 -- acknowledge device presence
+  VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_STATUS, NextDevStat);
+
+  NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
+  VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_STATUS, NextDevStat);
+
+  // 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;
+  }
+
+  // Set page size (for later queue allocations)
+  VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE, EFI_PAGE_SIZE);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+
+  Uninitialize the internals of a virtio-blk device that has been successfully
+  set up with VirtioMmioInit().
+
+  @param[in out]  Dev  The device to clean up.
+
+**/
+
+STATIC
+VOID
+EFIAPI
+VirtioMmioUninit (
+  IN VIRTIO_MMIO_DEVICE *Device
+  )
+{
+  //
+  // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
+  // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
+  // the old comms area.
+  //
+  VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_STATUS, 0);
+}
+
+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->BaseAddress = BaseAddress;
+  VirtIo->Signature = VIRTIO_MMIO_DEVICE_SIGNATURE;
+  VirtIo->Handle = Handle;
+
+  // Initialize VirtIo Mmio Device
+  CopyMem (&VirtIo->VirtioDevice, &mMmioDeviceProtocolTemplate,
+      sizeof (VIRTIO_DEVICE_PROTOCOL));
+  VirtIo->VirtioDevice.SubSystemDeviceId =
+      MmioRead32 (BaseAddress + VIRTIO_MMIO_OFFSET_DEVICE_ID);
+  Status = VirtioMmioInit (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 UninstallVirtio;
+  }
+
+  return EFI_SUCCESS;
+
+UninstallVirtio:
+  VirtioMmioUninit (VirtIo);
+
+FreeVirtioMem:
+  FreePool (VirtIo);
+  return Status;
+}
+
+EFI_STATUS
+VirtioMmioUninstallDevice (
+  IN EFI_HANDLE             Handle
+  )
+{
+  VIRTIO_MMIO_DEVICE    *Device;
+  EFI_STATUS            Status;
+
+  // Get the device from handle
+  Device = VIRTIO_MMIO_DEVICE_FROM_HANDLE (Handle);
+
+  // Uninstall the protocol interface
+  Status = gBS->UninstallProtocolInterface (Handle,
+      &gVirtioDeviceProtocolGuid, &Device->VirtioDevice
+      );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Uninitialize the VirtIo Device
+  VirtioMmioUninit (Device);
+
+  return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h 
b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
new file mode 100644
index 0000000..66b3f76
--- /dev/null
+++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
@@ -0,0 +1,160 @@
+/** @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_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_PAGE_OFF          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
+#define VIRTIO_MMIO_OFFSET_DEVICE_SPECIFIC_CONFIG  0x100
+
+#define VIRTIO_MMIO_MAGIC                          0x74726976 // "virt"
+#define VIRTIO_MMIO_VENDOR_ID                      0x1AF4
+
+#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
+  );
+
+UINT32
+EFIAPI
+VirtioMmioGetDeviceFeatures (
+  VIRTIO_DEVICE_PROTOCOL *This
+  );
+
+UINT32
+EFIAPI
+VirtioMmioGetGuestFeatures (
+  VIRTIO_DEVICE_PROTOCOL *This
+  );
+
+UINT32
+EFIAPI
+VirtioMmioGetQueueAddress (
+  VIRTIO_DEVICE_PROTOCOL *This
+  );
+
+UINT32
+EFIAPI
+VirtioMmioGetQueueSel (
+  VIRTIO_DEVICE_PROTOCOL *This
+  );
+
+UINT16
+EFIAPI
+VirtioMmioGetQueueSize (
+  VIRTIO_DEVICE_PROTOCOL *This
+  );
+
+UINT8
+EFIAPI
+VirtioMmioGetDeviceStatus (
+  VIRTIO_DEVICE_PROTOCOL *This
+  );
+
+VOID
+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
+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 0000000..284c25a
--- /dev/null
+++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
@@ -0,0 +1,297 @@
+/** @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"
+
+UINT32
+EFIAPI
+VirtioMmioGetDeviceFeatures (
+  VIRTIO_DEVICE_PROTOCOL *This
+  )
+{
+  VIRTIO_MMIO_DEVICE *Device;
+
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+  return VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_HOST_FEATURES);
+}
+
+UINT32
+EFIAPI
+VirtioMmioGetGuestFeatures (
+  VIRTIO_DEVICE_PROTOCOL *This
+  )
+{
+  VIRTIO_MMIO_DEVICE *Device;
+
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+  return VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES);
+}
+
+UINT32
+EFIAPI
+VirtioMmioGetQueueAddress (
+  VIRTIO_DEVICE_PROTOCOL *This
+  )
+{
+  VIRTIO_MMIO_DEVICE *Device;
+
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+  return VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_PAGE_OFF);
+}
+
+UINT32
+EFIAPI
+VirtioMmioGetQueueSel (
+  VIRTIO_DEVICE_PROTOCOL *This
+  )
+{
+  VIRTIO_MMIO_DEVICE *Device;
+
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+  return VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_SEL);
+}
+
+UINT16
+EFIAPI
+VirtioMmioGetQueueSize (
+  VIRTIO_DEVICE_PROTOCOL *This
+  )
+{
+  VIRTIO_MMIO_DEVICE *Device;
+
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+  return VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX) & 0xFFFF;
+}
+
+UINT8
+EFIAPI
+VirtioMmioGetDeviceStatus (
+  VIRTIO_DEVICE_PROTOCOL *This
+  )
+{
+  VIRTIO_MMIO_DEVICE *Device;
+
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+  return VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_STATUS) & 0xFF;
+}
+
+
+VOID
+EFIAPI
+VirtioMmioSetQueueSize (
+  VIRTIO_DEVICE_PROTOCOL *This,
+  UINT16                  QueueSize
+  )
+{
+  VIRTIO_MMIO_DEVICE *Device;
+
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+  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
+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_PAGE_OFF, 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;
+  UINT8                    *DstByteAddress;
+  UINT8                     SrcByte;
+  UINTN                     Index;
+  VIRTIO_MMIO_DEVICE       *Device;
+
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+  // Double-check fieldsize
+  if (FieldSize > 8) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((FieldSize % 2) && FieldSize != 1) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Compute base address
+  DstBaseAddress = Device->BaseAddress +
+      VIRTIO_MMIO_OFFSET_DEVICE_SPECIFIC_CONFIG + FieldOffset;
+
+  //
+  // The device-specific memory area of Virtio-MMIO can only be written in
+  // byte accesses. This is not currently in the Virtio spec.
+  //
+  for (Index = 0; Index < FieldSize; Index++) {
+    DstByteAddress = ((UINT8 *)DstBaseAddress) + Index;
+    SrcByte = *(((UINT8 *)&Value) + Index);
+    MmioWrite8 ((UINTN) DstByteAddress, SrcByte);
+  }
+
+  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;
+  UINT8                    *SrcByteAddress;
+  UINTN                     Index;
+  VIRTIO_MMIO_DEVICE       *Device;
+
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+  // Parameter validation
+  if (FieldSize != BufferSize) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Double-check fieldsize
+  if (FieldSize > 8) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((FieldSize % 2) && FieldSize != 1) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Compute base address
+  SrcBaseAddress = Device->BaseAddress +
+      VIRTIO_MMIO_OFFSET_DEVICE_SPECIFIC_CONFIG + FieldOffset;
+
+  //
+  // The device-specific memory area of Virtio-MMIO can only be read in
+  // byte reads. This is not currently in the Virtio spec.
+  //
+  for (Index = 0; Index < FieldSize; Index++) {
+    SrcByteAddress = ((UINT8 *)SrcBaseAddress) + Index;
+    *(UINT8 *)(Buffer + Index) = MmioRead8 ((UINTN) SrcByteAddress);
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf 
b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
new file mode 100644
index 0000000..e6deccb
--- /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                    = 0x00010005
+  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
-- 
1.7.0.4


------------------------------------------------------------------------------
LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99!
1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint
2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes
Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. 
http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to