]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/QemuVideoDxe/Driver.c
ShellPkg/DP: Add more check for input parameters
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Driver.c
index 8d962b4438982ffbae4e838dd07be4d812a57111..73eb2cad05844fc93c1fe725bc9cc814e810a76a 100644 (file)
 \r
 **/\r
 \r
-#include "Qemu.h"\r
+#include <IndustryStandard/VmwareSvga.h>\r
 #include <IndustryStandard/Acpi.h>\r
+#include "Qemu.h"\r
+#include "UnalignedIoInternal.h"\r
 \r
 EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = {\r
   QemuVideoControllerDriverSupported,\r
@@ -28,35 +30,53 @@ EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = {
 \r
 QEMU_VIDEO_CARD gQemuVideoCardList[] = {\r
     {\r
+        PCI_CLASS_DISPLAY_VGA,\r
         CIRRUS_LOGIC_VENDOR_ID,\r
         CIRRUS_LOGIC_5430_DEVICE_ID,\r
         QEMU_VIDEO_CIRRUS_5430,\r
         L"Cirrus 5430"\r
     },{\r
+        PCI_CLASS_DISPLAY_VGA,\r
         CIRRUS_LOGIC_VENDOR_ID,\r
         CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID,\r
         QEMU_VIDEO_CIRRUS_5430,\r
         L"Cirrus 5430"\r
     },{\r
+        PCI_CLASS_DISPLAY_VGA,\r
         CIRRUS_LOGIC_VENDOR_ID,\r
         CIRRUS_LOGIC_5446_DEVICE_ID,\r
         QEMU_VIDEO_CIRRUS_5446,\r
         L"Cirrus 5446"\r
     },{\r
+        PCI_CLASS_DISPLAY_VGA,\r
         0x1234,\r
         0x1111,\r
         QEMU_VIDEO_BOCHS_MMIO,\r
         L"QEMU Standard VGA"\r
     },{\r
+        PCI_CLASS_DISPLAY_OTHER,\r
+        0x1234,\r
+        0x1111,\r
+        QEMU_VIDEO_BOCHS_MMIO,\r
+        L"QEMU Standard VGA (secondary)"\r
+    },{\r
+        PCI_CLASS_DISPLAY_VGA,\r
         0x1b36,\r
         0x0100,\r
         QEMU_VIDEO_BOCHS,\r
         L"QEMU QXL VGA"\r
     },{\r
+        PCI_CLASS_DISPLAY_VGA,\r
         0x1af4,\r
         0x1050,\r
         QEMU_VIDEO_BOCHS_MMIO,\r
         L"QEMU VirtIO VGA"\r
+    },{\r
+        PCI_CLASS_DISPLAY_VGA,\r
+        VMWARE_PCI_VENDOR_ID_VMWARE,\r
+        VMWARE_PCI_DEVICE_ID_VMWARE_SVGA2,\r
+        QEMU_VIDEO_VMWARE_SVGA,\r
+        L"QEMU VMWare SVGA"\r
     },{\r
         0 /* end of list */\r
     }\r
@@ -64,6 +84,7 @@ QEMU_VIDEO_CARD gQemuVideoCardList[] = {
 \r
 static QEMU_VIDEO_CARD*\r
 QemuVideoDetect(\r
+  IN UINT8 SubClass,\r
   IN UINT16 VendorId,\r
   IN UINT16 DeviceId\r
   )\r
@@ -71,7 +92,8 @@ QemuVideoDetect(
   UINTN Index = 0;\r
 \r
   while (gQemuVideoCardList[Index].VendorId != 0) {\r
-    if (gQemuVideoCardList[Index].VendorId == VendorId &&\r
+    if (gQemuVideoCardList[Index].SubClass == SubClass &&\r
+        gQemuVideoCardList[Index].VendorId == VendorId &&\r
         gQemuVideoCardList[Index].DeviceId == DeviceId) {\r
       return gQemuVideoCardList + Index;\r
     }\r
@@ -134,7 +156,10 @@ QemuVideoControllerDriverSupported (
   }\r
 \r
   Status = EFI_UNSUPPORTED;\r
-  Card = QemuVideoDetect(Pci.Hdr.VendorId, Pci.Hdr.DeviceId);\r
+  if (!IS_PCI_DISPLAY (&Pci)) {\r
+    goto Done;\r
+  }\r
+  Card = QemuVideoDetect(Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId);\r
   if (Card != NULL) {\r
     DEBUG ((EFI_D_INFO, "QemuVideo: %s detected\n", Card->Name));\r
     Status = EFI_SUCCESS;\r
@@ -233,12 +258,13 @@ QemuVideoControllerDriverStart (
   //\r
   // Determine card variant.\r
   //\r
-  Card = QemuVideoDetect(Pci.Hdr.VendorId, Pci.Hdr.DeviceId);\r
+  Card = QemuVideoDetect(Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId);\r
   if (Card == NULL) {\r
     Status = EFI_DEVICE_ERROR;\r
     goto ClosePciIo;\r
   }\r
   Private->Variant = Card->Variant;\r
+  Private->FrameBufferVramBarIndex = PCI_BAR_IDX0;\r
 \r
   //\r
   // IsQxl is based on the detected Card->Variant, which at a later point might\r
@@ -313,6 +339,58 @@ QemuVideoControllerDriverStart (
     }\r
   }\r
 \r
+  //\r
+  // Check if accessing Vmware SVGA interface works\r
+  //\r
+  if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {\r
+    EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *IoDesc;\r
+    UINT32                            TargetId;\r
+    UINT32                            SvgaIdRead;\r
+\r
+    IoDesc = NULL;\r
+    Status = Private->PciIo->GetBarAttributes (\r
+                               Private->PciIo,\r
+                               PCI_BAR_IDX0,\r
+                               NULL,\r
+                               (VOID**) &IoDesc\r
+                               );\r
+    if (EFI_ERROR (Status) ||\r
+        IoDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_IO ||\r
+        IoDesc->AddrRangeMin > MAX_UINT16 + 1 - (VMWARE_SVGA_VALUE_PORT + 4)) {\r
+      if (IoDesc != NULL) {\r
+        FreePool (IoDesc);\r
+      }\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto RestoreAttributes;\r
+    }\r
+    Private->VmwareSvgaBasePort = (UINT16) IoDesc->AddrRangeMin;\r
+    FreePool (IoDesc);\r
+\r
+    TargetId = VMWARE_SVGA_ID_2;\r
+    while (TRUE) {\r
+      VmwareSvgaWrite (Private, VmwareSvgaRegId, TargetId);\r
+      SvgaIdRead = VmwareSvgaRead (Private, VmwareSvgaRegId);\r
+      if ((SvgaIdRead == TargetId) || (TargetId <= VMWARE_SVGA_ID_0)) {\r
+        break;\r
+      }\r
+      TargetId--;\r
+    }\r
+\r
+    if (SvgaIdRead != TargetId) {\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "QemuVideo: QEMU_VIDEO_VMWARE_SVGA ID mismatch "\r
+        "(got 0x%x, base address 0x%x)\n",\r
+        SvgaIdRead,\r
+        Private->VmwareSvgaBasePort\r
+        ));\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto RestoreAttributes;\r
+    }\r
+\r
+    Private->FrameBufferVramBarIndex = PCI_BAR_IDX1;\r
+  }\r
+\r
   //\r
   // Get ParentDevicePath\r
   //\r
@@ -368,6 +446,9 @@ QemuVideoControllerDriverStart (
   case QEMU_VIDEO_BOCHS:\r
     Status = QemuVideoBochsModeSetup (Private, IsQxl);\r
     break;\r
+  case QEMU_VIDEO_VMWARE_SVGA:\r
+    Status = QemuVideoVmwareSvgaModeSetup (Private);\r
+    break;\r
   default:\r
     ASSERT (FALSE);\r
     Status = EFI_DEVICE_ERROR;\r
@@ -429,6 +510,9 @@ DestructQemuVideoGraphics:
 \r
 FreeModeData:\r
   FreePool (Private->ModeData);\r
+  if (Private->VmwareSvgaModeInfo != NULL) {\r
+    FreePool (Private->VmwareSvgaModeInfo);\r
+  }\r
 \r
 UninstallGopDevicePath:\r
   gBS->UninstallProtocolInterface (Private->Handle,\r
@@ -550,6 +634,9 @@ QemuVideoControllerDriverStop (
         );\r
 \r
   FreePool (Private->ModeData);\r
+  if (Private->VmwareSvgaModeInfo != NULL) {\r
+    FreePool (Private->VmwareSvgaModeInfo);\r
+  }\r
   gBS->UninstallProtocolInterface (Private->Handle,\r
          &gEfiDevicePathProtocolGuid, Private->GopDevicePath);\r
   FreePool (Private->GopDevicePath);\r
@@ -747,7 +834,7 @@ ClearScreen (
   Private->PciIo->Mem.Write (\r
                         Private->PciIo,\r
                         EfiPciIoWidthFillUint32,\r
-                        0,\r
+                        Private->FrameBufferVramBarIndex,\r
                         0,\r
                         0x400000 >> 2,\r
                         &Color\r
@@ -884,6 +971,38 @@ BochsRead (
   return Data;\r
 }\r
 \r
+VOID\r
+VmwareSvgaWrite (\r
+  QEMU_VIDEO_PRIVATE_DATA   *Private,\r
+  UINT16                    Register,\r
+  UINT32                    Value\r
+  )\r
+{\r
+  UnalignedIoWrite32 (\r
+    Private->VmwareSvgaBasePort + VMWARE_SVGA_INDEX_PORT,\r
+    Register\r
+    );\r
+  UnalignedIoWrite32 (\r
+    Private->VmwareSvgaBasePort + VMWARE_SVGA_VALUE_PORT,\r
+    Value\r
+    );\r
+}\r
+\r
+UINT32\r
+VmwareSvgaRead (\r
+  QEMU_VIDEO_PRIVATE_DATA   *Private,\r
+  UINT16                    Register\r
+  )\r
+{\r
+  UnalignedIoWrite32 (\r
+    Private->VmwareSvgaBasePort + VMWARE_SVGA_INDEX_PORT,\r
+    Register\r
+    );\r
+  return UnalignedIoRead32 (\r
+           Private->VmwareSvgaBasePort + VMWARE_SVGA_VALUE_PORT\r
+           );\r
+}\r
+\r
 VOID\r
 VgaOutb (\r
   QEMU_VIDEO_PRIVATE_DATA  *Private,\r
@@ -938,6 +1057,35 @@ InitializeBochsGraphicsMode (
   ClearScreen (Private);\r
 }\r
 \r
+VOID\r
+InitializeVmwareSvgaGraphicsMode (\r
+  QEMU_VIDEO_PRIVATE_DATA  *Private,\r
+  QEMU_VIDEO_BOCHS_MODES   *ModeData\r
+  )\r
+{\r
+  UINT32 Capabilities;\r
+\r
+  VmwareSvgaWrite (Private, VmwareSvgaRegWidth, ModeData->Width);\r
+  VmwareSvgaWrite (Private, VmwareSvgaRegHeight, ModeData->Height);\r
+\r
+  Capabilities = VmwareSvgaRead (\r
+                   Private,\r
+                   VmwareSvgaRegCapabilities\r
+                   );\r
+  if ((Capabilities & VMWARE_SVGA_CAP_8BIT_EMULATION) != 0) {\r
+    VmwareSvgaWrite (\r
+      Private,\r
+      VmwareSvgaRegBitsPerPixel,\r
+      ModeData->ColorDepth\r
+      );\r
+  }\r
+\r
+  VmwareSvgaWrite (Private, VmwareSvgaRegEnable, 1);\r
+\r
+  SetDefaultPalette (Private);\r
+  ClearScreen (Private);\r
+}\r
+\r
 EFI_STATUS\r
 EFIAPI\r
 InitializeQemuVideo (\r