[edk2] [PATCH 2/4] OvmfPkg: add QemuRamfbDxe

Gerd Hoffmann posted 4 patches 7 years, 1 month ago
There is a newer version of this series
[edk2] [PATCH 2/4] OvmfPkg: add QemuRamfbDxe
Posted by Gerd Hoffmann 7 years, 1 month ago
Add a driver for the qemu ramfb display device.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 OvmfPkg/QemuRamfbDxe/QemuRamfb.c      | 308 ++++++++++++++++++++++++++++++++++
 OvmfPkg/OvmfPkgIa32.dsc               |   1 +
 OvmfPkg/OvmfPkgIa32.fdf               |   1 +
 OvmfPkg/OvmfPkgIa32X64.dsc            |   1 +
 OvmfPkg/OvmfPkgIa32X64.fdf            |   1 +
 OvmfPkg/OvmfPkgX64.dsc                |   1 +
 OvmfPkg/OvmfPkgX64.fdf                |   1 +
 OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf |  34 ++++
 8 files changed, 348 insertions(+)
 create mode 100644 OvmfPkg/QemuRamfbDxe/QemuRamfb.c
 create mode 100644 OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf

diff --git a/OvmfPkg/QemuRamfbDxe/QemuRamfb.c b/OvmfPkg/QemuRamfbDxe/QemuRamfb.c
new file mode 100644
index 0000000000..f04a314c24
--- /dev/null
+++ b/OvmfPkg/QemuRamfbDxe/QemuRamfb.c
@@ -0,0 +1,308 @@
+#include <Uefi.h>
+#include <Protocol/GraphicsOutput.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/FrameBufferBltLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/QemuFwCfgLib.h>
+
+#include <Guid/QemuRamfb.h>
+
+#define RAMFB_FORMAT  0x34325258 /* DRM_FORMAT_XRGB8888 */
+#define RAMFB_BPP     4
+
+EFI_GUID gQemuRamfbGuid = QEMU_RAMFB_GUID;
+
+typedef struct RAMFB_CONFIG {
+  UINT64 Address;
+  UINT32 FourCC;
+  UINT32 Flags;
+  UINT32 Width;
+  UINT32 Height;
+  UINT32 Stride;
+} RAMFB_CONFIG;
+
+EFI_HANDLE                    RamfbHandle;
+EFI_HANDLE                    GopHandle;
+FRAME_BUFFER_CONFIGURE        *QemuRamfbFrameBufferBltConfigure;
+UINTN                         QemuRamfbFrameBufferBltConfigureSize;
+
+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION QemuRamfbModeInfo[] = {
+  {
+    .HorizontalResolution  = 640,
+    .VerticalResolution    = 480,
+  },{
+    .HorizontalResolution  = 800,
+    .VerticalResolution    = 600,
+  },{
+    .HorizontalResolution  = 1024,
+    .VerticalResolution    = 768,
+  }
+};
+#define QemuRamfbModeCount (sizeof(QemuRamfbModeInfo)/sizeof(QemuRamfbModeInfo[0]))
+
+EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE QemuRamfbMode = {
+  .MaxMode               = QemuRamfbModeCount,
+  .Mode                  = 0,
+  .Info                  = QemuRamfbModeInfo,
+  .SizeOfInfo            = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
+};
+
+EFI_STATUS
+EFIAPI
+QemuRamfbGraphicsOutputQueryMode (
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
+  IN  UINT32                                ModeNumber,
+  OUT UINTN                                 *SizeOfInfo,
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
+  )
+{
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *ModeInfo;
+
+  if (Info == NULL || SizeOfInfo == NULL || ModeNumber > QemuRamfbMode.MaxMode) {
+    return EFI_INVALID_PARAMETER;
+  }
+  ModeInfo = &QemuRamfbModeInfo[ModeNumber];
+
+  *Info = AllocateCopyPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
+                            ModeInfo);
+  if (*Info == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+QemuRamfbGraphicsOutputSetMode (
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+  IN  UINT32                       ModeNumber
+  )
+{
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *ModeInfo;
+  RAMFB_CONFIG                          Config;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         Black;
+  RETURN_STATUS                         Ret;
+  FIRMWARE_CONFIG_ITEM                  Item;
+  UINTN                                 Size;
+
+  if (ModeNumber > QemuRamfbMode.MaxMode) {
+    return EFI_UNSUPPORTED;
+  }
+  ModeInfo = &QemuRamfbModeInfo[ModeNumber];
+
+  DEBUG ((EFI_D_INFO, "Ramfb: SetMode %d (%dx%d)\n", ModeNumber,
+          ModeInfo->HorizontalResolution,
+          ModeInfo->VerticalResolution));
+
+  QemuRamfbMode.Mode = ModeNumber;
+  QemuRamfbMode.Info = ModeInfo;
+
+  Config.Address = SwapBytes64( QemuRamfbMode.FrameBufferBase );
+  Config.FourCC  = SwapBytes32( RAMFB_FORMAT );
+  Config.Flags   = SwapBytes32( 0 );
+  Config.Width   = SwapBytes32( ModeInfo->HorizontalResolution );
+  Config.Height  = SwapBytes32( ModeInfo->VerticalResolution );
+  Config.Stride  = SwapBytes32( ModeInfo->HorizontalResolution * RAMFB_BPP );
+
+  QemuFwCfgFindFile("etc/ramfb", &Item, &Size);
+  QemuFwCfgSelectItem(Item);
+  QemuFwCfgWriteBytes(sizeof(Config), &Config);
+
+  Ret = FrameBufferBltConfigure (
+    (VOID*)(UINTN)QemuRamfbMode.FrameBufferBase,
+    ModeInfo,
+    QemuRamfbFrameBufferBltConfigure,
+    &QemuRamfbFrameBufferBltConfigureSize);
+
+  if (Ret == RETURN_BUFFER_TOO_SMALL) {
+    if (QemuRamfbFrameBufferBltConfigure != NULL) {
+      FreePool(QemuRamfbFrameBufferBltConfigure);
+    }
+    QemuRamfbFrameBufferBltConfigure =
+      AllocatePool(QemuRamfbFrameBufferBltConfigureSize);
+
+    Ret = FrameBufferBltConfigure (
+      (VOID*)(UINTN)QemuRamfbMode.FrameBufferBase,
+      ModeInfo,
+      QemuRamfbFrameBufferBltConfigure,
+      &QemuRamfbFrameBufferBltConfigureSize);
+  }
+
+  /* clear screen */
+  ZeroMem (&Black, sizeof (Black));
+  Ret = FrameBufferBlt (
+    QemuRamfbFrameBufferBltConfigure,
+    &Black,
+    EfiBltVideoFill,
+    0, 0,
+    0, 0,
+    ModeInfo->HorizontalResolution,
+    ModeInfo->VerticalResolution,
+    0
+    );
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+QemuRamfbGraphicsOutputBlt (
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
+  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer, OPTIONAL
+  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION     BltOperation,
+  IN  UINTN                                 SourceX,
+  IN  UINTN                                 SourceY,
+  IN  UINTN                                 DestinationX,
+  IN  UINTN                                 DestinationY,
+  IN  UINTN                                 Width,
+  IN  UINTN                                 Height,
+  IN  UINTN                                 Delta
+  )
+{
+  return FrameBufferBlt (
+    QemuRamfbFrameBufferBltConfigure,
+    BltBuffer,
+    BltOperation,
+    SourceX,
+    SourceY,
+    DestinationX,
+    DestinationY,
+    Width,
+    Height,
+    Delta);
+}
+
+EFI_GRAPHICS_OUTPUT_PROTOCOL QemuRamfbGraphicsOutput = {
+  .QueryMode        = QemuRamfbGraphicsOutputQueryMode,
+  .SetMode          = QemuRamfbGraphicsOutputSetMode,
+  .Blt              = QemuRamfbGraphicsOutputBlt,
+  .Mode             = &QemuRamfbMode,
+};
+
+EFI_STATUS
+EFIAPI
+InitializeQemuRamfb (
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *RamfbDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
+  VOID                      *DevicePath;
+  VENDOR_DEVICE_PATH        VendorDeviceNode;
+  ACPI_ADR_DEVICE_PATH      AcpiDeviceNode;
+  EFI_STATUS                Status;
+  RETURN_STATUS             Ret;
+  FIRMWARE_CONFIG_ITEM      Item;
+  EFI_PHYSICAL_ADDRESS      FbBase;
+  UINTN                     Size, FbSize, MaxFbSize, Pages, Index;
+
+  DEBUG ((EFI_D_INFO, "InitializeQemuRamfb\n"));
+
+  if (!QemuFwCfgIsAvailable()) {
+    DEBUG ((EFI_D_INFO, "Ramfb: no FwCfg\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  Ret = QemuFwCfgFindFile("etc/ramfb", &Item, &Size);
+  if (Ret != RETURN_SUCCESS) {
+    DEBUG ((EFI_D_INFO, "Ramfb: no etc/ramfb in FwCfg\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  MaxFbSize = 0;
+  for (Index = 0; Index < QemuRamfbModeCount; Index++) {
+    QemuRamfbModeInfo[Index].PixelsPerScanLine =
+      QemuRamfbModeInfo[Index].HorizontalResolution;
+    QemuRamfbModeInfo[Index].PixelFormat =
+      PixelBlueGreenRedReserved8BitPerColor,
+    FbSize = RAMFB_BPP *
+      QemuRamfbModeInfo[Index].HorizontalResolution *
+      QemuRamfbModeInfo[Index].VerticalResolution;
+    if (MaxFbSize < FbSize)
+      MaxFbSize = FbSize;
+    DEBUG ((EFI_D_INFO, "Ramfb: Mode %d: %dx%d, %d kB\n", Index,
+            QemuRamfbModeInfo[Index].HorizontalResolution,
+            QemuRamfbModeInfo[Index].VerticalResolution,
+            FbSize / 1024));
+  }
+
+  Pages = EFI_SIZE_TO_PAGES(MaxFbSize);
+  MaxFbSize = EFI_PAGES_TO_SIZE(Pages);
+  FbBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateRuntimePages(Pages);
+  if (!FbBase) {
+    DEBUG ((EFI_D_INFO, "Ramfb: memory allocation failed\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+  DEBUG ((EFI_D_INFO, "Ramfb: Framebuffer at 0x%lx, %d kB, %d pages\n",
+          FbBase, MaxFbSize / 1024, Pages));
+  QemuRamfbMode.FrameBufferSize = MaxFbSize;
+  QemuRamfbMode.FrameBufferBase = FbBase;
+
+  /* 800 x 600 */
+  QemuRamfbGraphicsOutputSetMode (&QemuRamfbGraphicsOutput, 1);
+
+  /* ramfb vendor devpath */
+  ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
+  VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
+  VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
+  VendorDeviceNode.Guid = gQemuRamfbGuid;
+  SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));
+
+  RamfbDevicePath = AppendDevicePathNode (
+    NULL,
+    (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode);
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+    &RamfbHandle,
+    &gEfiDevicePathProtocolGuid, RamfbDevicePath,
+    NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_INFO, "Ramfb: install Ramfb Vendor DevicePath failed\n"));
+    FreePool((VOID*)(UINTN)QemuRamfbMode.FrameBufferBase);
+    return Status;
+  }
+
+  /* gop devpath + protocol */
+  ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
+  AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
+  AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
+  AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0,
+                                         ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL,
+                                         0, 0);
+  SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
+
+  GopDevicePath = AppendDevicePathNode (
+    RamfbDevicePath,
+    (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode);
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+    &GopHandle,
+    &gEfiDevicePathProtocolGuid, GopDevicePath,
+    &gEfiGraphicsOutputProtocolGuid, &QemuRamfbGraphicsOutput,
+    NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_INFO, "Ramfb: install GOP DevicePath failed\n"));
+    FreePool((VOID*)(UINTN)QemuRamfbMode.FrameBufferBase);
+    return Status;
+  }
+
+  gBS->OpenProtocol (
+    RamfbHandle,
+    &gEfiDevicePathProtocolGuid,
+    &DevicePath,
+    gImageHandle,
+    GopHandle,
+    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
+
+  return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index a2c995b910..7ddda89999 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -745,6 +745,7 @@
   MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
 
   OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
   OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
 
   #
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index b199713925..52b8b1fea1 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -351,6 +351,7 @@ INF  RuleOverride=CSM OvmfPkg/Csm/Csm16/Csm16.inf
 !endif
 
 INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+INF  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
 INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
 INF  OvmfPkg/PlatformDxe/Platform.inf
 INF  OvmfPkg/IoMmuDxe/IoMmuDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index bc7db229d2..3481cdc36b 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -754,6 +754,7 @@
   MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
 
   OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
   OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
 
   #
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index 4ebf64b2b9..70845d6972 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -357,6 +357,7 @@ INF  RuleOverride=CSM OvmfPkg/Csm/Csm16/Csm16.inf
 !endif
 
 INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+INF  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
 INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
 INF  OvmfPkg/PlatformDxe/Platform.inf
 INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 0767b34d18..8b0895b0ff 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -752,6 +752,7 @@
   MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
 
   OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
   OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
 
   #
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 9ca96f9282..1eb46ac9a2 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -357,6 +357,7 @@ INF  RuleOverride=CSM OvmfPkg/Csm/Csm16/Csm16.inf
 !endif
 
 INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+INF  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
 INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
 INF  OvmfPkg/PlatformDxe/Platform.inf
 INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
diff --git a/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf b/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
new file mode 100644
index 0000000000..75a7d86832
--- /dev/null
+++ b/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
@@ -0,0 +1,34 @@
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = QemuRamfbDxe
+  FILE_GUID                      = dce1b094-7dc6-45d0-9fdd-d7fc3cc3e4ef
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = InitializeQemuRamfb
+
+[Sources.common]
+  QemuRamfb.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  DevicePathLib
+  FrameBufferBltLib
+  MemoryAllocationLib
+  UefiBootManagerLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiLib
+  QemuFwCfgLib
+
+[Protocols]
+  gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
+
+[Depex]
+  TRUE
-- 
2.9.3

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH 2/4] OvmfPkg: add QemuRamfbDxe
Posted by Ard Biesheuvel 7 years, 1 month ago
Hello Gerd,

Thanks a lot for contributing this code. I am quite pleased that we
finally have a solution for the EFI frame buffer for ARM systems
running under KVM.

One comment below.

On 8 June 2018 at 13:39, Gerd Hoffmann <kraxel@redhat.com> wrote:
> Add a driver for the qemu ramfb display device.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  OvmfPkg/QemuRamfbDxe/QemuRamfb.c      | 308 ++++++++++++++++++++++++++++++++++
>  OvmfPkg/OvmfPkgIa32.dsc               |   1 +
>  OvmfPkg/OvmfPkgIa32.fdf               |   1 +
>  OvmfPkg/OvmfPkgIa32X64.dsc            |   1 +
>  OvmfPkg/OvmfPkgIa32X64.fdf            |   1 +
>  OvmfPkg/OvmfPkgX64.dsc                |   1 +
>  OvmfPkg/OvmfPkgX64.fdf                |   1 +
>  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf |  34 ++++
>  8 files changed, 348 insertions(+)
>  create mode 100644 OvmfPkg/QemuRamfbDxe/QemuRamfb.c
>  create mode 100644 OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
>
> diff --git a/OvmfPkg/QemuRamfbDxe/QemuRamfb.c b/OvmfPkg/QemuRamfbDxe/QemuRamfb.c
> new file mode 100644
> index 0000000000..f04a314c24
> --- /dev/null
> +++ b/OvmfPkg/QemuRamfbDxe/QemuRamfb.c
> @@ -0,0 +1,308 @@
> +#include <Uefi.h>
> +#include <Protocol/GraphicsOutput.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/FrameBufferBltLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootManagerLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +#include <Library/UefiLib.h>
> +#include <Library/QemuFwCfgLib.h>
> +
> +#include <Guid/QemuRamfb.h>
> +
> +#define RAMFB_FORMAT  0x34325258 /* DRM_FORMAT_XRGB8888 */
> +#define RAMFB_BPP     4
> +
> +EFI_GUID gQemuRamfbGuid = QEMU_RAMFB_GUID;
> +
> +typedef struct RAMFB_CONFIG {
> +  UINT64 Address;
> +  UINT32 FourCC;
> +  UINT32 Flags;
> +  UINT32 Width;
> +  UINT32 Height;
> +  UINT32 Stride;
> +} RAMFB_CONFIG;
> +
> +EFI_HANDLE                    RamfbHandle;
> +EFI_HANDLE                    GopHandle;
> +FRAME_BUFFER_CONFIGURE        *QemuRamfbFrameBufferBltConfigure;
> +UINTN                         QemuRamfbFrameBufferBltConfigureSize;
> +
> +EFI_GRAPHICS_OUTPUT_MODE_INFORMATION QemuRamfbModeInfo[] = {
> +  {
> +    .HorizontalResolution  = 640,
> +    .VerticalResolution    = 480,
> +  },{
> +    .HorizontalResolution  = 800,
> +    .VerticalResolution    = 600,
> +  },{
> +    .HorizontalResolution  = 1024,
> +    .VerticalResolution    = 768,
> +  }
> +};
> +#define QemuRamfbModeCount (sizeof(QemuRamfbModeInfo)/sizeof(QemuRamfbModeInfo[0]))
> +
> +EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE QemuRamfbMode = {
> +  .MaxMode               = QemuRamfbModeCount,
> +  .Mode                  = 0,
> +  .Info                  = QemuRamfbModeInfo,
> +  .SizeOfInfo            = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
> +};
> +
> +EFI_STATUS
> +EFIAPI
> +QemuRamfbGraphicsOutputQueryMode (
> +  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
> +  IN  UINT32                                ModeNumber,
> +  OUT UINTN                                 *SizeOfInfo,
> +  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
> +  )
> +{
> +  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *ModeInfo;
> +
> +  if (Info == NULL || SizeOfInfo == NULL || ModeNumber > QemuRamfbMode.MaxMode) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  ModeInfo = &QemuRamfbModeInfo[ModeNumber];
> +
> +  *Info = AllocateCopyPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
> +                            ModeInfo);
> +  if (*Info == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +QemuRamfbGraphicsOutputSetMode (
> +  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
> +  IN  UINT32                       ModeNumber
> +  )
> +{
> +  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *ModeInfo;
> +  RAMFB_CONFIG                          Config;
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         Black;
> +  RETURN_STATUS                         Ret;
> +  FIRMWARE_CONFIG_ITEM                  Item;
> +  UINTN                                 Size;
> +
> +  if (ModeNumber > QemuRamfbMode.MaxMode) {
> +    return EFI_UNSUPPORTED;
> +  }
> +  ModeInfo = &QemuRamfbModeInfo[ModeNumber];
> +
> +  DEBUG ((EFI_D_INFO, "Ramfb: SetMode %d (%dx%d)\n", ModeNumber,
> +          ModeInfo->HorizontalResolution,
> +          ModeInfo->VerticalResolution));
> +
> +  QemuRamfbMode.Mode = ModeNumber;
> +  QemuRamfbMode.Info = ModeInfo;
> +
> +  Config.Address = SwapBytes64( QemuRamfbMode.FrameBufferBase );
> +  Config.FourCC  = SwapBytes32( RAMFB_FORMAT );
> +  Config.Flags   = SwapBytes32( 0 );
> +  Config.Width   = SwapBytes32( ModeInfo->HorizontalResolution );
> +  Config.Height  = SwapBytes32( ModeInfo->VerticalResolution );
> +  Config.Stride  = SwapBytes32( ModeInfo->HorizontalResolution * RAMFB_BPP );
> +
> +  QemuFwCfgFindFile("etc/ramfb", &Item, &Size);
> +  QemuFwCfgSelectItem(Item);
> +  QemuFwCfgWriteBytes(sizeof(Config), &Config);
> +
> +  Ret = FrameBufferBltConfigure (
> +    (VOID*)(UINTN)QemuRamfbMode.FrameBufferBase,
> +    ModeInfo,
> +    QemuRamfbFrameBufferBltConfigure,
> +    &QemuRamfbFrameBufferBltConfigureSize);
> +
> +  if (Ret == RETURN_BUFFER_TOO_SMALL) {
> +    if (QemuRamfbFrameBufferBltConfigure != NULL) {
> +      FreePool(QemuRamfbFrameBufferBltConfigure);
> +    }
> +    QemuRamfbFrameBufferBltConfigure =
> +      AllocatePool(QemuRamfbFrameBufferBltConfigureSize);
> +
> +    Ret = FrameBufferBltConfigure (
> +      (VOID*)(UINTN)QemuRamfbMode.FrameBufferBase,
> +      ModeInfo,
> +      QemuRamfbFrameBufferBltConfigure,
> +      &QemuRamfbFrameBufferBltConfigureSize);
> +  }
> +
> +  /* clear screen */
> +  ZeroMem (&Black, sizeof (Black));
> +  Ret = FrameBufferBlt (
> +    QemuRamfbFrameBufferBltConfigure,
> +    &Black,
> +    EfiBltVideoFill,
> +    0, 0,
> +    0, 0,
> +    ModeInfo->HorizontalResolution,
> +    ModeInfo->VerticalResolution,
> +    0
> +    );
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +QemuRamfbGraphicsOutputBlt (
> +  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
> +  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer, OPTIONAL
> +  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION     BltOperation,
> +  IN  UINTN                                 SourceX,
> +  IN  UINTN                                 SourceY,
> +  IN  UINTN                                 DestinationX,
> +  IN  UINTN                                 DestinationY,
> +  IN  UINTN                                 Width,
> +  IN  UINTN                                 Height,
> +  IN  UINTN                                 Delta
> +  )
> +{
> +  return FrameBufferBlt (
> +    QemuRamfbFrameBufferBltConfigure,
> +    BltBuffer,
> +    BltOperation,
> +    SourceX,
> +    SourceY,
> +    DestinationX,
> +    DestinationY,
> +    Width,
> +    Height,
> +    Delta);
> +}
> +
> +EFI_GRAPHICS_OUTPUT_PROTOCOL QemuRamfbGraphicsOutput = {
> +  .QueryMode        = QemuRamfbGraphicsOutputQueryMode,
> +  .SetMode          = QemuRamfbGraphicsOutputSetMode,
> +  .Blt              = QemuRamfbGraphicsOutputBlt,
> +  .Mode             = &QemuRamfbMode,
> +};
> +
> +EFI_STATUS
> +EFIAPI
> +InitializeQemuRamfb (
> +  IN EFI_HANDLE           ImageHandle,
> +  IN EFI_SYSTEM_TABLE     *SystemTable
> +  )
> +{
> +  EFI_DEVICE_PATH_PROTOCOL  *RamfbDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
> +  VOID                      *DevicePath;
> +  VENDOR_DEVICE_PATH        VendorDeviceNode;
> +  ACPI_ADR_DEVICE_PATH      AcpiDeviceNode;
> +  EFI_STATUS                Status;
> +  RETURN_STATUS             Ret;
> +  FIRMWARE_CONFIG_ITEM      Item;
> +  EFI_PHYSICAL_ADDRESS      FbBase;
> +  UINTN                     Size, FbSize, MaxFbSize, Pages, Index;
> +
> +  DEBUG ((EFI_D_INFO, "InitializeQemuRamfb\n"));
> +
> +  if (!QemuFwCfgIsAvailable()) {
> +    DEBUG ((EFI_D_INFO, "Ramfb: no FwCfg\n"));
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  Ret = QemuFwCfgFindFile("etc/ramfb", &Item, &Size);
> +  if (Ret != RETURN_SUCCESS) {
> +    DEBUG ((EFI_D_INFO, "Ramfb: no etc/ramfb in FwCfg\n"));
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  MaxFbSize = 0;
> +  for (Index = 0; Index < QemuRamfbModeCount; Index++) {
> +    QemuRamfbModeInfo[Index].PixelsPerScanLine =
> +      QemuRamfbModeInfo[Index].HorizontalResolution;
> +    QemuRamfbModeInfo[Index].PixelFormat =
> +      PixelBlueGreenRedReserved8BitPerColor,
> +    FbSize = RAMFB_BPP *
> +      QemuRamfbModeInfo[Index].HorizontalResolution *
> +      QemuRamfbModeInfo[Index].VerticalResolution;
> +    if (MaxFbSize < FbSize)
> +      MaxFbSize = FbSize;
> +    DEBUG ((EFI_D_INFO, "Ramfb: Mode %d: %dx%d, %d kB\n", Index,
> +            QemuRamfbModeInfo[Index].HorizontalResolution,
> +            QemuRamfbModeInfo[Index].VerticalResolution,
> +            FbSize / 1024));
> +  }
> +
> +  Pages = EFI_SIZE_TO_PAGES(MaxFbSize);
> +  MaxFbSize = EFI_PAGES_TO_SIZE(Pages);
> +  FbBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateRuntimePages(Pages);

EfiRuntimeServicesMemory is special in the sense that it gets added to
the page tables that are installed while UEFI runtime services are
being invoked by the OS. Given that the runtime firmware does not care
about this frame buffer, this is unnecessary, and so I'd rather avoid
it. The proper fix /could/ be to use EfiRuntimeServicesMemory with the
EFI_MEMORY_RUNTIME attribute cleared, but sadly, edk2 does not
implement that at all. So instead, I recommend using
EfiReservedMemoryType here.

(The spec may argue that you should never use it, but it also
recommends that, e.g., SMBIOS tables are put in
EfiRuntimeServicesMemory with the EFI_MEMORY_RUNTIME attribute
cleared, so it is obviously not in sync with reality)

Thanks,
Ard.


> +  if (!FbBase) {
> +    DEBUG ((EFI_D_INFO, "Ramfb: memory allocation failed\n"));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  DEBUG ((EFI_D_INFO, "Ramfb: Framebuffer at 0x%lx, %d kB, %d pages\n",
> +          FbBase, MaxFbSize / 1024, Pages));
> +  QemuRamfbMode.FrameBufferSize = MaxFbSize;
> +  QemuRamfbMode.FrameBufferBase = FbBase;
> +
> +  /* 800 x 600 */
> +  QemuRamfbGraphicsOutputSetMode (&QemuRamfbGraphicsOutput, 1);
> +
> +  /* ramfb vendor devpath */
> +  ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
> +  VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
> +  VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
> +  VendorDeviceNode.Guid = gQemuRamfbGuid;
> +  SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));
> +
> +  RamfbDevicePath = AppendDevicePathNode (
> +    NULL,
> +    (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode);
> +
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +    &RamfbHandle,
> +    &gEfiDevicePathProtocolGuid, RamfbDevicePath,
> +    NULL);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_INFO, "Ramfb: install Ramfb Vendor DevicePath failed\n"));
> +    FreePool((VOID*)(UINTN)QemuRamfbMode.FrameBufferBase);
> +    return Status;
> +  }
> +
> +  /* gop devpath + protocol */
> +  ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
> +  AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
> +  AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
> +  AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0,
> +                                         ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL,
> +                                         0, 0);
> +  SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
> +
> +  GopDevicePath = AppendDevicePathNode (
> +    RamfbDevicePath,
> +    (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode);
> +
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +    &GopHandle,
> +    &gEfiDevicePathProtocolGuid, GopDevicePath,
> +    &gEfiGraphicsOutputProtocolGuid, &QemuRamfbGraphicsOutput,
> +    NULL);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_INFO, "Ramfb: install GOP DevicePath failed\n"));
> +    FreePool((VOID*)(UINTN)QemuRamfbMode.FrameBufferBase);
> +    return Status;
> +  }
> +
> +  gBS->OpenProtocol (
> +    RamfbHandle,
> +    &gEfiDevicePathProtocolGuid,
> +    &DevicePath,
> +    gImageHandle,
> +    GopHandle,
> +    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
> index a2c995b910..7ddda89999 100644
> --- a/OvmfPkg/OvmfPkgIa32.dsc
> +++ b/OvmfPkg/OvmfPkgIa32.dsc
> @@ -745,6 +745,7 @@
>    MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
>
>    OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> +  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
>    OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
>
>    #
> diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
> index b199713925..52b8b1fea1 100644
> --- a/OvmfPkg/OvmfPkgIa32.fdf
> +++ b/OvmfPkg/OvmfPkgIa32.fdf
> @@ -351,6 +351,7 @@ INF  RuleOverride=CSM OvmfPkg/Csm/Csm16/Csm16.inf
>  !endif
>
>  INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> +INF  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
>  INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
>  INF  OvmfPkg/PlatformDxe/Platform.inf
>  INF  OvmfPkg/IoMmuDxe/IoMmuDxe.inf
> diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
> index bc7db229d2..3481cdc36b 100644
> --- a/OvmfPkg/OvmfPkgIa32X64.dsc
> +++ b/OvmfPkg/OvmfPkgIa32X64.dsc
> @@ -754,6 +754,7 @@
>    MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
>
>    OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> +  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
>    OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
>
>    #
> diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
> index 4ebf64b2b9..70845d6972 100644
> --- a/OvmfPkg/OvmfPkgIa32X64.fdf
> +++ b/OvmfPkg/OvmfPkgIa32X64.fdf
> @@ -357,6 +357,7 @@ INF  RuleOverride=CSM OvmfPkg/Csm/Csm16/Csm16.inf
>  !endif
>
>  INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> +INF  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
>  INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
>  INF  OvmfPkg/PlatformDxe/Platform.inf
>  INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
> index 0767b34d18..8b0895b0ff 100644
> --- a/OvmfPkg/OvmfPkgX64.dsc
> +++ b/OvmfPkg/OvmfPkgX64.dsc
> @@ -752,6 +752,7 @@
>    MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
>
>    OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> +  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
>    OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
>
>    #
> diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
> index 9ca96f9282..1eb46ac9a2 100644
> --- a/OvmfPkg/OvmfPkgX64.fdf
> +++ b/OvmfPkg/OvmfPkgX64.fdf
> @@ -357,6 +357,7 @@ INF  RuleOverride=CSM OvmfPkg/Csm/Csm16/Csm16.inf
>  !endif
>
>  INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> +INF  OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
>  INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
>  INF  OvmfPkg/PlatformDxe/Platform.inf
>  INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
> diff --git a/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf b/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
> new file mode 100644
> index 0000000000..75a7d86832
> --- /dev/null
> +++ b/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
> @@ -0,0 +1,34 @@
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = QemuRamfbDxe
> +  FILE_GUID                      = dce1b094-7dc6-45d0-9fdd-d7fc3cc3e4ef
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +
> +  ENTRY_POINT                    = InitializeQemuRamfb
> +
> +[Sources.common]
> +  QemuRamfb.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  OvmfPkg/OvmfPkg.dec
> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  DebugLib
> +  DevicePathLib
> +  FrameBufferBltLib
> +  MemoryAllocationLib
> +  UefiBootManagerLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiLib
> +  QemuFwCfgLib
> +
> +[Protocols]
> +  gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
> +
> +[Depex]
> +  TRUE
> --
> 2.9.3
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH 2/4] OvmfPkg: add QemuRamfbDxe
Posted by Laszlo Ersek 7 years, 1 month ago
On 06/08/18 13:39, Gerd Hoffmann wrote:

