12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082 |
- /** @file
- This driver effectuates OVMF's platform configuration settings and exposes
- them via HII.
- Copyright (C) 2014, Red Hat, Inc.
- Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <Library/BaseLib.h>
- #include <Library/BaseMemoryLib.h>
- #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>
- #include "Platform.h"
- #include "PlatformConfig.h"
- //
- // The HiiAddPackages() library function requires that any controller (or
- // image) handle, to be associated with the HII packages under installation, be
- // "decorated" with a device path. The tradition seems to be a vendor device
- // path.
- //
- // We'd like to associate our HII packages with the driver's image handle. The
- // first idea is to use the driver image's device path. Unfortunately, loaded
- // images only come with an EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL (not the
- // usual EFI_DEVICE_PATH_PROTOCOL), ie. a different GUID. In addition, even the
- // EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL interface may be NULL, if the image
- // has been loaded from an "unnamed" memory source buffer.
- //
- // Hence let's just stick with the tradition -- use a dedicated vendor device
- // path, with the driver's FILE_GUID.
- //
- #pragma pack(1)
- typedef struct {
- VENDOR_DEVICE_PATH VendorDevicePath;
- EFI_DEVICE_PATH_PROTOCOL End;
- } PKG_DEVICE_PATH;
- #pragma pack()
- STATIC PKG_DEVICE_PATH mPkgDevicePath = {
- {
- {
- HARDWARE_DEVICE_PATH,
- HW_VENDOR_DP,
- {
- (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
- (UINT8)(sizeof (VENDOR_DEVICE_PATH) >> 8)
- }
- },
- EFI_CALLER_ID_GUID
- },
- {
- END_DEVICE_PATH_TYPE,
- END_ENTIRE_DEVICE_PATH_SUBTYPE,
- {
- (UINT8)(END_DEVICE_PATH_LENGTH),
- (UINT8)(END_DEVICE_PATH_LENGTH >> 8)
- }
- }
- };
- //
- // The configuration interface between the HII engine (form display etc) and
- // this driver.
- //
- STATIC EFI_HII_CONFIG_ACCESS_PROTOCOL mConfigAccess;
- //
- // The handle representing our list of packages after installation.
- //
- STATIC EFI_HII_HANDLE mInstalledPackages;
- //
- // The arrays below constitute our HII package list. They are auto-generated by
- // the VFR compiler and linked into the driver image during the build.
- //
- // - The strings package receives its C identifier from the driver's BASE_NAME,
- // plus "Strings".
- //
- // - The forms package receives its C identifier from the VFR file's basename,
- // plus "Bin".
- //
- //
- 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;
- //
- // The driver image handle, used to obtain the device path for <ConfigHdr>.
- //
- STATIC EFI_HANDLE mImageHandle;
- //
- // Cache the resolutions we get from the GOP.
- //
- typedef struct {
- UINT32 X;
- UINT32 Y;
- } GOP_MODE;
- STATIC UINTN mNumGopModes;
- STATIC GOP_MODE *mGopModes;
- /**
- Load the persistent platform configuration and translate it to binary form
- state.
- If the platform configuration is missing, then the function fills in a
- default state.
- @param[out] MainFormState Binary form/widget state after translation.
- @retval EFI_SUCCESS Form/widget state ready.
- @return Error codes from underlying functions.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- PlatformConfigToFormState (
- OUT MAIN_FORM_STATE *MainFormState
- )
- {
- EFI_STATUS Status;
- PLATFORM_CONFIG PlatformConfig;
- UINT64 OptionalElements;
- UINTN ModeNumber;
- ZeroMem (MainFormState, sizeof *MainFormState);
- Status = PlatformConfigLoad (&PlatformConfig, &OptionalElements);
- switch (Status) {
- case EFI_SUCCESS:
- if (OptionalElements & PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION) {
- //
- // Format the preferred resolution as text.
- //
- UnicodeSPrintAsciiFormat (
- (CHAR16 *)MainFormState->CurrentPreferredResolution,
- sizeof MainFormState->CurrentPreferredResolution,
- "%Ldx%Ld",
- (INT64)PlatformConfig.HorizontalResolution,
- (INT64)PlatformConfig.VerticalResolution
- );
- //
- // Try to locate it in the drop-down list too. This may not succeed, but
- // that's fine.
- //
- for (ModeNumber = 0; ModeNumber < mNumGopModes; ++ModeNumber) {
- if ((mGopModes[ModeNumber].X == PlatformConfig.HorizontalResolution) &&
- (mGopModes[ModeNumber].Y == PlatformConfig.VerticalResolution))
- {
- MainFormState->NextPreferredResolution = (UINT32)ModeNumber;
- break;
- }
- }
- break;
- }
- //
- // fall through otherwise
- //
- case EFI_NOT_FOUND:
- UnicodeSPrintAsciiFormat (
- (CHAR16 *)MainFormState->CurrentPreferredResolution,
- sizeof MainFormState->CurrentPreferredResolution,
- "Unset"
- );
- break;
- default:
- return Status;
- }
- return EFI_SUCCESS;
- }
- /**
- This function is called by the HII machinery when it fetches the form state.
- See the precise documentation in the UEFI spec.
- @param[in] This The Config Access Protocol instance.
- @param[in] Request A <ConfigRequest> format UCS-2 string describing the
- query.
- @param[out] Progress A pointer into Request on output, identifying the query
- element where processing failed.
- @param[out] Results A <MultiConfigAltResp> format UCS-2 string that has
- all values filled in for the names in the Request
- string.
- @retval EFI_SUCCESS Extraction of form state in <MultiConfigAltResp>
- encoding successful.
- @return Status codes from underlying functions.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- ExtractConfig (
- IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
- IN CONST EFI_STRING Request,
- OUT EFI_STRING *Progress,
- OUT EFI_STRING *Results
- )
- {
- MAIN_FORM_STATE MainFormState;
- EFI_STATUS Status;
- EFI_STRING ConfigRequestHdr;
- EFI_STRING ConfigRequest;
- UINTN Size;
- BOOLEAN AllocatedRequest;
- DEBUG ((DEBUG_VERBOSE, "%a: Request=\"%s\"\n", __FUNCTION__, Request));
- if ((Progress == NULL) || (Results == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- ConfigRequestHdr = NULL;
- ConfigRequest = NULL;
- Size = 0;
- AllocatedRequest = FALSE;
- //
- // Check if <ConfigHdr> matches the GUID and name
- //
- *Progress = Request;
- if ((Request != NULL) &&
- !HiiIsConfigHdrMatch (
- Request,
- &gOvmfPlatformConfigGuid,
- mHiiFormName
- )
- )
- {
- return EFI_NOT_FOUND;
- }
- Status = PlatformConfigToFormState (&MainFormState);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
- //
- // Request has no <RequestElement>, so construct full request string.
- // Allocate and fill a buffer large enough to hold <ConfigHdr>
- // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a
- // null terminator.
- //
- ConfigRequestHdr = HiiConstructConfigHdr (
- &gOvmfPlatformConfigGuid,
- mVariableName,
- mImageHandle
- );
- if (ConfigRequestHdr == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
- ConfigRequest = AllocateZeroPool (Size);
- AllocatedRequest = TRUE;
- if (ConfigRequest == NULL) {
- FreePool (ConfigRequestHdr);
- return EFI_OUT_OF_RESOURCES;
- }
- UnicodeSPrint (
- ConfigRequest,
- Size,
- L"%s&OFFSET=0&WIDTH=%016LX",
- ConfigRequestHdr,
- sizeof MainFormState
- );
- FreePool (ConfigRequestHdr);
- } else {
- ConfigRequest = Request;
- }
- //
- // Answer the textual request keying off the binary form state.
- //
- Status = gHiiConfigRouting->BlockToConfig (
- gHiiConfigRouting,
- ConfigRequest,
- (VOID *)&MainFormState,
- sizeof MainFormState,
- Results,
- Progress
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: BlockToConfig(): %r, Progress=\"%s\"\n",
- __FUNCTION__,
- Status,
- (Status == EFI_DEVICE_ERROR) ? NULL : *Progress
- ));
- } else {
- DEBUG ((DEBUG_VERBOSE, "%a: Results=\"%s\"\n", __FUNCTION__, *Results));
- }
- //
- // If we used a newly allocated ConfigRequest, update Progress to point to
- // original Request instead of ConfigRequest.
- //
- if (Request == NULL) {
- *Progress = NULL;
- } else if (StrStr (Request, L"OFFSET") == NULL) {
- if (EFI_ERROR (Status)) {
- //
- // Since we constructed ConfigRequest, failure can only occur if there
- // is not enough memory. In this case, we point Progress to the first
- // character of Request.
- //
- *Progress = Request;
- } else {
- //
- // In case of success, we point Progress to the null terminator of
- // Request.
- //
- *Progress = Request + StrLen (Request);
- }
- }
- if (AllocatedRequest) {
- FreePool (ConfigRequest);
- }
- return Status;
- }
- /**
- Interpret the binary form state and save it as persistent platform
- configuration.
- @param[in] MainFormState Binary form/widget state to verify and save.
- @retval EFI_SUCCESS Platform configuration saved.
- @return Error codes from underlying functions.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- FormStateToPlatformConfig (
- IN CONST MAIN_FORM_STATE *MainFormState
- )
- {
- EFI_STATUS Status;
- PLATFORM_CONFIG PlatformConfig;
- CONST GOP_MODE *GopMode;
- //
- // There's nothing to do with the textual CurrentPreferredResolution field.
- // We verify and translate the selection in the drop-down list.
- //
- if (MainFormState->NextPreferredResolution >= mNumGopModes) {
- return EFI_INVALID_PARAMETER;
- }
- GopMode = mGopModes + MainFormState->NextPreferredResolution;
- ZeroMem (&PlatformConfig, sizeof PlatformConfig);
- PlatformConfig.HorizontalResolution = GopMode->X;
- PlatformConfig.VerticalResolution = GopMode->Y;
- Status = PlatformConfigSave (&PlatformConfig);
- return Status;
- }
- /**
- This function is called by the HII machinery when it wants the driver to
- interpret and persist the form state.
- See the precise documentation in the UEFI spec.
- @param[in] This The Config Access Protocol instance.
- @param[in] Configuration A <ConfigResp> format UCS-2 string describing the
- form state.
- @param[out] Progress A pointer into Configuration on output,
- identifying the element where processing failed.
- @retval EFI_SUCCESS Configuration verified, state permanent.
- @return Status codes from underlying functions.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- RouteConfig (
- IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
- IN CONST EFI_STRING Configuration,
- OUT EFI_STRING *Progress
- )
- {
- MAIN_FORM_STATE MainFormState;
- UINTN BlockSize;
- EFI_STATUS Status;
- DEBUG ((
- DEBUG_VERBOSE,
- "%a: Configuration=\"%s\"\n",
- __FUNCTION__,
- Configuration
- ));
- if ((Progress == NULL) || (Configuration == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Check if <ConfigHdr> matches the GUID and name
- //
- *Progress = Configuration;
- if ((Configuration != NULL) &&
- !HiiIsConfigHdrMatch (
- Configuration,
- &gOvmfPlatformConfigGuid,
- mHiiFormName
- )
- )
- {
- return EFI_NOT_FOUND;
- }
- //
- // the "read" step in RMW
- //
- Status = PlatformConfigToFormState (&MainFormState);
- if (EFI_ERROR (Status)) {
- *Progress = Configuration;
- return Status;
- }
- //
- // the "modify" step in RMW
- //
- // (Update the binary form state. This update may be partial, which is why in
- // general we must pre-load the form state from the platform config.)
- //
- BlockSize = sizeof MainFormState;
- Status = gHiiConfigRouting->ConfigToBlock (
- gHiiConfigRouting,
- Configuration,
- (VOID *)&MainFormState,
- &BlockSize,
- Progress
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: ConfigToBlock(): %r, Progress=\"%s\"\n",
- __FUNCTION__,
- Status,
- (Status == EFI_BUFFER_TOO_SMALL) ? NULL : *Progress
- ));
- return Status;
- }
- //
- // the "write" step in RMW
- //
- Status = FormStateToPlatformConfig (&MainFormState);
- if (EFI_ERROR (Status)) {
- *Progress = Configuration;
- }
- return Status;
- }
- STATIC
- EFI_STATUS
- EFIAPI
- Callback (
- IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
- IN EFI_BROWSER_ACTION Action,
- IN EFI_QUESTION_ID QuestionId,
- IN UINT8 Type,
- IN OUT EFI_IFR_TYPE_VALUE *Value,
- OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
- )
- {
- DEBUG ((
- DEBUG_VERBOSE,
- "%a: Action=0x%Lx QuestionId=%d Type=%d\n",
- __FUNCTION__,
- (UINT64)Action,
- QuestionId,
- Type
- ));
- if (Action != EFI_BROWSER_ACTION_CHANGED) {
- return EFI_UNSUPPORTED;
- }
- switch (QuestionId) {
- case QUESTION_SAVE_EXIT:
- *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
- break;
- case QUESTION_DISCARD_EXIT:
- *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
- break;
- default:
- break;
- }
- return EFI_SUCCESS;
- }
- /**
- 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.
- @param[in] PackageList The package list with the formset and form for
- which the drop down options are produced. Option
- names are added as new strings to PackageList.
- @param[out] OpCodeBuffer On output, a dynamically allocated opcode buffer
- with drop down list options corresponding to GOP
- 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
- have been extended with new strings. OpCodeBuffer is
- unchanged.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- CreateResolutionOptions (
- IN EFI_HII_HANDLE PackageList,
- OUT VOID **OpCodeBuffer,
- IN UINTN NumGopModes,
- IN GOP_MODE *GopModes
- )
- {
- EFI_STATUS Status;
- VOID *OutputBuffer;
- UINTN ModeNumber;
- OutputBuffer = HiiAllocateOpCodeHandle ();
- if (OutputBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- 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;
- }
- }
- *OpCodeBuffer = OutputBuffer;
- return EFI_SUCCESS;
- FreeOutputBuffer:
- HiiFreeOpCodeHandle (OutputBuffer);
- return Status;
- }
- /**
- 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.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- PopulateForm (
- IN EFI_HII_HANDLE PackageList,
- IN EFI_GUID *FormSetGuid,
- IN EFI_FORM_ID FormId,
- IN UINTN NumGopModes,
- IN GOP_MODE *GopModes
- )
- {
- EFI_STATUS Status;
- VOID *OpCodeBuffer;
- VOID *OpCode;
- EFI_IFR_GUID_LABEL *Anchor;
- VOID *OpCodeBuffer2;
- OpCodeBuffer2 = NULL;
- //
- // 1. Allocate an empty opcode buffer.
- //
- OpCodeBuffer = HiiAllocateOpCodeHandle ();
- if (OpCodeBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // 2. Create a label opcode (which is a Tiano extension) inside the buffer.
- // The label's number must match the "anchor" label in the form.
- //
- OpCode = HiiCreateGuidOpCode (
- OpCodeBuffer,
- &gEfiIfrTianoGuid,
- NULL /* optional copy origin */,
- sizeof *Anchor
- );
- if (OpCode == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto FreeOpCodeBuffer;
- }
- Anchor = OpCode;
- Anchor->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
- Anchor->Number = LABEL_RES_NEXT;
- //
- // 3. Create the opcodes inside the buffer that are to be inserted into the
- // form.
- //
- // 3.1. Get a list of resolutions.
- //
- Status = CreateResolutionOptions (
- PackageList,
- &OpCodeBuffer2,
- NumGopModes,
- GopModes
- );
- if (EFI_ERROR (Status)) {
- goto FreeOpCodeBuffer;
- }
- //
- // 3.2. Create a one-of-many question with the above options.
- //
- OpCode = HiiCreateOneOfOpCode (
- OpCodeBuffer, // create opcode inside this
- // opcode buffer,
- QUESTION_RES_NEXT, // ID of question,
- FORMSTATEID_MAIN_FORM, // identifies form state
- // storage,
- (UINT16)OFFSET_OF (
- MAIN_FORM_STATE, // value of question stored
- NextPreferredResolution
- ), // at this offset,
- STRING_TOKEN (STR_RES_NEXT), // Prompt,
- STRING_TOKEN (STR_RES_NEXT_HELP), // Help,
- 0, // QuestionFlags,
- EFI_IFR_NUMERIC_SIZE_4, // see sizeof
- // NextPreferredResolution,
- OpCodeBuffer2, // buffer with possible
- // choices,
- NULL // DEFAULT opcodes
- );
- if (OpCode == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto FreeOpCodeBuffer2;
- }
- //
- // 4. Update the form with the opcode buffer.
- //
- Status = HiiUpdateForm (
- PackageList,
- FormSetGuid,
- FormId,
- OpCodeBuffer, // buffer with head anchor, and new contents to be
- // inserted at it
- NULL // buffer with tail anchor, for deleting old
- // contents up to it
- );
- FreeOpCodeBuffer2:
- HiiFreeOpCodeHandle (OpCodeBuffer2);
- FreeOpCodeBuffer:
- HiiFreeOpCodeHandle (OpCodeBuffer);
- return Status;
- }
- /**
- Load and execute the platform configuration.
- @retval EFI_SUCCESS Configuration loaded and executed.
- @return Status codes from PlatformConfigLoad().
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- ExecutePlatformConfig (
- VOID
- )
- {
- EFI_STATUS Status;
- PLATFORM_CONFIG PlatformConfig;
- UINT64 OptionalElements;
- RETURN_STATUS PcdStatus;
- Status = PlatformConfigLoad (&PlatformConfig, &OptionalElements);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- (Status == EFI_NOT_FOUND) ? DEBUG_VERBOSE : DEBUG_ERROR,
- "%a: failed to load platform config: %r\n",
- __FUNCTION__,
- Status
- ));
- return Status;
- }
- if (OptionalElements & PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION) {
- //
- // Pass the preferred resolution to GraphicsConsoleDxe via dynamic PCDs.
- //
- PcdStatus = PcdSet32S (
- PcdVideoHorizontalResolution,
- PlatformConfig.HorizontalResolution
- );
- ASSERT_RETURN_ERROR (PcdStatus);
- PcdStatus = PcdSet32S (
- PcdVideoVerticalResolution,
- PlatformConfig.VerticalResolution
- );
- ASSERT_RETURN_ERROR (PcdStatus);
- PcdStatus = PcdSet8S (PcdVideoResolutionSource, 1);
- ASSERT_RETURN_ERROR (PcdStatus);
- }
- return EFI_SUCCESS;
- }
- /**
- 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.
- @param[in] SystemTable Pointer to SystemTable.
- @retval EFI_SUCESS Driver has loaded successfully.
- @retval EFI_OUT_OF_RESOURCES Failed to install HII packages.
- @return Error codes from lower level functions.
- **/
- EFI_STATUS
- EFIAPI
- PlatformInit (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- ExecutePlatformConfig ();
- mConfigAccess.ExtractConfig = &ExtractConfig;
- mConfigAccess.RouteConfig = &RouteConfig;
- mConfigAccess.Callback = &Callback;
- //
- // Declare ourselves suitable for HII communication.
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &ImageHandle,
- &gEfiDevicePathProtocolGuid,
- &mPkgDevicePath,
- &gEfiHiiConfigAccessProtocolGuid,
- &mConfigAccess,
- NULL
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Save the driver image handle.
- //
- mImageHandle = ImageHandle;
- //
- // Publish the HII package list to HII Database.
- //
- mInstalledPackages = HiiAddPackages (
- &gEfiCallerIdGuid, // PackageListGuid
- ImageHandle, // associated DeviceHandle
- PlatformDxeStrings, // 1st package
- PlatformFormsBin, // 2nd package
- NULL // terminator
- );
- if (mInstalledPackages == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto UninstallProtocols;
- }
- 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);
- UninstallProtocols:
- gBS->UninstallMultipleProtocolInterfaces (
- ImageHandle,
- &gEfiDevicePathProtocolGuid,
- &mPkgDevicePath,
- &gEfiHiiConfigAccessProtocolGuid,
- &mConfigAccess,
- NULL
- );
- return Status;
- }
- /**
- Unload the driver.
- @param[in] ImageHandle Handle that identifies the image to evict.
- @retval EFI_SUCCESS The image has been unloaded.
- **/
- EFI_STATUS
- EFIAPI
- PlatformUnload (
- 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,
- &gEfiHiiConfigAccessProtocolGuid,
- &mConfigAccess,
- NULL
- );
- return EFI_SUCCESS;
- }
|