Revision: 15372
          http://sourceforge.net/p/edk2/code/15372
Author:   jljusten
Date:     2014-03-22 07:13:50 +0000 (Sat, 22 Mar 2014)
Log Message:
-----------
OvmfPkg: PlatformDxe: get available resolutions from GOP

Generate the options for the drop-down list from the GOP resolutions.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <[email protected]>
Reviewed-by: Jordan Justen <[email protected]>

Modified Paths:
--------------
    trunk/edk2/OvmfPkg/PlatformDxe/Platform.c
    trunk/edk2/OvmfPkg/PlatformDxe/Platform.inf

Modified: trunk/edk2/OvmfPkg/PlatformDxe/Platform.c
===================================================================
--- trunk/edk2/OvmfPkg/PlatformDxe/Platform.c   2014-03-22 07:13:44 UTC (rev 
15371)
+++ trunk/edk2/OvmfPkg/PlatformDxe/Platform.c   2014-03-22 07:13:50 UTC (rev 
15372)
@@ -18,9 +18,12 @@
 #include <Library/DebugLib.h>
 #include <Library/DevicePathLib.h>
 #include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiHiiServicesLib.h>
 #include <Protocol/DevicePath.h>
+#include <Protocol/GraphicsOutput.h>
 #include <Protocol/HiiConfigAccess.h>
 #include <Guid/MdeModuleHii.h>
 #include <Guid/OvmfPlatformConfig.h>
@@ -98,7 +101,30 @@
 extern UINT8 PlatformDxeStrings[];
 extern UINT8 PlatformFormsBin[];
 
+//
+// We want to be notified about GOP installations until we find one GOP
+// interface that lets us populate the form.
+//
+STATIC EFI_EVENT mGopEvent;
 
+//
+// The registration record underneath this pointer allows us to iterate through
+// the GOP instances one by one.
+//
+STATIC VOID *mGopTracker;
+
+//
+// Cache the resolutions we get from the GOP.
+//
+typedef struct {
+  UINT32 X;
+  UINT32 Y;
+} GOP_MODE;
+
+STATIC UINTN    mNumGopModes;
+STATIC GOP_MODE *mGopModes;
+
+
 /**
   This function is called by the HII machinery when it fetches the form state.
 
@@ -180,6 +206,68 @@
 
 
 /**
+  Query and save all resolutions supported by the GOP.
+
+  @param[in]  Gop          The Graphics Output Protocol instance to query.
+
+  @param[out] NumGopModes  The number of modes supported by the GOP. On output,
+                           this parameter will be positive.
+
+  @param[out] GopModes     On output, a dynamically allocated array containing
+                           the resolutions returned by the GOP. The caller is
+                           responsible for freeing the array after use.
+
+  @retval EFI_UNSUPPORTED       No modes found.
+  @retval EFI_OUT_OF_RESOURCES  Failed to allocate GopModes.
+  @return                       Error codes from Gop->QueryMode().
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+QueryGopModes (
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop,
+  OUT UINTN                        *NumGopModes,
+  OUT GOP_MODE                     **GopModes
+  )
+{
+  EFI_STATUS Status;
+  UINT32     ModeNumber;
+
+  if (Gop->Mode->MaxMode == 0) {
+    return EFI_UNSUPPORTED;
+  }
+  *NumGopModes = Gop->Mode->MaxMode;
+
+  *GopModes = AllocatePool (Gop->Mode->MaxMode * sizeof **GopModes);
+  if (*GopModes == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  for (ModeNumber = 0; ModeNumber < Gop->Mode->MaxMode; ++ModeNumber) {
+    EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+    UINTN                                SizeOfInfo;
+
+    Status = Gop->QueryMode (Gop, ModeNumber, &SizeOfInfo, &Info);
+    if (EFI_ERROR (Status)) {
+      goto FreeGopModes;
+    }
+
+    (*GopModes)[ModeNumber].X = Info->HorizontalResolution;
+    (*GopModes)[ModeNumber].Y = Info->VerticalResolution;
+    FreePool (Info);
+  }
+
+  return EFI_SUCCESS;
+
+FreeGopModes:
+  FreePool (*GopModes);
+
+  return Status;
+}
+
+
+/**
   Create a set of "one-of-many" (ie. "drop down list") option IFR opcodes,
   based on available GOP resolutions, to be placed under a "one-of-many" (ie.
   "drop down list") opcode.
@@ -193,6 +281,10 @@
                             resolutions. The caller is responsible for freeing
                             OpCodeBuffer with HiiFreeOpCodeHandle() after use.
 
+  @param[in]  NumGopModes   Number of entries in GopModes.
+
+  @param[in]  GopModes      Array of resolutions retrieved from the GOP.
+
   @retval EFI_SUCESS  Opcodes have been successfully produced.
 
   @return             Status codes from underlying functions. PackageList may
@@ -204,31 +296,40 @@
 EFIAPI
 CreateResolutionOptions (
   IN  EFI_HII_HANDLE  *PackageList,
-  OUT VOID            **OpCodeBuffer
+  OUT VOID            **OpCodeBuffer,
+  IN  UINTN           NumGopModes,
+  IN  GOP_MODE        *GopModes
   )
 {
-  EFI_STATUS                   Status;
-  VOID                         *OutputBuffer;
-  EFI_STRING_ID                NewString;
-  VOID                         *OpCode;
+  EFI_STATUS Status;
+  VOID       *OutputBuffer;
+  UINTN      ModeNumber;
 
   OutputBuffer = HiiAllocateOpCodeHandle ();
   if (OutputBuffer == NULL) {
     return EFI_OUT_OF_RESOURCES;
   }
 
-  NewString = HiiSetString (PackageList, 0 /* new string */, L"800x600",
-                NULL /* for all languages */);
-  if (NewString == 0) {
-    Status = EFI_OUT_OF_RESOURCES;
-    goto FreeOutputBuffer;
+  for (ModeNumber = 0; ModeNumber < NumGopModes; ++ModeNumber) {
+    CHAR16        Desc[MAXSIZE_RES_CUR];
+    EFI_STRING_ID NewString;
+    VOID          *OpCode;
+
+    UnicodeSPrintAsciiFormat (Desc, sizeof Desc, "%Ldx%Ld",
+      (INT64) GopModes[ModeNumber].X, (INT64) GopModes[ModeNumber].Y);
+    NewString = HiiSetString (PackageList, 0 /* new string */, Desc,
+                  NULL /* for all languages */);
+    if (NewString == 0) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto FreeOutputBuffer;
+    }
+    OpCode = HiiCreateOneOfOptionOpCode (OutputBuffer, NewString,
+               0 /* Flags */, EFI_IFR_NUMERIC_SIZE_4, ModeNumber);
+    if (OpCode == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto FreeOutputBuffer;
+    }
   }