> diff --git a/OvmfPkg/QemuRamfbDxe/QemuRamfb.c b/OvmfPkg/QemuRamfbDxe/QemuRamfb.c
> new file mode 100644
> index 0000000000..f04a314c24
> --- /dev/null
> +++ b/OvmfPkg/QemuRamfbDxe/QemuRamfb.c
> @@ -0,0 +1,308 @@
> +#include <Uefi.h>

(1) I think we should be able to drop this. See the leading comment in
"MdePkg/Include/Uefi.h" -- and this is not a UEFI_DRIVER but a platform
DXE_DRIVER module.

> +#include <Protocol/GraphicsOutput.h>
> +
> +#include <Library/BaseMemoryLib.h>

OK, ZeroMem() is from this one.

> +#include <Library/DebugLib.h>

OK, DEBUG() needs this.

> +#include <Library/DevicePathLib.h>

OK, AppendDevicePathNode().

> +#include <Library/FrameBufferBltLib.h>

OK, FrameBufferBltConfigure().

> +#include <Library/MemoryAllocationLib.h>

OK, AllocateCopyPool().

> +#include <Library/UefiBootManagerLib.h>

(2) I think we can drop this. (Please also remove it from the
[LibraryClasses] section in the INF file.)

> +#include <Library/UefiBootServicesTableLib.h>

