/** @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 #include 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); }