The GraphicsConsoleDxe driver (in MdeModulePkg/Universal/Console)
determines the preferred video resolution from the dynamic PCDs
- gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution
- gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution

Before BDS connects the console(s), let's look up a UEFI variable called
"PreferredResolution" (belonging to gOvmfSystemConfigGuid), parse its
contents (eg. "1024x768"), and set the above PCDs accordingly.

This enables guests to set/query their preferred GOP resolutions
persistently (effective from next boot), using either the UEFI shell's
"setvar" and "dmpstore" commands:

  setvar PreferredResolution -guid 7235C51C-0C80-4CAB-87AC-3B084A6304B1 \
      -bs -rt -nv ="1024x768"

  dmpstore PreferredResolution -guid 7235C51C-0C80-4CAB-87AC-3B084A6304B1

or the guest OS's own utilities that wrap gRT->SetVariable() /
gRT->GetVariable().

Setting the GOP resolution during boot is useful when the guest OS (for
lack of a dedicated display driver) continues to work with the original
GOP resolution and framebuffer.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <[email protected]>
---
 OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf |  5 ++
 OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c      | 60 +++++++++++++++++++++++
 2 files changed, 65 insertions(+)

diff --git a/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf 
b/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf
index a2b72ba..31ab235 100644
--- a/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf
+++ b/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf
@@ -53,11 +53,16 @@
   QemuFwCfgLib
   LoadLinuxLib
 
+[Guids]
+  gOvmfSystemConfigGuid # ALWAYS_CONSUMED
+
 [Pcd]
   gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformBootTimeOut
   gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile
   gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution
 
 [Pcd.IA32, Pcd.X64]
   gEfiMdePkgTokenSpaceGuid.PcdFSBClock
diff --git a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c 
b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
index ab9c93e..2d20739 100644
--- a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
+++ b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
@@ -14,6 +14,7 @@
 
 #include "BdsPlatform.h"
 #include "QemuBootOrder.h"
+#include <Guid/OvmfSystemConfig.h>
 
 
 //
@@ -1027,6 +1028,64 @@ Returns:
 }
 
 
+/**
+  Read a resolution string with format "1024x768" from the PreferredResolution
+  variable under gOvmfSystemConfigGuid, and pass it to GraphicsConsoleDxe via
+  dynamic PCDs.
+
+  We don't try to enforce the format, we just recognize sensible resolutions
+  given in the correct format, and avoid undefined behavior.
+
+  @retval EFI_SUCCESS            PCDs have been set.
+  @retval EFI_INVALID_PARAMETER  Invalid format detected in variable contents.
+  @return                        Status codes from gRT->GetVariable().
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SetPreferredResolution (
+  VOID
+  )
+{
+  UINTN         DataSize;
+  UINT8         Data[16];
+  EFI_STATUS    Status;
+  STATIC CHAR16 Variable[] = L"PreferredResolution";
+  UINT32        Dimensions[2];
+  UINTN         DimIdx;
+  UINTN         Idx;
+
+  DataSize = sizeof Data;
+  Status = gRT->GetVariable (Variable, &gOvmfSystemConfigGuid, NULL, &DataSize,
+                  Data);
+  if (EFI_ERROR (Status)) {
+    DEBUG (((Status == EFI_NOT_FOUND) ? EFI_D_VERBOSE : EFI_D_ERROR,
+      "%a: failed to get %s: %r\n", __FUNCTION__, Variable, Status));
+    return Status;
+  }
+
+  ZeroMem (Dimensions, sizeof Dimensions);
+  DimIdx = 0;
+  for (Idx = 0; Idx < DataSize; ++Idx) {
+    if (Data[Idx] >= '0' && Data[Idx] <= '9' && DimIdx < 2) {
+      Dimensions[DimIdx] = Dimensions[DimIdx] * 10 + (Data[Idx] - '0');
+    } else if (Data[Idx] == 'x') {
+      ++DimIdx;
+    } else {
+      DEBUG ((EFI_D_ERROR, "%a: invalid format at position %d\n", __FUNCTION__,
+        (INT32) Idx));
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  DEBUG ((EFI_D_INFO, "%a: setting %Ldx%Ld\n", __FUNCTION__,
+    (INT64) Dimensions[0], (INT64) Dimensions[1]));
+  PcdSet32 (PcdVideoHorizontalResolution, Dimensions[0]);
+  PcdSet32 (PcdVideoVerticalResolution, Dimensions[1]);
+  return EFI_SUCCESS;
+}
+
+
 VOID
 EFIAPI
 PlatformBdsPolicyBehavior (
@@ -1108,6 +1167,7 @@ Returns:
   //
   // Connect platform console
   //
+  SetPreferredResolution ();
   Status = PlatformBdsConnectConsole (gPlatformConsole);
   if (EFI_ERROR (Status)) {
     //
-- 
1.8.3.1



------------------------------------------------------------------------------
WatchGuard Dimension instantly turns raw network data into actionable 
security intelligence. It gives you real-time visual feedback on key
security issues and trends.  Skip the complicated setup - simply import
a virtual appliance and go from zero to informed in seconds.
http://pubads.g.doubleclick.net/gampad/clk?id=123612991&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to