OK, gBS->InstallMultipleProtocolInterfaces().

> +#include <Library/UefiDriverEntryPoint.h>

(3) Well, strictly speaking, this isn't necessary as an #include -- the
corresponding lib class under [LibraryClasses] *is* necessary though.

I've grepped the tree for this #include directive, and usage is
inconsistent. In new drivers we introduce, I prefer that we not add the
include. Can you please drop it? (Again, do keep it in the INF file.)

> +#include <Library/UefiLib.h>

(4) I tried to see if we use anything from UefiLib.h, and came up empty.
Can you please attempt to drop it both here and from [LibraryClasses] in
the INF file?

> +#include <Library/QemuFwCfgLib.h>

Yup, needed.

> +
> +#include <Guid/QemuRamfb.h>
> +
> +#define RAMFB_FORMAT  0x34325258 /* DRM_FORMAT_XRGB8888 */
> +#define RAMFB_BPP     4
> +
> +EFI_GUID gQemuRamfbGuid = QEMU_RAMFB_GUID;

(5) Please drop this -- we have the declaration of gQemuRamfbGuid from
<Guid/QemuRamfb.h>, and the definition comes from source code
auto-generated by the build tools.

(I'll comment more on the usage below.)

> +
> +typedef struct RAMFB_CONFIG {
> +  UINT64 Address;
> +  UINT32 FourCC;
> +  UINT32 Flags;
> +  UINT32 Width;
> +  UINT32 Height;
> +  UINT32 Stride;
> +} RAMFB_CONFIG;

(6) Please wrap this in:

#pragma pack (1)
...
#pragma pack ()

(7) We could also add this type definition in a new file
"OvmfPkg/Include/IndustryStandard/QemuRamfbConfig.h". However, I do
realize that's somewhat overkill. Up to you; I don't mind if we keep it
here.

> +
> +EFI_HANDLE                    RamfbHandle;
> +EFI_HANDLE                    GopHandle;
> +FRAME_BUFFER_CONFIGURE        *QemuRamfbFrameBufferBltConfigure;
> +UINTN                         QemuRamfbFrameBufferBltConfigureSize;

(8) Please make all these variables STATIC, and also prepend an "m"
prefix to their names (it stands for "module"):

STATIC EFI_HANDLE                    mRamfbHandle;

> +
> +EFI_GRAPHICS_OUTPUT_MODE_INFORMATION QemuRamfbModeInfo[] = {

(9) Same comment as (8).

> +  {
> +    .HorizontalResolution  = 640,
> +    .VerticalResolution    = 480,
> +  },{
> +    .HorizontalResolution  = 800,
> +    .VerticalResolution    = 600,
> +  },{
> +    .HorizontalResolution  = 1024,
> +    .VerticalResolution    = 768,
> +  }
> +};

(10) In edk2 we cannot use designated initializers. I suggest (for
example) assigning these values in the entry point function.

Alternatively, please use the C90-style syntax for aggregate
initialization (i.e. just insert enough zeros):

STATIC EFI_GRAPHICS_OUTPUT_MODE_INFORMATION QemuRamfbModeInfo[] = {
  {
    0,   // Version
    640, // HorizontalResolution
    400, // VerticalResolution
    0,   // PixelFormat -- filled in later
    0,   // PixelInformation -- will be ignored
    0    // PixelsPerScanLine -- filled in later
  },
  ...
};

> +#define QemuRamfbModeCount (sizeof(QemuRamfbModeInfo)/sizeof(QemuRamfbModeInfo[0]))

(11) Please use ARRAY_SIZE() instead, wherever necessary.

> +
> +EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE QemuRamfbMode = {
> +  .MaxMode               = QemuRamfbModeCount,
> +  .Mode                  = 0,
> +  .Info                  = QemuRamfbModeInfo,
> +  .SizeOfInfo            = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
> +};

(12) See (10).

(13) Please insert a space between "sizeof" and "(". In edk2, we put one
space between function identifier / function-like macro name, and the
opening paren, in function calls / macro invocations.

(Obviously, I know that "sizeof" is neither a function nor a macro; it
is an operator. In fact my preferred style is just "sizeof object", no
parens. However, if we use the parens, which is indeed required for
typenames, then we should use one space.)

> +
> +EFI_STATUS
> +EFIAPI
> +QemuRamfbGraphicsOutputQueryMode (

(14) Please also make all functions STATIC, except InitializeQemuRamfb().

> +  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
> +  IN  UINT32                                ModeNumber,
> +  OUT UINTN                                 *SizeOfInfo,
> +  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
> +  )
> +{
> +  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *ModeInfo;
> +
> +  if (Info == NULL || SizeOfInfo == NULL || ModeNumber > QemuRamfbMode.MaxMode) {

(15) I think the ModeNumber comparison is off-by-one; equality should be
rejected too.

> +    return EFI_INVALID_PARAMETER;
> +  }
> +  ModeInfo = &QemuRamfbModeInfo[ModeNumber];
> +
> +  *Info = AllocateCopyPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
> +                            ModeInfo);

(16) The indentation is incorrect; "ModeInfo" should start 2 colums to
the right of the "A" in AllocateCopyPool().

In general, in edk2 there are two accepted indentation styles for
function calls that extend to multiple lines:

variant #1: all arguments (including the first one) on separate lines,
with the closing paren also on a separate line:

  Status = StructPointer->Function (
                            Arg1,
                            Arg2,
                            Arg3
                            );

variant #2: filling horizontal space with arguments up to column 80; and
whenever a line break is needed, stick with the same indentation as seen
in variant #1. The closing paren is not broken to a separate line.

  Status = StructPointer->Function (LongArgumentOne, LongArgumentTwo,
                            LongArgumentThree, LongArgumentFour);

For both styles, if StructPointer doesn't exist, then the indentation
remains the same, relatively speaking, anchored to "Function".

> +  if (*Info == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +QemuRamfbGraphicsOutputSetMode (
> +  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
> +  IN  UINT32                       ModeNumber
> +  )
> +{
> +  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *ModeInfo;
> +  RAMFB_CONFIG                          Config;
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         Black;
> +  RETURN_STATUS                         Ret;

(17) We generally call such variables "Status".

> +  FIRMWARE_CONFIG_ITEM                  Item;
> +  UINTN                                 Size;
> +
> +  if (ModeNumber > QemuRamfbMode.MaxMode) {
> +    return EFI_UNSUPPORTED;
> +  }

(18) See (15).

> +  ModeInfo = &QemuRamfbModeInfo[ModeNumber];
> +
> +  DEBUG ((EFI_D_INFO, "Ramfb: SetMode %d (%dx%d)\n", ModeNumber,

(19) We've stopped adding EFI_D_* macros; instead we use DEBUG_* macros
in new code.

(20) Please print UINT32 values with "%u" rather than "%d".

> +          ModeInfo->HorizontalResolution,
> +          ModeInfo->VerticalResolution));

(21) Please see (16).

> +
> +  QemuRamfbMode.Mode = ModeNumber;
> +  QemuRamfbMode.Info = ModeInfo;
> +
> +  Config.Address = SwapBytes64( QemuRamfbMode.FrameBufferBase );

(22) Please #include <BaseLib.h> for SwapBytes*(); also please add it to
[LibraryClasses] in the INF file.

(23) The space characters near the parens are not idiomatic; we'd use

  Config.Address = SwapBytes64 (QemuRamfbMode.FrameBufferBase);

> +  Config.FourCC  = SwapBytes32( RAMFB_FORMAT );
> +  Config.Flags   = SwapBytes32( 0 );
> +  Config.Width   = SwapBytes32( ModeInfo->HorizontalResolution );
> +  Config.Height  = SwapBytes32( ModeInfo->VerticalResolution );
> +  Config.Stride  = SwapBytes32( ModeInfo->HorizontalResolution * RAMFB_BPP );
> +
> +  QemuFwCfgFindFile("etc/ramfb", &Item, &Size);

(24) You perform the same lookup in the entry point function; can you
please cache the selector value ("Item") in a new

  STATIC FIRMWARE_CONFIG_ITEM mRamFbFwCfgItem;

global variable? And then use that here.

Furthermore, instead of Size, you can use "sizeof Config".

> +  QemuFwCfgSelectItem(Item);
> +  QemuFwCfgWriteBytes(sizeof(Config), &Config);

(25) (several counts:) please see (13).

> +
> +  Ret = FrameBufferBltConfigure (
> +    (VOID*)(UINTN)QemuRamfbMode.FrameBufferBase,
> +    ModeInfo,
> +    QemuRamfbFrameBufferBltConfigure,
> +    &QemuRamfbFrameBufferBltConfigureSize);

(26) Please see (16).

> +
> +  if (Ret == RETURN_BUFFER_TOO_SMALL) {
> +    if (QemuRamfbFrameBufferBltConfigure != NULL) {
> +      FreePool(QemuRamfbFrameBufferBltConfigure);

(27) Please see (13).

> +    }
> +    QemuRamfbFrameBufferBltConfigure =
> +      AllocatePool(QemuRamfbFrameBufferBltConfigureSize);

(28) Please see (13).

(29) Please reorganize the function as follows: this AllocatePool() call
should be moved near the top, so that, if it fails, we can return
EFI_OUT_OF_RESOURCES without actually changing fw_cfg or any of the
GOP-related data structures. Then, please check the return value for NULL.

My understanding is that QemuRamfbMode.FrameBufferBase is invariant (=
independent of the mode requested), after the initial setup, so this
should be possible.

> +
> +    Ret = FrameBufferBltConfigure (
> +      (VOID*)(UINTN)QemuRamfbMode.FrameBufferBase,
> +      ModeInfo,
> +      QemuRamfbFrameBufferBltConfigure,
> +      &QemuRamfbFrameBufferBltConfigureSize);
> +  }

(30) Please see (16).

(31) At this point, "Ret" (well, "Status") must either be RETURN_SUCCESS
or RETURN_UNSUPPORTED. Please add:

  if (RETURN_ERROR (Status)) {
    ASSERT (Status == RETURN_UNSUPPORTED);
    return Status;
  }

> +
> +  /* clear screen */

(32) The edk2 style for such comments is:

  //
  // clear screen
  //

> +  ZeroMem (&Black, sizeof (Black));
> +  Ret = FrameBufferBlt (
> +    QemuRamfbFrameBufferBltConfigure,
> +    &Black,
> +    EfiBltVideoFill,
> +    0, 0,
> +    0, 0,
> +    ModeInfo->HorizontalResolution,
> +    ModeInfo->VerticalResolution,
> +    0
> +    );

(33) We've got a load of arguments here, can we please do:

  Status = FrameBufferBlt (
             QemuRamfbFrameBufferBltConfigure,
             &Black,
             EfiBltVideoFill,
             0,                                // SourceX -- ignored
             0,                                // SourceY -- ignored
             0,                                // DestinationX
             0,                                // DestinationY
             ModeInfo->HorizontalResolution,   // Width
             ModeInfo->VerticalResolution,     // Height
             0                                 // Delta -- ignored
             );

(34) I agree that this call should never fail, and even if it does, we
should still return EFI_SUCCESS about the mode change. But, it might be
nice to log a debug message on failure, such as:

  DEBUG ((DEBUG_WARN, "%a: clearing the screen failed: %r\n",
    __FUNCTION__, Status));

> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +QemuRamfbGraphicsOutputBlt (
> +  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
> +  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer, OPTIONAL
> +  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION     BltOperation,
> +  IN  UINTN                                 SourceX,
> +  IN  UINTN                                 SourceY,
> +  IN  UINTN                                 DestinationX,
> +  IN  UINTN                                 DestinationY,
> +  IN  UINTN                                 Width,
> +  IN  UINTN                                 Height,
> +  IN  UINTN                                 Delta
> +  )
> +{
> +  return FrameBufferBlt (
> +    QemuRamfbFrameBufferBltConfigure,
> +    BltBuffer,
> +    BltOperation,
> +    SourceX,
> +    SourceY,
> +    DestinationX,
> +    DestinationY,
> +    Width,
> +    Height,
> +    Delta);
> +}

(35) Please see (16).

> +
> +EFI_GRAPHICS_OUTPUT_PROTOCOL QemuRamfbGraphicsOutput = {
> +  .QueryMode        = QemuRamfbGraphicsOutputQueryMode,
> +  .SetMode          = QemuRamfbGraphicsOutputSetMode,
> +  .Blt              = QemuRamfbGraphicsOutputBlt,
> +  .Mode             = &QemuRamfbMode,
> +};

(36) Please see (10).

> +
> +EFI_STATUS
> +EFIAPI
> +InitializeQemuRamfb (
> +  IN EFI_HANDLE           ImageHandle,
> +  IN EFI_SYSTEM_TABLE     *SystemTable
> +  )
> +{
> +  EFI_DEVICE_PATH_PROTOCOL  *RamfbDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
> +  VOID                      *DevicePath;
> +  VENDOR_DEVICE_PATH        VendorDeviceNode;
> +  ACPI_ADR_DEVICE_PATH      AcpiDeviceNode;
> +  EFI_STATUS                Status;
> +  RETURN_STATUS             Ret;

Another background story... EFI_STATUS is for (a) anything defined in
the Platform Init and UEFI specifications, (b) library classes that are
meant to be used *solely* in modules defined by those specifications.

RETURN_STATUS is for libraries that are lower-level than those, at least
conceptually; in other words, if they provide functionality that is
independent of client module type ("BASE" libraries). In theory such
libraries are OK to use in SEC modules even.

Technically, there isn't any difference between these types and their
values, however. Thus, if you have a function in which you already have
an EFI_STATUS local variable (for storing EFI_STATUS values), you can
freely store RETURN_STATUS retvals to it as well. If you only assign
RETURN_STATUS values, then it's more idiomatic to use RETURN_STATUS.
(Which is what you do in QemuRamfbGraphicsOutputSetMode(), correctly.)

For RETURN_STATUS variables, we have macros such as:
- RETURN_ERROR (Status)
- ASSERT_RETURN_ERROR (Status)

For EFI_STATUS variables, we have the same, just replace RETURN with EFI.

(37) So, I suggest dropping "Ret", and just using Status.

> +  FIRMWARE_CONFIG_ITEM      Item;

(38) See (24).

> +  EFI_PHYSICAL_ADDRESS      FbBase;
> +  UINTN                     Size, FbSize, MaxFbSize, Pages, Index;

(39) I know it's annoying, but please break at least *some* of those to
separate declarations. I guess keeping "FbSize" and "MaxFbSize" on the
same line makes sense.

Furthermore, "Size" should be called "FwCfgSize" (for clarity).

> +
> +  DEBUG ((EFI_D_INFO, "InitializeQemuRamfb\n"));

(40) Please see (19). (There are some more occurrences below.)

(41) Also, I suggest using "%a" with __FUNCTION__.

> +
> +  if (!QemuFwCfgIsAvailable()) {
> +    DEBUG ((EFI_D_INFO, "Ramfb: no FwCfg\n"));
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  Ret = QemuFwCfgFindFile("etc/ramfb", &Item, &Size);
> +  if (Ret != RETURN_SUCCESS) {
> +    DEBUG ((EFI_D_INFO, "Ramfb: no etc/ramfb in FwCfg\n"));
> +    return EFI_NOT_FOUND;
> +  }

(42) For whatever reason, the idiomatic spelling for the comparison is

  if (EFI_ERROR (Status)) {
    ...
  }

(43) You might want to drop the debug message for this case, as in most
setups, I expect ramfb will not be present; plus, if the driver exits
with an error code, the DXE core will log that anyway. If you'd really
like to keep the message, I suggest DEBUG_VERBOSE.

(44) If the lookup succeeds, please compare "FwCfgSize" against sizeof
(RAMFB_CONFIG). In case of mismatch, log an error (DEBUG_ERROR) and exit.

> +
> +  MaxFbSize = 0;
> +  for (Index = 0; Index < QemuRamfbModeCount; Index++) {
> +    QemuRamfbModeInfo[Index].PixelsPerScanLine =
> +      QemuRamfbModeInfo[Index].HorizontalResolution;
> +    QemuRamfbModeInfo[Index].PixelFormat =
> +      PixelBlueGreenRedReserved8BitPerColor,

(45) Nice use of the comma operator :) but I think it may not be
intended. Please let's stick with the semicolon.

> +    FbSize = RAMFB_BPP *
> +      QemuRamfbModeInfo[Index].HorizontalResolution *
> +      QemuRamfbModeInfo[Index].VerticalResolution;
> +    if (MaxFbSize < FbSize)
> +      MaxFbSize = FbSize;

(46) The edk2 coding style requires braces.

> +    DEBUG ((EFI_D_INFO, "Ramfb: Mode %d: %dx%d, %d kB\n", Index,
> +            QemuRamfbModeInfo[Index].HorizontalResolution,
> +            QemuRamfbModeInfo[Index].VerticalResolution,
> +            FbSize / 1024));
> +  }

(47) indentation, please see (16).

(48) For printing UINTN values portably across 32-bit and 64-bit builds,
the safest way is to cast the variable to UINT64, and then print it with
"%Lu" (or, if you like hex, "%Lx").

This refers to both "Index" and "FbSize".

(Also, feel free to use lower-case "l" in place of my suggested
upper-case "L"; in edk2 they are interchangeable for printing integers.
I just dislike lower-case "l" because in ISO C, it stands for "long",
whereas "L" is not defined in ISO C for integers. I think that makes "L"
a better fit for a non-standard purpose such as "print UINT64". And, no,
edk2 does not have PRIx64.)

(49) EFI_D_*, please see (19)

(50) Please see (20) as well, for printing the resolutions.

> +
> +  Pages = EFI_SIZE_TO_PAGES(MaxFbSize);
> +  MaxFbSize = EFI_PAGES_TO_SIZE(Pages);
> +  FbBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateRuntimePages(Pages);

(51) Multiple instances of (13).

(52) What Ard said about runtime allocations.

Please call AllocateReservedPages() instead.

> +  if (!FbBase) {

(53) In edk2, we only use the logical negation operator (!) for
BOOLEANs. Please compare FbBase against 0 explicitly.

> +    DEBUG ((EFI_D_INFO, "Ramfb: memory allocation failed\n"));
> +    return EFI_OUT_OF_RESOURCES;
> +  }

(54) please see (19).

> +  DEBUG ((EFI_D_INFO, "Ramfb: Framebuffer at 0x%lx, %d kB, %d pages\n",
> +          FbBase, MaxFbSize / 1024, Pages));

(55) Please see (48) for "MaxFbSize / 1024" and "Pages".

> +  QemuRamfbMode.FrameBufferSize = MaxFbSize;
> +  QemuRamfbMode.FrameBufferBase = FbBase;
> +
> +  /* 800 x 600 */
> +  QemuRamfbGraphicsOutputSetMode (&QemuRamfbGraphicsOutput, 1);
> +
> +  /* ramfb vendor devpath */

(56) Please refer to (32); two instances above.

> +  ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
> +  VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
> +  VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
> +  VendorDeviceNode.Guid = gQemuRamfbGuid;

(57) Unfortunately, structure assignment is forbidden in edk2; please
use the CopyGuid() function from BaseMemoryLib. See more below.

> +  SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));

(58) This line seems overlong (82 characters); please stick with 80 chars.

(59) I think you've filled in all members of VendorDeviceNode; can you
drop the ZeroMem()?

> +
> +  RamfbDevicePath = AppendDevicePathNode (
> +    NULL,
> +    (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode);
> +

(60) Please see (16).

(61) Please check the return value. AppendDevicePathNode() allocates
memory dynamically. If it fails, we should roll back earlier operations
(if any) and exit with EFI_OUT_OF_RESOURCES.

> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +    &RamfbHandle,
> +    &gEfiDevicePathProtocolGuid, RamfbDevicePath,
> +    NULL);

(62) Please see (16).

> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_INFO, "Ramfb: install Ramfb Vendor DevicePath failed\n"));

