]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg: add QemuRamfbDxe
authorGerd Hoffmann <kraxel@redhat.com>
Wed, 13 Jun 2018 07:29:34 +0000 (09:29 +0200)
committerLaszlo Ersek <lersek@redhat.com>
Thu, 14 Jun 2018 09:56:45 +0000 (11:56 +0200)
Add a driver for the qemu ramfb display device.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
[lersek@redhat.com: fix INF banner typo]
[lersek@redhat.com: make some local variable definitions more idiomatic]
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
OvmfPkg/OvmfPkgIa32.dsc
OvmfPkg/OvmfPkgIa32.fdf
OvmfPkg/OvmfPkgIa32X64.dsc
OvmfPkg/OvmfPkgIa32X64.fdf
OvmfPkg/OvmfPkgX64.dsc
OvmfPkg/OvmfPkgX64.fdf
OvmfPkg/QemuRamfbDxe/QemuRamfb.c [new file with mode: 0644]
OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf [new file with mode: 0644]

index a2c995b910cd21b9434ca6f141798a04dc0be5a5..7ddda89999e8aae4b83eeaff87476cb0d6e47879 100644 (file)
   MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
 \r
   OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf\r
   MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
 \r
   OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf\r
+  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf\r
   OvmfPkg/VirtioGpuDxe/VirtioGpu.inf\r
 \r
   #\r
   OvmfPkg/VirtioGpuDxe/VirtioGpu.inf\r
 \r
   #\r
index b199713925fe7c01e97c1b0e057be8973edd40f6..52b8b1fea1fcd7cae422918562985cf9f9e61754 100644 (file)
@@ -351,6 +351,7 @@ INF  RuleOverride=CSM OvmfPkg/Csm/Csm16/Csm16.inf
 !endif\r
 \r
 INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf\r
 !endif\r
 \r
 INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf\r
+INF  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf\r
 INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf\r
 INF  OvmfPkg/PlatformDxe/Platform.inf\r
 INF  OvmfPkg/IoMmuDxe/IoMmuDxe.inf\r
 INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf\r
 INF  OvmfPkg/PlatformDxe/Platform.inf\r
 INF  OvmfPkg/IoMmuDxe/IoMmuDxe.inf\r
index bc7db229d2d93ab6be8d49cce72da9aa21d753b7..3481cdc36b42cb1267e7a217ec407a4c2fa0c823 100644 (file)
   MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
 \r
   OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf\r
   MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
 \r
   OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf\r
+  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf\r
   OvmfPkg/VirtioGpuDxe/VirtioGpu.inf\r
 \r
   #\r
   OvmfPkg/VirtioGpuDxe/VirtioGpu.inf\r
 \r
   #\r
index 4ebf64b2b9dcfcf2a560444645795207334c6cec..70845d6972fd83542dc35619dc02f30e59ce866b 100644 (file)
@@ -357,6 +357,7 @@ INF  RuleOverride=CSM OvmfPkg/Csm/Csm16/Csm16.inf
 !endif\r
 \r
 INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf\r
 !endif\r
 \r
 INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf\r
+INF  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf\r
 INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf\r
 INF  OvmfPkg/PlatformDxe/Platform.inf\r
 INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf\r
 INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf\r
 INF  OvmfPkg/PlatformDxe/Platform.inf\r
 INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf\r
index 0767b34d1877e7708c3f95c573c271ff72b76a1b..8b0895b0ffa519c7d2254f7d7f0dc57c69bc5b43 100644 (file)
   MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
 \r
   OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf\r
   MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
 \r
   OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf\r
+  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf\r
   OvmfPkg/VirtioGpuDxe/VirtioGpu.inf\r
 \r
   #\r
   OvmfPkg/VirtioGpuDxe/VirtioGpu.inf\r
 \r
   #\r
index 9ca96f92828728f6dfc60d419130a80a57412975..1eb46ac9a2d8e478ec8ce20117fad9f488efdaf8 100644 (file)
@@ -357,6 +357,7 @@ INF  RuleOverride=CSM OvmfPkg/Csm/Csm16/Csm16.inf
 !endif\r
 \r
 INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf\r
 !endif\r
 \r
 INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf\r
