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