diff options
-rw-r--r-- | OvmfPkg/QemuVideoDxe/Driver.c | 9 | ||||
-rw-r--r-- | OvmfPkg/QemuVideoDxe/Initialize.c | 47 | ||||
-rw-r--r-- | OvmfPkg/QemuVideoDxe/Qemu.h | 3 |
3 files changed, 53 insertions, 6 deletions
diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c index 2194cbef44..17bd4cc2cc 100644 --- a/OvmfPkg/QemuVideoDxe/Driver.c +++ b/OvmfPkg/QemuVideoDxe/Driver.c @@ -173,6 +173,7 @@ QemuVideoControllerDriverStart ( EFI_TPL OldTpl;
EFI_STATUS Status;
QEMU_VIDEO_PRIVATE_DATA *Private;
+ BOOLEAN IsQxl;
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
ACPI_ADR_DEVICE_PATH AcpiDeviceNode;
PCI_TYPE00 Pci;
@@ -235,6 +236,12 @@ QemuVideoControllerDriverStart ( Private->Variant = Card->Variant;
//
+ // IsQxl is based on the detected Card->Variant, which at a later point might
+ // not match Private->Variant.
+ //
+ IsQxl = (BOOLEAN)(Card->Variant == QEMU_VIDEO_BOCHS);
+
+ //
// Save original PCI attributes
//
Status = Private->PciIo->Attributes (
@@ -354,7 +361,7 @@ QemuVideoControllerDriverStart ( break;
case QEMU_VIDEO_BOCHS_MMIO:
case QEMU_VIDEO_BOCHS:
- Status = QemuVideoBochsModeSetup (Private);
+ Status = QemuVideoBochsModeSetup (Private, IsQxl);
break;
default:
ASSERT (FALSE);
diff --git a/OvmfPkg/QemuVideoDxe/Initialize.c b/OvmfPkg/QemuVideoDxe/Initialize.c index a536d47bbb..9e0c3aa09f 100644 --- a/OvmfPkg/QemuVideoDxe/Initialize.c +++ b/OvmfPkg/QemuVideoDxe/Initialize.c @@ -253,7 +253,8 @@ QEMU_VIDEO_BOCHS_MODES QemuVideoBochsModes[] = { EFI_STATUS
QemuVideoBochsModeSetup (
- QEMU_VIDEO_PRIVATE_DATA *Private
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ BOOLEAN IsQxl
)
{
UINT32 AvailableFbSize;
@@ -262,10 +263,48 @@ QemuVideoBochsModeSetup ( QEMU_VIDEO_BOCHS_MODES *VideoMode;
//
- // fetch available framebuffer size
+ // Fetch the available framebuffer size.
+ //
+ // VBE_DISPI_INDEX_VIDEO_MEMORY_64K is expected to return the size of the
+ // drawable framebuffer. Up to and including qemu-2.1 however it used to
+ // return the size of PCI BAR 0 (ie. the full video RAM size).
+ //
+ // On stdvga the two concepts coincide with each other; the full memory size
+ // is usable for drawing.
//
- AvailableFbSize = BochsRead (Private, VBE_DISPI_INDEX_VIDEO_MEMORY_64K);
- AvailableFbSize *= SIZE_64KB;
+ // On QXL however, only a leading segment, "surface 0", can be used for
+ // drawing; the rest of the video memory is used for the QXL guest-host
+ // protocol. VBE_DISPI_INDEX_VIDEO_MEMORY_64K should report the size of
+ // "surface 0", but since it doesn't (up to and including qemu-2.1), we
+ // retrieve the size of the drawable portion from a field in the QXL ROM BAR,
+ // where it is also available.
+ //
+ if (IsQxl) {
+ UINT32 Signature;
+ UINT32 DrawStart;
+
+ Signature = 0;
+ DrawStart = 0xFFFFFFFF;
+ AvailableFbSize = 0;
+ if (EFI_ERROR (
+ Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,
+ PCI_BAR_IDX2, 0, 1, &Signature)) ||
+ Signature != SIGNATURE_32 ('Q', 'X', 'R', 'O') ||
+ EFI_ERROR (
+ Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,
+ PCI_BAR_IDX2, 36, 1, &DrawStart)) ||
+ DrawStart != 0 ||
+ EFI_ERROR (
+ Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,
+ PCI_BAR_IDX2, 40, 1, &AvailableFbSize))) {
+ DEBUG ((EFI_D_ERROR, "%a: can't read size of drawable buffer from QXL "
+ "ROM\n", __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+ } else {
+ AvailableFbSize = BochsRead (Private, VBE_DISPI_INDEX_VIDEO_MEMORY_64K);
+ AvailableFbSize *= SIZE_64KB;
+ }
DEBUG ((EFI_D_VERBOSE, "%a: AvailableFbSize=0x%x\n", __FUNCTION__,
AvailableFbSize));
diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h index 4bf51c7150..52ee20d8ba 100644 --- a/OvmfPkg/QemuVideoDxe/Qemu.h +++ b/OvmfPkg/QemuVideoDxe/Qemu.h @@ -499,7 +499,8 @@ QemuVideoCirrusModeSetup ( EFI_STATUS
QemuVideoBochsModeSetup (
- QEMU_VIDEO_PRIVATE_DATA *Private
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ BOOLEAN IsQxl
);
VOID
|