+INF  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf\r
 INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf\r
 INF  OvmfPkg/PlatformDxe/Platform.inf\r
 INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf\r
 INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf\r
 INF  OvmfPkg/PlatformDxe/Platform.inf\r
 INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf\r
diff --git a/OvmfPkg/QemuRamfbDxe/QemuRamfb.c b/OvmfPkg/QemuRamfbDxe/QemuRamfb.c
new file mode 100644 (file)
index 0000000..b49f2ca
--- /dev/null
@@ -0,0 +1,400 @@
+/** @file\r
+  This driver is a implementation of the Graphics Output Protocol\r
+  for the QEMU ramfb device.\r
+\r
+  Copyright (c) 2018, Red Hat Inc.\r
+\r
+  This program and the accompanying materials are licensed and made\r
+  available under the terms and conditions of the BSD License which\r
+  accompanies this distribution. The full text of the license may be\r
+  found at http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"\r
+  BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER\r
+  EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Protocol/GraphicsOutput.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/FrameBufferBltLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/QemuFwCfgLib.h>\r
+\r
+#include <Guid/QemuRamfb.h>\r
+\r
+#define RAMFB_FORMAT  0x34325258 /* DRM_FORMAT_XRGB8888 */\r
+#define RAMFB_BPP     4\r
+\r
+#pragma pack (1)\r
+typedef struct RAMFB_CONFIG {\r
+  UINT64 Address;\r
+  UINT32 FourCC;\r
+  UINT32 Flags;\r
+  UINT32 Width;\r
+  UINT32 Height;\r
+  UINT32 Stride;\r
+} RAMFB_CONFIG;\r
+#pragma pack ()\r
+\r
+STATIC EFI_HANDLE                    mRamfbHandle;\r
+STATIC EFI_HANDLE                    mGopHandle;\r
+STATIC FRAME_BUFFER_CONFIGURE        *mQemuRamfbFrameBufferBltConfigure;\r
+STATIC UINTN                         mQemuRamfbFrameBufferBltConfigureSize;\r
+STATIC FIRMWARE_CONFIG_ITEM          mRamfbFwCfgItem;\r
+\r
+STATIC EFI_GRAPHICS_OUTPUT_MODE_INFORMATION mQemuRamfbModeInfo[] = {\r
+  {\r
+    0,    // Version\r
+    640,  // HorizontalResolution\r
+    480,  // VerticalResolution\r
+  },{\r
+    0,    // Version\r
+    800,  // HorizontalResolution\r
+    600,  // VerticalResolution\r
+  },{\r
+    0,    // Version\r
+    1024, // HorizontalResolution\r
+    768,  // VerticalResolution\r
+  }\r
+};\r
+\r
+STATIC EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE mQemuRamfbMode = {\r
+  ARRAY_SIZE (mQemuRamfbModeInfo),                // MaxMode\r
+  0,                                              // Mode\r
+  mQemuRamfbModeInfo,                             // Info\r
+  sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),  // SizeOfInfo\r
+};\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+QemuRamfbGraphicsOutputQueryMode (\r
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,\r
+  IN  UINT32                                ModeNumber,\r
+  OUT UINTN                                 *SizeOfInfo,\r
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info\r
+  )\r
+{\r
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *ModeInfo;\r
+\r
+  if (Info == NULL || SizeOfInfo == NULL ||\r
+      ModeNumber >= mQemuRamfbMode.MaxMode) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  ModeInfo = &mQemuRamfbModeInfo[ModeNumber];\r
+\r
+  *Info = AllocateCopyPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
+            ModeInfo);\r
+  if (*Info == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+QemuRamfbGraphicsOutputSetMode (\r
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
+  IN  UINT32                       ModeNumber\r
+  )\r
+{\r
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *ModeInfo;\r
+  RAMFB_CONFIG                          Config;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         Black;\r
+  RETURN_STATUS                         Status;\r
+\r
+  if (ModeNumber >= mQemuRamfbMode.MaxMode) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  ModeInfo = &mQemuRamfbModeInfo[ModeNumber];\r
+\r
+  DEBUG ((DEBUG_INFO, "Ramfb: SetMode %u (%ux%u)\n", ModeNumber,\r
+    ModeInfo->HorizontalResolution, ModeInfo->VerticalResolution));\r
+\r
+  Config.Address = SwapBytes64 (mQemuRamfbMode.FrameBufferBase);\r
+  Config.FourCC  = SwapBytes32 (RAMFB_FORMAT);\r
+  Config.Flags   = SwapBytes32 (0);\r
+  Config.Width   = SwapBytes32 (ModeInfo->HorizontalResolution);\r
+  Config.Height  = SwapBytes32 (ModeInfo->VerticalResolution);\r
+  Config.Stride  = SwapBytes32 (ModeInfo->HorizontalResolution * RAMFB_BPP);\r
+\r
+  Status = FrameBufferBltConfigure (\r
+             (VOID*)(UINTN)mQemuRamfbMode.FrameBufferBase,\r
+             ModeInfo,\r
+             mQemuRamfbFrameBufferBltConfigure,\r
+             &mQemuRamfbFrameBufferBltConfigureSize\r
+             );\r
+\r
+  if (Status == RETURN_BUFFER_TOO_SMALL) {\r
+    if (mQemuRamfbFrameBufferBltConfigure != NULL) {\r
+      FreePool (mQemuRamfbFrameBufferBltConfigure);\r
+    }\r
+    mQemuRamfbFrameBufferBltConfigure =\r
+      AllocatePool (mQemuRamfbFrameBufferBltConfigureSize);\r
+    if (mQemuRamfbFrameBufferBltConfigure == NULL) {\r
+      mQemuRamfbFrameBufferBltConfigureSize = 0;\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    Status = FrameBufferBltConfigure (\r
+               (VOID*)(UINTN)mQemuRamfbMode.FrameBufferBase,\r
+               ModeInfo,\r
+               mQemuRamfbFrameBufferBltConfigure,\r
+               &mQemuRamfbFrameBufferBltConfigureSize\r
+               );\r
+  }\r
+  if (RETURN_ERROR (Status)) {\r
+    ASSERT (Status == RETURN_UNSUPPORTED);\r
+    return Status;\r
+  }\r
+\r
+  mQemuRamfbMode.Mode = ModeNumber;\r
+  mQemuRamfbMode.Info = ModeInfo;\r
+\r
+  QemuFwCfgSelectItem (mRamfbFwCfgItem);\r
+  QemuFwCfgWriteBytes (sizeof (Config), &Config);\r
+\r
+  //\r
+  // clear screen\r
+  //\r
+  ZeroMem (&Black, sizeof (Black));\r
+  Status = FrameBufferBlt (\r
+             mQemuRamfbFrameBufferBltConfigure,\r
+             &Black,\r
+             EfiBltVideoFill,\r
+             0,                               // SourceX -- ignored\r
+             0,                               // SourceY -- ignored\r
+             0,                               // DestinationX\r
+             0,                               // DestinationY\r
+             ModeInfo->HorizontalResolution,  // Width\r
+             ModeInfo->VerticalResolution,    // Height\r
+             0                                // Delta -- ignored\r
+             );\r
+  if (RETURN_ERROR (Status)) {\r
+    DEBUG ((DEBUG_WARN, "%a: clearing the screen failed: %r\n",\r
+      __FUNCTION__, Status));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+QemuRamfbGraphicsOutputBlt (\r
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,\r
+  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer, OPTIONAL\r
+  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION     BltOperation,\r
+  IN  UINTN                                 SourceX,\r
+  IN  UINTN                                 SourceY,\r
+  IN  UINTN                                 DestinationX,\r
+  IN  UINTN                                 DestinationY,\r
+  IN  UINTN                                 Width,\r
+  IN  UINTN                                 Height,\r
+  IN  UINTN                                 Delta\r
+  )\r
+{\r
+  return FrameBufferBlt (\r
+           mQemuRamfbFrameBufferBltConfigure,\r
+           BltBuffer,\r
+           BltOperation,\r
+           SourceX,\r
+           SourceY,\r
+           DestinationX,\r
+           DestinationY,\r
+           Width,\r
+           Height,\r
+           Delta\r
+           );\r
+}\r
+\r
+STATIC EFI_GRAPHICS_OUTPUT_PROTOCOL mQemuRamfbGraphicsOutput = {\r
+  QemuRamfbGraphicsOutputQueryMode,\r
+  QemuRamfbGraphicsOutputSetMode,\r
+  QemuRamfbGraphicsOutputBlt,\r
+  &mQemuRamfbMode,\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeQemuRamfb (\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *RamfbDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;\r
+  VOID                      *DevicePath;\r
+  VENDOR_DEVICE_PATH        VendorDeviceNode;\r
+  ACPI_ADR_DEVICE_PATH      AcpiDeviceNode;\r
+  EFI_STATUS                Status;\r
+  EFI_PHYSICAL_ADDRESS      FbBase;\r
+  UINTN                     FbSize, MaxFbSize, Pages;\r
+  UINTN                     FwCfgSize;\r
+  UINTN                     Index;\r
+\r
+  if (!QemuFwCfgIsAvailable ()) {\r
+    DEBUG ((DEBUG_INFO, "Ramfb: no FwCfg\n"));\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Status = QemuFwCfgFindFile ("etc/ramfb", &mRamfbFwCfgItem, &FwCfgSize);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  if (FwCfgSize != sizeof (RAMFB_CONFIG)) {\r
+    DEBUG ((DEBUG_ERROR, "Ramfb: FwCfg size mismatch (expected %lu, got %lu)\n",\r
+      (UINT64)sizeof (RAMFB_CONFIG), (UINT64)FwCfgSize));\r
+    return EFI_PROTOCOL_ERROR;\r
+  }\r
+\r
+  MaxFbSize = 0;\r
+  for (Index = 0; Index < ARRAY_SIZE (mQemuRamfbModeInfo); Index++) {\r
+    mQemuRamfbModeInfo[Index].PixelsPerScanLine =\r
+      mQemuRamfbModeInfo[Index].HorizontalResolution;\r
+    mQemuRamfbModeInfo[Index].PixelFormat =\r
+      PixelBlueGreenRedReserved8BitPerColor;\r
+    FbSize = RAMFB_BPP *\r
+      mQemuRamfbModeInfo[Index].HorizontalResolution *\r
+      mQemuRamfbModeInfo[Index].VerticalResolution;\r
+    if (MaxFbSize < FbSize) {\r
+      MaxFbSize = FbSize;\r
+    }\r
+    DEBUG ((DEBUG_INFO, "Ramfb: Mode %lu: %ux%u, %lu kB\n", (UINT64)Index,\r
+      mQemuRamfbModeInfo[Index].HorizontalResolution,\r
+      mQemuRamfbModeInfo[Index].VerticalResolution,\r
+      (UINT64)(FbSize / 1024)));\r
+  }\r
+\r
+  Pages = EFI_SIZE_TO_PAGES (MaxFbSize);\r
+  MaxFbSize = EFI_PAGES_TO_SIZE (Pages);\r
+  FbBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateReservedPages (Pages);\r
+  if (FbBase == 0) {\r
+    DEBUG ((DEBUG_ERROR, "Ramfb: memory allocation failed\n"));\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  DEBUG ((DEBUG_INFO, "Ramfb: Framebuffer at 0x%lx, %lu kB, %lu pages\n",\r
+    (UINT64)FbBase, (UINT64)(MaxFbSize / 1024), (UINT64)Pages));\r
+  mQemuRamfbMode.FrameBufferSize = MaxFbSize;\r
+  mQemuRamfbMode.FrameBufferBase = FbBase;\r
+\r
+  //\r
+  // 800 x 600\r
+  //\r
+  QemuRamfbGraphicsOutputSetMode (&mQemuRamfbGraphicsOutput, 1);\r
+\r
+  //\r
+  // ramfb vendor devpath\r
+  //\r
+  VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;\r
+  VendorDeviceNode.Header.SubType = HW_VENDOR_DP;\r
+  CopyGuid (&VendorDeviceNode.Guid, &gQemuRamfbGuid);\r
+  SetDevicePathNodeLength (&VendorDeviceNode.Header,\r
+    sizeof (VENDOR_DEVICE_PATH));\r
+\r
+  RamfbDevicePath = AppendDevicePathNode (NULL,\r
+    (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode);\r
+  if (RamfbDevicePath == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto FreeFramebuffer;\r
+  }\r
+\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &mRamfbHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  RamfbDevicePath,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Ramfb: install Ramfb Vendor DevicePath failed: %r\n",\r
+      Status));\r
+    goto FreeRamfbDevicePath;\r
+  }\r
+\r
+  //\r
+  // gop devpath + protocol\r
+  //\r
+  AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
+  AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
+  AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (\r
+    1,                                       // DeviceIdScheme\r
+    0,                                       // HeadId\r
+    0,                                       // NonVgaOutput\r
+    1,                                       // BiosCanDetect\r
+    0,                                       // VendorInfo\r
+    ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL,  // Type\r
+    0,                                       // Port\r
+    0                                        // Index\r
+    );\r
+  SetDevicePathNodeLength (&AcpiDeviceNode.Header,\r
+    sizeof (ACPI_ADR_DEVICE_PATH));\r
+\r
+  GopDevicePath = AppendDevicePathNode (RamfbDevicePath,\r
+    (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode);\r
+  if (GopDevicePath == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto FreeRamfbHandle;\r
+  }\r
+\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &mGopHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  GopDevicePath,\r
+                  &gEfiGraphicsOutputProtocolGuid,\r
+                  &mQemuRamfbGraphicsOutput,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Ramfb: install GOP DevicePath failed: %r\n",\r
+      Status));\r
+    goto FreeGopDevicePath;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  mRamfbHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  &DevicePath,\r
+                  gImageHandle,\r
+                  mGopHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Ramfb: OpenProtocol failed: %r\n", Status));\r
+    goto FreeGopHandle;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+FreeGopHandle:\r
+  gBS->UninstallMultipleProtocolInterfaces (\r
+         mGopHandle,\r
+         &gEfiDevicePathProtocolGuid,\r
+         GopDevicePath,\r
+         &gEfiGraphicsOutputProtocolGuid,\r
+         &mQemuRamfbGraphicsOutput,\r
+         NULL\r
+         );\r
+FreeGopDevicePath:\r
+  FreePool (GopDevicePath);\r
+FreeRamfbHandle:\r
+  gBS->UninstallMultipleProtocolInterfaces (\r
+         mRamfbHandle,\r
+         &gEfiDevicePathProtocolGuid,\r
+         RamfbDevicePath,\r
+         NULL\r
+         );\r
+FreeRamfbDevicePath:\r
+  FreePool (RamfbDevicePath);\r
+FreeFramebuffer:\r
+  FreePages ((VOID*)(UINTN)mQemuRamfbMode.FrameBufferBase, Pages);\r
+  return Status;\r
+}\r
diff --git a/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf b/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
new file mode 100644 (file)
index 0000000..013edef
--- /dev/null
@@ -0,0 +1,53 @@
+## @file\r
+#  This driver is a implementation of the Graphics Output Protocol\r
+#  for the QEMU ramfb device.\r
+#\r
+#  Copyright (c) 2018, Red Hat Inc.\r
+#\r
+#  This program and the accompanying materials are licensed and made\r
+#  available under the terms and conditions of the BSD License which\r
+#  accompanies this distribution. The full text of the license may be\r
+#  found at http://opensource.org/licenses/bsd-license.php\r
+#\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"\r
+#  BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER\r
+#  EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = QemuRamfbDxe\r
+  FILE_GUID                      = dce1b094-7dc6-45d0-9fdd-d7fc3cc3e4ef\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+\r
+  ENTRY_POINT                    = InitializeQemuRamfb\r
+\r
+[Sources]\r
+  QemuRamfb.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  OvmfPkg/OvmfPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  DevicePathLib\r
+  FrameBufferBltLib\r
+  MemoryAllocationLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+  QemuFwCfgLib\r
+\r
+[Protocols]\r
+  gEfiGraphicsOutputProtocolGuid                ## PRODUCES\r
+\r
+[Guids]\r
+  gQemuRamfbGuid\r
+\r
+[Depex]\r
+  TRUE\r