]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/QemuVideoDxe/Initialize.c
UefiCpuPkg/PiSmmCpuDxeSmm: patch "gSmbase" with PatchInstructionX86()
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Initialize.c
index b12253ba58927873842dd7f09010df74ad14aaeb..357124d628e7c6bc425ca27e310e8905f96f432a 100644 (file)
@@ -13,6 +13,7 @@
 \r
 **/\r
 \r
+#include <IndustryStandard/VmwareSvga.h>\r
 #include "Qemu.h"\r
 \r
 \r
@@ -144,18 +145,18 @@ UINT16 Seq_1024_768_32bpp_60[15] = {
 /// Table of supported video modes\r
 ///\r
 QEMU_VIDEO_CIRRUS_MODES  QemuVideoCirrusModes[] = {\r
-//  {  640, 480, 8, 60, Crtc_640_480_256_60,  Seq_640_480_256_60,  0xe3 },\r
-//  {  800, 600, 8, 60, Crtc_800_600_256_60,  Seq_800_600_256_60,  0xef },\r
-  {  640, 480, 32, 60, Crtc_640_480_32bpp_60,  Seq_640_480_32bpp_60,  0xef },\r
-  {  800, 600, 32, 60, Crtc_800_600_32bpp_60,  Seq_800_600_32bpp_60,  0xef },\r
-//  { 1024, 768, 8, 60, Crtc_1024_768_256_60, Seq_1024_768_256_60, 0xef }\r
-  { 1024, 768, 24, 60, Crtc_1024_768_24bpp_60, Seq_1024_768_24bpp_60, 0xef }\r
-//  { 1024, 768, 32, 60, Crtc_1024_768_32bpp_60, Seq_1024_768_32bpp_60, 0xef }\r
-//  { 960, 720, 32, 60, Crtc_960_720_32bpp_60, Seq_1024_768_32bpp_60, 0xef }\r
+//  {  640, 480, 8, Crtc_640_480_256_60,  Seq_640_480_256_60,  0xe3 },\r
+//  {  800, 600, 8, Crtc_800_600_256_60,  Seq_800_600_256_60,  0xef },\r
+  {  640, 480, 32, Crtc_640_480_32bpp_60,  Seq_640_480_32bpp_60,  0xef },\r
+  {  800, 600, 32, Crtc_800_600_32bpp_60,  Seq_800_600_32bpp_60,  0xef },\r
+//  { 1024, 768, 8, Crtc_1024_768_256_60, Seq_1024_768_256_60, 0xef }\r
+  { 1024, 768, 24, Crtc_1024_768_24bpp_60, Seq_1024_768_24bpp_60, 0xef }\r
+//  { 1024, 768, 32, Crtc_1024_768_32bpp_60, Seq_1024_768_32bpp_60, 0xef }\r
+//  { 960, 720, 32, Crtc_960_720_32bpp_60, Seq_1024_768_32bpp_60, 0xef }\r
 };\r
 \r
 #define QEMU_VIDEO_CIRRUS_MODE_COUNT \\r
-  (sizeof (QemuVideoCirrusModes) / sizeof (QemuVideoCirrusModes[0]))\r
+  (ARRAY_SIZE (QemuVideoCirrusModes))\r
 \r
 /**\r
   Construct the valid video modes for QemuVideo.\r
@@ -247,7 +248,7 @@ QEMU_VIDEO_BOCHS_MODES  QemuVideoBochsModes[] = {
 };\r
 \r
 #define QEMU_VIDEO_BOCHS_MODE_COUNT \\r
-  (sizeof (QemuVideoBochsModes) / sizeof (QemuVideoBochsModes[0]))\r
+  (ARRAY_SIZE (QemuVideoBochsModes))\r
 \r
 EFI_STATUS\r
 QemuVideoBochsModeSetup (\r
@@ -303,7 +304,7 @@ QemuVideoBochsModeSetup (
     AvailableFbSize  = BochsRead (Private, VBE_DISPI_INDEX_VIDEO_MEMORY_64K);\r
     AvailableFbSize *= SIZE_64KB;\r
   }\r
-  DEBUG ((EFI_D_VERBOSE, "%a: AvailableFbSize=0x%x\n", __FUNCTION__,\r
+  DEBUG ((EFI_D_INFO, "%a: AvailableFbSize=0x%x\n", __FUNCTION__,\r
     AvailableFbSize));\r
 \r
   //\r
@@ -346,3 +347,159 @@ QemuVideoBochsModeSetup (
   return EFI_SUCCESS;\r
 }\r
 \r
+EFI_STATUS\r
+QemuVideoVmwareSvgaModeSetup (\r
+  QEMU_VIDEO_PRIVATE_DATA *Private\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  UINT32                                FbSize;\r
+  UINT32                                MaxWidth, MaxHeight;\r
+  UINT32                                Capabilities;\r
+  UINT32                                BitsPerPixel;\r
+  UINT32                                Index;\r
+  QEMU_VIDEO_MODE_DATA                  *ModeData;\r
+  QEMU_VIDEO_BOCHS_MODES                *VideoMode;\r
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *ModeInfo;\r
+\r
+  VmwareSvgaWrite (Private, VmwareSvgaRegEnable, 0);\r
+\r
+  Private->ModeData =\r
+    AllocatePool (sizeof (Private->ModeData[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT);\r
+  if (Private->ModeData == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ModeDataAllocError;\r
+  }\r
+\r
+  Private->VmwareSvgaModeInfo =\r
+    AllocatePool (\r
+      sizeof (Private->VmwareSvgaModeInfo[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT\r
+      );\r
+  if (Private->VmwareSvgaModeInfo == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ModeInfoAllocError;\r
+  }\r
+\r
+  FbSize =       VmwareSvgaRead (Private, VmwareSvgaRegFbSize);\r
+  MaxWidth =     VmwareSvgaRead (Private, VmwareSvgaRegMaxWidth);\r
+  MaxHeight =    VmwareSvgaRead (Private, VmwareSvgaRegMaxHeight);\r
+  Capabilities = VmwareSvgaRead (Private, VmwareSvgaRegCapabilities);\r
+  if ((Capabilities & VMWARE_SVGA_CAP_8BIT_EMULATION) != 0) {\r
+    BitsPerPixel = VmwareSvgaRead (\r
+                     Private,\r
+                     VmwareSvgaRegHostBitsPerPixel\r
+                     );\r
+    VmwareSvgaWrite (\r
+      Private,\r
+      VmwareSvgaRegBitsPerPixel,\r
+      BitsPerPixel\r
+      );\r
+  } else {\r
+    BitsPerPixel = VmwareSvgaRead (\r
+                     Private,\r
+                     VmwareSvgaRegBitsPerPixel\r
+                     );\r
+  }\r
+\r
+  if (FbSize == 0       ||\r
+      MaxWidth == 0     ||\r
+      MaxHeight == 0    ||\r
+      BitsPerPixel == 0 ||\r
+      BitsPerPixel % 8 != 0) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto Rollback;\r
+  }\r
+\r
+  ModeData = Private->ModeData;\r
+  ModeInfo = Private->VmwareSvgaModeInfo;\r
+  VideoMode = &QemuVideoBochsModes[0];\r
+  for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index++) {\r
+    UINTN RequiredFbSize;\r
+\r
+    RequiredFbSize = (UINTN) VideoMode->Width * VideoMode->Height *\r
+                     (BitsPerPixel / 8);\r
+    if (RequiredFbSize <= FbSize     &&\r
+        VideoMode->Width <= MaxWidth &&\r
+        VideoMode->Height <= MaxHeight) {\r
+      UINT32  BytesPerLine;\r
+      UINT32  RedMask, GreenMask, BlueMask, PixelMask;\r
+\r
+      VmwareSvgaWrite (\r
+        Private,\r
+        VmwareSvgaRegWidth,\r
+        VideoMode->Width\r
+        );\r
+      VmwareSvgaWrite (\r
+        Private,\r
+        VmwareSvgaRegHeight,\r
+        VideoMode->Height\r
+        );\r
+\r
+      ModeData->InternalModeIndex    = Index;\r
+      ModeData->HorizontalResolution = VideoMode->Width;\r
+      ModeData->VerticalResolution   = VideoMode->Height;\r
+      ModeData->ColorDepth           = BitsPerPixel;\r
+\r
+      //\r
+      // Setting VmwareSvgaRegWidth/VmwareSvgaRegHeight actually changes\r
+      // the device's display mode, so we save all properties of each mode up\r
+      // front to avoid inadvertent mode changes later.\r
+      //\r
+      ModeInfo->Version = 0;\r
+      ModeInfo->HorizontalResolution = ModeData->HorizontalResolution;\r
+      ModeInfo->VerticalResolution   = ModeData->VerticalResolution;\r
+\r
+      ModeInfo->PixelFormat = PixelBitMask;\r
+\r
+      RedMask   = VmwareSvgaRead (Private, VmwareSvgaRegRedMask);\r
+      ModeInfo->PixelInformation.RedMask = RedMask;\r
+\r
+      GreenMask = VmwareSvgaRead (Private, VmwareSvgaRegGreenMask);\r
+      ModeInfo->PixelInformation.GreenMask = GreenMask;\r
+\r
+      BlueMask  = VmwareSvgaRead (Private, VmwareSvgaRegBlueMask);\r
+      ModeInfo->PixelInformation.BlueMask = BlueMask;\r
+\r
+      //\r
+      // Reserved mask is whatever bits in the pixel not containing RGB data,\r
+      // so start with binary 1s for every bit in the pixel, then mask off\r
+      // bits already used for RGB. Special case 32 to avoid undefined\r
+      // behaviour in the shift.\r
+      //\r
+      if (BitsPerPixel == 32) {\r
+        if (BlueMask == 0xff && GreenMask == 0xff00 && RedMask == 0xff0000) {\r
+          ModeInfo->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
+        } else if (BlueMask == 0xff0000 &&\r
+                   GreenMask == 0xff00 &&\r
+                   RedMask == 0xff) {\r
+          ModeInfo->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;\r
+        }\r
+        PixelMask = MAX_UINT32;\r
+      } else {\r
+        PixelMask = (1u << BitsPerPixel) - 1;\r
+      }\r
+      ModeInfo->PixelInformation.ReservedMask =\r
+        PixelMask & ~(RedMask | GreenMask | BlueMask);\r
+\r
+      BytesPerLine = VmwareSvgaRead (Private, VmwareSvgaRegBytesPerLine);\r
+      ModeInfo->PixelsPerScanLine = BytesPerLine / (BitsPerPixel / 8);\r
+\r
+      ModeData++;\r
+      ModeInfo++;\r
+    }\r
+    VideoMode++;\r
+  }\r
+  Private->MaxMode = ModeData - Private->ModeData;\r
+  return EFI_SUCCESS;\r
+\r
+Rollback:\r
+  FreePool (Private->VmwareSvgaModeInfo);\r
+  Private->VmwareSvgaModeInfo = NULL;\r
+\r
+ModeInfoAllocError:\r
+  FreePool (Private->ModeData);\r
+  Private->ModeData = NULL;\r
+\r
+ModeDataAllocError:\r
+  return Status;\r
+}\r