alder_lake_bios/Insyde/InsydeSetupPkg/Drivers/H2OFormBrowserDxe/H2OFormBrowser.c

2755 lines
87 KiB
C

/** @file
Function definition for formbrowser
;******************************************************************************
;* Copyright (c) 2013 - 2021, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "InternalH2OFormBrowser.h"
#include <Protocol/FormBrowserEx2.h>
#include <Library/DxeOemSvcKernelLib.h>
extern EFI_GUID gEfiCallerIdGuid;
EFI_LOCK mHiiExportPackageListsLock = {TPL_CALLBACK, TPL_APPLICATION, EfiLockReleased};
H2O_DISPLAY_ENGINE_EVT_OPEN_D *mOpenD = NULL;
/**
Get hotkey information for specific formset/form/statement(optional)
@param[in] FormSet Pointer to the formset
@param[in] Form Pointer to the form
@param[in] Statement Pointer to the statement
@param[out] HotKeyInfoCount Pointer to the count of hot key info
@param[out] HotKeyInfo Double pointer to the hot key info
@retval EFI_SUCCESS Get hot key info successfully
@retval EFI_INVALID_PARAMETER Input parameter is NULL
@retval EFI_NOT_FOUND Hot key info is not found
**/
EFI_STATUS
FBGetHotKeyInfo (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_FORM *Form,
IN FORM_BROWSER_STATEMENT *Statement OPTIONAL,
OUT UINT32 *HotKeyInfoCount,
OUT HOT_KEY_INFO **HotKeyInfo
)
{
EFI_STATUS Status;
UINT32 Index;
if (FormSet == NULL || Form == NULL || HotKeyInfoCount == NULL || HotKeyInfo == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// The source priority of hot key list for a form:
// 1, Specific formset/form/statement (highest priority)
// 2, Specific formset/form
// 3, SCU formset class GUID if now is in SCU.
// 4, Formset class GUID of current form
// 5, Default formset GUID which value is zero GUID (lowest priority)
//
if (Statement != NULL) {
Status = GetHotKeyListByQuestion (
&FormSet->Guid,
Form->FormId,
(Statement->QuestionId != 0),
(Statement->QuestionId != 0) ? Statement->QuestionId : GetStatementPosition (Form, Statement),
HotKeyInfoCount,
HotKeyInfo
);
if (!EFI_ERROR (Status)) {
return EFI_SUCCESS;
}
}
Status = GetHotKeyList (&FormSet->Guid, Form->FormId, HotKeyInfoCount, HotKeyInfo);
if (!EFI_ERROR (Status)) {
return EFI_SUCCESS;
}
if (GetScuFormset () != NULL) {
Status = GetHotKeyList (&mScuFormSetGuid, Form->FormId, HotKeyInfoCount, HotKeyInfo);
if (!EFI_ERROR (Status)) {
return EFI_SUCCESS;
}
}
for (Index = 0; Index < FormSet->NumberOfClassGuid; Index++) {
if (CompareMem (&FormSet->ClassGuid[Index], &gZeroGuid, sizeof (EFI_GUID)) != 0) {
Status = GetHotKeyList (&FormSet->ClassGuid[Index], Form->FormId, HotKeyInfoCount, HotKeyInfo);
if (!EFI_ERROR (Status)) {
return EFI_SUCCESS;
}
}
}
Status = GetHotKeyList (&gZeroGuid, gCurrentSelection->FormId, HotKeyInfoCount, HotKeyInfo);
if (!EFI_ERROR (Status)) {
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
}
VOID
UpdateParentPage (
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private
)
{
H2O_FORM_BROWSER_P *ParentPage;
FORM_ENTRY_INFO *FormEntryInfo;
LIST_ENTRY *FormEntryInfoLink;
FORM_BROWSER_FORMSET *FormSet;
LIST_ENTRY *FormSetLink;
FORM_BROWSER_FORM *Form;
LIST_ENTRY *FormLink;
ParentPage = NULL;
FormEntryInfoLink = GetFirstNode (&mFBPrivate.FormBrowserEx2.FormViewHistoryHead);
while (!IsNull (&mFBPrivate.FormBrowserEx2.FormViewHistoryHead, FormEntryInfoLink)) {
FormEntryInfo = FORM_ENTRY_INFO_FROM_LINK (FormEntryInfoLink);
FormEntryInfoLink = GetNextNode (&mFBPrivate.FormBrowserEx2.FormViewHistoryHead, FormEntryInfoLink);
FormSetLink = GetFirstNode (&Private->FormSetList);
while (!IsNull (&Private->FormSetList, FormSetLink)) {
FormSet = FORM_BROWSER_FORMSET_FROM_DISPLAY_LINK (FormSetLink);
FormSetLink = GetNextNode (&Private->FormSetList, FormSetLink);
if (FormSet->HiiHandle != FormEntryInfo->HiiHandle ||
!CompareGuid (&FormSet->Guid, &FormEntryInfo->FormSetGuid)) {
continue;
}
FormLink = GetFirstNode (&FormSet->FormListHead);
while (!IsNull (&FormSet->FormListHead, FormLink)) {
Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
if (Form->FormId == FormEntryInfo->FormId) {
Form->PageInfo.ParentPage = ParentPage;
ParentPage = &Form->PageInfo;
break;
}
}
}
}
}
STATIC
EFI_STATUS
UpdatePageIdList (
IN OUT H2O_FORM_BROWSER_PRIVATE_DATA *Private
)
{
FORM_BROWSER_FORMSET *FormSet;
FORM_BROWSER_FORM *Form;
LIST_ENTRY *LinkFormSet;
LIST_ENTRY *LinkForm;
UINT32 Count;
FBFreePool ((VOID **) &Private->PageIdList);
Private->PageCount = 0;
Count = 0;
LinkFormSet = GetFirstNode (&Private->FormSetList);
while (!IsNull (&Private->FormSetList, LinkFormSet)) {
FormSet = FORM_BROWSER_FORMSET_FROM_DISPLAY_LINK (LinkFormSet);
LinkFormSet = GetNextNode (&Private->FormSetList, LinkFormSet);
LinkForm = GetFirstNode (&FormSet->FormListHead);
while (!IsNull (&FormSet->FormListHead, LinkForm)) {
Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);
LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);
Count++;
}
}
if (Count == 0) {
return EFI_SUCCESS;
}
Private->PageIdList = AllocateZeroPool (Count * sizeof (H2O_PAGE_ID));
if (Private->PageIdList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Private->PageCount = Count;
Count = 0;
LinkFormSet = GetFirstNode (&Private->FormSetList);
while (!IsNull (&Private->FormSetList, LinkFormSet)) {
FormSet = FORM_BROWSER_FORMSET_FROM_DISPLAY_LINK (LinkFormSet);
LinkFormSet = GetNextNode (&Private->FormSetList, LinkFormSet);
LinkForm = GetFirstNode (&FormSet->FormListHead);
while (!IsNull (&FormSet->FormListHead, LinkForm)) {
Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);
LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);
Private->PageIdList[Count++] = Form->PageInfo.PageId;
}
}
return EFI_SUCCESS;
}
STATIC
VOID
DestroyAllH2OStatements (
IN FORM_BROWSER_FORM *Form
)
{
FORM_BROWSER_STATEMENT *Statement;
LIST_ENTRY *LinkStatement;
LinkStatement = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, LinkStatement)) {
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);
LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);
DestroyH2OStatement (Statement);
}
}
STATIC
EFI_STATUS
InitAllH2OStatements (
IN OUT FORM_BROWSER_FORM *Form
)
{
H2O_FORM_BROWSER_P *Page;
UINTN Index;
UINT16 DisplayOrder;
UINT16 *DisplayOrderValueList;
LIST_ENTRY *LinkStatement;
FORM_BROWSER_STATEMENT *Statement;
EXPRESS_RESULT ExpressResult;
BOOLEAN IsNewPage;
if (Form == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Form->NumberOfStatement == 0 || IsListEmpty (&Form->StatementListHead)) {
return EFI_SUCCESS;
}
Page = &Form->PageInfo;
if (Page->StatementIds == NULL) {
return EFI_NOT_FOUND;
}
IsNewPage = (Page->NumberOfStatementIds == 0) ? TRUE : FALSE;
Page->NumberOfStatementIds = 0;
if (Page->StatementIds != NULL) {
ZeroMem (Page->StatementIds, sizeof (H2O_STATEMENT_ID) * Form->NumberOfStatement);
}
DisplayOrderValueList = AllocateZeroPool (Form->NumberOfStatement * sizeof (UINT16));
if (DisplayOrderValueList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
LinkStatement = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, LinkStatement)) {
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);
LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);
ExpressResult = EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL);
if (IS_VFR_IMPORT_FAKE_STATEMENT(Statement)) {
//
// Do not insert the import fake statement
//
ExpressResult = ExpressSuppress;
}
if (!IsNewPage) {
if (Statement->RefreshInterval == 0 && CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) {
//
// Only update page id
//
Statement->Statement.PageId = Page->PageId;
continue;
}
} else {
ASSERT (Page->NumberOfStatementIds < Form->NumberOfStatement);
if (ExpressResult <= ExpressGrayOut) {
//
// Add statement ID into the list by VFCF display-order property.
//
DisplayOrder = GetStatementDisplayOrder (Form, Statement);
for (Index = 0; Index < Page->NumberOfStatementIds; Index++) {
if (DisplayOrder > DisplayOrderValueList[Index]) {
break;
}
}
CopyMem (&DisplayOrderValueList[Index + 1], &DisplayOrderValueList[Index], (Page->NumberOfStatementIds - Index) * sizeof (UINT16));
CopyMem (&Page->StatementIds[Index + 1] , &Page->StatementIds[Index] , (Page->NumberOfStatementIds - Index) * sizeof (H2O_STATEMENT_ID));
DisplayOrderValueList[Index] = DisplayOrder;
Page->StatementIds[Index] = Statement->StatementId;
Page->NumberOfStatementIds++;
}
}
InitH2OStatement (
Form->FormSet,
Form,
ExpressResult,
Page,
Statement
);
}
FreePool (DisplayOrderValueList);
return EFI_SUCCESS;
}
/**
Formbrowser initialize page information
@param [in] Private Formbrowser private data
@retval EFI_SUCCESS Formbrowser initialize hotkey success
**/
EFI_STATUS
FBInitPageInfo (
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private
)
{
FORM_BROWSER_FORMSET *FormSet;
FORM_BROWSER_FORM *Form;
LIST_ENTRY *LinkFormSet;
LIST_ENTRY *LinkForm;
H2O_FORM_BROWSER_P *Page;
UI_MENU_SELECTION *Selection;
Selection = gCurrentSelection;
DestroyPageInfo (Private);
//
// Find all Form in Form Set
//
Private->PageCount = 0;
LinkFormSet = GetFirstNode (&Private->FormSetList);
while (!IsNull (&Private->FormSetList, LinkFormSet)) {
FormSet = FORM_BROWSER_FORMSET_FROM_DISPLAY_LINK (LinkFormSet);
LinkFormSet = GetNextNode (&Private->FormSetList, LinkFormSet);
LinkForm = GetFirstNode (&FormSet->FormListHead);
while (!IsNull (&FormSet->FormListHead, LinkForm)) {
Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);
LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);
Page = &Form->PageInfo;
InitPage (Private, FormSet, Form, Page);
if (FormSet->HiiHandle != Selection->Handle ||
Form->FormId != Selection->FormId) {
//
// For performance concern, only initialize statements of current form.
//
continue;
}
InitAllH2OStatements (Form);
}
}
UpdateParentPage (Private);
UpdatePageIdList (Private);
return EFI_SUCCESS;
}
/**
Formbrowser repaint scene.
@param [in] Private Formbrowser private data
@retval EFI_SUCCESS Formbrowser repaint scene success
**/
EFI_STATUS
FBRepaint (
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private
)
{
H2O_DISPLAY_ENGINE_EVT_OPEN_L OpenL;
H2O_DISPLAY_ENGINE_EVT_OPEN_P OpenP;
//
// If selection not ready, do nothing (maybe only pop dialog)
//
if (gCurrentSelection == NULL) {
if (mOpenD != NULL) {
FBBroadcastEvent ((H2O_DISPLAY_ENGINE_EVT *) mOpenD);
}
return EFI_SUCCESS;
}
//
// send OPEN_L, OPEN_P
//
ZeroMem (&OpenL, sizeof (H2O_DISPLAY_ENGINE_EVT_OPEN_L));
OpenL.Hdr.Size = sizeof (H2O_DISPLAY_ENGINE_EVT_OPEN_L);
OpenL.Hdr.Target = H2O_DISPLAY_ENGINE_EVT_TARGET_FORM_BROWSER;
OpenL.Hdr.Type = H2O_DISPLAY_ENGINE_EVT_TYPE_OPEN_L;
FBBroadcastEvent ((H2O_DISPLAY_ENGINE_EVT*)&OpenL);
ZeroMem (&OpenP, sizeof (H2O_DISPLAY_ENGINE_EVT_OPEN_P));
OpenP.Hdr.Size = sizeof (H2O_DISPLAY_ENGINE_EVT_OPEN_P);
OpenP.Hdr.Target = H2O_DISPLAY_ENGINE_EVT_TARGET_FORM_BROWSER;
OpenP.Hdr.Type = H2O_DISPLAY_ENGINE_EVT_TYPE_OPEN_P;
FBBroadcastEvent ((H2O_DISPLAY_ENGINE_EVT*)&OpenP);
if (mOpenD != NULL) {
FBBroadcastEvent ((H2O_DISPLAY_ENGINE_EVT *) mOpenD);
}
return EFI_SUCCESS;
}
/**
Get the form set image based on the input IFR and HII Package List Handle.
@param [in] Formset Pointer to EFI_IFR_FORM_SET instance.
@param [in] HiiHandle The package list in the HII database to search for
the specified string.
@return Other The output EFI_IMAGE_INPUT.
@retval NULL Cannot find formset image.
**/
STATIC
EFI_IMAGE_INPUT *
GetFormSetImage (
IN EFI_IFR_FORM_SET *Formset,
IN EFI_HII_HANDLE HiiHandle
)
{
EFI_IFR_OP_HEADER *OpHeader;
EFI_STATUS Status;
EFI_IMAGE_INPUT *ImageIn;
ASSERT (Formset != NULL && Formset->Header.OpCode == EFI_IFR_FORM_SET_OP );
OpHeader = (EFI_IFR_OP_HEADER *) (((UINT8 *) Formset) + Formset->Header.Length);
//
// Skip all of default store OP code
//
while (OpHeader->OpCode == EFI_IFR_DEFAULTSTORE_OP || OpHeader->OpCode == EFI_IFR_GUID_OP) {
OpHeader = (EFI_IFR_OP_HEADER *) (((UINT8 *) OpHeader) + OpHeader->Length);
}
if (OpHeader->OpCode != EFI_IFR_IMAGE_OP) {
return NULL;
}
//
// Try to get image by image ID from HII handle.
//
ImageIn = AllocateZeroPool (sizeof (EFI_IMAGE_INPUT));
ASSERT (ImageIn != NULL);
if (ImageIn == NULL) {
return NULL;
}
Status = gHiiImage->GetImage (
gHiiImage,
HiiHandle,
((EFI_IFR_IMAGE *) OpHeader)->Id,
ImageIn
);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
FreePool (ImageIn);
return NULL;
}
return ImageIn;
}
/**
Export HII package list with critical section design.
@param[in] Handle The HII handle
@param[out] HiiPackageListSize Pointer to output HII package list size
@param[out] HiiPackageList Pointer to the pointer of HII package list
@retval EFI_SUCCESS Export HII package list successfully.
@retval EFI_OUT_OF_RESOURCES Fail to allocate memory.
@retval Other ExportPackageLists() return failed.
**/
EFI_STATUS
FBHiiExportPackageLists (
IN EFI_HII_HANDLE Handle,
OUT UINTN *HiiPackageListSize,
OUT EFI_HII_PACKAGE_LIST_HEADER **HiiPackageList
)
{
EFI_STATUS Status;
EFI_HII_PACKAGE_LIST_HEADER *Buffer;
UINTN BufferSize;
Buffer = NULL;
BufferSize = 0;
//
// Acquire lock to avoid HII package list is changed.
//
EfiAcquireLock (&mHiiExportPackageListsLock);
Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, Buffer);
if (Status != EFI_BUFFER_TOO_SMALL) {
Status = EFI_NOT_FOUND;
goto Done;
}
Buffer = AllocatePool (BufferSize);
ASSERT (Buffer != NULL);
if (Buffer == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, Buffer);
if (EFI_ERROR (Status)) {
FreePool (Buffer);
goto Done;
}
*HiiPackageListSize = BufferSize;
*HiiPackageList = Buffer;
Done:
EfiReleaseLock (&mHiiExportPackageListsLock);
return Status;
}
/**
Extract the displayed formset for given HII handle and class guid.
@param Handle The HII handle.
@param SetupClassGuid The class guid specifies which form set will be displayed.
@param SkipCount Skip some formsets which has processed before.
@param FormSetTitle Formset title string.
@param FormSetHelp Formset help string.
@param FormSetGuid Return the formset guid for this formset.
@retval TRUE The formset for given HII handle will be displayed.
@return FALSE The formset for given HII handle will not be displayed.
**/
BOOLEAN
LocateFormSetInfo (
IN EFI_HII_HANDLE Handle,
IN OUT CHAR16 **FormSetTitle,
IN OUT EFI_IMAGE_INPUT **FormSetImage
)
{
EFI_STATUS Status;
UINTN BufferSize;
EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
UINT8 *Package;
UINT8 *OpCodeData;
UINT32 Offset;
UINT32 Offset2;
UINT32 PackageListLength;
EFI_HII_PACKAGE_HEADER PackageHeader;
ASSERT (Handle != NULL);
ASSERT (FormSetTitle != NULL);
ASSERT (FormSetImage != NULL);
*FormSetTitle = NULL;
*FormSetImage = NULL;
Status = FBHiiExportPackageLists (Handle, &BufferSize, &HiiPackageList);
if (EFI_ERROR (Status)) {
return FALSE;
}
//
// Get Form package from this HII package List
//
Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
Offset2 = 0;
PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
while (Offset < PackageListLength) {
Package = ((UINT8 *) HiiPackageList) + Offset;
CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
//
// Search FormSet Opcode in this Form Package
//
Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
while (Offset2 < PackageHeader.Length) {
OpCodeData = Package + Offset2;
Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
*FormSetTitle = GetString (((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, Handle);
*FormSetImage = GetFormSetImage ((EFI_IFR_FORM_SET *) OpCodeData, Handle);
FreePool (HiiPackageList);
return TRUE;
}
}
}
//
// Go to next package
//
Offset += PackageHeader.Length;
}
FreePool (HiiPackageList);
return FALSE;
}
/**
Formbrowser initialize setup menu information
@param [in] Private Formbrowser private data
@param [in] HiiHandleList Pointer to HII handle list
@param [in] HiiHandleCount Number of HII handle in list
@retval EFI_SUCCESS Formbrowser initialize setup menu success
**/
EFI_STATUS
FBInitSMInfo (
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE *HiiHandleList,
IN UINTN HiiHandleCount
)
{
UINT32 Index;
EFI_HII_HANDLE *SetupMenuHiiHandle;
UINTN SetupMenuCount;
UINT32 SetupMenuIndex;
EFI_GUID ZeroGuid;
EFI_STATUS OemSvcStatus;
ZeroMem (&ZeroGuid, sizeof (EFI_GUID));
SetupMenuCount = HiiHandleCount;
SetupMenuHiiHandle = AllocateCopyPool (sizeof(EFI_HII_HANDLE) * SetupMenuCount, HiiHandleList);
if (SetupMenuHiiHandle == NULL) {
return EFI_OUT_OF_RESOURCES;
}
if (GetScuFormset () != NULL) {
//
// Call OEM service function to determine setup menu when SCU
//
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcAdjustNavigationMenu \n"));
OemSvcStatus = OemSvcAdjustNavigationMenu (SetupMenuHiiHandle, &SetupMenuCount, &ZeroGuid);
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcAdjustNavigationMenu Status: %r\n", OemSvcStatus));
}
//
// Initialize page ID for each setup menu info
//
Private->SetupMenuInfo = AllocateZeroPool (sizeof (SETUP_MENU_INFO) * SetupMenuCount);
if (Private->SetupMenuInfo == NULL) {
FreePool (SetupMenuHiiHandle);
return EFI_OUT_OF_RESOURCES;
}
for (SetupMenuIndex = 0; SetupMenuIndex < SetupMenuCount; SetupMenuIndex++) {
for (Index = 0; Index < HiiHandleCount; Index++) {
if (HiiHandleList[Index] != SetupMenuHiiHandle[SetupMenuIndex]) {
continue;
}
Private->SetupMenuInfo[Private->NumberOfSetupMenus].PageId = (Index << 16);
Private->NumberOfSetupMenus++;
break;
}
}
FreePool (SetupMenuHiiHandle);
return EFI_SUCCESS;
}
/**
Update setup menu information (page ID, title string and image)
@param [in] Private Formbrowser private data
@retval EFI_SUCCESS Successfully update setup menu information
**/
EFI_STATUS
FBUpdateSMInfo (
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private
)
{
UINT32 Index;
UINT32 HiiHandleIndex;
LIST_ENTRY *Link;
FORM_BROWSER_FORM *FirstForm;
SETUP_MENU_INFO *SetupMenuInfo;
for (Index = 0; Index < Private->NumberOfSetupMenus; Index++) {
SetupMenuInfo = &Private->SetupMenuInfo[Index];
HiiHandleIndex = SetupMenuInfo->PageId >> 16;
//
// Update current FormSet Root page id
//
if (HiiHandleIndex == Private->HiiHandleIndex) {
if (HiiHandleIndex < Private->HiiHandleCount &&
Private->HiiHandleList[HiiHandleIndex] == gCurrentSelection->Handle) {
Link = GetFirstNode (&gCurrentSelection->FormSet->FormListHead);
FirstForm = FORM_BROWSER_FORM_FROM_LINK (Link);
SetupMenuInfo->PageId = (H2O_PAGE_ID) ((HiiHandleIndex << 16) + FirstForm->FormId);
}
} else {
SetupMenuInfo->PageId = (H2O_PAGE_ID) (HiiHandleIndex << 16);
}
//
// Update title string and image for each setup menu
//
if (HiiHandleIndex < Private->HiiHandleCount) {
FBFreePool ((VOID **) &SetupMenuInfo->PageTitle);
if (SetupMenuInfo->PageImage != NULL) {
FreePool (SetupMenuInfo->PageImage->Bitmap);
FreePool (SetupMenuInfo->PageImage);
}
LocateFormSetInfo (
Private->HiiHandleList[HiiHandleIndex],
&SetupMenuInfo->PageTitle,
&SetupMenuInfo->PageImage
);
}
}
return EFI_SUCCESS;
}
/**
Load specific Hii formsets in the global maintain list of form browser.
@param[in] Handles A pointer to an array of Handles.
@param[in] HandleCount The number of Handles specified in Handle.
@retval EFI_SUCCESS Successfully load Hii formsets
@retval EFI_INVALID_PARAMETER Input pointer is NULL
@retval EFI_OUT_OF_RESOURCES Allocate pool fail
**/
EFI_STATUS
LoadHiiFormset (
IN EFI_HII_HANDLE *Handles,
IN UINTN HandleCount
)
{
FORM_BROWSER_FORMSET *LocalFormSet;
UINTN Index;
EFI_GUID ZeroGuid;
EFI_STATUS Status;
FORM_BROWSER_FORMSET *OldFormset;
FORM_BROWSER_FORM *Form;
LIST_ENTRY *Link;
if (Handles == NULL) {
return EFI_INVALID_PARAMETER;
}
OldFormset = mSystemLevelFormSet;
for (Index = 0; Index < HandleCount; Index++) {
//
// Initialize FormSet Setting
//
LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
if (LocalFormSet == NULL) {
return EFI_OUT_OF_RESOURCES;
}
mSystemLevelFormSet = LocalFormSet;
ZeroMem (&ZeroGuid, sizeof (ZeroGuid));
Status = InitializeFormSet (Handles[Index], &ZeroGuid, LocalFormSet);
if (IsListEmpty (&LocalFormSet->FormListHead)) {
DestroyFormSet (LocalFormSet);
continue;
} else if (EFI_ERROR (Status)) {
FreePool (LocalFormSet);
continue;
}
FBProcessImport (LocalFormSet);
FBProcessVfcfProperty (LocalFormSet);
FBProcessVfcfExpression (LocalFormSet);
InitCurrentSetting (LocalFormSet);
//
// Initialize Questions' Value
//
Status = LoadFormSetConfig (NULL, LocalFormSet);
if (EFI_ERROR (Status)) {
DestroyFormSet (LocalFormSet);
continue;
}
//
// Evaluate form expressions for non-SCU formset, because user may load default without going to these formsets.
//
if (CompareGuid (LocalFormSet->ClassGuid, &mScuFormSetGuid)) {
continue;
}
Link = GetFirstNode (&LocalFormSet->FormListHead);
while (!IsNull (&LocalFormSet->FormListHead, Link)) {
Form = FORM_BROWSER_FORM_FROM_LINK (Link);
EvaluateFormExpressions (LocalFormSet, Form);
Link = GetNextNode (&LocalFormSet->FormListHead, Link);
}
}
mSystemLevelFormSet = OldFormset;
return EFI_SUCCESS;
}
/**
Destroy specific Hii formsets from the global maintain list of form browser.
@param[in] Handles A pointer to an array of Handles.
@param[in] HandleCount The number of Handles specified in Handle.
@retval EFI_SUCCESS Successfully load Hii formsets
@retval EFI_INVALID_PARAMETER Input pointer is NULL
**/
EFI_STATUS
DestroyLoadHiiFormset (
VOID
)
{
LIST_ENTRY *FormSetLink;
FORM_BROWSER_FORMSET *FormSet;
FORM_BROWSER_FORMSET *OldFormset;
OldFormset = mSystemLevelFormSet;
FormSetLink = GetFirstNode (&gBrowserFormSetList);
while (!IsNull (&gBrowserFormSetList, FormSetLink)) {
FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormSetLink);
FormSetLink = GetNextNode (&gBrowserFormSetList, FormSetLink);
mSystemLevelFormSet = FormSet;
CleanBrowserStorage (FormSet);
RemoveEntryList (&FormSet->Link);
DestroyFormSet (FormSet);
}
mSystemLevelFormSet = OldFormset;
return EFI_SUCCESS;
}
/**
Check if two browser storages are identical or not
@param[in] BrowserStorage1 A pointer to browser storage
@param[in] BrowserStorage2 A pointer to browser storage
@retval TRUE Two browser storages are identical
@retval FALSE Two browser storages are different or input pointer is NULL
**/
BOOLEAN
IsStorageIdentical (
IN BROWSER_STORAGE *BrowserStorage1,
IN BROWSER_STORAGE *BrowserStorage2
)
{
if (BrowserStorage1 == NULL || BrowserStorage2 == NULL) {
return FALSE;
}
if ((BrowserStorage1->Type != BrowserStorage2->Type) ||
!CompareGuid (&BrowserStorage1->Guid, &BrowserStorage2->Guid)) {
return FALSE;
}
switch (BrowserStorage1->Type) {
case EFI_HII_VARSTORE_NAME_VALUE:
if (BrowserStorage1->HiiHandle == BrowserStorage2->HiiHandle) {
return TRUE;
}
break;
case EFI_HII_VARSTORE_EFI_VARIABLE:
case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
if (StrCmp (BrowserStorage1->Name, BrowserStorage2->Name) == 0) {
return TRUE;
}
case EFI_HII_VARSTORE_BUFFER:
if (BrowserStorage1->HiiHandle == BrowserStorage2->HiiHandle &&
StrCmp (BrowserStorage1->Name, BrowserStorage2->Name) == 0) {
return TRUE;
}
break;
}
return FALSE;
}
/**
Sync formset storage
@param[out] DstFormSetStorage A pointer to destination browser storage
@param[in] SrcFormSetStorage A pointer to source browser storage
@retval EFI_SUCCESS Successfully sync formset storage
@retval EFI_INVALID_PARAMETER Input pointer is NULL
@retval EFI_ABORTED Two storage are not identical
@retval EFI_UNSUPPORTED Function does not support for storage type
**/
EFI_STATUS
SyncStorage (
OUT FORMSET_STORAGE *DstFormSetStorage,
IN FORMSET_STORAGE *SrcFormSetStorage
)
{
LIST_ENTRY *SrcLink;
NAME_VALUE_NODE *SrcNode;
LIST_ENTRY *DstLink;
NAME_VALUE_NODE *DstNode;
if (DstFormSetStorage == NULL || SrcFormSetStorage == NULL) {
return EFI_INVALID_PARAMETER;
}
if (!IsStorageIdentical (DstFormSetStorage->BrowserStorage, SrcFormSetStorage->BrowserStorage)) {
return EFI_ABORTED;
}
switch (DstFormSetStorage->BrowserStorage->Type) {
case EFI_HII_VARSTORE_BUFFER:
case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
CopyMem (
DstFormSetStorage->BrowserStorage->EditBuffer,
SrcFormSetStorage->BrowserStorage->EditBuffer,
MIN(DstFormSetStorage->BrowserStorage->Size, SrcFormSetStorage->BrowserStorage->Size)
);
break;
case EFI_HII_VARSTORE_NAME_VALUE:
//
// Update each name value of source formset storage to destination formset storage.
//
SrcLink = GetFirstNode (&SrcFormSetStorage->BrowserStorage->NameValueListHead);
while (!IsNull (&SrcFormSetStorage->BrowserStorage->NameValueListHead, SrcLink)) {
SrcNode = NAME_VALUE_NODE_FROM_LINK (SrcLink);
SrcLink = GetNextNode (&SrcFormSetStorage->BrowserStorage->NameValueListHead, SrcLink);
DstLink = GetFirstNode (&DstFormSetStorage->BrowserStorage->NameValueListHead);
while (!IsNull (&DstFormSetStorage->BrowserStorage->NameValueListHead, DstLink)) {
DstNode = NAME_VALUE_NODE_FROM_LINK (DstLink);
DstLink = GetNextNode (&DstFormSetStorage->BrowserStorage->NameValueListHead, DstLink);
if (StrCmp (DstNode->Name, SrcNode->Name) == 0) {
NewStringCpy (&DstNode->EditValue, SrcNode->EditValue);
break;
}
}
}
break;
default:
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
/**
Sync all storages of two formset
@param[out] DstFormSet A pointer to destination formset
@param[in] SrcFormSet A pointer to source formset
@retval EFI_SUCCESS Successfully sync formset
@retval EFI_INVALID_PARAMETER Input pointer is NULL
**/
EFI_STATUS
SyncStorageByFormset (
OUT FORM_BROWSER_FORMSET *DstFormSet,
IN FORM_BROWSER_FORMSET *SrcFormSet
)
{
LIST_ENTRY *DstLink;
FORMSET_STORAGE *DstFormSetStorage;
LIST_ENTRY *SrcLink;
FORMSET_STORAGE *SrcFormSetStorage;
if (DstFormSet == NULL || SrcFormSet == NULL) {
return EFI_INVALID_PARAMETER;
}
DstLink = GetFirstNode (&DstFormSet->StorageListHead);
while (!IsNull (&DstFormSet->StorageListHead, DstLink)) {
DstFormSetStorage = (FORMSET_STORAGE_FROM_LINK (DstLink));
DstLink = GetNextNode (&DstFormSet->StorageListHead, DstLink);
//
// Skip if there is no RequestElement
//
if (DstFormSetStorage->ElementCount == 0) {
continue;
}
SrcLink = GetFirstNode (&SrcFormSet->StorageListHead);
while (!IsNull (&SrcFormSet->StorageListHead, SrcLink)) {
SrcFormSetStorage = (FORMSET_STORAGE_FROM_LINK (SrcLink));
SrcLink = GetNextNode (&SrcFormSet->StorageListHead, SrcLink);
//
// Skip if there is no RequestElement
//
if (SrcFormSetStorage->ElementCount == 0) {
continue;
}
SyncStorage (DstFormSetStorage, SrcFormSetStorage);
}
}
return EFI_SUCCESS;
}
/**
Sync storages of current formset to all formsets of global maintain list
**/
VOID
SyncCurrentStorageToAllHiiHandles (
VOID
)
{
FORM_BROWSER_FORMSET *FormSet;
LIST_ENTRY *FormSetLink;
FormSetLink = GetFirstNode (&gBrowserFormSetList);
while (!IsNull (&gBrowserFormSetList, FormSetLink)) {
FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormSetLink);
FormSetLink = GetNextNode (&gBrowserFormSetList, FormSetLink);
if (!ValidateFormSet (FormSet) || FormSet == mSystemLevelFormSet || CompareGuid (FormSet->ClassGuid, &mScuFormSetGuid)) {
continue;
}
SyncStorageByFormset (FormSet, mSystemLevelFormSet);
LoadFormSetConfig (gCurrentSelection, FormSet);
UpdateStatementStatus (FormSet, NULL, FormSetLevel);
}
}
EFI_STATUS
UpdateScuFormSetConfig (
VOID
)
{
LIST_ENTRY *Link;
FORM_BROWSER_FORMSET *OldFormSet;
FORM_BROWSER_FORMSET *FormSet;
EFI_BROWSER_ACTION_REQUEST ActionRequest;
OldFormSet = mSystemLevelFormSet;
//
// Get current question value from SCU VFR driver for SCU FormSet in the maintain list.
//
Link = GetFirstNode (&gBrowserFormSetList);
while (!IsNull (&gBrowserFormSetList, Link)) {
FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
Link = GetNextNode (&gBrowserFormSetList, Link);
if (!ValidateFormSet(FormSet) ||
!CompareGuid (FormSet->ClassGuid, &mScuFormSetGuid)) {
continue;
}
if (FormSet->ConfigAccess != NULL) {
mSystemLevelFormSet = FormSet;
FormSet->ConfigAccess->Callback (FormSet->ConfigAccess, EFI_BROWSER_ACTION_FORM_OPEN, 0, 0, NULL, &ActionRequest);
LoadFormSetConfig (gCurrentSelection, FormSet);
}
}
mSystemLevelFormSet = OldFormSet;
return EFI_SUCCESS;
}
/**
Get SCU browser formset data from gBrowserFormSetList
@return The pointer of SCU browser formset or NULL if there is no SCU browser formset data in gBrowserFormSetList
**/
FORM_BROWSER_FORMSET *
GetScuFormset (
VOID
)
{
FORM_BROWSER_FORMSET *LocalFormSet;
LIST_ENTRY *Link;
//
// Check current browser formset first.
//
if (mSystemLevelFormSet != NULL && CompareGuid (mSystemLevelFormSet->ClassGuid, &mScuFormSetGuid)) {
return mSystemLevelFormSet;
}
Link = GetFirstNode (&gBrowserFormSetList);
while (!IsNull (&gBrowserFormSetList, Link)) {
LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
if (CompareGuid (LocalFormSet->ClassGuid, &mScuFormSetGuid)) {
return LocalFormSet;
}
Link = GetNextNode (&gBrowserFormSetList, Link);
}
return NULL;
}
/**
Check if there is a storage element in the formset
@retval TRUE There is a storage element in the formset
@retval FALSE There is no storage element in the formset
**/
STATIC
BOOLEAN
HasStorageElement (
IN FORM_BROWSER_FORMSET *FormSet
)
{
LIST_ENTRY *Link;
FORMSET_STORAGE *FormSetStorage;
BROWSER_STORAGE *Storage;
Link = GetFirstNode (&FormSet->StorageListHead);
while (!IsNull (&FormSet->StorageListHead, Link)) {
FormSetStorage = (FORMSET_STORAGE_FROM_LINK (Link));
Storage = FormSetStorage->BrowserStorage;
Link = GetNextNode (&FormSet->StorageListHead, Link);
if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
continue;
}
if (FormSetStorage->ElementCount != 0) {
return TRUE;
}
}
return FALSE;
}
/**
Get SCU submit formset data from gBrowserFormSetList
@return The pointer of SCU submit formset or NULL if there is no SCU submit formset data in gBrowserFormSetList
**/
FORM_BROWSER_FORMSET *
GetScuSubmitFormset (
VOID
)
{
FORM_BROWSER_FORMSET *LocalFormSet;
LIST_ENTRY *Link;
//
// Check current browser formset first.
//
if (mSystemLevelFormSet != NULL && CompareGuid (mSystemLevelFormSet->ClassGuid, &mScuFormSetGuid) && HasStorageElement(mSystemLevelFormSet)) {
return mSystemLevelFormSet;
}
Link = GetFirstNode (&gBrowserFormSetList);
while (!IsNull (&gBrowserFormSetList, Link)) {
LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
if (CompareGuid (LocalFormSet->ClassGuid, &mScuFormSetGuid) && HasStorageElement(LocalFormSet)) {
return LocalFormSet;
}
Link = GetNextNode (&gBrowserFormSetList, Link);
}
return NULL;
}
/**
Formbrowser tranform page id to Form
@param [in] Private Formbrowser private data.
@param [in] PageId Formbrowser page identifer.
@retval EFI_SUCCESS Formbrowser tranform page id to Form success.
**/
FORM_BROWSER_FORM *
FBPageIdToForm (
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private,
IN H2O_PAGE_ID PageId
)
{
UINT32 Index;
FORM_BROWSER_FORMSET *FormSet;
FORM_BROWSER_FORM *Form;
LIST_ENTRY *LinkFormSet;
LIST_ENTRY *LinkForm;
Index = 0;
Form = NULL;
LinkFormSet = GetFirstNode (&Private->FormSetList);
while (!IsNull (&Private->FormSetList, LinkFormSet)) {
FormSet = FORM_BROWSER_FORMSET_FROM_DISPLAY_LINK (LinkFormSet);
LinkFormSet = GetNextNode (&Private->FormSetList, LinkFormSet);
LinkForm = GetFirstNode (&FormSet->FormListHead);
while (!IsNull (&FormSet->FormListHead, LinkForm)) {
Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);
LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);
if (Form->PageInfo.PageId == PageId) {
return Form;
}
}
}
return NULL;
}
/**
Formbrowser set question default value.
@param [in] Private Formbrowser private data
@param [in] QuestionDefault Question default structure
@param [in] PageId Specified page id
@param [in] QuestionId Specified question id
@param [in] HiiValue Specified default HII value
**/
STATIC
VOID
FBSetQuestionDefault (
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private,
IN H2O_FORM_BROWSER_QD *QuestionDefault,
IN H2O_PAGE_ID PageId,
IN EFI_QUESTION_ID QuestionId,
IN EFI_HII_VALUE *HiiValue
)
{
QuestionDefault->Signature = H2O_FORM_BROWSER_QUESTION_DEFAULT_SIGNATURE;
QuestionDefault->Size = sizeof (H2O_FORM_BROWSER_QD);
QuestionDefault->PageId = PageId;
QuestionDefault->QuestionId = QuestionId;
CopyHiiValue (&QuestionDefault->Value, HiiValue);
}
STATIC
VOID
InitSelection (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_FORM *Form,
IN FORM_BROWSER_STATEMENT *Statement OPTIONAL,
IN OUT UI_MENU_SELECTION *Selection
)
{
if (FormSet == NULL || Form == NULL || Selection == NULL) {
return;
}
ZeroMem (Selection, sizeof (UI_MENU_SELECTION));
Selection->Handle = FormSet->HiiHandle;
CopyGuid (&Selection->FormSetGuid, &FormSet->Guid);
Selection->FormId = Form->FormId;
Selection->QuestionId = (Statement != NULL)? Statement->QuestionId : 0;
Selection->Sequence = 0;
Selection->Action = UI_ACTION_NONE;
Selection->FormSet = FormSet;
Selection->Form = Form;
Selection->Statement = Statement;
Selection->FormEditable = TRUE;
Selection->CurrentMenu = NULL;
}
/**
Get page data according to specific page ID.
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[in] PageId Specific input page ID.
@param[out] PageInfo A pointer to point H2O_FORM_BROWSER_P instance.
@retval EFI_SUCCESS Get page data successful.
@retval EFI_INVALID_PARAMETER This is NULL, or PageInfo is NULL.
@retval EFI_NOT_FOUND Cannot find specific input page ID.
@retval EFI_OUT_OF_RESOURCES Could not allocate resources for page.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserGetPInfo (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN H2O_PAGE_ID PageId,
OUT H2O_FORM_BROWSER_P **PageInfo
)
{
H2O_FORM_BROWSER_PRIVATE_DATA *Private;
H2O_FORM_BROWSER_P *Page;
FORM_BROWSER_FORM *Form;
Private = H2O_FORM_BROWSER_DATA_FROM_PROTOCOL (This);
if (Private->FB.CurrentP != NULL && PageId == Private->FB.CurrentP->PageId) {
Page = Private->FB.CurrentP;
} else {
Form = FBPageIdToForm (Private, PageId);
if (Form == NULL) {
return EFI_NOT_FOUND;
}
Page = &Form->PageInfo;
DestroyPage (Page);
DestroyAllH2OStatements (Form);
InitPage (Private, Form->FormSet, Form, Page);
InitAllH2OStatements (Form);
}
*PageInfo = AllocateCopyPool (sizeof (H2O_FORM_BROWSER_P), Page);
if (*PageInfo == NULL) {
return EFI_OUT_OF_RESOURCES;
}
return EFI_SUCCESS;
}
/**
Get page Info by FormSet ID and Form ID
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[in] FormsetId Specific input FormSet Guid.
@param[in] FormsetId Specific input Form ID.
@param[out] PageInfo A pointer to point H2O_FORM_BROWSER_P instance.
@retval EFI_SUCCESS Get page data successful.
@retval EFI_INVALID_PARAMETER This is NULL, or PageInfo is NULL.
@retval EFI_NOT_FOUND Cannot find specific input page ID.
@retval EFI_OUT_OF_RESOURCES Could not allocate resources for page.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserGetPInfoByForm (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN EFI_GUID *FormsetId,
IN H2O_FORM_ID FormId,
OUT H2O_FORM_BROWSER_P **PageInfo
)
{
H2O_FORM_BROWSER_PRIVATE_DATA *Private;
FORM_BROWSER_FORMSET *FormSet;
FORM_BROWSER_FORM *Form;
H2O_FORM_BROWSER_P *Page;
EFI_HII_HANDLE HiiHandle;
UI_MENU_SELECTION Selection;
if (This == NULL || FormsetId == NULL || FormId == 0 || PageInfo == NULL) {
return EFI_INVALID_PARAMETER;
}
Private = H2O_FORM_BROWSER_DATA_FROM_PROTOCOL (This);
if (Private->FB.CurrentP != NULL &&
Private->FB.CurrentP->FormId == FormId &&
CompareGuid (&Private->FB.CurrentP->FormsetGuid, FormsetId)) {
Page = Private->FB.CurrentP;
} else {
FormSet = GetFormSetByFormSetGuid (FormsetId, &gBrowserFormSetList, NULL);
if (FormSet == NULL || FormSet != gCurrentSelection->FormSet) {
//
// Reload formset to make sure import opcode is updated.
//
HiiHandle = (FormSet == NULL) ? HiiGetHiiHandleByFormSetGuid (FormsetId) : FormSet->HiiHandle;
if (HiiHandle == NULL) {
return EFI_NOT_FOUND;
}
LoadHiiFormset (&HiiHandle, 1);
UpdatePageIdList (Private);
FormSet = GetFormSetByFormSetGuid (FormsetId, &gBrowserFormSetList, NULL);
if (FormSet == NULL) {
return EFI_NOT_FOUND;
}
Form = IdToForm (FormSet, FormId);
if (Form == NULL) {
return EFI_NOT_FOUND;
}
InitSelection (FormSet, Form, NULL, &Selection);
ProcessCallBackFunction (&Selection, FormSet, Form, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);
ProcessCallBackFunction (&Selection, FormSet, Form, NULL, EFI_BROWSER_ACTION_RETRIEVE , FALSE);
} else {
Form = IdToForm (FormSet, FormId);
if (Form == NULL) {
return EFI_NOT_FOUND;
}
}
Page = &Form->PageInfo;
DestroyPage (Page);
DestroyAllH2OStatements (Form);
InitPage (Private, FormSet, Form, Page);
InitAllH2OStatements (Form);
}
*PageInfo = AllocateCopyPool (sizeof (H2O_FORM_BROWSER_P), Page);
if (*PageInfo == NULL) {
return EFI_OUT_OF_RESOURCES;
}
return EFI_SUCCESS;
}
/**
Get all of page IDs
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[out] PageCount A pointer to the number of page ID in PageBuffer.
@param[out] PageBuffer A pointer to a buffer which will be allocated by the function which contains all
of H2O_PAGE_ID. The buffer should be freed by the caller.
@retval EFI_SUCCESS Get array of page IDs successful.
@retval EFI_NOT_FOUND No page IDs match the search.
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate PageIdBuffer.
@retval EFI_INVALID_PARAMETER This is NULL, PageIdCount is NULL or PageIdBuffer is NULL.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserGetPAll (
IN H2O_FORM_BROWSER_PROTOCOL *This,
OUT UINT32 *PageIdCount,
OUT H2O_PAGE_ID **PageIdBuffer
)
{
H2O_FORM_BROWSER_PRIVATE_DATA *Private;
H2O_PAGE_ID *Buffer;
Private = H2O_FORM_BROWSER_DATA_FROM_PROTOCOL (This);
if (Private->PageCount == 0) {
return EFI_NOT_FOUND;
}
Buffer = AllocateCopyPool (sizeof (H2O_PAGE_ID) * Private->PageCount, Private->PageIdList);
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
*PageIdCount = Private->PageCount;
*PageIdBuffer = Buffer;
return EFI_SUCCESS;
}
/**
Formbrowser get statement information.
@param [in] Private Formbrowser private data
@param [in] PageId Formbrowser page identifer
@param [in] StatementId Formbrowser statement identifier
@param [out] StatementData Formbrowser statement data
@retval EFI_SUCCESS Formbrowser get statement information success
@retval EFI_INVALID_PARAMETER Current page is not exist
@retval EFI_UNSUPPORTED Page id is not current page id.
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate statement data Buffer.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserGetSInfo (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN H2O_PAGE_ID PageId,
IN H2O_STATEMENT_ID StatementId,
OUT H2O_FORM_BROWSER_S **StatementData
)
{
H2O_FORM_BROWSER_PRIVATE_DATA *Private;
FORM_BROWSER_FORM *Form;
FORM_BROWSER_STATEMENT *Statement;
LIST_ENTRY *Link;
Private = H2O_FORM_BROWSER_DATA_FROM_PROTOCOL (This);
ASSERT (Private->FB.CurrentP != NULL);
if (Private->FB.CurrentP != NULL && PageId == Private->FB.CurrentP->PageId) {
Form = FORM_BROWSER_FORM_FROM_H2O_PAGE (Private->FB.CurrentP);
} else {
Form = FBPageIdToForm (Private, PageId);
if (Form == NULL) {
return EFI_NOT_FOUND;
}
}
Link = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, Link)) {
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
Link = GetNextNode (&Form->StatementListHead, Link);
if (Statement->StatementId == StatementId) {
*StatementData = AllocateCopyPool (sizeof (H2O_FORM_BROWSER_S), &Statement->Statement);
if (*StatementData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
/**
Get Question data according to Page identifier and Question identifier.
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[in] PageId Input Page identifier.
@param[in] QuestionId Input Question ID.
@param[out] QuestionData A pointer to H2O_FORM_BROWSER_Q instance.
@retval EFI_SUCCESS Get Question data successful.
@retval EFI_INVALID_PARAMETER This is NULL, QuestionData is NULL.
@retval EFI_NOT_FOUND Cannot find specific Question data.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserGetQInfo (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN H2O_PAGE_ID PageId,
IN EFI_QUESTION_ID QuestionId,
OUT H2O_FORM_BROWSER_Q **QuestionData
)
{
H2O_FORM_BROWSER_PRIVATE_DATA *Private;
FORM_BROWSER_FORM *Form;
FORM_BROWSER_STATEMENT *Statement;
LIST_ENTRY *Link;
Private = H2O_FORM_BROWSER_DATA_FROM_PROTOCOL (This);
ASSERT (Private->FB.CurrentP != NULL);
if (Private->FB.CurrentP != NULL && PageId == Private->FB.CurrentP->PageId) {
Form = FORM_BROWSER_FORM_FROM_H2O_PAGE(Private->FB.CurrentP);
} else {
Form = FBPageIdToForm (Private, PageId);
if (Form == NULL) {
return EFI_NOT_FOUND;
}
}
Link = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, Link)) {
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
Link = GetNextNode (&Form->StatementListHead, Link);
if (Statement->QuestionId == QuestionId) {
*QuestionData = AllocateCopyPool (sizeof (H2O_FORM_BROWSER_Q), &Statement->Statement);
if (*QuestionData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
/**
Get all of Question identifiers from specific Page.
@param[in] This Get array of Question identifiers successful.
@param[in] PageId Input Page identifier.
@param[out] QuestionIdCount A pointer to the number of Question ID in QuestionIdBuffer.
@param[out] QuestionIdBuffer A pointer to a buffer which will be allocated by the function which contains all
of Question IDs. The buffer should be freed by the caller.
@retval EFI_SUCCESS Get array of Question IDs successful.
@retval EFI_NOT_FOUND No Question ID match the search.
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate QuestionIdBuffer.
@retval EFI_INVALID_PARAMETER This is NULL, QuestionIdCount is NULL or QuestionIdBuffer is NULL.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserGetQAll (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN H2O_PAGE_ID PageId,
OUT UINT32 *QuestionIdCount,
OUT EFI_QUESTION_ID **QuestionIdBuffer
)
{
H2O_FORM_BROWSER_PRIVATE_DATA *Private;
FORM_BROWSER_FORM *Form;
FORM_BROWSER_STATEMENT *Statement;
LIST_ENTRY *LinkStatement;
UINT32 QuestionCount;
EFI_QUESTION_ID *QuestionIdPtr;
Private = H2O_FORM_BROWSER_DATA_FROM_PROTOCOL (This);
Form = FBPageIdToForm (Private, PageId);
if (Form == NULL) {
return EFI_NOT_FOUND;
}
QuestionCount = 0;
LinkStatement = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, LinkStatement)) {
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);
LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);
if (Statement->QuestionId != 0) {
QuestionCount++;
}
}
QuestionIdPtr = AllocatePool (sizeof (EFI_QUESTION_ID) * QuestionCount);
ASSERT (QuestionIdPtr != NULL);
if (QuestionIdPtr == NULL) {
return EFI_OUT_OF_RESOURCES;
}
*QuestionIdCount = QuestionCount;
*QuestionIdBuffer = QuestionIdPtr;
LinkStatement = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, LinkStatement)) {
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);
LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);
if (Statement->QuestionId != 0) {
*(QuestionIdPtr++) = Statement->QuestionId;
}
}
return EFI_SUCCESS;
}
/**
According to Page identifier and Question identifier to get all of types default values in this question.
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[in] PageId Input Page identifier.
@param[in] QuestionId Input Question ID.
@param[out] DefaultCount A pointer to the number of H2O_FORM_BROWSER_QD instance in DefaultBuffer.
@param[out] DefaultBuffer A pointer to a buffer which will be allocated by the function which contains all
of H2O_FORM_BROWSER_QD instances. The buffer should be freed by the caller.
@retval EFI_SUCCESS Get Question defaults successful.
@retval EFI_NOT_FOUND Cannot find default values from specific Question data.
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate DefaultBuffer.
@retval EFI_INVALID_PARAMETER This is NULL, DefaultCount is NULL or DefaultBuffer is NULL.
**/
EFI_STATUS
H2OFormBrowserGetQDefaults (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN H2O_PAGE_ID PageId,
IN EFI_QUESTION_ID QuestionId,
OUT UINT32 *DefaultCount,
OUT H2O_FORM_BROWSER_QD **DefaultBuffer
)
{
H2O_FORM_BROWSER_PRIVATE_DATA *Private;
FORM_BROWSER_FORM *Form;
FORM_BROWSER_STATEMENT *Statement;
EFI_HII_VALUE BackupQuestionValue;
UINTN Count;
EFI_STATUS Status;
H2O_FORM_BROWSER_QD *QuestionDefault;
ASSERT (DefaultBuffer != NULL);
if (QuestionId == 0) {
*DefaultCount = 0;
*DefaultBuffer = NULL;
return EFI_SUCCESS;
}
Private = H2O_FORM_BROWSER_DATA_FROM_PROTOCOL (This);
Form = FBPageIdToForm (Private, PageId);
if (Form == NULL) {
return EFI_NOT_FOUND;
}
Statement = IdToQuestion2 (Form, QuestionId);
if (Statement == NULL) {
return EFI_NOT_FOUND;
}
//#define EFI_HII_DEFAULT_CLASS_STANDARD 0x0000
//#define EFI_HII_DEFAULT_CLASS_MANUFACTURING 0x0001
//#define EFI_HII_DEFAULT_CLASS_SAFE 0x0002
CopyMem (&BackupQuestionValue, &Statement->HiiValue, sizeof (EFI_HII_VALUE));
Count = 0;
QuestionDefault = (H2O_FORM_BROWSER_QD*)AllocateZeroPool (sizeof (H2O_FORM_BROWSER_QD) * 3);
if (QuestionDefault == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = GetQuestionDefault (Form->FormSet, Form, Statement, EFI_HII_DEFAULT_CLASS_STANDARD);
if (!EFI_ERROR (Status)) {
FBSetQuestionDefault (Private, QuestionDefault + Count, PageId, QuestionId, &Statement->HiiValue);
Count++;
}
Status = GetQuestionDefault (Form->FormSet, Form, Statement, EFI_HII_DEFAULT_CLASS_MANUFACTURING);
if (!EFI_ERROR (Status)) {
FBSetQuestionDefault (Private, QuestionDefault + Count, PageId, QuestionId, &Statement->HiiValue);
Count++;;
}
Status = GetQuestionDefault (Form->FormSet, Form, Statement, EFI_HII_DEFAULT_CLASS_SAFE);
if (!EFI_ERROR (Status)) {
FBSetQuestionDefault (Private, QuestionDefault + Count, PageId, QuestionId, &Statement->HiiValue);
Count++;;
}
CopyMem (&Statement->HiiValue, &BackupQuestionValue, sizeof (EFI_HII_VALUE));
//
// default id some is count
//
if (Count != 0) {
*DefaultBuffer = QuestionDefault;
*DefaultCount = (UINT32) Count;
return EFI_SUCCESS;
}
*DefaultBuffer = NULL;
*DefaultCount = 0;
FreePool (QuestionDefault);
return EFI_NOT_FOUND;
}
/**
Get Variable Store data according to specific Variable Store ID.
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[in] PageId Input Page identifier.
@param[in] VarStoreId Specific input Variable Store ID.
@param[out] VarbleStoreData Pointer to H2O_FORM_BROWSER_VS instance.
@retval EFI_SUCCESS Get Variable Store successful.
@retval EFI_INVALID_PARAMETER This is NULL, or VariableStoreData is NULL.
@retval EFI_NOT_FOUND Cannot find specific Variable Store data.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserGetVSInfo (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN H2O_PAGE_ID PageId,
IN EFI_VARSTORE_ID VarStoreId,
OUT H2O_FORM_BROWSER_VS **VarbleStoreData
)
{
H2O_FORM_BROWSER_PRIVATE_DATA *Private;
FORM_BROWSER_FORM *Form;
FORM_BROWSER_FORMSET *FormSet;
LIST_ENTRY *LinkStorage;
FORMSET_STORAGE *Storage;
BROWSER_STORAGE *BrowserStorage;
H2O_FORM_BROWSER_VS *VarStoreData;
Private = H2O_FORM_BROWSER_DATA_FROM_PROTOCOL (This);
DEBUG ((EFI_D_INFO, "H2OFormBrowserGetVSInfo()\n"));
Form = FBPageIdToForm (Private, PageId);
if (Form == NULL) {
return EFI_NOT_FOUND;
}
DEBUG ((EFI_D_INFO, "Form->FormSet: %g\n", &Form->FormSet->Guid));
FormSet = Form->FormSet;
LinkStorage = GetFirstNode (&FormSet->StorageListHead);
while (!IsNull (&FormSet->StorageListHead, LinkStorage)) {
Storage = FORMSET_STORAGE_FROM_LINK (LinkStorage);
DEBUG ((EFI_D_INFO, "Storage->VarStoreId: %x\n", Storage->VarStoreId));
if (VarStoreId == Storage->VarStoreId) {
BrowserStorage = Storage->BrowserStorage;
VarStoreData = AllocateZeroPool (sizeof (H2O_FORM_BROWSER_VS));
if (VarStoreData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
VarStoreData->Signature = (UINT32)BrowserStorage->Signature;
VarStoreData->Size = sizeof (H2O_FORM_BROWSER_VS);
VarStoreData->PageId = PageId;
VarStoreData->Type = BrowserStorage->Type;
VarStoreData->VarStoreId = Storage->VarStoreId;
CopyMem (&VarStoreData->Guid, &BrowserStorage->Guid, sizeof(EFI_GUID));
VarStoreData->Name = BrowserStorage->Name;
VarStoreData->StorageSize = BrowserStorage->Size;
VarStoreData->Buffer = BrowserStorage->Buffer;
VarStoreData->EditBuffer = BrowserStorage->EditBuffer;
VarStoreData->Attributes = BrowserStorage->Attributes;
VarStoreData->ConfigHdr = BrowserStorage->ConfigHdr;
VarStoreData->ConfigRequest = BrowserStorage->ConfigRequest;
*VarbleStoreData = VarStoreData;
return EFI_SUCCESS;
}
LinkStorage = GetNextNode (&FormSet->StorageListHead, LinkStorage);
}
return EFI_NOT_FOUND;
}
/**
Get all of Variable Store identifiers from specific Page.
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[in] PageId Input Page identifier.
@param[out] VarStoreCount A pointer to the number of Variable Store ID in VarStoreBuffer.
@param[out] VarStoreBuffer A pointer to a buffer which will be allocated by the function which contains all
of EFI_VARSTORE_ID instances. The buffer should be freed by the caller.
@retval EFI_SUCCESS Get array of Variable Store IDs successful.
@retval EFI_NOT_FOUND No Variable Store ID match the search.
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate VarStoreBuffer.
@retval EFI_INVALID_PARAMETER This is NULL,, VarStoreCount is NULL or VarStoreBuffer is NULL.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserGetVSAll (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN H2O_PAGE_ID PageId,
OUT UINTN *VarStoreCount,
OUT EFI_VARSTORE_ID **VarStoreBuffer
)
{
H2O_FORM_BROWSER_PRIVATE_DATA *Private;
FORM_BROWSER_FORM *Form;
FORM_BROWSER_FORMSET *FormSet;
LIST_ENTRY *LinkStorage;
FORMSET_STORAGE *Storage;
UINTN StorageCount;
EFI_VARSTORE_ID *StorageIdPtr;
Private = H2O_FORM_BROWSER_DATA_FROM_PROTOCOL (This);
Form = FBPageIdToForm (Private, PageId);
if (Form == NULL) {
return EFI_NOT_FOUND;
}
FormSet = Form->FormSet;
StorageCount = 0;
LinkStorage = GetFirstNode (&FormSet->StorageListHead);
while (!IsNull (&FormSet->StorageListHead, LinkStorage)) {
Storage = FORMSET_STORAGE_FROM_LINK (LinkStorage);
StorageCount++;
LinkStorage = GetNextNode (&FormSet->StorageListHead, LinkStorage);
}
StorageIdPtr = AllocateZeroPool (sizeof(FORMSET_STORAGE) * StorageCount);
if (StorageIdPtr == NULL) {
return EFI_OUT_OF_RESOURCES;
}
*VarStoreCount = StorageCount;
*VarStoreBuffer = StorageIdPtr;
LinkStorage = GetFirstNode (&FormSet->StorageListHead);
while (!IsNull (&FormSet->StorageListHead, LinkStorage)) {
Storage = FORMSET_STORAGE_FROM_LINK (LinkStorage);
LinkStorage = GetNextNode (&FormSet->StorageListHead, LinkStorage);
*(StorageIdPtr++) = Storage->VarStoreId;
}
return EFI_SUCCESS;
}
/**
Get Default Store data according to specific Default Store identifier.
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[in] PageId Input Page identifier.
@param[in] DefaultStoreId Specific input Variable Store ID.
@param[out] DefaultStoreData A pointer to H2O_FORM_BROWSER_DS instance.
@retval EFI_SUCCESS Get Default Store successful.
@retval EFI_INVALID_PARAMETER This is NULL, or DefaultStoreData is NULL.
@retval EFI_NOT_FOUND Cannot find specific Default Store data.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserGetDSInfo (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN H2O_PAGE_ID PageId,
IN EFI_DEFAULT_ID DefaultStoreId,
OUT H2O_FORM_BROWSER_DS **DefaultStoreData
)
{
return EFI_SUCCESS;
}
/**
Get all of Default Store identifiers from specific Page.
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[in] PageId Input Page identifier.
@param[out] DefaultStoreIdCount A pointer to the number of Default Store ID in DefaultStoreIdBuffer.
@param[out] DefaultStoreIdBuffer A pointer to a buffer which will be allocated by the function which contains all
of EFI_DEFAULT_ID instances.
@retval EFI_SUCCESS Get array of Default Store IDs successful.
@retval EFI_NOT_FOUND No Default Store ID match the search.
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate DefaultStoreIdBuffer.
@retval EFI_INVALID_PARAMETER This is NULL, DefaultStoreIdCount is NULL or DefaultStoreIdBuffer is NULL.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserGetDSAll (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN H2O_PAGE_ID PageId,
OUT UINT32 *DefaultStoreIdCount,
OUT EFI_DEFAULT_ID **DefaultStoreIdBuffer
)
{
return EFI_SUCCESS;
}
/**
Add console device to supported list.
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[in] ConsoleDev A pointer to H2O_FORM_BROWSER_CONSOLE_DEV instance.
@retval EFI_SUCCESS Add console device to supported list successful.
@retval EFI_ALREADY_STARTED The console device is already in supported list.
@retval EFI_INVALID_PARAMETER This is NULL or CosoleDev is NULL.
**/
EFI_STATUS
H2OFormBrowserAddC (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN H2O_FORM_BROWSER_CONSOLE_DEV *ConsoleDev
)
{
return EFI_SUCCESS;
}
/**
Return information about all installed Consoles, the devices associated with them and
which Display Engine is currently managing them.
@param[in] This Pointer to current instance of this protocol.
@param[in] CId Unsigned integer that specifies the console index. -1 = all consoles.
@param[out] CDevCount Pointer to returned console device count.
@param[out] CDevs Pointer to returned pointer to array of console device descriptors.
The array should be freed by the caller. CDevCount indicates
the number of elements in the array.
@retval EFI_SUCCESS Get array of console devices successful.
@retval EFI_NOT_FOUND No consoleID match the search.
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate CDevs.
@retval EFI_INVALID_PARAMETER This is NULL, CDevCount is NULL or CDevs is NULL.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserGetCInfo (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN H2O_CONSOLE_ID CId,
OUT UINT32 *CDevCount,
OUT H2O_FORM_BROWSER_CONSOLE_DEV **CDevs
)
{
H2O_FORM_BROWSER_PRIVATE_DATA *Private;
H2O_FORM_BROWSER_CONSOLE_DEV *ConsoleDevList;
UINT32 Index;
UINT32 Count;
UINTN ConsoleDevIndex;
Private = H2O_FORM_BROWSER_DATA_FROM_PROTOCOL (This);
if (mConsoleDevList == NULL || mConsoleDevListCount == 0) {
return EFI_NOT_FOUND;
}
Count = 0;
for (Index = 0; Index < mConsoleDevListCount; Index++) {
if (CId == -1 || mConsoleDevList[Index]->ConsoleId == CId) {
Count++;
}
}
//
// the last console device is NULL
//
ConsoleDevIndex = 0;
ConsoleDevList = AllocateZeroPool ((Count + 1) * sizeof (H2O_FORM_BROWSER_CONSOLE_DEV));
if (ConsoleDevList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
for (Index = 0; Index < mConsoleDevListCount; Index++) {
if (CId == -1 || mConsoleDevList[Index]->ConsoleId == CId) {
CopyMem (
&ConsoleDevList[ConsoleDevIndex],
mConsoleDevList[Index],
sizeof (H2O_FORM_BROWSER_CONSOLE_DEV)
);
ConsoleDevIndex++;
}
}
*CDevCount = (UINT32) Count;
*CDevs = ConsoleDevList;
return EFI_SUCCESS;
}
/**
Return array of Console IDs.
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[out] CIdCount Pointer to returned console ID count.
@param[out] CIdBuffer Pointer to returned pointer to array of console ID. The array should be freed by
the caller. CIdCount indicates the number of elements in the array.
@retval EFI_SUCCESS Get array of console IDs successful.
@retval EFI_NOT_FOUND No console IDs ID match the search.
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate CIdBuffer.
@retval EFI_INVALID_PARAMETER This is NULL, CIdCount is NULL or CIdBuffer is NULL.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserGetCAll (
IN H2O_FORM_BROWSER_PROTOCOL *This,
OUT UINT32 *CIdCount,
OUT H2O_CONSOLE_ID **CIdBuffer
)
{
H2O_FORM_BROWSER_PRIVATE_DATA *Private;
UINT32 IdCount;
H2O_CONSOLE_ID *IdBuffer;
UINT32 Index;
if (This == NULL || CIdCount == NULL || CIdBuffer == NULL) {
return EFI_INVALID_PARAMETER;
}
Private = H2O_FORM_BROWSER_DATA_FROM_PROTOCOL (This);
if (Private->EngineListCount == 0) {
return EFI_NOT_FOUND;
}
IdCount = Private->EngineListCount;
IdBuffer = (H2O_CONSOLE_ID *) AllocatePool (sizeof (H2O_CONSOLE_ID) * IdCount);
if (IdBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
for (Index = 0; Index < IdCount; Index++) {
IdBuffer[Index] = Index + 1;
}
*CIdCount = IdCount;
*CIdBuffer = IdBuffer;
return EFI_SUCCESS;
}
/**
Return data about the Setup Menu.
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[out] SetupMenuData A pointer to returned setup menu data
@retval EFI_SUCCESS Get setup menu data successful.
@retval EFI_INVALID_PARAMETER This is NULL or SetupMenuData is NULL.
@retval EFI_NOT_FOUND Cannot find setup menu data.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserGetSMInfo (
IN H2O_FORM_BROWSER_PROTOCOL *This,
OUT H2O_FORM_BROWSER_SM **SetupMenuData
)
{
H2O_FORM_BROWSER_PRIVATE_DATA *Private;
H2O_FORM_BROWSER_SM *SetupMenu;
Private = H2O_FORM_BROWSER_DATA_FROM_PROTOCOL (This);
if (Private->SetupMenuInfo == NULL || Private->NumberOfSetupMenus == 0) {
return EFI_NOT_FOUND;
}
SetupMenu = (H2O_FORM_BROWSER_SM *) AllocateZeroPool (sizeof (H2O_FORM_BROWSER_SM));
if (SetupMenu == NULL) {
return EFI_OUT_OF_RESOURCES;
}
SetupMenu->Signature = H2O_FORMSET_BROWSER_SETUP_MENU_SIGNATURE;
if (GetScuFormset () != NULL) {
SetupMenu->CoreVersionString = GetString (STRING_TOKEN (SCU_CORE_VERSION_STRING), mHiiHandle);
SetupMenu->TitleString = GetString (STRING_TOKEN (SCU_TITLE_STRING) , mHiiHandle);
} else {
SetupMenu->CoreVersionString = NULL;
SetupMenu->TitleString = GetString (gCurrentSelection->FormSet->FormSetTitle, gCurrentSelection->FormSet->HiiHandle);
}
CopyGuid (&SetupMenu->FormSetGuid, &gCurrentSelection->FormSet->Guid);
SetupMenu->NumberOfSetupMenus = Private->NumberOfSetupMenus;
SetupMenu->SetupMenuInfoList = AllocateCopyPool (
sizeof (SETUP_MENU_INFO) * Private->NumberOfSetupMenus,
Private->SetupMenuInfo
);
if (SetupMenu->SetupMenuInfoList == NULL) {
FreePool (SetupMenu);
return EFI_OUT_OF_RESOURCES;
}
*SetupMenuData = SetupMenu;
return EFI_SUCCESS;
}
/**
Update setup menu data.
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[out] SetupMenuData A pointer to input setup menu data
@retval EFI_SUCCESS Update setup menu info successful.
@retval EFI_INVALID_PARAMETER This is NULL or SetupMenuData is NULL.
@retval EFI_UNSUPPORTED Cannot update setup menu data.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserUpdateSMInfo (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN H2O_FORM_BROWSER_SM *SetupMenuData
)
{
return EFI_SUCCESS;
}
/**
Add the notification to the notification queue and signal the Notification event.
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[in] Notify A pointer to the H2O_DISPLAY_ENGINE_EVT instance.
@retval EFI_SUCCESS Register notify successful.
@retval EFI_INVALID_PARAMETER This is NULL or Notify is NULL.
**/
EFI_STATUS
H2OFormBrowserNotify (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN CONST H2O_DISPLAY_ENGINE_EVT *Notify
)
{
QueueEvent ((H2O_DISPLAY_ENGINE_EVT *)Notify);
return EFI_SUCCESS;
}
/**
Add the notification to the notification queue and signal the notification event after
a period of time.
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[in] TriggerTime The number of 100ns units until the timer expires. A
TriggerTime of 0 is legal. If TriggerTime is 0, signal
event immediately.
@param[in] Notify A pointer to the H2O_DISPLAY_ENGINE_EVT instance.
@retval EFI_SUCCESS Register notify successful.
@retval EFI_INVALID_PARAMETER This is NULL or Notify is NULL.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserRegisterTimer (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN CONST H2O_DISPLAY_ENGINE_EVT *Notify,
IN UINT64 TriggerTime
)
{
EFI_STATUS Status;
if (This == NULL || Notify == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = FBSetTimer (
Notify->Target,
((H2O_DISPLAY_ENGINE_EVT_TIMER *) Notify)->TimerId,
H2O_FORM_BROWSER_TIMER_TYPE_RELATIVE,
Notify,
MultU64x32 (TriggerTime, 100)
);
return Status;
}
EFI_STATUS
EFIAPI
H2OFormBrowserGetVfrProp (
IN H2O_FORM_BROWSER_PROTOCOL *This,
IN OUT H2O_VFR_PROPERTY *VfrProperty
)
{
FORM_BROWSER_FORMSET *Formset;
FORM_BROWSER_FORMSET *TempFormset;
FORM_BROWSER_FORM *Form;
FORM_BROWSER_FORM *TempForm;
FORM_BROWSER_STATEMENT *Statement;
FORM_BROWSER_STATEMENT *TempStatement;
QUESTION_OPTION *Option;
QUESTION_OPTION *TempOption;
LIST_ENTRY *Link;
VfrProperty->FormsetPropList = NULL;
VfrProperty->FormPropList = NULL;
VfrProperty->StatementPropList = NULL;
VfrProperty->OptionPropList = NULL;
Formset = NULL;
Link = GetFirstNode (&gBrowserFormSetList);
while (!IsNull (&gBrowserFormSetList, Link)) {
TempFormset = FORM_BROWSER_FORMSET_FROM_LINK (Link);
Link = GetNextNode (&gBrowserFormSetList, Link);
if (CompareGuid (&TempFormset->Guid, &VfrProperty->FormsetGuid)) {
Formset = TempFormset;
break;
}
}
if (Formset != NULL) {
VfrProperty->FormsetPropList = &Formset->PropertyListHead;
} else {
return EFI_NOT_FOUND;
}
VfrProperty->HiiHandle = Formset->HiiHandle;
Form = NULL;
Link = GetFirstNode (&Formset->FormListHead);
while (!IsNull (&Formset->FormListHead, Link)) {
TempForm = FORM_BROWSER_FORM_FROM_LINK (Link);
Link = GetNextNode (&Formset->FormListHead, Link);
if (TempForm->FormId == (UINT16)VfrProperty->FormId) {
Form = TempForm;
break;
}
}
if (Form != NULL) {
VfrProperty->FormPropList = &Form->PropertyListHead;
} else {
return EFI_SUCCESS;
}
if (VfrProperty->StatementId == 0xFFFF) {
return EFI_SUCCESS;
}
Statement = NULL;
Link = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, Link)) {
TempStatement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
Link = GetNextNode (&Form->StatementListHead, Link);
if (TempStatement->StatementId == VfrProperty->StatementId) {
Statement = TempStatement;
break;
}
}
if (Statement != NULL) {
VfrProperty->StatementPropList = &Statement->PropertyListHead;
} else {
return EFI_SUCCESS;
}
Option = NULL;
Link = GetFirstNode (&Statement->OptionListHead);
while (!IsNull (&Statement->OptionListHead, Link)) {
TempOption = QUESTION_OPTION_FROM_LINK (Link);
Link = GetNextNode (&Statement->OptionListHead, Link);
if (TempOption->Value.Value.u64 == VfrProperty->OptionValue) {
Option = TempOption;
break;
}
}
if (Option != NULL) {
VfrProperty->OptionPropList = &Option->PropertyListHead;
}
return EFI_SUCCESS;
}
/**
Get changed Questions data buffer.
@param[in] This A pointer to the H2O_FORM_BROWSER_PROTOCOL instance.
@param[out] ChangedQuestionCount A pointer to the number of changed Questions in ChangedQuestionBuffer.
@param[out] ChangedQuestionBuffer A pointer to a buffer which will be allocated by the function which
contains all changed Questions.
@retval EFI_SUCCESS Get changed Questions successful.
@retval EFI_NOT_FOUND No changed Questions.
**/
EFI_STATUS
EFIAPI
H2OFormBrowserGetChangedQuestions (
IN H2O_FORM_BROWSER_PROTOCOL *This,
OUT UINT32 *ChangedQuestionCount,
OUT H2O_FORM_BROWSER_Q **ChangedQuestionBuffer
)
{
LIST_ENTRY *LinkFormSet;
LIST_ENTRY *LinkForm;
LIST_ENTRY *LinkStatement;
FORM_BROWSER_FORMSET *FormSet;
FORM_BROWSER_FORM *Form;
FORM_BROWSER_STATEMENT *Statement;
EXPRESS_RESULT ExpressResult;
H2O_FORM_BROWSER_P *Page;
UINT32 QuestionIndex;
UINT32 QuestionCount;
H2O_FORM_BROWSER_Q *QuestionBufPtr;
UpdateScuFormSetConfig ();
UpdateStatementStatus (NULL, NULL, SystemLevel);
QuestionCount = 0;
LinkFormSet = GetFirstNode (&gBrowserFormSetList);
while (!IsNull (&gBrowserFormSetList, LinkFormSet)) {
FormSet = FORM_BROWSER_FORMSET_FROM_LINK (LinkFormSet);
LinkForm = GetFirstNode (&FormSet->FormListHead);
while (!IsNull (&FormSet->FormListHead, LinkForm)) {
Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);
LinkStatement = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, LinkStatement)) {
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);
if (Statement->ValueChanged == TRUE &&
(Statement->ExtFlags & H2O_IFR_EXT_FLAG_SETUP_CHANGE_LIST_IGNORE) == 0) {
//
// Get the count of questions which has been changed.
//
QuestionCount++;
}
LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);
}
LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);
}
LinkFormSet = GetNextNode (&gBrowserFormSetList, LinkFormSet);
}
if (QuestionCount == 0) {
*ChangedQuestionCount = 0;
return EFI_SUCCESS;
}
QuestionBufPtr = NULL;
QuestionBufPtr = AllocateZeroPool (sizeof(H2O_FORM_BROWSER_Q) * QuestionCount);
if (QuestionBufPtr == NULL) {
return EFI_OUT_OF_RESOURCES;
}
QuestionIndex = 0;
LinkFormSet = GetFirstNode (&gBrowserFormSetList);
while (!IsNull (&gBrowserFormSetList, LinkFormSet)) {
FormSet = FORM_BROWSER_FORMSET_FROM_LINK (LinkFormSet);
LinkForm = GetFirstNode (&FormSet->FormListHead);
while (!IsNull (&FormSet->FormListHead, LinkForm)) {
Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);
LinkStatement = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, LinkStatement)) {
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);
if (Statement->ValueChanged == TRUE &&
(Statement->ExtFlags & H2O_IFR_EXT_FLAG_SETUP_CHANGE_LIST_IGNORE) == 0) {
//
// Initialize the H2O Statement content, and copy to the returned buffer.
//
ExpressResult = EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL);
Page = &Form->PageInfo;
InitH2OStatement (
FormSet,
Form,
ExpressResult,
Page,
Statement
);
CopyMem (&QuestionBufPtr[QuestionIndex], &Statement->Statement, sizeof(H2O_FORM_BROWSER_Q));
QuestionIndex++;
}
LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);
}
LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);
}
LinkFormSet = GetNextNode (&gBrowserFormSetList, LinkFormSet);
}
*ChangedQuestionCount = QuestionCount;
*ChangedQuestionBuffer = QuestionBufPtr;
return EFI_SUCCESS;
}
H2O_FORM_BROWSER_PRIVATE_DATA mFBPrivate = {
H2O_FORM_BROWSER_SIGNATURE,
NULL,
{
sizeof (H2O_FORM_BROWSER_PROTOCOL),
NULL,
NULL,
H2OFormBrowserGetPInfo,
H2OFormBrowserGetPAll,
H2OFormBrowserGetSInfo,
H2OFormBrowserGetQInfo,
H2OFormBrowserGetQAll,
H2OFormBrowserGetQDefaults,
H2OFormBrowserGetVSInfo,
H2OFormBrowserGetVSAll,
H2OFormBrowserGetDSInfo,
H2OFormBrowserGetDSAll,
H2OFormBrowserAddC,
H2OFormBrowserGetCInfo,
H2OFormBrowserGetCAll,
H2OFormBrowserGetSMInfo,
H2OFormBrowserUpdateSMInfo,
H2OFormBrowserNotify,
H2OFormBrowserRegisterTimer,
H2OFormBrowserGetVfrProp,
H2OFormBrowserGetChangedQuestions,
H2OFormBrowserGetPInfoByForm
},
{
SendForm,
BrowserCallback
},
{
SetScope,
RegisterHotKey,
RegiserExitHandler,
SaveReminder
},
{
BROWSER_EXTENSION2_VERSION_1,
SetScope,
RegisterHotKey,
RegiserExitHandler,
IsBrowserDataModified,
ExecuteAction,
}
};
/**
Driver entry point
@param[in] ImageHandle ImageHandle of the loaded driver.
@param[in] SystemTable Pointer to the EFI System Table.
@retval EFI_SUCCESS Destroy hotkey information success
**/
EFI_STATUS
EFIAPI
FBEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
//
// Locate required Hii relative protocols
//
Status = gBS->LocateProtocol (
&gEfiHiiDatabaseProtocolGuid,
NULL,
(VOID **) &gHiiDatabase
);
ASSERT_EFI_ERROR (Status);
Status = gBS->LocateProtocol (
&gEfiHiiConfigRoutingProtocolGuid,
NULL,
(VOID **) &gHiiConfigRouting
);
ASSERT_EFI_ERROR (Status);
Status = gBS->LocateProtocol (
&gEfiDevicePathFromTextProtocolGuid,
NULL,
(VOID **) &mPathFromText
);
ASSERT_EFI_ERROR (Status);
//
// Publish our HII data
//
mHiiHandle = HiiAddPackages (
&gEfiCallerIdGuid,
ImageHandle,
H2OFormBrowserDxeStrings,
NULL
);
ASSERT (mHiiHandle != NULL);
InitializeListHead (&mFBPrivate.FormSetList);
InitializeListHead (&mFBPrivate.TimerList);
InitializeListHead (&mFBPrivate.FormBrowserEx2.FormViewHistoryHead);
InitializeListHead (&mFBPrivate.FormBrowserEx2.OverrideQestListHead);
InitializeListHead (&mFBPrivate.TargetInfoList);
InitializeListHead (&mFBPrivate.NeedAddHiiHandleList);
Status = gBS->InstallMultipleProtocolInterfaces (
&mFBPrivate.ImageHandle,
&gEfiFormBrowser2ProtocolGuid,
&mFBPrivate.FormBrowser2,
&gH2OFormBrowserProtocolGuid,
&mFBPrivate.FB,
&gEdkiiFormBrowserEx2ProtocolGuid,
&mFBPrivate.FormBrowserEx2,
NULL
);
ASSERT_EFI_ERROR (Status);
InitializeDisplayFormData ();
Status = InstallH2ODialogProtocol (mFBPrivate.ImageHandle);
ASSERT_EFI_ERROR (Status);
Status = InstallHiiPopupProtocol (mFBPrivate.ImageHandle);
ASSERT_EFI_ERROR (Status);
return Status;
}
/**
Destroy hotkey information
@param[in] HotKeyInfoCount The count of hot key info
@param[in] HotKeyInfo Pointer to the hot key info
@retval EFI_SUCCESS Destroy hotkey information success
**/
EFI_STATUS
DestroyHotKeyInfo (
IN UINT32 HotKeyInfoCount,
IN HOT_KEY_INFO *HotKeyInfo
)
{
UINT32 Index;
if (HotKeyInfoCount == 0 || HotKeyInfo == NULL) {
return EFI_SUCCESS;
}
for (Index = 0; Index < HotKeyInfoCount; Index ++) {
FBFreePool ((VOID **)&HotKeyInfo[Index].Mark);
FBFreePool ((VOID **)&HotKeyInfo[Index].String);
if (HotKeyInfo[Index].ImageBuffer != NULL) {
FBFreePool ((VOID **)&HotKeyInfo[Index].ImageBuffer->Bitmap);
FBFreePool ((VOID **)&HotKeyInfo[Index].ImageBuffer);
}
}
FreePool (HotKeyInfo);
return EFI_SUCCESS;
}
EFI_STATUS
DestroyPageInfoByFormSet (
IN FORM_BROWSER_FORMSET *FormSet
)
{
FORM_BROWSER_FORM *Form;
LIST_ENTRY *LinkForm;
H2O_FORM_BROWSER_P *Page;
LinkForm = GetFirstNode (&FormSet->FormListHead);
while (!IsNull (&FormSet->FormListHead, LinkForm)) {
Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);
LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);
Page = &Form->PageInfo;
if (Page->Signature != H2O_FORM_PAGE_SIGNATURE) {
continue;
}
DestroyPage (Page);
DestroyAllH2OStatements (Form);
}
return EFI_SUCCESS;
}
/**
Destroy page information
@param [in] Private Formbrowser private data
@retval EFI_SUCCESS Destroy page information success
**/
EFI_STATUS
DestroyPageInfo (
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private
)
{
FORM_BROWSER_FORMSET *FormSet;
LIST_ENTRY *LinkFormSet;
LinkFormSet = GetFirstNode (&Private->FormSetList);
while (!IsNull (&Private->FormSetList, LinkFormSet)) {
FormSet = FORM_BROWSER_FORMSET_FROM_DISPLAY_LINK (LinkFormSet);
LinkFormSet = GetNextNode (&Private->FormSetList, LinkFormSet);
DestroyPageInfoByFormSet (FormSet);
}
FBFreePool ((VOID **) &Private->PageIdList);
DestroyHotKeyInfo (Private->NumberOfHotKeys, Private->HotKeyInfo);
Private->NumberOfHotKeys = 0;
Private->HotKeyInfo = NULL;
return EFI_SUCCESS;
}
/**
Destroy FormSet list
@param [in] Private Formbrowser private data
@retval EFI_SUCCESS Destroy FormSet list success
**/
EFI_STATUS
DestroyFormSetList (
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private
)
{
LIST_ENTRY *Link;
FORM_BROWSER_FORMSET *FormSet;
Link = GetFirstNode (&Private->FormSetList);
while (!IsNull (&Private->FormSetList, Link)) {
FormSet = FORM_BROWSER_FORMSET_FROM_DISPLAY_LINK (Link);
Link = GetNextNode (&Private->FormSetList, Link);
RemoveEntryList (&FormSet->Link);
DestroyFormSet (FormSet);
}
return EFI_SUCCESS;
}
/**
Destroy setup menu information
@param [in] Private Formbrowser private data
@retval EFI_SUCCESS Destroy setup menu information success
**/
EFI_STATUS
DestroySetupMenuInfo (
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private
)
{
UINT32 Index;
if (Private->NumberOfSetupMenus != 0 && Private->SetupMenuInfo != NULL) {
for (Index = 0; Index < (UINT32)Private->NumberOfSetupMenus; Index++) {
FBFreePool ((VOID **) &Private->SetupMenuInfo[Index].PageTitle);
if (Private->SetupMenuInfo[Index].PageImage != NULL) {
FreePool (Private->SetupMenuInfo[Index].PageImage->Bitmap);
FreePool (Private->SetupMenuInfo[Index].PageImage);
}
}
}
FBFreePool ((VOID **)&Private->SetupMenuInfo);
Private->NumberOfSetupMenus = 0;
return EFI_SUCCESS;
}
/**
Initialize the HII String Token to the correct values.
**/
VOID
InitializeBrowserStrings (
VOID
)
{
FreeBrowserStrings ();
gPressEnter = GetString (STRING_TOKEN (PRESS_ENTER), mHiiHandle);
gEmptyString = GetString (STRING_TOKEN (EMPTY_STRING), mHiiHandle);
gAreYouSure = GetString (STRING_TOKEN (ARE_YOU_SURE), mHiiHandle);
gYesResponse = GetString (STRING_TOKEN (ARE_YOU_SURE_YES), mHiiHandle);
gNoResponse = GetString (STRING_TOKEN (ARE_YOU_SURE_NO), mHiiHandle);
gSaveChanges = GetString (STRING_TOKEN (SAVE_CHANGES), mHiiHandle);
gSpaceString = GetString (STRING_TOKEN (STR_SPACE), mHiiHandle);
gSaveFailed = GetString (STRING_TOKEN (SAVE_FAILED), mHiiHandle);
gFormNotFound = GetString (STRING_TOKEN (STATUS_BROWSER_FORM_NOT_FOUND), mHiiHandle);
gFormSuppress = GetString (STRING_TOKEN (FORM_SUPPRESSED), mHiiHandle);
gProtocolNotFound = GetString (STRING_TOKEN (PROTOCOL_NOT_FOUND), mHiiHandle);
gBrowserError = GetString (STRING_TOKEN (STATUS_BROWSER_ERROR), mHiiHandle);
}
/**
Free up the resource allocated for all strings required
by Setup Browser.
**/
VOID
FreeBrowserStrings (
VOID
)
{
FBFreePool ((VOID **)&gPressEnter);
FBFreePool ((VOID **)&gEmptyString);
FBFreePool ((VOID **)&gAreYouSure);
FBFreePool ((VOID **)&gYesResponse);
FBFreePool ((VOID **)&gNoResponse);
FBFreePool ((VOID **)&gSaveChanges);
FBFreePool ((VOID **)&gSpaceString);
FBFreePool ((VOID **)&gSaveFailed);
FBFreePool ((VOID **)&gFormNotFound);
FBFreePool ((VOID **)&gFormSuppress);
FBFreePool ((VOID **)&gProtocolNotFound);
FBFreePool ((VOID **)&gBrowserError);
}