summaryrefslogtreecommitdiff
path: root/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
diff options
context:
space:
mode:
Diffstat (limited to 'OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c')
-rw-r--r--OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
new file mode 100644
index 000000000..f763db5fb
--- /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;
+}