]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/QemuVideoDxe/Initialize.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Initialize.c
index b5a5660ed2eed5481463b0ccf0695ab364b9f498..2a3cbc65c32a5611b66dbb9294668f27f97f860a 100644 (file)
@@ -9,7 +9,6 @@
 \r
 #include "Qemu.h"\r
 \r
-\r
 ///\r
 /// Generic Attribute Controller Register Settings\r
 ///\r
@@ -22,33 +21,33 @@ UINT8  AttributeController[21] = {
 ///\r
 /// Generic Graphics Controller Register Settings\r
 ///\r
-UINT8 GraphicsController[9] = {\r
+UINT8  GraphicsController[9] = {\r
   0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF\r
 };\r
 \r
 //\r
 // 640 x 480 x 256 color @ 60 Hertz\r
 //\r
-UINT8 Crtc_640_480_256_60[28] = {\r
+UINT8  Crtc_640_480_256_60[28] = {\r
   0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,\r
   0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
   0xe1, 0x83, 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,\r
   0xff, 0x00, 0x00, 0x22\r
 };\r
 \r
-UINT8 Crtc_640_480_32bpp_60[28] = {\r
+UINT8  Crtc_640_480_32bpp_60[28] = {\r
   0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,\r
   0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
   0xe1, 0x83, 0xdf, 0x40, 0x00, 0xe7, 0x04, 0xe3,\r
   0xff, 0x00, 0x00, 0x32\r
 };\r
 \r
-UINT16 Seq_640_480_256_60[15] = {\r
+UINT16  Seq_640_480_256_60[15] = {\r
   0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,\r
   0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e\r
 };\r
 \r
-UINT16 Seq_640_480_32bpp_60[15] = {\r
+UINT16  Seq_640_480_32bpp_60[15] = {\r
   0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,\r
   0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e\r
 };\r
@@ -56,38 +55,38 @@ UINT16 Seq_640_480_32bpp_60[15] = {
 //\r
 // 800 x 600 x 256 color @ 60 Hertz\r
 //\r
-UINT8 Crtc_800_600_256_60[28] = {\r
+UINT8  Crtc_800_600_256_60[28] = {\r
   0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,\r
   0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
   0x58, 0x8C, 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,\r
   0xFF, 0x00, 0x00, 0x22\r
 };\r
 \r
-UINT8 Crtc_800_600_32bpp_60[28] = {\r
+UINT8  Crtc_800_600_32bpp_60[28] = {\r
   0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,\r
   0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
   0x58, 0x8C, 0x57, 0x90, 0x00, 0x5F, 0x91, 0xE3,\r
   0xFF, 0x00, 0x00, 0x32\r
 };\r
 \r
-UINT16 Seq_800_600_256_60[15] = {\r
+UINT16  Seq_800_600_256_60[15] = {\r
   0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,\r
   0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e\r
 };\r
 \r
-UINT16 Seq_800_600_32bpp_60[15] = {\r
+UINT16  Seq_800_600_32bpp_60[15] = {\r
   0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,\r
   0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e\r
 };\r
 \r
-UINT8 Crtc_960_720_32bpp_60[28] = {\r
+UINT8  Crtc_960_720_32bpp_60[28] = {\r
   0xA3, 0x77, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,\r
   0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
   0x02, 0x88, 0xCF, 0xe0, 0x00, 0x00, 0x64, 0xE3,\r
   0xFF, 0x4A, 0x00, 0x32\r
 };\r
 \r
-UINT16 Seq_960_720_32bpp_60[15] = {\r
+UINT16  Seq_960_720_32bpp_60[15] = {\r
   0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,\r
   0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e\r
 };\r
@@ -95,14 +94,14 @@ UINT16 Seq_960_720_32bpp_60[15] = {
 //\r
 // 1024 x 768 x 256 color @ 60 Hertz\r
 //\r
-UINT8 Crtc_1024_768_256_60[28] = {\r
+UINT8  Crtc_1024_768_256_60[28] = {\r
   0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,\r
   0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
   0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,\r
   0xFF, 0x4A, 0x00, 0x22\r
 };\r
 \r
-UINT16 Seq_1024_768_256_60[15] = {\r
+UINT16  Seq_1024_768_256_60[15] = {\r
   0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,\r
   0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e\r
 };\r
@@ -110,26 +109,26 @@ UINT16 Seq_1024_768_256_60[15] = {
 //\r
 // 1024 x 768 x 24-bit color @ 60 Hertz\r
 //\r
-UINT8 Crtc_1024_768_24bpp_60[28] = {\r
+UINT8  Crtc_1024_768_24bpp_60[28] = {\r
   0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,\r
   0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
   0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,\r
   0xFF, 0x4A, 0x00, 0x32\r
 };\r
 \r
-UINT16 Seq_1024_768_24bpp_60[15] = {\r
+UINT16  Seq_1024_768_24bpp_60[15] = {\r
   0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1507, 0x0008, 0x4a0b,\r
   0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e\r
 };\r
 \r
-UINT8 Crtc_1024_768_32bpp_60[28] = {\r
+UINT8  Crtc_1024_768_32bpp_60[28] = {\r
   0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,\r
   0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
   0x02, 0x88, 0xFF, 0xe0, 0x00, 0x00, 0x64, 0xE3,\r
   0xFF, 0x4A, 0x00, 0x32\r
 };\r
 \r
-UINT16 Seq_1024_768_32bpp_60[15] = {\r
+UINT16  Seq_1024_768_32bpp_60[15] = {\r
   0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,\r
   0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e\r
 };\r
@@ -138,14 +137,14 @@ UINT16 Seq_1024_768_32bpp_60[15] = {
 /// Table of supported video modes\r
 ///\r
 QEMU_VIDEO_CIRRUS_MODES  QemuVideoCirrusModes[] = {\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
+  //  {  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
+  //  { 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
@@ -160,9 +159,9 @@ QemuVideoCirrusModeSetup (
   QEMU_VIDEO_PRIVATE_DATA  *Private\r
   )\r
 {\r
-  UINT32                                 Index;\r
-  QEMU_VIDEO_MODE_DATA                   *ModeData;\r
-  QEMU_VIDEO_CIRRUS_MODES                *VideoMode;\r
+  UINT32                   Index;\r
+  QEMU_VIDEO_MODE_DATA     *ModeData;\r
+  QEMU_VIDEO_CIRRUS_MODES  *VideoMode;\r
 \r
   //\r
   // Setup Video Modes\r
@@ -173,25 +172,28 @@ QemuVideoCirrusModeSetup (
   if (Private->ModeData == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
-  ModeData = Private->ModeData;\r
+\r
+  ModeData  = Private->ModeData;\r
   VideoMode = &QemuVideoCirrusModes[0];\r
-  for (Index = 0; Index < QEMU_VIDEO_CIRRUS_MODE_COUNT; Index ++) {\r
-    ModeData->InternalModeIndex = Index;\r
-    ModeData->HorizontalResolution          = VideoMode->Width;\r
-    ModeData->VerticalResolution            = VideoMode->Height;\r
-    ModeData->ColorDepth                    = VideoMode->ColorDepth;\r
-    DEBUG ((DEBUG_INFO,\r
+  for (Index = 0; Index < QEMU_VIDEO_CIRRUS_MODE_COUNT; Index++) {\r
+    ModeData->InternalModeIndex    = Index;\r
+    ModeData->HorizontalResolution = VideoMode->Width;\r
+    ModeData->VerticalResolution   = VideoMode->Height;\r
+    ModeData->ColorDepth           = VideoMode->ColorDepth;\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
       "Adding Mode %d as Cirrus Internal Mode %d: %dx%d, %d-bit\n",\r
-      (INT32) (ModeData - Private->ModeData),\r
+      (INT32)(ModeData - Private->ModeData),\r
       ModeData->InternalModeIndex,\r
       ModeData->HorizontalResolution,\r
       ModeData->VerticalResolution,\r
       ModeData->ColorDepth\r
       ));\r
 \r
-    ModeData ++ ;\r
-    VideoMode ++;\r
+    ModeData++;\r
+    VideoMode++;\r
   }\r
+\r
   Private->MaxMode = ModeData - Private->ModeData;\r
 \r
   return EFI_SUCCESS;\r
@@ -200,59 +202,178 @@ QemuVideoCirrusModeSetup (
 ///\r
 /// Table of supported video modes\r
 ///\r
-QEMU_VIDEO_BOCHS_MODES  QemuVideoBochsModes[] = {\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
+STATIC QEMU_VIDEO_BOCHS_MODES  QemuVideoBochsModes[] = {\r
+  { 640,  480  },\r
+  { 800,  480  },\r
+  { 800,  600  },\r
+  { 832,  624  },\r
+  { 960,  640  },\r
+  { 1024, 600  },\r
+  { 1024, 768  },\r
+  { 1152, 864  },\r
+  { 1152, 870  },\r
+  { 1280, 720  },\r
+  { 1280, 760  },\r
+  { 1280, 768  },\r
+  { 1280, 800  },\r
+  { 1280, 960  },\r
+  { 1280, 1024 },\r
+  { 1360, 768  },\r
+  { 1366, 768  },\r
+  { 1400, 1050 },\r
+  { 1440, 900  },\r
+  { 1600, 900  },\r
+  { 1600, 1200 },\r
+  { 1680, 1050 },\r
+  { 1920, 1080 },\r
+  { 1920, 1200 },\r
+  { 1920, 1440 },\r
+  { 2000, 2000 },\r
+  { 2048, 1536 },\r
+  { 2048, 2048 },\r
+  { 2560, 1440 },\r
+  { 2560, 1600 },\r
+  { 2560, 2048 },\r
+  { 2800, 2100 },\r
+  { 3200, 2400 },\r
+  { 3840, 2160 },\r
+  { 4096, 2160 },\r
+  { 7680, 4320 },\r
+  { 8192, 4320 }\r
 };\r
 \r
 #define QEMU_VIDEO_BOCHS_MODE_COUNT \\r
   (ARRAY_SIZE (QemuVideoBochsModes))\r
 \r
+STATIC\r
+VOID\r
+QemuVideoBochsAddMode (\r
+  QEMU_VIDEO_PRIVATE_DATA  *Private,\r
+  UINT32                   AvailableFbSize,\r
+  UINT32                   Width,\r
+  UINT32                   Height\r
+  )\r
+{\r
+  QEMU_VIDEO_MODE_DATA  *ModeData = Private->ModeData + Private->MaxMode;\r
+  UINTN                 RequiredFbSize;\r
+\r
+  RequiredFbSize = (UINTN)Width * Height * 4;\r
+  if (RequiredFbSize > AvailableFbSize) {\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "Skipping Bochs Mode %dx%d, 32-bit (not enough vram)\n",\r
+      Width,\r
+      Height\r
+      ));\r
+    return;\r
+  }\r
+\r
+  ModeData->InternalModeIndex    = (UINT32)Private->MaxMode;\r
+  ModeData->HorizontalResolution = Width;\r
+  ModeData->VerticalResolution   = Height;\r
+  ModeData->ColorDepth           = 32;\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "Adding Bochs Internal Mode %d: %dx%d, %d-bit\n",\r
+    ModeData->InternalModeIndex,\r
+    ModeData->HorizontalResolution,\r
+    ModeData->VerticalResolution,\r
+    ModeData->ColorDepth\r
+    ));\r
+\r
+  Private->MaxMode++;\r
+}\r
+\r
+STATIC\r
+VOID\r
+QemuVideoBochsEdid (\r
+  QEMU_VIDEO_PRIVATE_DATA  *Private,\r
+  UINT32                   *XRes,\r
+  UINT32                   *YRes\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  if (Private->Variant != QEMU_VIDEO_BOCHS_MMIO) {\r
+    return;\r
+  }\r
+\r
+  Status = Private->PciIo->Mem.Read (\r
+                                 Private->PciIo,\r
+                                 EfiPciIoWidthUint8,\r
+                                 PCI_BAR_IDX2,\r
+                                 0,\r
+                                 sizeof (Private->Edid),\r
+                                 Private->Edid\r
+                                 );\r
+  if (Status != EFI_SUCCESS) {\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a: mmio read failed\n",\r
+      __FUNCTION__\r
+      ));\r
+    return;\r
+  }\r
+\r
+  if ((Private->Edid[0] != 0x00) ||\r
+      (Private->Edid[1] != 0xff))\r
+  {\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a: magic check failed\n",\r
+      __FUNCTION__\r
+      ));\r
+    return;\r
+  }\r
+\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "%a: blob found (extensions: %d)\n",\r
+    __FUNCTION__,\r
+    Private->Edid[126]\r
+    ));\r
+\r
+  if ((Private->Edid[54] == 0x00) &&\r
+      (Private->Edid[55] == 0x00))\r
+  {\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a: no detailed timing descriptor\n",\r
+      __FUNCTION__\r
+      ));\r
+    return;\r
+  }\r
+\r
+  *XRes = Private->Edid[56] | ((Private->Edid[58] & 0xf0) << 4);\r
+  *YRes = Private->Edid[59] | ((Private->Edid[61] & 0xf0) << 4);\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "%a: default resolution: %dx%d\n",\r
+    __FUNCTION__,\r
+    *XRes,\r
+    *YRes\r
+    ));\r
+\r
+  if (PcdGet8 (PcdVideoResolutionSource) == 0) {\r
+    Status = PcdSet32S (PcdVideoHorizontalResolution, *XRes);\r
+    ASSERT_RETURN_ERROR (Status);\r
+    Status = PcdSet32S (PcdVideoVerticalResolution, *YRes);\r
+    ASSERT_RETURN_ERROR (Status);\r
+    Status = PcdSet8S (PcdVideoResolutionSource, 2);\r
+    ASSERT_RETURN_ERROR (Status);\r
+  }\r
+\r
+  // TODO: register edid as gEfiEdidDiscoveredProtocolGuid ?\r
+}\r
+\r
 EFI_STATUS\r
 QemuVideoBochsModeSetup (\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
+  UINT32  AvailableFbSize;\r
+  UINT32  Index, XRes = 0, YRes = 0;\r
 \r
   //\r
   // Fetch the available framebuffer size.\r
@@ -272,71 +393,99 @@ QemuVideoBochsModeSetup (
   // where it is also available.\r
   //\r
   if (IsQxl) {\r
-    UINT32 Signature;\r
-    UINT32 DrawStart;\r
+    UINT32  Signature;\r
+    UINT32  DrawStart;\r
 \r
-    Signature = 0;\r
-    DrawStart = 0xFFFFFFFF;\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
+          Private->PciIo->Mem.Read (\r
+                                Private->PciIo,\r
+                                EfiPciIoWidthUint32,\r
+                                PCI_BAR_IDX2,\r
+                                0,\r
+                                1,\r
+                                &Signature\r
+                                )\r
+          ) ||\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
+          Private->PciIo->Mem.Read (\r
+                                Private->PciIo,\r
+                                EfiPciIoWidthUint32,\r
+                                PCI_BAR_IDX2,\r
+                                36,\r
+                                1,\r
+                                &DrawStart\r
+                                )\r
+          ) ||\r
+        (DrawStart != 0) ||\r
         EFI_ERROR (\r
-          Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,\r
-                                PCI_BAR_IDX2, 40, 1, &AvailableFbSize))) {\r
-      DEBUG ((DEBUG_ERROR, "%a: can't read size of drawable buffer from QXL "\r
-        "ROM\n", __FUNCTION__));\r
+          Private->PciIo->Mem.Read (\r
+                                Private->PciIo,\r
+                                EfiPciIoWidthUint32,\r
+                                PCI_BAR_IDX2,\r
+                                40,\r
+                                1,\r
+                                &AvailableFbSize\r
+                                )\r
+          ))\r
+    {\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "%a: can't read size of drawable buffer from QXL "\r
+        "ROM\n",\r
+        __FUNCTION__\r
+        ));\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 ((DEBUG_INFO, "%a: AvailableFbSize=0x%x\n", __FUNCTION__,\r
-    AvailableFbSize));\r
+\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "%a: AvailableFbSize=0x%x\n",\r
+    __FUNCTION__,\r
+    AvailableFbSize\r
+    ));\r
 \r
   //\r
   // Setup Video Modes\r
   //\r
   Private->ModeData = AllocatePool (\r
-                        sizeof (Private->ModeData[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT\r
+                        sizeof (Private->ModeData[0]) * (QEMU_VIDEO_BOCHS_MODE_COUNT+1)\r
                         );\r
   if (Private->ModeData == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
-  ModeData = Private->ModeData;\r
-  VideoMode = &QemuVideoBochsModes[0];\r
-  for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index ++) {\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
-      DEBUG ((DEBUG_INFO,\r
-        "Adding Mode %d as Bochs Internal Mode %d: %dx%d, %d-bit\n",\r
-        (INT32) (ModeData - Private->ModeData),\r
-        ModeData->InternalModeIndex,\r
-        ModeData->HorizontalResolution,\r
-        ModeData->VerticalResolution,\r
-        ModeData->ColorDepth\r
-        ));\r
 \r
-      ModeData ++ ;\r
+  QemuVideoBochsEdid (Private, &XRes, &YRes);\r
+  if (XRes && YRes) {\r
+    QemuVideoBochsAddMode (\r
+      Private,\r
+      AvailableFbSize,\r
+      XRes,\r
+      YRes\r
+      );\r
+  }\r
+\r
+  for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index++) {\r
+    if ((QemuVideoBochsModes[Index].Width == XRes) &&\r
+        (QemuVideoBochsModes[Index].Height == YRes))\r
+    {\r
+      continue; // duplicate with edid resolution\r
     }\r
-    VideoMode ++;\r
+\r
+    QemuVideoBochsAddMode (\r
+      Private,\r
+      AvailableFbSize,\r
+      QemuVideoBochsModes[Index].Width,\r
+      QemuVideoBochsModes[Index].Height\r
+      );\r
   }\r
-  Private->MaxMode = ModeData - Private->ModeData;\r
 \r
   return EFI_SUCCESS;\r
 }\r
-\r