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 <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15372 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Laszlo Ersek 2014-03-22 07:13:50 +00:00 committed by jljusten
parent 9c08bbe59c
commit da07afaf59
2 changed files with 222 additions and 20 deletions

View File

@ -18,9 +18,12 @@
#include <Library/DebugLib.h> #include <Library/DebugLib.h>
#include <Library/DevicePathLib.h> #include <Library/DevicePathLib.h>
#include <Library/HiiLib.h> #include <Library/HiiLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiBootServicesTableLib.h> #include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiHiiServicesLib.h> #include <Library/UefiHiiServicesLib.h>
#include <Protocol/DevicePath.h> #include <Protocol/DevicePath.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/HiiConfigAccess.h> #include <Protocol/HiiConfigAccess.h>
#include <Guid/MdeModuleHii.h> #include <Guid/MdeModuleHii.h>
#include <Guid/OvmfPlatformConfig.h> #include <Guid/OvmfPlatformConfig.h>
@ -98,6 +101,29 @@ STATIC EFI_HII_HANDLE mInstalledPackages;
extern UINT8 PlatformDxeStrings[]; extern UINT8 PlatformDxeStrings[];
extern UINT8 PlatformFormsBin[]; 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. This function is called by the HII machinery when it fetches the form state.
@ -179,6 +205,68 @@ Callback (
} }
/**
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, 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. based on available GOP resolutions, to be placed under a "one-of-many" (ie.
@ -193,6 +281,10 @@ Callback (
resolutions. The caller is responsible for freeing resolutions. The caller is responsible for freeing
OpCodeBuffer with HiiFreeOpCodeHandle() after use. 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. @retval EFI_SUCESS Opcodes have been successfully produced.
@return Status codes from underlying functions. PackageList may @return Status codes from underlying functions. PackageList may
@ -204,30 +296,39 @@ EFI_STATUS
EFIAPI EFIAPI
CreateResolutionOptions ( CreateResolutionOptions (
IN EFI_HII_HANDLE *PackageList, IN EFI_HII_HANDLE *PackageList,
OUT VOID **OpCodeBuffer OUT VOID **OpCodeBuffer,
IN UINTN NumGopModes,
IN GOP_MODE *GopModes
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
VOID *OutputBuffer; VOID *OutputBuffer;
EFI_STRING_ID NewString; UINTN ModeNumber;
VOID *OpCode;
OutputBuffer = HiiAllocateOpCodeHandle (); OutputBuffer = HiiAllocateOpCodeHandle ();
if (OutputBuffer == NULL) { if (OutputBuffer == NULL) {
return EFI_OUT_OF_RESOURCES; return EFI_OUT_OF_RESOURCES;
} }
NewString = HiiSetString (PackageList, 0 /* new string */, L"800x600", for (ModeNumber = 0; ModeNumber < NumGopModes; ++ModeNumber) {
NULL /* for all languages */); CHAR16 Desc[MAXSIZE_RES_CUR];
if (NewString == 0) { EFI_STRING_ID NewString;
Status = EFI_OUT_OF_RESOURCES; VOID *OpCode;
goto FreeOutputBuffer;
} UnicodeSPrintAsciiFormat (Desc, sizeof Desc, "%Ldx%Ld",
OpCode = HiiCreateOneOfOptionOpCode (OutputBuffer, NewString, (INT64) GopModes[ModeNumber].X, (INT64) GopModes[ModeNumber].Y);
0 /* Flags */, EFI_IFR_NUMERIC_SIZE_4, 0 /* Value */); NewString = HiiSetString (PackageList, 0 /* new string */, Desc,
if (OpCode == NULL) { NULL /* for all languages */);
Status = EFI_OUT_OF_RESOURCES; if (NewString == 0) {
goto FreeOutputBuffer; 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;
}
} }
*OpCodeBuffer = OutputBuffer; *OpCodeBuffer = OutputBuffer;
@ -244,6 +345,9 @@ FreeOutputBuffer:
Populate the form identified by the (PackageList, FormSetGuid, FormId) Populate the form identified by the (PackageList, FormSetGuid, FormId)
triplet. triplet.
The drop down list of video resolutions is generated from (NumGopModes,
GopModes).
@retval EFI_SUCESS Form successfully updated. @retval EFI_SUCESS Form successfully updated.
@return Status codes from underlying functions. @return Status codes from underlying functions.
@ -254,7 +358,9 @@ EFIAPI
PopulateForm ( PopulateForm (
IN EFI_HII_HANDLE *PackageList, IN EFI_HII_HANDLE *PackageList,
IN EFI_GUID *FormSetGuid, IN EFI_GUID *FormSetGuid,
IN EFI_FORM_ID FormId IN EFI_FORM_ID FormId,
IN UINTN NumGopModes,
IN GOP_MODE *GopModes
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
@ -293,7 +399,8 @@ PopulateForm (
// //
// 3.1. Get a list of resolutions. // 3.1. Get a list of resolutions.
// //
Status = CreateResolutionOptions (PackageList, &OpCodeBuffer2); Status = CreateResolutionOptions (PackageList, &OpCodeBuffer2,
NumGopModes, GopModes);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto FreeOpCodeBuffer; goto FreeOpCodeBuffer;
} }
@ -381,6 +488,66 @@ ExecutePlatformConfig (
} }
/**
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. Entry point for this driver.
@ -433,14 +600,29 @@ PlatformInit (
goto UninstallProtocols; goto UninstallProtocols;
} }
Status = PopulateForm (mInstalledPackages, &gOvmfPlatformConfigGuid, Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, &GopInstalled,
FORMID_MAIN_FORM); NULL /* Context */, &mGopEvent);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto RemovePackages; 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; return EFI_SUCCESS;
CloseGopEvent:
gBS->CloseEvent (mGopEvent);
RemovePackages: RemovePackages:
HiiRemovePackages (mInstalledPackages); HiiRemovePackages (mInstalledPackages);
@ -465,6 +647,24 @@ PlatformUnload (
IN EFI_HANDLE ImageHandle 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); HiiRemovePackages (mInstalledPackages);
gBS->UninstallMultipleProtocolInterfaces (ImageHandle, gBS->UninstallMultipleProtocolInterfaces (ImageHandle,
&gEfiDevicePathProtocolGuid, &mPkgDevicePath, &gEfiDevicePathProtocolGuid, &mPkgDevicePath,

View File

@ -42,6 +42,7 @@
DevicePathLib DevicePathLib
HiiLib HiiLib
MemoryAllocationLib MemoryAllocationLib
PrintLib
UefiBootServicesTableLib UefiBootServicesTableLib
UefiHiiServicesLib UefiHiiServicesLib
UefiLib UefiLib
@ -54,6 +55,7 @@
[Protocols] [Protocols]
gEfiDevicePathProtocolGuid ## PRODUCES gEfiDevicePathProtocolGuid ## PRODUCES
gEfiGraphicsOutputProtocolGuid ## CONSUMES
gEfiHiiConfigAccessProtocolGuid ## PRODUCES gEfiHiiConfigAccessProtocolGuid ## PRODUCES
[Guids] [Guids]