From: Phil Dennis-Jordan <phil@philjordan.eu>
In addition to the QXL, Cirrus, etc. VGA adapters, Qemu also implements
a basic version of VMWare's SVGA2 display device. Drivers for this device
exist for guest OSes which do not support Qemu's other display adapters,
so supporting it in OVMF is useful in conjunction with those OSes.
This change adds support for the SVGA2 device's framebuffer to
QemuVideoDxe, based on VMWare's documentation. The most basic
initialisation, framebuffer layout query, and mode setting are
implemented.
The device relies on port-based 32-bit I/O, unfortunately on misaligned
addresses. This requires the addition of unaligned I/O helper functions
for various compiler families, and limits the driver's support to the
x86 family of platforms.
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
---
OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf | 6 ++
OvmfPkg/QemuVideoDxe/Qemu.h | 50 +++++++++++
OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h | 51 ++++++++++++
OvmfPkg/QemuVideoDxe/Driver.c | 67 +++++++++++++++
OvmfPkg/QemuVideoDxe/Gop.c | 71 +++++++++++++++-
OvmfPkg/QemuVideoDxe/Initialize.c | 88 ++++++++++++++++++++
OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c | 59 +++++++++++++
OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c | 79 ++++++++++++++++++
OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c | 81 ++++++++++++++++++
OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c | 53 ++++++++++++
10 files changed, 604 insertions(+), 1 deletion(-)
diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
index affb6ffd88e0..346a5aed94fa 100644
--- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
@@ -41,6 +41,12 @@ [Sources.common]
[Sources.Ia32, Sources.X64]
VbeShim.c
+ UnalignedIoGcc.c | GCC
+ UnalignedIoMsc.c | MSFT
+ UnalignedIoIcc.c | INTEL
+
+[Sources.IPF, Sources.EBC, Sources.ARM, Sources.AARCH64]
+ UnalignedIoUnsupported.c
[Packages]
MdePkg/MdePkg.dec
diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
index 2ce37defc5b8..7be2cac63130 100644
--- a/OvmfPkg/QemuVideoDxe/Qemu.h
+++ b/OvmfPkg/QemuVideoDxe/Qemu.h
@@ -56,6 +56,10 @@ typedef struct {
UINT32 HorizontalResolution;
UINT32 VerticalResolution;
UINT32 ColorDepth;
+ //
+ // VMWare specific:
+ //
+ UINT32 PixelsPerLine; // includes any dead space
} QEMU_VIDEO_MODE_DATA;
#define PIXEL_RED_SHIFT 0
@@ -92,6 +96,7 @@ typedef enum {
QEMU_VIDEO_CIRRUS_5446,
QEMU_VIDEO_BOCHS,
QEMU_VIDEO_BOCHS_MMIO,
+ QEMU_VIDEO_VMWARE_SVGA2,
} QEMU_VIDEO_VARIANT;
typedef struct {
@@ -119,6 +124,8 @@ typedef struct {
QEMU_VIDEO_VARIANT Variant;
FRAME_BUFFER_CONFIGURE *FrameBufferBltConfigure;
UINTN FrameBufferBltConfigureSize;
+
+ UINT16 VMWareSVGA2_BasePort;
} QEMU_VIDEO_PRIVATE_DATA;
///
@@ -459,6 +466,13 @@ outw (
UINT16 Data
);
+VOID
+outl (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN Address,
+ UINT32 Data
+ );
+
UINT8
inb (
QEMU_VIDEO_PRIVATE_DATA *Private,
@@ -471,6 +485,12 @@ inw (
UINTN Address
);
+UINT32
+inl (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN Address
+ );
+
VOID
BochsWrite (
QEMU_VIDEO_PRIVATE_DATA *Private,
@@ -502,9 +522,39 @@ QemuVideoBochsModeSetup (
BOOLEAN IsQxl
);
+EFI_STATUS
+QemuVideoVmwareModeSetup (
+ QEMU_VIDEO_PRIVATE_DATA *Private
+ );
+
VOID
InstallVbeShim (
IN CONST CHAR16 *CardName,
IN EFI_PHYSICAL_ADDRESS FrameBufferBase
);
+
+VOID
+QemuVideoVMWSVGA2RegisterWrite (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINT16 reg,
+ UINT32 value
+ );
+
+UINT32
+QemuVideoVMWSVGA2RegisterRead (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINT16 reg
+ );
+
+EFI_STATUS
+QemuVideoVMWSVGA2CompleteModeData (
+ IN QEMU_VIDEO_PRIVATE_DATA *Private,
+ OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode
+ );
+
+void InitializeVMWSVGA2GraphicsMode (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ QEMU_VIDEO_BOCHS_MODES *ModeData
+ );
+
#endif
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h b/OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h
new file mode 100644
index 000000000000..1b9f71afb6db
--- /dev/null
+++ b/OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h
@@ -0,0 +1,51 @@
+/** @file
+ Unaligned port I/O, with implementations for various x86 compilers and a dummy
+ for platforms which do not support unaligned port I/O.
+
+ Copyright (c) 2017, Phil Dennis-Jordan.<BR>
+ 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 _UNALIGNED_IO_INTERNAL_H_
+#define _UNALIGNED_IO_INTERNAL_H_
+
+/**
+ Performs a 32-bit write to the specified, possibly unaligned I/O-type address.
+
+ If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+ @param[in] Port I/O port address
+ @param[in] Value 32-bit word to write
+
+ @return The value written to the I/O port.
+
+**/
+UINT32
+UnalignedIoWrite32 (
+ IN UINTN Port,
+ IN UINT32 Value
+ );
+
+/**
+ Reads 32-bit word from the specified, possibly unaligned I/O-type address.
+
+ If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+ @param[in] Port I/O port from which to read.
+
+ @return The value read from the specified location.
+
+**/
+UINT32
+UnalignedIoRead32 (
+ IN UINTN Port
+ );
+
+#endif
diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
index fc8025ec46de..84caf1672675 100644
--- a/OvmfPkg/QemuVideoDxe/Driver.c
+++ b/OvmfPkg/QemuVideoDxe/Driver.c
@@ -15,6 +15,7 @@
**/
#include "Qemu.h"
+#include "svga_reg.h"
#include <IndustryStandard/Acpi.h>
EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = {
@@ -58,6 +59,16 @@ QEMU_VIDEO_CARD gQemuVideoCardList[] = {
QEMU_VIDEO_BOCHS_MMIO,
L"QEMU VirtIO VGA"
},{
+#if defined MDE_CPU_IA32 || defined MDE_CPU_X64
+ //
+ // Support only platforms which can do unaligned port I/O
+ //
+ PCI_VENDOR_ID_VMWARE,
+ PCI_DEVICE_ID_VMWARE_SVGA2,
+ QEMU_VIDEO_VMWARE_SVGA2,
+ L"QEMU VMWare SVGA2"
+ },{
+#endif
0 /* end of list */
}
};
@@ -317,6 +328,41 @@ QemuVideoControllerDriverStart (
}
//
+ // Check if accessing VMWARE_SVGA2 interface works
+ //
+ if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA2) {
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *iodesc;
+ UINT32 TargetId;
+ UINT32 Svga2IDRead;
+
+ Private->PciIo->GetBarAttributes (
+ Private->PciIo,
+ PCI_BAR_IDX0,
+ NULL,
+ (VOID**) &iodesc
+ );
+ Private->VMWareSVGA2_BasePort = iodesc->AddrRangeMin;
+
+ TargetId = SVGA_ID_2;
+ while (1) {
+ QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_ID, TargetId);
+ Svga2IDRead = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_ID);
+ if ((Svga2IDRead == TargetId) || (TargetId <= SVGA_ID_0)) {
+ break;
+ }
+ --TargetId;
+ }
+
+ if (Svga2IDRead != TargetId) {
+ DEBUG ((DEBUG_ERROR, "QemuVideo: QEMU_VIDEO_VMWARE_SVGA2 ID mismatch"
+ " (got 0x%x, base address 0x%x)\n",
+ Svga2IDRead, Private->VMWareSVGA2_BasePort));
+ Status = EFI_DEVICE_ERROR;
+ goto RestoreAttributes;
+ }
+ }
+
+ //
// Get ParentDevicePath
//
Status = gBS->HandleProtocol (
@@ -371,6 +417,9 @@ QemuVideoControllerDriverStart (
case QEMU_VIDEO_BOCHS:
Status = QemuVideoBochsModeSetup (Private, IsQxl);
break;
+ case QEMU_VIDEO_VMWARE_SVGA2:
+ Status = QemuVideoVmwareModeSetup (Private);
+ break;
default:
ASSERT (FALSE);
Status = EFI_DEVICE_ERROR;
@@ -975,3 +1024,21 @@ InitializeQemuVideo (
return Status;
}
+
+void InitializeVMWSVGA2GraphicsMode (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ QEMU_VIDEO_BOCHS_MODES *ModeData
+ )
+{
+ QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_WIDTH, ModeData->Width);
+ QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_HEIGHT, ModeData->Height);
+
+ UINT32 capabilities = QemuVideoVMWSVGA2RegisterRead (
+ Private, SVGA_REG_CAPABILITIES);
+ if ((capabilities & SVGA_CAP_8BIT_EMULATION) != 0) {
+ QemuVideoVMWSVGA2RegisterWrite(
+ Private, SVGA_REG_BITS_PER_PIXEL, ModeData->ColorDepth);
+ }
+ SetDefaultPalette (Private);
+ ClearScreen (Private);
+}
diff --git a/OvmfPkg/QemuVideoDxe/Gop.c b/OvmfPkg/QemuVideoDxe/Gop.c
index 359e9217d3d1..05c571b78aa7 100644
--- a/OvmfPkg/QemuVideoDxe/Gop.c
+++ b/OvmfPkg/QemuVideoDxe/Gop.c
@@ -14,6 +14,7 @@
**/
#include "Qemu.h"
+#include "svga_reg.h"
STATIC
VOID
@@ -76,6 +77,63 @@ QemuVideoCompleteModeData (
}
+EFI_STATUS
+QemuVMSVGA2VideoCompleteModeData (
+ IN QEMU_VIDEO_PRIVATE_DATA *Private,
+ OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode
+ )
+{
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc;
+ UINT32 RedMask, GreenMask, BlueMask;
+ UINT32 BitsPerPixel, BytesPerLine, FBOffset;
+
+ Info = Mode->Info;
+ Info->Version = 0;
+ Info->PixelFormat = PixelBitMask;
+
+ RedMask = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_RED_MASK);
+ Info->PixelInformation.RedMask = RedMask;
+
+ GreenMask = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_GREEN_MASK);
+ Info->PixelInformation.GreenMask = GreenMask;
+
+ BlueMask = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_BLUE_MASK);
+ Info->PixelInformation.BlueMask = BlueMask;
+
+ QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_ENABLE, 1);
+
+ FBOffset = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_FB_OFFSET);
+ BytesPerLine = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_BYTES_PER_LINE);
+ BitsPerPixel = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_BITS_PER_PIXEL);
+
+ if (BitsPerPixel == 32) {
+ if (BlueMask == 0xff && GreenMask == 0xff00 && RedMask == 0xff0000) {
+ Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
+ } else if (BlueMask == 0xff0000 && GreenMask == 0xff00 && RedMask == 0xff) {
+ Info->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;
+ }
+ }
+
+ Info->PixelInformation.ReservedMask = ((0x2u << (BitsPerPixel - 1u)) - 1u)
+ & ~(RedMask | GreenMask | BlueMask);
+ Info->PixelsPerScanLine = BytesPerLine / (BitsPerPixel / 8);
+
+ Private->PciIo->GetBarAttributes (
+ Private->PciIo,
+ PCI_BAR_IDX1,
+ NULL,
+ (VOID**) &FrameBufDesc
+ );
+
+ Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin + FBOffset;
+ Mode->FrameBufferSize = BytesPerLine * Info->VerticalResolution;
+
+ FreePool (FrameBufDesc);
+ return EFI_SUCCESS;
+}
+
+
//
// Graphics Output Protocol Member Functions
//
@@ -129,6 +187,10 @@ Routine Description:
(*Info)->VerticalResolution = ModeData->VerticalResolution;
QemuVideoCompleteModeInfo (ModeData, *Info);
+ if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA2) {
+ (*Info)->PixelsPerScanLine = ModeData->PixelsPerLine;
+ }
+
return EFI_SUCCESS;
}
@@ -176,6 +238,9 @@ Routine Description:
case QEMU_VIDEO_BOCHS:
InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);
break;
+ case QEMU_VIDEO_VMWARE_SVGA2:
+ InitializeVMWSVGA2GraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);
+ break;
default:
ASSERT (FALSE);
return EFI_DEVICE_ERROR;
@@ -186,7 +251,11 @@ Routine Description:
This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
- QemuVideoCompleteModeData (Private, This->Mode);
+ if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA2) {
+ QemuVMSVGA2VideoCompleteModeData(Private, This->Mode);
+ } else {
+ QemuVideoCompleteModeData (Private, This->Mode);
+ }
//
// Re-initialize the frame buffer configure when mode changes.
diff --git a/OvmfPkg/QemuVideoDxe/Initialize.c b/OvmfPkg/QemuVideoDxe/Initialize.c
index d5d8cfef9661..a33d178b2d42 100644
--- a/OvmfPkg/QemuVideoDxe/Initialize.c
+++ b/OvmfPkg/QemuVideoDxe/Initialize.c
@@ -14,6 +14,8 @@
**/
#include "Qemu.h"
+#include "svga_reg.h"
+#include "UnalignedIoInternal.h"
///
@@ -346,3 +348,89 @@ QemuVideoBochsModeSetup (
return EFI_SUCCESS;
}
+VOID
+QemuVideoVMWSVGA2RegisterWrite (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINT16 reg,
+ UINT32 value
+ )
+{
+ UnalignedIoWrite32 (Private->VMWareSVGA2_BasePort + SVGA_INDEX_PORT, reg);
+ UnalignedIoWrite32 (Private->VMWareSVGA2_BasePort + SVGA_VALUE_PORT, value);
+}
+
+UINT32
+QemuVideoVMWSVGA2RegisterRead (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINT16 reg
+ )
+{
+ UnalignedIoWrite32 (Private->VMWareSVGA2_BasePort + SVGA_INDEX_PORT, reg);
+ return UnalignedIoRead32 (Private->VMWareSVGA2_BasePort + SVGA_VALUE_PORT);
+}
+
+EFI_STATUS
+QemuVideoVmwareModeSetup (
+ QEMU_VIDEO_PRIVATE_DATA *Private
+ )
+{
+ UINT32 FBSize;
+ UINT32 MaxWidth, MaxHeight;
+ UINT32 Capabilities;
+ UINT32 HostBitsPerPixel;
+ UINT32 Index;
+ QEMU_VIDEO_MODE_DATA *ModeData;
+ QEMU_VIDEO_BOCHS_MODES *VideoMode;
+
+ QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_ENABLE, 0);
+
+ Private->ModeData =
+ AllocatePool (sizeof (Private->ModeData[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT);
+ if (Private->ModeData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FBSize = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_FB_SIZE);
+ MaxWidth = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_MAX_WIDTH);
+ MaxHeight = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_MAX_HEIGHT);
+ Capabilities = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_CAPABILITIES);
+ if ((Capabilities & SVGA_CAP_8BIT_EMULATION) != 0) {
+ HostBitsPerPixel =
+ QemuVideoVMWSVGA2RegisterRead(Private, SVGA_REG_HOST_BITS_PER_PIXEL);
+ QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_BITS_PER_PIXEL, HostBitsPerPixel);
+ } else {
+ HostBitsPerPixel = QemuVideoVMWSVGA2RegisterRead(Private, SVGA_REG_BITS_PER_PIXEL);
+ }
+
+ ModeData = Private->ModeData;
+ VideoMode = &QemuVideoBochsModes[0];
+ for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index ++) {
+ UINTN RequiredFbSize;
+
+ ASSERT (HostBitsPerPixel % 8 == 0);
+ RequiredFbSize = (UINTN) VideoMode->Width * VideoMode->Height *
+ (HostBitsPerPixel / 8);
+ if (RequiredFbSize <= FBSize
+ && VideoMode->Width <= MaxWidth
+ && VideoMode->Height <= MaxHeight)
+ {
+ UINT32 BytesPerLine;
+
+ QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_WIDTH, VideoMode->Width);
+ QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_HEIGHT, VideoMode->Height);
+ BytesPerLine =
+ QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_BYTES_PER_LINE);
+ ModeData->PixelsPerLine = BytesPerLine / (HostBitsPerPixel / 8);
+
+ ModeData->InternalModeIndex = Index;
+ ModeData->HorizontalResolution = VideoMode->Width;
+ ModeData->VerticalResolution = VideoMode->Height;
+ ModeData->ColorDepth = HostBitsPerPixel;
+
+ ModeData ++;
+ }
+ VideoMode ++;
+ }
+ Private->MaxMode = ModeData - Private->ModeData;
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c b/OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c
new file mode 100644
index 000000000000..55e283b392e9
--- /dev/null
+++ b/OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c
@@ -0,0 +1,59 @@
+/** @file
+ Unaligned Port I/O. This file has compiler specifics for GCC as there is no
+ ANSI C standard for doing IO.
+
+ Based on IoLibGcc.c.
+
+ Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UnalignedIoInternal.h"
+
+/**
+ Reads 32-bit word from the specified, possibly unaligned I/O-type address.
+
+ If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+ @param[in] Port I/O port from which to read.
+
+ @return The value read from the specified location.
+**/
+UINT32
+UnalignedIoRead32 (
+ IN UINTN Port
+ )
+{
+ UINT32 Data;
+ __asm__ __volatile__ ( "inl %1, %0" : "=a"(Data) : "Nd"((UINT16)Port) );
+ return Data;
+}
+
+/**
+ Performs a 32-bit write to the specified, possibly unaligned I/O-type address.
+
+ If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+ @param[in] Port I/O port address
+ @param[in] Value 32-bit word to write
+
+ @return The value written to the I/O port.
+
+**/
+UINT32
+UnalignedIoWrite32 (
+ IN UINTN Port,
+ IN UINT32 Value
+ )
+{
+ __asm__ __volatile__ ( "outl %0, %1" : : "a"(Value), "Nd"((UINT16)Port) );
+ return Value;
+}
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c b/OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c
new file mode 100644
index 000000000000..cc2274462db9
--- /dev/null
+++ b/OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c
@@ -0,0 +1,79 @@
+/** @file
+ Unaligned port I/O. This file has compiler specifics for ICC as there
+ is no ANSI C standard for doing IO.
+
+ Based on IoLibIcc.c.
+
+ Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+ 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 "UnalignedIoInternal.h"
+
+/**
+ Reads 32-bit word from the specified, possibly unaligned I/O-type address.
+
+ Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned.
+ This function must guarantee that all I/O read and write operations are
+ serialized.
+
+ If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+ @param Port The I/O port to read.
+
+ @return The value read.
+
+**/
+UINT32
+UnalignedIoRead32 (
+ IN UINTN Port
+ )
+{
+ UINT32 Data;
+
+ __asm {
+ mov dx, word ptr [Port]
+ in eax, dx
+ mov dword ptr [Data], eax
+ }
+
+ return Data;
+}
+
+/**
+ Performs a 32-bit write to the specified, possibly unaligned I/O-type address.
+
+ Writes the 32-bit I/O port specified by Port with the value specified by Value
+ and returns Value. This function must guarantee that all I/O read and write
+ operations are serialized.
+
+ If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+ @param Port The I/O port to write.
+ @param Value The value to write to the I/O port.
+
+ @return The value written the I/O port.
+
+**/
+UINT32
+UnalignedIoWrite32 (
+ IN UINTN Port,
+ IN UINT32 Value
+ )
+{
+ __asm {
+ mov eax, dword ptr [Value]
+ mov dx, word ptr [Port]
+ out dx, eax
+ }
+
+ return Value;
+}
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c b/OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c
new file mode 100644
index 000000000000..436ff39da253
--- /dev/null
+++ b/OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c
@@ -0,0 +1,81 @@
+/** @file
+ Unaligned port I/O. This file has compiler specifics for Microsoft C as there
+ is no ANSI C standard for doing IO.
+
+ Based on IoLibMsc.c
+
+ Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UnalignedIoInternal.h"
+
+unsigned long _inpd (unsigned short port);
+unsigned long _outpd (unsigned short port, unsigned long dataword );
+void _ReadWriteBarrier (void);
+
+/**
+ Reads 32-bit word from the specified, possibly unaligned I/O-type address.
+
+ Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned.
+ This function must guarantee that all I/O read and write operations are
+ serialized.
+
+ If 32-bit I/O port operations are not supported, then ASSERT().
+ If Port is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Port The I/O port to read.
+
+ @return The value read.
+
+**/
+UINT32
+EFIAPI
+UnalignedIoRead32 (
+ IN UINTN Port
+ )
+{
+ UINT32 Value;
+
+ _ReadWriteBarrier ();
+ Value = _inpd ((UINT16)Port);
+ _ReadWriteBarrier ();
+ return Value;
+}
+
+/**
+ Performs a 32-bit write to the specified, possibly unaligned I/O-type address.
+
+ Writes the 32-bit I/O port specified by Port with the value specified by Value
+ and returns Value. This function must guarantee that all I/O read and write
+ operations are serialized.
+
+ If 32-bit I/O port operations are not supported, then ASSERT().
+ If Port is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Port The I/O port to write.
+ @param Value The value to write to the I/O port.
+
+ @return The value written to the I/O port.
+
+**/
+UINT32
+EFIAPI
+UnalignedIoWrite32 (
+ IN UINTN Port,
+ IN UINT32 Value
+ )
+{
+ _ReadWriteBarrier ();
+ _outpd ((UINT16)Port, Value);
+ _ReadWriteBarrier ();
+ return Value;
+}
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c b/OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c
new file mode 100644
index 000000000000..20b185869ef5
--- /dev/null
+++ b/OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c
@@ -0,0 +1,53 @@
+/** @file
+ Unaligned port I/O dummy implementation for platforms which do not support it.
+
+ Copyright (c) 2017, Phil Dennis-Jordan.<BR>
+ 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 "UnalignedIoInternal.h"
+
+/**
+ Reads 32-bit word from the specified, possibly unaligned I/O-type address.
+
+ If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+ @param[in] Port I/O port from which to read.
+
+ @return The value read from the specified location.
+**/
+UINT32
+UnalignedIoRead32 (
+ IN UINTN Port
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ Performs a 32-bit write to the specified, possibly unaligned I/O-type address.
+
+ If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+ @param[in] Port I/O port address
+ @param[in] Value 32-bit word to write
+
+ @return The value written to the I/O port.
+
+**/
+UINT32
+UnalignedIoWrite32 (
+ IN UINTN Port,
+ IN UINT32 Value
+ )
+{
+ ASSERT (FALSE);
+}
--
2.3.2 (Apple Git-55)
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2024 Red Hat, Inc.