]> git.proxmox.com Git - mirror_edk2.git/commitdiff
1, Port BiosVideoThunkDxe driver from edk to edk2;
authorklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 28 Feb 2009 17:28:44 +0000 (17:28 +0000)
committerklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 28 Feb 2009 17:28:44 +0000 (17:28 +0000)
2, The LegacyBiosThunk driver has been merged to BiosVideoThunkDxe driver, because only BiosVideo use legacy thunk now.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7733 6f19259b-4bc3-4df7-8a09-765794883524

DuetPkg/BiosVideoThunkDxe/BiosVideo.c [new file with mode: 0644]
DuetPkg/BiosVideoThunkDxe/BiosVideo.h [new file with mode: 0644]
DuetPkg/BiosVideoThunkDxe/BiosVideo.inf [new file with mode: 0644]
DuetPkg/BiosVideoThunkDxe/ComponentName.c [new file with mode: 0644]
DuetPkg/BiosVideoThunkDxe/VesaBiosExtensions.h [new file with mode: 0644]
DuetPkg/DuetPkg.dsc
DuetPkg/DuetPkg.fdf

diff --git a/DuetPkg/BiosVideoThunkDxe/BiosVideo.c b/DuetPkg/BiosVideoThunkDxe/BiosVideo.c
new file mode 100644 (file)
index 0000000..c8b090c
--- /dev/null
@@ -0,0 +1,2644 @@
+/*++\r
+\r
+Copyright (c) 2006 - 2008, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  BiosVideo.c\r
+    \r
+Abstract:\r
+\r
+  ConsoleOut Routines that speak VGA.\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "BiosVideo.h"\r
+\r
+\r
+//\r
+// EFI Driver Binding Protocol Instance\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding = {\r
+  BiosVideoDriverBindingSupported,\r
+  BiosVideoDriverBindingStart,\r
+  BiosVideoDriverBindingStop,\r
+  0x3,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+//\r
+// Global lookup tables for VGA graphics modes\r
+//\r
+UINT8                       mVgaLeftMaskTable[]   = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };\r
+\r
+UINT8                       mVgaRightMaskTable[]  = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };\r
+\r
+UINT8                       mVgaBitMaskTable[]    = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };\r
+\r
+THUNK_CONTEXT               mThunkContext;\r
+\r
+EFI_LEGACY_8259_PROTOCOL    *mLegacy8259 = NULL;\r
+\r
+#define EFI_CPU_EFLAGS_IF 0x200\r
+\r
+EFI_UGA_PIXEL               mVgaColorToUgaColor[] = {\r
+  {\r
+    0x00,\r
+    0x00,\r
+    0x00,\r
+    0x00\r
+  },\r
+  {\r
+    0x98,\r
+    0x00,\r
+    0x00,\r
+    0x00\r
+  },\r
+  {\r
+    0x00,\r
+    0x98,\r
+    0x00,\r
+    0x00\r
+  },\r
+  {\r
+    0x98,\r
+    0x98,\r
+    0x00,\r
+    0x00\r
+  },\r
+  {\r
+    0x00,\r
+    0x00,\r
+    0x98,\r
+    0x00\r
+  },\r
+  {\r
+    0x98,\r
+    0x00,\r
+    0x98,\r
+    0x00\r
+  },\r
+  {\r
+    0x00,\r
+    0x98,\r
+    0x98,\r
+    0x00\r
+  },\r
+  {\r
+    0x98,\r
+    0x98,\r
+    0x98,\r
+    0x00\r
+  },\r
+  {\r
+    0x10,\r
+    0x10,\r
+    0x10,\r
+    0x00\r
+  },\r
+  {\r
+    0xff,\r
+    0x10,\r
+    0x10,\r
+    0x00\r
+  },\r
+  {\r
+    0x10,\r
+    0xff,\r
+    0x10,\r
+    0x00\r
+  },\r
+  {\r
+    0xff,\r
+    0xff,\r
+    0x10,\r
+    0x00\r
+  },\r
+  {\r
+    0x10,\r
+    0x10,\r
+    0xff,\r
+    0x00\r
+  },\r
+  {\r
+    0xf0,\r
+    0x10,\r
+    0xff,\r
+    0x00\r
+  },\r
+  {\r
+    0x10,\r
+    0xff,\r
+    0xff,\r
+    0x00\r
+  },\r
+  {\r
+    0xff,\r
+    0xff,\r
+    0xff,\r
+    0x00\r
+  }\r
+};\r
+\r
+VOID\r
+InitializeBiosIntCaller (\r
+  VOID\r
+  );\r
+  \r
+VOID\r
+InitializeInterruptRedirection (\r
+  VOID\r
+  );\r
+    \r
+BOOLEAN\r
+EFIAPI\r
+LegacyBiosInt86 (\r
+  IN  UINT8                           BiosInt,\r
+  IN  EFI_IA32_REGISTER_SET           *Regs\r
+  );\r
+    \r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoDriverEntryPoint (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+/*++\r
+  \r
+  Routine Description:\r
+  \r
+    Driver Entry Point.\r
+        \r
+  Arguments:\r
+  \r
+  ImageHandle - Handle of driver image.\r
+  SystemTable - Pointer to system table.\r
+  \r
+  Returns:\r
+  \r
+    EFI_STATUS\r
+    \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
+            ImageHandle,\r
+            SystemTable,\r
+            &gBiosVideoDriverBinding,\r
+            ImageHandle,\r
+            &gBiosVideoComponentName,\r
+            &gBiosVideoComponentName2\r
+            );\r
+\r
+  return Status;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+BiosVideoExitBootServices (\r
+  EFI_EVENT  Event,\r
+  VOID       *Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Callback function for exit boot service event\r
+\r
+Arguments:\r
+\r
+  Event   - EFI_EVENT structure\r
+  Context - Event context\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+/*\r
+  BIOS_VIDEO_DEV        *BiosVideoPrivate;\r
+  EFI_IA32_REGISTER_SET Regs;\r
+\r
+  //\r
+  // Get our context\r
+  //\r
+  BiosVideoPrivate = (BIOS_VIDEO_DEV *) Context;\r
+\r
+  //\r
+  // Set the 80x25 Text VGA Mode\r
+  //\r
+  Regs.H.AH = 0x00;\r
+  Regs.H.AL = 0x83;\r
+  BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+\r
+  Regs.H.AH = 0x11;\r
+  Regs.H.AL = 0x14;\r
+  Regs.H.BL = 0;\r
+  BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+*/\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+/*++\r
+  \r
+  Routine Description:\r
+\r
+    Supported.\r
+    \r
+  Arguments:\r
+\r
+  This - Pointer to driver binding protocol\r
+  Controller - Controller handle to connect\r
+  RemainingDevicePath - A pointer to the remaining portion of a device path\r
+    \r
+    \r
+  Returns:\r
+\r
+  EFI_STATUS - EFI_SUCCESS:This controller can be managed by this driver,\r
+               Otherwise, this controller cannot be managed by this driver\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_LEGACY_8259_PROTOCOL        *Legacy8259;\r
+  EFI_PCI_IO_PROTOCOL             *PciIo;\r
+  \r
+  DEBUG ((EFI_D_INFO, "BiosVideoDriverBindingSupported\n"));\r
+\r
+  //\r
+  // See if the Legacy BIOS Protocol is available\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &Legacy8259);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Open the IO Abstraction(s) needed to perform the supported test\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  (VOID **) &PciIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_INFO, "BiosVideoDriverBindingSupported: Fail to open PciIo protocol!\n"));\r
+    return Status;\r
+  }\r
+  \r
+  if (!BiosVideoIsVga (PciIo)) {\r
+    DEBUG ((EFI_D_INFO, "BiosVideoDriverBindingSupported: Is not VGA!\n"));\r
+    Status = EFI_UNSUPPORTED;\r
+  }\r
+\r
+  gBS->CloseProtocol (\r
+        Controller,\r
+        &gEfiPciIoProtocolGuid,\r
+        This->DriverBindingHandle,\r
+        Controller\r
+        );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+/*++\r
+  \r
+  Routine Description:\r
+\r
+    Install UGA Draw Protocol onto VGA device handles\r
+  \r
+  Arguments:\r
+\r
+  This - Pointer to driver binding protocol\r
+  Controller - Controller handle to connect\r
+  RemainingDevicePath - A pointer to the remaining portion of a device path\r
+    \r
+  Returns:\r
+\r
+    EFI_STATUS\r
+    \r
+--*/\r
+{\r
+  EFI_STATUS      Status;\r
+  BIOS_VIDEO_DEV  *BiosVideoPrivate;\r
+\r
+  DEBUG ((EFI_D_INFO, "BiosVideoDriverBindingStart\n"));\r
+  //\r
+  // Initialize local variables\r
+  //\r
+  BiosVideoPrivate = NULL;\r
+\r
+  //\r
+  // Allocate the private device structure\r
+  //\r
+  Status = gBS->AllocatePool (\r
+                  EfiBootServicesData,\r
+                  sizeof (BIOS_VIDEO_DEV),\r
+                  &BiosVideoPrivate\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  ZeroMem (BiosVideoPrivate, sizeof (BIOS_VIDEO_DEV));\r
+\r
+  //\r
+  // See if the Legacy BIOS Protocol is available\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &mLegacy8259);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+  \r
+  //\r
+  // Prepare for status code\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  Controller,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  &BiosVideoPrivate->DevicePath\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+  //\r
+  // Open the IO Abstraction(s) needed\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  (VOID **) &(BiosVideoPrivate->PciIo),\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+  \r
+  DEBUG ((EFI_D_INFO, "InitializeBiosIntCaller\n"));\r
+  InitializeBiosIntCaller();\r
+  InitializeInterruptRedirection();\r
+  DEBUG ((EFI_D_INFO, "InitializeBiosIntCaller Finished!\n"));\r
+  \r
+  if (!BiosVideoIsVga (BiosVideoPrivate->PciIo)) {\r
+    DEBUG ((EFI_D_INFO, "BiosVideoDriverBindingStart: not VGA\n"));\r
+    Status = EFI_UNSUPPORTED;\r
+    goto Done;\r
+  }\r
+  \r
+  BiosVideoPrivate->VgaCompatible = TRUE; \r
+  //\r
+  // Initialize the private device structure\r
+  //\r
+  BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE;\r
+  BiosVideoPrivate->Handle    = Controller;\r
+\r
+  /**\r
+  Status = gBS->CreateEvent (\r
+                  EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,\r
+                  EFI_TPL_NOTIFY,\r
+                  BiosVideoExitBootServices,\r
+                  BiosVideoPrivate,\r
+                  &BiosVideoPrivate->ExitBootServicesEvent\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+  **/\r
+  \r
+  //\r
+  // Fill in UGA Draw specific mode structures\r
+  //\r
+  BiosVideoPrivate->HardwareNeedsStarting = TRUE;\r
+  BiosVideoPrivate->CurrentMode           = 0;\r
+  BiosVideoPrivate->MaxMode               = 0;\r
+  BiosVideoPrivate->ModeData              = NULL;\r
+  BiosVideoPrivate->LineBuffer            = NULL;\r
+  BiosVideoPrivate->VgaFrameBuffer        = NULL;\r
+  BiosVideoPrivate->VbeFrameBuffer        = NULL;\r
+\r
+  //\r
+  // Fill in the VGA Mini Port Protocol fields\r
+  //\r
+  BiosVideoPrivate->VgaMiniPort.SetMode                   = BiosVideoVgaMiniPortSetMode;\r
+  BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset           = 0xb8000;\r
+  BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4;\r
+  BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset    = 0x3d5;\r
+  BiosVideoPrivate->VgaMiniPort.VgaMemoryBar              = EFI_PCI_IO_PASS_THROUGH_BAR;\r
+  BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar    = EFI_PCI_IO_PASS_THROUGH_BAR;\r
+  BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar       = EFI_PCI_IO_PASS_THROUGH_BAR;\r
+\r
+  //\r
+  // Assume that UGA Draw will be produced until proven otherwise\r
+  //\r
+  BiosVideoPrivate->ProduceUgaDraw = TRUE;\r
+\r
+  //\r
+  // Check for VESA BIOS Extensions for modes that are compatible with UGA Draw\r
+  //\r
+  //CpuDeadLoop();\r
+  DEBUG ((EFI_D_INFO, "BiosVideoDriverBindingStart: Before check VBE!\n"));\r
+  Status = BiosVideoCheckForVbe (BiosVideoPrivate);\r
+  DEBUG ((EFI_D_INFO, "BiosVideoDriverBindingStart: check VBE status=%r!\n", Status));\r
+  \r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_INFO, "BiosVideoDriverBindingStart: Fail to check VBE!\n"));\r
+    //\r
+    // The VESA BIOS Extensions are not compatible with UGA Draw, so check for support\r
+    // for the standard 640x480 16 color VGA mode\r
+    //\r
+    if (BiosVideoPrivate->VgaCompatible) {\r
+      Status = BiosVideoCheckForVga (BiosVideoPrivate);\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do\r
+      // not produce the UGA Draw protocol.  Instead, produce the VGA MiniPort Protocol.\r
+      //\r
+      BiosVideoPrivate->ProduceUgaDraw = FALSE;\r
+\r
+      //\r
+      // INT services are available, so on the 80x25 and 80x50 text mode are supported\r
+      //\r
+      BiosVideoPrivate->VgaMiniPort.MaxMode = 2;\r
+    }\r
+  }\r
+\r
+  if (BiosVideoPrivate->ProduceUgaDraw) {\r
+    DEBUG ((EFI_D_INFO, "BiosVideoDriverBindingStart: Produce Uga Draw!\n"));\r
+    //\r
+    // Install UGA Draw Protocol\r
+    //\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    &Controller,\r
+                    &gEfiUgaDrawProtocolGuid,\r
+                    &BiosVideoPrivate->UgaDraw,\r
+                    NULL\r
+                    );\r
+  } else {\r
+    //\r
+    // Install VGA Mini Port Protocol\r
+    //\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    &Controller,\r
+                    &gEfiVgaMiniPortProtocolGuid,\r
+                    &BiosVideoPrivate->VgaMiniPort,\r
+                    NULL\r
+                    );\r
+  }\r
+\r
+Done:\r
+  if (EFI_ERROR (Status)) {\r
+    if (BiosVideoPrivate != NULL) {\r
+      //\r
+      // Free mode data\r
+      //\r
+      if (BiosVideoPrivate->ModeData != NULL) {\r
+        gBS->FreePool (BiosVideoPrivate->ModeData);\r
+      }\r
+      //\r
+      // Free memory allocated below 1MB\r
+      //\r
+      if (BiosVideoPrivate->PagesBelow1MB != 0) {\r
+        gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->NumberOfPagesBelow1MB);\r
+      }\r
+\r
+      if (BiosVideoPrivate->PciIo != NULL) {\r
+        //\r
+        // Release PCI I/O and UGA Draw Protocols on the controller handle.\r
+        //\r
+        gBS->CloseProtocol (\r
+              Controller,\r
+              &gEfiPciIoProtocolGuid,\r
+              This->DriverBindingHandle,\r
+              Controller\r
+              );\r
+      }\r
+      //\r
+      // Close the ExitBootServices event\r
+      //\r
+      if (BiosVideoPrivate->ExitBootServicesEvent != NULL) {\r
+        gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent);\r
+      }\r
+      //\r
+      // Free private data structure\r
+      //\r
+      gBS->FreePool (BiosVideoPrivate);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN  EFI_HANDLE                      Controller,\r
+  IN  UINTN                           NumberOfChildren,\r
+  IN  EFI_HANDLE                      *ChildHandleBuffer\r
+  )\r
+/*++\r
+  \r
+  Routine Description:\r
+\r
+    Stop.\r
+  \r
+  Arguments:\r
+\r
+  This - Pointer to driver binding protocol\r
+  Controller - Controller handle to connect\r
+  NumberOfChilren - Number of children handle created by this driver\r
+  ChildHandleBuffer - Buffer containing child handle created\r
+  \r
+  Returns:\r
+\r
+  EFI_SUCCESS - Driver disconnected successfully from controller\r
+  EFI_UNSUPPORTED - Cannot find BIOS_VIDEO_DEV structure\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_UGA_DRAW_PROTOCOL       *Uga;\r
+  EFI_VGA_MINI_PORT_PROTOCOL  *VgaMiniPort;\r
+  BIOS_VIDEO_DEV              *BiosVideoPrivate;\r
+  EFI_IA32_REGISTER_SET       Regs;\r
+\r
+  BiosVideoPrivate = NULL;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiUgaDrawProtocolGuid,\r
+                  (VOID **) &Uga,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_UGA_DRAW_THIS (Uga);\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiVgaMiniPortProtocolGuid,\r
+                  (VOID **) &VgaMiniPort,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort);\r
+  }\r
+\r
+  if (BiosVideoPrivate == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (BiosVideoPrivate->ProduceUgaDraw) {\r
+    Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                    Controller,\r
+                    &gEfiUgaDrawProtocolGuid,\r
+                    &BiosVideoPrivate->UgaDraw,\r
+                    NULL\r
+                    );\r
+  } else {\r
+    Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                    Controller,\r
+                    &gEfiVgaMiniPortProtocolGuid,\r
+                    &BiosVideoPrivate->VgaMiniPort,\r
+                    NULL\r
+                    );\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  gBS->SetMem (&Regs, sizeof (Regs), 0);  \r
+  \r
+  //\r
+  // Set the 80x25 Text VGA Mode\r
+  //\r
+  Regs.H.AH = 0x00;\r
+  Regs.H.AL = 0x03;\r
+  LegacyBiosInt86 (0x10, &Regs);\r
+\r
+  Regs.H.AH = 0x11;\r
+  Regs.H.AL = 0x14;\r
+  Regs.H.BL = 0;\r
+  LegacyBiosInt86 (0x10, &Regs);\r
+\r
+  //\r
+  // Do not disable IO/memory decode since that would prevent legacy ROM from working\r
+  //\r
+  //\r
+  // Free VGA Frame Buffer\r
+  //\r
+  if (BiosVideoPrivate->VgaFrameBuffer != NULL) {\r
+    gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
+  }\r
+  //\r
+  // Free VBE Frame Buffer\r
+  //\r
+  if (BiosVideoPrivate->VbeFrameBuffer != NULL) {\r
+    gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
+  }\r
+  //\r
+  // Free line buffer\r
+  //\r
+  if (BiosVideoPrivate->LineBuffer != NULL) {\r
+    gBS->FreePool (BiosVideoPrivate->LineBuffer);\r
+  }\r
+  //\r
+  // Free mode data\r
+  //\r
+  if (BiosVideoPrivate->ModeData != NULL) {\r
+    gBS->FreePool (BiosVideoPrivate->ModeData);\r
+  }\r
+  //\r
+  // Free memory allocated below 1MB\r
+  //\r
+  if (BiosVideoPrivate->PagesBelow1MB != 0) {\r
+    gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->NumberOfPagesBelow1MB);\r
+  }\r
+\r
+  if (BiosVideoPrivate->VbeSaveRestorePages != 0) {\r
+    gBS->FreePages (BiosVideoPrivate->VbeSaveRestoreBuffer, BiosVideoPrivate->VbeSaveRestorePages);\r
+  }\r
+  //\r
+  // Release PCI I/O and UGA Draw Protocols on the controller handle.\r
+  //\r
+  gBS->CloseProtocol (\r
+        Controller,\r
+        &gEfiPciIoProtocolGuid,\r
+        This->DriverBindingHandle,\r
+        Controller\r
+        );\r
+\r
+  //\r
+  // Close the ExitBootServices event\r
+  //\r
+  gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent);\r
+\r
+  //\r
+  // Free private data structure\r
+  //\r
+  gBS->FreePool (BiosVideoPrivate);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+#define PCI_DEVICE_ENABLED  (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE)\r
+\r
+\r
+BOOLEAN\r
+BiosVideoIsVga (\r
+  IN  EFI_PCI_IO_PROTOCOL       *PciIo\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  BOOLEAN       VgaCompatible;\r
+  PCI_TYPE00    Pci;\r
+\r
+  VgaCompatible = FALSE;\r
+\r
+  //\r
+  // Read the PCI Configuration Header\r
+  //\r
+  Status = PciIo->Pci.Read (\r
+                        PciIo,\r
+                        EfiPciIoWidthUint32,\r
+                        0,\r
+                        sizeof (Pci) / sizeof (UINT32),\r
+                        &Pci\r
+                        );\r
+  if (EFI_ERROR (Status)) {\r
+    return VgaCompatible;\r
+  }\r
+\r
+  //\r
+  // See if this is a VGA compatible controller or not\r
+  //\r
+  if ((Pci.Hdr.Command & PCI_DEVICE_ENABLED) == PCI_DEVICE_ENABLED) {\r
+    if (Pci.Hdr.ClassCode[2] == PCI_CLASS_OLD && Pci.Hdr.ClassCode[1] == PCI_CLASS_OLD_VGA) {\r
+      //\r
+      // Base Class 0x00 Sub-Class 0x01 - Backward compatible VGA device\r
+      //\r
+      VgaCompatible = TRUE;\r
+    }\r
+\r
+    if (Pci.Hdr.ClassCode[2] == PCI_CLASS_DISPLAY && Pci.Hdr.ClassCode[1] == PCI_CLASS_DISPLAY_VGA && Pci.Hdr.ClassCode[0] == 0x00) {\r
+      //\r
+      // Base Class 3 Sub-Class 0 Programming interface 0 - VGA compatible Display controller\r
+      //\r
+      VgaCompatible = TRUE;\r
+    }\r
+  }\r
+\r
+  return VgaCompatible;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+BiosVideoCheckForVbe (\r
+  IN OUT BIOS_VIDEO_DEV  *BiosVideoPrivate  \r
+  )\r
+/*++\r
+  \r
+  Routine Description:\r
+\r
+  Check for VBE device   \r
+  \r
+  Arguments:\r
+  \r
+  BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure\r
+  \r
+  Returns:\r
+  \r
+  EFI_SUCCESS - VBE device found\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_IA32_REGISTER_SET Regs;\r
+  UINT16                *ModeNumberPtr;\r
+  BOOLEAN               ModeFound;\r
+  BIOS_VIDEO_MODE_DATA  *ModeBuffer;\r
+  UINTN                 Index;\r
+\r
+  //\r
+  // Allocate buffer under 1MB for VBE data structures\r
+  //\r
+  BiosVideoPrivate->NumberOfPagesBelow1MB = EFI_SIZE_TO_PAGES (\r
+                                              sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK) + sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK) +\r
+                                              sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK)\r
+                                              );\r
+\r
+  BiosVideoPrivate->PagesBelow1MB = 0x00100000 - 1;\r
+\r
+  Status = gBS->AllocatePages (\r
+                  AllocateMaxAddress,\r
+                  EfiBootServicesData,\r
+                  BiosVideoPrivate->NumberOfPagesBelow1MB,\r
+                  &BiosVideoPrivate->PagesBelow1MB\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Fill in the UGA Draw Protocol\r
+  //\r
+  BiosVideoPrivate->UgaDraw.GetMode = BiosVideoUgaDrawGetMode;\r
+  BiosVideoPrivate->UgaDraw.SetMode = BiosVideoUgaDrawSetMode;\r
+  BiosVideoPrivate->UgaDraw.Blt     = BiosVideoUgaDrawVbeBlt;\r
+\r
+  //\r
+  // Fill in the VBE related data structures\r
+  //\r
+  BiosVideoPrivate->VbeInformationBlock = (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB);\r
+  BiosVideoPrivate->VbeModeInformationBlock = (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1);\r
+  BiosVideoPrivate->VbeCrtcInformationBlock = (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1);\r
+  BiosVideoPrivate->VbeSaveRestorePages   = 0;\r
+  BiosVideoPrivate->VbeSaveRestoreBuffer  = 0;\r
+\r
+  //\r
+  // Test to see if the Video Adapter is compliant with VBE 3.0\r
+  //\r
+  gBS->SetMem (&Regs, sizeof (Regs), 0);\r
+  Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION;\r
+  gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0);\r
+  BiosVideoPrivate->VbeInformationBlock->VESASignature  = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE;\r
+  Regs.X.ES = EFI_SEGMENT ((UINTN)BiosVideoPrivate->VbeInformationBlock);\r
+  Regs.X.DI = EFI_OFFSET ((UINTN)BiosVideoPrivate->VbeInformationBlock);\r
+\r
+  LegacyBiosInt86 (0x10, &Regs);\r
+\r
+  Status = EFI_DEVICE_ERROR;\r
+\r
+  //\r
+  // See if the VESA call succeeded\r
+  //\r
+  if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Check for 'VESA' signature\r
+  //\r
+  if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Check to see if this is VBE 2.0 or higher\r
+  //\r
+  if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Walk through the mode list to see if there is at least one mode the is compatible with the UGA_DRAW protocol\r
+  //\r
+  ModeNumberPtr = (UINT16 *)\r
+    (\r
+      (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) |\r
+        ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff)\r
+    );\r
+  for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; ModeNumberPtr++) {\r
+    //\r
+    // Make sure this is a mode number defined by the VESA VBE specification.  If it isn'tm then skip this mode number.\r
+    //\r
+    if ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {\r
+      continue;\r
+    }\r
+    //\r
+    // Get the information about the mode\r
+    //\r
+    gBS->SetMem (&Regs, sizeof (Regs), 0);\r
+    Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;\r
+    Regs.X.CX = *ModeNumberPtr;\r
+    gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);\r
+    Regs.X.ES = EFI_SEGMENT ((UINTN)BiosVideoPrivate->VbeModeInformationBlock);\r
+    Regs.X.DI = EFI_OFFSET ((UINTN)BiosVideoPrivate->VbeModeInformationBlock);\r
+\r
+    LegacyBiosInt86 (0x10, &Regs);\r
+\r
+    //\r
+    // See if the call succeeded.  If it didn't, then try the next mode.\r
+    //\r
+    if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
+      continue;\r
+    }\r
+    //\r
+    // See if the mode supports color.  If it doesn't then try the next mode.\r
+    //\r
+    if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) {\r
+      continue;\r
+    }\r
+    //\r
+    // See if the mode supports graphics.  If it doesn't then try the next mode.\r
+    //\r
+    if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) {\r
+      continue;\r
+    }\r
+    //\r
+    // See if the mode supports a linear frame buffer.  If it doesn't then try the next mode.\r
+    //\r
+    if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) {\r
+      continue;\r
+    }\r
+    //\r
+    // See if the mode supports 32 bit color.  If it doesn't then try the next mode.\r
+    // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the\r
+    // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel\r
+    //\r
+    if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) {\r
+      continue;\r
+    }\r
+\r
+    if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) {\r
+      continue;\r
+    }\r
+\r
+    if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) {\r
+      continue;\r
+    }\r
+    //\r
+    // See if the physical base pointer for the linear mode is valid.  If it isn't then try the next mode.\r
+    //\r
+    if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) {\r
+      continue;\r
+    }\r
+    //\r
+    // See if the resolution is 1024x768, 800x600, or 640x480\r
+    //\r
+    ModeFound = FALSE;\r
+    if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 1024 &&\r
+        BiosVideoPrivate->VbeModeInformationBlock->YResolution == 768\r
+        ) {\r
+      ModeFound = TRUE;\r
+    }\r
+\r
+    if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 800 &&\r
+        BiosVideoPrivate->VbeModeInformationBlock->YResolution == 600\r
+        ) {\r
+      ModeFound = TRUE;\r
+    }\r
+\r
+    if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 640 &&\r
+        BiosVideoPrivate->VbeModeInformationBlock->YResolution == 480\r
+        ) {\r
+      ModeFound = TRUE;\r
+    }\r
+\r
+    if (!ModeFound) {\r
+      continue;\r
+    }\r
+    //\r
+    // Add mode to the list of available modes\r
+    //\r
+    BiosVideoPrivate->MaxMode++;\r
+    Status = gBS->AllocatePool (\r
+                    EfiBootServicesData,\r
+                    BiosVideoPrivate->MaxMode * sizeof (BIOS_VIDEO_MODE_DATA),\r
+                    (VOID **) &ModeBuffer\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    if (BiosVideoPrivate->MaxMode > 1) {\r
+      gBS->CopyMem (\r
+            ModeBuffer,\r
+            BiosVideoPrivate->ModeData,\r
+            (BiosVideoPrivate->MaxMode - 1) * sizeof (BIOS_VIDEO_MODE_DATA)\r
+            );\r
+    }\r
+\r
+    if (BiosVideoPrivate->ModeData != NULL) {\r
+      gBS->FreePool (BiosVideoPrivate->ModeData);\r
+    }\r
+\r
+    ModeBuffer[BiosVideoPrivate->MaxMode - 1].VbeModeNumber = *ModeNumberPtr;\r
+    if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) {\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine;\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition;\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1);\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition;\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1);\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition;\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1);\r
+\r
+    } else {\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine;\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition;\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1);\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition;\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1);\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition;\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1);\r
+\r
+    }\r
+\r
+    ModeBuffer[BiosVideoPrivate->MaxMode - 1].LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;\r
+    ModeBuffer[BiosVideoPrivate->MaxMode - 1].HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
+    ModeBuffer[BiosVideoPrivate->MaxMode - 1].VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
+\r
+    if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel >= 24) {\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].ColorDepth = 32;\r
+    } else {\r
+      ModeBuffer[BiosVideoPrivate->MaxMode - 1].ColorDepth = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;\r
+    }\r
+\r
+    ModeBuffer[BiosVideoPrivate->MaxMode - 1].BitsPerPixel  = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;\r
+\r
+    ModeBuffer[BiosVideoPrivate->MaxMode - 1].RefreshRate   = 60;\r
+\r
+    BiosVideoPrivate->ModeData = ModeBuffer;\r
+  }\r
+  //\r
+  // Check to see if we found any modes that are compatible with UGA DRAW\r
+  //\r
+  if (BiosVideoPrivate->MaxMode == 0) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto Done;\r
+  }\r
+  //\r
+  // Find the best mode to initialize\r
+  //\r
+  Status = BiosVideoUgaDrawSetMode (&BiosVideoPrivate->UgaDraw, 1024, 768, 32, 60);\r
+  //Status = BiosVideoUgaDrawSetMode (&BiosVideoPrivate->UgaDraw, 800, 600, 32, 60);\r
+  if (EFI_ERROR (Status)) {\r
+    Status = BiosVideoUgaDrawSetMode (&BiosVideoPrivate->UgaDraw, 800, 600, 32, 60);\r
+    //Status = BiosVideoUgaDrawSetMode (&BiosVideoPrivate->UgaDraw, 1024, 768, 32, 60);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = BiosVideoUgaDrawSetMode (&BiosVideoPrivate->UgaDraw, 640, 480, 32, 60);\r
+      for (Index = 0; EFI_ERROR (Status) && Index < BiosVideoPrivate->MaxMode; Index++) {\r
+        Status = BiosVideoUgaDrawSetMode (\r
+                  &BiosVideoPrivate->UgaDraw,\r
+                  BiosVideoPrivate->ModeData[Index].HorizontalResolution,\r
+                  BiosVideoPrivate->ModeData[Index].VerticalResolution,\r
+                  BiosVideoPrivate->ModeData[Index].ColorDepth,\r
+                  BiosVideoPrivate->ModeData[Index].RefreshRate\r
+                  );\r
+      }\r
+    }\r
+  }\r
+\r
+Done:\r
+  //\r
+  // If there was an error, then free the mode structure\r
+  //\r
+  if (EFI_ERROR (Status)) {\r
+    if (BiosVideoPrivate->ModeData != NULL) {\r
+      gBS->FreePool (BiosVideoPrivate->ModeData);\r
+      BiosVideoPrivate->ModeData  = NULL;\r
+      BiosVideoPrivate->MaxMode   = 0;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+BiosVideoCheckForVga (\r
+  IN OUT BIOS_VIDEO_DEV  *BiosVideoPrivate  \r
+  )\r
+/*++\r
+  \r
+  Routine Description:\r
+\r
+    Check for VGA device\r
+  \r
+  Arguments:\r
+  \r
+    BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure\r
+  \r
+  Returns:\r
+  \r
+    EFI_SUCCESS - Standard VGA device found\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS            Status;\r
+  BIOS_VIDEO_MODE_DATA  *ModeBuffer;\r
+\r
+  //\r
+  // Fill in the UGA Draw Protocol\r
+  //\r
+  BiosVideoPrivate->UgaDraw.GetMode = BiosVideoUgaDrawGetMode;\r
+  BiosVideoPrivate->UgaDraw.SetMode = BiosVideoUgaDrawSetMode;\r
+  BiosVideoPrivate->UgaDraw.Blt     = BiosVideoUgaDrawVgaBlt;\r
+\r
+  //\r
+  // Add mode to the list of available modes\r
+  //\r
+  BiosVideoPrivate->MaxMode++;\r
+  Status = gBS->AllocatePool (\r
+                  EfiBootServicesData,\r
+                  BiosVideoPrivate->MaxMode * sizeof (BIOS_VIDEO_MODE_DATA),\r
+                  (VOID **) &ModeBuffer\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (BiosVideoPrivate->MaxMode > 1) {\r
+    gBS->CopyMem (\r
+          ModeBuffer,\r
+          BiosVideoPrivate->ModeData,\r
+          (BiosVideoPrivate->MaxMode - 1) * sizeof (BIOS_VIDEO_MODE_DATA)\r
+          );\r
+  }\r
+\r
+  if (BiosVideoPrivate->ModeData != NULL) {\r
+    gBS->FreePool (BiosVideoPrivate->ModeData);\r
+  }\r
+\r
+  ModeBuffer[BiosVideoPrivate->MaxMode - 1].VbeModeNumber         = 0x0012;\r
+  ModeBuffer[BiosVideoPrivate->MaxMode - 1].BytesPerScanLine      = 640;\r
+  ModeBuffer[BiosVideoPrivate->MaxMode - 1].LinearFrameBuffer     = (VOID *) (UINTN)(0xa0000);\r
+  ModeBuffer[BiosVideoPrivate->MaxMode - 1].HorizontalResolution  = 640;\r
+  ModeBuffer[BiosVideoPrivate->MaxMode - 1].VerticalResolution    = 480;\r
+  ModeBuffer[BiosVideoPrivate->MaxMode - 1].ColorDepth            = 32;\r
+  ModeBuffer[BiosVideoPrivate->MaxMode - 1].RefreshRate           = 60;\r
+\r
+  BiosVideoPrivate->ModeData = ModeBuffer;\r
+\r
+  //\r
+  // Test to see if the Video Adapter support the 640x480 16 color mode\r
+  //\r
+  Status = BiosVideoUgaDrawSetMode (&BiosVideoPrivate->UgaDraw, 640, 480, 32, 60);\r
+\r
+  //\r
+  // If there was an error, then free the mode structure\r
+  //\r
+  if (EFI_ERROR (Status)) {\r
+    BiosVideoPrivate->MaxMode = 0;\r
+    if (BiosVideoPrivate->ModeData != NULL) {\r
+      gBS->FreePool (BiosVideoPrivate->ModeData);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+//\r
+// UGA Protocol Member Functions for VESA BIOS Extensions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoUgaDrawGetMode (\r
+  IN  EFI_UGA_DRAW_PROTOCOL  *This,\r
+  OUT UINT32                 *HorizontalResolution,\r
+  OUT UINT32                 *VerticalResolution,\r
+  OUT UINT32                 *ColorDepth,\r
+  OUT UINT32                 *RefreshRate\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  UGA protocol interface to get video mode\r
+\r
+Arguments:\r
+\r
+  This                  - Pointer to UGA draw protocol instance\r
+  HorizontalResolution  - Horizontal Resolution, in pixels\r
+  VerticalResolution    - Vertical Resolution, in pixels\r
+  ColorDepth            - Bit number used to represent color value of a pixel \r
+  RefreshRate           - Refresh rate, in Hertz\r
+\r
+Returns:\r
+\r
+  EFI_DEVICE_ERROR - Hardware need starting\r
+  EFI_INVALID_PARAMETER - Invalid parameter passed in\r
+  EFI_SUCCESS - Video mode query successfully\r
+\r
+--*/\r
+{\r
+  BIOS_VIDEO_DEV  *BiosVideoPrivate;\r
+\r
+  BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_UGA_DRAW_THIS (This);\r
+\r
+  if (BiosVideoPrivate->HardwareNeedsStarting) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  if (HorizontalResolution == NULL || VerticalResolution == NULL || ColorDepth == NULL || RefreshRate == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *HorizontalResolution = BiosVideoPrivate->ModeData[BiosVideoPrivate->CurrentMode].HorizontalResolution;\r
+  *VerticalResolution   = BiosVideoPrivate->ModeData[BiosVideoPrivate->CurrentMode].VerticalResolution;\r
+  *ColorDepth           = BiosVideoPrivate->ModeData[BiosVideoPrivate->CurrentMode].ColorDepth;\r
+  *RefreshRate          = BiosVideoPrivate->ModeData[BiosVideoPrivate->CurrentMode].RefreshRate;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoUgaDrawSetMode (\r
+  IN  EFI_UGA_DRAW_PROTOCOL  *This,\r
+  IN  UINT32                 HorizontalResolution,\r
+  IN  UINT32                 VerticalResolution,\r
+  IN  UINT32                 ColorDepth,\r
+  IN  UINT32                 RefreshRate\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  UGA draw protocol interface to set video mode\r
+\r
+Arguments:\r
+\r
+  This                  - Pointer to UGA draw protocol instance\r
+  HorizontalResolution  - Horizontal Resolution, in pixels\r
+  VerticalResolution    - Vertical Resolution, in pixels\r
+  ColorDepth            - Bit number used to represent color value of a pixel \r
+  RefreshRate           - Refresh rate, in Hertz\r
+\r
+Returns:\r
+\r
+  EFI_DEVICE_ERROR - Device error\r
+  EFI_SUCCESS - Video mode set successfully\r
+  EFI_UNSUPPORTED - Cannot support this video mode\r
+\r
+--*/\r
+{\r
+  EFI_STATUS            Status;\r
+  BIOS_VIDEO_DEV        *BiosVideoPrivate;\r
+  UINTN                 Index;\r
+  EFI_IA32_REGISTER_SET Regs;\r
+\r
+  BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_UGA_DRAW_THIS (This);\r
+\r
+  for (Index = 0; Index < BiosVideoPrivate->MaxMode; Index++) {\r
+\r
+    if (HorizontalResolution != BiosVideoPrivate->ModeData[Index].HorizontalResolution) {\r
+      continue;\r
+    }\r
+\r
+    if (VerticalResolution != BiosVideoPrivate->ModeData[Index].VerticalResolution) {\r
+      continue;\r
+    }\r
+\r
+    if (ColorDepth != BiosVideoPrivate->ModeData[Index].ColorDepth) {\r
+      continue;\r
+    }\r
+\r
+    if (RefreshRate != BiosVideoPrivate->ModeData[Index].RefreshRate) {\r
+      continue;\r
+    }\r
+\r
+    if (BiosVideoPrivate->LineBuffer) {\r
+      gBS->FreePool (BiosVideoPrivate->LineBuffer);\r
+    }\r
+\r
+    if (BiosVideoPrivate->VgaFrameBuffer) {\r
+      gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
+    }\r
+\r
+    if (BiosVideoPrivate->VbeFrameBuffer) {\r
+      gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
+    }\r
+\r
+    BiosVideoPrivate->LineBuffer = NULL;\r
+    Status = gBS->AllocatePool (\r
+                    EfiBootServicesData,\r
+                    BiosVideoPrivate->ModeData[Index].BytesPerScanLine,\r
+                    &BiosVideoPrivate->LineBuffer\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    //\r
+    // Clear all registers\r
+    //\r
+    gBS->SetMem (&Regs, sizeof (Regs), 0);\r
+\r
+    if (BiosVideoPrivate->ModeData[Index].VbeModeNumber < 0x100) {\r
+      //\r
+      // Allocate a working buffer for BLT operations to the VGA frame buffer\r
+      //\r
+      BiosVideoPrivate->VgaFrameBuffer = NULL;\r
+      Status = gBS->AllocatePool (\r
+                      EfiBootServicesData,\r
+                      4 * 480 * 80,\r
+                      &BiosVideoPrivate->VgaFrameBuffer\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      //\r
+      // Set VGA Mode\r
+      //\r
+      Regs.X.AX = BiosVideoPrivate->ModeData[Index].VbeModeNumber;\r
+      LegacyBiosInt86 (0x10, &Regs);\r
+\r
+    } else {\r
+      //\r
+      // Allocate a working buffer for BLT operations to the VBE frame buffer\r
+      //\r
+      BiosVideoPrivate->VbeFrameBuffer = NULL;\r
+      Status = gBS->AllocatePool (\r
+                      EfiBootServicesData,\r
+                      BiosVideoPrivate->ModeData[Index].BytesPerScanLine * BiosVideoPrivate->ModeData[Index].VerticalResolution,\r
+                      &BiosVideoPrivate->VbeFrameBuffer\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      //\r
+      // Set VBE mode\r
+      //\r
+      Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE;\r
+      Regs.X.BX = (UINT16) (BiosVideoPrivate->ModeData[Index].VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER);\r
+      gBS->SetMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK), 0);\r
+      Regs.X.ES = EFI_SEGMENT ((UINTN)BiosVideoPrivate->VbeCrtcInformationBlock);\r
+      Regs.X.DI = EFI_OFFSET ((UINTN)BiosVideoPrivate->VbeCrtcInformationBlock);\r
+      LegacyBiosInt86 (0x10, &Regs);\r
+\r
+      //\r
+      // Check to see if the call succeeded\r
+      //\r
+      if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      //\r
+      // Initialize the state of the VbeFrameBuffer\r
+      //\r
+      Status = BiosVideoPrivate->PciIo->Mem.Read (\r
+                                              BiosVideoPrivate->PciIo,\r
+                                              EfiPciIoWidthUint32,\r
+                                              EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                                              (UINT64) (UINTN) BiosVideoPrivate->ModeData[Index].LinearFrameBuffer,\r
+                                              (BiosVideoPrivate->ModeData[Index].BytesPerScanLine * BiosVideoPrivate->ModeData[Index].VerticalResolution) >> 2,\r
+                                              BiosVideoPrivate->VbeFrameBuffer\r
+                                              );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    BiosVideoPrivate->CurrentMode           = Index;\r
+\r
+    BiosVideoPrivate->HardwareNeedsStarting = FALSE;\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+VOID\r
+CopyVideoBuffer (\r
+  IN  EFI_PCI_IO_PROTOCOL   *PciIo,\r
+  IN  UINT8                 *VbeBuffer,\r
+  IN  VOID                  *MemAddress,\r
+  IN  UINTN                 DestinationX,\r
+  IN  UINTN                 DestinationY,\r
+  IN  UINTN                 TotalBytes,\r
+  IN  UINT32                VbePixelWidth,\r
+  IN  UINTN                 BytesPerScanLine\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.\r
+\r
+Arguments:\r
+\r
+  PciIo             - The pointer of EFI_PCI_IO_PROTOCOL\r
+  VbeBuffer         - The data to transfer to screen\r
+  MemAddress        - Physical frame buffer base address\r
+  DestinationX      - The X coordinate of the destination for BltOperation\r
+  DestinationY      - The Y coordinate of the destination for BltOperation\r
+  TotalBytes        - The total bytes of copy\r
+  VbePixelWidth     - Bytes per pixel\r
+  BytesPerScanLine  - Bytes per scan line\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+{\r
+  UINTN                 FrameBufferAddr;\r
+  UINTN                 CopyBlockNum;\r
+  UINTN                 RemainingBytes;\r
+  UINTN                 UnalignedBytes;\r
+  EFI_STATUS            Status;\r
+\r
+  FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;\r
+\r
+  //\r
+  // If TotalBytes is less than 4 bytes, only start byte copy.\r
+  //\r
+  if (TotalBytes < 4) {\r
+    Status = PciIo->Mem.Write (\r
+                     PciIo,\r
+                     EfiPciIoWidthUint8,\r
+                     EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                     (UINT64) FrameBufferAddr,\r
+                     TotalBytes,\r
+                     VbeBuffer\r
+                     );\r
+    ASSERT_EFI_ERROR (Status);\r
+    return;\r
+  }\r
+\r
+  //\r
+  // If VbeBuffer is not 4-byte aligned, start byte copy.\r
+  //\r
+  UnalignedBytes  = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;\r
+\r
+  if (UnalignedBytes != 0) {\r
+    Status = PciIo->Mem.Write (\r
+                     PciIo,\r
+                     EfiPciIoWidthUint8,\r
+                     EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                     (UINT64) FrameBufferAddr,\r
+                     UnalignedBytes,\r
+                     VbeBuffer\r
+                     );\r
+    ASSERT_EFI_ERROR (Status);\r
+    FrameBufferAddr += UnalignedBytes;\r
+    VbeBuffer       += UnalignedBytes;\r
+  }\r
+\r
+  //\r
+  // Calculate 4-byte block count and remaining bytes.\r
+  //\r
+  CopyBlockNum   = (TotalBytes - UnalignedBytes) >> 2;\r
+  RemainingBytes = (TotalBytes - UnalignedBytes) &  3;\r
+\r
+  //\r
+  // Copy 4-byte block and remaining bytes to physical frame buffer.\r
+  //\r
+  if (CopyBlockNum != 0) {\r
+    Status = PciIo->Mem.Write (\r
+                    PciIo,\r
+                    EfiPciIoWidthUint32,\r
+                    EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                    (UINT64) FrameBufferAddr,\r
+                    CopyBlockNum,\r
+                    VbeBuffer\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  if (RemainingBytes != 0) {\r
+    FrameBufferAddr += (CopyBlockNum << 2);\r
+    VbeBuffer       += (CopyBlockNum << 2);\r
+    Status = PciIo->Mem.Write (\r
+                    PciIo,\r
+                    EfiPciIoWidthUint8,\r
+                    EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                    (UINT64) FrameBufferAddr,\r
+                    RemainingBytes,\r
+                    VbeBuffer\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+}\r
+\r
+//\r
+// BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoUgaDrawVbeBlt (\r
+  IN  EFI_UGA_DRAW_PROTOCOL  *This,\r
+  IN  EFI_UGA_PIXEL          *BltBuffer, OPTIONAL\r
+  IN  EFI_UGA_BLT_OPERATION  BltOperation,\r
+  IN  UINTN                  SourceX,\r
+  IN  UINTN                  SourceY,\r
+  IN  UINTN                  DestinationX,\r
+  IN  UINTN                  DestinationY,\r
+  IN  UINTN                  Width,\r
+  IN  UINTN                  Height,\r
+  IN  UINTN                  Delta\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  UGA draw protocol instance to block transfer for VBE device\r
+\r
+Arguments:\r
+\r
+  This          - Pointer to UGA draw protocol instance\r
+  BltBuffer     - The data to transfer to screen\r
+  BltOperation  - The operation to perform\r
+  SourceX       - The X coordinate of the source for BltOperation\r
+  SourceY       - The Y coordinate of the source for BltOperation\r
+  DestinationX  - The X coordinate of the destination for BltOperation\r
+  DestinationY  - The Y coordinate of the destination for BltOperation\r
+  Width         - The width of a rectangle in the blt rectangle in pixels\r
+  Height        - The height of a rectangle in the blt rectangle in pixels\r
+  Delta         - Not used for EfiUgaVideoFill and EfiUgaVideoToVideo operation.\r
+                  If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
+                  If a subrectangle of the BltBuffer is used, then Delta represents \r
+                  the number of bytes in a row of the BltBuffer.\r
+\r
+Returns:\r
+\r
+  EFI_INVALID_PARAMETER - Invalid parameter passed in\r
+  EFI_SUCCESS - Blt operation success\r
+\r
+--*/\r
+{\r
+  BIOS_VIDEO_DEV        *BiosVideoPrivate;\r
+  BIOS_VIDEO_MODE_DATA  *Mode;\r
+  EFI_PCI_IO_PROTOCOL   *PciIo;\r
+  EFI_TPL               OriginalTPL;\r
+  UINTN                 DstY;\r
+  UINTN                 SrcY;\r
+  UINTN                 DstX;\r
+  EFI_UGA_PIXEL         *Blt;\r
+  VOID                  *MemAddress;\r
+  EFI_UGA_PIXEL         *VbeFrameBuffer;\r
+  UINTN                 BytesPerScanLine;\r
+  UINTN                 Index;\r
+  UINT8                 *VbeBuffer;\r
+  UINT8                 *VbeBuffer1;\r
+  UINT8                 *BltUint8;\r
+  UINT32                VbePixelWidth;\r
+  UINT32                Pixel;\r
+  UINTN                 TotalBytes;\r
+\r
+  BiosVideoPrivate  = BIOS_VIDEO_DEV_FROM_UGA_DRAW_THIS (This);\r
+  Mode              = &BiosVideoPrivate->ModeData[BiosVideoPrivate->CurrentMode];\r
+  PciIo             = BiosVideoPrivate->PciIo;\r
+\r
+  VbeFrameBuffer    = BiosVideoPrivate->VbeFrameBuffer;\r
+  MemAddress        = Mode->LinearFrameBuffer;\r
+  BytesPerScanLine  = Mode->BytesPerScanLine;\r
+  VbePixelWidth     = Mode->BitsPerPixel / 8;\r
+  BltUint8          = (UINT8 *) BltBuffer;\r
+  TotalBytes        = Width * VbePixelWidth;\r
+\r
+  if ((BltOperation < EfiUgaVideoFill) || (BltOperation >= EfiUgaBltMax)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Width == 0 || Height == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // We need to fill the Virtual Screen buffer with the blt data.\r
+  // The virtual screen is upside down, as the first row is the bootom row of\r
+  // the image.\r
+  //\r
+  if (BltOperation == EfiUgaVideoToBltBuffer) {\r
+    //\r
+    // Video to BltBuffer: Source is Video, destination is BltBuffer\r
+    //\r
+    if (SourceY + Height > Mode->VerticalResolution) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if (SourceX + Width > Mode->HorizontalResolution) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  } else {\r
+    //\r
+    // BltBuffer to Video: Source is BltBuffer, destination is Video\r
+    //\r
+    if (DestinationY + Height > Mode->VerticalResolution) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if (DestinationX + Width > Mode->HorizontalResolution) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  //\r
+  // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
+  // is the number of bytes in each row of BltBuffer.  Since BltBuffer is Width pixels size,\r
+  // the number of bytes in each row can be computed.\r
+  //\r
+  if (Delta == 0) {\r
+    Delta = Width * sizeof (EFI_UGA_PIXEL);\r
+  }\r
+  //\r
+  // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
+  // We would not want a timer based event (Cursor, ...) to come in while we are\r
+  // doing this operation.\r
+  //\r
+  OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  switch (BltOperation) {\r
+  case EfiUgaVideoToBltBuffer:\r
+    for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {\r
+      Blt = (EFI_UGA_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_UGA_PIXEL));\r
+      //\r
+      // Shuffle the packed bytes in the hardware buffer to match EFI_UGA_PIXEL\r
+      //\r
+      VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));\r
+      for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
+        Pixel         = *(UINT32 *) (VbeBuffer);\r
+        Blt->Red      = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);\r
+        Blt->Blue     = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);\r
+        Blt->Green    = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);\r
+        Blt->Reserved = 0;\r
+        Blt++;\r
+        VbeBuffer += VbePixelWidth;\r
+      }\r
+\r
+    }\r
+    break;\r
+\r
+  case EfiUgaVideoToVideo:\r
+    for (Index = 0; Index < Height; Index++) {\r
+      if (DestinationY <= SourceY) {\r
+        SrcY  = SourceY + Index;\r
+        DstY  = DestinationY + Index;\r
+      } else {\r
+        SrcY  = SourceY + Height - Index - 1;\r
+        DstY  = DestinationY + Height - Index - 1;\r
+      }\r
+\r
+      VbeBuffer   = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);\r
+      VbeBuffer1  = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);\r
+\r
+      gBS->CopyMem (\r
+            VbeBuffer,\r
+            VbeBuffer1,\r
+            TotalBytes\r
+            );\r
+\r
+      //\r
+      // Update physical frame buffer.\r
+      //\r
+      CopyVideoBuffer (\r
+        PciIo,\r
+        VbeBuffer,\r
+        MemAddress,\r
+        DestinationX,\r
+        DstY,\r
+        TotalBytes,\r
+        VbePixelWidth,\r
+        BytesPerScanLine\r
+        );\r
+    }\r
+    break;\r
+\r
+  case EfiUgaVideoFill:\r
+    VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
+    Blt       = (EFI_UGA_PIXEL *) BltUint8;\r
+    //\r
+    // Shuffle the RGB fields in EFI_UGA_PIXEL to match the hardware buffer\r
+    //\r
+    Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
+      (\r
+        (Blt->Green & Mode->Green.Mask) <<\r
+        Mode->Green.Position\r
+      ) |\r
+          ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
+\r
+    for (Index = 0; Index < Width; Index++) {\r
+      gBS->CopyMem (\r
+            VbeBuffer,\r
+            &Pixel,\r
+            VbePixelWidth\r
+            );\r
+      VbeBuffer += VbePixelWidth;\r
+    }\r
+\r
+    VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
+    for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {\r
+      gBS->CopyMem (\r
+            (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),\r
+            VbeBuffer,\r
+            TotalBytes\r
+            );\r
+    }\r
+    for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {\r
+      //\r
+      // Update physical frame buffer.\r
+      //\r
+      CopyVideoBuffer (\r
+        PciIo,\r
+        VbeBuffer,\r
+        MemAddress,\r
+        DestinationX,\r
+        DstY,\r
+        TotalBytes,\r
+        VbePixelWidth,\r
+        BytesPerScanLine\r
+        );\r
+    }\r
+\r
+    break;\r
+\r
+  case EfiUgaBltBufferToVideo:\r
+    for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {\r
+      Blt       = (EFI_UGA_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_UGA_PIXEL));\r
+      VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
+      for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
+        //\r
+        // Shuffle the RGB fields in EFI_UGA_PIXEL to match the hardware buffer\r
+        //\r
+        Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
+          ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |\r
+            ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
+        gBS->CopyMem (\r
+              VbeBuffer,\r
+              &Pixel,\r
+              VbePixelWidth\r
+              );\r
+        Blt++;\r
+        VbeBuffer += VbePixelWidth;\r
+      }\r
+\r
+      VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
+\r
+      //\r
+      // Update physical frame buffer.\r
+      //\r
+      CopyVideoBuffer (\r
+        PciIo,\r
+        VbeBuffer,\r
+        MemAddress,\r
+        DestinationX,\r
+        DstY,\r
+        TotalBytes,\r
+        VbePixelWidth,\r
+        BytesPerScanLine\r
+        );\r
+    }\r
+    break;\r
+  }\r
+\r
+  gBS->RestoreTPL (OriginalTPL);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+VOID\r
+WriteGraphicsController (\r
+  IN  EFI_PCI_IO_PROTOCOL  *PciIo,\r
+  IN  UINTN                Address,\r
+  IN  UINTN                Data\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Write graphics controller registers\r
+\r
+Arguments:\r
+\r
+  PciIo   - Pointer to PciIo protocol instance of the controller\r
+  Address - Register address\r
+  Data    - Data to be written to register\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  Address = Address | (Data << 8);\r
+  PciIo->Io.Write (\r
+              PciIo,\r
+              EfiPciIoWidthUint16,\r
+              EFI_PCI_IO_PASS_THROUGH_BAR,\r
+              VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER,\r
+              1,\r
+              &Address\r
+              );\r
+}\r
+\r
+VOID\r
+VgaReadBitPlanes (\r
+  EFI_PCI_IO_PROTOCOL  *PciIo,\r
+  UINT8                *HardwareBuffer,\r
+  UINT8                *MemoryBuffer,\r
+  UINTN                WidthInBytes,\r
+  UINTN                Height\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Read the four bit plane of VGA frame buffer\r
+\r
+Arguments:\r
+\r
+  PciIo           - Pointer to PciIo protocol instance of the controller\r
+  HardwareBuffer  - Hardware VGA frame buffer address\r
+  MemoryBuffer    - Memory buffer address\r
+  WidthInBytes    - Number of bytes in a line to read\r
+  Height          - Height of the area to read\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINTN BitPlane;\r
+  UINTN Rows;\r
+  UINTN FrameBufferOffset;\r
+  UINT8 *Source;\r
+  UINT8 *Destination;\r
+\r
+  //\r
+  // Program the Mode Register Write mode 0, Read mode 0\r
+  //\r
+  WriteGraphicsController (\r
+    PciIo,\r
+    VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
+    VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0\r
+    );\r
+\r
+  for (BitPlane = 0, FrameBufferOffset = 0;\r
+       BitPlane < VGA_NUMBER_OF_BIT_PLANES;\r
+       BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE\r
+      ) {\r
+    //\r
+    // Program the Read Map Select Register to select the correct bit plane\r
+    //\r
+    WriteGraphicsController (\r
+      PciIo,\r
+      VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER,\r
+      BitPlane\r
+      );\r
+\r
+    Source      = HardwareBuffer;\r
+    Destination = MemoryBuffer + FrameBufferOffset;\r
+\r
+    for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) {\r
+      PciIo->Mem.Read (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint8,\r
+                  EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                  (UINT64) Source,\r
+                  WidthInBytes,\r
+                  (VOID *) Destination\r
+                  );\r
+    }\r
+  }\r
+}\r
+\r
+VOID\r
+VgaConvertToUgaColor (\r
+  UINT8          *MemoryBuffer,\r
+  UINTN          X,\r
+  UINTN          Y,\r
+  EFI_UGA_PIXEL  *BltBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Internal routine to convert VGA color to UGA color\r
+\r
+Arguments:\r
+\r
+  MemoryBuffer  - Buffer containing VGA color\r
+  X             - The X coordinate of pixel on screen\r
+  Y             - The Y coordinate of pixel on screen\r
+  BltBuffer     - Buffer to contain converted UGA color\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINTN Mask;\r
+  UINTN Bit;\r
+  UINTN Color;\r
+\r
+  MemoryBuffer += ((Y << 6) + (Y << 4) + (X >> 3));\r
+  Mask = mVgaBitMaskTable[X & 0x07];\r
+  for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) {\r
+    if (*MemoryBuffer & Mask) {\r
+      Color |= Bit;\r
+    }\r
+  }\r
+\r
+  *BltBuffer = mVgaColorToUgaColor[Color];\r
+}\r
+\r
+UINT8\r
+VgaConvertColor (\r
+  IN  EFI_UGA_PIXEL          *BltBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Internal routine to convert UGA color to VGA color\r
+\r
+Arguments:\r
+\r
+  BltBuffer - buffer containing UGA color\r
+\r
+Returns:\r
+\r
+  Converted VGA color\r
+\r
+--*/\r
+{\r
+  UINT8 Color;\r
+\r
+  Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04));\r
+  if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) {\r
+    Color |= 0x08;\r
+  }\r
+\r
+  return Color;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoUgaDrawVgaBlt (\r
+  IN  EFI_UGA_DRAW_PROTOCOL  *This,\r
+  IN  EFI_UGA_PIXEL          *BltBuffer, OPTIONAL\r
+  IN  EFI_UGA_BLT_OPERATION  BltOperation,\r
+  IN  UINTN                  SourceX,\r
+  IN  UINTN                  SourceY,\r
+  IN  UINTN                  DestinationX,\r
+  IN  UINTN                  DestinationY,\r
+  IN  UINTN                  Width,\r
+  IN  UINTN                  Height,\r
+  IN  UINTN                  Delta\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  UGA draw protocol instance to block transfer for VGA device\r
+\r
+Arguments:\r
+\r
+  This          - Pointer to UGA draw protocol instance\r
+  BltBuffer     - The data to transfer to screen\r
+  BltOperation  - The operation to perform\r
+  SourceX       - The X coordinate of the source for BltOperation\r
+  SourceY       - The Y coordinate of the source for BltOperation\r
+  DestinationX  - The X coordinate of the destination for BltOperation\r
+  DestinationY  - The Y coordinate of the destination for BltOperation\r
+  Width         - The width of a rectangle in the blt rectangle in pixels\r
+  Height        - The height of a rectangle in the blt rectangle in pixels\r
+  Delta         - Not used for EfiUgaVideoFill and EfiUgaVideoToVideo operation.\r
+                  If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
+                  If a subrectangle of the BltBuffer is used, then Delta represents \r
+                  the number of bytes in a row of the BltBuffer.\r
+\r
+Returns:\r
+\r
+  EFI_INVALID_PARAMETER - Invalid parameter passed in\r
+  EFI_SUCCESS - Blt operation success\r
+\r
+--*/\r
+{\r
+  BIOS_VIDEO_DEV      *BiosVideoPrivate;\r
+  EFI_TPL             OriginalTPL;\r
+  UINT8               *MemAddress;\r
+  UINTN               BytesPerScanLine;\r
+  UINTN               BytesPerBitPlane;\r
+  UINTN               Bit;\r
+  UINTN               Index;\r
+  UINTN               Index1;\r
+  UINTN               StartAddress;\r
+  UINTN               Bytes;\r
+  UINTN               Offset;\r
+  UINT8               LeftMask;\r
+  UINT8               RightMask;\r
+  UINTN               Address;\r
+  UINTN               AddressFix;\r
+  UINT8               *Address1;\r
+  UINT8               *SourceAddress;\r
+  UINT8               *DestinationAddress;\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT8               Data;\r
+  UINT8               PixelColor;\r
+  UINT8               *VgaFrameBuffer;\r
+  UINTN               SourceOffset;\r
+  UINTN               SourceWidth;\r
+  UINTN               Rows;\r
+  UINTN               Columns;\r
+  UINTN               X;\r
+  UINTN               Y;\r
+\r
+  BiosVideoPrivate  = BIOS_VIDEO_DEV_FROM_UGA_DRAW_THIS (This);\r
+\r
+  PciIo             = BiosVideoPrivate->PciIo;\r
+  MemAddress        = BiosVideoPrivate->ModeData[BiosVideoPrivate->CurrentMode].LinearFrameBuffer;\r
+  BytesPerScanLine  = BiosVideoPrivate->ModeData[BiosVideoPrivate->CurrentMode].BytesPerScanLine >> 3;\r
+  BytesPerBitPlane  = BytesPerScanLine * BiosVideoPrivate->ModeData[BiosVideoPrivate->CurrentMode].VerticalResolution;\r
+  VgaFrameBuffer    = BiosVideoPrivate->VgaFrameBuffer;\r
+\r
+  if ((BltOperation < EfiUgaVideoFill) || (BltOperation >= EfiUgaBltMax)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Width == 0 || Height == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // We need to fill the Virtual Screen buffer with the blt data.\r
+  // The virtual screen is upside down, as the first row is the bootom row of\r
+  // the image.\r
+  //\r
+  if (BltOperation == EfiUgaVideoToBltBuffer) {\r
+    //\r
+    // Video to BltBuffer: Source is Video, destination is BltBuffer\r
+    //\r
+    if (SourceY + Height > BiosVideoPrivate->ModeData[BiosVideoPrivate->CurrentMode].VerticalResolution) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if (SourceX + Width > BiosVideoPrivate->ModeData[BiosVideoPrivate->CurrentMode].HorizontalResolution) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  } else {\r
+    //\r
+    // BltBuffer to Video: Source is BltBuffer, destination is Video\r
+    //\r
+    if (DestinationY + Height > BiosVideoPrivate->ModeData[BiosVideoPrivate->CurrentMode].VerticalResolution) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if (DestinationX + Width > BiosVideoPrivate->ModeData[BiosVideoPrivate->CurrentMode].HorizontalResolution) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  //\r
+  // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
+  // is the number of bytes in each row of BltBuffer.  Since BltBuffer is Width pixels size,\r
+  // the number of bytes in each row can be computed.\r
+  //\r
+  if (Delta == 0) {\r
+    Delta = Width * sizeof (EFI_UGA_PIXEL);\r
+  }\r
+  //\r
+  // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
+  // We would not want a timer based event (Cursor, ...) to come in while we are\r
+  // doing this operation.\r
+  //\r
+  OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  //\r
+  // Compute some values we need for VGA\r
+  //\r
+  switch (BltOperation) {\r
+  case EfiUgaVideoToBltBuffer:\r
+\r
+    SourceOffset  = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
+    SourceWidth   = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
+\r
+    //\r
+    // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
+    //\r
+    VgaReadBitPlanes (\r
+      PciIo,\r
+      MemAddress + SourceOffset,\r
+      VgaFrameBuffer + SourceOffset,\r
+      SourceWidth,\r
+      Height\r
+      );\r
+\r
+    //\r
+    // Convert VGA Bit Planes to a UGA 32-bit color value\r
+    //\r
+    BltBuffer += (DestinationY * (Delta >> 2) + DestinationX);\r
+    for (Rows = 0, Y = SourceY; Rows < Height; Rows++, Y++, BltBuffer += (Delta >> 2)) {\r
+      for (Columns = 0, X = SourceX; Columns < Width; Columns++, X++, BltBuffer++) {\r
+        VgaConvertToUgaColor (VgaFrameBuffer, X, Y, BltBuffer);\r
+      }\r
+\r
+      BltBuffer -= Width;\r
+    }\r
+\r
+    break;\r
+\r
+  case EfiUgaVideoToVideo:\r
+    //\r
+    // Check for an aligned Video to Video operation\r
+    //\r
+    if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) {\r
+      //\r
+      // Program the Mode Register Write mode 1, Read mode 0\r
+      //\r
+      WriteGraphicsController (\r
+        BiosVideoPrivate->PciIo,\r
+        VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
+        VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1\r
+        );\r
+\r
+      SourceAddress       = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3));\r
+      DestinationAddress  = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
+      Bytes               = Width >> 3;\r
+      for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) {\r
+        PciIo->CopyMem (\r
+                PciIo,\r
+                EfiPciIoWidthUint8,\r
+                EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                (UINT64) (DestinationAddress + Offset),\r
+                EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                (UINT64) (SourceAddress + Offset),\r
+                Bytes\r
+                );\r
+      }\r
+    } else {\r
+      SourceOffset  = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
+      SourceWidth   = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
+\r
+      //\r
+      // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
+      //\r
+      VgaReadBitPlanes (\r
+        PciIo,\r
+        MemAddress + SourceOffset,\r
+        VgaFrameBuffer + SourceOffset,\r
+        SourceWidth,\r
+        Height\r
+        );\r
+    }\r
+\r
+    break;\r
+\r
+  case EfiUgaVideoFill:\r
+    StartAddress  = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
+    Bytes         = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3);\r
+    LeftMask      = mVgaLeftMaskTable[DestinationX & 0x07];\r
+    RightMask     = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07];\r
+    if (Bytes == 0) {\r
+      LeftMask &= RightMask;\r
+      RightMask = 0;\r
+    }\r
+\r
+    if (LeftMask == 0xff) {\r
+      StartAddress--;\r
+      Bytes++;\r
+      LeftMask = 0;\r
+    }\r
+\r
+    if (RightMask == 0xff) {\r
+      Bytes++;\r
+      RightMask = 0;\r
+    }\r
+\r
+    PixelColor = VgaConvertColor (BltBuffer);\r
+\r
+    //\r
+    // Program the Mode Register Write mode 2, Read mode 0\r
+    //\r
+    WriteGraphicsController (\r
+      BiosVideoPrivate->PciIo,\r
+      VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
+      VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
+      );\r
+\r
+    //\r
+    // Program the Data Rotate/Function Select Register to replace\r
+    //\r
+    WriteGraphicsController (\r
+      BiosVideoPrivate->PciIo,\r
+      VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
+      VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
+      );\r
+\r
+    if (LeftMask != 0) {\r
+      //\r
+      // Program the BitMask register with the Left column mask\r
+      //\r
+      WriteGraphicsController (\r
+        BiosVideoPrivate->PciIo,\r
+        VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
+        LeftMask\r
+        );\r
+\r
+      for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
+        //\r
+        // Read data from the bit planes into the latches\r
+        //\r
+        PciIo->Mem.Read (\r
+                    PciIo,\r
+                    EfiPciIoWidthUint8,\r
+                    EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                    (UINT64) Address,\r
+                    1,\r
+                    &Data\r
+                    );\r
+        //\r
+        // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
+        //\r
+        PciIo->Mem.Write (\r
+                    PciIo,\r
+                    EfiPciIoWidthUint8,\r
+                    EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                    (UINT64) Address,\r
+                    1,\r
+                    &PixelColor\r
+                    );\r
+      }\r
+    }\r
+\r
+    if (Bytes > 1) {\r
+      //\r
+      // Program the BitMask register with the middle column mask of 0xff\r
+      //\r
+      WriteGraphicsController (\r
+        BiosVideoPrivate->PciIo,\r
+        VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
+        0xff\r
+        );\r
+\r
+      for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) {\r
+        PciIo->Mem.Write (\r
+                    PciIo,\r
+                    EfiPciIoWidthFillUint8,\r
+                    EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                    (UINT64) Address,\r
+                    Bytes - 1,\r
+                    &PixelColor\r
+                    );\r
+      }\r
+    }\r
+\r
+    if (RightMask != 0) {\r
+      //\r
+      // Program the BitMask register with the Right column mask\r
+      //\r
+      WriteGraphicsController (\r
+        BiosVideoPrivate->PciIo,\r
+        VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
+        RightMask\r
+        );\r
+\r
+      for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) {\r
+        //\r
+        // Read data from the bit planes into the latches\r
+        //\r
+        PciIo->Mem.Read (\r
+                    PciIo,\r
+                    EfiPciIoWidthUint8,\r
+                    EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                    (UINT64) Address,\r
+                    1,\r
+                    &Data\r
+                    );\r
+        //\r
+        // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
+        //\r
+        PciIo->Mem.Write (\r
+                    PciIo,\r
+                    EfiPciIoWidthUint8,\r
+                    EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                    (UINT64) Address,\r
+                    1,\r
+                    &PixelColor\r
+                    );\r
+      }\r
+    }\r
+    break;\r
+\r
+  case EfiUgaBltBufferToVideo:\r
+    StartAddress  = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
+    LeftMask      = mVgaBitMaskTable[DestinationX & 0x07];\r
+\r
+    //\r
+    // Program the Mode Register Write mode 2, Read mode 0\r
+    //\r
+    WriteGraphicsController (\r
+      BiosVideoPrivate->PciIo,\r
+      VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
+      VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
+      );\r
+\r
+    //\r
+    // Program the Data Rotate/Function Select Register to replace\r
+    //\r
+    WriteGraphicsController (\r
+      BiosVideoPrivate->PciIo,\r
+      VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
+      VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
+      );\r
+\r
+    for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
+      for (Index1 = 0; Index1 < Width; Index1++) {\r
+        BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]);\r
+      }\r
+      AddressFix = Address;\r
+\r
+      for (Bit = 0; Bit < 8; Bit++) {\r
+        //\r
+        // Program the BitMask register with the Left column mask\r
+        //\r
+        WriteGraphicsController (\r
+          BiosVideoPrivate->PciIo,\r
+          VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
+          LeftMask\r
+          );\r
+\r
+        for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) {\r
+          //\r
+          // Read data from the bit planes into the latches\r
+          //\r
+          PciIo->Mem.Read (\r
+                      PciIo,\r
+                      EfiPciIoWidthUint8,\r
+                      EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                      (UINT64) Address1,\r
+                      1,\r
+                      &Data\r
+                      );\r
+\r
+          PciIo->Mem.Write (\r
+                      PciIo,\r
+                      EfiPciIoWidthUint8,\r
+                      EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                      (UINT64) Address1,\r
+                      1,\r
+                      &BiosVideoPrivate->LineBuffer[Index1]\r
+                      );\r
+        }\r
+\r
+        LeftMask = (UINT8) (LeftMask >> 1);\r
+        if (LeftMask == 0) {\r
+          LeftMask = 0x80;\r
+          AddressFix++;\r
+        }\r
+      }\r
+    }\r
+\r
+    break;\r
+  }\r
+\r
+  gBS->RestoreTPL (OriginalTPL);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+//\r
+// VGA Mini Port Protocol Functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoVgaMiniPortSetMode (\r
+  IN  EFI_VGA_MINI_PORT_PROTOCOL  *This,\r
+  IN  UINTN                       ModeNumber\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  VgaMiniPort protocol interface to set mode\r
+\r
+Arguments:\r
+\r
+  This        - Pointer to VgaMiniPort protocol instance\r
+  ModeNumber  - The index of the mode\r
+\r
+Returns:\r
+\r
+  EFI_UNSUPPORTED - The requested mode is not supported\r
+  EFI_SUCCESS - The requested mode is set successfully\r
+\r
+--*/\r
+{\r
+  BIOS_VIDEO_DEV        *BiosVideoPrivate;\r
+  EFI_IA32_REGISTER_SET Regs;\r
+\r
+  //\r
+  // Make sure the ModeNumber is a valid value\r
+  //\r
+  if (ModeNumber >= This->MaxMode) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  //\r
+  // Get the device structure for this device\r
+  //\r
+  BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This);\r
+\r
+  gBS->SetMem (&Regs, sizeof (Regs), 0);\r
+\r
+  switch (ModeNumber) {\r
+  case 0:\r
+    //\r
+    // Set the 80x25 Text VGA Mode\r
+    //\r
+    Regs.H.AH = 0x00;\r
+    Regs.H.AL = 0x83;\r
+    LegacyBiosInt86 (0x10, &Regs);\r
+\r
+    Regs.H.AH = 0x11;\r
+    Regs.H.AL = 0x14;\r
+    Regs.H.BL = 0;\r
+    LegacyBiosInt86 (0x10, &Regs);\r
+    break;\r
+\r
+  case 1:\r
+    //\r
+    // Set the 80x50 Text VGA Mode\r
+    //\r
+    Regs.H.AH = 0x00;\r
+    Regs.H.AL = 0x83;\r
+    LegacyBiosInt86 (0x10, &Regs);\r
+    Regs.H.AH = 0x11;\r
+    Regs.H.AL = 0x12;\r
+    Regs.H.BL = 0;\r
+    LegacyBiosInt86 (0x10, &Regs);\r
+    break;\r
+\r
+  default:\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+InitializeBiosIntCaller (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  UINT32                RealModeBufferSize;\r
+  UINT32                ExtraStackSize;\r
+  EFI_PHYSICAL_ADDRESS  LegacyRegionBase;\r
+  \r
+  //\r
+  // Get LegacyRegion\r
+  //\r
+  AsmGetThunk16Properties (&RealModeBufferSize, &ExtraStackSize);\r
+\r
+  LegacyRegionBase = 0x100000;\r
+  Status = gBS->AllocatePages (\r
+                  AllocateMaxAddress,\r
+                  EfiACPIMemoryNVS,\r
+                  EFI_SIZE_TO_PAGES(RealModeBufferSize + ExtraStackSize + 200),\r
+                  &LegacyRegionBase\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  mThunkContext.RealModeBuffer     = (VOID*)(UINTN)LegacyRegionBase;\r
+  mThunkContext.RealModeBufferSize = EFI_PAGES_TO_SIZE (RealModeBufferSize);\r
+  mThunkContext.ThunkAttributes    = 3;\r
+  AsmPrepareThunk16(&mThunkContext);\r
+  \r
+  //Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &mLegacy8259);\r
+  //ASSERT_EFI_ERROR (Status);  \r
+}\r
+\r
+VOID\r
+InitializeInterruptRedirection (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Initialize interrupt redirection code and entries, because\r
+    IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f.\r
+    Or the interrupt will lost when we do thunk.\r
+    NOTE: We do not reset 8259 vector base, because it will cause pending\r
+    interrupt lost.\r
+\r
+  Arguments:\r
+    NONE\r
+\r
+  Returns:\r
+    NONE\r
+--*/\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_PHYSICAL_ADDRESS  LegacyRegionBase;\r
+  UINTN                 LegacyRegionLength;\r
+  UINT32                *IdtArray;\r
+  UINTN                 Index;\r
+  UINT8                 ProtectedModeBaseVector;\r
+  UINT32                InterruptRedirectionCode[] = {\r
+    0x90CF08CD, // INT8; IRET; NOP\r
+    0x90CF09CD, // INT9; IRET; NOP\r
+    0x90CF0ACD, // INTA; IRET; NOP\r
+    0x90CF0BCD, // INTB; IRET; NOP\r
+    0x90CF0CCD, // INTC; IRET; NOP\r
+    0x90CF0DCD, // INTD; IRET; NOP\r
+    0x90CF0ECD, // INTE; IRET; NOP\r
+    0x90CF0FCD  // INTF; IRET; NOP\r
+  };\r
+\r
+  //\r
+  // Get LegacyRegion\r
+  //\r
+  LegacyRegionLength = sizeof(InterruptRedirectionCode);\r
+  LegacyRegionBase = 0x100000;\r
+  Status = gBS->AllocatePages (\r
+                  AllocateMaxAddress,\r
+                  EfiACPIMemoryNVS,\r
+                  EFI_SIZE_TO_PAGES(LegacyRegionLength),\r
+                  &LegacyRegionBase\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Copy code to legacy region\r
+  //\r
+  CopyMem ((VOID *)(UINTN)LegacyRegionBase, InterruptRedirectionCode, sizeof (InterruptRedirectionCode));\r
+\r
+  //\r
+  // Get VectorBase, it should be 0x68\r
+  //\r
+  Status = mLegacy8259->GetVector (mLegacy8259, Efi8259Irq0, &ProtectedModeBaseVector);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Patch IVT 0x68 ~ 0x6f\r
+  //\r
+  IdtArray = (UINT32 *) 0;\r
+  for (Index = 0; Index < 8; Index++) {\r
+    IdtArray[ProtectedModeBaseVector + Index] = ((EFI_SEGMENT (LegacyRegionBase + Index * 4)) << 16) | (EFI_OFFSET (LegacyRegionBase + Index * 4));\r
+  }\r
+\r
+  return ;\r
+}\r
+\r
+BOOLEAN\r
+EFIAPI\r
+LegacyBiosInt86 (\r
+  IN  UINT8                           BiosInt,\r
+  IN  EFI_IA32_REGISTER_SET           *Regs\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Thunk to 16-bit real mode and execute a software interrupt with a vector \r
+    of BiosInt. Regs will contain the 16-bit register context on entry and \r
+    exit.\r
+\r
+  Arguments:\r
+    This    - Protocol instance pointer.\r
+    BiosInt - Processor interrupt vector to invoke\r
+    Reg     - Register contexted passed into (and returned) from thunk to \r
+              16-bit mode\r
+\r
+  Returns:\r
+    FALSE   - Thunk completed, and there were no BIOS errors in the target code.\r
+              See Regs for status.\r
+    TRUE    - There was a BIOS erro in the target code.\r
+\r
+--*/\r
+{\r
+  UINTN                 Status;\r
+  UINT32                Eflags;\r
+  IA32_REGISTER_SET     ThunkRegSet;\r
+  BOOLEAN               Ret;\r
+  UINT16                *Stack16;\r
+  \r
+  Regs->X.Flags.Reserved1 = 1;\r
+  Regs->X.Flags.Reserved2 = 0;\r
+  Regs->X.Flags.Reserved3 = 0;\r
+  Regs->X.Flags.Reserved4 = 0;\r
+  Regs->X.Flags.IOPL      = 3;\r
+  Regs->X.Flags.NT        = 0;\r
+  Regs->X.Flags.IF        = 1;\r
+  Regs->X.Flags.TF        = 0;\r
+  Regs->X.Flags.CF        = 0;\r
+\r
+  ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet));\r
+  ThunkRegSet.E.EDI  = Regs->E.EDI;\r
+  ThunkRegSet.E.ESI  = Regs->E.ESI;\r
+  ThunkRegSet.E.EBP  = Regs->E.EBP;\r
+  ThunkRegSet.E.EBX  = Regs->E.EBX;\r
+  ThunkRegSet.E.EDX  = Regs->E.EDX;\r
+  ThunkRegSet.E.ECX  = Regs->E.ECX;\r
+  ThunkRegSet.E.EAX  = Regs->E.EAX;\r
+  ThunkRegSet.E.DS   = Regs->E.DS;\r
+  ThunkRegSet.E.ES   = Regs->E.ES;\r
+\r
+  CopyMem (&(ThunkRegSet.E.EFLAGS), &(Regs->E.EFlags), sizeof (UINT32));\r
\r
+  //\r
+  // The call to Legacy16 is a critical section to EFI\r
+  //\r
+  Eflags = AsmReadEflags ();\r
+  if ((Eflags | EFI_CPU_EFLAGS_IF) != 0) {\r
+    DisableInterrupts ();\r
+  }\r
+\r
+  //\r
+  // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.\r
+  //\r
+  Status = mLegacy8259->SetMode (mLegacy8259, Efi8259LegacyMode, NULL, NULL);\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  Stack16 = (UINT16 *)((UINT8 *) mThunkContext.RealModeBuffer + mThunkContext.RealModeBufferSize - sizeof (UINT16));\r
+  Stack16 -= sizeof (ThunkRegSet.E.EFLAGS) / sizeof (UINT16);\r
+  CopyMem (Stack16, &ThunkRegSet.E.EFLAGS, sizeof (ThunkRegSet.E.EFLAGS));\r
+\r
+  ThunkRegSet.E.SS   = (UINT16) (((UINTN) Stack16 >> 16) << 12);\r
+  ThunkRegSet.E.ESP  = (UINT16) (UINTN) Stack16;\r
+  ThunkRegSet.E.Eip  = (UINT16)((UINT32 *)NULL)[BiosInt];\r
+  ThunkRegSet.E.CS   = (UINT16)(((UINT32 *)NULL)[BiosInt] >> 16);\r
+  mThunkContext.RealModeState = &ThunkRegSet;\r
+  AsmThunk16 (&mThunkContext);\r
+\r
+  //\r
+  // Restore protected mode interrupt state\r
+  //\r
+  Status = mLegacy8259->SetMode (mLegacy8259, Efi8259ProtectedMode, NULL, NULL);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // End critical section\r
+  //\r
+  if ((Eflags | EFI_CPU_EFLAGS_IF) != 0) {\r
+    EnableInterrupts ();\r
+  }\r
+\r
+  Regs->E.EDI      = ThunkRegSet.E.EDI;      \r
+  Regs->E.ESI      = ThunkRegSet.E.ESI;  \r
+  Regs->E.EBP      = ThunkRegSet.E.EBP;  \r
+  Regs->E.EBX      = ThunkRegSet.E.EBX;  \r
+  Regs->E.EDX      = ThunkRegSet.E.EDX;  \r
+  Regs->E.ECX      = ThunkRegSet.E.ECX;  \r
+  Regs->E.EAX      = ThunkRegSet.E.EAX;\r
+  Regs->E.SS       = ThunkRegSet.E.SS;\r
+  Regs->E.CS       = ThunkRegSet.E.CS;  \r
+  Regs->E.DS       = ThunkRegSet.E.DS;  \r
+  Regs->E.ES       = ThunkRegSet.E.ES;\r
+\r
+  CopyMem (&(Regs->E.EFlags), &(ThunkRegSet.E.EFLAGS), sizeof (UINT32));\r
+\r
+  Ret = (BOOLEAN) (Regs->E.EFlags.CF == 1);\r
+\r
+  return Ret;\r
+}\r
+\r
+\r
diff --git a/DuetPkg/BiosVideoThunkDxe/BiosVideo.h b/DuetPkg/BiosVideoThunkDxe/BiosVideo.h
new file mode 100644 (file)
index 0000000..2123090
--- /dev/null
@@ -0,0 +1,511 @@
+/*++\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  BiosVideo.h\r
+    \r
+Abstract: \r
+\r
+Revision History\r
+--*/\r
+\r
+#ifndef _BIOS_UGA_H\r
+#define _BIOS_UGA_H\r
+\r
+#include <Uefi.h>\r
+\r
+//\r
+// Driver Consumed Protocol Prototypes\r
+//\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/DriverBinding.h>\r
+#include <Protocol/ComponentName.h>\r
+#include <Protocol/ComponentName2.h>\r
+#include <Protocol/UgaDraw.h>\r
+#include <Protocol/VgaMiniPort.h>\r
+#include <Protocol/Legacy8259.h>\r
+#include <Protocol/LegacyBios.h>\r
+\r
+#include <Library/UefiLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+#include <IndustryStandard/Pci22.h>\r
+\r
+#include "VesaBiosExtensions.h"\r
+//\r
+// Driver Produced Protocol Prototypes\r
+//\r
+//#include EFI_PROTOCOL_DEFINITION (DriverBinding)\r
+//#include EFI_PROTOCOL_DEFINITION (ComponentName)\r
+//#include EFI_PROTOCOL_DEFINITION (ComponentName2)\r
+//#include EFI_PROTOCOL_DEFINITION (UgaDraw)\r
+//#include EFI_PROTOCOL_DEFINITION (VgaMiniPort)\r
+\r
+//\r
+// Packed format support: The number of bits reserved for each of the colors and the actual\r
+// position of RGB in the frame buffer is specified in the VBE Mode information\r
+//\r
+typedef struct {\r
+  UINT8 Position; // Position of the color\r
+  UINT8 Mask;     // The number of bits expressed as a mask\r
+} BIOS_VIDEO_COLOR_PLACEMENT;\r
+\r
+//\r
+// BIOS UGA Draw Graphical Mode Data\r
+//\r
+typedef struct {\r
+  UINT16                      VbeModeNumber;\r
+  UINT16                      BytesPerScanLine;\r
+  VOID                        *LinearFrameBuffer;\r
+  UINT32                      HorizontalResolution;\r
+  UINT32                      VerticalResolution;\r
+  UINT32                      ColorDepth;\r
+  UINT32                      RefreshRate;\r
+  UINT32                      BitsPerPixel;\r
+  BIOS_VIDEO_COLOR_PLACEMENT  Red;\r
+  BIOS_VIDEO_COLOR_PLACEMENT  Green;\r
+  BIOS_VIDEO_COLOR_PLACEMENT  Blue;\r
+} BIOS_VIDEO_MODE_DATA;\r
+\r
+//\r
+// BIOS UGA Device Structure\r
+//\r
+#define BIOS_VIDEO_DEV_SIGNATURE  SIGNATURE_32 ('B', 'V', 'M', 'p')\r
+\r
+typedef struct {\r
+  UINTN                                       Signature;\r
+  EFI_HANDLE                                  Handle;\r
+\r
+  //\r
+  // Consumed Protocols\r
+  //\r
+  EFI_PCI_IO_PROTOCOL                         *PciIo;\r
+  //EFI_LEGACY_BIOS_THUNK_PROTOCOL              *LegacyBios;\r
+\r
+  //\r
+  // Produced Protocols\r
+  //\r
+  EFI_UGA_DRAW_PROTOCOL                       UgaDraw;\r
+  EFI_VGA_MINI_PORT_PROTOCOL                  VgaMiniPort;\r
+\r
+  //\r
+  // General fields\r
+  //\r
+  EFI_EVENT                                   ExitBootServicesEvent;\r
+  BOOLEAN                                     VgaCompatible;\r
+  BOOLEAN                                     ProduceUgaDraw;\r
+\r
+  //\r
+  // UGA Draw related fields\r
+  //\r
+  BOOLEAN                                     HardwareNeedsStarting;\r
+  UINTN                                       CurrentMode;\r
+  UINTN                                       MaxMode;\r
+  BIOS_VIDEO_MODE_DATA                        *ModeData;\r
+  UINT8                                       *LineBuffer;\r
+  EFI_UGA_PIXEL                               *VbeFrameBuffer;\r
+  UINT8                                       *VgaFrameBuffer;\r
+\r
+  //\r
+  // VESA Bios Extensions related fields\r
+  //\r
+  UINTN                                       NumberOfPagesBelow1MB;    // Number of 4KB pages in PagesBelow1MB\r
+  EFI_PHYSICAL_ADDRESS                        PagesBelow1MB;            // Buffer for all VBE Information Blocks\r
+  VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK      *VbeInformationBlock;     // 0x200 bytes.  Must be allocated below 1MB\r
+  VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *VbeModeInformationBlock; // 0x100 bytes.  Must be allocated below 1MB\r
+  VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *VbeCrtcInformationBlock; // 59 bytes.  Must be allocated below 1MB\r
+  UINTN                                       VbeSaveRestorePages;      // Number of 4KB pages in VbeSaveRestoreBuffer\r
+  EFI_PHYSICAL_ADDRESS                        VbeSaveRestoreBuffer;     // Must be allocated below 1MB\r
+  //\r
+  // Status code\r
+  //\r
+  EFI_DEVICE_PATH_PROTOCOL                    *DevicePath;\r
+} BIOS_VIDEO_DEV;\r
+\r
+#define BIOS_VIDEO_DEV_FROM_UGA_DRAW_THIS(a)      CR (a, BIOS_VIDEO_DEV, UgaDraw, BIOS_VIDEO_DEV_SIGNATURE)\r
+\r
+#define BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS(a) CR (a, BIOS_VIDEO_DEV, VgaMiniPort, BIOS_VIDEO_DEV_SIGNATURE)\r
+\r
+//\r
+// Global Variables\r
+//\r
+extern EFI_DRIVER_BINDING_PROTOCOL   gBiosVideoDriverBinding;\r
+extern EFI_COMPONENT_NAME_PROTOCOL   gBiosVideoComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL  gBiosVideoComponentName2;\r
+\r
+//\r
+// Driver Binding Protocol functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+/*++\r
+  \r
+  Routine Description:\r
+\r
+    Supported.\r
+    \r
+  Arguments:\r
+\r
+  This - Pointer to driver binding protocol\r
+  Controller - Controller handle to connect\r
+  RemainingDevicePath - A pointer to the remaining portion of a device path\r
+    \r
+    \r
+  Returns:\r
+\r
+  EFI_STATUS - EFI_SUCCESS:This controller can be managed by this driver,\r
+               Otherwise, this controller cannot be managed by this driver\r
+  \r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+/*++\r
+  \r
+  Routine Description:\r
+\r
+    Install UGA Draw Protocol onto VGA device handles\r
+  \r
+  Arguments:\r
+\r
+  This - Pointer to driver binding protocol\r
+  Controller - Controller handle to connect\r
+  RemainingDevicePath - A pointer to the remaining portion of a device path\r
+    \r
+  Returns:\r
+\r
+    EFI_STATUS\r
+    \r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   Controller,\r
+  IN  UINTN                        NumberOfChildren,\r
+  IN  EFI_HANDLE                   *ChildHandleBuffer\r
+  )\r
+/*++\r
+  \r
+  Routine Description:\r
+\r
+    Stop.\r
+  \r
+  Arguments:\r
+\r
+  This - Pointer to driver binding protocol\r
+  Controller - Controller handle to connect\r
+  NumberOfChilren - Number of children handle created by this driver\r
+  ChildHandleBuffer - Buffer containing child handle created\r
+  \r
+  Returns:\r
+\r
+  EFI_SUCCESS - Driver disconnected successfully from controller\r
+  EFI_UNSUPPORTED - Cannot find BIOS_VIDEO_DEV structure\r
+  \r
+--*/\r
+;\r
+\r
+//\r
+// Private worker functions\r
+//\r
+EFI_STATUS\r
+BiosVideoCheckForVbe (\r
+  BIOS_VIDEO_DEV  *BiosVideoPrivate\r
+  )\r
+/*++\r
+  \r
+  Routine Description:\r
+\r
+  Check for VBE device   \r
+  \r
+  Arguments:\r
+  \r
+  BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure\r
+  \r
+  Returns:\r
+  \r
+  EFI_SUCCESS - VBE device found\r
+  \r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+BiosVideoCheckForVga (\r
+  BIOS_VIDEO_DEV  *BiosVideoPrivate\r
+  )\r
+/*++\r
+  \r
+  Routine Description:\r
+\r
+    Check for VGA device\r
+  \r
+  Arguments:\r
+  \r
+    BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure\r
+  \r
+  Returns:\r
+  \r
+    EFI_SUCCESS - Standard VGA device found\r
+  \r
+--*/\r
+;\r
+\r
+//\r
+// BIOS UGA Draw Protocol functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoUgaDrawGetMode (\r
+  IN  EFI_UGA_DRAW_PROTOCOL  *This,\r
+  OUT UINT32                 *HorizontalResolution,\r
+  OUT UINT32                 *VerticalResolution,\r
+  OUT UINT32                 *ColorDepth,\r
+  OUT UINT32                 *RefreshRate\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  UGA protocol interface to get video mode\r
+\r
+Arguments:\r
+\r
+  This                  - Pointer to UGA draw protocol instance\r
+  HorizontalResolution  - Horizontal Resolution, in pixels\r
+  VerticalResolution    - Vertical Resolution, in pixels\r
+  ColorDepth            - Bit number used to represent color value of a pixel \r
+  RefreshRate           - Refresh rate, in Hertz\r
+\r
+Returns:\r
+\r
+  EFI_DEVICE_ERROR - Hardware need starting\r
+  EFI_INVALID_PARAMETER - Invalid parameter passed in\r
+  EFI_SUCCESS - Video mode query successfully\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoUgaDrawSetMode (\r
+  IN  EFI_UGA_DRAW_PROTOCOL  *This,\r
+  IN  UINT32                 HorizontalResolution,\r
+  IN  UINT32                 VerticalResolution,\r
+  IN  UINT32                 ColorDepth,\r
+  IN  UINT32                 RefreshRate\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  UGA draw protocol interface to set video mode\r
+\r
+Arguments:\r
+\r
+  This                  - Pointer to UGA draw protocol instance\r
+  HorizontalResolution  - Horizontal Resolution, in pixels\r
+  VerticalResolution    - Vertical Resolution, in pixels\r
+  ColorDepth            - Bit number used to represent color value of a pixel \r
+  RefreshRate           - Refresh rate, in Hertz\r
+\r
+Returns:\r
+\r
+  EFI_DEVICE_ERROR - Device error\r
+  EFI_SUCCESS - Video mode set successfully\r
+  EFI_UNSUPPORTED - Cannot support this video mode\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoUgaDrawVbeBlt (\r
+  IN  EFI_UGA_DRAW_PROTOCOL  *This,\r
+  IN  EFI_UGA_PIXEL          *BltBuffer, OPTIONAL\r
+  IN  EFI_UGA_BLT_OPERATION  BltOperation,\r
+  IN  UINTN                  SourceX,\r
+  IN  UINTN                  SourceY,\r
+  IN  UINTN                  DestinationX,\r
+  IN  UINTN                  DestinationY,\r
+  IN  UINTN                  Width,\r
+  IN  UINTN                  Height,\r
+  IN  UINTN                  Delta\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  UGA draw protocol instance to block transfer for VBE device\r
+\r
+Arguments:\r
+\r
+  This          - Pointer to UGA draw protocol instance\r
+  BltBuffer     - The data to transfer to screen\r
+  BltOperation  - The operation to perform\r
+  SourceX       - The X coordinate of the source for BltOperation\r
+  SourceY       - The Y coordinate of the source for BltOperation\r
+  DestinationX  - The X coordinate of the destination for BltOperation\r
+  DestinationY  - The Y coordinate of the destination for BltOperation\r
+  Width         - The width of a rectangle in the blt rectangle in pixels\r
+  Height        - The height of a rectangle in the blt rectangle in pixels\r
+  Delta         - Not used for EfiUgaVideoFill and EfiUgaVideoToVideo operation.\r
+                  If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
+                  If a subrectangle of the BltBuffer is used, then Delta represents \r
+                  the number of bytes in a row of the BltBuffer.\r
+\r
+Returns:\r
+\r
+  EFI_INVALID_PARAMETER - Invalid parameter passed in\r
+  EFI_SUCCESS - Blt operation success\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoUgaDrawVgaBlt (\r
+  IN  EFI_UGA_DRAW_PROTOCOL  *This,\r
+  IN  EFI_UGA_PIXEL          *BltBuffer, OPTIONAL\r
+  IN  EFI_UGA_BLT_OPERATION  BltOperation,\r
+  IN  UINTN                  SourceX,\r
+  IN  UINTN                  SourceY,\r
+  IN  UINTN                  DestinationX,\r
+  IN  UINTN                  DestinationY,\r
+  IN  UINTN                  Width,\r
+  IN  UINTN                  Height,\r
+  IN  UINTN                  Delta\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  UGA draw protocol instance to block transfer for VGA device\r
+\r
+Arguments:\r
+\r
+  This          - Pointer to UGA draw protocol instance\r
+  BltBuffer     - The data to transfer to screen\r
+  BltOperation  - The operation to perform\r
+  SourceX       - The X coordinate of the source for BltOperation\r
+  SourceY       - The Y coordinate of the source for BltOperation\r
+  DestinationX  - The X coordinate of the destination for BltOperation\r
+  DestinationY  - The Y coordinate of the destination for BltOperation\r
+  Width         - The width of a rectangle in the blt rectangle in pixels\r
+  Height        - The height of a rectangle in the blt rectangle in pixels\r
+  Delta         - Not used for EfiUgaVideoFill and EfiUgaVideoToVideo operation.\r
+                  If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
+                  If a subrectangle of the BltBuffer is used, then Delta represents \r
+                  the number of bytes in a row of the BltBuffer.\r
+\r
+Returns:\r
+\r
+  EFI_INVALID_PARAMETER - Invalid parameter passed in\r
+  EFI_SUCCESS - Blt operation success\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// BIOS VGA Mini Port Protocol functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoVgaMiniPortSetMode (\r
+  IN  EFI_VGA_MINI_PORT_PROTOCOL  *This,\r
+  IN  UINTN                       ModeNumber\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  VgaMiniPort protocol interface to set mode\r
+\r
+Arguments:\r
+\r
+  This        - Pointer to VgaMiniPort protocol instance\r
+  ModeNumber  - The index of the mode\r
+\r
+Returns:\r
+\r
+  EFI_UNSUPPORTED - The requested mode is not supported\r
+  EFI_SUCCESS - The requested mode is set successfully\r
+\r
+--*/\r
+;\r
+\r
+\r
+BOOLEAN\r
+BiosVideoIsVga (\r
+  IN  EFI_PCI_IO_PROTOCOL       *PciIo\r
+  )\r
+;\r
+\r
+\r
+//\r
+// Standard VGA Definitions\r
+//\r
+#define VGA_HORIZONTAL_RESOLUTION                         640\r
+#define VGA_VERTICAL_RESOLUTION                           480\r
+#define VGA_NUMBER_OF_BIT_PLANES                          4\r
+#define VGA_PIXELS_PER_BYTE                               8\r
+#define VGA_BYTES_PER_SCAN_LINE                           (VGA_HORIZONTAL_RESOLUTION / VGA_PIXELS_PER_BYTE)\r
+#define VGA_BYTES_PER_BIT_PLANE                           (VGA_VERTICAL_RESOLUTION * VGA_BYTES_PER_SCAN_LINE)\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER          0x3ce\r
+#define VGA_GRAPHICS_CONTROLLER_DATA_REGISTER             0x3cf\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_SET_RESET_REGISTER        0x00\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_ENABLE_SET_RESET_REGISTER 0x01\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_COLOR_COMPARE_REGISTER    0x02\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER      0x03\r
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE          0x00\r
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_AND              0x08\r
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_OR               0x10\r
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_XOR              0x18\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER  0x04\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_MODE_REGISTER             0x05\r
+#define VGA_GRAPHICS_CONTROLLER_READ_MODE_0               0x00\r
+#define VGA_GRAPHICS_CONTROLLER_READ_MODE_1               0x08\r
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0              0x00\r
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1              0x01\r
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2              0x02\r
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_3              0x03\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_MISCELLANEOUS_REGISTER    0x06\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_COLOR_DONT_CARE_REGISTER  0x07\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER         0x08\r
+\r
+#endif\r
diff --git a/DuetPkg/BiosVideoThunkDxe/BiosVideo.inf b/DuetPkg/BiosVideoThunkDxe/BiosVideo.inf
new file mode 100644 (file)
index 0000000..d8ac37f
--- /dev/null
@@ -0,0 +1,52 @@
+#/*++\r
+# \r
+# Copyright (c) 2006, Intel Corporation                                                         \r
+# All rights reserved. This program and the accompanying materials                          \r
+# are licensed and made available under the terms and conditions of the BSD License         \r
+# which accompanies this distribution.  The full text of the license may be found at        \r
+# http://opensource.org/licenses/bsd-license.php                                            \r
+#                                                                                           \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+#\r
+#  Module Name:\r
+#\r
+#    BiosVideo.inf\r
+#\r
+#  Abstract:\r
+#\r
+#    Component description file for BIOS VGA Miniport module.\r
+#\r
+#--*/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = BiosVideo\r
+  FILE_GUID                      = 29CF55F8-B675-4f5d-8F2F-B87A3ECFD063\r
+  MODULE_TYPE                    = UEFI_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = BiosVideoDriverEntryPoint\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
+  DuetPkg/DuetPkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiLib\r
+  DebugLib\r
+  UefiBootServicesTableLib\r
+  BaseMemoryLib\r
+  UefiDriverEntryPoint\r
+  \r
+[Sources.common]\r
+  BiosVideo.h\r
+  BiosVideo.c\r
+  ComponentName.c\r
+  VesaBiosExtensions.h\r
+\r
+[Protocols]\r
+  gEfiPciIoProtocolGuid\r
+  gEfiVgaMiniPortProtocolGuid\r
+  gEfiLegacy8259ProtocolGuid\r
diff --git a/DuetPkg/BiosVideoThunkDxe/ComponentName.c b/DuetPkg/BiosVideoThunkDxe/ComponentName.c
new file mode 100644 (file)
index 0000000..fea56d7
--- /dev/null
@@ -0,0 +1,166 @@
+/*++\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  ComponentName.c\r
+\r
+Abstract:\r
+\r
+--*/\r
+\r
+#include "BiosVideo.h"\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  );\r
+  \r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,\r
+  IN  EFI_HANDLE                                      ControllerHandle,\r
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,\r
+  IN  CHAR8                                           *Language,\r
+  OUT CHAR16                                          **ControllerName\r
+  );\r
+    \r
+//\r
+// EFI Component Name Protocol\r
+//\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gBiosVideoComponentName = {\r
+  BiosVideoComponentNameGetDriverName,\r
+  BiosVideoComponentNameGetControllerName,\r
+  "eng"\r
+};\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2 = {\r
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosVideoComponentNameGetDriverName,\r
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosVideoComponentNameGetControllerName,\r
+  "en"\r
+};\r
+\r
+\r
+static EFI_UNICODE_STRING_TABLE mBiosVideoDriverNameTable[] = {\r
+  {\r
+    "eng;en",\r
+    L"BIOS[INT10] Video Driver"\r
+  },\r
+  {\r
+    NULL,\r
+    NULL\r
+  }\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Retrieves a Unicode string that is the user readable name of the EFI Driver.\r
+\r
+  Arguments:\r
+    This       - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+    Language   - A pointer to a three character ISO 639-2 language identifier.\r
+                 This is the language of the driver name that that the caller \r
+                 is requesting, and it must match one of the languages specified\r
+                 in SupportedLanguages.  The number of languages supported by a \r
+                 driver is up to the driver writer.\r
+    DriverName - A pointer to the Unicode string to return.  This Unicode string\r
+                 is the name of the driver specified by This in the language \r
+                 specified by Language.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The Unicode string for the Driver specified by This\r
+                            and the language specified by Language was returned \r
+                            in DriverName.\r
+    EFI_INVALID_PARAMETER - Language is NULL.\r
+    EFI_INVALID_PARAMETER - DriverName is NULL.\r
+    EFI_UNSUPPORTED       - The driver specified by This does not support the \r
+                            language specified by Language.\r
+\r
+--*/\r
+{\r
+  return LookupUnicodeString2 (\r
+           Language,\r
+           This->SupportedLanguages,\r
+           mBiosVideoDriverNameTable,\r
+           DriverName,\r
+           (BOOLEAN)(This == &gBiosVideoComponentName)\r
+           );          \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,\r
+  IN  EFI_HANDLE                                      ControllerHandle,\r
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,\r
+  IN  CHAR8                                           *Language,\r
+  OUT CHAR16                                          **ControllerName\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Retrieves a Unicode string that is the user readable name of the controller\r
+    that is being managed by an EFI Driver.\r
+\r
+  Arguments:\r
+    This             - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+    ControllerHandle - The handle of a controller that the driver specified by \r
+                       This is managing.  This handle specifies the controller \r
+                       whose name is to be returned.\r
+    ChildHandle      - The handle of the child controller to retrieve the name \r
+                       of.  This is an optional parameter that may be NULL.  It \r
+                       will be NULL for device drivers.  It will also be NULL \r
+                       for a bus drivers that wish to retrieve the name of the \r
+                       bus controller.  It will not be NULL for a bus driver \r
+                       that wishes to retrieve the name of a child controller.\r
+    Language         - A pointer to a three character ISO 639-2 language \r
+                       identifier.  This is the language of the controller name \r
+                       that that the caller is requesting, and it must match one\r
+                       of the languages specified in SupportedLanguages.  The \r
+                       number of languages supported by a driver is up to the \r
+                       driver writer.\r
+    ControllerName   - A pointer to the Unicode string to return.  This Unicode\r
+                       string is the name of the controller specified by \r
+                       ControllerHandle and ChildHandle in the language specified\r
+                       by Language from the point of view of the driver specified\r
+                       by This. \r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The Unicode string for the user readable name in the \r
+                            language specified by Language for the driver \r
+                            specified by This was returned in DriverName.\r
+    EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.\r
+    EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.\r
+    EFI_INVALID_PARAMETER - Language is NULL.\r
+    EFI_INVALID_PARAMETER - ControllerName is NULL.\r
+    EFI_UNSUPPORTED       - The driver specified by This is not currently managing \r
+                            the controller specified by ControllerHandle and \r
+                            ChildHandle.\r
+    EFI_UNSUPPORTED       - The driver specified by This does not support the \r
+                            language specified by Language.\r
+\r
+--*/\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
diff --git a/DuetPkg/BiosVideoThunkDxe/VesaBiosExtensions.h b/DuetPkg/BiosVideoThunkDxe/VesaBiosExtensions.h
new file mode 100644 (file)
index 0000000..7f128ad
--- /dev/null
@@ -0,0 +1,457 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  VesaBiosExtensions.h\r
+\r
+Abstract:\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _VESA_BIOS_EXTENSIONS_H\r
+#define _VESA_BIOS_EXTENSIONS_H\r
+\r
+//\r
+// Turn on byte packing of data structures\r
+//\r
+#pragma pack(1)\r
+//\r
+// VESA BIOS Extensions status codes\r
+//\r
+#define VESA_BIOS_EXTENSIONS_STATUS_SUCCESS 0x004f\r
+\r
+//\r
+// VESA BIOS Extensions Services\r
+//\r
+#define VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION  0x4f00\r
+\r
+/*++\r
+\r
+  Routine Description:\r
+    Function 00 : Return Controller Information\r
+\r
+  Arguments:\r
+    Inputs:\r
+      AX    = 0x4f00\r
+      ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK structure\r
+    Outputs:\r
+      AX    = Return Status\r
+\r
+--*/\r
+#define VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION  0x4f01\r
+\r
+/*++\r
+\r
+  Routine Description:\r
+    Function 01 : Return Mode Information\r
+\r
+  Arguments:\r
+    Inputs:\r
+      AX    = 0x4f01\r
+      CX    = Mode Number\r
+      ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK structure\r
+    Outputs:\r
+      AX    = Return Status\r
+\r
+--*/\r
+#define VESA_BIOS_EXTENSIONS_SET_MODE 0x4f02\r
+\r
+/*++\r
+\r
+  Routine Description:\r
+    Function 02 : Set Mode\r
+\r
+  Arguments:\r
+    Inputs:\r
+      AX    = 0x4f02\r
+      BX    = Desired mode to set\r
+        D0-D8   = Mode Number\r
+        D9-D10  = Reserved (must be 0)\r
+        D11     = 0 - Use current default refresh rate\r
+                = 1 - Use user specfieid CRTC values for refresh rate\r
+        D12-D13 = Reserved (must be 0)\r
+        D14     = 0 - Use windowed frame buffer model\r
+                = 1 - Use linear/flat frame buffer model\r
+        D15     = 0 - Clear display memory\r
+                = 1 - Don't clear display memory\r
+      ES:DI = Pointer to buffer to the VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK structure\r
+    Outputs:\r
+      AX    = Return Status\r
+\r
+--*/\r
+#define VESA_BIOS_EXTENSIONS_RETURN_CURRENT_MODE  0x4f03\r
+\r
+/*++\r
+\r
+  Routine Description:\r
+    Function 03 : Return Current Mode\r
+\r
+  Arguments:\r
+    Inputs:\r
+      AX    = 0x4f03\r
+    Outputs:\r
+      AX    = Return Status\r
+      BX    = Current mode\r
+        D0-D13  = Mode Number\r
+        D14     = 0 - Windowed frame buffer model\r
+                = 1 - Linear/flat frame buffer model\r
+        D15     = 0 - Memory cleared at last mode set\r
+                = 1 - Memory not cleared at last mode set\r
+\r
+--*/\r
+#define VESA_BIOS_EXTENSIONS_SAVE_RESTORE_STATE 0x4f04\r
+\r
+/*++\r
+\r
+  Routine Description:\r
+    Function 04 : Save/Restore State\r
+\r
+  Arguments:\r
+    Inputs:\r
+      AX    = 0x4f03\r
+      DL    = 0x00 - Return Save/Restore State buffer size\r
+            = 0x01 - Save State\r
+            = 0x02 - Restore State\r
+      CX    = Requested Status\r
+        D0  = Save/Restore controller hardware state\r
+        D1  = Save/Restore BIOS data state\r
+        D2  = Save/Restore DAC state\r
+        D3  = Save/Restore Regsiter state\r
+      ES:BX = Pointer to buffer if DL=1 or DL=2\r
+    Outputs:\r
+      AX    = Return Status\r
+      BX    = Number of 64 byte blocks to hold the state buffer if DL=0\r
+\r
+--*/\r
+#define VESA_BIOS_EXTENSIONS_EDID  0x4f15\r
+\r
+/*++\r
+\r
+  Routine Description:\r
+    Function 15 : implement VBE/DDC service\r
+\r
+  Arguments:\r
+    Inputs:\r
+      AX    = 0x4f15\r
+      BL    = 0x00 - Report VBE/DDC Capabilities\r
+      CX    = 0x00 - Controller unit number (00 = primary controller)\r
+      ES:DI = Null pointer, must be 0:0 in version 1.0\r
+    Outputs:\r
+      AX    = Return Status\r
+      BH    = Approx. time in seconds, rounded up, to transfer one EDID block(128 bytes)\r
+      BL    = DDC level supported\r
+        D0  = 0 DDC1 not supported\r
+            = 1 DDC1 supported\r
+        D1  = 0 DDC2 not supported\r
+            = 1 DDC2 supported\r
+        D2  = 0 Screen not blanked during data transfer\r
+            = 1 Screen blanked during data transfer\r
+\r
+    Inputs:\r
+      AX    = 0x4f15\r
+      BL    = 0x01 - Read EDID\r
+      CX    = 0x00 - Controller unit number (00 = primary controller)\r
+      DX    = 0x00 - EDID block number\r
+      ES:DI = Pointer to buffer in which the EDID block is returned\r
+    Outputs:\r
+      AX    = Return Status\r
+--*/\r
+\r
+//\r
+// Timing data from EDID data block\r
+//\r
+#define VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE                    128\r
+#define VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER 17\r
+\r
+typedef struct {\r
+  UINT16  HorizontalResolution;\r
+  UINT16  VerticalResolution;\r
+  UINT16  RefreshRate;\r
+} VESA_BIOS_EXTENSIONS_EDID_TIMING;\r
+\r
+typedef struct {\r
+  UINT32  ValidNumber;\r
+  UINT32  Key[VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER];\r
+} VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING;\r
+\r
+typedef struct {\r
+  UINT8   Header[8];                        //EDID header "00 FF FF FF FF FF FF 00"\r
+  UINT16  ManufactureName;                  //EISA 3-character ID\r
+  UINT16  ProductCode;                      //Vendor assigned code\r
+  UINT32  SerialNumber;                     //32-bit serial number\r
+  UINT8   WeekOfManufacture;                //Week number\r
+  UINT8   YearOfManufacture;                //Year\r
+  UINT8   EdidVersion;                      //EDID Structure Version\r
+  UINT8   EdidRevision;                     //EDID Structure Revision\r
+  UINT8   VideoInputDefinition;\r
+  UINT8   MaxHorizontalImageSize;           //cm\r
+  UINT8   MaxVerticalImageSize;             //cm\r
+  UINT8   DisplayTransferCharacteristic;\r
+  UINT8   FeatureSupport;\r
+  UINT8   RedGreenLowBits;                  //Rx1 Rx0 Ry1 Ry0 Gx1 Gx0 Gy1Gy0\r
+  UINT8   BlueWhiteLowBits;                 //Bx1 Bx0 By1 By0 Wx1 Wx0 Wy1 Wy0\r
+  UINT8   RedX;                             //Red-x Bits 9 - 2\r
+  UINT8   RedY;                             //Red-y Bits 9 - 2\r
+  UINT8   GreenX;                           //Green-x Bits 9 - 2\r
+  UINT8   GreenY;                           //Green-y Bits 9 - 2\r
+  UINT8   BlueX;                            //Blue-x Bits 9 - 2\r
+  UINT8   BlueY;                            //Blue-y Bits 9 - 2\r
+  UINT8   WhiteX;                           //White-x Bits 9 - 2\r
+  UINT8   WhiteY;                           //White-x Bits 9 - 2\r
+  UINT8   EstablishedTimings[3];\r
+  UINT8   StandardTimingIdentification[16];\r
+  UINT8   DetailedTimingDescriptions[72];\r
+  UINT8   ExtensionFlag;                    //Number of (optional) 128-byte EDID extension blocks to follow\r
+  UINT8   Checksum;\r
+} VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK;\r
+\r
+//\r
+// Super VGA Information Block\r
+//\r
+typedef struct {\r
+  UINT32  VESASignature;      // 'VESA' 4 byte signature\r
+  UINT16  VESAVersion;        // VBE version number\r
+  UINT32  OEMStringPtr;       // Pointer to OEM string\r
+  UINT32  Capabilities;       // Capabilities of video card\r
+  UINT32  VideoModePtr;       // Pointer to an array of 16-bit supported modes values terminated by 0xFFFF\r
+  UINT16  TotalMemory;        // Number of 64kb memory blocks\r
+  UINT16  OemSoftwareRev;     // VBE implementation Software revision\r
+  UINT32  OemVendorNamePtr;   // VbeFarPtr to Vendor Name String\r
+  UINT32  OemProductNamePtr;  // VbeFarPtr to Product Name String\r
+  UINT32  OemProductRevPtr;   // VbeFarPtr to Product Revision String\r
+  UINT8   Reserved[222];      // Reserved for VBE implementation scratch area\r
+  UINT8   OemData[256];       // Data area for OEM strings.  Pad to 512 byte block size\r
+} VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK;\r
+\r
+//\r
+// Super VGA Information Block VESASignature values\r
+//\r
+#define VESA_BIOS_EXTENSIONS_VESA_SIGNATURE SIGNATURE_32 ('V', 'E', 'S', 'A')\r
+#define VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE SIGNATURE_32 ('V', 'B', 'E', '2')\r
+\r
+//\r
+// Super VGA Information Block VESAVersion values\r
+//\r
+#define VESA_BIOS_EXTENSIONS_VERSION_1_2  0x0102\r
+#define VESA_BIOS_EXTENSIONS_VERSION_2_0  0x0200\r
+#define VESA_BIOS_EXTENSIONS_VERSION_3_0  0x0300\r
+\r
+//\r
+// Super VGA Information Block Capabilities field bit defintions\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_8_BIT_DAC 0x01  // 0: DAC width is fixed at 6 bits/color\r
+// 1: DAC width switchable to 8 bits/color\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_VGA 0x02  // 0: Controller is VGA compatible\r
+// 1: Controller is not VGA compatible\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_NORMAL_RAMDAC 0x04  // 0: Normal RAMDAC operation\r
+// 1: Use blank bit in function 9 to program RAMDAC\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_STEREOSCOPIC  0x08  // 0: No hardware stereoscopic signal support\r
+// 1: Hardware stereoscopic signal support\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_VESA_EVC  0x10  // 0: Stero signaling supported via external VESA stereo connector\r
+// 1: Stero signaling supported via VESA EVC connector\r
+//\r
+// Super VGA mode number bite field definitions\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA 0x0100  // 0: Not a VESA defined VBE mode\r
+// 1: A VESA defined VBE mode\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_REFRESH_CONTROL_USER 0x0800  // 0: Use current BIOS default referesh rate\r
+// 1: Use the user specified CRTC values for refresh rate\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER  0x4000  // 0: Use a banked/windowed frame buffer\r
+// 1: Use a linear/flat frame buffer\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_PRESERVE_MEMORY  0x8000  // 0: Clear display memory\r
+// 1: Preseve display memory\r
+//\r
+// Super VGA Information Block mode list terminator value\r
+//\r
+#define VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST 0xffff\r
+\r
+//\r
+// Window Function\r
+//\r
+typedef\r
+VOID\r
+(*VESA_BIOS_EXTENSIONS_WINDOW_FUNCTION) (\r
+  VOID\r
+  );\r
+\r
+//\r
+// Super VGA Mode Information Block\r
+//\r
+typedef struct {\r
+  //\r
+  // Manadory fields for all VESA Bios Extensions revisions\r
+  //\r
+  UINT16                                ModeAttributes;   // Mode attributes\r
+  UINT8                                 WinAAttributes;   // Window A attributes\r
+  UINT8                                 WinBAttributes;   // Window B attributes\r
+  UINT16                                WinGranularity;   // Window granularity in k\r
+  UINT16                                WinSize;          // Window size in k\r
+  UINT16                                WinASegment;      // Window A segment\r
+  UINT16                                WinBSegment;      // Window B segment\r
+  UINT32                                WindowFunction;   // Pointer to window function\r
+  UINT16                                BytesPerScanLine; // Bytes per scanline\r
+  //\r
+  // Manadory fields for VESA Bios Extensions 1.2 and above\r
+  //\r
+  UINT16                                XResolution;          // Horizontal resolution\r
+  UINT16                                YResolution;          // Vertical resolution\r
+  UINT8                                 XCharSize;            // Character cell width\r
+  UINT8                                 YCharSize;            // Character cell height\r
+  UINT8                                 NumberOfPlanes;       // Number of memory planes\r
+  UINT8                                 BitsPerPixel;         // Bits per pixel\r
+  UINT8                                 NumberOfBanks;        // Number of CGA style banks\r
+  UINT8                                 MemoryModel;          // Memory model type\r
+  UINT8                                 BankSize;             // Size of CGA style banks\r
+  UINT8                                 NumberOfImagePages;   // Number of images pages\r
+  UINT8                                 Reserved1;            // Reserved\r
+  UINT8                                 RedMaskSize;          // Size of direct color red mask\r
+  UINT8                                 RedFieldPosition;     // Bit posn of lsb of red mask\r
+  UINT8                                 GreenMaskSize;        // Size of direct color green mask\r
+  UINT8                                 GreenFieldPosition;   // Bit posn of lsb of green mask\r
+  UINT8                                 BlueMaskSize;         // Size of direct color blue mask\r
+  UINT8                                 BlueFieldPosition;    // Bit posn of lsb of blue mask\r
+  UINT8                                 RsvdMaskSize;         // Size of direct color res mask\r
+  UINT8                                 RsvdFieldPosition;    // Bit posn of lsb of res mask\r
+  UINT8                                 DirectColorModeInfo;  // Direct color mode attributes\r
+  //\r
+  // Manadory fields for VESA Bios Extensions 2.0 and above\r
+  //\r
+  UINT32                                PhysBasePtr;  // Physical Address for flat memory frame buffer\r
+  UINT32                                Reserved2;    // Reserved\r
+  UINT16                                Reserved3;    // Reserved\r
+  //\r
+  // Manadory fields for VESA Bios Extensions 3.0 and above\r
+  //\r
+  UINT16                                LinBytesPerScanLine;    // Bytes/scan line for linear modes\r
+  UINT8                                 BnkNumberOfImagePages;  // Number of images for banked modes\r
+  UINT8                                 LinNumberOfImagePages;  // Number of images for linear modes\r
+  UINT8                                 LinRedMaskSize;         // Size of direct color red mask (linear mode)\r
+  UINT8                                 LinRedFieldPosition;    // Bit posiiton of lsb of red mask (linear modes)\r
+  UINT8                                 LinGreenMaskSize;       // Size of direct color green mask (linear mode)\r
+  UINT8                                 LinGreenFieldPosition;  // Bit posiiton of lsb of green mask (linear modes)\r
+  UINT8                                 LinBlueMaskSize;        // Size of direct color blue mask (linear mode)\r
+  UINT8                                 LinBlueFieldPosition;   // Bit posiiton of lsb of blue mask (linear modes)\r
+  UINT8                                 LinRsvdMaskSize;        // Size of direct color reserved mask (linear mode)\r
+  UINT8                                 LinRsvdFieldPosition;   // Bit posiiton of lsb of reserved mask (linear modes)\r
+  UINT32                                MaxPixelClock;          // Maximum pixel clock (in Hz) for graphics mode\r
+  UINT8                                 Pad[190];               // Pad to 256 byte block size\r
+} VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK;\r
+\r
+//\r
+// Super VGA Mode Information Block ModeAttributes field bit defintions\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_HARDWARE  0x0001  // 0: Mode not supported in handware\r
+// 1: Mode supported in handware\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_TTY 0x0004  // 0: TTY Output functions not supported by BIOS\r
+// 1: TTY Output functions supported by BIOS\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR 0x0008  // 0: Monochrome mode\r
+// 1: Color mode\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS  0x0010  // 0: Text mode\r
+// 1: Graphics mode\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_VGA 0x0020  // 0: VGA compatible mode\r
+// 1: Not a VGA compatible mode\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_WINDOWED  0x0040  // 0: VGA compatible windowed memory mode\r
+// 1: Not a VGA compatible windowed memory mode\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER 0x0080  // 0: No linear fram buffer mode available\r
+// 1: Linear frame buffer mode available\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DOUBLE_SCAN 0x0100  // 0: No double scan mode available\r
+// 1: Double scan mode available\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_INTERLACED  0x0200  // 0: No interlaced mode is available\r
+// 1: Interlaced mode is available\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NO_TRIPPLE_BUFFER 0x0400  // 0: No hardware triple buffer mode support available\r
+// 1: Hardware triple buffer mode support available\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_STEREOSCOPIC  0x0800  // 0: No hardware steroscopic display support\r
+// 1: Hardware steroscopic display support\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DUAL_DISPLAY  0x1000  // 0: No dual display start address support\r
+// 1: Dual display start address support\r
+//\r
+// Super VGA Mode Information Block WinAAttribite/WinBAttributes field bit defintions\r
+//\r
+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_RELOCATABLE 0x01  // 0: Single non-relocatable window only\r
+// 1: Relocatable window(s) are supported\r
+//\r
+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_READABLE  0x02  // 0: Window is not readable\r
+// 1: Window is readable\r
+//\r
+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_WRITABLE  0x04  // 0: Window is not writable\r
+// 1: Window is writable\r
+//\r
+// Super VGA Mode Information Block DirectColorMode field bit defintions\r
+//\r
+#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_PROG_COLOR_RAMP  0x01  // 0: Color ram is fixed\r
+// 1: Color ramp is programmable\r
+//\r
+#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_RSVD_USABLE  0x02  // 0: Bits in Rsvd field are reserved\r
+// 1: Bits in Rsdv field are usable\r
+//\r
+// Super VGA Memory Models\r
+//\r
+typedef enum {\r
+  memPL = 3,  // Planar memory model\r
+  memPK = 4,  // Packed pixel memory model\r
+  memRGB= 6,  // Direct color RGB memory model\r
+  memYUV= 7,  // Direct color YUV memory model\r
+} VESA_BIOS_EXTENSIONS_MEMORY_MODELS;\r
+\r
+//\r
+// Super VGA CRTC Information Block\r
+//\r
+typedef struct {\r
+  UINT16  HorizontalTotal;      // Horizontal total in pixels\r
+  UINT16  HorizontalSyncStart;  // Horizontal sync start in pixels\r
+  UINT16  HorizontalSyncEnd;    // Horizontal sync end in pixels\r
+  UINT16  VericalTotal;         // Vertical total in pixels\r
+  UINT16  VericalSyncStart;     // Vertical sync start in pixels\r
+  UINT16  VericalSyncEnd;       // Vertical sync end in pixels\r
+  UINT8   Flags;                // Flags (Interlaced/DoubleScan/etc).\r
+  UINT32  PixelClock;           // Pixel clock in units of Hz\r
+  UINT16  RefreshRate;          // Refresh rate in units of 0.01 Hz\r
+  UINT8   Reserved[40];         // Pad\r
+} VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK;\r
+\r
+#define VESA_BIOS_EXTENSIONS_CRTC_FLAGS_DOUBLE_SCAN 0x01  // 0: Graphics mode is not souble scanned\r
+// 1: Graphics mode is double scanned\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CRTC_FLAGSINTERLACED 0x02  // 0: Graphics mode is not interlaced\r
+// 1: Graphics mode is interlaced\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CRTC_HORIZONTAL_SYNC_NEGATIVE  0x04  // 0: Horizontal sync polarity is positive(+)\r
+// 0: Horizontal sync polarity is negative(-)\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CRTC_VERITICAL_SYNC_NEGATIVE 0x08  // 0: Verical sync polarity is positive(+)\r
+// 0: Verical sync polarity is negative(-)\r
+//\r
+// Turn off byte packing of data structures\r
+//\r
+#pragma pack()\r
+\r
+#endif\r
index c5d86384660a3801d99828d6a55a7744a62a1004..6887613164bfeb38ecc97e4570e05a84ed2eee6a 100644 (file)
   MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf\r
   MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf\r
   \r
+  # Bios Thunk\r
+  DuetPkg/BiosVideoThunkDxe/BiosVideo.inf\r
+  \r
 [Components.IA32]  \r
   DuetPkg/BootSector/BootSector.inf\r
   \r
index b602e9f014e359d7cb1e9507e5f876da957b99c7..74db92f076abfb673789eb93b756ce1d74dde90b 100644 (file)
@@ -116,6 +116,7 @@ INF  IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf
 INF  MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf\r
 INF  MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf\r
 INF  MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf\r
+INF  DuetPkg/BiosVideoThunkDxe/BiosVideo.inf\r
 \r
 FILE DRIVER = 961578FE-B6B7-44c3-AF35-6BC705CD2B1F {\r
   SECTION PE32 = FatBinPkg/EnhancedFatDxe/Ia32/Fat.efi\r