Skip to content

Commit

Permalink
OvmfPkg: QemuVideoDxe: Int10h stub for Windows 7 & 2008 (stdvga, QXL)
Browse files Browse the repository at this point in the history
The Windows 2008 R2 SP1 (and Windows 7) UEFI guest's default video driver
dereferences the real mode Int10h vector, loads the pointed-to handler
code, and executes what it thinks to be VGA BIOS services in an internal
real-mode emulator. Consequently, video mode switching doesn't work in
Windows 2008 R2 SP1 when it runs on the pure UEFI build of OVMF, making
the guest uninstallable.

This patch adds a VGABIOS "shim" to QemuVideoDxe. For the first stdvga or
QXL card bound, an extremely stripped down VGABIOS imitation is installed
in the C segment. It provides a real implementation for the few services
that are in fact necessary for the win2k8r2sp1 UEFI guest, plus some fakes
that the guest invokes but whose effect is not important.

The C segment is not present in the UEFI memory map prepared by OVMF. We
never add memory space that would cover it (either in PEI, in the form of
memory resource descriptor HOBs, or in DXE, via gDS->AddMemorySpace()).
This way the handler body is invisible to all non-buggy UEFI guests, and
the rest of edk2.

The Int10h real-mode IVT entry is covered with a Boot Services Code page,
making that too unaccessible to the rest of edk2. (Thus UEFI guest OSes
different from the Windows 2008 family can reclaim the page. The Windows
2008 family accesses the page at zero regardless of the allocation type.)

The patch is the result of collaboration:

Initial proof of concept IVT entry installation and handler skeleton (in
NASM) by Jordan Justen.

Service tracing and implementation, data collection/analysis, and C coding
by yours truly.

Last minute changes by Gerd Hoffmann:
- Use OEM mode number (0xf1) instead of standard 800x600 mode (0x143). The
  resolution of the OEM mode (0xf1) is not standardized; the guest can't
  expect anything from it in advance.
- Use 1024x768 rather than 800x600 for more convenience in the Windows
  2008 R2 SP1 guest during OS installation, and after normal boot until
  the QXL XDDM guest driver is installed.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15540 6f19259b-4bc3-4df7-8a09-765794883524
  • Loading branch information
lersek authored and jljusten committed May 20, 2014
1 parent d8f36fb commit 9080334
Show file tree
Hide file tree
Showing 9 changed files with 1,470 additions and 0 deletions.
97 changes: 97 additions & 0 deletions OvmfPkg/Include/IndustryStandard/LegacyVgaBios.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/** @file
Type definitions related to the VBE (VESA BIOS Extension, Int10h AH=4Fh)
services GET INFORMATION (AL=00h) and GET MODE INFORMATION (AL=01h).
For reference, see Ralf Brown's Interrupt List:
<http://www.cs.cmu.edu/~ralf/files.html>
<http://www.ctyme.com/rbrown.htm>
Copyright (C) 2014, Red Hat, Inc.
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 __LEGACY_VGA_BIOS_H__
#define __LEGACY_VGA_BIOS_H__

#include <Base.h>

#pragma pack (1)
typedef struct {
UINT8 Signature[4];
UINT16 VesaVersion;
UINT32 OemNameAddress;
UINT32 Capabilities;
UINT32 ModeListAddress;
UINT16 VideoMem64K;
UINT16 OemSoftwareVersion;
UINT32 VendorNameAddress;
UINT32 ProductNameAddress;
UINT32 ProductRevAddress;
} VBE_INFO_BASE;

typedef struct {
VBE_INFO_BASE Base;
UINT8 Buffer[256 - sizeof (VBE_INFO_BASE)];
} VBE_INFO;

typedef struct {
UINT16 ModeAttr;
UINT8 WindowAAttr;
UINT8 WindowBAttr;
UINT16 WindowGranularityKB;
UINT16 WindowSizeKB;
UINT16 WindowAStartSegment;
UINT16 WindowBStartSegment;
UINT32 WindowPositioningAddress;
UINT16 BytesPerScanLine;

UINT16 Width;
UINT16 Height;
UINT8 CharCellWidth;
UINT8 CharCellHeight;
UINT8 NumPlanes;
UINT8 BitsPerPixel;
UINT8 NumBanks;
UINT8 MemoryModel;
UINT8 BankSizeKB;
UINT8 NumImagePagesLessOne;
UINT8 Vbe3;

UINT8 RedMaskSize;
UINT8 RedMaskPos;
UINT8 GreenMaskSize;
UINT8 GreenMaskPos;
UINT8 BlueMaskSize;
UINT8 BlueMaskPos;
UINT8 ReservedMaskSize;
UINT8 ReservedMaskPos;
UINT8 DirectColorModeInfo;

UINT32 LfbAddress;
UINT32 OffScreenAddress;
UINT16 OffScreenSizeKB;

UINT16 BytesPerScanLineLinear;
UINT8 NumImagesLessOneBanked;
UINT8 NumImagesLessOneLinear;
UINT8 RedMaskSizeLinear;
UINT8 RedMaskPosLinear;
UINT8 GreenMaskSizeLinear;
UINT8 GreenMaskPosLinear;
UINT8 BlueMaskSizeLinear;
UINT8 BlueMaskPosLinear;
UINT8 ReservedMaskSizeLinear;
UINT8 ReservedMaskPosLinear;
UINT32 MaxPixelClockHz;
UINT8 Reserved[190];
} VBE_MODE_INFO;
#pragma pack ()

#endif
5 changes: 5 additions & 0 deletions OvmfPkg/QemuVideoDxe/Driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,11 @@ QemuVideoControllerDriverStart (
goto UninstallGop;
}

if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
Private->Variant == QEMU_VIDEO_BOCHS) {
InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
}

gBS->RestoreTPL (OldTpl);
return EFI_SUCCESS;

Expand Down
5 changes: 5 additions & 0 deletions OvmfPkg/QemuVideoDxe/Qemu.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,4 +502,9 @@ QemuVideoBochsModeSetup (
QEMU_VIDEO_PRIVATE_DATA *Private
);

VOID
InstallVbeShim (
IN CONST CHAR16 *CardName,
IN EFI_PHYSICAL_ADDRESS FrameBufferBase
);
#endif
4 changes: 4 additions & 0 deletions OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,21 @@
DriverSupportedEfiVersion.c
Gop.c
Initialize.c
VbeShim.c

[Packages]
MdePkg/MdePkg.dec
OptionRomPkg/OptionRomPkg.dec
OvmfPkg/OvmfPkg.dec

[LibraryClasses]
BaseMemoryLib
BltLib
DebugLib
DevicePathLib
MemoryAllocationLib
PciLib
PrintLib
TimerLib
UefiBootServicesTableLib
UefiDriverEntryPoint
Expand Down

0 comments on commit 9080334

Please sign in to comment.