OvmfPkg/QemuVideoDxe: VMWare SVGA device support
In addition to the QXL, Cirrus, etc. VGA adapters, Qemu also implements a basic version of VMWare's SVGA display device. Drivers for this device exist for some 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 SVGA device's framebuffer to QemuVideoDxe's graphics output protocol implementation, based on VMWare's documentation. The most basic initialisation, framebuffer layout query, and mode setting operations are implemented. The device relies on port-based 32-bit I/O, unfortunately on misaligned addresses. This 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> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
This commit is contained in:
committed by
Laszlo Ersek
parent
05a5379458
commit
c137d95081
@@ -14,8 +14,10 @@
|
||||
|
||||
**/
|
||||
|
||||
#include "Qemu.h"
|
||||
#include <IndustryStandard/VmwareSvga.h>
|
||||
#include <IndustryStandard/Acpi.h>
|
||||
#include "Qemu.h"
|
||||
#include "UnalignedIoInternal.h"
|
||||
|
||||
EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = {
|
||||
QemuVideoControllerDriverSupported,
|
||||
@@ -57,6 +59,11 @@ QEMU_VIDEO_CARD gQemuVideoCardList[] = {
|
||||
0x1050,
|
||||
QEMU_VIDEO_BOCHS_MMIO,
|
||||
L"QEMU VirtIO VGA"
|
||||
},{
|
||||
VMWARE_PCI_VENDOR_ID_VMWARE,
|
||||
VMWARE_PCI_DEVICE_ID_VMWARE_SVGA2,
|
||||
QEMU_VIDEO_VMWARE_SVGA,
|
||||
L"QEMU VMWare SVGA"
|
||||
},{
|
||||
0 /* end of list */
|
||||
}
|
||||
@@ -242,6 +249,7 @@ QemuVideoControllerDriverStart (
|
||||
goto ClosePciIo;
|
||||
}
|
||||
Private->Variant = Card->Variant;
|
||||
Private->FrameBufferVramBarIndex = PCI_BAR_IDX0;
|
||||
|
||||
//
|
||||
// IsQxl is based on the detected Card->Variant, which at a later point might
|
||||
@@ -316,6 +324,58 @@ QemuVideoControllerDriverStart (
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check if accessing Vmware SVGA interface works
|
||||
//
|
||||
if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {
|
||||
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *IoDesc;
|
||||
UINT32 TargetId;
|
||||
UINT32 SvgaIdRead;
|
||||
|
||||
IoDesc = NULL;
|
||||
Status = Private->PciIo->GetBarAttributes (
|
||||
Private->PciIo,
|
||||
PCI_BAR_IDX0,
|
||||
NULL,
|
||||
(VOID**) &IoDesc
|
||||
);
|
||||
if (EFI_ERROR (Status) ||
|
||||
IoDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_IO ||
|
||||
IoDesc->AddrRangeMin > MAX_UINT16 + 1 - (VMWARE_SVGA_VALUE_PORT + 4)) {
|
||||
if (IoDesc != NULL) {
|
||||
FreePool (IoDesc);
|
||||
}
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto RestoreAttributes;
|
||||
}
|
||||
Private->VmwareSvgaBasePort = (UINT16) IoDesc->AddrRangeMin;
|
||||
FreePool (IoDesc);
|
||||
|
||||
TargetId = VMWARE_SVGA_ID_2;
|
||||
while (TRUE) {
|
||||
VmwareSvgaWrite (Private, VmwareSvgaRegId, TargetId);
|
||||
SvgaIdRead = VmwareSvgaRead (Private, VmwareSvgaRegId);
|
||||
if ((SvgaIdRead == TargetId) || (TargetId <= VMWARE_SVGA_ID_0)) {
|
||||
break;
|
||||
}
|
||||
TargetId--;
|
||||
}
|
||||
|
||||
if (SvgaIdRead != TargetId) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"QemuVideo: QEMU_VIDEO_VMWARE_SVGA ID mismatch "
|
||||
"(got 0x%x, base address 0x%x)\n",
|
||||
SvgaIdRead,
|
||||
Private->VmwareSvgaBasePort
|
||||
));
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto RestoreAttributes;
|
||||
}
|
||||
|
||||
Private->FrameBufferVramBarIndex = PCI_BAR_IDX1;
|
||||
}
|
||||
|
||||
//
|
||||
// Get ParentDevicePath
|
||||
//
|
||||
@@ -371,6 +431,9 @@ QemuVideoControllerDriverStart (
|
||||
case QEMU_VIDEO_BOCHS:
|
||||
Status = QemuVideoBochsModeSetup (Private, IsQxl);
|
||||
break;
|
||||
case QEMU_VIDEO_VMWARE_SVGA:
|
||||
Status = QemuVideoVmwareSvgaModeSetup (Private);
|
||||
break;
|
||||
default:
|
||||
ASSERT (FALSE);
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
@@ -432,6 +495,9 @@ DestructQemuVideoGraphics:
|
||||
|
||||
FreeModeData:
|
||||
FreePool (Private->ModeData);
|
||||
if (Private->VmwareSvgaModeInfo != NULL) {
|
||||
FreePool (Private->VmwareSvgaModeInfo);
|
||||
}
|
||||
|
||||
UninstallGopDevicePath:
|
||||
gBS->UninstallProtocolInterface (Private->Handle,
|
||||
@@ -553,6 +619,9 @@ QemuVideoControllerDriverStop (
|
||||
);
|
||||
|
||||
FreePool (Private->ModeData);
|
||||
if (Private->VmwareSvgaModeInfo != NULL) {
|
||||
FreePool (Private->VmwareSvgaModeInfo);
|
||||
}
|
||||
gBS->UninstallProtocolInterface (Private->Handle,
|
||||
&gEfiDevicePathProtocolGuid, Private->GopDevicePath);
|
||||
FreePool (Private->GopDevicePath);
|
||||
@@ -750,7 +819,7 @@ ClearScreen (
|
||||
Private->PciIo->Mem.Write (
|
||||
Private->PciIo,
|
||||
EfiPciIoWidthFillUint32,
|
||||
0,
|
||||
Private->FrameBufferVramBarIndex,
|
||||
0,
|
||||
0x400000 >> 2,
|
||||
&Color
|
||||
@@ -887,6 +956,38 @@ BochsRead (
|
||||
return Data;
|
||||
}
|
||||
|
||||
VOID
|
||||
VmwareSvgaWrite (
|
||||
QEMU_VIDEO_PRIVATE_DATA *Private,
|
||||
UINT16 Register,
|
||||
UINT32 Value
|
||||
)
|
||||
{
|
||||
UnalignedIoWrite32 (
|
||||
Private->VmwareSvgaBasePort + VMWARE_SVGA_INDEX_PORT,
|
||||
Register
|
||||
);
|
||||
UnalignedIoWrite32 (
|
||||
Private->VmwareSvgaBasePort + VMWARE_SVGA_VALUE_PORT,
|
||||
Value
|
||||
);
|
||||
}
|
||||
|
||||
UINT32
|
||||
VmwareSvgaRead (
|
||||
QEMU_VIDEO_PRIVATE_DATA *Private,
|
||||
UINT16 Register
|
||||
)
|
||||
{
|
||||
UnalignedIoWrite32 (
|
||||
Private->VmwareSvgaBasePort + VMWARE_SVGA_INDEX_PORT,
|
||||
Register
|
||||
);
|
||||
return UnalignedIoRead32 (
|
||||
Private->VmwareSvgaBasePort + VMWARE_SVGA_VALUE_PORT
|
||||
);
|
||||
}
|
||||
|
||||
VOID
|
||||
VgaOutb (
|
||||
QEMU_VIDEO_PRIVATE_DATA *Private,
|
||||
@@ -941,6 +1042,35 @@ InitializeBochsGraphicsMode (
|
||||
ClearScreen (Private);
|
||||
}
|
||||
|
||||
VOID
|
||||
InitializeVmwareSvgaGraphicsMode (
|
||||
QEMU_VIDEO_PRIVATE_DATA *Private,
|
||||
QEMU_VIDEO_BOCHS_MODES *ModeData
|
||||
)
|
||||
{
|
||||
UINT32 Capabilities;
|
||||
|
||||
VmwareSvgaWrite (Private, VmwareSvgaRegWidth, ModeData->Width);
|
||||
VmwareSvgaWrite (Private, VmwareSvgaRegHeight, ModeData->Height);
|
||||
|
||||
Capabilities = VmwareSvgaRead (
|
||||
Private,
|
||||
VmwareSvgaRegCapabilities
|
||||
);
|
||||
if ((Capabilities & VMWARE_SVGA_CAP_8BIT_EMULATION) != 0) {
|
||||
VmwareSvgaWrite (
|
||||
Private,
|
||||
VmwareSvgaRegBitsPerPixel,
|
||||
ModeData->ColorDepth
|
||||
);
|
||||
}
|
||||
|
||||
VmwareSvgaWrite (Private, VmwareSvgaRegEnable, 1);
|
||||
|
||||
SetDefaultPalette (Private);
|
||||
ClearScreen (Private);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
InitializeQemuVideo (
|
||||
|
Reference in New Issue
Block a user