(63) We should use DEBUG_ERROR here.

(64) In such cases it is helpful to print Status too; please use the
"%r" format specifier for that.

> +    FreePool((VOID*)(UINTN)QemuRamfbMode.FrameBufferBase);

(65) Please see (13).

> +    return Status;

(65) This leaks two objects:

- the RamfbHandle handle created with
gBS->InstallMultipleProtocolInterfaces(),

- the RamfbDevicePath devpath created with AppendDevicePathNode().

In edk2 we like the "cascading error path", with several labels and goto
statements; I suggest we put it to use as well. On the error path, we
should tear down resources in reverse order of construction, as usual:

- in UEFI, a handle is created when the first protocol interface is
installed on an initially NULL handle; and a handle destroyed when the
last protocol interface is uninstalled from it.

Common pitfall: InstallMultipleProtocolInterfaces() takes a *pointer to*
a handle (because if the handle is NULL on input, the function wants to
store the new handle on output); however,
UninstallMultipleProtocolInterfaces() takes the handle itself! Be
careful with the address-of ("&") operator.

- "RamfbDevicePath" should be freed with FreePool().

> +  }
> +
> +  /* gop devpath + protocol */

(66) please see (32).

> +  ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));

(67) Does (59) apply here?

> +  AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
> +  AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
> +  AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0,
> +                                         ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL,
> +                                         0, 0);

