On Thu, May 8, 2014 at 10:45 AM, Laszlo Ersek <ler...@redhat.com> wrote: > The Windows 2008 R2 SP1 UEFI guest's default video driver is buggy -- it > 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.
Can you add a Windows 2008 section to the README? For example, I think -vga qxl needs to be used, right? > 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 Reserved page, making > that too unaccessible to non-buggy UEFI guests and the rest of edk2. > > The patch is the result of collaboration: > > Initial IVT entry installation and handler skeleton (in NASM) by Jordan > Justen (almost completely rewritten). > > Service tracing and implementation, data collection/analysis, and C coding > by yours truly. > > Last minute changes by Gerd Hoffman: > - 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 <ler...@redhat.com> > --- > > Notes: > Tested as follows: > (1) Installed a fresh win2k8r2sp1 guest > (en_windows_server_2008_r2_with_sp1_x64_dvd_617601.iso), using the > QXL card. > - Installation completed fine, first normal boot went OK too. > - Upgraded video driver to QXL XDDM, enabling S3. > - Tested S3 suspend/resume twice in a row. > (2) Sanity checked preexistent Fedora 20 guest, including S3. > (3) Sanity checked preexistent RHEL-7 guest, including S3. > (4) Sanity checked preexistent RHEL-6 guest (Cirrus card -- no guest > drivers for Bochs or QXL, so the VBE shim isn't even installed. > Also, no S3 support in the guest.) > (5) Sanity checked preexistent Windows 2012 R2 guest, not including S3 > (QXL WDDM driver under development). Resolution set by PlatformDxe > takes effect / is inherited. > (6) Sanity checked preexistent Windows 8 guest, not including S3. See > Windows 2012 R2. > > OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf | 3 + > OvmfPkg/QemuVideoDxe/Qemu.h | 5 + > OvmfPkg/QemuVideoDxe/VbeShim.h | 820 > ++++++++++++++++++++++++++++++++++ > OvmfPkg/QemuVideoDxe/Driver.c | 17 + > OvmfPkg/QemuVideoDxe/VbeShim.c | 325 ++++++++++++++ > OvmfPkg/QemuVideoDxe/VbeShim.asm | 302 +++++++++++++ > OvmfPkg/QemuVideoDxe/VbeShim.sh | 82 ++++ > 7 files changed, 1554 insertions(+) > create mode 100644 OvmfPkg/QemuVideoDxe/VbeShim.h > create mode 100644 OvmfPkg/QemuVideoDxe/VbeShim.c > create mode 100644 OvmfPkg/QemuVideoDxe/VbeShim.asm > create mode 100755 OvmfPkg/QemuVideoDxe/VbeShim.sh > diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.c b/OvmfPkg/QemuVideoDxe/VbeShim.c > new file mode 100644 > index 0000000..1a32f1b > --- /dev/null > +++ b/OvmfPkg/QemuVideoDxe/VbeShim.c > @@ -0,0 +1,325 @@ > +/** @file > + Install a fake VGABIOS service handler (real mode Int10h) for the buggy > + Windows 2008 R2 SP1 UEFI guest. > + > + The handler is never meant to be directly executed by a VCPU; it's there > for > + the internal real mode emulator of Windows 2008 R2 SP1. > + > + The code is based on 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. > + Copyright (c) 2013 - 2014, 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 "Qemu.h" > +#include "VbeShim.h" > + > +#include <Library/DebugLib.h> > +#include <Library/PciLib.h> > +#include <Library/PrintLib.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; OvmfPkg/Include/IndustryStandard/LegacyVgaBios.h? > + > +typedef struct { > + UINT16 Offset; > + UINT16 Segment; > +} IVT_ENTRY; > +#pragma pack () > + > +// > +// This string is displayed by Windows 2008 R2 SP1 in the Screen Resolution, > +// Advanced Settings dialog. It should be short. > +// > +STATIC CONST CHAR8 mProductRevision[] = "OVMF Int10h (fake)"; > + > +/** > + Install the VBE Info and VBE Mode Info structures, and the VBE service > + handler routine in the C segment. Point the real-mode Int10h interrupt > vector > + to the handler. The only advertised mode is 1024x768x32. > + > + @param[in] CardName Name of the video card to be exposed in the > + Product Name field of the VBE Info structure. > The > + parameter must originate from a > + QEMU_VIDEO_CARD.Name field. > + @param[in] FrameBufferBase Guest-physical base address of the video card's > + frame buffer. > + > + @retval EFI_SUCCESS Shim successfully installed. > + @return gBS->AllocatePages() status codes. > +**/ > +EFI_STATUS > +InstallVbeShim ( > + IN CONST CHAR16 *CardName, > + IN EFI_PHYSICAL_ADDRESS FrameBufferBase > + ) > +{ > + UINTN Pam1Address; > + UINT8 Pam1; > + EFI_PHYSICAL_ADDRESS SegmentC; > + UINTN SegmentCPages; > + EFI_STATUS Status; > + VBE_INFO *VbeInfoFull; > + VBE_INFO_BASE *VbeInfo; > + UINT8 *Ptr; > + UINTN Printed; > + VBE_MODE_INFO *VbeModeInfo; > + EFI_PHYSICAL_ADDRESS Segment0; > + UINTN Segment0Pages; > + IVT_ENTRY *Int0x10; > + > + Pam1Address = PCI_LIB_ADDRESS (0, 0, 0, 0x5A); Should we use LegacyRegion here? I guess that would mean always enabling Csm/CsmSupportLib. > + // > + // low nibble covers 0xC0000 to 0xC3FFF > + // high nibble covers 0xC4000 to 0xC7FFF > + // bit1 in each nibble is Write Enable > + // bit0 in each nibble is Read Enable > + // > + Pam1 = PciRead8 (Pam1Address); > + PciWrite8 (Pam1Address, Pam1 | (BIT1 | BIT0)); > + > + // > + // We never added memory space durig PEI or DXE for the C segment, so we > + // don't need to (and can't) allocate from there. Also, guest operating > + // systems will see a hole in the UEFI memory map there. > + // > + SegmentC = 0xC0000; > + SegmentCPages = 4; > + > + ASSERT (sizeof mVbeShim <= EFI_PAGES_TO_SIZE (SegmentCPages)); > + CopyMem ((VOID *)(UINTN)SegmentC, mVbeShim, sizeof mVbeShim); > + > + // > + // Fill in the VBE INFO structure. > + // > + VbeInfoFull = (VBE_INFO *)(UINTN)SegmentC; > + VbeInfo = &VbeInfoFull->Base; > + Ptr = VbeInfoFull->Buffer; > + > + CopyMem (VbeInfo->Signature, "VESA", 4); > + VbeInfo->VesaVersion = 0x0300; > + > + VbeInfo->OemNameAddress = (UINT32)(SegmentC << 12 | (UINT16)(UINTN)Ptr); > + CopyMem (Ptr, "QEMU", 5); > + Ptr += 5; > + > + VbeInfo->Capabilities = BIT0; // DAC can be switched into 8-bit mode > + > + VbeInfo->ModeListAddress = (UINT32)(SegmentC << 12 | (UINT16)(UINTN)Ptr); > + *(UINT16*)Ptr = 0x00f1; // mode number > + Ptr += 2; > + *(UINT16*)Ptr = 0xFFFF; // mode list terminator > + Ptr += 2; > + > + VbeInfo->VideoMem64K = (UINT16)((1024 * 768 * 4 + 65535) / 65536); > + VbeInfo->OemSoftwareVersion = 0x0000; > + > + VbeInfo->VendorNameAddress = (UINT32)(SegmentC << 12 | (UINT16)(UINTN)Ptr); > + CopyMem (Ptr, "OVMF", 5); > + Ptr += 5; > + > + VbeInfo->ProductNameAddress = (UINT32)(SegmentC << 12 | > (UINT16)(UINTN)Ptr); > + Printed = AsciiSPrint ((CHAR8 *)Ptr, > + sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer), "%s", > + CardName); > + Ptr += Printed + 1; > + > + VbeInfo->ProductRevAddress = (UINT32)(SegmentC << 12 | (UINT16)(UINTN)Ptr); > + CopyMem (Ptr, mProductRevision, sizeof mProductRevision); > + Ptr += sizeof mProductRevision; > + > + ASSERT (sizeof VbeInfoFull->Buffer >= Ptr - VbeInfoFull->Buffer); > + ZeroMem (Ptr, sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer)); > + > + // > + // Fil in the VBE MODE INFO structure. > + // > + VbeModeInfo = (VBE_MODE_INFO *)(VbeInfoFull + 1); > + > + // > + // bit0: mode supported by present hardware configuration > + // bit1: optional information available (must be =1 for VBE v1.2+) > + // bit3: set if color, clear if monochrome > + // bit4: set if graphics mode, clear if text mode > + // bit5: mode is not VGA-compatible > + // bit7: linear framebuffer mode supported > + // > + VbeModeInfo->ModeAttr = BIT7 | BIT5 | BIT4 | BIT3 | BIT1 | BIT0; > + > + // > + // bit0: exists > + // bit1: bit1: readable > + // bit2: writeable > + // > + VbeModeInfo->WindowAAttr = BIT2 | BIT1 | BIT0; > + > + VbeModeInfo->WindowBAttr = 0x00; > + VbeModeInfo->WindowGranularityKB = 0x0040; > + VbeModeInfo->WindowSizeKB = 0x0040; > + VbeModeInfo->WindowAStartSegment = 0xA000; > + VbeModeInfo->WindowBStartSegment = 0x0000; > + VbeModeInfo->WindowPositioningAddress = 0x0000; > + VbeModeInfo->BytesPerScanLine = 1024 * 4; > + > + VbeModeInfo->Width = 1024; > + VbeModeInfo->Height = 768; > + VbeModeInfo->CharCellWidth = 8; > + VbeModeInfo->CharCellHeight = 16; > + VbeModeInfo->NumPlanes = 1; > + VbeModeInfo->BitsPerPixel = 32; > + VbeModeInfo->NumBanks = 1; > + VbeModeInfo->MemoryModel = 6; // direct color > + VbeModeInfo->BankSizeKB = 0; > + VbeModeInfo->NumImagePagesLessOne = 0; > + VbeModeInfo->Vbe3 = 0x01; > + > + VbeModeInfo->RedMaskSize = 8; > + VbeModeInfo->RedMaskPos = 16; > + VbeModeInfo->GreenMaskSize = 8; > + VbeModeInfo->GreenMaskPos = 8; > + VbeModeInfo->BlueMaskSize = 8; > + VbeModeInfo->BlueMaskPos = 0; > + VbeModeInfo->ReservedMaskSize = 8; > + VbeModeInfo->ReservedMaskPos = 24; > + > + // > + // bit1: Bytes in reserved field may be used by application > + // > + VbeModeInfo->DirectColorModeInfo = BIT1; > + > + VbeModeInfo->LfbAddress = (UINT32)FrameBufferBase; > + VbeModeInfo->OffScreenAddress = 0; > + VbeModeInfo->OffScreenSizeKB = 0; > + > + VbeModeInfo->BytesPerScanLineLinear = 1024 * 4; > + VbeModeInfo->NumImagesLessOneBanked = 0; > + VbeModeInfo->NumImagesLessOneLinear = 0; > + VbeModeInfo->RedMaskSizeLinear = 8; > + VbeModeInfo->RedMaskPosLinear = 16; > + VbeModeInfo->GreenMaskSizeLinear = 8; > + VbeModeInfo->GreenMaskPosLinear = 8; > + VbeModeInfo->BlueMaskSizeLinear = 8; > + VbeModeInfo->BlueMaskPosLinear = 0; > + VbeModeInfo->ReservedMaskSizeLinear = 8; > + VbeModeInfo->ReservedMaskPosLinear = 24; > + VbeModeInfo->MaxPixelClockHz = 0; > + > + ZeroMem (VbeModeInfo->Reserved, sizeof VbeModeInfo->Reserved); > + > + // > + // Clear Write Enable (bit1), keep Read Enable (bit0) set > + // > + PciWrite8 (Pam1Address, (Pam1 & ~BIT1) | BIT0); > + > + Segment0 = 0; > + Segment0Pages = 1; > + Status = gBS->AllocatePages (AllocateAddress, EfiReservedMemoryType, > + Segment0Pages, &Segment0); > + if (EFI_ERROR (Status)) { > + goto RestorePam1; > + } If CSM is enabled, we will fail to allocate, right? If we don't error here, and install the int10-stub, then wouldn't Windows 2008 still be able to use QemuVideoDxe? > + // > + // This is a UEFI driver -- the arch protocols have been installed > + // previously. Among those, the CPU arch protocol has configured the IDT, > so > + // we can overwrite the IVT used in real mode. > + // > + Int0x10 = (IVT_ENTRY *)(UINTN)Segment0 + 0x10; > + > + // > + // See SVN r14218. > + // > + ASSERT (Int0x10->Segment == 0x0000); > + ASSERT (Int0x10->Offset == 0x0000); > + > + Int0x10->Segment = SegmentC >> 4; > + Int0x10->Offset = (EFI_PHYSICAL_ADDRESS)(UINTN)(VbeModeInfo + 1) - > SegmentC; > + > + DEBUG ((EFI_D_INFO, "%a: VBE shim installed\n", __FUNCTION__)); > + return EFI_SUCCESS; > + > +RestorePam1: > + PciWrite8 (Pam1Address, Pam1); > + > + DEBUG ((EFI_D_ERROR, "%a: VBE shim installation failed: %r\n", > __FUNCTION__, > + Status)); > + return Status; > +} > diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.asm > b/OvmfPkg/QemuVideoDxe/VbeShim.asm > new file mode 100644 > index 0000000..bb3d601 > --- /dev/null > +++ b/OvmfPkg/QemuVideoDxe/VbeShim.asm > @@ -0,0 +1,302 @@ > +;------------------------------------------------------------------------------ > +; @file > +; A minimal Int10h stub that allows the Windows 2008 R2 SP1 UEFI guest's > buggy, > +; default VGA driver to switch to 1024x768x32, on the stdvga and QXL video > +; cards of QEMU. > +; > +; Copyright (C) 2014, Red Hat, Inc. > +; Copyright (c) 2013 - 2014, 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. > +; > +;------------------------------------------------------------------------------ > + > +BITS 16 > +ORG 0 > + > +VbeInfo: > +TIMES 256 nop > + > +VbeModeInfo: > +TIMES 256 nop > + > + > +Handler: > + cmp ax, 0x4f00 > + je GetInfo > + cmp ax, 0x4f01 > + je GetModeInfo > + cmp ax, 0x4f02 > + je SetMode > + cmp ax, 0x4f03 > + je GetMode > + cmp ax, 0x4f10 > + je GetPmCapabilities > + cmp ax, 0x4f15 > + je ReadEdid > + cmp ah, 0x00 > + je SetModeLegacy > + mov si, StrUnkownFunction > + call PrintStringSi > +Hang: > + jmp Hang > + > + > +GetInfo: > + push es > + push di > + push ds > + push si > + push cx > + > + mov si, StrEnterGetInfo > + call PrintStringSi > + > + ; target (es:di) set on input > + push cs > + pop ds > + mov si, VbeInfo > + ; source (ds:si) set now > + > + mov cx, 256 > + cld > + rep movsb > + > + pop cx > + pop si > + pop ds > + pop di > + pop es > + jmp Success > + > + > +GetModeInfo: > + push es > + push di > + push ds > + push si > + push cx > + > + mov si, StrEnterGetModeInfo > + call PrintStringSi > + > + and cx, ~0x4000 ; clear potentially set LFB bit in mode number > + cmp cx, 0x00f1 > + je KnownMode1 > + mov si, StrUnkownMode > + call PrintStringSi > + jmp Hang > +KnownMode1: > + ; target (es:di) set on input > + push cs > + pop ds > + mov si, VbeModeInfo > + ; source (ds:si) set now > + > + mov cx, 256 > + cld > + rep movsb > + > + pop cx > + pop si > + pop ds > + pop di > + pop es > + jmp Success > + > + > +%define ATT_ADDRESS_REGISTER 0x03c0 > +%define VBE_DISPI_IOPORT_INDEX 0x01ce > +%define VBE_DISPI_IOPORT_DATA 0x01d0 > + > +%define VBE_DISPI_INDEX_XRES 0x1 > +%define VBE_DISPI_INDEX_YRES 0x2 > +%define VBE_DISPI_INDEX_BPP 0x3 > +%define VBE_DISPI_INDEX_ENABLE 0x4 > +%define VBE_DISPI_INDEX_BANK 0x5 > +%define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 > +%define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 > +%define VBE_DISPI_INDEX_X_OFFSET 0x8 > +%define VBE_DISPI_INDEX_Y_OFFSET 0x9 > + > +%define VBE_DISPI_ENABLED 0x01 > +%define VBE_DISPI_LFB_ENABLED 0x40 > + > +%macro BochsWrite 2 > + push dx > + push ax > + > + mov dx, VBE_DISPI_IOPORT_INDEX > + mov ax, %1 > + out dx, ax > + > + mov dx, VBE_DISPI_IOPORT_DATA > + mov ax, %2 > + out dx, ax > + > + pop ax > + pop dx > +%endmacro > + > +SetMode: > + push si > + push dx > + push ax > + > + mov si, StrEnterSetMode > + call PrintStringSi > + > + cmp bx, 0x40f1 > + je KnownMode2 > + mov si, StrUnkownMode > + call PrintStringSi > + jmp Hang > +KnownMode2: > + > + ; unblank > + mov dx, ATT_ADDRESS_REGISTER > + mov al, 0x20 > + out dx, al > + > + BochsWrite VBE_DISPI_INDEX_ENABLE, 0 > + BochsWrite VBE_DISPI_INDEX_BANK, 0 > + BochsWrite VBE_DISPI_INDEX_X_OFFSET, 0 > + BochsWrite VBE_DISPI_INDEX_Y_OFFSET, 0 > + BochsWrite VBE_DISPI_INDEX_BPP, 32 > + BochsWrite VBE_DISPI_INDEX_XRES, 1024 > + BochsWrite VBE_DISPI_INDEX_VIRT_WIDTH, 1024 > + BochsWrite VBE_DISPI_INDEX_YRES, 768 > + BochsWrite VBE_DISPI_INDEX_VIRT_HEIGHT, 768 > + BochsWrite VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | > VBE_DISPI_LFB_ENABLED > + > + pop ax > + pop dx > + pop si > + jmp Success > + > + > +GetMode: > + push si > + mov si, StrEnterGetMode > + call PrintStringSi > + mov bx, 0x40f1 > + pop si > + jmp Success > + > + > +GetPmCapabilities: > + push si > + mov si, StrGetPmCapabilities > + call PrintStringSi > + pop si > + jmp Unsupported > + > + > +ReadEdid: > + push si > + mov si, StrReadEdid > + call PrintStringSi > + pop si > + jmp Unsupported > + > + > +SetModeLegacy: > + push si > + mov si, StrEnterSetModeLegacy > + call PrintStringSi > + > + cmp al, 0x03 > + je KnownMode3 > + cmp al, 0x12 > + je KnownMode4 > + mov si, StrUnkownMode > + call PrintStringSi > + jmp Hang > +KnownMode3: > + mov al, 0x30 > + jmp SetModeLegacyDone > +KnownMode4: > + mov al, 0x20 > +SetModeLegacyDone: > + mov si, StrExitSuccess > + call PrintStringSi > + pop si > + iret > + > + > +Success: > + push si > + mov si, StrExitSuccess > + call PrintStringSi > + pop si > + > + mov ax, 0x004f > + iret > + > + > +Unsupported: > + push si > + mov si, StrExitUnsupported > + call PrintStringSi > + pop si > + > + mov ax, 0x014f > + iret > + > + > +PrintStringSi: > + pusha > + push ds ; save original > + push cs > + pop ds > + mov dx, 0x0402 > +PrintStringSiLoop: > + lodsb > + cmp al, 0 > + je PrintStringSiDone > + out dx, al > + jmp PrintStringSiLoop > +PrintStringSiDone: > + pop ds ; restore original > + popa > + ret Can you guard this debug with an ifdef, and disable it by default? > + > + > +StrExitSuccess: > + db 'Exit', 0x0a, 0 > + > +StrExitUnsupported: > + db 'Unsupported', 0x0a, 0 > + > +StrUnkownFunction: > + db 'Unknown Function', 0x0a, 0 > + > +StrEnterGetInfo: > + db 'GetInfo', 0x0a, 0 > + > +StrEnterGetModeInfo: > + db 'GetModeInfo', 0x0a, 0 > + > +StrEnterGetMode: > + db 'GetMode', 0x0a, 0 > + > +StrEnterSetMode: > + db 'SetMode', 0x0a, 0 > + > +StrEnterSetModeLegacy: > + db 'SetModeLegacy', 0x0a, 0 > + > +StrUnkownMode: > + db 'Unkown Mode', 0x0a, 0 > + > +StrGetPmCapabilities: > + db 'GetPmCapabilities', 0x0a, 0 > + > +StrReadEdid: > + db 'ReadEdid', 0x0a, 0 Bonus point for dropping these strings when debug is disabled. :) Seems like a macro could make that happen. > diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.sh b/OvmfPkg/QemuVideoDxe/VbeShim.sh > new file mode 100755 > index 0000000..37e7586 > --- /dev/null > +++ b/OvmfPkg/QemuVideoDxe/VbeShim.sh This script is great. :) > @@ -0,0 +1,82 @@ > +#!/bin/sh > +### > +# @file > +# Shell script to assemble and dump the fake Int10h handler from NASM source > to > +# a C array. > +# > +# Copyright (C) 2014, Red Hat, Inc. > +# Copyright (c) 2013 - 2014, 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. > +# > +### > + > +set -e -u > + > +STEM=$(dirname -- "$0")/$(basename -- "$0" .sh) > + > +# > +# Install exit handler -- remove temporary files. > +# > +exit_handler() > +{ > + rm -f "$STEM".bin "$STEM".disasm "$STEM".offsets "$STEM".insns > "$STEM".bytes > +} > +trap exit_handler EXIT > + > +# > +# Assemble the source file. > +# > +nasm -o "$STEM".bin "$STEM".asm > + > +# > +# Disassemble it, in order to get a binary dump associated with the source. > +# > +ndisasm "$STEM".bin >"$STEM".disasm > + > +# > +# Create three files, each with one column of the disassembly. > +# > +# The first column contains the offsets, and it starts the comment. > +# > +cut -c 1-8 "$STEM".disasm \ > +| sed -e 's,^, /* ,' >"$STEM".offsets > + > +# > +# The second column contains the assembly-language instructions, and it > closes > +# the comment. We first pad it to 30 characters. > +# > +cut -c 29- "$STEM".disasm \ > +| sed -e 's,$, ,' \ > + -e 's,^\(.\{30\}\).*$,\1 */,' >"$STEM".insns > + > +# > +# The third column contains the bytes corresponding to the instruction, > +# represented as C integer constants. First strip trailing whitespace from > the > +# middle column of the input disassembly, then process pairs of nibbles. > +# > +cut -c 11-28 "$STEM".disasm \ > +| sed -e 's, \+$,,' -e 's/\(..\)/ 0x\1,/g' >"$STEM".bytes > + > +# > +# Write the output file, recombining the columns. The output should have CRLF > +# line endings. > +# > +{ > + printf '//\n' > + printf '// THIS IS A GENERATED FILE. DO NOT EDIT.\n' How about: THIS FILE IS GENERATED BY $STEM -Jordan ------------------------------------------------------------------------------ Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce _______________________________________________ edk2-devel mailing list edk2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/edk2-devel