OvmfPkg/VirtioMmioDeviceLib: Implement VIRTIO_DEVICE_PROTOCOL for VirtIo Devices...
authorOlivier Martin <olivier.martin@arm.com>
Wed, 11 Dec 2013 16:57:59 +0000 (16:57 +0000)
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 11 Dec 2013 16:57:59 +0000 (16:57 +0000)
Why is the virtio-mmio implementation of the protocol a library,
instead of a driver binary?
The UEFI driver model would encourage to create a virtio-mmio driver
instead of a library. But the reasons why I created a library are:

- A virtio-mmio driver would imply an additional protocol that would
probably have a single attribute field:

typedef struct {
  PHYSICAL_ADDRESS       BaseAddress;
} VIRTIO_MMIO_DEVICE_PROTOCOL;

- There is no (easy) way to scan the available VirtIo devices on a
platform. So, the UEFI firmware for this platform would need a driver
to produce instances for every virtio devices it wants to expose in
UEFI. A single call to a helper library (ie: VirtioMmioDeviceLib)
make the porting easier.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <olivier.martin@arm.com>
v5:
- typo fix in VirtioMmioInstallDevice() comment block
- plug MmioDevice leak in VirtioMmioUninstallDevice()
- return EFI_INVALID_PARAMETER in VirtioMmioGetQueueAddress() if
  QueueAddress is NULL