-  OpCode = HiiCreateOneOfOptionOpCode (OutputBuffer, NewString,
-             0 /* Flags */, EFI_IFR_NUMERIC_SIZE_4, 0 /* Value */);
-  if (OpCode == NULL) {
-    Status = EFI_OUT_OF_RESOURCES;
-    goto FreeOutputBuffer;
-  }
 
   *OpCodeBuffer = OutputBuffer;
   return EFI_SUCCESS;
@@ -244,6 +345,9 @@
   Populate the form identified by the (PackageList, FormSetGuid, FormId)
   triplet.
 
+  The drop down list of video resolutions is generated from (NumGopModes,
+  GopModes).
+
   @retval EFI_SUCESS  Form successfully updated.
   @return             Status codes from underlying functions.
 
@@ -254,7 +358,9 @@
 PopulateForm (
   IN  EFI_HII_HANDLE  *PackageList,
   IN  EFI_GUID        *FormSetGuid,
-  IN  EFI_FORM_ID     FormId
+  IN  EFI_FORM_ID     FormId,
+  IN  UINTN           NumGopModes,
+  IN  GOP_MODE        *GopModes
   )
 {
   EFI_STATUS         Status;
@@ -293,7 +399,8 @@
   //
   // 3.1. Get a list of resolutions.
   //
-  Status = CreateResolutionOptions (PackageList, &OpCodeBuffer2);
+  Status = CreateResolutionOptions (PackageList, &OpCodeBuffer2,
+             NumGopModes, GopModes);
   if (EFI_ERROR (Status)) {
     goto FreeOpCodeBuffer;
   }
@@ -382,6 +489,66 @@
 
 
 /**
+  Notification callback for GOP interface installation.
+
+  @param[in] Event    Event whose notification function is being invoked.
+
+  @param[in] Context  The pointer to the notification function's context, which
+                      is implementation-dependent.
+**/
+STATIC
+VOID
+EFIAPI
+GopInstalled (
+  IN EFI_EVENT Event,
+  IN VOID      *Context
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
+
+  ASSERT (Event == mGopEvent);
+
+  //
+  // Check further GOPs.
+  //
+  for (;;) {
+    mNumGopModes = 0;
+    mGopModes = NULL;
+
+    Status = gBS->LocateProtocol (&gEfiGraphicsOutputProtocolGuid, mGopTracker,
+                    (VOID **) &Gop);
+    if (EFI_ERROR (Status)) {
+      return;
+    }
+
+    Status = QueryGopModes (Gop, &mNumGopModes, &mGopModes);
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    Status = PopulateForm (mInstalledPackages, &gOvmfPlatformConfigGuid,
+               FORMID_MAIN_FORM, mNumGopModes, mGopModes);
+    if (EFI_ERROR (Status)) {
+      FreePool (mGopModes);
+      continue;
+    }
+
+    break;
+  }
+
+  //
+  // Success -- so uninstall this callback. Closing the event removes all
+  // pending notifications and all protocol registrations.
+  //
+  Status = gBS->CloseEvent (mGopEvent);
+  ASSERT_EFI_ERROR (Status);
+  mGopEvent = NULL;
+  mGopTracker = NULL;
+}
+
+
+/**
   Entry point for this driver.
 
   @param[in] ImageHandle  Image handle of this driver.
@@ -433,14 +600,29 @@
     goto UninstallProtocols;
   }
 
-  Status = PopulateForm (mInstalledPackages, &gOvmfPlatformConfigGuid,
-             FORMID_MAIN_FORM);
+  Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, &GopInstalled,
+                  NULL /* Context */, &mGopEvent);
   if (EFI_ERROR (Status)) {
     goto RemovePackages;
   }
 