(68) Please add comments to the individual arguments. Example:
"OvmfPkg/VirtioGpuDxe/DriverBinding.c", the initializer of "mAcpiAdr".

> +  SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
> +
> +  GopDevicePath = AppendDevicePathNode (
> +    RamfbDevicePath,
> +    (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode);
> +
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +    &GopHandle,
> +    &gEfiDevicePathProtocolGuid, GopDevicePath,
> +    &gEfiGraphicsOutputProtocolGuid, &QemuRamfbGraphicsOutput,
> +    NULL);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_INFO, "Ramfb: install GOP DevicePath failed\n"));
> +    FreePool((VOID*)(UINTN)QemuRamfbMode.FrameBufferBase);
> +    return Status;
> +  }

(69) Same comments as (60) through (65).

> +
> +  gBS->OpenProtocol (
> +    RamfbHandle,
> +    &gEfiDevicePathProtocolGuid,
> +    &DevicePath,
> +    gImageHandle,
> +    GopHandle,
> +    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);

(70) Please see (16).

(71) Please check the return status. If the call fails, please roll back
the earlier actions and propagate the error out of the entry point function.

> +
> +  return EFI_SUCCESS;
> +}

> diff --git a/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf b/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
> new file mode 100644
> index 0000000000..75a7d86832
> --- /dev/null
> +++ b/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
> @@ -0,0 +1,34 @@

