]> git.proxmox.com Git - mirror_edk2.git/blobdiff - CorebootPayloadPkg/FbGop/FbGop.c
Pkg-Module: CorebootPayloadPkg
[mirror_edk2.git] / CorebootPayloadPkg / FbGop / FbGop.c
diff --git a/CorebootPayloadPkg/FbGop/FbGop.c b/CorebootPayloadPkg/FbGop/FbGop.c
new file mode 100644 (file)
index 0000000..196efe8
--- /dev/null
@@ -0,0 +1,1532 @@
+/** @file\r
+  ConsoleOut Routines that speak VGA.\r
+\r
+Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution.  The\r
+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
+**/\r
+\r
+#include "FbGop.h"\r
+\r
+EFI_PIXEL_BITMASK  mPixelBitMask = {0x0000FF, 0x00FF00, 0xFF0000, 0x000000};\r
+\r
+//\r
+// Save controller attributes during first start\r
+//\r
+UINT64                         mOriginalPciAttributes;\r
+BOOLEAN                        mPciAttributesSaved = FALSE;\r
+\r
+\r
+//\r
+// EFI Driver Binding Protocol Instance\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL gFbGopDriverBinding = {\r
+  FbGopDriverBindingSupported,\r
+  FbGopDriverBindingStart,\r
+  FbGopDriverBindingStop,\r
+  0x3,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+//\r
+// Native resolution in EDID DetailedTiming[0]\r
+//\r
+UINT32    mNativeModeHorizontal;\r
+UINT32    mNativeModeVertical;\r
+\r
+/**\r
+  Supported.\r
+\r
+  @param  This                   Pointer to driver binding protocol\r
+  @param  Controller             Controller handle to connect\r
+  @param  RemainingDevicePath    A pointer to the remaining portion of a device\r
+                                 path\r
+\r
+  @retval EFI_STATUS             EFI_SUCCESS:This controller can be managed by this\r
+                                 driver, Otherwise, this controller cannot be\r
+                                 managed by this driver\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FbGopDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_PCI_IO_PROTOCOL       *PciIo;\r
+  PCI_TYPE00                Pci;\r
+  EFI_DEV_PATH              *Node;\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
+    return Status;\r
+  }\r
+\r
+  //\r
+  // See if this is a PCI Graphics Controller by looking at the Command register and\r
+  // Class Code Register\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
+    Status = EFI_UNSUPPORTED;\r
+    goto Done;\r
+  }\r
+\r
+  Status = EFI_UNSUPPORTED;\r
+  if (Pci.Hdr.ClassCode[2] == 0x03 || (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01)) {\r
+\r
+    Status = EFI_SUCCESS;\r
+    //\r
+    // If this is a graphics controller,\r
+    // go further check RemainingDevicePath validation\r
+    //\r
+    if (RemainingDevicePath != NULL) {\r
+      Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
+      //\r
+      // Check if RemainingDevicePath is the End of Device Path Node, \r
+      // if yes, return EFI_SUCCESS\r
+      //\r
+      if (!IsDevicePathEnd (Node)) {\r
+        //\r
+        // If RemainingDevicePath isn't the End of Device Path Node,\r
+        // check its validation\r
+        //\r
+        if (Node->DevPath.Type != ACPI_DEVICE_PATH ||\r
+            Node->DevPath.SubType != ACPI_ADR_DP ||\r
+            DevicePathNodeLength(&Node->DevPath) < sizeof(ACPI_ADR_DEVICE_PATH)) {\r
+          Status = EFI_UNSUPPORTED;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+Done:\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiPciIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Install Graphics Output Protocol onto VGA device handles.\r
+\r
+  @param  This                   Pointer to driver binding protocol\r
+  @param  Controller             Controller handle to connect\r
+  @param  RemainingDevicePath    A pointer to the remaining portion of a device\r
+                                 path\r
+\r
+  @return EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FbGopDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;\r
+  EFI_PCI_IO_PROTOCOL       *PciIo;  \r
+  UINT64                    Supports;\r
+\r
+  DEBUG ((EFI_D_INFO, "GOP START\n"));\r
+  \r
+  //\r
+  // Initialize local variables\r
+  //\r
+  PciIo            = NULL;\r
+  ParentDevicePath = NULL;\r
+\r
+  //\r
+  // Prepare for status code\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  Controller,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &ParentDevicePath\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Open the IO Abstraction(s) needed\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) && (Status != EFI_ALREADY_STARTED)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Save original PCI attributes\r
+  //\r
+  if (!mPciAttributesSaved) {\r
+    Status = PciIo->Attributes (\r
+                      PciIo,\r
+                      EfiPciIoAttributeOperationGet,\r
+                      0,\r
+                      &mOriginalPciAttributes\r
+                      );\r
+    \r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+    mPciAttributesSaved = TRUE;\r
+  }\r
+\r
+  //\r
+  // Get supported PCI attributes\r
+  //\r
+  Status = PciIo->Attributes (\r
+                    PciIo,\r
+                    EfiPciIoAttributeOperationSupported,\r
+                    0,\r
+                    &Supports\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  Supports &= (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);\r
+  if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto Done;\r
+  }  \r
+  \r
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+    EFI_PROGRESS_CODE,\r
+    EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE,\r
+    ParentDevicePath\r
+    );\r
+  //\r
+  // Enable the device and make sure VGA cycles are being forwarded to this VGA device\r
+  //\r
+  Status = PciIo->Attributes (\r
+             PciIo,\r
+             EfiPciIoAttributeOperationEnable,\r
+             EFI_PCI_DEVICE_ENABLE,\r
+             NULL\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+      EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT,\r
+      ParentDevicePath\r
+      );\r
+    goto Done;\r
+  }\r
+\r
+  if (RemainingDevicePath != NULL) {\r
+    if (IsDevicePathEnd (RemainingDevicePath)) {\r
+      //\r
+      // If RemainingDevicePath is the End of Device Path Node,\r
+      // don't create any child device and return EFI_SUCESS\r
+      Status = EFI_SUCCESS;\r
+      goto Done;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Create child handle and install GraphicsOutputProtocol on it\r
+  //\r
+  Status = FbGopChildHandleInstall (\r
+             This,\r
+             Controller,\r
+             PciIo,\r
+             NULL,\r
+             ParentDevicePath,\r
+             RemainingDevicePath\r
+             );\r
+  \r
+Done:\r
+  if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
+          \r
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+      EFI_PROGRESS_CODE,\r
+      EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE,\r
+      ParentDevicePath\r
+      );\r
+\r
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+      EFI_PROGRESS_CODE,\r
+      EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED,\r
+      ParentDevicePath\r
+      );\r
+    if (!HasChildHandle (Controller)) {\r
+      if (mPciAttributesSaved) {\r
+        //\r
+        // Restore original PCI attributes\r
+        //\r
+        PciIo->Attributes (\r
+                        PciIo,\r
+                        EfiPciIoAttributeOperationSet,\r
+                        mOriginalPciAttributes,\r
+                        NULL\r
+                        );\r
+      }\r
+    }\r
+    //\r
+    // Release PCI I/O Protocols on the controller handle.\r
+    //\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiPciIoProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Stop.\r
+\r
+  @param  This                   Pointer to driver binding protocol\r
+  @param  Controller             Controller handle to connect\r
+  @param  NumberOfChildren       Number of children handle created by this driver\r
+  @param  ChildHandleBuffer      Buffer containing child handle created\r
+\r
+  @retval EFI_SUCCESS            Driver disconnected successfully from controller\r
+  @retval EFI_UNSUPPORTED        Cannot find FB_VIDEO_DEV structure\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FbGopDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN  EFI_HANDLE                      Controller,\r
+  IN  UINTN                           NumberOfChildren,\r
+  IN  EFI_HANDLE                      *ChildHandleBuffer\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  BOOLEAN                      AllChildrenStopped;\r
+  UINTN                        Index;\r
+  EFI_PCI_IO_PROTOCOL          *PciIo;\r
+\r
+  AllChildrenStopped = TRUE;\r
+\r
+  if (NumberOfChildren == 0) {\r
+    //\r
+    // Close PCI I/O protocol on the controller handle\r
+    //\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiPciIoProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  for (Index = 0; Index < NumberOfChildren; Index++) {\r
+        \r
+    Status = EFI_SUCCESS;\r
+\r
+    FbGopChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      AllChildrenStopped = FALSE;\r
+    }\r
+  }\r
+\r
+  if (!AllChildrenStopped) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  if (!HasChildHandle (Controller)) {\r
+    if (mPciAttributesSaved) {\r
+      Status = gBS->HandleProtocol (\r
+                      Controller,\r
+                      &gEfiPciIoProtocolGuid,\r
+                      (VOID **) &PciIo\r
+                      );\r
+      ASSERT_EFI_ERROR (Status);\r
+      \r
+      //\r
+      // Restore original PCI attributes\r
+      //\r
+      Status = PciIo->Attributes (\r
+                        PciIo,\r
+                        EfiPciIoAttributeOperationSet,\r
+                        mOriginalPciAttributes,\r
+                        NULL\r
+                        );\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  }\r
+\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Install child handles if the Handle supports MBR format.\r
+\r
+  @param  This                   Calling context.\r
+  @param  ParentHandle           Parent Handle\r
+  @param  ParentPciIo            Parent PciIo interface\r
+  @param  ParentLegacyBios       Parent LegacyBios interface\r
+  @param  ParentDevicePath       Parent Device Path\r
+  @param  RemainingDevicePath    Remaining Device Path\r
+\r
+  @retval EFI_SUCCESS            If a child handle was added\r
+  @retval other                  A child handle was not added\r
+\r
+**/\r
+EFI_STATUS\r
+FbGopChildHandleInstall (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   ParentHandle,\r
+  IN  EFI_PCI_IO_PROTOCOL          *ParentPciIo,\r
+  IN  VOID                         *ParentLegacyBios,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS               Status;\r
+  FB_VIDEO_DEV            *FbGopPrivate;\r
+  PCI_TYPE00               Pci;\r
+  ACPI_ADR_DEVICE_PATH     AcpiDeviceNode;\r
+  BOOLEAN                  ProtocolInstalled;\r
+\r
+  //\r
+  // Allocate the private device structure for video device\r
+  //\r
+  FbGopPrivate = (FB_VIDEO_DEV *) AllocateZeroPool (\r
+                                                                                                                                                                       sizeof (FB_VIDEO_DEV)\r
+                                                                                                                                                                       );\r
+  if (NULL == FbGopPrivate) {\r
+               Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // See if this is a VGA compatible controller or not\r
+  //\r
+  Status = ParentPciIo->Pci.Read (\r
+                          ParentPciIo,\r
+                          EfiPciIoWidthUint32,\r
+                          0,\r
+                          sizeof (Pci) / sizeof (UINT32),\r
+                          &Pci\r
+                          );\r
+  if (EFI_ERROR (Status)) {\r
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+      EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,\r
+      ParentDevicePath\r
+      );\r
+    goto Done;\r
+  }\r
+  \r
+  //\r
+  // Initialize the child private structure\r
+  //\r
+  FbGopPrivate->Signature = FB_VIDEO_DEV_SIGNATURE;\r
+\r
+  //\r
+  // Fill in Graphics Output specific mode structures\r
+  //  \r
+  FbGopPrivate->ModeData              = NULL;\r
+    \r
+  FbGopPrivate->VbeFrameBuffer        = NULL;\r
+\r
+  FbGopPrivate->EdidDiscovered.SizeOfEdid  = 0;\r
+  FbGopPrivate->EdidDiscovered.Edid        = NULL;\r
+  FbGopPrivate->EdidActive.SizeOfEdid      = 0;\r
+  FbGopPrivate->EdidActive.Edid            = NULL;\r
+  \r
+  //\r
+  // Fill in the Graphics Output Protocol\r
+  //\r
+  FbGopPrivate->GraphicsOutput.QueryMode = FbGopGraphicsOutputQueryMode;\r
+  FbGopPrivate->GraphicsOutput.SetMode   = FbGopGraphicsOutputSetMode;\r
+\r
+\r
+  //\r
+  // Allocate buffer for Graphics Output Protocol mode information\r
+  //\r
+  FbGopPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool (\r
+                                             sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE)\r
+                                             );\r
+  if (NULL == FbGopPrivate->GraphicsOutput.Mode) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  FbGopPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (\r
+                                             sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)\r
+                                             );\r
+  if (NULL ==  FbGopPrivate->GraphicsOutput.Mode->Info) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.\r
+  //\r
+  if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) {\r
+    if (RemainingDevicePath == NULL) {\r
+      ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
+      AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
+      AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
+      AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
+      SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
+    \r
+      FbGopPrivate->GopDevicePath = AppendDevicePathNode (\r
+                                          ParentDevicePath,\r
+                                          (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
+                                          );\r
+    } else {\r
+      FbGopPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);\r
+    }\r
+    \r
+    //\r
+    // Creat child handle and device path protocol firstly\r
+    //\r
+    FbGopPrivate->Handle = NULL;\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    &FbGopPrivate->Handle,\r
+                    &gEfiDevicePathProtocolGuid,\r
+                    FbGopPrivate->GopDevicePath,\r
+                    NULL\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally\r
+  //\r
+  FbGopPrivate->PciIo                 = ParentPciIo;\r
+\r
+  //\r
+  // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output\r
+  //\r
+  Status = FbGopCheckForVbe (FbGopPrivate);\r
+  DEBUG ((EFI_D_INFO, "FbGopCheckForVbe - %r\n", Status));\r
+  \r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    //goto Done;    \r
+  }\r
+\r
+  ProtocolInstalled = FALSE;\r
+  \r
+  //\r
+  // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &FbGopPrivate->Handle,\r
+                  &gEfiGraphicsOutputProtocolGuid,\r
+                  &FbGopPrivate->GraphicsOutput,  \r
+                  &gEfiEdidDiscoveredProtocolGuid,\r
+                  &FbGopPrivate->EdidDiscovered,                                                    \r
+                  &gEfiEdidActiveProtocolGuid,\r
+                  &FbGopPrivate->EdidActive,                  \r
+                  NULL\r
+                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Open the Parent Handle for the child\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    ParentHandle,\r
+                    &gEfiPciIoProtocolGuid,\r
+                    (VOID **) &FbGopPrivate->PciIo,\r
+                    This->DriverBindingHandle,\r
+                    FbGopPrivate->Handle,\r
+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+    ProtocolInstalled = TRUE;\r
+  }\r
+  \r
+Done:\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Free private data structure\r
+    //\r
+    FbGopDeviceReleaseResource (FbGopPrivate);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Deregister an video child handle and free resources.\r
+\r
+  @param  This                   Protocol instance pointer.\r
+  @param  Controller             Video controller handle\r
+  @param  Handle                 Video child handle\r
+\r
+  @return EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+FbGopChildHandleUninstall (\r
+  EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  EFI_HANDLE                     Controller,\r
+  EFI_HANDLE                     Handle\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;  \r
+  FB_VIDEO_DEV                 *FbGopPrivate;\r
+  EFI_PCI_IO_PROTOCOL          *PciIo;\r
+\r
+  FbGopPrivate     = NULL;\r
+  GraphicsOutput   = NULL;\r
+  PciIo            = NULL;\r
+  Status           = EFI_UNSUPPORTED;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Handle,\r
+                  &gEfiGraphicsOutputProtocolGuid,\r
+                  (VOID **) &GraphicsOutput,\r
+                  This->DriverBindingHandle,\r
+                  Handle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+      FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);\r
+  }\r
+  \r
+  if (FbGopPrivate == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Close PCI I/O protocol that opened by child handle\r
+  //\r
+  Status = gBS->CloseProtocol (\r
+                  Controller,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  This->DriverBindingHandle,\r
+                  Handle\r
+                  );\r
+\r
+  //\r
+  // Uninstall protocols on child handle\r
+  //\r
+  Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                    FbGopPrivate->Handle,\r
+                    &gEfiDevicePathProtocolGuid,\r
+                    FbGopPrivate->GopDevicePath,\r
+                    &gEfiGraphicsOutputProtocolGuid,\r
+                    &FbGopPrivate->GraphicsOutput,\r
+                    NULL\r
+                    );\r
\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->OpenProtocol (\r
+           Controller,\r
+           &gEfiPciIoProtocolGuid,\r
+           (VOID **) &PciIo,\r
+           This->DriverBindingHandle,\r
+           Handle,\r
+           EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+           );\r
+    return Status;\r
+  }\r
+  \r
+  //\r
+  // Release all allocated resources\r
+  //\r
+  FbGopDeviceReleaseResource (FbGopPrivate);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Release resource for biso video instance.\r
+\r
+  @param  FbGopPrivate       Video child device private data structure\r
+\r
+**/\r
+VOID\r
+FbGopDeviceReleaseResource (\r
+  FB_VIDEO_DEV  *FbGopPrivate\r
+  )\r
+{\r
+  if (FbGopPrivate == NULL) {\r
+    return ;\r
+  }\r
+\r
+  //\r
+  // Release all the resourses occupied by the FB_VIDEO_DEV\r
+  //\r
+  \r
+  //\r
+  // Free VBE Frame Buffer\r
+  //\r
+  if (FbGopPrivate->VbeFrameBuffer != NULL) {\r
+    FreePool (FbGopPrivate->VbeFrameBuffer);\r
+  }\r
+  \r
+  //\r
+  // Free mode data\r
+  //\r
+  if (FbGopPrivate->ModeData != NULL) {\r
+    FreePool (FbGopPrivate->ModeData);\r
+  }  \r
+\r
+  //\r
+  // Free graphics output protocol occupied resource\r
+  //\r
+  if (FbGopPrivate->GraphicsOutput.Mode != NULL) {\r
+    if (FbGopPrivate->GraphicsOutput.Mode->Info != NULL) {\r
+        FreePool (FbGopPrivate->GraphicsOutput.Mode->Info);\r
+        FbGopPrivate->GraphicsOutput.Mode->Info = NULL;\r
+    }\r
+    FreePool (FbGopPrivate->GraphicsOutput.Mode);\r
+    FbGopPrivate->GraphicsOutput.Mode = NULL;\r
+  }  \r
+\r
+  if (FbGopPrivate->GopDevicePath!= NULL) {\r
+    FreePool (FbGopPrivate->GopDevicePath);\r
+  }\r
+\r
+  FreePool (FbGopPrivate);\r
+\r
+  return ;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Check if all video child handles have been uninstalled.\r
+\r
+  @param  Controller             Video controller handle\r
+\r
+  @return TRUE                   Child handles exist.\r
+  @return FALSE                  All video child handles have been uninstalled.\r
+\r
+**/\r
+BOOLEAN\r
+HasChildHandle (\r
+  IN EFI_HANDLE  Controller\r
+  )\r
+{\r
+  UINTN                                Index;\r
+  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY  *OpenInfoBuffer;\r
+  UINTN                                EntryCount;\r
+  BOOLEAN                              HasChild;\r
+  EFI_STATUS                           Status;\r
+\r
+  EntryCount = 0;\r
+  HasChild   = FALSE;\r
+  Status = gBS->OpenProtocolInformation (\r
+                  Controller,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  &OpenInfoBuffer,\r
+                  &EntryCount\r
+                  );\r
+  for (Index = 0; Index < EntryCount; Index++) {\r
+    if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
+      HasChild = TRUE;\r
+    }\r
+  }\r
+  \r
+  return HasChild;\r
+}\r
+\r
+/**\r
+  Check for VBE device.\r
+\r
+  @param  FbGopPrivate       Pointer to FB_VIDEO_DEV structure\r
+\r
+  @retval EFI_SUCCESS            VBE device found\r
+\r
+**/\r
+EFI_STATUS\r
+FbGopCheckForVbe (\r
+  IN OUT FB_VIDEO_DEV  *FbGopPrivate\r
+  )\r
+{\r
+  EFI_STATUS                             Status;  \r
+  FB_VIDEO_MODE_DATA                     *ModeBuffer;\r
+  FB_VIDEO_MODE_DATA                     *CurrentModeData;  \r
+  UINTN                                  ModeNumber;  \r
+  UINTN                                  BitsPerPixel; \r
+  UINTN                                  BytesPerScanLine;\r
+  UINT32                                 HorizontalResolution;\r
+  UINT32                                 VerticalResolution;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL          *VbeFrameBuffer;  \r
+  EFI_HOB_GUID_TYPE                      *GuidHob;\r
+  FRAME_BUFFER_INFO                      *pFbInfo;\r
+  \r
+  Status = EFI_SUCCESS;\r
+  //\r
+  // Find the frame buffer information guid hob\r
+  //\r
+  GuidHob = GetFirstGuidHob (&gUefiFrameBufferInfoGuid);\r
+  ASSERT (GuidHob != NULL);\r
+  pFbInfo = (FRAME_BUFFER_INFO *)GET_GUID_HOB_DATA (GuidHob);\r
+  \r
+  //\r
+  // Add mode to the list of available modes\r
+  //\r
+  VbeFrameBuffer = NULL;\r
+  ModeBuffer     = NULL;\r
+  \r
+  ModeNumber           = 1;  \r
+  BitsPerPixel         = pFbInfo->BitsPerPixel;\r
+  HorizontalResolution = pFbInfo->HorizontalResolution;\r
+  VerticalResolution   = pFbInfo->VerticalResolution;\r
+  BytesPerScanLine     = HorizontalResolution * (BitsPerPixel / 8);\r
+  \r
+  ModeBuffer = (FB_VIDEO_MODE_DATA *) AllocatePool (\r
+                                                                                                                                                                               ModeNumber * sizeof (FB_VIDEO_MODE_DATA)\r
+                                                                                                                                                       );\r
+  if (NULL == ModeBuffer) {\r
+         Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  VbeFrameBuffer =\r
+                       (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool (\r
+                                                                                                                                                                       BytesPerScanLine * VerticalResolution\r
+                                                                                                                                                                 );\r
+  if (NULL == VbeFrameBuffer) {\r
+         Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+       \r
+  if (FbGopPrivate->ModeData != NULL) {\r
+    FreePool (FbGopPrivate->ModeData);\r
+  }\r
+    \r
+  if (FbGopPrivate->VbeFrameBuffer != NULL) {\r
+    FreePool (FbGopPrivate->VbeFrameBuffer);\r
+  }  \r
+  \r
+  CurrentModeData = &ModeBuffer[ModeNumber - 1];\r
+  CurrentModeData->BytesPerScanLine = (UINT16)BytesPerScanLine;\r
+  \r
+  CurrentModeData->Red      = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Red);  \r
+  CurrentModeData->Blue     = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Blue);    \r
+  CurrentModeData->Green    = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Green);    \r
+  CurrentModeData->Reserved = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Reserved);  \r
+  \r
+  CurrentModeData->BitsPerPixel    = (UINT32)BitsPerPixel;\r
+  CurrentModeData->HorizontalResolution = HorizontalResolution;\r
+  CurrentModeData->VerticalResolution   = VerticalResolution;  \r
+  CurrentModeData->FrameBufferSize = CurrentModeData->BytesPerScanLine * CurrentModeData->VerticalResolution;    \r
+  CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN) pFbInfo->LinearFrameBuffer;\r
+  CurrentModeData->VbeModeNumber        = 0;\r
+  CurrentModeData->ColorDepth           = 32;\r
+  CurrentModeData->RefreshRate          = 60;\r
+  \r
+  CurrentModeData->PixelFormat = PixelBitMask;\r
+  if ((CurrentModeData->BitsPerPixel == 32) &&\r
+      (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {\r
+    if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {\r
+      CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;\r
+    } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {\r
+      CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
+    }\r
+  }  \r
+  \r
+  CopyMem (&(CurrentModeData->PixelBitMask), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK));    \r
+          \r
+  FbGopPrivate->ModeData       = ModeBuffer;\r
+  FbGopPrivate->VbeFrameBuffer = VbeFrameBuffer;\r
+  \r
+  //\r
+  // Assign Gop's Blt function\r
+  //\r
+  FbGopPrivate->GraphicsOutput.Blt     = FbGopGraphicsOutputVbeBlt;\r
+  \r
+  FbGopPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
+  FbGopPrivate->GraphicsOutput.Mode->Mode    = 0;      \r
+  FbGopPrivate->GraphicsOutput.Mode->Info->Version = 0;\r
+  FbGopPrivate->GraphicsOutput.Mode->Info->HorizontalResolution = HorizontalResolution;\r
+  FbGopPrivate->GraphicsOutput.Mode->Info->VerticalResolution   = VerticalResolution;   \r
+  FbGopPrivate->GraphicsOutput.Mode->Info->PixelFormat = CurrentModeData->PixelFormat;\r
+  CopyMem (&(FbGopPrivate->GraphicsOutput.Mode->Info->PixelInformation), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK));  \r
+  FbGopPrivate->GraphicsOutput.Mode->Info->PixelsPerScanLine = HorizontalResolution;    \r
+  FbGopPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
+  FbGopPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) CurrentModeData->LinearFrameBuffer;\r
+  FbGopPrivate->GraphicsOutput.Mode->FrameBufferSize =  CurrentModeData->FrameBufferSize;\r
+  \r
+  //\r
+  // Find the best mode to initialize\r
+  //  \r
+\r
+Done:\r
+  //\r
+  // If there was an error, then free the mode structure\r
+  //\r
+  if (EFI_ERROR (Status)) {\r
+      \r
+    if (VbeFrameBuffer != NULL) {\r
+      FreePool (VbeFrameBuffer);\r
+    }    \r
+    \r
+    if (ModeBuffer != NULL) {\r
+      FreePool (ModeBuffer);\r
+    }    \r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+//\r
+// Graphics Output Protocol Member Functions for VESA BIOS Extensions\r
+//\r
+\r
+/**\r
+  Graphics Output protocol interface to get video mode.\r
+\r
+  @param  This                   Protocol instance pointer.\r
+  @param  ModeNumber             The mode number to return information on.\r
+  @param  SizeOfInfo             A pointer to the size, in bytes, of the Info\r
+                                 buffer.\r
+  @param  Info                   Caller allocated buffer that returns information\r
+                                 about ModeNumber.\r
+\r
+  @retval EFI_SUCCESS            Mode information returned.\r
+  @retval EFI_DEVICE_ERROR       A hardware error occurred trying to retrieve the\r
+                                 video mode.\r
+  @retval EFI_NOT_STARTED        Video display is not initialized. Call SetMode ()\r
+  @retval EFI_INVALID_PARAMETER  One of the input args was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FbGopGraphicsOutputQueryMode (\r
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,\r
+  IN  UINT32                                ModeNumber,\r
+  OUT UINTN                                 *SizeOfInfo,\r
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info\r
+  )\r
+{\r
+  FB_VIDEO_DEV        *FbGopPrivate;\r
+  FB_VIDEO_MODE_DATA  *ModeData;\r
+\r
+  FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
+\r
+  if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (\r
+                                                                                                                                                                                                               sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)\r
+                                                                                                                                                                                                               );\r
+  if (NULL == *Info) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
+\r
+  ModeData = &FbGopPrivate->ModeData[ModeNumber];\r
+  (*Info)->Version = 0;\r
+  (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
+  (*Info)->VerticalResolution   = ModeData->VerticalResolution;\r
+  (*Info)->PixelFormat = ModeData->PixelFormat;\r
+  CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask));\r
+\r
+  (*Info)->PixelsPerScanLine =  (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Graphics Output protocol interface to set video mode.\r
+\r
+  @param  This                   Protocol instance pointer.\r
+  @param  ModeNumber             The mode number to be set.\r
+\r
+  @retval EFI_SUCCESS            Graphics mode was changed.\r
+  @retval EFI_DEVICE_ERROR       The device had an error and could not complete the\r
+                                 request.\r
+  @retval EFI_UNSUPPORTED        ModeNumber is not supported by this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FbGopGraphicsOutputSetMode (\r
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL * This,\r
+  IN  UINT32                       ModeNumber\r
+  )\r
+{  \r
+  FB_VIDEO_DEV          *FbGopPrivate;\r
+  FB_VIDEO_MODE_DATA    *ModeData;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
+\r
+  if (This == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
+\r
+  ModeData = &FbGopPrivate->ModeData[ModeNumber];\r
+\r
+  if (ModeNumber >= This->Mode->MaxMode) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
+  if (ModeNumber == This->Mode->Mode) {\r
+    //\r
+    // Clear screen to black\r
+    //    \r
+    ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+    FbGopGraphicsOutputVbeBlt (\r
+                        This,\r
+                        &Background,\r
+                        EfiBltVideoFill,\r
+                        0,\r
+                        0,\r
+                        0,\r
+                        0,\r
+                        ModeData->HorizontalResolution,\r
+                        ModeData->VerticalResolution,\r
+                        0\r
+    );\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
+}\r
+\r
+/**\r
+  Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.\r
+\r
+  @param   PciIo              The pointer of EFI_PCI_IO_PROTOCOL\r
+  @param   VbeBuffer          The data to transfer to screen\r
+  @param   MemAddress         Physical frame buffer base address\r
+  @param   DestinationX       The X coordinate of the destination for BltOperation\r
+  @param   DestinationY       The Y coordinate of the destination for BltOperation\r
+  @param   TotalBytes         The total bytes of copy\r
+  @param   VbePixelWidth      Bytes per pixel\r
+  @param   BytesPerScanLine   Bytes per scan line\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
+  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
+  Worker function to block transfer for VBE device.\r
+\r
+  @param  FbGopPrivate       Instance of FB_VIDEO_DEV\r
+  @param  BltBuffer              The data to transfer to screen\r
+  @param  BltOperation           The operation to perform\r
+  @param  SourceX                The X coordinate of the source for BltOperation\r
+  @param  SourceY                The Y coordinate of the source for BltOperation\r
+  @param  DestinationX           The X coordinate of the destination for\r
+                                 BltOperation\r
+  @param  DestinationY           The Y coordinate of the destination for\r
+                                 BltOperation\r
+  @param  Width                  The width of a rectangle in the blt rectangle in\r
+                                 pixels\r
+  @param  Height                 The height of a rectangle in the blt rectangle in\r
+                                 pixels\r
+  @param  Delta                  Not used for EfiBltVideoFill and\r
+                                 EfiBltVideoToVideo operation. If a Delta of 0 is\r
+                                 used, the entire BltBuffer will be operated on. If\r
+                                 a subrectangle of the BltBuffer is used, then\r
+                                 Delta represents the number of bytes in a row of\r
+                                 the BltBuffer.\r
+  @param  Mode                   Mode data.\r
+\r
+  @retval EFI_INVALID_PARAMETER  Invalid parameter passed in\r
+  @retval EFI_SUCCESS            Blt operation success\r
+\r
+**/\r
+EFI_STATUS\r
+FbGopVbeBltWorker (\r
+  IN  FB_VIDEO_DEV                       *FbGopPrivate,\r
+  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BltBuffer, OPTIONAL\r
+  IN  EFI_GRAPHICS_OUTPUT_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
+  IN  FB_VIDEO_MODE_DATA               *Mode\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL            *PciIo;\r
+  EFI_TPL                        OriginalTPL;\r
+  UINTN                          DstY;\r
+  UINTN                          SrcY;\r
+  UINTN                          DstX;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *Blt;\r
+  VOID                           *MemAddress;\r
+  EFI_GRAPHICS_OUTPUT_BLT_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
+  PciIo             = FbGopPrivate->PciIo;\r
+\r
+  VbeFrameBuffer    = FbGopPrivate->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 (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\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 == EfiBltVideoToBltBuffer) {\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_GRAPHICS_OUTPUT_BLT_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 EfiBltVideoToBltBuffer:\r
+    for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {\r
+      Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+      //\r
+      // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL\r
+      //\r
+      VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));\r
+      for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
+        Pixel         = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24;\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 EfiBltVideoToVideo:\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 EfiBltVideoFill:\r
+    VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
+    Blt       = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;\r
+    //\r
+    // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_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
+\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
+    break;\r
+\r
+  case EfiBltBufferToVideo:\r
+    for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {\r
+      Blt       = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_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_GRAPHICS_OUTPUT_BLT_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
+    default: ;\r
+  }\r
+\r
+  gBS->RestoreTPL (OriginalTPL);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Graphics Output protocol instance to block transfer for VBE device.\r
+\r
+  @param  This                   Pointer to Graphics Output protocol instance\r
+  @param  BltBuffer              The data to transfer to screen\r
+  @param  BltOperation           The operation to perform\r
+  @param  SourceX                The X coordinate of the source for BltOperation\r
+  @param  SourceY                The Y coordinate of the source for BltOperation\r
+  @param  DestinationX           The X coordinate of the destination for\r
+                                 BltOperation\r
+  @param  DestinationY           The Y coordinate of the destination for\r
+                                 BltOperation\r
+  @param  Width                  The width of a rectangle in the blt rectangle in\r
+                                 pixels\r
+  @param  Height                 The height of a rectangle in the blt rectangle in\r
+                                 pixels\r
+  @param  Delta                  Not used for EfiBltVideoFill and\r
+                                 EfiBltVideoToVideo operation. If a Delta of 0 is\r
+                                 used, the entire BltBuffer will be operated on. If\r
+                                 a subrectangle of the BltBuffer is used, then\r
+                                 Delta represents the number of bytes in a row of\r
+                                 the BltBuffer.\r
+\r
+  @retval EFI_INVALID_PARAMETER  Invalid parameter passed in\r
+  @retval EFI_SUCCESS            Blt operation success\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FbGopGraphicsOutputVbeBlt (\r
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL       *This,\r
+  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BltBuffer, OPTIONAL\r
+  IN  EFI_GRAPHICS_OUTPUT_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
+  FB_VIDEO_DEV                 *FbGopPrivate;\r
+  FB_VIDEO_MODE_DATA           *Mode;\r
+\r
+  if (This == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  FbGopPrivate  = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
+  Mode          = &FbGopPrivate->ModeData[This->Mode->Mode];\r
+\r
+  return FbGopVbeBltWorker (\r
+           FbGopPrivate,\r
+           BltBuffer,\r
+           BltOperation,\r
+           SourceX,\r
+           SourceY,\r
+           DestinationX,\r
+           DestinationY,\r
+           Width,\r
+           Height,\r
+           Delta,\r
+           Mode\r
+           );\r
+}\r
+\r
+\r
+/**\r
+  The user Entry Point for module UefiFbGop. The user code starts with this function.\r
+\r
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
+  @param[in] SystemTable    A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS       The entry point is executed successfully.\r
+  @retval other             Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FbGopEntryPoint(\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_HOB_GUID_TYPE  *GuidHob;\r
+  \r
+  //\r
+  // Find the frame buffer information guid hob\r
+  //\r
+  GuidHob = GetFirstGuidHob (&gUefiFrameBufferInfoGuid);\r
+  if (GuidHob != NULL) {   \r
+    //\r
+    // Install driver model protocol(s).\r
+    //\r
+    Status = EfiLibInstallDriverBindingComponentName2 (\r
+               ImageHandle,\r
+               SystemTable,\r
+               &gFbGopDriverBinding,\r
+               ImageHandle,\r
+               &gFbGopComponentName,\r
+               &gFbGopComponentName2\r
+               );\r
+    ASSERT_EFI_ERROR (Status);\r
+  } else {\r
+    DEBUG ((EFI_D_ERROR, "No FrameBuffer information from coreboot.  NO GOP driver !!!\n"));\r
+    Status = EFI_ABORTED;\r
+  }\r
+  return Status;  \r
+}\r
+\r