- VirtioMmioSetQueueSize(): fix return value (it's a status code)
- VirtioMmioSetPageSize(): check against EFI_PAGE_SIZE with "if" plus
  EFI_UNSUPPORTED, rather than ASSERT()
- VirtioMmioDeviceWrite(), VirtioMmioDeviceRead(): remove redundant
  (FieldSize > 8) checks
- VirtioMmioDeviceLib.inf: drop UefiDriverEntryPoint library dependency

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14965 6f19259b-4bc3-4df7-8a09-765794883524

OvmfPkg/Include/Library/VirtioMmioDeviceLib.h [new file with mode: 0644]
OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c [new file with mode: 0644]
OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h [new file with mode: 0644]
OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c [new file with mode: 0644]
OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf [new file with mode: 0644]

diff --git a/OvmfPkg/Include/Library/VirtioMmioDeviceLib.h b/OvmfPkg/Include/Library/VirtioMmioDeviceLib.h
new file mode 100644 (file)
index 0000000..3f63a65
--- /dev/null
@@ -0,0 +1,66 @@
+/** @file\r
+\r
+  Definitions for the VirtIo MMIO Device Library\r
+\r
+  Copyright (C) 2013, ARM Ltd\r
+\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution. The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _VIRTIO_MMIO_DEVICE_LIB_H_\r
+#define _VIRTIO_MMIO_DEVICE_LIB_H_\r
+\r
+/**\r
+\r
+  Initialize VirtIo Device and Install VIRTIO_DEVICE_PROTOCOL protocol\r
+\r
+  @param[in] BaseAddress  Base Address of the VirtIo MMIO Device\r
+\r
+  @param[in] Handle       Handle of the device the driver should be attached\r
+                          to.\r
+\r
+  @retval EFI_SUCCESS           The VirtIo Device has been installed\r
+                                successfully.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES  The function failed to allocate memory required\r
+                                by the Virtio MMIO device initialization.\r
+\r
+  @retval EFI_UNSUPPORTED       BaseAddress does not point to a VirtIo MMIO\r
+                                device.\r
+\r
+  @return                       Status code returned by InstallProtocolInterface\r
+                                Boot Service function.\r
+\r
+**/\r
+EFI_STATUS\r
+VirtioMmioInstallDevice (\r
+  IN PHYSICAL_ADDRESS       BaseAddress,\r
+  IN EFI_HANDLE             Handle\r
+  );\r
+\r
+/**\r
+\r
+  Uninstall the VirtIo Device\r
+\r
+  @param[in] Handle       Handle of the device where the VirtIo Device protocol\r
+                          should have been installed.\r
+\r
+  @retval EFI_SUCCESS     The device has been un-initialized successfully.\r
+\r
+  @return                 Status code returned by UninstallProtocolInterface\r
+                          Boot Service function.\r
+\r
+**/\r
+EFI_STATUS\r
+VirtioMmioUninstallDevice (\r
+  IN EFI_HANDLE             Handle\r
+  );\r
+\r
+#endif // _VIRTIO_MMIO_DEVICE_LIB_H_\r
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
new file mode 100644 (file)
index 0000000..4af9dd0
--- /dev/null
@@ -0,0 +1,224 @@
+/** @file\r
+\r
+  This driver produces Virtio Device Protocol instances for Virtio Mmio devices.\r
+\r
+  Copyright (C) 2013, ARM Ltd.\r
+\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution. The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#include "VirtioMmioDevice.h"\r
+\r
+static VIRTIO_DEVICE_PROTOCOL mMmioDeviceProtocolTemplate = {\r
+    0,                                     // Revision\r
+    0,                                     // SubSystemDeviceId\r
+    VirtioMmioGetDeviceFeatures,           // GetDeviceFeatures\r
+    VirtioMmioSetGuestFeatures,            // SetGuestFeatures\r
+    VirtioMmioGetQueueAddress,             // GetQueueAddress\r
+    VirtioMmioSetQueueAddress,             // SetQueueAddress\r
+    VirtioMmioSetQueueSel,                 // SetQueueSel\r
+    VirtioMmioSetQueueNotify,              // SetQueueNotify\r
+    VirtioMmioSetQueueAlignment,           // SetQueueAlign\r
+    VirtioMmioSetPageSize,                 // SetPageSize\r
+    VirtioMmioGetQueueSize,                // GetQueueNumMax\r
+    VirtioMmioSetQueueSize,                // SetQueueNum\r
+    VirtioMmioGetDeviceStatus,             // GetDeviceStatus\r
+    VirtioMmioSetDeviceStatus,             // SetDeviceStatus\r
+    VirtioMmioDeviceWrite,                 // WriteDevice\r
+    VirtioMmioDeviceRead                   // ReadDevice\r
+};\r
+\r
+/**\r
+\r
+  Initialize the VirtIo MMIO Device\r
+\r
+  @param[in] BaseAddress   Base Address of the VirtIo MMIO Device\r
+\r
+  @param[in, out] Device   The driver instance to configure.\r
+\r
+  @retval EFI_SUCCESS      Setup complete.\r
+\r
+  @retval EFI_UNSUPPORTED  The driver is not a VirtIo MMIO device.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioInit (\r
+  IN PHYSICAL_ADDRESS        BaseAddress,\r
+  IN OUT VIRTIO_MMIO_DEVICE *Device\r
+  )\r
+{\r
+  UINT32     MagicValue;\r
+  UINT32     VendorId;\r
+  UINT32     Version;\r
+\r
+  //\r
+  // Initialize VirtIo Mmio Device\r
+  //\r
+  CopyMem (&Device->VirtioDevice, &mMmioDeviceProtocolTemplate,\r
+        sizeof (VIRTIO_DEVICE_PROTOCOL));\r
+  Device->BaseAddress = BaseAddress;\r
+  Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5);\r
+  Device->VirtioDevice.SubSystemDeviceId =\r
+          MmioRead32 (BaseAddress + VIRTIO_MMIO_OFFSET_DEVICE_ID);\r
+\r
+  //\r
+  // Double-check MMIO-specific values\r
+  //\r
+  MagicValue = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_MAGIC);\r
+  if (MagicValue != VIRTIO_MMIO_MAGIC) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Version = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VERSION);\r
+  if (Version != 1) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Double-check MMIO-specific values\r
+  //\r
+  VendorId = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VENDOR_ID);\r
+  if (VendorId != VIRTIO_VENDOR_ID) {\r
+    //\r
+    // The ARM Base and Foundation Models do not report a valid VirtIo VendorId.\r
+    // They return a value of 0x0 for the VendorId.\r
+    //\r
+    DEBUG((EFI_D_WARN, "VirtioMmioInit: Warning: The VendorId (0x%X) does not "\r
+                       "match the VirtIo VendorId (0x%X).\n",\r
+                       VendorId, VIRTIO_VENDOR_ID));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Uninitialize the internals of a virtio-mmio device that has been successfully\r
+  set up with VirtioMmioInit().\r
+\r
+  @param[in, out]  Device  The device to clean up.\r
+\r
+**/\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+VirtioMmioUninit (\r
+  IN VIRTIO_MMIO_DEVICE *Device\r
+  )\r
+{\r
+  //\r
+  // Note: This function mirrors VirtioMmioInit() that does not allocate any\r
+  //       resources - there's nothing to free here.\r
+  //\r
+}\r
+\r
+EFI_STATUS\r
+VirtioMmioInstallDevice (\r
+  IN PHYSICAL_ADDRESS       BaseAddress,\r
+  IN EFI_HANDLE             Handle\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  VIRTIO_MMIO_DEVICE *VirtIo;\r
+\r
+  if (!BaseAddress) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (Handle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Allocate VIRTIO_MMIO_DEVICE\r
+  //\r
+  VirtIo = AllocateZeroPool (sizeof (VIRTIO_MMIO_DEVICE));\r
+  if (VirtIo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  VirtIo->Signature = VIRTIO_MMIO_DEVICE_SIGNATURE;\r
+\r
+  Status = VirtioMmioInit (BaseAddress, VirtIo);\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeVirtioMem;\r
+  }\r
+\r
+  //\r
+  // Install VIRTIO_DEVICE_PROTOCOL to Handle\r
+  //\r
+  Status = gBS->InstallProtocolInterface (&Handle,\r
+                  &gVirtioDeviceProtocolGuid, EFI_NATIVE_INTERFACE,\r
+                  &VirtIo->VirtioDevice);\r
+  if (EFI_ERROR (Status)) {\r
+    goto UninitVirtio;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+UninitVirtio:\r
+  VirtioMmioUninit (VirtIo);\r
+\r
+FreeVirtioMem:\r
+  FreePool (VirtIo);\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+VirtioMmioUninstallDevice (\r
+  IN EFI_HANDLE             DeviceHandle\r
+  )\r
+{\r
+  VIRTIO_DEVICE_PROTOCOL  *VirtioDevice;\r
+  VIRTIO_MMIO_DEVICE      *MmioDevice;\r
+  EFI_STATUS              Status;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  DeviceHandle,                  // candidate device\r
+                  &gVirtioDeviceProtocolGuid,    // retrieve the VirtIo iface\r
+                  (VOID **)&VirtioDevice,        // target pointer\r
+                  DeviceHandle,                  // requestor driver identity\r
+                  DeviceHandle,                  // requesting lookup for dev.\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get the MMIO device from the VirtIo Device instance\r
+  //\r
+  MmioDevice = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice);\r
+\r
+  //\r
+  // Uninstall the protocol interface\r
+  //\r
+  Status = gBS->UninstallProtocolInterface (DeviceHandle,\r
+      &gVirtioDeviceProtocolGuid, &MmioDevice->VirtioDevice\r
+      );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Uninitialize the VirtIo Device\r
+  //\r
+  VirtioMmioUninit (MmioDevice);\r
+  FreePool (MmioDevice);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
new file mode 100644 (file)
index 0000000..3e4e560
--- /dev/null
@@ -0,0 +1,147 @@
+/** @file\r
+\r
+  Internal definitions for the VirtIo MMIO Device driver\r
+\r
+  Copyright (C) 2013, ARM Ltd\r
+\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution. The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _VIRTIO_MMIO_DEVICE_INTERNAL_H_\r
+#define _VIRTIO_MMIO_DEVICE_INTERNAL_H_\r
+\r
+#include <Protocol/VirtioDevice.h>\r
+\r
+#include <IndustryStandard/Virtio.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/VirtioMmioDeviceLib.h>\r
+\r
+#define VIRTIO_MMIO_DEVICE_SIGNATURE  SIGNATURE_32 ('V', 'M', 'I', 'O')\r
+\r
+typedef struct {\r
+  UINT32                 Signature;\r
+  VIRTIO_DEVICE_PROTOCOL VirtioDevice;\r
+  PHYSICAL_ADDRESS       BaseAddress;\r
+} VIRTIO_MMIO_DEVICE;\r
+\r
+#define VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE(Device) \\r
+    CR (Device, VIRTIO_MMIO_DEVICE, VirtioDevice, VIRTIO_MMIO_DEVICE_SIGNATURE)\r
+\r
+#define VIRTIO_CFG_WRITE(Device, Offset, Val) \\r
+    (MmioWrite32 (Device->BaseAddress + (Offset), Val))\r
+#define VIRTIO_CFG_READ(Device, Offset)       \\r
+    (MmioRead32  (Device->BaseAddress + (Offset)))\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioDeviceRead (\r
+  IN  VIRTIO_DEVICE_PROTOCOL    *This,\r
+  IN  UINTN                     FieldOFfset,\r
+  IN  UINTN                     FieldSize,\r
+  IN  UINTN                     BufferSize,\r
+  OUT VOID*                     Buffer\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioDeviceWrite (\r
+  IN  VIRTIO_DEVICE_PROTOCOL    *This,\r
+  IN  UINTN                     FieldOffset,\r
+  IN  UINTN                     FieldSize,\r
+  IN  UINT64                    Value\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioGetDeviceFeatures (\r
+  IN VIRTIO_DEVICE_PROTOCOL *This,\r
+  OUT UINT32                *DeviceFeatures\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioGetQueueAddress (\r
+  IN  VIRTIO_DEVICE_PROTOCOL *This,\r
+  OUT UINT32                 *QueueAddress\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioGetQueueSize (\r
+  IN  VIRTIO_DEVICE_PROTOCOL  *This,\r
+  OUT UINT16                  *QueueNumMax\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioGetDeviceStatus (\r
+  IN  VIRTIO_DEVICE_PROTOCOL  *This,\r
+  OUT UINT8                   *DeviceStatus\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetQueueSize (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT16                  QueueSize\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetDeviceStatus (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT8                   DeviceStatus\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetQueueNotify (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT16                  QueueNotify\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetQueueSel (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT16                  Sel\r
+  );\r
+\r
+EFI_STATUS\r
+VirtioMmioSetQueueAddress (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT32                  Address\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetQueueAlignment (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT32                  Alignment\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetPageSize (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT32                  PageSize\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetGuestFeatures (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT32                  Features\r
+  );\r
+\r
+#endif // _VIRTIO_MMIO_DEVICE_INTERNAL_H_\r
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
new file mode 100644 (file)
index 0000000..3950c07
--- /dev/null
@@ -0,0 +1,310 @@
+/** @file\r
+\r
+  This driver produces Virtio Device Protocol instances for Virtio MMIO devices.\r
+\r
+  Copyright (C) 2012, Red Hat, Inc.\r
+  Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (C) 2013, ARM Ltd.\r
+\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution. The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "VirtioMmioDevice.h"\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioGetDeviceFeatures (\r
+  IN VIRTIO_DEVICE_PROTOCOL *This,\r
+  OUT UINT32                *DeviceFeatures\r
+  )\r
+{\r
+  VIRTIO_MMIO_DEVICE *Device;\r
+\r
+  if (DeviceFeatures == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  *DeviceFeatures = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_HOST_FEATURES);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioGetQueueAddress (\r
+  IN  VIRTIO_DEVICE_PROTOCOL *This,\r
+  OUT UINT32                 *QueueAddress\r
+  )\r
+{\r
+  VIRTIO_MMIO_DEVICE *Device;\r
+\r
+  if (QueueAddress == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  *QueueAddress = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioGetQueueSize (\r
+  IN  VIRTIO_DEVICE_PROTOCOL  *This,\r
+  OUT UINT16                  *QueueNumMax\r
+  )\r
+{\r
+  VIRTIO_MMIO_DEVICE *Device;\r
+\r
+  if (QueueNumMax == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  *QueueNumMax = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX) & 0xFFFF;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioGetDeviceStatus (\r
+  IN  VIRTIO_DEVICE_PROTOCOL  *This,\r
+  OUT UINT8                   *DeviceStatus\r
+  )\r
+{\r
+  VIRTIO_MMIO_DEVICE *Device;\r
+\r
+  if (DeviceStatus == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  *DeviceStatus = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_STATUS) & 0xFF;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetQueueSize (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT16                  QueueSize\r
+  )\r
+{\r
+  VIRTIO_MMIO_DEVICE *Device;\r
+\r
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM, QueueSize);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetDeviceStatus (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT8                   DeviceStatus\r
+  )\r
+{\r
+  VIRTIO_MMIO_DEVICE *Device;\r
+\r
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_STATUS, DeviceStatus);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetQueueNotify (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT16                  QueueNotify\r
+  )\r
+{\r
+  VIRTIO_MMIO_DEVICE *Device;\r
+\r
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY, QueueNotify);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetQueueAlignment (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT32                  Alignment\r
+  )\r
+{\r
+  VIRTIO_MMIO_DEVICE *Device;\r
+\r
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_ALIGN, Alignment);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetPageSize (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT32                  PageSize\r
+  )\r
+{\r
+  VIRTIO_MMIO_DEVICE *Device;\r
+\r
+  if (PageSize != EFI_PAGE_SIZE) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE, PageSize);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetQueueSel (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT16                  Sel\r
+  )\r
+{\r
+  VIRTIO_MMIO_DEVICE *Device;\r
+\r
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_SEL, Sel);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+VirtioMmioSetQueueAddress (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT32                  Address\r
+  )\r
+{\r
+  VIRTIO_MMIO_DEVICE *Device;\r
+\r
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN, Address);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetGuestFeatures (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT32                  Features\r
+  )\r
+{\r
+  VIRTIO_MMIO_DEVICE *Device;\r
+\r
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES, Features);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioDeviceWrite (\r
+  IN VIRTIO_DEVICE_PROTOCOL *This,\r
+  IN UINTN                  FieldOffset,\r
+  IN UINTN                  FieldSize,\r
+  IN UINT64                 Value\r
+  )\r
+{\r
+  UINTN                     DstBaseAddress;\r
+  VIRTIO_MMIO_DEVICE       *Device;\r
+\r
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  //\r
+  // Double-check fieldsize\r
+  //\r
+  if ((FieldSize != 1) && (FieldSize != 2) &&\r
+      (FieldSize != 4) && (FieldSize != 8)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Compute base address\r
+  //\r
+  DstBaseAddress = Device->BaseAddress +\r
+      VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;\r
+\r
+  //\r
+  // The device-specific memory area of Virtio-MMIO can only be written in\r
+  // byte accesses. This is not currently in the Virtio spec.\r
+  //\r
+  MmioWriteBuffer8 (DstBaseAddress, FieldSize, (UINT8*)&Value);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioDeviceRead (\r
+  IN  VIRTIO_DEVICE_PROTOCOL    *This,\r
+  IN  UINTN                     FieldOffset,\r
+  IN  UINTN                     FieldSize,\r
+  IN  UINTN                     BufferSize,\r
+  OUT VOID                      *Buffer\r
+  )\r
+{\r
+  UINTN                     SrcBaseAddress;\r
+  VIRTIO_MMIO_DEVICE       *Device;\r
+\r
+  Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  //\r
+  // Parameter validation\r
+  //\r
+  ASSERT (FieldSize == BufferSize);\r
+\r
+  //\r
+  // Double-check fieldsize\r
+  //\r
+  if ((FieldSize != 1) && (FieldSize != 2) &&\r
+      (FieldSize != 4) && (FieldSize != 8)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Compute base address\r
+  //\r
+  SrcBaseAddress = Device->BaseAddress +\r
+      VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;\r
+\r
+  //\r
+  // The device-specific memory area of Virtio-MMIO can only be read in\r
+  // byte reads. This is not currently in the Virtio spec.\r
+  //\r
+  MmioReadBuffer8 (SrcBaseAddress, BufferSize, Buffer);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
new file mode 100644 (file)
index 0000000..2e266a9
--- /dev/null
@@ -0,0 +1,42 @@
+## @file\r
+# This driver produces the VirtIo Device Protocol instances for VirtIo Mmio\r
+# Device\r
+#\r
+# Copyright (C) 2013, ARM Ltd\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010006\r
+  BASE_NAME                      = VirtioMmioDeviceLib\r
+  FILE_GUID                      = 3b6ed966-b5d1-46a8-965b-867ff22d9c89\r
+  MODULE_TYPE                    = UEFI_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = VirtioMmioDeviceLib\r
+\r
+[Sources]\r
+  VirtioMmioDevice.c\r
+  VirtioMmioDeviceFunctions.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  OvmfPkg/OvmfPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseMemoryLib\r
+  DebugLib\r
+  IoLib\r
+  MemoryAllocationLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\r
+\r
+[Protocols]\r
+  gVirtioDeviceProtocolGuid            ## PRODUCES\r