(72) Here's a shared request for both new files ("QemuRamfb.c" and
"QemuRamfbDxe.inf"): please refer to the standard .c and .inf file
"banners" for example under OvmfPkg/VirtioGpuDxe. Files should start with:
- a @file comment that briefly states what the file is good for,
- a list of copyright notices,
- the copyright license / reference (2-clause BSDL usually).

> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = QemuRamfbDxe
> +  FILE_GUID                      = dce1b094-7dc6-45d0-9fdd-d7fc3cc3e4ef
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +
> +  ENTRY_POINT                    = InitializeQemuRamfb
> +
> +[Sources.common]
> +  QemuRamfb.c

(73) We can simply say [Sources] here.

> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  OvmfPkg/OvmfPkg.dec
> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  DebugLib
> +  DevicePathLib
> +  FrameBufferBltLib
> +  MemoryAllocationLib
> +  UefiBootManagerLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiLib
> +  QemuFwCfgLib
> +
> +[Protocols]
> +  gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START

(74) The "BY_START" protocol usage comment is incorrect here, because
we're not producing instances of the protocol in a DriverBindingStart()
function. (In other words, the driver is not a UEFI_DRIVER that conforms
to the UEFI driver model, instead it's a platform DXE driver.) Please
use the comment "## PRODUCES" (you can also drop "PROTOCOL").

(75) In turn, is where I refer back to (5) and (57). Please add a
section like this:

[Guids]
  gQemuRamfbGuid

This will ensure that the build utilities generate a "gQemuRamfbGuid"
*definition* (not just a declaration) for you.

> +
> +[Depex]
> +  TRUE
> 

I realize this review ended up quite long and tedious. I think (hope!)
that you're going to contribute to edk2 in the longer term, thus I
intended to use this opportunity to spell out idioms and such that might
apply to your future patches too.

Thank you!
Laszlo
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH 2/4] OvmfPkg: add QemuRamfbDxe
Posted by Gerd Hoffmann 7 years ago
  Hi,

