]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/QemuVideoDxe/Gop.c
OvmfPkg/Gop: clear the screen to black in SetMode()
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Gop.c
index d364630c47609407a1062d84a35557bea4570474..b479d24a87634a31c4d563dd542fa3ef637c7c8a 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Graphics Output Protocol functions for the QEMU video controller.\r
 \r
 /** @file\r
   Graphics Output Protocol functions for the QEMU video controller.\r
 \r
-  Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2007 - 2018, 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 of the BSD License\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -13,9 +13,8 @@
 \r
 **/\r
 \r
 \r
 **/\r
 \r
+#include <IndustryStandard/VmwareSvga.h>\r
 #include "Qemu.h"\r
 #include "Qemu.h"\r
-#include <IndustryStandard/Acpi.h>\r
-#include <Library/BltLib.h>\r
 \r
 STATIC\r
 VOID\r
 \r
 STATIC\r
 VOID\r
@@ -70,11 +69,49 @@ QemuVideoCompleteModeData (
   Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;\r
   Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution;\r
   Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData->ColorDepth + 7) / 8);\r
   Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;\r
   Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution;\r
   Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData->ColorDepth + 7) / 8);\r
-  DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%x, FrameBufferSize: 0x%x\n", Mode->FrameBufferBase, Mode->FrameBufferSize));\r
+  DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",\r
+    Mode->FrameBufferBase, (UINT64)Mode->FrameBufferSize));\r
 \r
 \r
+  FreePool (FrameBufDesc);\r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+STATIC\r
+EFI_STATUS\r
+QemuVideoVmwareSvgaCompleteModeData (\r
+  IN  QEMU_VIDEO_PRIVATE_DATA           *Private,\r
+  OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     *FrameBufDesc;\r
+  UINT32                                BytesPerLine, FbOffset, BytesPerPixel;\r
+\r
+  Info = Mode->Info;\r
+  CopyMem (Info, &Private->VmwareSvgaModeInfo[Mode->Mode], sizeof (*Info));\r
+  BytesPerPixel = Private->ModeData[Mode->Mode].ColorDepth / 8;\r
+  BytesPerLine = Info->PixelsPerScanLine * BytesPerPixel;\r
+\r
+  FbOffset = VmwareSvgaRead (Private, VmwareSvgaRegFbOffset);\r
+\r
+  Status = Private->PciIo->GetBarAttributes (\r
+                             Private->PciIo,\r
+                             PCI_BAR_IDX1,\r
+                             NULL,\r
+                             (VOID**) &FrameBufDesc\r
+                             );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin + FbOffset;\r
+  Mode->FrameBufferSize = BytesPerLine * Info->VerticalResolution;\r
+\r
+  FreePool (FrameBufDesc);\r
+  return Status;\r
+}\r
+\r
 \r
 //\r
 // Graphics Output Protocol Member Functions\r
 \r
 //\r
 // Graphics Output Protocol Member Functions\r
@@ -113,10 +150,6 @@ Routine Description:
 \r
   Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
 \r
 \r
   Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
 \r
-  if (Private->HardwareNeedsStarting) {\r
-    return EFI_NOT_STARTED;\r
-  }\r
-\r
   if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -128,10 +161,14 @@ Routine Description:
 \r
   *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
 \r
 \r
   *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
 \r