+  Status = gBS->RegisterProtocolNotify (&gEfiGraphicsOutputProtocolGuid,
+                  mGopEvent, &mGopTracker);
+  if (EFI_ERROR (Status)) {
+    goto CloseGopEvent;
+  }
+
+  //
+  // Check already installed GOPs.
+  //
+  Status = gBS->SignalEvent (mGopEvent);
+  ASSERT_EFI_ERROR (Status);
+
   return EFI_SUCCESS;
 
+CloseGopEvent:
+  gBS->CloseEvent (mGopEvent);
+
 RemovePackages:
   HiiRemovePackages (mInstalledPackages);
 
@@ -465,6 +647,24 @@
   IN  EFI_HANDLE  ImageHandle
   )
 {
+  if (mGopEvent == NULL) {
+    //
+    // The GOP callback ran successfully and unregistered itself. Release the
+    // resources allocated there.
+    //
+    ASSERT (mGopModes != NULL);
+    FreePool (mGopModes);
+  } else {
+    //
+    // Otherwise we need to unregister the callback.
+    //
+    ASSERT (mGopModes == NULL);
+    gBS->CloseEvent (mGopEvent);
+  }
+
+  //
+  // Release resources allocated by the entry point.
+  //
   HiiRemovePackages (mInstalledPackages);
   gBS->UninstallMultipleProtocolInterfaces (ImageHandle,
          &gEfiDevicePathProtocolGuid,      &mPkgDevicePath,

Modified: trunk/edk2/OvmfPkg/PlatformDxe/Platform.inf
===================================================================
--- trunk/edk2/OvmfPkg/PlatformDxe/Platform.inf 2014-03-22 07:13:44 UTC (rev 
15371)
+++ trunk/edk2/OvmfPkg/PlatformDxe/Platform.inf 2014-03-22 07:13:50 UTC (rev 
15372)
@@ -42,6 +42,7 @@
   DevicePathLib
   HiiLib
   MemoryAllocationLib
+  PrintLib
   UefiBootServicesTableLib
   UefiHiiServicesLib
   UefiLib
@@ -54,6 +55,7 @@
 
 [Protocols]
   gEfiDevicePathProtocolGuid      ## PRODUCES
+  gEfiGraphicsOutputProtocolGuid  ## CONSUMES
   gEfiHiiConfigAccessProtocolGuid ## PRODUCES
 
 [Guids]

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and their
applications. Written by three acclaimed leaders in the field,
this first edition is now available. Download your free book today!
http://p.sf.net/sfu/13534_NeoTech
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to