]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/QemuVideoDxe/Initialize.c
IntelFsp2Pkg: Add missing OEM status code defines.
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Initialize.c
index 37744786cb6645d79a8757441fe54b9033b333a7..9e0c3aa09fd6fbfaccd97c29af5141adc113e346 100644 (file)
@@ -182,14 +182,15 @@ QemuVideoCirrusModeSetup (
   ModeData = Private->ModeData;\r
   VideoMode = &QemuVideoCirrusModes[0];\r
   for (Index = 0; Index < QEMU_VIDEO_CIRRUS_MODE_COUNT; Index ++) {\r
-    ModeData->ModeNumber = Index;\r
+    ModeData->InternalModeIndex = Index;\r
     ModeData->HorizontalResolution          = VideoMode->Width;\r
     ModeData->VerticalResolution            = VideoMode->Height;\r
     ModeData->ColorDepth                    = VideoMode->ColorDepth;\r
     ModeData->RefreshRate                   = VideoMode->RefreshRate;\r
     DEBUG ((EFI_D_INFO,\r
-      "Adding Cirrus Video Mode %d: %dx%d, %d-bit, %d Hz\n",\r
-      ModeData->ModeNumber,\r
+      "Adding Mode %d as Cirrus Internal Mode %d: %dx%d, %d-bit, %d Hz\n",\r
+      (INT32) (ModeData - Private->ModeData),\r
+      ModeData->InternalModeIndex,\r
       ModeData->HorizontalResolution,\r
       ModeData->VerticalResolution,\r
       ModeData->ColorDepth,\r
@@ -199,7 +200,7 @@ QemuVideoCirrusModeSetup (
     ModeData ++ ;\r
     VideoMode ++;\r
   }\r
-  Private->MaxMode = QEMU_VIDEO_CIRRUS_MODE_COUNT;\r
+  Private->MaxMode = ModeData - Private->ModeData;\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -208,9 +209,43 @@ QemuVideoCirrusModeSetup (
 /// Table of supported video modes\r
 ///\r
 QEMU_VIDEO_BOCHS_MODES  QemuVideoBochsModes[] = {\r
-  {  640, 480, 32 },\r
-  {  800, 600, 32 },\r
-  { 1024, 768, 24 },\r
+  {  640,  480, 32 },\r
+  {  800,  480, 32 },\r
+  {  800,  600, 32 },\r
+  {  832,  624, 32 },\r
+  {  960,  640, 32 },\r
+  { 1024,  600, 32 },\r
+  { 1024,  768, 32 },\r
+  { 1152,  864, 32 },\r
+  { 1152,  870, 32 },\r
+  { 1280,  720, 32 },\r
+  { 1280,  760, 32 },\r
+  { 1280,  768, 32 },\r
+  { 1280,  800, 32 },\r
+  { 1280,  960, 32 },\r
+  { 1280, 1024, 32 },\r
+  { 1360,  768, 32 },\r
+  { 1366,  768, 32 },\r
+  { 1400, 1050, 32 },\r
+  { 1440,  900, 32 },\r
+  { 1600,  900, 32 },\r
+  { 1600, 1200, 32 },\r
+  { 1680, 1050, 32 },\r
+  { 1920, 1080, 32 },\r
+  { 1920, 1200, 32 },\r
+  { 1920, 1440, 32 },\r
+  { 2000, 2000, 32 },\r
+  { 2048, 1536, 32 },\r
+  { 2048, 2048, 32 },\r
+  { 2560, 1440, 32 },\r
+  { 2560, 1600, 32 },\r
+  { 2560, 2048, 32 },\r
+  { 2800, 2100, 32 },\r
+  { 3200, 2400, 32 },\r
+  { 3840, 2160, 32 },\r
+  { 4096, 2160, 32 },\r
+  { 7680, 4320, 32 },\r
+  { 8192, 4320, 32 }\r
 };\r
 \r
 #define QEMU_VIDEO_BOCHS_MODE_COUNT \\r
@@ -218,13 +253,61 @@ QEMU_VIDEO_BOCHS_MODES  QemuVideoBochsModes[] = {
 \r
 EFI_STATUS\r
 QemuVideoBochsModeSetup (\r
-  QEMU_VIDEO_PRIVATE_DATA  *Private\r
+  QEMU_VIDEO_PRIVATE_DATA  *Private,\r
+  BOOLEAN                  IsQxl\r
   )\r
 {\r
+  UINT32                                 AvailableFbSize;\r
   UINT32                                 Index;\r
   QEMU_VIDEO_MODE_DATA                   *ModeData;\r
   QEMU_VIDEO_BOCHS_MODES                 *VideoMode;\r
 \r
+  //\r
+  // Fetch the available framebuffer size.\r
+  //\r
+  // VBE_DISPI_INDEX_VIDEO_MEMORY_64K is expected to return the size of the\r
+  // drawable framebuffer. Up to and including qemu-2.1 however it used to\r
+  // return the size of PCI BAR 0 (ie. the full video RAM size).\r
+  //\r
+  // On stdvga the two concepts coincide with each other; the full memory size\r
+  // is usable for drawing.\r
+  //\r
+  // On QXL however, only a leading segment, "surface 0", can be used for\r
+  // drawing; the rest of the video memory is used for the QXL guest-host\r
+  // protocol. VBE_DISPI_INDEX_VIDEO_MEMORY_64K should report the size of\r
+  // "surface 0", but since it doesn't (up to and including qemu-2.1), we\r
+  // retrieve the size of the drawable portion from a field in the QXL ROM BAR,\r
+  // where it is also available.\r
+  //\r
+  if (IsQxl) {\r
+    UINT32 Signature;\r
+    UINT32 DrawStart;\r
+\r
+    Signature = 0;\r
+    DrawStart = 0xFFFFFFFF;\r
+    AvailableFbSize = 0;\r
+    if (EFI_ERROR (\r
+          Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,\r
+                                PCI_BAR_IDX2, 0, 1, &Signature)) ||\r
+        Signature != SIGNATURE_32 ('Q', 'X', 'R', 'O') ||\r
+        EFI_ERROR (\r
+          Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,\r
+                                PCI_BAR_IDX2, 36, 1, &DrawStart)) ||\r
+        DrawStart != 0 ||\r
+        EFI_ERROR (\r
+          Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,\r
+                                PCI_BAR_IDX2, 40, 1, &AvailableFbSize))) {\r
+      DEBUG ((EFI_D_ERROR, "%a: can't read size of drawable buffer from QXL "\r
+        "ROM\n", __FUNCTION__));\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  } else {\r
+    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
+    AvailableFbSize));\r
+\r
   //\r
   // Setup Video Modes\r
   //\r
@@ -237,24 +320,32 @@ QemuVideoBochsModeSetup (
   ModeData = Private->ModeData;\r
   VideoMode = &QemuVideoBochsModes[0];\r
   for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index ++) {\r
-    ModeData->ModeNumber = Index;\r
-    ModeData->HorizontalResolution          = VideoMode->Width;\r
-    ModeData->VerticalResolution            = VideoMode->Height;\r
-    ModeData->ColorDepth                    = VideoMode->ColorDepth;\r
-    ModeData->RefreshRate                   = 60;\r
-    DEBUG ((EFI_D_INFO,\r
-      "Adding Bochs Video Mode %d: %dx%d, %d-bit, %d Hz\n",\r
-      ModeData->ModeNumber,\r
-      ModeData->HorizontalResolution,\r
-      ModeData->VerticalResolution,\r
-      ModeData->ColorDepth,\r
-      ModeData->RefreshRate\r
-      ));\r
-\r
-    ModeData ++ ;\r
+    UINTN RequiredFbSize;\r
+\r
+    ASSERT (VideoMode->ColorDepth % 8 == 0);\r
+    RequiredFbSize = (UINTN) VideoMode->Width * VideoMode->Height *\r
+                     (VideoMode->ColorDepth / 8);\r
+    if (RequiredFbSize <= AvailableFbSize) {\r
+      ModeData->InternalModeIndex    = Index;\r
+      ModeData->HorizontalResolution = VideoMode->Width;\r
+      ModeData->VerticalResolution   = VideoMode->Height;\r
+      ModeData->ColorDepth           = VideoMode->ColorDepth;\r
+      ModeData->RefreshRate          = 60;\r
+      DEBUG ((EFI_D_INFO,\r
+        "Adding Mode %d as Bochs Internal Mode %d: %dx%d, %d-bit, %d Hz\n",\r
+        (INT32) (ModeData - Private->ModeData),\r
+        ModeData->InternalModeIndex,\r
+        ModeData->HorizontalResolution,\r
+        ModeData->VerticalResolution,\r
+        ModeData->ColorDepth,\r
+        ModeData->RefreshRate\r
+        ));\r
+\r
+      ModeData ++ ;\r
+    }\r
     VideoMode ++;\r
   }\r
-  Private->MaxMode = QEMU_VIDEO_BOCHS_MODE_COUNT;\r
+  Private->MaxMode = ModeData - Private->ModeData;\r
 \r
   return EFI_SUCCESS;\r
 }\r