> > +  {
> > +    .HorizontalResolution  = 640,
> > +    .VerticalResolution    = 480,
> > +  },{
> > +    .HorizontalResolution  = 800,
> > +    .VerticalResolution    = 600,
> > +  },{
> > +    .HorizontalResolution  = 1024,
> > +    .VerticalResolution    = 768,
> > +  }
> > +};
> 
> (10) In edk2 we cannot use designated initializers. I suggest (for
> example) assigning these values in the entry point function.

Really?  C99 is almost 20 years old now ...
Are there compilers left without C99 support which edk2 still supports?

> In general, in edk2 there are two accepted indentation styles for
> function calls that extend to multiple lines:
> 
> variant #1: all arguments (including the first one) on separate lines,
> with the closing paren also on a separate line:
> 
>   Status = StructPointer->Function (
>                             Arg1,
>                             Arg2,
>                             Arg3
>                             );

Hmm, pretty unusual, which is bad for editor auto-indent support.
Anyone knows tricks to teack emacs that style?

cheers,
  Gerd

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH 2/4] OvmfPkg: add QemuRamfbDxe
Posted by Laszlo Ersek 7 years ago
On 06/12/18 11:15, Gerd Hoffmann wrote:
>   Hi,
> 
>>> +  {
>>> +    .HorizontalResolution  = 640,
>>> +    .VerticalResolution    = 480,
>>> +  },{
>>> +    .HorizontalResolution  = 800,
>>> +    .VerticalResolution    = 600,
>>> +  },{
>>> +    .HorizontalResolution  = 1024,
>>> +    .VerticalResolution    = 768,
>>> +  }
>>> +};
>>
>> (10) In edk2 we cannot use designated initializers. I suggest (for
>> example) assigning these values in the entry point function.
> 
> Really?  C99 is almost 20 years old now ...
> Are there compilers left without C99 support which edk2 still supports?

Visual Studio has never committed to *full* C99 support, to my
knowledge. I don't know whether VS happens to support designated
initializers specifically; either way, we can't use them in edk2.

... After some googling, I see "signs" that VS >=2013 supports
designated initializers.

However, edk2 targets VS 2003, 2005, 2008, 2010, and 2012 too, before
2013. Refer to "Supported Tool Chains" in
"BaseTools/Conf/tools_def.template".

> 
>> In general, in edk2 there are two accepted indentation styles for
>> function calls that extend to multiple lines:
>>
>> variant #1: all arguments (including the first one) on separate lines,
>> with the closing paren also on a separate line:
>>
>>   Status = StructPointer->Function (
>>                             Arg1,
>>                             Arg2,
>>                             Arg3
>>                             );
> 
> Hmm, pretty unusual,

Yes, very much. I believe this indentation style might originate from
Windows, but I'm not sure.

> which is bad for editor auto-indent support.
> Anyone knows tricks to teack emacs that style?

I don't use emacs, apologies!
Laszlo
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel