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:
&#149; 3 signs your SCM is hindering your productivity
&#149; Requirements for releasing software faster
&#149; 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

Reply via email to