-  ModeData = &Private->ModeData[ModeNumber];\r
-  (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
-  (*Info)->VerticalResolution   = ModeData->VerticalResolution;\r
-  QemuVideoCompleteModeInfo (ModeData, *Info);\r
+  if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {\r
+    CopyMem (*Info, &Private->VmwareSvgaModeInfo[ModeNumber], sizeof (**Info));\r
+  } else {\r
+    ModeData = &Private->ModeData[ModeNumber];\r
+    (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
+    (*Info)->VerticalResolution   = ModeData->VerticalResolution;\r
+    QemuVideoCompleteModeInfo (ModeData, *Info);\r
+  }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -159,9 +196,10 @@ Routine Description:
 \r
 --*/\r
 {\r
 \r
 --*/\r
 {\r
-  QEMU_VIDEO_PRIVATE_DATA    *Private;\r
-  QEMU_VIDEO_MODE_DATA       *ModeData;\r
-//  UINTN                             Count;\r
+  QEMU_VIDEO_PRIVATE_DATA       *Private;\r
+  QEMU_VIDEO_MODE_DATA          *ModeData;\r
+  RETURN_STATUS                 Status;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black;\r
 \r
   Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
 \r
 \r
   Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
 \r
@@ -171,31 +209,83 @@ Routine Description:
 \r
   ModeData = &Private->ModeData[ModeNumber];\r
 \r
 \r
   ModeData = &Private->ModeData[ModeNumber];\r
 \r
-  if (Private->LineBuffer) {\r
-    gBS->FreePool (Private->LineBuffer);\r
-  }\r
-\r
-  Private->LineBuffer = NULL;\r
-  Private->LineBuffer = AllocatePool (4 * ModeData->HorizontalResolution);\r
-  if (Private->LineBuffer == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+  switch (Private->Variant) {\r
+  case QEMU_VIDEO_CIRRUS_5430:\r
+  case QEMU_VIDEO_CIRRUS_5446:\r
+    InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);\r
+    break;\r
+  case QEMU_VIDEO_BOCHS_MMIO:\r
+  case QEMU_VIDEO_BOCHS:\r
+    InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);\r
+    break;\r
+  case QEMU_VIDEO_VMWARE_SVGA:\r
+    InitializeVmwareSvgaGraphicsMode (\r
+      Private,\r
+      &QemuVideoBochsModes[ModeData->InternalModeIndex]\r
+      );\r
+    break;\r
+  default:\r
+    ASSERT (FALSE);\r
+    return EFI_DEVICE_ERROR;\r
   }\r
 \r
   }\r
 \r
-  InitializeGraphicsMode (Private, &QemuVideoVideoModes[ModeData->ModeNumber]);\r
-\r
   This->Mode->Mode = ModeNumber;\r
   This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
   This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
   This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
 \r
   This->Mode->Mode = ModeNumber;\r
   This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
   This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
   This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
 \r
-  QemuVideoCompleteModeData (Private, This->Mode);\r
+  if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {\r
+    QemuVideoVmwareSvgaCompleteModeData (Private, This->Mode);\r
+  } else {\r
+    QemuVideoCompleteModeData (Private, This->Mode);\r
+  }\r
 \r
 \r
-  BltLibConfigure (\r
-    (VOID*)(UINTN) This->Mode->FrameBufferBase,\r
-    This->Mode->Info\r
-    );\r
+  //\r
+  // Re-initialize the frame buffer configure when mode changes.\r
+  //\r
+  Status = FrameBufferBltConfigure (\r
+             (VOID*) (UINTN) This->Mode->FrameBufferBase,\r
+             This->Mode->Info,\r
+             Private->FrameBufferBltConfigure,\r
+             &Private->FrameBufferBltConfigureSize\r
+             );\r
+  if (Status == RETURN_BUFFER_TOO_SMALL) {\r
+    //\r
+    // Frame buffer configure may be larger in new mode.\r
+    //\r
+    if (Private->FrameBufferBltConfigure != NULL) {\r
+      FreePool (Private->FrameBufferBltConfigure);\r
+    }\r
+    Private->FrameBufferBltConfigure =\r
+      AllocatePool (Private->FrameBufferBltConfigureSize);\r
+    ASSERT (Private->FrameBufferBltConfigure != NULL);\r
+\r
+    //\r
+    // Create the configuration for FrameBufferBltLib\r
+    //\r
+    Status = FrameBufferBltConfigure (\r
+                (VOID*) (UINTN) This->Mode->FrameBufferBase,\r
+                This->Mode->Info,\r
+                Private->FrameBufferBltConfigure,\r
+                &Private->FrameBufferBltConfigureSize\r
+                );\r
+  }\r
+  ASSERT (Status == RETURN_SUCCESS);\r
 \r
 \r
-  Private->HardwareNeedsStarting  = FALSE;\r
+  //\r
+  // Per UEFI Spec, need to clear the visible portions of the output display to black.\r
+  //\r
+  ZeroMem (&Black, sizeof (Black));\r
+  Status = FrameBufferBlt (\r
+             Private->FrameBufferBltConfigure,\r
+             &Black,\r
+             EfiBltVideoFill,\r
+             0, 0,\r
+             0, 0,\r
+             This->Mode->Info->HorizontalResolution, This->Mode->Info->VerticalResolution,\r
+             0\r
+             );\r
+  ASSERT_RETURN_ERROR (Status);\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -245,7 +335,9 @@ Returns:
 {\r
   EFI_STATUS                      Status;\r
   EFI_TPL                         OriginalTPL;\r
 {\r
   EFI_STATUS                      Status;\r
   EFI_TPL                         OriginalTPL;\r
+  QEMU_VIDEO_PRIVATE_DATA         *Private;\r
 \r
 \r
+  Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\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
   //\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
@@ -258,7 +350,8 @@ Returns:
   case EfiBltBufferToVideo:\r
   case EfiBltVideoFill:\r
   case EfiBltVideoToVideo:\r
   case EfiBltBufferToVideo:\r
   case EfiBltVideoFill:\r
   case EfiBltVideoToVideo:\r
-    Status = BltLibGopBlt (\r
+    Status = FrameBufferBlt (\r
+      Private->FrameBufferBltConfigure,\r
       BltBuffer,\r
       BltOperation,\r
       SourceX,\r
       BltBuffer,\r
       BltOperation,\r
       SourceX,\r
@@ -306,23 +399,28 @@ QemuVideoGraphicsOutputConstructor (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+\r
   Status = gBS->AllocatePool (\r
                   EfiBootServicesData,\r
                   sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
                   (VOID **) &Private->GraphicsOutput.Mode->Info\r
                   );\r
   if (EFI_ERROR (Status)) {\r
   Status = gBS->AllocatePool (\r
                   EfiBootServicesData,\r
                   sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
                   (VOID **) &Private->GraphicsOutput.Mode->Info\r
                   );\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto FreeMode;\r
   }\r
   Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;\r
   Private->GraphicsOutput.Mode->Mode    = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
   }\r
   Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;\r
   Private->GraphicsOutput.Mode->Mode    = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
-  Private->HardwareNeedsStarting        = TRUE;\r
-  Private->LineBuffer                   = NULL;\r
+  Private->FrameBufferBltConfigure      = NULL;\r
+  Private->FrameBufferBltConfigureSize  = 0;\r
 \r
   //\r
   // Initialize the hardware\r
   //\r
 \r
   //\r
   // Initialize the hardware\r
   //\r
-  GraphicsOutput->SetMode (GraphicsOutput, 0);\r
+  Status = GraphicsOutput->SetMode (GraphicsOutput, 0);\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeInfo;\r
+  }\r
+\r
   DrawLogo (\r
     Private,\r
     Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,\r
   DrawLogo (\r
     Private,\r
     Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,\r
@@ -330,6 +428,15 @@ QemuVideoGraphicsOutputConstructor (
     );\r
 \r
   return EFI_SUCCESS;\r
     );\r
 \r
   return EFI_SUCCESS;\r
+\r
+FreeInfo:\r
+  FreePool (Private->GraphicsOutput.Mode->Info);\r
+\r
+FreeMode:\r
+  FreePool (Private->GraphicsOutput.Mode);\r
+  Private->GraphicsOutput.Mode = NULL;\r
+\r
+  return Status;\r
 }\r
 \r
 EFI_STATUS\r
 }\r
 \r
 EFI_STATUS\r
@@ -348,6 +455,10 @@ Returns:
 \r
 --*/\r
 {\r
 \r
 --*/\r
 {\r
+  if (Private->FrameBufferBltConfigure != NULL) {\r
+    FreePool (Private->FrameBufferBltConfigure);\r
+  }\r
+\r
   if (Private->GraphicsOutput.Mode != NULL) {\r
     if (Private->GraphicsOutput.Mode->Info != NULL) {\r
       gBS->FreePool (Private->GraphicsOutput.Mode->Info);\r
   if (Private->GraphicsOutput.Mode != NULL) {\r
     if (Private->GraphicsOutput.Mode->Info != NULL) {\r
       gBS->FreePool (Private->GraphicsOutput.Mode->Info);\r