From: Olivier Martin Date: Wed, 11 Dec 2013 16:57:59 +0000 (+0000) Subject: OvmfPkg/VirtioMmioDeviceLib: Implement VIRTIO_DEVICE_PROTOCOL for VirtIo Devices... X-Git-Tag: edk2-stable201903~11992 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=6fb4e772a0ad14399532201d1b9ecb811c9c7262 OvmfPkg/VirtioMmioDeviceLib: Implement VIRTIO_DEVICE_PROTOCOL for VirtIo Devices over MMIO 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 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 Reviewed-by: Jordan Justen git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14965 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/OvmfPkg/Include/Library/VirtioMmioDeviceLib.h b/OvmfPkg/Include/Library/VirtioMmioDeviceLib.h new file mode 100644 index 0000000000..3f63a650be --- /dev/null +++ b/OvmfPkg/Include/Library/VirtioMmioDeviceLib.h @@ -0,0 +1,66 @@ +/** @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 to allocate memory required + 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/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c new file mode 100644 index 0000000000..4af9dd0ac2 --- /dev/null +++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c @@ -0,0 +1,224 @@ +/** @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 +#include +#include + +#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_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/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h new file mode 100644 index 0000000000..3e4e5606cc --- /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 + +#include + +#include +#include +#include +#include + +#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..3950c07f7f --- /dev/null +++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c @@ -0,0 +1,310 @@ +/** @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.
+ 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) { + return EFI_INVALID_PARAMETER; + } + + 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); + + VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM, QueueSize); + + return EFI_SUCCESS; +} + +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; + + 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 ( + 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 != 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; +} diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf new file mode 100644 index 0000000000..2e266a9d45 --- /dev/null +++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf @@ -0,0 +1,42 @@ +## @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 + UefiLib + +[Protocols] + gVirtioDeviceProtocolGuid ## PRODUCES