mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-30 17:14:07 +02:00
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:
parent
9c08bbe59c
commit
da07afaf59
@ -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,
|
||||||
|
@ -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]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user