/** @file\r
Entry and initialization module for the browser.\r
\r
-Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2020 - 2022 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
{\r
SendForm,\r
BrowserCallback\r
+ },\r
+ {\r
+ SetScope,\r
+ RegisterHotKey,\r
+ RegiserExitHandler,\r
+ SaveReminder\r
+ },\r
+ {\r
+ BROWSER_EXTENSION2_VERSION_1_1,\r
+ SetScope,\r
+ RegisterHotKey,\r
+ RegiserExitHandler,\r
+ IsBrowserDataModified,\r
+ ExecuteAction,\r
+ { NULL, NULL },\r
+ { NULL, NULL },\r
+ IsResetRequired\r
}\r
};\r
\r
-EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;\r
-EFI_HII_STRING_PROTOCOL *mHiiString;\r
-EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;\r
-\r
-UINTN gBrowserContextCount = 0;\r
-LIST_ENTRY gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList);\r
-\r
-BANNER_DATA *gBannerData;\r
-EFI_HII_HANDLE gFrontPageHandle;\r
-UINTN gClassOfVfr;\r
-UINTN gFunctionKeySetting;\r
-BOOLEAN gResetRequired;\r
-EFI_HII_HANDLE gHiiHandle;\r
-UINT16 gDirection;\r
-EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
+EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;\r
+EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;\r
+EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mPathFromText;\r
+EDKII_FORM_DISPLAY_ENGINE_PROTOCOL *mFormDisplay;\r
+\r
+UINTN gBrowserContextCount = 0;\r
+LIST_ENTRY gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList);\r
+LIST_ENTRY gBrowserFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList);\r
+LIST_ENTRY gBrowserHotKeyList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList);\r
+LIST_ENTRY gBrowserStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList);\r
+LIST_ENTRY gBrowserSaveFailFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserSaveFailFormSetList);\r
+\r
+BOOLEAN mSystemSubmit = FALSE;\r
+BOOLEAN gResetRequiredFormLevel;\r
+BOOLEAN gResetRequiredSystemLevel = FALSE;\r
+BOOLEAN gExitRequired;\r
+BOOLEAN gFlagReconnect;\r
+BOOLEAN gCallbackReconnect;\r
+BROWSER_SETTING_SCOPE gBrowserSettingScope = FormSetLevel;\r
+BOOLEAN mBrowserScopeFirstSet = TRUE;\r
+EXIT_HANDLER ExitHandlerFunction = NULL;\r
+FORM_BROWSER_FORMSET *mSystemLevelFormSet;\r
\r
//\r
// Browser Global Strings\r
//\r
-CHAR16 *gFunctionNineString;\r
-CHAR16 *gFunctionTenString;\r
-CHAR16 *gEnterString;\r
-CHAR16 *gEnterCommitString;\r
-CHAR16 *gEnterEscapeString;\r
-CHAR16 *gEscapeString;\r
-CHAR16 *gSaveFailed;\r
-CHAR16 *gMoveHighlight;\r
-CHAR16 *gMakeSelection;\r
-CHAR16 *gDecNumericInput;\r
-CHAR16 *gHexNumericInput;\r
-CHAR16 *gToggleCheckBox;\r
-CHAR16 *gPromptForData;\r
-CHAR16 *gPromptForPassword;\r
-CHAR16 *gPromptForNewPassword;\r
-CHAR16 *gConfirmPassword;\r
-CHAR16 *gConfirmError;\r
-CHAR16 *gPassowordInvalid;\r
-CHAR16 *gPressEnter;\r
-CHAR16 *gEmptyString;\r
-CHAR16 *gAreYouSure;\r
-CHAR16 *gYesResponse;\r
-CHAR16 *gNoResponse;\r
-CHAR16 *gMiniString;\r
-CHAR16 *gPlusString;\r
-CHAR16 *gMinusString;\r
-CHAR16 *gAdjustNumber;\r
-CHAR16 *gSaveChanges;\r
-CHAR16 *gOptionMismatch;\r
-CHAR16 *gFormSuppress;\r
-\r
-CHAR16 *mUnknownString = L"!";\r
-\r
-CHAR16 gPromptBlockWidth;\r
-CHAR16 gOptionBlockWidth;\r
-CHAR16 gHelpBlockWidth;\r
-\r
-EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
-EFI_GUID gSetupBrowserGuid = {\r
- 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}\r
-};\r
+CHAR16 *gEmptyString;\r
+CHAR16 *mUnknownString = L"!";\r
+\r
+extern EFI_GUID mCurrentFormSetGuid;\r
+extern EFI_HII_HANDLE mCurrentHiiHandle;\r
+extern UINT16 mCurrentFormId;\r
+extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData;\r
+\r
+/**\r
+ Create a menu with specified formset GUID and form ID, and add it as a child\r
+ of the given parent menu.\r
+\r
+ @param HiiHandle Hii handle related to this formset.\r
+ @param FormSetGuid The Formset Guid of menu to be added.\r
+ @param FormId The Form ID of menu to be added.\r
+ @param QuestionId The question id of this menu to be added.\r
+\r
+ @return A pointer to the newly added menu or NULL if memory is insufficient.\r
+\r
+**/\r
+FORM_ENTRY_INFO *\r
+UiAddMenuList (\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN EFI_GUID *FormSetGuid,\r
+ IN UINT16 FormId,\r
+ IN UINT16 QuestionId\r
+ )\r
+{\r
+ FORM_ENTRY_INFO *MenuList;\r
+\r
+ MenuList = AllocateZeroPool (sizeof (FORM_ENTRY_INFO));\r
+ if (MenuList == NULL) {\r
+ return NULL;\r
+ }\r
\r
-FORM_BROWSER_FORMSET *gOldFormSet;\r
+ MenuList->Signature = FORM_ENTRY_INFO_SIGNATURE;\r
+\r
+ MenuList->HiiHandle = HiiHandle;\r
+ CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
+ MenuList->FormId = FormId;\r
+ MenuList->QuestionId = QuestionId;\r
\r
-FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {\r
//\r
- // Boot Manager\r
+ // If parent is not specified, it is the root Form of a Formset\r
//\r
- {\r
- {\r
- 0x847bc3fe,\r
- 0xb974,\r
- 0x446d,\r
- {\r
- 0x94,\r
- 0x49,\r
- 0x5a,\r
- 0xd5,\r
- 0x41,\r
- 0x2e,\r
- 0x99,\r
- 0x3b\r
- }\r
- },\r
- NONE_FUNCTION_KEY_SETTING\r
- },\r
+ InsertTailList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
+\r
+ return MenuList;\r
+}\r
+\r
+/**\r
+ Return the form id for the input hiihandle and formset.\r
+\r
+ @param HiiHandle HiiHandle for FormSet.\r
+ @param FormSetGuid The Formset GUID of the menu to search.\r
+\r
+ @return First form's id for this form set.\r
+\r
+**/\r
+EFI_FORM_ID\r
+GetFirstFormId (\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN EFI_GUID *FormSetGuid\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORM *Form;\r
+\r
+ Link = GetFirstNode (&gCurrentSelection->FormSet->FormListHead);\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+ return Form->FormId;\r
+}\r
+\r
+/**\r
+ Search Menu with given FormSetGuid and FormId in all cached menu list.\r
+\r
+ @param HiiHandle HiiHandle for FormSet.\r
+ @param FormSetGuid The Formset GUID of the menu to search.\r
+ @param FormId The Form ID of menu to search.\r
+\r
+ @return A pointer to menu found or NULL if not found.\r
+\r
+**/\r
+FORM_ENTRY_INFO *\r
+UiFindMenuList (\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN EFI_GUID *FormSetGuid,\r
+ IN UINT16 FormId\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_ENTRY_INFO *MenuList;\r
+ FORM_ENTRY_INFO *RetMenu;\r
+ EFI_FORM_ID FirstFormId;\r
+\r
+ RetMenu = NULL;\r
+\r
+ Link = GetFirstNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
+ while (!IsNull (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link)) {\r
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (Link);\r
+ Link = GetNextNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link);\r
+\r
+ //\r
+ // If already find the menu, free the menus behind it.\r
+ //\r
+ if (RetMenu != NULL) {\r
+ RemoveEntryList (&MenuList->Link);\r
+ FreePool (MenuList);\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Find the same FromSet.\r
+ //\r
+ if (MenuList->HiiHandle == HiiHandle) {\r
+ if (IsZeroGuid (&MenuList->FormSetGuid)) {\r
+ //\r
+ // FormSetGuid is not specified.\r
+ //\r
+ RetMenu = MenuList;\r
+ } else if (CompareGuid (&MenuList->FormSetGuid, FormSetGuid)) {\r
+ if (MenuList->FormId == FormId) {\r
+ RetMenu = MenuList;\r
+ } else if ((FormId == 0) || (MenuList->FormId == 0)) {\r
+ FirstFormId = GetFirstFormId (HiiHandle, FormSetGuid);\r
+ if (((FormId == 0) && (FirstFormId == MenuList->FormId)) || ((MenuList->FormId == 0) && (FirstFormId == FormId))) {\r
+ RetMenu = MenuList;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return RetMenu;\r
+}\r
+\r
+/**\r
+ Find parent menu for current menu.\r
+\r
+ @param CurrentMenu Current Menu\r
+ @param SettingLevel Whether find parent menu in Form Level or Formset level.\r
+ In form level, just find the parent menu;\r
+ In formset level, find the parent menu which has different\r
+ formset guid value.\r
+\r
+ @retval The parent menu for current menu.\r
+**/\r
+FORM_ENTRY_INFO *\r
+UiFindParentMenu (\r
+ IN FORM_ENTRY_INFO *CurrentMenu,\r
+ IN BROWSER_SETTING_SCOPE SettingLevel\r
+ )\r
+{\r
+ FORM_ENTRY_INFO *ParentMenu;\r
+ LIST_ENTRY *Link;\r
+\r
+ ASSERT (SettingLevel == FormLevel || SettingLevel == FormSetLevel);\r
+\r
+ if (CurrentMenu == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ ParentMenu = NULL;\r
+ Link = &CurrentMenu->Link;\r
+\r
+ while (Link->BackLink != &mPrivateData.FormBrowserEx2.FormViewHistoryHead) {\r
+ ParentMenu = FORM_ENTRY_INFO_FROM_LINK (Link->BackLink);\r
+\r
+ if (SettingLevel == FormLevel) {\r
+ //\r
+ // For FormLevel, just find the parent menu, return.\r
+ //\r
+ break;\r
+ }\r
+\r
+ if (!CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
+ //\r
+ // For SystemLevel, must find the menu which has different formset.\r
+ //\r
+ break;\r
+ }\r
+\r
+ Link = Link->BackLink;\r
+ }\r
+\r
//\r
- // Device Manager\r
+ // Not find the parent menu, just return NULL.\r
//\r
- {\r
- {\r
- 0x3ebfa8e6,\r
- 0x511d,\r
- 0x4b5b,\r
- {\r
- 0xa9,\r
- 0x5f,\r
- 0xfb,\r
- 0x38,\r
- 0x26,\r
- 0xf,\r
- 0x1c,\r
- 0x27\r
- }\r
- },\r
- NONE_FUNCTION_KEY_SETTING\r
- },\r
+ if (Link->BackLink == &mPrivateData.FormBrowserEx2.FormViewHistoryHead) {\r
+ return NULL;\r
+ }\r
+\r
+ return ParentMenu;\r
+}\r
+\r
+/**\r
+ Free Menu list linked list.\r
+\r
+ @param MenuListHead One Menu list point in the menu list.\r
+\r
+**/\r
+VOID\r
+UiFreeMenuList (\r
+ LIST_ENTRY *MenuListHead\r
+ )\r
+{\r
+ FORM_ENTRY_INFO *MenuList;\r
+\r
+ while (!IsListEmpty (MenuListHead)) {\r
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (MenuListHead->ForwardLink);\r
+ RemoveEntryList (&MenuList->Link);\r
+\r
+ FreePool (MenuList);\r
+ }\r
+}\r
+\r
+/**\r
+ Copy current Menu list to the new menu list.\r
+\r
+ @param NewMenuListHead New create Menu list.\r
+ @param CurrentMenuListHead Current Menu list.\r
+\r
+**/\r
+VOID\r
+UiCopyMenuList (\r
+ OUT LIST_ENTRY *NewMenuListHead,\r
+ IN LIST_ENTRY *CurrentMenuListHead\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_ENTRY_INFO *MenuList;\r
+ FORM_ENTRY_INFO *NewMenuEntry;\r
+\r
//\r
- // BMM FormSet.\r
+ // If new menu list not empty, free it first.\r
//\r
- {\r
- {\r
- 0x642237c7,\r
- 0x35d4,\r
- 0x472d,\r
- {\r
- 0x83,\r
- 0x65,\r
- 0x12,\r
- 0xe0,\r
- 0xcc,\r
- 0xf2,\r
- 0x7a,\r
- 0x22\r
- }\r
- },\r
- NONE_FUNCTION_KEY_SETTING\r
- },\r
+ UiFreeMenuList (NewMenuListHead);\r
+\r
+ Link = GetFirstNode (CurrentMenuListHead);\r
+ while (!IsNull (CurrentMenuListHead, Link)) {\r
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (Link);\r
+ Link = GetNextNode (CurrentMenuListHead, Link);\r
+\r
+ NewMenuEntry = AllocateZeroPool (sizeof (FORM_ENTRY_INFO));\r
+ ASSERT (NewMenuEntry != NULL);\r
+ NewMenuEntry->Signature = FORM_ENTRY_INFO_SIGNATURE;\r
+ NewMenuEntry->HiiHandle = MenuList->HiiHandle;\r
+ CopyMem (&NewMenuEntry->FormSetGuid, &MenuList->FormSetGuid, sizeof (EFI_GUID));\r
+ NewMenuEntry->FormId = MenuList->FormId;\r
+ NewMenuEntry->QuestionId = MenuList->QuestionId;\r
+\r
+ InsertTailList (NewMenuListHead, &NewMenuEntry->Link);\r
+ }\r
+}\r
+\r
+/**\r
+ Load all hii formset to the browser.\r
+\r
+**/\r
+VOID\r
+LoadAllHiiFormset (\r
+ VOID\r
+ )\r
+{\r
+ FORM_BROWSER_FORMSET *LocalFormSet;\r
+ EFI_HII_HANDLE *HiiHandles;\r
+ UINTN Index;\r
+ EFI_GUID ZeroGuid;\r
+ EFI_STATUS Status;\r
+ FORM_BROWSER_FORMSET *OldFormset;\r
+\r
+ OldFormset = mSystemLevelFormSet;\r
+\r
//\r
- // BMM File Explorer FormSet.\r
+ // Get all the Hii handles\r
//\r
- {\r
- {\r
- 0x1f2d63e1,\r
- 0xfebd,\r
- 0x4dc7,\r
- {\r
- 0x9c,\r
- 0xc5,\r
- 0xba,\r
- 0x2b,\r
- 0x1c,\r
- 0xef,\r
- 0x9c,\r
- 0x5b\r
- }\r
- },\r
- NONE_FUNCTION_KEY_SETTING\r
- },\r
-};\r
+ HiiHandles = HiiGetHiiHandles (NULL);\r
+ ASSERT (HiiHandles != NULL);\r
+\r
+ //\r
+ // Search for formset of each class type\r
+ //\r
+ for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
+ //\r
+ // Check HiiHandles[Index] does exist in global maintain list.\r
+ //\r
+ if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Initilize FormSet Setting\r
+ //\r
+ LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
+ ASSERT (LocalFormSet != NULL);\r
+ mSystemLevelFormSet = LocalFormSet;\r
+\r
+ ZeroMem (&ZeroGuid, sizeof (ZeroGuid));\r
+ Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet);\r
+ if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) {\r
+ DestroyFormSet (LocalFormSet);\r
+ continue;\r
+ }\r
+\r
+ InitializeCurrentSetting (LocalFormSet);\r
+\r
+ //\r
+ // Initilize Questions' Value\r
+ //\r
+ Status = LoadFormSetConfig (NULL, LocalFormSet);\r
+ if (EFI_ERROR (Status)) {\r
+ DestroyFormSet (LocalFormSet);\r
+ continue;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Free resources, and restore gOldFormSet and gClassOfVfr\r
+ //\r
+ FreePool (HiiHandles);\r
+\r
+ mSystemLevelFormSet = OldFormset;\r
+}\r
+\r
+/**\r
+ Pop up the error info.\r
+\r
+ @param BrowserStatus The input browser status.\r
+ @param HiiHandle The Hiihandle for this opcode.\r
+ @param OpCode The opcode use to get the erro info and timeout value.\r
+ @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.\r
+\r
+**/\r
+UINT32\r
+PopupErrorMessage (\r
+ IN UINT32 BrowserStatus,\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN EFI_IFR_OP_HEADER *OpCode OPTIONAL,\r
+ IN CHAR16 *ErrorString\r
+ )\r
+{\r
+ FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
+ USER_INPUT UserInputData;\r
+\r
+ Statement = NULL;\r
+\r
+ if (OpCode != NULL) {\r
+ Statement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));\r
+ ASSERT (Statement != NULL);\r
+ Statement->OpCode = OpCode;\r
+ gDisplayFormData.HighLightedStatement = Statement;\r
+ }\r
+\r
+ //\r
+ // Used to compatible with old display engine.\r
+ // New display engine not use this field.\r
+ //\r
+ gDisplayFormData.ErrorString = ErrorString;\r
+ gDisplayFormData.BrowserStatus = BrowserStatus;\r
+\r
+ if (HiiHandle != NULL) {\r
+ gDisplayFormData.HiiHandle = HiiHandle;\r
+ }\r
+\r
+ mFormDisplay->FormDisplay (&gDisplayFormData, &UserInputData);\r
+\r
+ gDisplayFormData.BrowserStatus = BROWSER_SUCCESS;\r
+ gDisplayFormData.ErrorString = NULL;\r
+\r
+ if (OpCode != NULL) {\r
+ FreePool (Statement);\r
+ }\r
+\r
+ return UserInputData.Action;\r
+}\r
\r
/**\r
This is the routine which an external caller uses to direct the browser\r
EFI_STATUS\r
EFIAPI\r
SendForm (\r
- IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
- IN EFI_HII_HANDLE *Handles,\r
- IN UINTN HandleCount,\r
- IN EFI_GUID *FormSetGuid, OPTIONAL\r
- IN UINT16 FormId, OPTIONAL\r
- IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL\r
- OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL\r
+ IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE *Handles,\r
+ IN UINTN HandleCount,\r
+ IN EFI_GUID *FormSetGuid OPTIONAL,\r
+ IN UINT16 FormId OPTIONAL,\r
+ IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions OPTIONAL,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL\r
)\r
{\r
- EFI_STATUS Status;\r
- UI_MENU_SELECTION *Selection;\r
- UINTN Index;\r
- FORM_BROWSER_FORMSET *FormSet;\r
-\r
- //\r
- // Save globals used by SendForm()\r
- //\r
- SaveBrowserContext ();\r
-\r
- Status = EFI_SUCCESS;\r
- ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+ EFI_STATUS Status;\r
+ UI_MENU_SELECTION *Selection;\r
+ UINTN Index;\r
+ FORM_BROWSER_FORMSET *FormSet;\r
+ FORM_ENTRY_INFO *MenuList;\r
+ BOOLEAN RetVal;\r
\r
//\r
- // Seed the dimensions in the global\r
+ // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.\r
//\r
- gST->ConOut->QueryMode (\r
- gST->ConOut,\r
- gST->ConOut->Mode->Mode,\r
- &gScreenDimensions.RightColumn,\r
- &gScreenDimensions.BottomRow\r
- );\r
-\r
- if (ScreenDimensions != NULL) {\r
- //\r
- // Check local dimension vs. global dimension.\r
- //\r
- if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||\r
- (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)\r
- ) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
- } else {\r
- //\r
- // Local dimension validation.\r
- //\r
- if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&\r
- (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&\r
- ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&\r
- (\r
- (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +\r
- SCROLL_ARROW_HEIGHT *\r
- 2 +\r
- FRONT_PAGE_HEADER_HEIGHT +\r
- FOOTER_HEIGHT +\r
- 1\r
- )\r
- ) {\r
- CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
- } else {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
- }\r
- }\r
+ if (mFormDisplay == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "Fatal Error! EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found!"));\r
+ return EFI_UNSUPPORTED;\r
}\r
\r
- gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);\r
- gPromptBlockWidth = (CHAR16) (gOptionBlockWidth + LEFT_SKIPPED_COLUMNS);\r
- gHelpBlockWidth = (CHAR16) (gOptionBlockWidth - LEFT_SKIPPED_COLUMNS);\r
-\r
//\r
- // Initialize the strings for the browser, upon exit of the browser, the strings will be freed\r
+ // Save globals used by SendForm()\r
//\r
- InitializeBrowserStrings ();\r
-\r
- gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;\r
+ SaveBrowserContext ();\r
\r
- //\r
- // Ensure we are in Text mode\r
- //\r
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gFlagReconnect = FALSE;\r
+ gResetRequiredFormLevel = FALSE;\r
+ gExitRequired = FALSE;\r
+ gCallbackReconnect = FALSE;\r
+ Status = EFI_SUCCESS;\r
+ gEmptyString = L"";\r
+ gDisplayFormData.ScreenDimensions = (EFI_SCREEN_DESCRIPTOR *)ScreenDimensions;\r
\r
for (Index = 0; Index < HandleCount; Index++) {\r
Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));\r
if (FormSetGuid != NULL) {\r
CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
Selection->FormId = FormId;\r
+ } else {\r
+ CopyMem (&Selection->FormSetGuid, &gEfiHiiPlatformSetupFormsetGuid, sizeof (EFI_GUID));\r
}\r
\r
- gOldFormSet = NULL;\r
-\r
do {\r
FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
ASSERT (FormSet != NULL);\r
\r
+ //\r
+ // Validate the HiiHandle\r
+ // if validate failed, find the first validate parent HiiHandle.\r
+ //\r
+ if (!ValidateHiiHandle (Selection->Handle)) {\r
+ FindNextMenu (Selection, FormSetLevel);\r
+ }\r
+\r
//\r
// Initialize internal data structures of FormSet\r
//\r
DestroyFormSet (FormSet);\r
break;\r
}\r
- Selection->FormSet = FormSet;\r
+\r
+ Selection->FormSet = FormSet;\r
+ mSystemLevelFormSet = FormSet;\r
\r
//\r
// Display this formset\r
\r
Status = SetupBrowser (Selection);\r
\r
- gCurrentSelection = NULL;\r
+ gCurrentSelection = NULL;\r
+ mSystemLevelFormSet = NULL;\r
+\r
+ //\r
+ // Check incoming formset whether is same with previous. If yes, that means action is not exiting of formset so do not reconnect controller.\r
+ //\r
+ if ((gFlagReconnect || gCallbackReconnect) && !CompareGuid (&FormSet->Guid, &Selection->FormSetGuid)) {\r
+ RetVal = ReconnectController (FormSet->DriverHandle);\r
+ if (!RetVal) {\r
+ PopupErrorMessage (BROWSER_RECONNECT_FAIL, NULL, NULL, NULL);\r
+ }\r
+\r
+ gFlagReconnect = FALSE;\r
+ gCallbackReconnect = FALSE;\r
+ }\r
+\r
+ //\r
+ // If no data is changed, don't need to save current FormSet into the maintain list.\r
+ //\r
+ if (!IsNvUpdateRequiredForFormSet (FormSet)) {\r
+ CleanBrowserStorage (FormSet);\r
+ RemoveEntryList (&FormSet->Link);\r
+ DestroyFormSet (FormSet);\r
+ }\r
\r
if (EFI_ERROR (Status)) {\r
break;\r
}\r
-\r
} while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
\r
- if (gOldFormSet != NULL) {\r
- DestroyFormSet (gOldFormSet);\r
- gOldFormSet = NULL;\r
- }\r
-\r
FreePool (Selection);\r
}\r
\r
if (ActionRequest != NULL) {\r
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
- if (gResetRequired) {\r
+ if (gResetRequiredFormLevel) {\r
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
}\r
}\r
\r
- FreeBrowserStrings ();\r
+ mFormDisplay->ExitDisplay ();\r
\r
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
- gST->ConOut->ClearScreen (gST->ConOut);\r
+ //\r
+ // Clear the menu history data.\r
+ //\r
+ while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
+ RemoveEntryList (&MenuList->Link);\r
+ FreePool (MenuList);\r
+ }\r
\r
-Done:\r
//\r
// Restore globals used by SendForm()\r
//\r
return Status;\r
}\r
\r
-\r
/**\r
- This function is called by a callback handler to retrieve uncommitted state\r
- data from the browser.\r
+ Get or set data to the storage.\r
\r
- @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
- instance.\r
- @param ResultsDataSize A pointer to the size of the buffer associated\r
- with ResultsData.\r
+ @param ResultsDataSize The size of the buffer associatedwith ResultsData.\r
@param ResultsData A string returned from an IFR browser or\r
equivalent. The results string will have no\r
routing information in them.\r
browser state information or set (if RetrieveData\r
= FALSE) data in the uncommitted browser state\r
information.\r
- @param VariableGuid An optional field to indicate the target variable\r
- GUID name to use.\r
- @param VariableName An optional field to indicate the target\r
- human-readable variable name.\r
+ @param Storage The pointer to the storage.\r
\r
@retval EFI_SUCCESS The results have been distributed or are awaiting\r
distribution.\r
- @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to\r
- contain the results data.\r
\r
**/\r
EFI_STATUS\r
-EFIAPI\r
-BrowserCallback (\r
- IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
- IN OUT UINTN *ResultsDataSize,\r
+ProcessStorage (\r
+ IN OUT UINTN *ResultsDataSize,\r
+ IN OUT EFI_STRING *ResultsData,\r
+ IN BOOLEAN RetrieveData,\r
+ IN BROWSER_STORAGE *Storage\r
+ )\r
+{\r
+ CHAR16 *ConfigResp;\r
+ EFI_STATUS Status;\r
+ CHAR16 *StrPtr;\r
+ UINTN BufferSize;\r
+ UINTN TmpSize;\r
+ UINTN MaxLen;\r
+ FORMSET_STORAGE *BrowserStorage;\r
+\r
+ if (RetrieveData) {\r
+ //\r
+ // Generate <ConfigResp>\r
+ //\r
+ Status = StorageToConfigResp (Storage, &ConfigResp, Storage->ConfigRequest, TRUE);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.\r
+ // Also need to consider add "\0" at first time.\r
+ //\r
+ StrPtr = StrStr (ConfigResp, L"PATH");\r
+ ASSERT (StrPtr != NULL);\r
+ StrPtr = StrStr (StrPtr, L"&");\r
+ StrPtr += 1;\r
+ BufferSize = StrSize (StrPtr);\r
+\r
+ //\r
+ // Copy the data if the input buffer is bigger enough.\r
+ //\r
+ if (*ResultsDataSize >= BufferSize) {\r
+ StrCpyS (*ResultsData, *ResultsDataSize / sizeof (CHAR16), StrPtr);\r
+ }\r
+\r
+ *ResultsDataSize = BufferSize;\r
+ FreePool (ConfigResp);\r
+ } else {\r
+ //\r
+ // Prepare <ConfigResp>\r
+ //\r
+ BrowserStorage = GetFstStgFromBrsStg (Storage);\r
+ ASSERT (BrowserStorage != NULL);\r
+ TmpSize = StrLen (*ResultsData);\r
+ BufferSize = (TmpSize + StrLen (BrowserStorage->ConfigHdr) + 2) * sizeof (CHAR16);\r
+ MaxLen = BufferSize / sizeof (CHAR16);\r
+ ConfigResp = AllocateZeroPool (BufferSize);\r
+ ASSERT (ConfigResp != NULL);\r
+\r
+ StrCpyS (ConfigResp, MaxLen, BrowserStorage->ConfigHdr);\r
+ StrCatS (ConfigResp, MaxLen, L"&");\r
+ StrCatS (ConfigResp, MaxLen, *ResultsData);\r
+\r
+ //\r
+ // Update Browser uncommited data\r
+ //\r
+ Status = ConfigRespToStorage (Storage, ConfigResp);\r
+ FreePool (ConfigResp);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This routine called this service in the browser to retrieve or set certain uncommitted\r
+ state information that resides in the open formsets.\r
+\r
+ @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
+ instance.\r
+ @param ResultsDataSize A pointer to the size of the buffer associated\r
+ with ResultsData.\r
+ @param ResultsData A string returned from an IFR browser or\r
+ equivalent. The results string will have no\r
+ routing information in them.\r
+ @param RetrieveData A BOOLEAN field which allows an agent to retrieve\r
+ (if RetrieveData = TRUE) data from the uncommitted\r
+ browser state information or set (if RetrieveData\r
+ = FALSE) data in the uncommitted browser state\r
+ information.\r
+ @param VariableGuid An optional field to indicate the target variable\r
+ GUID name to use.\r
+ @param VariableName An optional field to indicate the target\r
+ human-readable variable name.\r
+\r
+ @retval EFI_SUCCESS The results have been distributed or are awaiting\r
+ distribution.\r
+ @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to\r
+ contain the results data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BrowserCallback (\r
+ IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
+ IN OUT UINTN *ResultsDataSize,\r
IN OUT EFI_STRING ResultsData,\r
IN BOOLEAN RetrieveData,\r
- IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
+ IN CONST EFI_GUID *VariableGuid OPTIONAL,\r
IN CONST CHAR16 *VariableName OPTIONAL\r
)\r
{\r
- EFI_STATUS Status;\r
- LIST_ENTRY *Link;\r
- FORMSET_STORAGE *Storage;\r
- FORM_BROWSER_FORMSET *FormSet;\r
- BOOLEAN Found;\r
- CHAR16 *ConfigResp;\r
- CHAR16 *StrPtr;\r
- UINTN BufferSize;\r
- UINTN TmpSize;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ BROWSER_STORAGE *Storage;\r
+ FORMSET_STORAGE *FormsetStorage;\r
+ UINTN TotalSize;\r
+ BOOLEAN Found;\r
\r
- if (ResultsDataSize == NULL || ResultsData == NULL) {\r
+ if ((ResultsDataSize == NULL) || (ResultsData == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (gCurrentSelection == NULL) {\r
- return EFI_NOT_READY;\r
- }\r
-\r
- Storage = NULL;\r
- ConfigResp = NULL;\r
- FormSet = gCurrentSelection->FormSet;\r
-\r
- //\r
- // Find target storage\r
- //\r
- Link = GetFirstNode (&FormSet->StorageListHead);\r
- if (IsNull (&FormSet->StorageListHead, Link)) {\r
- return EFI_UNSUPPORTED;\r
- }\r
+ TotalSize = *ResultsDataSize;\r
+ Storage = NULL;\r
+ Found = FALSE;\r
+ Status = EFI_SUCCESS;\r
\r
if (VariableGuid != NULL) {\r
//\r
- // Try to find target storage\r
+ // Try to find target storage in the current formset.\r
//\r
- Found = FALSE;\r
- while (!IsNull (&FormSet->StorageListHead, Link)) {\r
- Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
- Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+ Link = GetFirstNode (&gBrowserStorageList);\r
+ while (!IsNull (&gBrowserStorageList, Link)) {\r
+ Storage = BROWSER_STORAGE_FROM_LINK (Link);\r
+ Link = GetNextNode (&gBrowserStorageList, Link);\r
+ //\r
+ // Check the current storage.\r
+ //\r
+ if (!CompareGuid (&Storage->Guid, (EFI_GUID *)VariableGuid)) {\r
+ continue;\r
+ }\r
\r
- if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {\r
- if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||\r
- Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
- //\r
- // Buffer storage require both GUID and Name\r
- //\r
- if (VariableName == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
+ if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+ {\r
+ //\r
+ // Buffer storage require both GUID and Name\r
+ //\r
+ if (VariableName == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
\r
- if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {\r
- continue;\r
- }\r
+ if (StrCmp (Storage->Name, (CHAR16 *)VariableName) != 0) {\r
+ continue;\r
}\r
- Found = TRUE;\r
- break;\r
}\r
+\r
+ if ((Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||\r
+ (Storage->Type == EFI_HII_VARSTORE_BUFFER))\r
+ {\r
+ if ((mSystemLevelFormSet == NULL) || (mSystemLevelFormSet->HiiHandle == NULL)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (Storage->HiiHandle != mSystemLevelFormSet->HiiHandle) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, Storage);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+ ConfigRequestAdjust (Storage, ResultsData, TRUE);\r
+ }\r
+\r
+ //\r
+ // Different formsets may have same varstore, so here just set the flag\r
+ // not exit the circle.\r
+ //\r
+ Found = TRUE;\r
+ break;\r
}\r
\r
if (!Found) {\r
//\r
// GUID/Name is not specified, take the first storage in FormSet\r
//\r
- Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
- }\r
-\r
- if (RetrieveData) {\r
- //\r
- // Skip if there is no RequestElement\r
- //\r
- if (Storage->ElementCount == 0) {\r
- return EFI_SUCCESS;\r
+ if (mSystemLevelFormSet == NULL) {\r
+ return EFI_NOT_READY;\r
}\r
\r
//\r
// Generate <ConfigResp>\r
//\r
- Status = StorageToConfigResp (Storage, &ConfigResp, FALSE);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ Link = GetFirstNode (&mSystemLevelFormSet->StorageListHead);\r
+ if (IsNull (&mSystemLevelFormSet->StorageListHead, Link)) {\r
+ return EFI_UNSUPPORTED;\r
}\r
\r
- //\r
- // Skip <ConfigHdr> and '&' to point to <ConfigBody>\r
- //\r
- StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;\r
-\r
- BufferSize = StrSize (StrPtr);\r
- if (*ResultsDataSize < BufferSize) {\r
- *ResultsDataSize = BufferSize;\r
+ FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
\r
- FreePool (ConfigResp);\r
- return EFI_BUFFER_TOO_SMALL;\r
+ Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, FormsetStorage->BrowserStorage);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
+ }\r
\r
- *ResultsDataSize = BufferSize;\r
- CopyMem (ResultsData, StrPtr, BufferSize);\r
+ if (RetrieveData) {\r
+ Status = TotalSize <= *ResultsDataSize ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;\r
+ *ResultsDataSize = TotalSize;\r
+ }\r
\r
- FreePool (ConfigResp);\r
- } else {\r
- //\r
- // Prepare <ConfigResp>\r
- //\r
- TmpSize = StrLen (ResultsData);\r
- BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);\r
- ConfigResp = AllocateZeroPool (BufferSize);\r
- ASSERT (ConfigResp != NULL);\r
+ return Status;\r
+}\r
\r
- StrCpy (ConfigResp, Storage->ConfigHdr);\r
- StrCat (ConfigResp, L"&");\r
- StrCat (ConfigResp, ResultsData);\r
+/**\r
+ Callback function for SimpleTextInEx protocol install events\r
\r
- //\r
- // Update Browser uncommited data\r
- //\r
- Status = ConfigRespToStorage (Storage, ConfigResp);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ @param Event the event that is signaled.\r
+ @param Context not used here.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+FormDisplayCallback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ if (mFormDisplay != NULL) {\r
+ return;\r
}\r
\r
- return EFI_SUCCESS;\r
+ gBS->LocateProtocol (\r
+ &gEdkiiFormDisplayEngineProtocolGuid,\r
+ NULL,\r
+ (VOID **)&mFormDisplay\r
+ );\r
}\r
\r
-\r
/**\r
Initialize Setup Browser driver.\r
\r
EFI_STATUS\r
EFIAPI\r
InitializeSetup (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ VOID *Registration;\r
\r
//\r
// Locate required Hii relative protocols\r
Status = gBS->LocateProtocol (\r
&gEfiHiiDatabaseProtocolGuid,\r
NULL,\r
- (VOID **) &mHiiDatabase\r
+ (VOID **)&mHiiDatabase\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
Status = gBS->LocateProtocol (\r
- &gEfiHiiStringProtocolGuid,\r
+ &gEfiHiiConfigRoutingProtocolGuid,\r
NULL,\r
- (VOID **) &mHiiString\r
+ (VOID **)&mHiiConfigRouting\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
Status = gBS->LocateProtocol (\r
- &gEfiHiiConfigRoutingProtocolGuid,\r
+ &gEfiDevicePathFromTextProtocolGuid,\r
NULL,\r
- (VOID **) &mHiiConfigRouting\r
+ (VOID **)&mPathFromText\r
);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Publish our HII data\r
- //\r
- gHiiHandle = HiiAddPackages (\r
- &gSetupBrowserGuid,\r
- ImageHandle,\r
- SetupBrowserStrings,\r
- NULL\r
- );\r
- ASSERT (gHiiHandle != NULL);\r
\r
//\r
- // Initialize Driver private data\r
+ // Install FormBrowser2 protocol\r
//\r
- gBannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
- ASSERT (gBannerData != NULL);\r
+ mPrivateData.Handle = NULL;\r
+ Status = gBS->InstallProtocolInterface (\r
+ &mPrivateData.Handle,\r
+ &gEfiFormBrowser2ProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &mPrivateData.FormBrowser2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
\r
//\r
- // Install FormBrowser2 protocol\r
+ // Install FormBrowserEx2 protocol\r
//\r
+ InitializeListHead (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
+ InitializeListHead (&mPrivateData.FormBrowserEx2.OverrideQestListHead);\r
mPrivateData.Handle = NULL;\r
+ Status = gBS->InstallProtocolInterface (\r
+ &mPrivateData.Handle,\r
+ &gEdkiiFormBrowserEx2ProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &mPrivateData.FormBrowserEx2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
Status = gBS->InstallProtocolInterface (\r
&mPrivateData.Handle,\r
- &gEfiFormBrowser2ProtocolGuid,\r
+ &gEdkiiFormBrowserExProtocolGuid,\r
EFI_NATIVE_INTERFACE,\r
- &mPrivateData.FormBrowser2\r
+ &mPrivateData.FormBrowserEx\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- return Status;\r
-}\r
+ InitializeDisplayFormData ();\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEdkiiFormDisplayEngineProtocolGuid,\r
+ NULL,\r
+ (VOID **)&mFormDisplay\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ EfiCreateProtocolNotifyEvent (\r
+ &gEdkiiFormDisplayEngineProtocolGuid,\r
+ TPL_CALLBACK,\r
+ FormDisplayCallback,\r
+ NULL,\r
+ &Registration\r
+ );\r
+ }\r
\r
+ return EFI_SUCCESS;\r
+}\r
\r
/**\r
Create a new string in HII Package List.\r
**/\r
EFI_STRING_ID\r
NewString (\r
- IN CHAR16 *String,\r
- IN EFI_HII_HANDLE HiiHandle\r
+ IN CHAR16 *String,\r
+ IN EFI_HII_HANDLE HiiHandle\r
)\r
{\r
EFI_STRING_ID StringId;\r
return StringId;\r
}\r
\r
-\r
/**\r
Delete a string from HII Package List.\r
\r
**/\r
EFI_STATUS\r
DeleteString (\r
- IN EFI_STRING_ID StringId,\r
- IN EFI_HII_HANDLE HiiHandle\r
+ IN EFI_STRING_ID StringId,\r
+ IN EFI_HII_HANDLE HiiHandle\r
)\r
{\r
CHAR16 NullChar;\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
Get the string based on the StringId and HII Package List Handle.\r
\r
**/\r
CHAR16 *\r
GetToken (\r
- IN EFI_STRING_ID Token,\r
- IN EFI_HII_HANDLE HiiHandle\r
+ IN EFI_STRING_ID Token,\r
+ IN EFI_HII_HANDLE HiiHandle\r
)\r
{\r
EFI_STRING String;\r
\r
String = HiiGetString (HiiHandle, Token, NULL);\r
if (String == NULL) {\r
- String = AllocateCopyPool (sizeof (mUnknownString), mUnknownString);\r
+ String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);\r
ASSERT (String != NULL);\r
}\r
- return (CHAR16 *) String;\r
-}\r
\r
+ return (CHAR16 *)String;\r
+}\r
\r
/**\r
Allocate new memory and then copy the Unicode string Source to Destination.\r
**/\r
VOID\r
NewStringCpy (\r
- IN OUT CHAR16 **Dest,\r
- IN CHAR16 *Src\r
+ IN OUT CHAR16 **Dest,\r
+ IN CHAR16 *Src\r
)\r
{\r
if (*Dest != NULL) {\r
FreePool (*Dest);\r
}\r
+\r
*Dest = AllocateCopyPool (StrSize (Src), Src);\r
ASSERT (*Dest != NULL);\r
}\r
\r
-\r
/**\r
Allocate new memory and concatinate Source on the end of Destination.\r
\r
**/\r
VOID\r
NewStringCat (\r
- IN OUT CHAR16 **Dest,\r
- IN CHAR16 *Src\r
+ IN OUT CHAR16 **Dest,\r
+ IN CHAR16 *Src\r
)\r
{\r
CHAR16 *NewString;\r
- UINTN TmpSize;\r
+ UINTN MaxLen;\r
\r
if (*Dest == NULL) {\r
NewStringCpy (Dest, Src);\r
return;\r
}\r
\r
- TmpSize = StrSize (*Dest);\r
- NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);\r
+ MaxLen = (StrSize (*Dest) + StrSize (Src) - 1) / sizeof (CHAR16);\r
+ NewString = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
ASSERT (NewString != NULL);\r
\r
- StrCpy (NewString, *Dest);\r
- StrCat (NewString, Src);\r
+ StrCpyS (NewString, MaxLen, *Dest);\r
+ StrCatS (NewString, MaxLen, Src);\r
\r
FreePool (*Dest);\r
*Dest = NewString;\r
}\r
\r
-\r
-/**\r
- Synchronize or restore Storage's Edit copy and Shadow copy.\r
-\r
- @param Storage The Storage to be synchronized.\r
- @param SyncOrRestore Sync the buffer to editbuffer or Restore the \r
- editbuffer to buffer\r
- if TRUE, copy the editbuffer to the buffer.\r
- if FALSE, copy the buffer to the editbuffer.\r
-\r
-**/\r
-VOID\r
-SynchronizeStorage (\r
- IN FORMSET_STORAGE *Storage,\r
- IN BOOLEAN SyncOrRestore\r
- )\r
-{\r
- LIST_ENTRY *Link;\r
- NAME_VALUE_NODE *Node;\r
-\r
- switch (Storage->Type) {\r
- case EFI_HII_VARSTORE_BUFFER:\r
- case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
- if (SyncOrRestore) {\r
- CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);\r
- } else {\r
- CopyMem (Storage->EditBuffer, Storage->Buffer, Storage->Size);\r
- }\r
- break;\r
-\r
- case EFI_HII_VARSTORE_NAME_VALUE:\r
- Link = GetFirstNode (&Storage->NameValueListHead);\r
- while (!IsNull (&Storage->NameValueListHead, Link)) {\r
- Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
-\r
- if (SyncOrRestore) {\r
- NewStringCpy (&Node->Value, Node->EditValue);\r
- } else {\r
- NewStringCpy (&Node->EditValue, Node->Value);\r
- }\r
-\r
- Link = GetNextNode (&Storage->NameValueListHead, Link);\r
- }\r
- break;\r
-\r
- case EFI_HII_VARSTORE_EFI_VARIABLE:\r
- default:\r
- break;\r
- }\r
-}\r
-\r
-\r
/**\r
Get Value for given Name from a NameValue Storage.\r
\r
@param Storage The NameValue Storage.\r
@param Name The Name.\r
@param Value The retured Value.\r
+ @param GetValueFrom Where to get source value, from EditValue or Value.\r
\r
@retval EFI_SUCCESS Value found for given Name.\r
@retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
**/\r
EFI_STATUS\r
GetValueByName (\r
- IN FORMSET_STORAGE *Storage,\r
- IN CHAR16 *Name,\r
- IN OUT CHAR16 **Value\r
+ IN BROWSER_STORAGE *Storage,\r
+ IN CHAR16 *Name,\r
+ IN OUT CHAR16 **Value,\r
+ IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
)\r
{\r
- LIST_ENTRY *Link;\r
- NAME_VALUE_NODE *Node;\r
+ LIST_ENTRY *Link;\r
+ NAME_VALUE_NODE *Node;\r
+\r
+ if ((GetValueFrom != GetSetValueWithEditBuffer) && (GetValueFrom != GetSetValueWithBuffer)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
*Value = NULL;\r
\r
Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
\r
if (StrCmp (Name, Node->Name) == 0) {\r
- NewStringCpy (Value, Node->EditValue);\r
+ if (GetValueFrom == GetSetValueWithEditBuffer) {\r
+ NewStringCpy (Value, Node->EditValue);\r
+ } else {\r
+ NewStringCpy (Value, Node->Value);\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r
\r
return EFI_NOT_FOUND;\r
}\r
\r
-\r
/**\r
Set Value of given Name in a NameValue Storage.\r
\r
@param Storage The NameValue Storage.\r
@param Name The Name.\r
@param Value The Value to set.\r
- @param Edit Whether update editValue or Value.\r
+ @param SetValueTo Whether update editValue or Value.\r
+ @param ReturnNode The node use the input name.\r
\r
@retval EFI_SUCCESS Value found for given Name.\r
@retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
**/\r
EFI_STATUS\r
SetValueByName (\r
- IN FORMSET_STORAGE *Storage,\r
- IN CHAR16 *Name,\r
- IN CHAR16 *Value,\r
- IN BOOLEAN Edit\r
+ IN BROWSER_STORAGE *Storage,\r
+ IN CHAR16 *Name,\r
+ IN CHAR16 *Value,\r
+ IN GET_SET_QUESTION_VALUE_WITH SetValueTo,\r
+ OUT NAME_VALUE_NODE **ReturnNode\r
)\r
{\r
- LIST_ENTRY *Link;\r
- NAME_VALUE_NODE *Node;\r
- CHAR16 *Buffer;\r
+ LIST_ENTRY *Link;\r
+ NAME_VALUE_NODE *Node;\r
+ CHAR16 *Buffer;\r
+\r
+ if ((SetValueTo != GetSetValueWithEditBuffer) && (SetValueTo != GetSetValueWithBuffer)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
Link = GetFirstNode (&Storage->NameValueListHead);\r
while (!IsNull (&Storage->NameValueListHead, Link)) {\r
Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
\r
if (StrCmp (Name, Node->Name) == 0) {\r
- if (Edit) {\r
+ if (SetValueTo == GetSetValueWithEditBuffer) {\r
Buffer = Node->EditValue;\r
} else {\r
Buffer = Node->Value;\r
}\r
+\r
if (Buffer != NULL) {\r
FreePool (Buffer);\r
}\r
+\r
Buffer = AllocateCopyPool (StrSize (Value), Value);\r
ASSERT (Buffer != NULL);\r
- if (Edit) {\r
+ if (SetValueTo == GetSetValueWithEditBuffer) {\r
Node->EditValue = Buffer;\r
} else {\r
Node->Value = Buffer;\r
}\r
+\r
+ if (ReturnNode != NULL) {\r
+ *ReturnNode = Node;\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r
\r
return EFI_NOT_FOUND;\r
}\r
\r
-\r
/**\r
Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
\r
- @param Buffer The Storage to be conveted.\r
+ @param Storage The Storage to be conveted.\r
@param ConfigResp The returned <ConfigResp>.\r
- @param SingleForm Whether update data for single form or formset level.\r
+ @param ConfigRequest The ConfigRequest string.\r
+ @param GetEditBuf Get the data from editbuffer or buffer.\r
\r
@retval EFI_SUCCESS Convert success.\r
@retval EFI_INVALID_PARAMETER Incorrect storage type.\r
**/\r
EFI_STATUS\r
StorageToConfigResp (\r
- IN VOID *Buffer,\r
- IN CHAR16 **ConfigResp,\r
- IN BOOLEAN SingleForm\r
+ IN BROWSER_STORAGE *Storage,\r
+ IN CHAR16 **ConfigResp,\r
+ IN CHAR16 *ConfigRequest,\r
+ IN BOOLEAN GetEditBuf\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_STRING Progress;\r
- LIST_ENTRY *Link;\r
- NAME_VALUE_NODE *Node;\r
- CHAR16 *ConfigRequest;\r
- FORMSET_STORAGE *Storage;\r
- FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
+ EFI_STATUS Status;\r
+ EFI_STRING Progress;\r
+ LIST_ENTRY *Link;\r
+ NAME_VALUE_NODE *Node;\r
+ UINT8 *SourceBuf;\r
+ FORMSET_STORAGE *FormsetStorage;\r
\r
Status = EFI_SUCCESS;\r
- if (SingleForm) {\r
- ConfigInfo = (FORM_BROWSER_CONFIG_REQUEST *) Buffer;\r
- Storage = ConfigInfo->Storage;\r
- ConfigRequest = ConfigInfo->ConfigRequest;\r
- } else {\r
- Storage = (FORMSET_STORAGE *) Buffer;\r
- ConfigRequest = Storage->ConfigRequest;\r
- }\r
\r
switch (Storage->Type) {\r
- case EFI_HII_VARSTORE_BUFFER:\r
- case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
- Status = mHiiConfigRouting->BlockToConfig (\r
- mHiiConfigRouting,\r
- ConfigRequest,\r
- Storage->EditBuffer,\r
- Storage->Size,\r
- ConfigResp,\r
- &Progress\r
- );\r
- break;\r
-\r
- case EFI_HII_VARSTORE_NAME_VALUE:\r
- *ConfigResp = NULL;\r
- NewStringCat (ConfigResp, Storage->ConfigHdr);\r
+ case EFI_HII_VARSTORE_BUFFER:\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+ SourceBuf = GetEditBuf ? Storage->EditBuffer : Storage->Buffer;\r
+ Status = mHiiConfigRouting->BlockToConfig (\r
+ mHiiConfigRouting,\r
+ ConfigRequest,\r
+ SourceBuf,\r
+ Storage->Size,\r
+ ConfigResp,\r
+ &Progress\r
+ );\r
+ break;\r
\r
- Link = GetFirstNode (&Storage->NameValueListHead);\r
- while (!IsNull (&Storage->NameValueListHead, Link)) {\r
- Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+ case EFI_HII_VARSTORE_NAME_VALUE:\r
+ *ConfigResp = NULL;\r
+ FormsetStorage = GetFstStgFromBrsStg (Storage);\r
+ ASSERT (FormsetStorage != NULL);\r
+ NewStringCat (ConfigResp, FormsetStorage->ConfigHdr);\r
+\r
+ Link = GetFirstNode (&Storage->NameValueListHead);\r
+ while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+ if (StrStr (ConfigRequest, Node->Name) != NULL) {\r
+ NewStringCat (ConfigResp, L"&");\r
+ NewStringCat (ConfigResp, Node->Name);\r
+ NewStringCat (ConfigResp, L"=");\r
+ if (GetEditBuf) {\r
+ NewStringCat (ConfigResp, Node->EditValue);\r
+ } else {\r
+ NewStringCat (ConfigResp, Node->Value);\r
+ }\r
+ }\r
\r
- if (StrStr (ConfigRequest, Node->Name) != NULL) {\r
- NewStringCat (ConfigResp, L"&");\r
- NewStringCat (ConfigResp, Node->Name);\r
- NewStringCat (ConfigResp, L"=");\r
- NewStringCat (ConfigResp, Node->EditValue);\r
+ Link = GetNextNode (&Storage->NameValueListHead, Link);\r
}\r
- Link = GetNextNode (&Storage->NameValueListHead, Link);\r
- }\r
- break;\r
\r
- case EFI_HII_VARSTORE_EFI_VARIABLE:\r
- default:\r
- Status = EFI_INVALID_PARAMETER;\r
- break;\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
}\r
\r
return Status;\r
}\r
\r
-\r
/**\r
Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
\r
**/\r
EFI_STATUS\r
ConfigRespToStorage (\r
- IN FORMSET_STORAGE *Storage,\r
- IN CHAR16 *ConfigResp\r
+ IN BROWSER_STORAGE *Storage,\r
+ IN CHAR16 *ConfigResp\r
)\r
{\r
EFI_STATUS Status;\r
Status = EFI_SUCCESS;\r
\r
switch (Storage->Type) {\r
- case EFI_HII_VARSTORE_BUFFER:\r
- case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
- BufferSize = Storage->Size;\r
- Status = mHiiConfigRouting->ConfigToBlock (\r
- mHiiConfigRouting,\r
- ConfigResp,\r
- Storage->EditBuffer,\r
- &BufferSize,\r
- &Progress\r
- );\r
- break;\r
-\r
- case EFI_HII_VARSTORE_NAME_VALUE:\r
- StrPtr = StrStr (ConfigResp, L"PATH");\r
- if (StrPtr == NULL) {\r
+ case EFI_HII_VARSTORE_BUFFER:\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+ BufferSize = Storage->Size;\r
+ Status = mHiiConfigRouting->ConfigToBlock (\r
+ mHiiConfigRouting,\r
+ ConfigResp,\r
+ Storage->EditBuffer,\r
+ &BufferSize,\r
+ &Progress\r
+ );\r
break;\r
- }\r
- StrPtr = StrStr (ConfigResp, L"&");\r
- while (StrPtr != NULL) {\r
- //\r
- // Skip '&'\r
- //\r
- StrPtr = StrPtr + 1;\r
- Name = StrPtr;\r
- StrPtr = StrStr (StrPtr, L"=");\r
+\r
+ case EFI_HII_VARSTORE_NAME_VALUE:\r
+ StrPtr = StrStr (ConfigResp, L"PATH");\r
if (StrPtr == NULL) {\r
break;\r
}\r
- *StrPtr = 0;\r
\r
- //\r
- // Skip '='\r
- //\r
- StrPtr = StrPtr + 1;\r
- Value = StrPtr;\r
- StrPtr = StrStr (StrPtr, L"&");\r
- if (StrPtr != NULL) {\r
+ StrPtr = StrStr (ConfigResp, L"&");\r
+ while (StrPtr != NULL) {\r
+ //\r
+ // Skip '&'\r
+ //\r
+ StrPtr = StrPtr + 1;\r
+ Name = StrPtr;\r
+ StrPtr = StrStr (StrPtr, L"=");\r
+ if (StrPtr == NULL) {\r
+ break;\r
+ }\r
+\r
*StrPtr = 0;\r
+\r
+ //\r
+ // Skip '='\r
+ //\r
+ StrPtr = StrPtr + 1;\r
+ Value = StrPtr;\r
+ StrPtr = StrStr (StrPtr, L"&");\r
+ if (StrPtr != NULL) {\r
+ *StrPtr = 0;\r
+ }\r
+\r
+ SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer, NULL);\r
}\r
- SetValueByName (Storage, Name, Value, TRUE);\r
- }\r
- break;\r
\r
- case EFI_HII_VARSTORE_EFI_VARIABLE:\r
- default:\r
- Status = EFI_INVALID_PARAMETER;\r
- break;\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
}\r
\r
return Status;\r
}\r
\r
+/**\r
+ Get bit field value from the buffer and then set the value for the question.\r
+ Note: Data type UINT32 can cover all the bit field value.\r
+\r
+ @param Question The question refer to bit field.\r
+ @param Buffer Point to the buffer which the question value get from.\r
+\r
+**/\r
+VOID\r
+GetBitsQuestionValue (\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN UINT8 *Buffer\r
+ )\r
+{\r
+ UINTN StartBit;\r
+ UINTN EndBit;\r
+ UINT32 RetVal;\r
+ UINT32 BufferValue;\r
+\r
+ StartBit = Question->BitVarOffset % 8;\r
+ EndBit = StartBit + Question->BitStorageWidth - 1;\r
+\r
+ CopyMem ((UINT8 *)&BufferValue, Buffer, Question->StorageWidth);\r
+\r
+ RetVal = BitFieldRead32 (BufferValue, StartBit, EndBit);\r
+\r
+ //\r
+ // Set question value.\r
+ // Note: Since Question with BufferValue (orderedlist, password, string)are not supported to refer bit field.\r
+ // Only oneof/checkbox/oneof can support bit field.So we can copy the value to the Hiivalue of Question directly.\r
+ //\r
+ CopyMem ((UINT8 *)&Question->HiiValue.Value, (UINT8 *)&RetVal, Question->StorageWidth);\r
+}\r
+\r
+/**\r
+ Set bit field value to the buffer.\r
+ Note: Data type UINT32 can cover all the bit field value.\r
+\r
+ @param Question The question refer to bit field.\r
+ @param Buffer Point to the buffer which the question value set to.\r
+ @param Value The bit field value need to set.\r
+\r
+**/\r
+VOID\r
+SetBitsQuestionValue (\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN OUT UINT8 *Buffer,\r
+ IN UINT32 Value\r
+ )\r
+{\r
+ UINT32 Operand;\r
+ UINTN StartBit;\r
+ UINTN EndBit;\r
+ UINT32 RetVal;\r
+\r
+ StartBit = Question->BitVarOffset % 8;\r
+ EndBit = StartBit + Question->BitStorageWidth - 1;\r
+\r
+ CopyMem ((UINT8 *)&Operand, Buffer, Question->StorageWidth);\r
+\r
+ RetVal = BitFieldWrite32 (Operand, StartBit, EndBit, Value);\r
+\r
+ CopyMem (Buffer, (UINT8 *)&RetVal, Question->StorageWidth);\r
+}\r
+\r
+/**\r
+ Convert the buffer value to HiiValue.\r
+\r
+ @param Question The question.\r
+ @param Value Unicode buffer save the question value.\r
+\r
+ @retval Status whether convert the value success.\r
+\r
+**/\r
+EFI_STATUS\r
+BufferToValue (\r
+ IN OUT FORM_BROWSER_STATEMENT *Question,\r
+ IN CHAR16 *Value\r
+ )\r
+{\r
+ CHAR16 *StringPtr;\r
+ BOOLEAN IsBufferStorage;\r
+ CHAR16 *DstBuf;\r
+ CHAR16 TempChar;\r
+ UINTN LengthStr;\r
+ UINT8 *Dst;\r
+ CHAR16 TemStr[5];\r
+ UINTN Index;\r
+ UINT8 DigitUint8;\r
+ BOOLEAN IsString;\r
+ UINTN Length;\r
+ EFI_STATUS Status;\r
+ UINT8 *Buffer;\r
+\r
+ Buffer = NULL;\r
+\r
+ IsString = (BOOLEAN)((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
+ if ((Question->Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+ (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+ {\r
+ IsBufferStorage = TRUE;\r
+ } else {\r
+ IsBufferStorage = FALSE;\r
+ }\r
+\r
+ //\r
+ // Question Value is provided by Buffer Storage or NameValue Storage\r
+ //\r
+ if (Question->BufferValue != NULL) {\r
+ //\r
+ // This Question is password or orderedlist\r
+ //\r
+ Dst = Question->BufferValue;\r
+ } else {\r
+ //\r
+ // Other type of Questions\r
+ //\r
+ if (Question->QuestionReferToBitField) {\r
+ Buffer = (UINT8 *)AllocateZeroPool (Question->StorageWidth);\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Dst = Buffer;\r
+ } else {\r
+ Dst = (UINT8 *)&Question->HiiValue.Value;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Temp cut at the end of this section, end with '\0' or '&'.\r
+ //\r
+ StringPtr = Value;\r
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+ StringPtr++;\r
+ }\r
+\r
+ TempChar = *StringPtr;\r
+ *StringPtr = L'\0';\r
+\r
+ LengthStr = StrLen (Value);\r
+\r
+ //\r
+ // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.\r
+ // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).\r
+ // So the maximum value string length of a question is : Question->StorageWidth * 2.\r
+ // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.\r
+ //\r
+ if (LengthStr > (UINTN)Question->StorageWidth * 2) {\r
+ Length = (UINTN)Question->StorageWidth * 2;\r
+ } else {\r
+ Length = LengthStr;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ if (!IsBufferStorage && IsString) {\r
+ //\r
+ // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
+ // Add string tail char L'\0' into Length\r
+ //\r
+ DstBuf = (CHAR16 *)Dst;\r
+ ZeroMem (TemStr, sizeof (TemStr));\r
+ for (Index = 0; Index < Length; Index += 4) {\r
+ StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), Value + Index, 4);\r
+ DstBuf[Index/4] = (CHAR16)StrHexToUint64 (TemStr);\r
+ }\r
+\r
+ //\r
+ // Add tailing L'\0' character\r
+ //\r
+ DstBuf[Index/4] = L'\0';\r
+ } else {\r
+ ZeroMem (TemStr, sizeof (TemStr));\r
+ for (Index = 0; Index < Length; Index++) {\r
+ TemStr[0] = Value[LengthStr - Index - 1];\r
+ DigitUint8 = (UINT8)StrHexToUint64 (TemStr);\r
+ if ((Index & 1) == 0) {\r
+ Dst[Index/2] = DigitUint8;\r
+ } else {\r
+ Dst[Index/2] = (UINT8)((DigitUint8 << 4) + Dst[Index/2]);\r
+ }\r
+ }\r
+ }\r
+\r
+ *StringPtr = TempChar;\r
+\r
+ if ((Buffer != NULL) && Question->QuestionReferToBitField) {\r
+ GetBitsQuestionValue (Question, Buffer);\r
+ FreePool (Buffer);\r
+ }\r
+\r
+ return Status;\r
+}\r
\r
/**\r
Get Question's current Value.\r
@param FormSet FormSet data structure.\r
@param Form Form data structure.\r
@param Question Question to be initialized.\r
- @param Cached TRUE: get from Edit copy FALSE: get from original\r
- Storage\r
+ @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
\r
@retval EFI_SUCCESS The function completed successfully.\r
\r
**/\r
EFI_STATUS\r
GetQuestionValue (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORM_BROWSER_FORM *Form,\r
- IN OUT FORM_BROWSER_STATEMENT *Question,\r
- IN BOOLEAN Cached\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN OUT FORM_BROWSER_STATEMENT *Question,\r
+ IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
)\r
{\r
EFI_STATUS Status;\r
UINT8 *Dst;\r
UINTN StorageWidth;\r
EFI_TIME EfiTime;\r
- FORMSET_STORAGE *Storage;\r
+ BROWSER_STORAGE *Storage;\r
+ FORMSET_STORAGE *FormsetStorage;\r
EFI_IFR_TYPE_VALUE *QuestionValue;\r
CHAR16 *ConfigRequest;\r
CHAR16 *Progress;\r
CHAR16 *Result;\r
CHAR16 *Value;\r
- CHAR16 *StringPtr;\r
UINTN Length;\r
- UINTN Index;\r
- UINTN LengthStr;\r
BOOLEAN IsBufferStorage;\r
- BOOLEAN IsString;\r
- CHAR16 TemStr[5];\r
- UINT8 DigitUint8;\r
- UINT8 *TemBuffer;\r
+ UINTN MaxLen;\r
\r
Status = EFI_SUCCESS;\r
Value = NULL;\r
+ Result = NULL;\r
\r
- //\r
- // Statement don't have storage, skip them\r
- //\r
- if (Question->QuestionId == 0) {\r
- return Status;\r
+ if (GetValueFrom >= GetSetValueWithMax) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
if (Question->ValueExpression != NULL) {\r
Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);\r
if (!EFI_ERROR (Status)) {\r
- CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
+ if (Question->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+ ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);\r
+ if (Question->StorageWidth > Question->ValueExpression->Result.BufferLen) {\r
+ CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->ValueExpression->Result.BufferLen);\r
+ Question->HiiValue.BufferLen = Question->ValueExpression->Result.BufferLen;\r
+ } else {\r
+ CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->StorageWidth);\r
+ Question->HiiValue.BufferLen = Question->StorageWidth;\r
+ }\r
+\r
+ FreePool (Question->ValueExpression->Result.Buffer);\r
+ }\r
+\r
+ Question->HiiValue.Type = Question->ValueExpression->Result.Type;\r
+ CopyMem (&Question->HiiValue.Value, &Question->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
}\r
+\r
return Status;\r
}\r
- \r
+\r
//\r
// Get question value by read expression.\r
//\r
- if (Question->ReadExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
+ if ((Question->ReadExpression != NULL) && (Form->FormType == STANDARD_MAP_FORM_TYPE)) {\r
Status = EvaluateExpression (FormSet, Form, Question->ReadExpression);\r
- if (!EFI_ERROR (Status) && (Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER)) {\r
+ if (!EFI_ERROR (Status) &&\r
+ ((Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER) || (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER)))\r
+ {\r
//\r
// Only update question value to the valid result.\r
//\r
- CopyMem (&Question->HiiValue, &Question->ReadExpression->Result, sizeof (EFI_HII_VALUE));\r
+ if (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+ ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);\r
+ if (Question->StorageWidth > Question->ReadExpression->Result.BufferLen) {\r
+ CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->ReadExpression->Result.BufferLen);\r
+ Question->HiiValue.BufferLen = Question->ReadExpression->Result.BufferLen;\r
+ } else {\r
+ CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->StorageWidth);\r
+ Question->HiiValue.BufferLen = Question->StorageWidth;\r
+ }\r
+\r
+ FreePool (Question->ReadExpression->Result.Buffer);\r
+ }\r
+\r
+ Question->HiiValue.Type = Question->ReadExpression->Result.Type;\r
+ CopyMem (&Question->HiiValue.Value, &Question->ReadExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
return EFI_SUCCESS;\r
}\r
}\r
//\r
// Question value is provided by RTC\r
//\r
- Storage = Question->Storage;\r
+ Storage = Question->Storage;\r
QuestionValue = &Question->HiiValue.Value;\r
if (Storage == NULL) {\r
//\r
// It's a Question without storage, or RTC date/time\r
//\r
- if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
+ if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {\r
//\r
// Date and time define the same Flags bit\r
//\r
switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
- case QF_DATE_STORAGE_TIME:\r
- Status = gRT->GetTime (&EfiTime, NULL);\r
- break;\r
+ case QF_DATE_STORAGE_TIME:\r
+ Status = gRT->GetTime (&EfiTime, NULL);\r
+ break;\r
\r
- case QF_DATE_STORAGE_WAKEUP:\r
- Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
- break;\r
+ case QF_DATE_STORAGE_WAKEUP:\r
+ Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
+ break;\r
\r
- case QF_DATE_STORAGE_NORMAL:\r
- default:\r
- //\r
- // For date/time without storage\r
- //\r
- return EFI_SUCCESS;\r
+ case QF_DATE_STORAGE_NORMAL:\r
+ default:\r
+ //\r
+ // For date/time without storage\r
+ //\r
+ return EFI_SUCCESS;\r
}\r
\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ if (Question->Operand == EFI_IFR_DATE_OP) {\r
+ QuestionValue->date.Year = 0xff;\r
+ QuestionValue->date.Month = 0xff;\r
+ QuestionValue->date.Day = 0xff;\r
+ } else {\r
+ QuestionValue->time.Hour = 0xff;\r
+ QuestionValue->time.Minute = 0xff;\r
+ QuestionValue->time.Second = 0xff;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
if (Question->Operand == EFI_IFR_DATE_OP) {\r
if (Question->BufferValue != NULL) {\r
Dst = Question->BufferValue;\r
} else {\r
- Dst = (UINT8 *) QuestionValue;\r
+ Dst = (UINT8 *)QuestionValue;\r
}\r
\r
Status = gRT->GetVariable (\r
- Question->VariableName,\r
- &Storage->Guid,\r
- NULL,\r
- &StorageWidth,\r
- Dst\r
- );\r
+ Question->VariableName,\r
+ &Storage->Guid,\r
+ NULL,\r
+ &StorageWidth,\r
+ Dst\r
+ );\r
//\r
// Always return success, even this EFI variable doesn't exist\r
//\r
//\r
// Other type of Questions\r
//\r
- Dst = (UINT8 *) &Question->HiiValue.Value;\r
+ Dst = (UINT8 *)&Question->HiiValue.Value;\r
}\r
\r
- if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
- Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+ if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+ {\r
IsBufferStorage = TRUE;\r
} else {\r
IsBufferStorage = FALSE;\r
}\r
- IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
- if (Cached) {\r
- if (IsBufferStorage) {\r
- //\r
- // Copy from storage Edit buffer\r
- //\r
- CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
- } else {\r
- Value = NULL;\r
- Status = GetValueByName (Storage, Question->VariableName, &Value);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
\r
- ASSERT (Value != NULL);\r
- LengthStr = StrLen (Value);\r
- Status = EFI_SUCCESS;\r
- if (IsString) {\r
+ if ((GetValueFrom == GetSetValueWithEditBuffer) || (GetValueFrom == GetSetValueWithBuffer)) {\r
+ if (IsBufferStorage) {\r
+ if (GetValueFrom == GetSetValueWithEditBuffer) {\r
//\r
- // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
- // Add string tail char L'\0' into Length\r
+ // Copy from storage Edit buffer\r
+ // If the Question refer to bit filed, get the value in the related bit filed.\r
//\r
- Length = StorageWidth + sizeof (CHAR16);\r
- if (Length < ((LengthStr / 4 + 1) * 2)) {\r
- Status = EFI_BUFFER_TOO_SMALL;\r
+ if (Question->QuestionReferToBitField) {\r
+ GetBitsQuestionValue (Question, Storage->EditBuffer + Question->VarStoreInfo.VarOffset);\r
} else {\r
- StringPtr = (CHAR16 *) Dst;\r
- ZeroMem (TemStr, sizeof (TemStr));\r
- for (Index = 0; Index < LengthStr; Index += 4) {\r
- StrnCpy (TemStr, Value + Index, 4);\r
- StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
- }\r
- //\r
- // Add tailing L'\0' character\r
- //\r
- StringPtr[Index/4] = L'\0';\r
+ CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
}\r
} else {\r
- if (StorageWidth < ((LengthStr + 1) / 2)) {\r
- Status = EFI_BUFFER_TOO_SMALL;\r
+ //\r
+ // Copy from storage Edit buffer\r
+ // If the Question refer to bit filed, get the value in the related bit filed.\r
+ //\r
+ if (Question->QuestionReferToBitField) {\r
+ GetBitsQuestionValue (Question, Storage->Buffer + Question->VarStoreInfo.VarOffset);\r
} else {\r
- ZeroMem (TemStr, sizeof (TemStr));\r
- for (Index = 0; Index < LengthStr; Index ++) {\r
- TemStr[0] = Value[LengthStr - Index - 1];\r
- DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
- if ((Index & 1) == 0) {\r
- Dst [Index/2] = DigitUint8;\r
- } else {\r
- Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
- }\r
- }\r
+ CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
}\r
}\r
+ } else {\r
+ Value = NULL;\r
+ Status = GetValueByName (Storage, Question->VariableName, &Value, GetValueFrom);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
+ ASSERT (Value != NULL);\r
+ Status = BufferToValue (Question, Value);\r
FreePool (Value);\r
}\r
} else {\r
- if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
- //\r
- // Request current settings from Configuration Driver\r
- //\r
- if (FormSet->ConfigAccess == NULL) {\r
+ FormsetStorage = GetFstStgFromVarId (FormSet, Question->VarStoreId);\r
+ ASSERT (FormsetStorage != NULL);\r
+ //\r
+ // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
+ // <ConfigHdr> + "&" + <VariableName>\r
+ //\r
+ if (IsBufferStorage) {\r
+ Length = StrLen (FormsetStorage->ConfigHdr);\r
+ Length += StrLen (Question->BlockName);\r
+ } else {\r
+ Length = StrLen (FormsetStorage->ConfigHdr);\r
+ Length += StrLen (Question->VariableName) + 1;\r
+ }\r
+\r
+ // Allocate buffer include '\0'\r
+ MaxLen = Length + 1;\r
+ ConfigRequest = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
+ ASSERT (ConfigRequest != NULL);\r
+\r
+ StrCpyS (ConfigRequest, MaxLen, FormsetStorage->ConfigHdr);\r
+ if (IsBufferStorage) {\r
+ StrCatS (ConfigRequest, MaxLen, Question->BlockName);\r
+ } else {\r
+ StrCatS (ConfigRequest, MaxLen, L"&");\r
+ StrCatS (ConfigRequest, MaxLen, Question->VariableName);\r
+ }\r
+\r
+ //\r
+ // Request current settings from Configuration Driver\r
+ //\r
+ Status = mHiiConfigRouting->ExtractConfig (\r
+ mHiiConfigRouting,\r
+ ConfigRequest,\r
+ &Progress,\r
+ &Result\r
+ );\r
+ FreePool (ConfigRequest);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Skip <ConfigRequest>\r
+ //\r
+ if (IsBufferStorage) {\r
+ Value = StrStr (Result, L"&VALUE");\r
+ if (Value == NULL) {\r
+ FreePool (Result);\r
return EFI_NOT_FOUND;\r
}\r
\r
//\r
- // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
- // <ConfigHdr> + "&" + <VariableName>\r
+ // Skip "&VALUE"\r
//\r
- if (IsBufferStorage) {\r
- Length = StrLen (Storage->ConfigHdr);\r
- Length += StrLen (Question->BlockName);\r
- } else {\r
- Length = StrLen (Storage->ConfigHdr);\r
- Length += StrLen (Question->VariableName) + 1;\r
- }\r
- ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
- ASSERT (ConfigRequest != NULL);\r
-\r
- StrCpy (ConfigRequest, Storage->ConfigHdr);\r
- if (IsBufferStorage) {\r
- StrCat (ConfigRequest, Question->BlockName);\r
- } else {\r
- StrCat (ConfigRequest, L"&");\r
- StrCat (ConfigRequest, Question->VariableName);\r
- }\r
+ Value = Value + 6;\r
+ } else {\r
+ Value = Result + Length;\r
+ }\r
\r
- Status = FormSet->ConfigAccess->ExtractConfig (\r
- FormSet->ConfigAccess,\r
- ConfigRequest,\r
- &Progress,\r
- &Result\r
- );\r
- FreePool (ConfigRequest);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Skip <ConfigRequest>\r
- //\r
- Value = Result + Length;\r
- if (IsBufferStorage) {\r
- //\r
- // Skip "&VALUE"\r
- //\r
- Value = Value + 6;\r
- }\r
- if (*Value != '=') {\r
- FreePool (Result);\r
- return EFI_NOT_FOUND;\r
- }\r
- //\r
- // Skip '=', point to value\r
- //\r
- Value = Value + 1;\r
-\r
- //\r
- // Suppress <AltResp> if any\r
- //\r
- StringPtr = Value;\r
- while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
- StringPtr++;\r
- }\r
- *StringPtr = L'\0';\r
-\r
- LengthStr = StrLen (Value);\r
- Status = EFI_SUCCESS;\r
- if (!IsBufferStorage && IsString) {\r
- //\r
- // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
- // Add string tail char L'\0' into Length\r
- //\r
- Length = StorageWidth + sizeof (CHAR16);\r
- if (Length < ((LengthStr / 4 + 1) * 2)) {\r
- Status = EFI_BUFFER_TOO_SMALL;\r
- } else {\r
- StringPtr = (CHAR16 *) Dst;\r
- ZeroMem (TemStr, sizeof (TemStr));\r
- for (Index = 0; Index < LengthStr; Index += 4) {\r
- StrnCpy (TemStr, Value + Index, 4);\r
- StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
- }\r
- //\r
- // Add tailing L'\0' character\r
- //\r
- StringPtr[Index/4] = L'\0';\r
- }\r
- } else {\r
- if (StorageWidth < ((LengthStr + 1) / 2)) {\r
- Status = EFI_BUFFER_TOO_SMALL;\r
- } else {\r
- ZeroMem (TemStr, sizeof (TemStr));\r
- for (Index = 0; Index < LengthStr; Index ++) {\r
- TemStr[0] = Value[LengthStr - Index - 1];\r
- DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
- if ((Index & 1) == 0) {\r
- Dst [Index/2] = DigitUint8;\r
- } else {\r
- Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
- }\r
- }\r
- }\r
- }\r
+ if (*Value != '=') {\r
FreePool (Result);\r
+ return EFI_NOT_FOUND;\r
+ }\r
\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
- TemBuffer = NULL;\r
- TemBuffer = AllocateZeroPool (Storage->Size);\r
- if (TemBuffer == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- return Status;\r
- }\r
- Length = Storage->Size;\r
- Status = gRT->GetVariable (\r
- Storage->Name,\r
- &Storage->Guid,\r
- NULL,\r
- &Length,\r
- TemBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (TemBuffer);\r
- return Status;\r
- }\r
-\r
- CopyMem (Dst, TemBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
+ //\r
+ // Skip '=', point to value\r
+ //\r
+ Value = Value + 1;\r
\r
- FreePool (TemBuffer);\r
+ Status = BufferToValue (Question, Value);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Result);\r
+ return Status;\r
}\r
\r
//\r
if (IsBufferStorage) {\r
CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
} else {\r
- SetValueByName (Storage, Question->VariableName, Value, TRUE);\r
+ SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer, NULL);\r
+ }\r
+\r
+ if (Result != NULL) {\r
+ FreePool (Result);\r
}\r
}\r
\r
return Status;\r
}\r
\r
-\r
/**\r
Save Question Value to edit copy(cached) or Storage(uncached).\r
\r
@param FormSet FormSet data structure.\r
@param Form Form data structure.\r
@param Question Pointer to the Question.\r
- @param Cached TRUE: set to Edit copy FALSE: set to original\r
- Storage\r
+ @param SetValueTo Update the question value to editbuffer , buffer or hii driver.\r
\r
@retval EFI_SUCCESS The function completed successfully.\r
\r
**/\r
EFI_STATUS\r
SetQuestionValue (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORM_BROWSER_FORM *Form,\r
- IN OUT FORM_BROWSER_STATEMENT *Question,\r
- IN BOOLEAN Cached\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN OUT FORM_BROWSER_STATEMENT *Question,\r
+ IN GET_SET_QUESTION_VALUE_WITH SetValueTo\r
)\r
{\r
EFI_STATUS Status;\r
EFI_TIME EfiTime;\r
UINTN BufferLen;\r
UINTN StorageWidth;\r
- FORMSET_STORAGE *Storage;\r
+ BROWSER_STORAGE *Storage;\r
+ FORMSET_STORAGE *FormsetStorage;\r
EFI_IFR_TYPE_VALUE *QuestionValue;\r
CHAR16 *ConfigResp;\r
CHAR16 *Progress;\r
CHAR16 *TemName;\r
CHAR16 *TemString;\r
UINTN Index;\r
+ NAME_VALUE_NODE *Node;\r
+ UINTN MaxLen;\r
\r
Status = EFI_SUCCESS;\r
+ Node = NULL;\r
\r
- //\r
- // Statement don't have storage, skip them\r
- //\r
- if (Question->QuestionId == 0) {\r
- return Status;\r
+ if (SetValueTo >= GetSetValueWithMax) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
if (Question->ValueExpression != NULL) {\r
return Status;\r
}\r
- \r
+\r
//\r
// Before set question value, evaluate its write expression.\r
//\r
- if (Question->WriteExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
+ if ((Question->WriteExpression != NULL) && (Form->FormType == STANDARD_MAP_FORM_TYPE)) {\r
Status = EvaluateExpression (FormSet, Form, Question->WriteExpression);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
//\r
// Question value is provided by RTC\r
//\r
- Storage = Question->Storage;\r
+ Storage = Question->Storage;\r
QuestionValue = &Question->HiiValue.Value;\r
if (Storage == NULL) {\r
//\r
// It's a Question without storage, or RTC date/time\r
//\r
- if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
+ if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {\r
//\r
// Date and time define the same Flags bit\r
//\r
switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
- case QF_DATE_STORAGE_TIME:\r
- Status = gRT->GetTime (&EfiTime, NULL);\r
- break;\r
+ case QF_DATE_STORAGE_TIME:\r
+ Status = gRT->GetTime (&EfiTime, NULL);\r
+ break;\r
\r
- case QF_DATE_STORAGE_WAKEUP:\r
- Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
- break;\r
+ case QF_DATE_STORAGE_WAKEUP:\r
+ Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
+ break;\r
\r
- case QF_DATE_STORAGE_NORMAL:\r
- default:\r
- //\r
- // For date/time without storage\r
- //\r
- return EFI_SUCCESS;\r
+ case QF_DATE_STORAGE_NORMAL:\r
+ default:\r
+ //\r
+ // For date/time without storage\r
+ //\r
+ return EFI_SUCCESS;\r
}\r
\r
if (EFI_ERROR (Status)) {\r
if (Question->BufferValue != NULL) {\r
Src = Question->BufferValue;\r
} else {\r
- Src = (UINT8 *) QuestionValue;\r
+ Src = (UINT8 *)QuestionValue;\r
}\r
\r
Status = gRT->SetVariable (\r
- Question->VariableName,\r
- &Storage->Guid,\r
- Storage->Attributes,\r
- StorageWidth,\r
- Src\r
- );\r
+ Question->VariableName,\r
+ &Storage->Guid,\r
+ Storage->Attributes,\r
+ StorageWidth,\r
+ Src\r
+ );\r
return Status;\r
}\r
\r
if (Question->BufferValue != NULL) {\r
Src = Question->BufferValue;\r
} else {\r
- Src = (UINT8 *) &Question->HiiValue.Value;\r
+ Src = (UINT8 *)&Question->HiiValue.Value;\r
}\r
\r
- if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
- Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+ if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+ {\r
IsBufferStorage = TRUE;\r
} else {\r
IsBufferStorage = FALSE;\r
}\r
- IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
- if (IsBufferStorage) {\r
- //\r
- // Copy to storage edit buffer\r
- //\r
- CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
- } else {\r
- if (IsString) {\r
- //\r
- // Allocate enough string buffer.\r
- //\r
- Value = NULL;\r
- BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
- Value = AllocateZeroPool (BufferLen);\r
- ASSERT (Value != NULL);\r
- //\r
- // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
- //\r
- TemName = (CHAR16 *) Src;\r
- TemString = Value;\r
- for (; *TemName != L'\0'; TemName++) {\r
- TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
- }\r
- } else {\r
- BufferLen = StorageWidth * 2 + 1;\r
- Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
- ASSERT (Value != NULL);\r
- //\r
- // Convert Buffer to Hex String\r
- //\r
- TemBuffer = Src + StorageWidth - 1;\r
- TemString = Value;\r
- for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
- TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
- }\r
- }\r
-\r
- Status = SetValueByName (Storage, Question->VariableName, Value, TRUE);\r
- FreePool (Value);\r
- }\r
\r
- if (!Cached) {\r
- if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
- //\r
- // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
- // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
- //\r
- if (IsBufferStorage) {\r
- Length = StrLen (Question->BlockName) + 7;\r
- } else {\r
- Length = StrLen (Question->VariableName) + 2;\r
- }\r
- if (!IsBufferStorage && IsString) {\r
- Length += (StrLen ((CHAR16 *) Src) * 4);\r
- } else {\r
- Length += (StorageWidth * 2);\r
- }\r
- ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
- ASSERT (ConfigResp != NULL);\r
+ IsString = (BOOLEAN)((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
\r
- StrCpy (ConfigResp, Storage->ConfigHdr);\r
- if (IsBufferStorage) {\r
- StrCat (ConfigResp, Question->BlockName);\r
- StrCat (ConfigResp, L"&VALUE=");\r
- } else {\r
- StrCat (ConfigResp, L"&");\r
- StrCat (ConfigResp, Question->VariableName);\r
- StrCat (ConfigResp, L"=");\r
+ if ((SetValueTo == GetSetValueWithEditBuffer) || (SetValueTo == GetSetValueWithBuffer)) {\r
+ if (IsBufferStorage) {\r
+ if (SetValueTo == GetSetValueWithEditBuffer) {\r
+ //\r
+ // Copy to storage edit buffer\r
+ // If the Question refer to bit filed, copy the value in related bit filed to storage edit buffer.\r
+ //\r
+ if (Question->QuestionReferToBitField) {\r
+ SetBitsQuestionValue (Question, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, (UINT32)(*Src));\r
+ } else {\r
+ CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+ }\r
+ } else if (SetValueTo == GetSetValueWithBuffer) {\r
+ //\r
+ // Copy to storage buffer\r
+ // If the Question refer to bit filed, copy the value in related bit filed to storage buffer.\r
+ //\r
+ if (Question->QuestionReferToBitField) {\r
+ SetBitsQuestionValue (Question, Storage->Buffer + Question->VarStoreInfo.VarOffset, (UINT32)(*Src));\r
+ } else {\r
+ CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+ }\r
}\r
-\r
- Value = ConfigResp + StrLen (ConfigResp);\r
-\r
- if (!IsBufferStorage && IsString) {\r
+ } else {\r
+ if (IsString) {\r
+ //\r
+ // Allocate enough string buffer.\r
+ //\r
+ Value = NULL;\r
+ BufferLen = ((StrLen ((CHAR16 *)Src) * 4) + 1) * sizeof (CHAR16);\r
+ Value = AllocateZeroPool (BufferLen);\r
+ ASSERT (Value != NULL);\r
//\r
// Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
//\r
- TemName = (CHAR16 *) Src;\r
+ TemName = (CHAR16 *)Src;\r
TemString = Value;\r
- for (; *TemName != L'\0'; TemName++) {\r
- TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
+ for ( ; *TemName != L'\0'; TemName++) {\r
+ UnicodeValueToStringS (\r
+ TemString,\r
+ BufferLen - ((UINTN)TemString - (UINTN)Value),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ *TemName,\r
+ 4\r
+ );\r
+ TemString += StrnLenS (TemString, (BufferLen - ((UINTN)TemString - (UINTN)Value)) / sizeof (CHAR16));\r
}\r
} else {\r
+ BufferLen = StorageWidth * 2 + 1;\r
+ Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
+ ASSERT (Value != NULL);\r
//\r
// Convert Buffer to Hex String\r
//\r
TemBuffer = Src + StorageWidth - 1;\r
TemString = Value;\r
- for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
- TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
+ for (Index = 0; Index < StorageWidth; Index++, TemBuffer--) {\r
+ UnicodeValueToStringS (\r
+ TemString,\r
+ BufferLen * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)Value),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ *TemBuffer,\r
+ 2\r
+ );\r
+ TemString += StrnLenS (TemString, BufferLen - ((UINTN)TemString - (UINTN)Value) / sizeof (CHAR16));\r
}\r
}\r
\r
- //\r
- // Convert to lower char.\r
- //\r
- for (TemString = Value; *Value != L'\0'; Value++) {\r
- if (*Value >= L'A' && *Value <= L'Z') {\r
- *Value = (CHAR16) (*Value - L'A' + L'a');\r
- }\r
+ Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo, &Node);\r
+ FreePool (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
+ }\r
+ } else if (SetValueTo == GetSetValueWithHiiDriver) {\r
+ //\r
+ // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
+ // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
+ //\r
+ if (IsBufferStorage) {\r
+ Length = StrLen (Question->BlockName) + 7;\r
+ } else {\r
+ Length = StrLen (Question->VariableName) + 2;\r
+ }\r
+\r
+ if (!IsBufferStorage && IsString) {\r
+ Length += (StrLen ((CHAR16 *)Src) * 4);\r
+ } else {\r
+ Length += (StorageWidth * 2);\r
+ }\r
+\r
+ FormsetStorage = GetFstStgFromVarId (FormSet, Question->VarStoreId);\r
+ ASSERT (FormsetStorage != NULL);\r
+ MaxLen = StrLen (FormsetStorage->ConfigHdr) + Length + 1;\r
+ ConfigResp = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
+ ASSERT (ConfigResp != NULL);\r
+\r
+ StrCpyS (ConfigResp, MaxLen, FormsetStorage->ConfigHdr);\r
+ if (IsBufferStorage) {\r
+ StrCatS (ConfigResp, MaxLen, Question->BlockName);\r
+ StrCatS (ConfigResp, MaxLen, L"&VALUE=");\r
+ } else {\r
+ StrCatS (ConfigResp, MaxLen, L"&");\r
+ StrCatS (ConfigResp, MaxLen, Question->VariableName);\r
+ StrCatS (ConfigResp, MaxLen, L"=");\r
+ }\r
+\r
+ Value = ConfigResp + StrLen (ConfigResp);\r
\r
+ if (!IsBufferStorage && IsString) {\r
//\r
- // Submit Question Value to Configuration Driver\r
+ // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
//\r
- if (FormSet->ConfigAccess != NULL) {\r
- Status = FormSet->ConfigAccess->RouteConfig (\r
- FormSet->ConfigAccess,\r
- ConfigResp,\r
- &Progress\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (ConfigResp);\r
- return Status;\r
- }\r
+ TemName = (CHAR16 *)Src;\r
+ TemString = Value;\r
+ for ( ; *TemName != L'\0'; TemName++) {\r
+ UnicodeValueToStringS (\r
+ TemString,\r
+ MaxLen * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ConfigResp),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ *TemName,\r
+ 4\r
+ );\r
+ TemString += StrnLenS (TemString, MaxLen - ((UINTN)TemString - (UINTN)ConfigResp) / sizeof (CHAR16));\r
}\r
- FreePool (ConfigResp);\r
- \r
- } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
- TemBuffer = NULL;\r
- TemBuffer = AllocateZeroPool(Storage->Size);\r
- if (TemBuffer == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- return Status;\r
+ } else {\r
+ //\r
+ // Convert Buffer to Hex String\r
+ //\r
+ TemBuffer = Src + StorageWidth - 1;\r
+ TemString = Value;\r
+ for (Index = 0; Index < StorageWidth; Index++, TemBuffer--) {\r
+ UnicodeValueToStringS (\r
+ TemString,\r
+ MaxLen * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ConfigResp),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ *TemBuffer,\r
+ 2\r
+ );\r
+ TemString += StrnLenS (TemString, MaxLen - ((UINTN)TemString - (UINTN)ConfigResp) / sizeof (CHAR16));\r
}\r
- Length = Storage->Size;\r
- Status = gRT->GetVariable (\r
- Storage->Name,\r
- &Storage->Guid,\r
- NULL,\r
- &Length,\r
- TemBuffer\r
- );\r
-\r
- CopyMem (TemBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
- \r
- Status = gRT->SetVariable (\r
- Storage->Name,\r
- &Storage->Guid,\r
- Storage->Attributes,\r
- Storage->Size,\r
- TemBuffer\r
- );\r
- FreePool (TemBuffer);\r
- if (EFI_ERROR (Status)){\r
- return Status;\r
+ }\r
+\r
+ //\r
+ // Convert to lower char.\r
+ //\r
+ for (TemString = Value; *Value != L'\0'; Value++) {\r
+ if ((*Value >= L'A') && (*Value <= L'Z')) {\r
+ *Value = (CHAR16)(*Value - L'A' + L'a');\r
}\r
}\r
+\r
+ //\r
+ // Submit Question Value to Configuration Driver\r
+ //\r
+ Status = mHiiConfigRouting->RouteConfig (\r
+ mHiiConfigRouting,\r
+ ConfigResp,\r
+ &Progress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (ConfigResp);\r
+ return Status;\r
+ }\r
+\r
+ FreePool (ConfigResp);\r
+\r
//\r
// Sync storage, from editbuffer to buffer.\r
//\r
return Status;\r
}\r
\r
-\r
/**\r
- Perform inconsistent check for a Form.\r
+ Perform nosubmitif check for a Form.\r
\r
@param FormSet FormSet data structure.\r
@param Form Form data structure.\r
@param Question The Question to be validated.\r
- @param Type Validation type: InConsistent or NoSubmit\r
+ @param Type Validation type: NoSubmit\r
\r
@retval EFI_SUCCESS Form validation pass.\r
@retval other Form validation failed.\r
**/\r
EFI_STATUS\r
ValidateQuestion (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORM_BROWSER_FORM *Form,\r
- IN FORM_BROWSER_STATEMENT *Question,\r
- IN UINTN Type\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN UINTN Type\r
)\r
{\r
- EFI_STATUS Status;\r
- LIST_ENTRY *Link;\r
- LIST_ENTRY *ListHead;\r
- EFI_STRING PopUp;\r
- EFI_INPUT_KEY Key;\r
- FORM_EXPRESSION *Expression;\r
-\r
- if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {\r
- ListHead = &Question->InconsistentListHead;\r
- } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
- ListHead = &Question->NoSubmitListHead;\r
- } else {\r
- return EFI_UNSUPPORTED;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *ListHead;\r
+ FORM_EXPRESSION *Expression;\r
+ UINT32 BrowserStatus;\r
+ CHAR16 *ErrorStr;\r
+\r
+ BrowserStatus = BROWSER_SUCCESS;\r
+ ErrorStr = NULL;\r
+\r
+ switch (Type) {\r
+ case EFI_HII_EXPRESSION_INCONSISTENT_IF:\r
+ ListHead = &Question->InconsistentListHead;\r
+ break;\r
+\r
+ case EFI_HII_EXPRESSION_WARNING_IF:\r
+ ListHead = &Question->WarningListHead;\r
+ break;\r
+\r
+ case EFI_HII_EXPRESSION_NO_SUBMIT_IF:\r
+ ListHead = &Question->NoSubmitListHead;\r
+ break;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ return EFI_UNSUPPORTED;\r
}\r
\r
Link = GetFirstNode (ListHead);\r
return Status;\r
}\r
\r
- if (Expression->Result.Value.b) {\r
- //\r
- // Condition meet, show up error message\r
- //\r
- if (Expression->Error != 0) {\r
- PopUp = GetToken (Expression->Error, FormSet->HiiHandle);\r
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);\r
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
- FreePool (PopUp);\r
+ if (IsTrue (&Expression->Result)) {\r
+ switch (Type) {\r
+ case EFI_HII_EXPRESSION_INCONSISTENT_IF:\r
+ BrowserStatus = BROWSER_INCONSISTENT_IF;\r
+ break;\r
+\r
+ case EFI_HII_EXPRESSION_WARNING_IF:\r
+ BrowserStatus = BROWSER_WARNING_IF;\r
+ break;\r
+\r
+ case EFI_HII_EXPRESSION_NO_SUBMIT_IF:\r
+ BrowserStatus = BROWSER_NO_SUBMIT_IF;\r
+ //\r
+ // This code only used to compatible with old display engine,\r
+ // New display engine will not use this field.\r
+ //\r
+ if (Expression->Error != 0) {\r
+ ErrorStr = GetToken (Expression->Error, FormSet->HiiHandle);\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
}\r
\r
- return EFI_NOT_READY;\r
+ if (!((Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) && mSystemSubmit)) {\r
+ //\r
+ // If in system submit process and for no_submit_if check, not popup this error message.\r
+ // Will process this fail again later in not system submit process.\r
+ //\r
+ PopupErrorMessage (BrowserStatus, FormSet->HiiHandle, Expression->OpCode, ErrorStr);\r
+ }\r
+\r
+ if (ErrorStr != NULL) {\r
+ FreePool (ErrorStr);\r
+ }\r
+\r
+ if (Type == EFI_HII_EXPRESSION_WARNING_IF) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_NOT_READY;\r
+ }\r
}\r
\r
Link = GetNextNode (ListHead, Link);\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Perform question check.\r
+\r
+ If one question has more than one check, process form high priority to low.\r
+ Only one error info will be popup.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param Question The Question to be validated.\r
+\r
+ @retval EFI_SUCCESS Form validation pass.\r
+ @retval other Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+ValueChangedValidation (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN FORM_BROWSER_STATEMENT *Question\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Do the inconsistentif check.\r
+ //\r
+ if (!IsListEmpty (&Question->InconsistentListHead)) {\r
+ Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Do the warningif check.\r
+ //\r
+ if (!IsListEmpty (&Question->WarningListHead)) {\r
+ Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_WARNING_IF);\r
+ }\r
+\r
+ return Status;\r
+}\r
\r
/**\r
Perform NoSubmit check for each Form in FormSet.\r
\r
@param FormSet FormSet data structure.\r
@param CurrentForm Current input form data structure.\r
+ @param Statement The statement for this check.\r
\r
@retval EFI_SUCCESS Form validation pass.\r
@retval other Form validation failed.\r
**/\r
EFI_STATUS\r
NoSubmitCheck (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORM_BROWSER_FORM *CurrentForm\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN OUT FORM_BROWSER_FORM **CurrentForm,\r
+ OUT FORM_BROWSER_STATEMENT **Statement\r
)\r
{\r
EFI_STATUS Status;\r
\r
LinkForm = GetFirstNode (&FormSet->FormListHead);\r
while (!IsNull (&FormSet->FormListHead, LinkForm)) {\r
- Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);\r
LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);\r
\r
- if (CurrentForm != NULL && CurrentForm != Form) {\r
+ if ((*CurrentForm != NULL) && (*CurrentForm != Form)) {\r
continue;\r
}\r
\r
Link = GetFirstNode (&Form->StatementListHead);\r
while (!IsNull (&Form->StatementListHead, Link)) {\r
Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
-\r
- Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
+ Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
if (EFI_ERROR (Status)) {\r
+ if (*CurrentForm == NULL) {\r
+ *CurrentForm = Form;\r
+ }\r
+\r
+ if (Statement != NULL) {\r
+ *Statement = Question;\r
+ }\r
+\r
return Status;\r
}\r
\r
/**\r
Fill storage's edit copy with settings requested from Configuration Driver.\r
\r
- @param FormSet FormSet data structure.\r
- @param ConfigInfo The config info related to this form.\r
- @param SyncOrRestore Sync the buffer to editbuffer or Restore the \r
+ @param Storage The storage which need to sync.\r
+ @param ConfigRequest The config request string which used to sync storage.\r
+ @param SyncOrRestore Sync the buffer to editbuffer or Restore the\r
editbuffer to buffer\r
if TRUE, copy the editbuffer to the buffer.\r
if FALSE, copy the buffer to the editbuffer.\r
\r
**/\r
EFI_STATUS\r
-SynchronizeStorageForForm (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORM_BROWSER_CONFIG_REQUEST *ConfigInfo,\r
- IN BOOLEAN SyncOrRestore\r
+SynchronizeStorage (\r
+ OUT BROWSER_STORAGE *Storage,\r
+ IN CHAR16 *ConfigRequest,\r
+ IN BOOLEAN SyncOrRestore\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_STRING Progress;\r
- EFI_STRING Result;\r
- UINTN BufferSize;\r
- LIST_ENTRY *Link;\r
- NAME_VALUE_NODE *Node;\r
- UINT8 *Src;\r
- UINT8 *Dst;\r
+ EFI_STATUS Status;\r
+ EFI_STRING Progress;\r
+ EFI_STRING Result;\r
+ UINTN BufferSize;\r
+ LIST_ENTRY *Link;\r
+ NAME_VALUE_NODE *Node;\r
+ UINT8 *Src;\r
+ UINT8 *Dst;\r
\r
Status = EFI_SUCCESS;\r
Result = NULL;\r
- if (FormSet->ConfigAccess == NULL && ConfigInfo->Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
- return EFI_NOT_FOUND;\r
- }\r
\r
- if (ConfigInfo->ElementCount == 0) {\r
- //\r
- // Skip if there is no RequestElement\r
- //\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
- (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
- BufferSize = ConfigInfo->Storage->Size;\r
+ if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+ {\r
+ BufferSize = Storage->Size;\r
\r
if (SyncOrRestore) {\r
- Src = ConfigInfo->Storage->EditBuffer;\r
- Dst = ConfigInfo->Storage->Buffer;\r
+ Src = Storage->EditBuffer;\r
+ Dst = Storage->Buffer;\r
} else {\r
- Src = ConfigInfo->Storage->Buffer;\r
- Dst = ConfigInfo->Storage->EditBuffer;\r
+ Src = Storage->Buffer;\r
+ Dst = Storage->EditBuffer;\r
}\r
\r
- Status = mHiiConfigRouting->BlockToConfig(\r
- mHiiConfigRouting,\r
- ConfigInfo->ConfigRequest,\r
- Src,\r
- BufferSize,\r
- &Result,\r
- &Progress\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ if (ConfigRequest != NULL) {\r
+ Status = mHiiConfigRouting->BlockToConfig (\r
+ mHiiConfigRouting,\r
+ ConfigRequest,\r
+ Src,\r
+ BufferSize,\r
+ &Result,\r
+ &Progress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
- Status = mHiiConfigRouting->ConfigToBlock (\r
- mHiiConfigRouting,\r
- Result,\r
- Dst,\r
- &BufferSize,\r
- &Progress\r
- );\r
- if (Result != NULL) {\r
- FreePool (Result);\r
+ Status = mHiiConfigRouting->ConfigToBlock (\r
+ mHiiConfigRouting,\r
+ Result,\r
+ Dst,\r
+ &BufferSize,\r
+ &Progress\r
+ );\r
+ if (Result != NULL) {\r
+ FreePool (Result);\r
+ }\r
+ } else {\r
+ CopyMem (Dst, Src, BufferSize);\r
}\r
- } else if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
- Link = GetFirstNode (&ConfigInfo->Storage->NameValueListHead);\r
- while (!IsNull (&ConfigInfo->Storage->NameValueListHead, Link)) {\r
+ } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ Link = GetFirstNode (&Storage->NameValueListHead);\r
+ while (!IsNull (&Storage->NameValueListHead, Link)) {\r
Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
\r
- if (StrStr (ConfigInfo->ConfigRequest, Node->Name) != NULL) {\r
+ if (((ConfigRequest != NULL) && (StrStr (ConfigRequest, Node->Name) != NULL)) ||\r
+ (ConfigRequest == NULL))\r
+ {\r
if (SyncOrRestore) {\r
NewStringCpy (&Node->Value, Node->EditValue);\r
} else {\r
}\r
}\r
\r
- Link = GetNextNode (&ConfigInfo->Storage->NameValueListHead, Link);\r
+ Link = GetNextNode (&Storage->NameValueListHead, Link);\r
}\r
}\r
\r
return Status;\r
}\r
\r
-\r
/**\r
- Discard data for form level or formset level.\r
+ When discard the question value, call the callback function with Changed type\r
+ to inform the hii driver.\r
\r
@param FormSet FormSet data structure.\r
@param Form Form data structure.\r
- @param SingleForm Only discard single form or formset.\r
-\r
- @retval EFI_SUCCESS The function completed successfully.\r
\r
**/\r
-EFI_STATUS\r
-DiscardForm (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORM_BROWSER_FORM *Form,\r
- IN BOOLEAN SingleForm\r
+VOID\r
+SendDiscardInfoToDriver (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
)\r
{\r
- LIST_ENTRY *Link;\r
- FORMSET_STORAGE *Storage;\r
- FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+ EFI_IFR_TYPE_VALUE *TypeValue;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
\r
- if (SingleForm) {\r
- if (Form->NvUpdateRequired) {\r
- ConfigInfo = NULL;\r
- Link = GetFirstNode (&Form->ConfigRequestHead);\r
- while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
- ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
- Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+ if (FormSet->ConfigAccess == NULL) {\r
+ return;\r
+ }\r
\r
- if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
- continue;\r
- }\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
\r
- //\r
- // Skip if there is no RequestElement\r
- //\r
- if (ConfigInfo->ElementCount == 0) {\r
- continue;\r
- }\r
+ if ((Question->Storage == NULL) || (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+ continue;\r
+ }\r
\r
- //\r
- // Prepare <ConfigResp>\r
- //\r
- SynchronizeStorageForForm(FormSet, ConfigInfo, FALSE);\r
- }\r
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
+ continue;\r
+ }\r
\r
- Form->NvUpdateRequired = FALSE;\r
+ if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
+ continue;\r
}\r
- } else {\r
- if (IsNvUpdateRequired(FormSet)) {\r
- //\r
- // Discard Buffer storage or Name/Value storage\r
- //\r
- Link = GetFirstNode (&FormSet->StorageListHead);\r
- while (!IsNull (&FormSet->StorageListHead, Link)) {\r
- Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
- Link = GetNextNode (&FormSet->StorageListHead, Link);\r
\r
- if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
- continue;\r
- }\r
+ if (!Question->ValueChanged) {\r
+ continue;\r
+ }\r
\r
- //\r
- // Skip if there is no RequestElement\r
- //\r
- if (Storage->ElementCount == 0) {\r
- continue;\r
- }\r
+ //\r
+ // Restore the question value before call the CHANGED callback type.\r
+ //\r
+ GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
\r
- SynchronizeStorage(Storage, FALSE);\r
- }\r
+ if (Question->Operand == EFI_IFR_STRING_OP) {\r
+ HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16 *)Question->BufferValue, NULL);\r
+ }\r
\r
- UpdateNvInfoInForm(FormSet, FALSE); \r
+ if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
+ TypeValue = (EFI_IFR_TYPE_VALUE *)Question->BufferValue;\r
+ } else {\r
+ TypeValue = &Question->HiiValue.Value;\r
}\r
- }\r
\r
- return EFI_SUCCESS; \r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ FormSet->ConfigAccess->Callback (\r
+ FormSet->ConfigAccess,\r
+ EFI_BROWSER_ACTION_CHANGED,\r
+ Question->QuestionId,\r
+ Question->HiiValue.Type,\r
+ TypeValue,\r
+ &ActionRequest\r
+ );\r
+ }\r
}\r
\r
/**\r
- Submit data for form level or formset level.\r
+ When submit the question value, call the callback function with Submitted type\r
+ to inform the hii driver.\r
\r
@param FormSet FormSet data structure.\r
@param Form Form data structure.\r
- @param SingleForm whether submit for the single form or all form set.\r
-\r
- @retval EFI_SUCCESS The function completed successfully.\r
\r
**/\r
-EFI_STATUS\r
-SubmitForm (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORM_BROWSER_FORM *Form,\r
- IN BOOLEAN SingleForm\r
+VOID\r
+SubmitCallbackForForm (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
)\r
{\r
- EFI_STATUS Status;\r
- LIST_ENTRY *Link;\r
- EFI_STRING ConfigResp;\r
- EFI_STRING Progress;\r
- FORMSET_STORAGE *Storage;\r
- UINTN BufferSize;\r
- UINT8 *TmpBuf;\r
- FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+ EFI_IFR_TYPE_VALUE *TypeValue;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
\r
- //\r
- // Validate the Form by NoSubmit check\r
- //\r
- if (SingleForm) {\r
- Status = NoSubmitCheck (FormSet, Form);\r
- } else {\r
- Status = NoSubmitCheck (FormSet, NULL);\r
+ if (FormSet->ConfigAccess == NULL) {\r
+ return;\r
}\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+ if ((Question->Storage == NULL) || (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+ continue;\r
+ }\r
+\r
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
+ continue;\r
+ }\r
+\r
+ if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
+ continue;\r
+ }\r
+\r
+ if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
+ TypeValue = (EFI_IFR_TYPE_VALUE *)Question->BufferValue;\r
+ } else {\r
+ TypeValue = &Question->HiiValue.Value;\r
+ }\r
+\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ FormSet->ConfigAccess->Callback (\r
+ FormSet->ConfigAccess,\r
+ EFI_BROWSER_ACTION_SUBMITTED,\r
+ Question->QuestionId,\r
+ Question->HiiValue.Type,\r
+ TypeValue,\r
+ &ActionRequest\r
+ );\r
}\r
+}\r
\r
- if (SingleForm) {\r
- ConfigInfo = NULL;\r
- Link = GetFirstNode (&Form->ConfigRequestHead);\r
- while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
- ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
- Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+/**\r
+ When value set Success, call the submit callback function.\r
\r
- Storage = ConfigInfo->Storage;\r
- if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
- continue;\r
- }\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
\r
- //\r
- // Skip if there is no RequestElement\r
- //\r
- if (ConfigInfo->ElementCount == 0) {\r
- continue;\r
- }\r
+**/\r
+VOID\r
+SubmitCallback (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ FORM_BROWSER_FORM *CurrentForm;\r
+ LIST_ENTRY *Link;\r
\r
- //\r
- // 1. Prepare <ConfigResp>\r
- //\r
- Status = StorageToConfigResp (ConfigInfo, &ConfigResp, TRUE);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ if (Form != NULL) {\r
+ SubmitCallbackForForm (FormSet, Form);\r
+ return;\r
+ }\r
\r
- //\r
- // 2. Set value to hii driver or efi variable.\r
- //\r
- if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
- Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
- //\r
- // Send <ConfigResp> to Configuration Driver\r
- //\r
- if (FormSet->ConfigAccess != NULL) {\r
- Status = FormSet->ConfigAccess->RouteConfig (\r
- FormSet->ConfigAccess,\r
- ConfigResp,\r
- &Progress\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (ConfigResp);\r
- return Status;\r
- }\r
- }\r
- } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
- TmpBuf = NULL;\r
- TmpBuf = AllocateZeroPool(Storage->Size);\r
- if (TmpBuf == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- return Status;\r
- }\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
\r
- BufferSize = Storage->Size;\r
- Status = gRT->GetVariable (\r
- Storage->Name,\r
- &Storage->Guid,\r
- NULL,\r
- &BufferSize,\r
- TmpBuf\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (TmpBuf);\r
- FreePool (ConfigResp);\r
- return Status;\r
- }\r
- ASSERT (BufferSize == Storage->Size); \r
- Status = mHiiConfigRouting->ConfigToBlock (\r
- mHiiConfigRouting,\r
- ConfigResp,\r
- TmpBuf,\r
- &BufferSize,\r
- &Progress\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (TmpBuf);\r
- FreePool (ConfigResp);\r
- return Status;\r
- }\r
+ SubmitCallbackForForm (FormSet, CurrentForm);\r
+ }\r
+}\r
\r
- Status = gRT->SetVariable (\r
- Storage->Name,\r
- &Storage->Guid,\r
- Storage->Attributes,\r
- Storage->Size,\r
- TmpBuf\r
- );\r
- FreePool (TmpBuf);\r
- if (EFI_ERROR (Status)) {\r
- FreePool (ConfigResp);\r
- return Status;\r
- }\r
- }\r
- FreePool (ConfigResp);\r
- //\r
- // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
- //\r
- SynchronizeStorageForForm(FormSet, ConfigInfo, TRUE);\r
- }\r
+/**\r
+ Validate the HiiHandle.\r
\r
- //\r
- // 4. Update the NV flag.\r
- // \r
- Form->NvUpdateRequired = FALSE;\r
- } else {\r
- //\r
- // Submit Buffer storage or Name/Value storage\r
- //\r
- Link = GetFirstNode (&FormSet->StorageListHead);\r
- while (!IsNull (&FormSet->StorageListHead, Link)) {\r
- Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
- Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+ @param HiiHandle The input HiiHandle which need to validate.\r
\r
- if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
- continue;\r
- }\r
+ @retval TRUE The handle is validate.\r
+ @retval FALSE The handle is invalidate.\r
\r
- //\r
- // Skip if there is no RequestElement\r
- //\r
- if (Storage->ElementCount == 0) {\r
- continue;\r
- }\r
+**/\r
+BOOLEAN\r
+ValidateHiiHandle (\r
+ EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ EFI_HII_HANDLE *HiiHandles;\r
+ UINTN Index;\r
+ BOOLEAN Find;\r
\r
- //\r
- // 1. Prepare <ConfigResp>\r
- //\r
- Status = StorageToConfigResp (Storage, &ConfigResp, FALSE);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ if (HiiHandle == NULL) {\r
+ return FALSE;\r
+ }\r
\r
- if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
- Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ Find = FALSE;\r
\r
- //\r
- // 2. Send <ConfigResp> to Configuration Driver\r
- //\r
- if (FormSet->ConfigAccess != NULL) {\r
- Status = FormSet->ConfigAccess->RouteConfig (\r
- FormSet->ConfigAccess,\r
- ConfigResp,\r
- &Progress\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (ConfigResp);\r
- return Status;\r
- }\r
- }\r
- } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
- //\r
- // 1&2. Set the edit data to the variable.\r
- //\r
- TmpBuf = NULL;\r
- TmpBuf = AllocateZeroPool (Storage->Size);\r
- if (TmpBuf == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- return Status;\r
- } \r
- BufferSize = Storage->Size;\r
- Status = gRT->GetVariable (\r
- Storage->Name,\r
- &Storage->Guid,\r
- NULL,\r
- &BufferSize,\r
- TmpBuf\r
- );\r
- ASSERT (BufferSize == Storage->Size); \r
- Status = mHiiConfigRouting->ConfigToBlock (\r
- mHiiConfigRouting,\r
- ConfigResp,\r
- TmpBuf,\r
- &BufferSize,\r
- &Progress\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (TmpBuf);\r
- FreePool (ConfigResp);\r
- return Status;\r
- }\r
+ HiiHandles = HiiGetHiiHandles (NULL);\r
+ ASSERT (HiiHandles != NULL);\r
\r
- Status = gRT->SetVariable (\r
- Storage->Name,\r
- &Storage->Guid,\r
- Storage->Attributes,\r
- Storage->Size,\r
- TmpBuf\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (TmpBuf);\r
- FreePool (ConfigResp);\r
- return Status;\r
- }\r
- FreePool (TmpBuf);\r
- }\r
- FreePool (ConfigResp);\r
- //\r
- // 3. Config success, update storage shadow Buffer\r
- //\r
- SynchronizeStorage (Storage, TRUE);\r
+ for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
+ if (HiiHandles[Index] == HiiHandle) {\r
+ Find = TRUE;\r
+ break;\r
}\r
-\r
- //\r
- // 4. Update the NV flag.\r
- // \r
- UpdateNvInfoInForm(FormSet, FALSE);\r
}\r
\r
- return EFI_SUCCESS;\r
+ FreePool (HiiHandles);\r
+\r
+ return Find;\r
}\r
\r
/**\r
- Get Question default value from AltCfg string.\r
+ Validate the FormSet. If the formset is not validate, remove it from the list.\r
\r
- @param FormSet The form set.\r
- @param Question The question.\r
- @param DefaultId The default Id.\r
+ @param FormSet The input FormSet which need to validate.\r
\r
- @retval EFI_SUCCESS Question is reset to default value.\r
+ @retval TRUE The handle is validate.\r
+ @retval FALSE The handle is invalidate.\r
\r
**/\r
-EFI_STATUS\r
-GetDefaultValueFromAltCfg (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN OUT FORM_BROWSER_STATEMENT *Question,\r
- IN UINT16 DefaultId\r
+BOOLEAN\r
+ValidateFormSet (\r
+ FORM_BROWSER_FORMSET *FormSet\r
)\r
{\r
- BOOLEAN IsBufferStorage;\r
- BOOLEAN IsString; \r
- UINTN Length;\r
- FORMSET_STORAGE *Storage;\r
- CHAR16 *ConfigRequest;\r
- CHAR16 *Progress;\r
- CHAR16 *Result;\r
- CHAR16 *ConfigResp;\r
- CHAR16 *Value;\r
- CHAR16 *StringPtr;\r
- UINTN LengthStr;\r
- UINT8 *Dst;\r
- CHAR16 TemStr[5];\r
- UINTN Index;\r
- UINT8 DigitUint8;\r
- EFI_STATUS Status;\r
-\r
- Status = EFI_NOT_FOUND;\r
- Length = 0;\r
- Dst = NULL;\r
- ConfigRequest = NULL;\r
- Result = NULL;\r
- ConfigResp = NULL;\r
- Value = NULL;\r
- Storage = Question->Storage;\r
+ BOOLEAN Find;\r
\r
- if ((Storage == NULL) || \r
- (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) || \r
- (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
- return Status;\r
- }\r
+ ASSERT (FormSet != NULL);\r
\r
+ Find = ValidateHiiHandle (FormSet->HiiHandle);\r
//\r
- // Question Value is provided by Buffer Storage or NameValue Storage\r
+ // Should not remove the formset which is being used.\r
//\r
- if (Question->BufferValue != NULL) {\r
- //\r
- // This Question is password or orderedlist\r
- //\r
- Dst = Question->BufferValue;\r
- } else {\r
- //\r
- // Other type of Questions\r
- //\r
- Dst = (UINT8 *) &Question->HiiValue.Value;\r
+ if (!Find && (FormSet != gCurrentSelection->FormSet)) {\r
+ CleanBrowserStorage (FormSet);\r
+ RemoveEntryList (&FormSet->Link);\r
+ DestroyFormSet (FormSet);\r
}\r
\r
- IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
- IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
+ return Find;\r
+}\r
\r
- //\r
- // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
- // <ConfigHdr> + "&" + <VariableName>\r
- //\r
- if (IsBufferStorage) {\r
- Length = StrLen (Storage->ConfigHdr);\r
- Length += StrLen (Question->BlockName);\r
- } else {\r
- Length = StrLen (Storage->ConfigHdr);\r
- Length += StrLen (Question->VariableName) + 1;\r
- }\r
- ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
- ASSERT (ConfigRequest != NULL);\r
+/**\r
+ Check whether need to enable the reset flag in form level.\r
+ Also clean all ValueChanged flag in question.\r
\r
- StrCpy (ConfigRequest, Storage->ConfigHdr);\r
- if (IsBufferStorage) {\r
- StrCat (ConfigRequest, Question->BlockName);\r
- } else {\r
- StrCat (ConfigRequest, L"&");\r
- StrCat (ConfigRequest, Question->VariableName);\r
- }\r
+ @param SetFlag Whether need to set the Reset Flag.\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
\r
- Status = FormSet->ConfigAccess->ExtractConfig (\r
- FormSet->ConfigAccess,\r
- ConfigRequest,\r
- &Progress,\r
- &Result\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
+**/\r
+VOID\r
+UpdateFlagForForm (\r
+ IN BOOLEAN SetFlag,\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+ BOOLEAN OldValue;\r
\r
- //\r
- // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
- // Get the default configuration string according to the default ID.\r
- //\r
- Status = mHiiConfigRouting->GetAltConfig (\r
- mHiiConfigRouting,\r
- Result,\r
- &Storage->Guid,\r
- Storage->Name,\r
- NULL,\r
- &DefaultId, // it can be NULL to get the current setting.\r
- &ConfigResp\r
- );\r
- \r
- //\r
- // The required setting can't be found. So, it is not required to be validated and set.\r
- //\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
\r
- //\r
- // Skip <ConfigRequest>\r
- //\r
- if (IsBufferStorage) {\r
- Value = StrStr (ConfigResp, L"&VALUE");\r
- ASSERT (Value != NULL);\r
- //\r
- // Skip "&VALUE"\r
- //\r
- Value = Value + 6;\r
- } else {\r
- Value = StrStr (ConfigResp, Question->VariableName);\r
- ASSERT (Value != NULL);\r
+ if (!Question->ValueChanged) {\r
+ continue;\r
+ }\r
\r
- Value = Value + StrLen (Question->VariableName);\r
- }\r
- if (*Value != '=') {\r
- Status = EFI_NOT_FOUND;\r
- goto Done;\r
- }\r
- //\r
- // Skip '=', point to value\r
- //\r
- Value = Value + 1;\r
+ OldValue = Question->ValueChanged;\r
\r
- //\r
- // Suppress <AltResp> if any\r
- //\r
- StringPtr = Value;\r
- while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
- StringPtr++;\r
- }\r
- *StringPtr = L'\0';\r
+ //\r
+ // Compare the buffer and editbuffer data to see whether the data has been saved.\r
+ //\r
+ Question->ValueChanged = IsQuestionValueChanged (FormSet, Form, Question, GetSetValueWithBothBuffer);\r
\r
- LengthStr = StrLen (Value);\r
- if (!IsBufferStorage && IsString) {\r
- StringPtr = (CHAR16 *) Dst;\r
- ZeroMem (TemStr, sizeof (TemStr));\r
- for (Index = 0; Index < LengthStr; Index += 4) {\r
- StrnCpy (TemStr, Value + Index, 4);\r
- StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
- }\r
//\r
- // Add tailing L'\0' character\r
+ // Only the changed data has been saved, then need to set the reset flag.\r
//\r
- StringPtr[Index/4] = L'\0';\r
- } else {\r
- ZeroMem (TemStr, sizeof (TemStr));\r
- for (Index = 0; Index < LengthStr; Index ++) {\r
- TemStr[0] = Value[LengthStr - Index - 1];\r
- DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
- if ((Index & 1) == 0) {\r
- Dst [Index/2] = DigitUint8;\r
- } else {\r
- Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
+ if (SetFlag && OldValue && !Question->ValueChanged) {\r
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0) {\r
+ gResetRequiredFormLevel = TRUE;\r
+ gResetRequiredSystemLevel = TRUE;\r
}\r
- }\r
- }\r
-\r
-Done:\r
- if (ConfigRequest != NULL){\r
- FreePool (ConfigRequest);\r
- }\r
\r
- if (ConfigResp != NULL) {\r
- FreePool (ConfigResp);\r
- }\r
- \r
- if (Result != NULL) {\r
- FreePool (Result);\r
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_RECONNECT_REQUIRED) != 0) {\r
+ gFlagReconnect = TRUE;\r
+ }\r
+ }\r
}\r
-\r
- return Status;\r
}\r
\r
/**\r
- Get default Id value used for browser.\r
+ Check whether need to enable the reset flag.\r
+ Also clean ValueChanged flag for all statements.\r
\r
- @param DefaultId The default id value used by hii.\r
+ Form level or formset level, only one.\r
\r
- @retval Browser used default value.\r
+ @param SetFlag Whether need to set the Reset Flag.\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
\r
**/\r
-INTN\r
-GetDefaultIdForCallBack (\r
- UINTN DefaultId\r
+VOID\r
+ValueChangeResetFlagUpdate (\r
+ IN BOOLEAN SetFlag,\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
)\r
-{ \r
- if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
- return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
- } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
- return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
- } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
- return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
- } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {\r
- return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
- } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {\r
- return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
- } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {\r
- return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
- } else {\r
- return -1;\r
+{\r
+ FORM_BROWSER_FORM *CurrentForm;\r
+ LIST_ENTRY *Link;\r
+\r
+ if (Form != NULL) {\r
+ UpdateFlagForForm (SetFlag, FormSet, Form);\r
+ return;\r
+ }\r
+\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+\r
+ UpdateFlagForForm (SetFlag, FormSet, CurrentForm);\r
}\r
}\r
\r
/**\r
- Reset Question to its default value.\r
+ Base on the return Progress string to find the form.\r
\r
- @param FormSet The form set.\r
- @param Form The form.\r
- @param Question The question.\r
- @param DefaultId The Class of the default.\r
+ Base on the first return Offset/Width (Name) string to find the form\r
+ which keep this string.\r
\r
- @retval EFI_SUCCESS Question is reset to default value.\r
+ @param FormSet FormSet data structure.\r
+ @param Storage Storage which has this Progress string.\r
+ @param Progress The Progress string which has the first fail string.\r
+ @param RetForm The return form for this progress string.\r
+ @param RetQuestion The return question for the error progress string.\r
+\r
+ @retval TRUE Find the error form and statement for this error progress string.\r
+ @retval FALSE Not find the error form.\r
\r
**/\r
-EFI_STATUS\r
-GetQuestionDefault (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORM_BROWSER_FORM *Form,\r
- IN FORM_BROWSER_STATEMENT *Question,\r
- IN UINT16 DefaultId\r
+BOOLEAN\r
+FindQuestionFromProgress (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN BROWSER_STORAGE *Storage,\r
+ IN EFI_STRING Progress,\r
+ OUT FORM_BROWSER_FORM **RetForm,\r
+ OUT FORM_BROWSER_STATEMENT **RetQuestion\r
)\r
{\r
- EFI_STATUS Status;\r
- LIST_ENTRY *Link;\r
- QUESTION_DEFAULT *Default;\r
- QUESTION_OPTION *Option;\r
- EFI_HII_VALUE *HiiValue;\r
- UINT8 Index;\r
- EFI_STRING StrValue;\r
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
- EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
- INTN Action;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *LinkStorage;\r
+ LIST_ENTRY *LinkStatement;\r
+ FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
+ FORM_BROWSER_FORM *Form;\r
+ EFI_STRING EndStr;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
\r
- Status = EFI_SUCCESS;\r
- StrValue = NULL;\r
+ ASSERT ((*Progress == '&') || (*Progress == 'G'));\r
\r
- //\r
- // Statement don't have storage, skip them\r
- //\r
- if (Question->QuestionId == 0) {\r
- return Status;\r
- }\r
+ ConfigInfo = NULL;\r
+ *RetForm = NULL;\r
+ *RetQuestion = NULL;\r
\r
//\r
- // There are Five ways to specify default value for a Question:\r
- // 1, use call back function (highest priority)\r
- // 2, use ExtractConfig function\r
- // 3, use nested EFI_IFR_DEFAULT \r
- // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
- // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
+ // Skip the first "&" or the ConfigHdr part.\r
//\r
- HiiValue = &Question->HiiValue;\r
+ if (*Progress == '&') {\r
+ Progress++;\r
+ } else {\r
+ //\r
+ // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
+ //\r
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // For Name/Value type, Skip the ConfigHdr part.\r
+ //\r
+ EndStr = StrStr (Progress, L"PATH=");\r
+ ASSERT (EndStr != NULL);\r
+ while (*EndStr != '&') {\r
+ EndStr++;\r
+ }\r
\r
- //\r
- // Get Question defaut value from call back function.\r
- //\r
- ConfigAccess = FormSet->ConfigAccess;\r
- Action = GetDefaultIdForCallBack (DefaultId);\r
- if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
- ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
- Status = ConfigAccess->Callback (\r
- ConfigAccess,\r
- Action,\r
- Question->QuestionId,\r
- HiiValue->Type,\r
- &HiiValue->Value,\r
- &ActionRequest\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- return Status;\r
+ *EndStr = '\0';\r
+ } else {\r
+ //\r
+ // For Buffer type, Skip the ConfigHdr part.\r
+ //\r
+ EndStr = StrStr (Progress, L"&OFFSET=");\r
+ ASSERT (EndStr != NULL);\r
+ *EndStr = '\0';\r
}\r
+\r
+ Progress = EndStr + 1;\r
}\r
\r
//\r
- // Get default value from altcfg string.\r
+ // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
//\r
- if (ConfigAccess != NULL) { \r
- Status = GetDefaultValueFromAltCfg(FormSet, Question, DefaultId);\r
- if (!EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,\r
+ // here, just keep the "Fred" string.\r
+ //\r
+ EndStr = StrStr (Progress, L"=");\r
+ ASSERT (EndStr != NULL);\r
+ *EndStr = '\0';\r
+ } else {\r
+ //\r
+ // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",\r
+ // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.\r
+ //\r
+ EndStr = StrStr (Progress, L"&VALUE=");\r
+ ASSERT (EndStr != NULL);\r
+ *EndStr = '\0';\r
}\r
\r
//\r
- // EFI_IFR_DEFAULT has highest priority\r
+ // Search in the form list.\r
//\r
- if (!IsListEmpty (&Question->DefaultListHead)) {\r
- Link = GetFirstNode (&Question->DefaultListHead);\r
- while (!IsNull (&Question->DefaultListHead, Link)) {\r
- Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
\r
- if (Default->DefaultId == DefaultId) {\r
- if (Default->ValueExpression != NULL) {\r
- //\r
- // Default is provided by an Expression, evaluate it\r
- //\r
- Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ //\r
+ // Search in the ConfigReqeust list in this form.\r
+ //\r
+ LinkStorage = GetFirstNode (&Form->ConfigRequestHead);\r
+ while (!IsNull (&Form->ConfigRequestHead, LinkStorage)) {\r
+ ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage);\r
+ LinkStorage = GetNextNode (&Form->ConfigRequestHead, LinkStorage);\r
\r
- CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
- } else {\r
- //\r
- // Default value is embedded in EFI_IFR_DEFAULT\r
- //\r
- CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
- }\r
+ if (Storage != ConfigInfo->Storage) {\r
+ continue;\r
+ }\r
\r
- if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
- StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
- if (StrValue == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
- Question->BufferValue = AllocateCopyPool (StrSize (StrValue), StrValue);\r
+ if (StrStr (ConfigInfo->ConfigRequest, Progress) != NULL) {\r
+ //\r
+ // Find the OffsetWidth string in this form.\r
+ //\r
+ *RetForm = Form;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (*RetForm != NULL) {\r
+ LinkStatement = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, LinkStatement)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);\r
+ LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);\r
+\r
+ if ((Statement->BlockName != NULL) && (StrStr (Statement->BlockName, Progress) != NULL)) {\r
+ *RetQuestion = Statement;\r
+ break;\r
}\r
\r
- return EFI_SUCCESS;\r
+ if ((Statement->VariableName != NULL) && (StrStr (Statement->VariableName, Progress) != NULL)) {\r
+ *RetQuestion = Statement;\r
+ break;\r
+ }\r
}\r
+ }\r
\r
- Link = GetNextNode (&Question->DefaultListHead, Link);\r
+ if (*RetForm != NULL) {\r
+ break;\r
}\r
}\r
\r
//\r
- // EFI_ONE_OF_OPTION\r
+ // restore the OffsetWidth string to the original format.\r
//\r
- if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
- if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
- //\r
- // OneOfOption could only provide Standard and Manufacturing default\r
- //\r
- Link = GetFirstNode (&Question->OptionListHead);\r
- while (!IsNull (&Question->OptionListHead, Link)) {\r
- Option = QUESTION_OPTION_FROM_LINK (Link);\r
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ *EndStr = '=';\r
+ } else {\r
+ *EndStr = '&';\r
+ }\r
\r
- if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
- ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
- ) {\r
- CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+ return (BOOLEAN)(*RetForm != NULL);\r
+}\r
\r
- return EFI_SUCCESS;\r
- }\r
+/**\r
+ Base on the return Progress string to get the SyncConfigRequest and RestoreConfigRequest\r
+ for form and formset.\r
\r
- Link = GetNextNode (&Question->OptionListHead, Link);\r
- }\r
- }\r
- }\r
+ @param Storage Storage which has this Progress string.\r
+ @param ConfigRequest The ConfigRequest string.\r
+ @param Progress The Progress string which has the first fail string.\r
+ @param RestoreConfigRequest Return the RestoreConfigRequest string.\r
+ @param SyncConfigRequest Return the SyncConfigRequest string.\r
\r
+**/\r
+VOID\r
+GetSyncRestoreConfigRequest (\r
+ IN BROWSER_STORAGE *Storage,\r
+ IN EFI_STRING ConfigRequest,\r
+ IN EFI_STRING Progress,\r
+ OUT EFI_STRING *RestoreConfigRequest,\r
+ OUT EFI_STRING *SyncConfigRequest\r
+ )\r
+{\r
+ EFI_STRING EndStr;\r
+ EFI_STRING ConfigHdrEndStr;\r
+ EFI_STRING ElementStr;\r
+ UINTN TotalSize;\r
+ UINTN RestoreEleSize;\r
+ UINTN SyncSize;\r
+\r
+ ASSERT ((*Progress == L'&') || (*Progress == L'G'));\r
//\r
- // EFI_IFR_CHECKBOX - lowest priority\r
+ // If the Progress starts with ConfigHdr, means the failure is in the first name / value pair.\r
+ // Need to restore all the fields in the ConfigRequest.\r
//\r
- if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
- if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
- //\r
- // Checkbox could only provide Standard and Manufacturing default\r
- //\r
- if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
- ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
- ) {\r
- HiiValue->Value.b = TRUE;\r
- } else {\r
- HiiValue->Value.b = FALSE;\r
- }\r
-\r
- return EFI_SUCCESS;\r
- }\r
+ if (*Progress == L'G') {\r
+ *RestoreConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
+ ASSERT (*RestoreConfigRequest != NULL);\r
+ return;\r
}\r
\r
//\r
- // For Questions without default\r
+ // Find the first fail "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
//\r
- switch (Question->Operand) {\r
- case EFI_IFR_NUMERIC_OP:\r
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
//\r
- // Take minimum value as numeric default value\r
+ // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,\r
+ // here, just keep the "Fred" string.\r
//\r
- if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
- HiiValue->Value.u64 = Question->Minimum;\r
- }\r
- break;\r
-\r
- case EFI_IFR_ONE_OF_OP:\r
+ EndStr = StrStr (Progress, L"=");\r
+ ASSERT (EndStr != NULL);\r
+ *EndStr = L'\0';\r
//\r
- // Take first oneof option as oneof's default value\r
+ // Find the ConfigHdr in ConfigRequest.\r
//\r
- if (ValueToOption (Question, HiiValue) == NULL) {\r
- Link = GetFirstNode (&Question->OptionListHead);\r
- if (!IsNull (&Question->OptionListHead, Link)) {\r
- Option = QUESTION_OPTION_FROM_LINK (Link);\r
- CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
- }\r
+ ConfigHdrEndStr = StrStr (ConfigRequest, L"PATH=");\r
+ ASSERT (ConfigHdrEndStr != NULL);\r
+ while (*ConfigHdrEndStr != L'&') {\r
+ ConfigHdrEndStr++;\r
}\r
- break;\r
-\r
- case EFI_IFR_ORDERED_LIST_OP:\r
+ } else {\r
//\r
- // Take option sequence in IFR as ordered list's default value\r
+ // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",\r
+ // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.\r
//\r
- Index = 0;\r
- Link = GetFirstNode (&Question->OptionListHead);\r
- while (!IsNull (&Question->OptionListHead, Link)) {\r
- Option = QUESTION_OPTION_FROM_LINK (Link);\r
-\r
- SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
-\r
- Index++;\r
- if (Index >= Question->MaxContainers) {\r
- break;\r
- }\r
-\r
- Link = GetNextNode (&Question->OptionListHead, Link);\r
- }\r
- break;\r
-\r
- default:\r
- Status = EFI_NOT_FOUND;\r
- break;\r
+ EndStr = StrStr (Progress, L"&VALUE=");\r
+ ASSERT (EndStr != NULL);\r
+ *EndStr = L'\0';\r
+ //\r
+ // Find the ConfigHdr in ConfigRequest.\r
+ //\r
+ ConfigHdrEndStr = StrStr (ConfigRequest, L"&OFFSET=");\r
}\r
\r
- return Status;\r
+ //\r
+ // Find the first fail pair in the ConfigRequest.\r
+ //\r
+ ElementStr = StrStr (ConfigRequest, Progress);\r
+ ASSERT (ElementStr != NULL);\r
+ //\r
+ // To get the RestoreConfigRequest.\r
+ //\r
+ RestoreEleSize = StrSize (ElementStr);\r
+ TotalSize = (ConfigHdrEndStr - ConfigRequest) * sizeof (CHAR16) + RestoreEleSize + sizeof (CHAR16);\r
+ *RestoreConfigRequest = AllocateZeroPool (TotalSize);\r
+ ASSERT (*RestoreConfigRequest != NULL);\r
+ StrnCpyS (*RestoreConfigRequest, TotalSize / sizeof (CHAR16), ConfigRequest, ConfigHdrEndStr - ConfigRequest);\r
+ StrCatS (*RestoreConfigRequest, TotalSize / sizeof (CHAR16), ElementStr);\r
+ //\r
+ // To get the SyncConfigRequest.\r
+ //\r
+ SyncSize = StrSize (ConfigRequest) - RestoreEleSize + sizeof (CHAR16);\r
+ *SyncConfigRequest = AllocateZeroPool (SyncSize);\r
+ ASSERT (*SyncConfigRequest != NULL);\r
+ StrnCpyS (*SyncConfigRequest, SyncSize / sizeof (CHAR16), ConfigRequest, SyncSize / sizeof (CHAR16) - 1);\r
+\r
+ //\r
+ // restore the Progress string to the original format.\r
+ //\r
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ *EndStr = L'=';\r
+ } else {\r
+ *EndStr = L'&';\r
+ }\r
+}\r
+\r
+/**\r
+ Popup an save error info and get user input.\r
+\r
+ @param TitleId The form title id.\r
+ @param HiiHandle The hii handle for this package.\r
+\r
+ @retval UINT32 The user select option for the save fail.\r
+ BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
+**/\r
+UINT32\r
+ConfirmSaveFail (\r
+ IN EFI_STRING_ID TitleId,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ CHAR16 *FormTitle;\r
+ CHAR16 *StringBuffer;\r
+ UINT32 RetVal;\r
+\r
+ FormTitle = GetToken (TitleId, HiiHandle);\r
+\r
+ StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
+ ASSERT (StringBuffer != NULL);\r
+\r
+ UnicodeSPrint (\r
+ StringBuffer,\r
+ 24 * sizeof (CHAR16) + StrSize (FormTitle),\r
+ L"Submit Fail For Form: %s.",\r
+ FormTitle\r
+ );\r
+\r
+ RetVal = PopupErrorMessage (BROWSER_SUBMIT_FAIL, NULL, NULL, StringBuffer);\r
+\r
+ FreePool (StringBuffer);\r
+ FreePool (FormTitle);\r
+\r
+ return RetVal;\r
}\r
\r
+/**\r
+ Popup an NO_SUBMIT_IF error info and get user input.\r
+\r
+ @param TitleId The form title id.\r
+ @param HiiHandle The hii handle for this package.\r
+\r
+ @retval UINT32 The user select option for the save fail.\r
+ BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
+**/\r
+UINT32\r
+ConfirmNoSubmitFail (\r
+ IN EFI_STRING_ID TitleId,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ CHAR16 *FormTitle;\r
+ CHAR16 *StringBuffer;\r
+ UINT32 RetVal;\r
+\r
+ FormTitle = GetToken (TitleId, HiiHandle);\r
+\r
+ StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
+ ASSERT (StringBuffer != NULL);\r
+\r
+ UnicodeSPrint (\r
+ StringBuffer,\r
+ 24 * sizeof (CHAR16) + StrSize (FormTitle),\r
+ L"NO_SUBMIT_IF error For Form: %s.",\r
+ FormTitle\r
+ );\r
+\r
+ RetVal = PopupErrorMessage (BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF, NULL, NULL, StringBuffer);\r
+\r
+ FreePool (StringBuffer);\r
+ FreePool (FormTitle);\r
+\r
+ return RetVal;\r
+}\r
\r
/**\r
- Reset Questions in a Formset to their default value.\r
+ Discard data based on the input setting scope (Form, FormSet or System).\r
\r
@param FormSet FormSet data structure.\r
- @param DefaultId The Class of the default.\r
+ @param Form Form data structure.\r
+ @param SettingScope Setting Scope for Discard action.\r
\r
@retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
\r
**/\r
EFI_STATUS\r
-ExtractFormSetDefault (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN UINT16 DefaultId\r
+DiscardForm (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN BROWSER_SETTING_SCOPE SettingScope\r
)\r
{\r
- EFI_STATUS Status;\r
- LIST_ENTRY *FormLink;\r
- LIST_ENTRY *StatementLink;\r
- FORM_BROWSER_STATEMENT *Question;\r
- FORM_BROWSER_FORM *Form;\r
+ LIST_ENTRY *Link;\r
+ FORMSET_STORAGE *Storage;\r
+ FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
+ FORM_BROWSER_FORMSET *LocalFormSet;\r
+ FORM_BROWSER_FORMSET *OldFormSet;\r
\r
- FormLink = GetFirstNode (&FormSet->FormListHead);\r
- while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
- Form = FORM_BROWSER_FORM_FROM_LINK (FormLink); \r
- \r
- //\r
- // Extract Form default\r
- //\r
- StatementLink = GetFirstNode (&Form->StatementListHead);\r
- while (!IsNull (&Form->StatementListHead, StatementLink)) {\r
- Question = FORM_BROWSER_STATEMENT_FROM_LINK (StatementLink);\r
- StatementLink = GetNextNode (&Form->StatementListHead, StatementLink);\r
+ //\r
+ // Check the supported setting level.\r
+ //\r
+ if (SettingScope >= MaxLevel) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if ((SettingScope == FormLevel) && IsNvUpdateRequiredForForm (Form)) {\r
+ ConfigInfo = NULL;\r
+ Link = GetFirstNode (&Form->ConfigRequestHead);\r
+ while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+ ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+ if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ continue;\r
+ }\r
\r
//\r
- // If Question is disabled, don't reset it to default\r
+ // Skip if there is no RequestElement\r
//\r
- if (Question->DisableExpression != NULL) {\r
- Status = EvaluateExpression (FormSet, Form, Question->DisableExpression);\r
- if (!EFI_ERROR (Status) && Question->DisableExpression->Result.Value.b) {\r
- continue;\r
- }\r
+ if (ConfigInfo->ElementCount == 0) {\r
+ continue;\r
}\r
\r
//\r
- // Reset Question to its default value\r
+ // Prepare <ConfigResp>\r
//\r
- Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
- if (EFI_ERROR (Status)) {\r
+ SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
+\r
+ //\r
+ // Call callback with Changed type to inform the driver.\r
+ //\r
+ SendDiscardInfoToDriver (FormSet, Form);\r
+ }\r
+\r
+ ValueChangeResetFlagUpdate (FALSE, FormSet, Form);\r
+ } else if ((SettingScope == FormSetLevel) && IsNvUpdateRequiredForFormSet (FormSet)) {\r
+ //\r
+ // Discard Buffer storage or Name/Value storage\r
+ //\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+ if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
continue;\r
}\r
\r
//\r
- // Synchronize Buffer storage's Edit buffer\r
+ // Skip if there is no RequestElement\r
//\r
- if ((Question->Storage != NULL) &&\r
- (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
- SetQuestionValue (FormSet, Form, Question, TRUE);\r
+ if (Storage->ElementCount == 0) {\r
+ continue;\r
+ }\r
+\r
+ SynchronizeStorage (Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
+ }\r
+\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+\r
+ //\r
+ // Call callback with Changed type to inform the driver.\r
+ //\r
+ SendDiscardInfoToDriver (FormSet, Form);\r
+ }\r
+\r
+ ValueChangeResetFlagUpdate (FALSE, FormSet, NULL);\r
+ } else if (SettingScope == SystemLevel) {\r
+ //\r
+ // System Level Discard.\r
+ //\r
+ OldFormSet = mSystemLevelFormSet;\r
+\r
+ //\r
+ // Discard changed value for each FormSet in the maintain list.\r
+ //\r
+ Link = GetFirstNode (&gBrowserFormSetList);\r
+ while (!IsNull (&gBrowserFormSetList, Link)) {\r
+ LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+ Link = GetNextNode (&gBrowserFormSetList, Link);\r
+ if (!ValidateFormSet (LocalFormSet)) {\r
+ continue;\r
+ }\r
+\r
+ mSystemLevelFormSet = LocalFormSet;\r
+\r
+ DiscardForm (LocalFormSet, NULL, FormSetLevel);\r
+ if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
+ //\r
+ // Remove maintain backup list after discard except for the current using FormSet.\r
+ //\r
+ CleanBrowserStorage (LocalFormSet);\r
+ RemoveEntryList (&LocalFormSet->Link);\r
+ DestroyFormSet (LocalFormSet);\r
}\r
}\r
- FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
+\r
+ mSystemLevelFormSet = OldFormSet;\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
- Initialize Question's Edit copy from Storage.\r
+ Submit data for a form.\r
\r
- @param Selection Selection contains the information about \r
- the Selection, form and formset to be displayed.\r
- Selection action may be updated in retrieve callback.\r
@param FormSet FormSet data structure.\r
@param Form Form data structure.\r
\r
@retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
\r
**/\r
EFI_STATUS\r
-LoadFormConfig (\r
- IN OUT UI_MENU_SELECTION *Selection,\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORM_BROWSER_FORM *Form\r
+SubmitForForm (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
)\r
{\r
- EFI_STATUS Status;\r
- LIST_ENTRY *Link;\r
- FORM_BROWSER_STATEMENT *Question;\r
- UINT8 *BufferValue;\r
- UINTN StorageWidth;\r
- \r
- Link = GetFirstNode (&Form->StatementListHead);\r
- while (!IsNull (&Form->StatementListHead, Link)) {\r
- Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ EFI_STRING ConfigResp;\r
+ EFI_STRING Progress;\r
+ BROWSER_STORAGE *Storage;\r
+ FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
+ BOOLEAN SubmitFormFail;\r
+\r
+ SubmitFormFail = FALSE;\r
+\r
+ if (!IsNvUpdateRequiredForForm (Form)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = NoSubmitCheck (FormSet, &Form, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Link = GetFirstNode (&Form->ConfigRequestHead);\r
+ while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+ ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+ Storage = ConfigInfo->Storage;\r
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ continue;\r
+ }\r
\r
//\r
- // Initialize local copy of Value for each Question\r
+ // Skip if there is no RequestElement\r
+ //\r
+ if (ConfigInfo->ElementCount == 0) {\r
+ continue;\r
+ }\r
+\r
//\r
- Status = GetQuestionValue (FormSet, Form, Question, TRUE);\r
+ // 1. Prepare <ConfigResp>\r
+ //\r
+ Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
- HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
+ //\r
+ // 2. Set value to hii config routine protocol.\r
+ //\r
+ Status = mHiiConfigRouting->RouteConfig (\r
+ mHiiConfigRouting,\r
+ ConfigResp,\r
+ &Progress\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.\r
+ //\r
+ SubmitFormFail = TRUE;\r
+ GetSyncRestoreConfigRequest (ConfigInfo->Storage, ConfigInfo->ConfigRequest, Progress, &ConfigInfo->RestoreConfigRequest, &ConfigInfo->SyncConfigRequest);\r
+ InsertTailList (&gBrowserSaveFailFormSetList, &ConfigInfo->SaveFailLink);\r
+ FreePool (ConfigResp);\r
+ continue;\r
}\r
\r
+ FreePool (ConfigResp);\r
//\r
- // According the spec, ref opcode try to get value from call back with "retrieve" type.\r
+ // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
//\r
- if ((Question->Operand == EFI_IFR_REF_OP) && (FormSet->ConfigAccess != NULL)) {\r
- Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);\r
+ }\r
+\r
+ //\r
+ // 4. Process the save failed storage.\r
+ //\r
+ if (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
+ if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
+ Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
+ while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
+ ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
+ Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
+ //\r
+ // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer\r
+ // base on the SyncConfigRequest to Sync the buffer.\r
+ //\r
+ SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->RestoreConfigRequest, FALSE);\r
+ FreePool (ConfigInfo->RestoreConfigRequest);\r
+ ConfigInfo->RestoreConfigRequest = NULL;\r
+ if (ConfigInfo->SyncConfigRequest != NULL) {\r
+ SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->SyncConfigRequest, TRUE);\r
+ FreePool (ConfigInfo->SyncConfigRequest);\r
+ ConfigInfo->SyncConfigRequest = NULL;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
}\r
+\r
+ SendDiscardInfoToDriver (FormSet, Form);\r
+ } else {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Free Form save fail list.\r
+ //\r
+ while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
+ Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
+ ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
+ RemoveEntryList (&ConfigInfo->SaveFailLink);\r
+ }\r
+ }\r
+\r
+ //\r
+ // 5. Update the NV flag.\r
+ //\r
+ ValueChangeResetFlagUpdate (TRUE, FormSet, Form);\r
+\r
+ //\r
+ // 6 Call callback with Submitted type to inform the driver.\r
+ //\r
+ if (!SubmitFormFail) {\r
+ SubmitCallback (FormSet, Form);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Submit data for a formset.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param SkipProcessFail Whether skip to process the save failed storage.\r
+ If submit formset is called when do system level save,\r
+ set this value to true and process the failed formset\r
+ together.\r
+ if submit formset is called when do formset level save,\r
+ set the value to false and process the failed storage\r
+ right after process all storages for this formset.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForFormSet (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN BOOLEAN SkipProcessFail\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ EFI_STRING ConfigResp;\r
+ EFI_STRING Progress;\r
+ BROWSER_STORAGE *Storage;\r
+ FORMSET_STORAGE *FormSetStorage;\r
+ FORM_BROWSER_FORM *Form;\r
+ BOOLEAN HasInserted;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+ BOOLEAN SubmitFormSetFail;\r
+ BOOLEAN DiscardChange;\r
+\r
+ HasInserted = FALSE;\r
+ SubmitFormSetFail = FALSE;\r
+ DiscardChange = FALSE;\r
+\r
+ if (!IsNvUpdateRequiredForFormSet (FormSet)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Form = NULL;\r
+ Status = NoSubmitCheck (FormSet, &Form, &Question);\r
+ if (EFI_ERROR (Status)) {\r
+ if (SkipProcessFail) {\r
+ //\r
+ // Process NO_SUBMIT check first, so insert it at head.\r
+ //\r
+ FormSet->SaveFailForm = Form;\r
+ FormSet->SaveFailStatement = Question;\r
+ InsertHeadList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
+ }\r
+\r
+ return Status;\r
+ }\r
+\r
+ Form = NULL;\r
+ Question = NULL;\r
+ //\r
+ // Submit Buffer storage or Name/Value storage\r
+ //\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+ Storage = FormSetStorage->BrowserStorage;\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Skip if there is no RequestElement\r
+ //\r
+ if (FormSetStorage->ElementCount == 0) {\r
+ continue;\r
}\r
\r
//\r
- // Check whether EfiVarstore with CallBack can be got.\r
+ // 1. Prepare <ConfigResp>\r
//\r
- if ((FormSet->ConfigAccess != NULL) &&\r
- (Selection->Action != UI_ACTION_REFRESH_FORMSET) &&\r
- (Question->QuestionId != 0) && \r
- (Question->Storage != NULL) &&\r
- (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) && \r
- ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {\r
+ Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
+ //\r
+ // 2. Send <ConfigResp> to Routine config Protocol.\r
+ //\r
+ Status = mHiiConfigRouting->RouteConfig (\r
+ mHiiConfigRouting,\r
+ ConfigResp,\r
+ &Progress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
//\r
- // Check QuestionValue does exist.\r
+ // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.\r
//\r
- StorageWidth = Question->StorageWidth;\r
- if (Question->BufferValue != NULL) {\r
- BufferValue = Question->BufferValue;\r
- } else {\r
- BufferValue = (UINT8 *) &Question->HiiValue.Value;\r
- }\r
- Status = gRT->GetVariable (\r
- Question->VariableName,\r
- &Question->Storage->Guid,\r
- NULL,\r
- &StorageWidth,\r
- BufferValue\r
- );\r
+ SubmitFormSetFail = TRUE;\r
+ GetSyncRestoreConfigRequest (FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, Progress, &FormSetStorage->RestoreConfigRequest, &FormSetStorage->SyncConfigRequest);\r
+ InsertTailList (&FormSet->SaveFailStorageListHead, &FormSetStorage->SaveFailLink);\r
+ if (!HasInserted) {\r
+ //\r
+ // Call submit formset for system level, save the formset info\r
+ // and process later.\r
+ //\r
+ FindQuestionFromProgress (FormSet, Storage, Progress, &Form, &Question);\r
+ ASSERT (Form != NULL && Question != NULL);\r
+ FormSet->SaveFailForm = Form;\r
+ FormSet->SaveFailStatement = Question;\r
+ if (SkipProcessFail) {\r
+ InsertTailList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
+ }\r
\r
- if (!EFI_ERROR (Status)) {\r
- Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
+ HasInserted = TRUE;\r
}\r
+\r
+ FreePool (ConfigResp);\r
+ continue;\r
}\r
\r
- Link = GetNextNode (&Form->StatementListHead, Link);\r
+ FreePool (ConfigResp);\r
+ //\r
+ // 3. Config success, update storage shadow Buffer\r
+ //\r
+ SynchronizeStorage (Storage, FormSetStorage->ConfigRequest, TRUE);\r
+ }\r
+\r
+ //\r
+ // 4. Has save fail storage need to handle.\r
+ //\r
+ if (Form != NULL) {\r
+ if (!SkipProcessFail) {\r
+ //\r
+ // If not in system level, just handl the save failed storage here.\r
+ //\r
+ if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
+ DiscardChange = TRUE;\r
+ Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
+ while (!IsNull (&FormSet->SaveFailStorageListHead, Link)) {\r
+ FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
+ Storage = FormSetStorage->BrowserStorage;\r
+ Link = GetNextNode (&FormSet->SaveFailStorageListHead, Link);\r
+ //\r
+ // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer\r
+ // base on the SyncConfigRequest to Sync the buffer.\r
+ //\r
+ SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->RestoreConfigRequest, FALSE);\r
+ FreePool (FormSetStorage->RestoreConfigRequest);\r
+ FormSetStorage->RestoreConfigRequest = NULL;\r
+ if (FormSetStorage->SyncConfigRequest != NULL) {\r
+ SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->SyncConfigRequest, TRUE);\r
+ FreePool (FormSetStorage->SyncConfigRequest);\r
+ FormSetStorage->SyncConfigRequest = NULL;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ } else {\r
+ UiCopyMenuList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
+\r
+ gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ gCurrentSelection->Handle = FormSet->HiiHandle;\r
+ CopyGuid (&gCurrentSelection->FormSetGuid, &FormSet->Guid);\r
+ gCurrentSelection->FormId = Form->FormId;\r
+ gCurrentSelection->QuestionId = Question->QuestionId;\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Free FormSet save fail list.\r
+ //\r
+ while (!IsListEmpty (&FormSet->SaveFailStorageListHead)) {\r
+ Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
+ FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
+ RemoveEntryList (&FormSetStorage->SaveFailLink);\r
+ }\r
+ } else {\r
+ //\r
+ // If in system level, just return error and handle the failed formset later.\r
+ //\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If user discard the change, send the discard info to driver.\r
+ //\r
+ if (DiscardChange) {\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+ //\r
+ // Call callback with Changed type to inform the driver.\r
+ //\r
+ SendDiscardInfoToDriver (FormSet, Form);\r
+ }\r
+ }\r
+\r
+ //\r
+ // 5. Update the NV flag.\r
+ //\r
+ ValueChangeResetFlagUpdate (TRUE, FormSet, NULL);\r
+\r
+ //\r
+ // 6. Call callback with Submitted type to inform the driver.\r
+ //\r
+ if (!SubmitFormSetFail) {\r
+ SubmitCallback (FormSet, NULL);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Submit data for all formsets.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForSystem (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *FormLink;\r
+ LIST_ENTRY *StorageLink;\r
+ FORMSET_STORAGE *FormSetStorage;\r
+ FORM_BROWSER_FORM *Form;\r
+ FORM_BROWSER_FORMSET *LocalFormSet;\r
+ UINT32 UserSelection;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ mSystemSubmit = TRUE;\r
+ Link = GetFirstNode (&gBrowserFormSetList);\r
+ while (!IsNull (&gBrowserFormSetList, Link)) {\r
+ LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+ Link = GetNextNode (&gBrowserFormSetList, Link);\r
+ if (!ValidateFormSet (LocalFormSet)) {\r
+ continue;\r
+ }\r
+\r
+ Status = SubmitForFormSet (LocalFormSet, TRUE);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Remove maintain backup list after save except for the current using FormSet.\r
+ //\r
+ if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
+ CleanBrowserStorage (LocalFormSet);\r
+ RemoveEntryList (&LocalFormSet->Link);\r
+ DestroyFormSet (LocalFormSet);\r
+ }\r
+ }\r
+\r
+ mSystemSubmit = FALSE;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Process the save failed formsets.\r
+ //\r
+ Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
+ while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
+ LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
+ Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
+\r
+ if (!ValidateFormSet (LocalFormSet)) {\r
+ continue;\r
+ }\r
+\r
+ Form = LocalFormSet->SaveFailForm;\r
+ Question = LocalFormSet->SaveFailStatement;\r
+\r
+ //\r
+ // Confirm with user, get user input.\r
+ //\r
+ if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
+ //\r
+ // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.\r
+ //\r
+ UserSelection = ConfirmNoSubmitFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
+ } else {\r
+ UserSelection = ConfirmSaveFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
+ }\r
+\r
+ if (UserSelection == BROWSER_ACTION_DISCARD) {\r
+ if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
+ StorageLink = GetFirstNode (&LocalFormSet->StorageListHead);\r
+ while (!IsNull (&LocalFormSet->StorageListHead, StorageLink)) {\r
+ FormSetStorage = FORMSET_STORAGE_FROM_LINK (StorageLink);\r
+ StorageLink = GetNextNode (&LocalFormSet->StorageListHead, StorageLink);\r
+\r
+ SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
+ }\r
+ } else {\r
+ StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
+ while (!IsNull (&LocalFormSet->SaveFailStorageListHead, StorageLink)) {\r
+ FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
+ StorageLink = GetNextNode (&LocalFormSet->SaveFailStorageListHead, StorageLink);\r
+ //\r
+ // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer\r
+ // base on the SyncConfigRequest to Sync the buffer.\r
+ //\r
+ SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->RestoreConfigRequest, FALSE);\r
+ FreePool (FormSetStorage->RestoreConfigRequest);\r
+ FormSetStorage->RestoreConfigRequest = NULL;\r
+ if ( FormSetStorage->SyncConfigRequest != NULL) {\r
+ SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->SyncConfigRequest, TRUE);\r
+ FreePool (FormSetStorage->SyncConfigRequest);\r
+ FormSetStorage->SyncConfigRequest = NULL;\r
+ }\r
+ }\r
+ }\r
+\r
+ FormLink = GetFirstNode (&LocalFormSet->FormListHead);\r
+ while (!IsNull (&LocalFormSet->FormListHead, FormLink)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
+ FormLink = GetNextNode (&LocalFormSet->FormListHead, FormLink);\r
+ //\r
+ // Call callback with Changed type to inform the driver.\r
+ //\r
+ SendDiscardInfoToDriver (LocalFormSet, Form);\r
+ }\r
+\r
+ if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
+ CleanBrowserStorage (LocalFormSet);\r
+ RemoveEntryList (&LocalFormSet->Link);\r
+ RemoveEntryList (&LocalFormSet->SaveFailLink);\r
+ DestroyFormSet (LocalFormSet);\r
+ } else {\r
+ ValueChangeResetFlagUpdate (FALSE, LocalFormSet, NULL);\r
+ }\r
+ } else {\r
+ if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
+ NoSubmitCheck (LocalFormSet, &Form, &Question);\r
+ }\r
+\r
+ UiCopyMenuList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
+\r
+ gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ gCurrentSelection->Handle = LocalFormSet->HiiHandle;\r
+ CopyGuid (&gCurrentSelection->FormSetGuid, &LocalFormSet->Guid);\r
+ gCurrentSelection->FormId = Form->FormId;\r
+ gCurrentSelection->QuestionId = Question->QuestionId;\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Clean the list which will not process.\r
+ //\r
+ while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
+ Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
+ LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
+ RemoveEntryList (&LocalFormSet->SaveFailLink);\r
+\r
+ while (!IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
+ StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
+ FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
+ RemoveEntryList (&FormSetStorage->SaveFailLink);\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Submit data based on the input Setting level (Form, FormSet or System).\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param SettingScope Setting Scope for Submit action.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForm (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN BROWSER_SETTING_SCOPE SettingScope\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ switch (SettingScope) {\r
+ case FormLevel:\r
+ Status = SubmitForForm (FormSet, Form);\r
+ break;\r
+\r
+ case FormSetLevel:\r
+ Status = SubmitForFormSet (FormSet, FALSE);\r
+ break;\r
+\r
+ case SystemLevel:\r
+ Status = SubmitForSystem ();\r
+ break;\r
+\r
+ default:\r
+ Status = EFI_UNSUPPORTED;\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Converts the unicode character of the string from uppercase to lowercase.\r
+ This is a internal function.\r
+\r
+ @param ConfigString String to be converted\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HiiToLower (\r
+ IN EFI_STRING ConfigString\r
+ )\r
+{\r
+ EFI_STRING String;\r
+ BOOLEAN Lower;\r
+\r
+ ASSERT (ConfigString != NULL);\r
+\r
+ //\r
+ // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+ //\r
+ for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
+ if (*String == L'=') {\r
+ Lower = TRUE;\r
+ } else if (*String == L'&') {\r
+ Lower = FALSE;\r
+ } else if (Lower && (*String >= L'A') && (*String <= L'F')) {\r
+ *String = (CHAR16)(*String - L'A' + L'a');\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Find the point in the ConfigResp string for this question.\r
+\r
+ @param Question The question.\r
+ @param ConfigResp Get ConfigResp string.\r
+\r
+ @retval point to the offset where is for this question.\r
+\r
+**/\r
+CHAR16 *\r
+GetOffsetFromConfigResp (\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN CHAR16 *ConfigResp\r
+ )\r
+{\r
+ CHAR16 *RequestElement;\r
+ CHAR16 *BlockData;\r
+\r
+ //\r
+ // Type is EFI_HII_VARSTORE_NAME_VALUE.\r
+ //\r
+ if (Question->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ RequestElement = StrStr (ConfigResp, Question->VariableName);\r
+ if (RequestElement != NULL) {\r
+ //\r
+ // Skip the "VariableName=" field.\r
+ //\r
+ RequestElement += StrLen (Question->VariableName) + 1;\r
+ }\r
+\r
+ return RequestElement;\r
+ }\r
+\r
+ //\r
+ // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER\r
+ //\r
+\r
+ //\r
+ // Convert all hex digits in ConfigResp to lower case before searching.\r
+ //\r
+ HiiToLower (ConfigResp);\r
+\r
+ //\r
+ // 1. Directly use Question->BlockName to find.\r
+ //\r
+ RequestElement = StrStr (ConfigResp, Question->BlockName);\r
+ if (RequestElement != NULL) {\r
+ //\r
+ // Skip the "Question->BlockName&VALUE=" field.\r
+ //\r
+ RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
+ return RequestElement;\r
+ }\r
+\r
+ //\r
+ // 2. Change all hex digits in Question->BlockName to lower and compare again.\r
+ //\r
+ BlockData = AllocateCopyPool (StrSize (Question->BlockName), Question->BlockName);\r
+ ASSERT (BlockData != NULL);\r
+ HiiToLower (BlockData);\r
+ RequestElement = StrStr (ConfigResp, BlockData);\r
+ FreePool (BlockData);\r
+\r
+ if (RequestElement != NULL) {\r
+ //\r
+ // Skip the "Question->BlockName&VALUE=" field.\r
+ //\r
+ RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
+ }\r
+\r
+ return RequestElement;\r
+}\r
+\r
+/**\r
+ Get Question default value from AltCfg string.\r
+\r
+ @param FormSet The form set.\r
+ @param Form The form\r
+ @param Question The question.\r
+\r
+ @retval EFI_SUCCESS Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetDefaultValueFromAltCfg (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN OUT FORM_BROWSER_STATEMENT *Question\r
+ )\r
+{\r
+ BROWSER_STORAGE *Storage;\r
+ FORMSET_STORAGE *FormSetStorage;\r
+ CHAR16 *ConfigResp;\r
+ CHAR16 *Value;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
+\r
+ Storage = Question->Storage;\r
+ if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Try to get AltCfg string from form. If not found it, then\r
+ // try to get it from formset.\r
+ //\r
+ ConfigResp = NULL;\r
+ Link = GetFirstNode (&Form->ConfigRequestHead);\r
+ while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+ ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+ if (Storage == ConfigInfo->Storage) {\r
+ ConfigResp = ConfigInfo->ConfigAltResp;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (ConfigResp == NULL) {\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+ if (Storage == FormSetStorage->BrowserStorage) {\r
+ ConfigResp = FormSetStorage->ConfigAltResp;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (ConfigResp == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Value = GetOffsetFromConfigResp (Question, ConfigResp);\r
+ if (Value == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ return BufferToValue (Question, Value);\r
+}\r
+\r
+/**\r
+ Get default Id value used for browser.\r
+\r
+ @param DefaultId The default id value used by hii.\r
+\r
+ @retval Browser used default value.\r
+\r
+**/\r
+INTN\r
+GetDefaultIdForCallBack (\r
+ UINTN DefaultId\r
+ )\r
+{\r
+ if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
+ } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
+ } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
+ } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000)) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
+ } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000)) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
+ } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000)) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
+ } else {\r
+ return -1;\r
+ }\r
+}\r
+\r
+/**\r
+ Return data element in an Array by its Index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Index Zero based index for data in this array.\r
+\r
+ @retval Value The data to be returned\r
+\r
+**/\r
+UINT64\r
+GetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index\r
+ )\r
+{\r
+ UINT64 Data;\r
+\r
+ ASSERT (Array != NULL);\r
+\r
+ Data = 0;\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ Data = (UINT64)*(((UINT8 *)Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ Data = (UINT64)*(((UINT16 *)Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ Data = (UINT64)*(((UINT32 *)Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ Data = (UINT64)*(((UINT64 *)Array) + Index);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return Data;\r
+}\r
+\r
+/**\r
+ Set value of a data element in an Array by its Index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Index Zero based index for data in this array.\r
+ @param Value The value to be set.\r
+\r
+**/\r
+VOID\r
+SetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index,\r
+ IN UINT64 Value\r
+ )\r
+{\r
+ ASSERT (Array != NULL);\r
+\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ *(((UINT8 *)Array) + Index) = (UINT8)Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ *(((UINT16 *)Array) + Index) = (UINT16)Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ *(((UINT32 *)Array) + Index) = (UINT32)Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ *(((UINT64 *)Array) + Index) = (UINT64)Value;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Search an Option of a Question by its value.\r
+\r
+ @param Question The Question\r
+ @param OptionValue Value for Option to be searched.\r
+\r
+ @retval Pointer Pointer to the found Option.\r
+ @retval NULL Option not found.\r
+\r
+**/\r
+QUESTION_OPTION *\r
+ValueToOption (\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN EFI_HII_VALUE *OptionValue\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ QUESTION_OPTION *Option;\r
+ INTN Result;\r
+\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Option = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+ if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
+ //\r
+ // Check the suppressif condition, only a valid option can be return.\r
+ //\r
+ if ((Option->SuppressExpression == NULL) ||\r
+ ((EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse)))\r
+ {\r
+ return Option;\r
+ }\r
+ }\r
+\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Reset Question to its default value.\r
+\r
+ @param FormSet The form set.\r
+ @param Form The form.\r
+ @param Question The question.\r
+ @param DefaultId The Class of the default.\r
+\r
+ @retval EFI_SUCCESS Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionDefault (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN UINT16 DefaultId\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ QUESTION_DEFAULT *Default;\r
+ QUESTION_OPTION *Option;\r
+ EFI_HII_VALUE *HiiValue;\r
+ UINT8 Index;\r
+ EFI_STRING StrValue;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ INTN Action;\r
+ CHAR16 *NewString;\r
+ EFI_IFR_TYPE_VALUE *TypeValue;\r
+ UINT16 OriginalDefaultId;\r
+ FORMSET_DEFAULTSTORE *DefaultStore;\r
+ LIST_ENTRY *DefaultLink;\r
+\r
+ Status = EFI_NOT_FOUND;\r
+ StrValue = NULL;\r
+ OriginalDefaultId = DefaultId;\r
+ DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);\r
+\r
+ //\r
+ // Statement don't have storage, skip them\r
+ //\r
+ if (Question->QuestionId == 0) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // There are Five ways to specify default value for a Question:\r
+ // 1, use call back function (highest priority)\r
+ // 2, use ExtractConfig function\r
+ // 3, use nested EFI_IFR_DEFAULT\r
+ // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
+ // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
+ //\r
+ReGetDefault:\r
+ HiiValue = &Question->HiiValue;\r
+ TypeValue = &HiiValue->Value;\r
+ if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+ //\r
+ // For orderedlist, need to pass the BufferValue to Callback function.\r
+ //\r
+ TypeValue = (EFI_IFR_TYPE_VALUE *)Question->BufferValue;\r
+ }\r
+\r
+ //\r
+ // Get Question defaut value from call back function.\r
+ //\r
+ ConfigAccess = FormSet->ConfigAccess;\r
+ Action = GetDefaultIdForCallBack (DefaultId);\r
+ if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = ConfigAccess->Callback (\r
+ ConfigAccess,\r
+ Action,\r
+ Question->QuestionId,\r
+ HiiValue->Type,\r
+ TypeValue,\r
+ &ActionRequest\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+ NewString = GetToken (Question->HiiValue.Value.string, FormSet->HiiHandle);\r
+ ASSERT (NewString != NULL);\r
+\r
+ ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth);\r
+ if (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth) {\r
+ ZeroMem (Question->BufferValue, Question->StorageWidth);\r
+ CopyMem (Question->BufferValue, NewString, StrSize (NewString));\r
+ } else {\r
+ CopyMem (Question->BufferValue, NewString, Question->StorageWidth);\r
+ }\r
+\r
+ FreePool (NewString);\r
+ }\r
+\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get default value from altcfg string.\r
+ //\r
+ if (ConfigAccess != NULL) {\r
+ Status = GetDefaultValueFromAltCfg (FormSet, Form, Question);\r
+ if (!EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // EFI_IFR_DEFAULT has highest priority\r
+ //\r
+ if (!IsListEmpty (&Question->DefaultListHead)) {\r
+ Link = GetFirstNode (&Question->DefaultListHead);\r
+ while (!IsNull (&Question->DefaultListHead, Link)) {\r
+ Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
+\r
+ if (Default->DefaultId == DefaultId) {\r
+ if (Default->ValueExpression != NULL) {\r
+ //\r
+ // Default is provided by an Expression, evaluate it\r
+ //\r
+ Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+ ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && Question->BufferValue != NULL);\r
+ if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {\r
+ CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);\r
+ Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;\r
+ } else {\r
+ CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);\r
+ Question->HiiValue.BufferLen = Question->StorageWidth;\r
+ }\r
+\r
+ FreePool (Default->ValueExpression->Result.Buffer);\r
+ }\r
+\r
+ HiiValue->Type = Default->ValueExpression->Result.Type;\r
+ CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+ } else {\r
+ //\r
+ // Default value is embedded in EFI_IFR_DEFAULT\r
+ //\r
+ if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+ ASSERT (HiiValue->Buffer != NULL);\r
+ CopyMem (HiiValue->Buffer, Default->Value.Buffer, Default->Value.BufferLen);\r
+ } else {\r
+ CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
+ }\r
+ }\r
+\r
+ if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+ StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
+ if (StrValue == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (Question->StorageWidth > StrSize (StrValue)) {\r
+ ZeroMem (Question->BufferValue, Question->StorageWidth);\r
+ CopyMem (Question->BufferValue, StrValue, StrSize (StrValue));\r
+ } else {\r
+ CopyMem (Question->BufferValue, StrValue, Question->StorageWidth);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Link = GetNextNode (&Question->DefaultListHead, Link);\r
+ }\r
+ }\r
+\r
+ //\r
+ // EFI_ONE_OF_OPTION\r
+ //\r
+ if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+ //\r
+ // OneOfOption could only provide Standard and Manufacturing default\r
+ //\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Option = QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+ if ((Option->SuppressExpression != NULL) &&\r
+ (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))\r
+ {\r
+ continue;\r
+ }\r
+\r
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
+ )\r
+ {\r
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // EFI_IFR_CHECKBOX - lowest priority\r
+ //\r
+ if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+ //\r
+ // Checkbox could only provide Standard and Manufacturing default\r
+ //\r
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
+ )\r
+ {\r
+ HiiValue->Value.b = TRUE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ //\r
+ // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.\r
+ // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.\r
+ // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.\r
+ //\r
+ while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {\r
+ DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (DefaultLink);\r
+ DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead, DefaultLink);\r
+ DefaultId = DefaultStore->DefaultId;\r
+ if (DefaultId == OriginalDefaultId) {\r
+ continue;\r
+ }\r
+\r
+ goto ReGetDefault;\r
+ }\r
+\r
+ //\r
+ // For Questions without default value for all the default id in the DefaultStoreList.\r
+ //\r
+ Status = EFI_NOT_FOUND;\r
+ switch (Question->Operand) {\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ HiiValue->Value.b = FALSE;\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_OP:\r
+ //\r
+ // Take minimum value as numeric default value\r
+ //\r
+ if ((Question->Flags & EFI_IFR_DISPLAY) == 0) {\r
+ //\r
+ // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.\r
+ //\r
+ switch (Question->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ if (((INT8)HiiValue->Value.u8 < (INT8)Question->Minimum) || ((INT8)HiiValue->Value.u8 > (INT8)Question->Maximum)) {\r
+ HiiValue->Value.u8 = (UINT8)Question->Minimum;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ if (((INT16)HiiValue->Value.u16 < (INT16)Question->Minimum) || ((INT16)HiiValue->Value.u16 > (INT16)Question->Maximum)) {\r
+ HiiValue->Value.u16 = (UINT16)Question->Minimum;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ if (((INT32)HiiValue->Value.u32 < (INT32)Question->Minimum) || ((INT32)HiiValue->Value.u32 > (INT32)Question->Maximum)) {\r
+ HiiValue->Value.u32 = (UINT32)Question->Minimum;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ if (((INT64)HiiValue->Value.u64 < (INT64)Question->Minimum) || ((INT64)HiiValue->Value.u64 > (INT64)Question->Maximum)) {\r
+ HiiValue->Value.u64 = Question->Minimum;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ } else {\r
+ if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
+ HiiValue->Value.u64 = Question->Minimum;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OF_OP:\r
+ //\r
+ // Take first oneof option as oneof's default value\r
+ //\r
+ if (ValueToOption (Question, HiiValue) == NULL) {\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Option = QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+ if ((Option->SuppressExpression != NULL) &&\r
+ (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))\r
+ {\r
+ continue;\r
+ }\r
+\r
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ //\r
+ // Take option sequence in IFR as ordered list's default value\r
+ //\r
+ Index = 0;\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Status = EFI_SUCCESS;\r
+ Option = QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+ if ((Option->SuppressExpression != NULL) &&\r
+ (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))\r
+ {\r
+ continue;\r
+ }\r
+\r
+ SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
+\r
+ Index++;\r
+ if (Index >= Question->MaxContainers) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Get AltCfg string for current form.\r
+\r
+ @param FormSet Form data structure.\r
+ @param Form Form data structure.\r
+ @param DefaultId The Class of the default.\r
+ @param BrowserStorage The input request storage for the questions.\r
+\r
+**/\r
+VOID\r
+ExtractAltCfgForForm (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN UINT16 DefaultId,\r
+ IN BROWSER_STORAGE *BrowserStorage\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ CHAR16 *ConfigResp;\r
+ CHAR16 *Progress;\r
+ CHAR16 *Result;\r
+ BROWSER_STORAGE *Storage;\r
+ FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
+ FORMSET_STORAGE *FormSetStorage;\r
+\r
+ //\r
+ // Check whether has get AltCfg string for this formset.\r
+ // If yes, no need to get AltCfg for form.\r
+ //\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+ Storage = FormSetStorage->BrowserStorage;\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+ if ((BrowserStorage != NULL) && (BrowserStorage != Storage)) {\r
+ continue;\r
+ }\r
+\r
+ if ((Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE) &&\r
+ (FormSetStorage->ElementCount != 0) &&\r
+ FormSetStorage->HasCallAltCfg)\r
+ {\r
+ return;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get AltCfg string for each form.\r
+ //\r
+ Link = GetFirstNode (&Form->ConfigRequestHead);\r
+ while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+ ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+ Storage = ConfigInfo->Storage;\r
+ if ((BrowserStorage != NULL) && (BrowserStorage != Storage)) {\r
+ continue;\r
+ }\r
+\r
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // 1. Skip if there is no RequestElement\r
+ //\r
+ if (ConfigInfo->ElementCount == 0) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // 2. Get value through hii config routine protocol.\r
+ //\r
+ Status = mHiiConfigRouting->ExtractConfig (\r
+ mHiiConfigRouting,\r
+ ConfigInfo->ConfigRequest,\r
+ &Progress,\r
+ &Result\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
+ // Get the default configuration string according to the default ID.\r
+ //\r
+ Status = mHiiConfigRouting->GetAltConfig (\r
+ mHiiConfigRouting,\r
+ Result,\r
+ &Storage->Guid,\r
+ Storage->Name,\r
+ NULL,\r
+ &DefaultId, // it can be NULL to get the current setting.\r
+ &ConfigResp\r
+ );\r
+ FreePool (Result);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ ConfigInfo->ConfigAltResp = ConfigResp;\r
+ }\r
+}\r
+\r
+/**\r
+ Clean AltCfg string for current form.\r
+\r
+ @param Form Form data structure.\r
+\r
+**/\r
+VOID\r
+CleanAltCfgForForm (\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
+\r
+ Link = GetFirstNode (&Form->ConfigRequestHead);\r
+ while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+ ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+ if (ConfigInfo->ConfigAltResp != NULL) {\r
+ FreePool (ConfigInfo->ConfigAltResp);\r
+ ConfigInfo->ConfigAltResp = NULL;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Get AltCfg string for current formset.\r
+\r
+ @param FormSet Form data structure.\r
+ @param DefaultId The Class of the default.\r
+ @param BrowserStorage The input request storage for the questions.\r
+\r
+**/\r
+VOID\r
+ExtractAltCfgForFormSet (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN UINT16 DefaultId,\r
+ IN BROWSER_STORAGE *BrowserStorage\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ CHAR16 *ConfigResp;\r
+ CHAR16 *Progress;\r
+ CHAR16 *Result;\r
+ BROWSER_STORAGE *Storage;\r
+ FORMSET_STORAGE *FormSetStorage;\r
+\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+ Storage = FormSetStorage->BrowserStorage;\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+ if ((BrowserStorage != NULL) && (BrowserStorage != Storage)) {\r
+ continue;\r
+ }\r
+\r
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // 1. Skip if there is no RequestElement\r
+ //\r
+ if (FormSetStorage->ElementCount == 0) {\r
+ continue;\r
+ }\r
+\r
+ FormSetStorage->HasCallAltCfg = TRUE;\r
+\r
+ //\r
+ // 2. Get value through hii config routine protocol.\r
+ //\r
+ Status = mHiiConfigRouting->ExtractConfig (\r
+ mHiiConfigRouting,\r
+ FormSetStorage->ConfigRequest,\r
+ &Progress,\r
+ &Result\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
+ // Get the default configuration string according to the default ID.\r
+ //\r
+ Status = mHiiConfigRouting->GetAltConfig (\r
+ mHiiConfigRouting,\r
+ Result,\r
+ &Storage->Guid,\r
+ Storage->Name,\r
+ NULL,\r
+ &DefaultId, // it can be NULL to get the current setting.\r
+ &ConfigResp\r
+ );\r
+\r
+ FreePool (Result);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ FormSetStorage->ConfigAltResp = ConfigResp;\r
+ }\r
+}\r
+\r
+/**\r
+ Clean AltCfg string for current formset.\r
+\r
+ @param FormSet Form data structure.\r
+\r
+**/\r
+VOID\r
+CleanAltCfgForFormSet (\r
+ IN FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORMSET_STORAGE *FormSetStorage;\r
+\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+ if (FormSetStorage->ConfigAltResp != NULL) {\r
+ FreePool (FormSetStorage->ConfigAltResp);\r
+ FormSetStorage->ConfigAltResp = NULL;\r
+ }\r
+\r
+ FormSetStorage->HasCallAltCfg = FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Reset Questions to their initial value or default value in a Form, Formset or System.\r
+\r
+ GetDefaultValueScope parameter decides which questions will reset\r
+ to its default value.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param DefaultId The Class of the default.\r
+ @param SettingScope Setting Scope for Default action.\r
+ @param GetDefaultValueScope Get default value scope.\r
+ @param Storage Get default value only for this storage.\r
+ @param RetrieveValueFirst Whether call the retrieve call back to\r
+ get the initial value before get default\r
+ value.\r
+ @param SkipGetAltCfg Whether skip the get altcfg string process.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractDefault (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN UINT16 DefaultId,\r
+ IN BROWSER_SETTING_SCOPE SettingScope,\r
+ IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope,\r
+ IN BROWSER_STORAGE *Storage OPTIONAL,\r
+ IN BOOLEAN RetrieveValueFirst,\r
+ IN BOOLEAN SkipGetAltCfg\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *FormLink;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+ FORM_BROWSER_FORMSET *LocalFormSet;\r
+ FORM_BROWSER_FORMSET *OldFormSet;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Check the supported setting level.\r
+ //\r
+ if ((SettingScope >= MaxLevel) || (GetDefaultValueScope >= GetDefaultForMax)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if ((GetDefaultValueScope == GetDefaultForStorage) && (Storage == NULL)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (SettingScope == FormLevel) {\r
+ //\r
+ // Prepare the AltCfg String for form.\r
+ //\r
+ if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
+ ExtractAltCfgForForm (FormSet, Form, DefaultId, Storage);\r
+ }\r
+\r
+ //\r
+ // Extract Form default\r
+ //\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+ //\r
+ // If get default value only for this storage, check the storage first.\r
+ //\r
+ if ((GetDefaultValueScope == GetDefaultForStorage) && (Question->Storage != Storage)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // If get default value only for no storage question, just skip the question which has storage.\r
+ //\r
+ if ((GetDefaultValueScope == GetDefaultForNoStorage) && (Question->Storage != NULL)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // If Question is disabled, don't reset it to default\r
+ //\r
+ if (Question->Expression != NULL) {\r
+ if (EvaluateExpressionList (Question->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (RetrieveValueFirst) {\r
+ //\r
+ // Call the Retrieve call back to get the initial question value.\r
+ //\r
+ Status = ProcessRetrieveForQuestion (FormSet->ConfigAccess, Question, FormSet);\r
+ }\r
+\r
+ //\r
+ // If not request to get the initial value or get initial value fail, then get default value.\r
+ //\r
+ if (!RetrieveValueFirst || EFI_ERROR (Status)) {\r
+ Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Synchronize Buffer storage's Edit buffer\r
+ //\r
+ if ((Question->Storage != NULL) &&\r
+ (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE))\r
+ {\r
+ SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Clean the AltCfg String.\r
+ //\r
+ if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
+ CleanAltCfgForForm (Form);\r
+ }\r
+ } else if (SettingScope == FormSetLevel) {\r
+ //\r
+ // Prepare the AltCfg String for formset.\r
+ //\r
+ if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
+ ExtractAltCfgForFormSet (FormSet, DefaultId, Storage);\r
+ }\r
+\r
+ FormLink = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
+ ExtractDefault (FormSet, Form, DefaultId, FormLevel, GetDefaultValueScope, Storage, RetrieveValueFirst, SkipGetAltCfg);\r
+ FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
+ }\r
+\r
+ //\r
+ // Clean the AltCfg String.\r
+ //\r
+ if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
+ CleanAltCfgForFormSet (FormSet);\r
+ }\r
+ } else if (SettingScope == SystemLevel) {\r
+ //\r
+ // Preload all Hii formset.\r
+ //\r
+ LoadAllHiiFormset ();\r
+\r
+ OldFormSet = mSystemLevelFormSet;\r
+\r
+ //\r
+ // Set Default Value for each FormSet in the maintain list.\r
+ //\r
+ Link = GetFirstNode (&gBrowserFormSetList);\r
+ while (!IsNull (&gBrowserFormSetList, Link)) {\r
+ LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+ Link = GetNextNode (&gBrowserFormSetList, Link);\r
+ if (!ValidateFormSet (LocalFormSet)) {\r
+ continue;\r
+ }\r
+\r
+ mSystemLevelFormSet = LocalFormSet;\r
+\r
+ ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst, SkipGetAltCfg);\r
+ }\r
+\r
+ mSystemLevelFormSet = OldFormSet;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Validate whether this question's value has changed.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param Question Question to be initialized.\r
+ @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
+\r
+ @retval TRUE Question's value has changed.\r
+ @retval FALSE Question's value has not changed\r
+\r
+**/\r
+BOOLEAN\r
+IsQuestionValueChanged (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN OUT FORM_BROWSER_STATEMENT *Question,\r
+ IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
+ )\r
+{\r
+ EFI_HII_VALUE BackUpValue;\r
+ CHAR8 *BackUpBuffer;\r
+ EFI_HII_VALUE BackUpValue2;\r
+ CHAR8 *BackUpBuffer2;\r
+ EFI_STATUS Status;\r
+ BOOLEAN ValueChanged;\r
+ UINTN BufferWidth;\r
+\r
+ //\r
+ // For quetion without storage, always mark it as data not changed.\r
+ //\r
+ if ((Question->Storage == NULL) && (Question->Operand != EFI_IFR_TIME_OP) && (Question->Operand != EFI_IFR_DATE_OP)) {\r
+ return FALSE;\r
+ }\r
+\r
+ BackUpBuffer = NULL;\r
+ BackUpBuffer2 = NULL;\r
+ ValueChanged = FALSE;\r
+\r
+ switch (Question->Operand) {\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ BufferWidth = Question->StorageWidth;\r
+ BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
+ ASSERT (BackUpBuffer != NULL);\r
+ break;\r
+\r
+ case EFI_IFR_STRING_OP:\r
+ case EFI_IFR_PASSWORD_OP:\r
+ BufferWidth = (UINTN)Question->Maximum * sizeof (CHAR16);\r
+ BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
+ ASSERT (BackUpBuffer != NULL);\r
+ break;\r
+\r
+ default:\r
+ BufferWidth = 0;\r
+ break;\r
+ }\r
+\r
+ CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+ if (GetValueFrom == GetSetValueWithBothBuffer) {\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ switch (Question->Operand) {\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ BufferWidth = Question->StorageWidth;\r
+ BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
+ ASSERT (BackUpBuffer2 != NULL);\r
+ break;\r
+\r
+ case EFI_IFR_STRING_OP:\r
+ case EFI_IFR_PASSWORD_OP:\r
+ BufferWidth = (UINTN)Question->Maximum * sizeof (CHAR16);\r
+ BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
+ ASSERT (BackUpBuffer2 != NULL);\r
+ break;\r
+\r
+ default:\r
+ BufferWidth = 0;\r
+ break;\r
+ }\r
+\r
+ CopyMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if ((CompareMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0) ||\r
+ (CompareMem (BackUpBuffer2, Question->BufferValue, BufferWidth) != 0))\r
+ {\r
+ ValueChanged = TRUE;\r
+ }\r
+ } else {\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if ((CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0) ||\r
+ (CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0))\r
+ {\r
+ ValueChanged = TRUE;\r
+ }\r
+ }\r
+\r
+ CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
+ if (BackUpBuffer != NULL) {\r
+ CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth);\r
+ FreePool (BackUpBuffer);\r
+ }\r
+\r
+ if (BackUpBuffer2 != NULL) {\r
+ FreePool (BackUpBuffer2);\r
+ }\r
+\r
+ Question->ValueChanged = ValueChanged;\r
+\r
+ return ValueChanged;\r
+}\r
+\r
+/**\r
+ Initialize Question's Edit copy from Storage.\r
+\r
+ @param Selection Selection contains the information about\r
+ the Selection, form and formset to be displayed.\r
+ Selection action may be updated in retrieve callback.\r
+ If Selection is NULL, only initialize Question value.\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormConfig (\r
+ IN OUT UI_MENU_SELECTION *Selection,\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+ //\r
+ // Initialize local copy of Value for each Question\r
+ //\r
+ if ((Question->Operand == EFI_IFR_PASSWORD_OP) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == 0)) {\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
+ } else {\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
+ HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16 *)Question->BufferValue, NULL);\r
+ }\r
+\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Initialize Question's Edit copy from Storage for the whole Formset.\r
+\r
+ @param Selection Selection contains the information about\r
+ the Selection, form and formset to be displayed.\r
+ Selection action may be updated in retrieve callback.\r
+ If Selection is NULL, only initialize Question value.\r
+ @param FormSet FormSet data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormSetConfig (\r
+ IN OUT UI_MENU_SELECTION *Selection,\r
+ IN FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORM *Form;\r
+\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+ //\r
+ // Initialize local copy of Value for each Form\r
+ //\r
+ Status = LoadFormConfig (Selection, FormSet, Form);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+ }\r
+\r
+ //\r
+ // Finished question initialization.\r
+ //\r
+ FormSet->QuestionInited = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Remove the Request element from the Config Request.\r
+\r
+ @param Storage Pointer to the browser storage.\r
+ @param RequestElement The pointer to the Request element.\r
+\r
+**/\r
+VOID\r
+RemoveElement (\r
+ IN OUT BROWSER_STORAGE *Storage,\r
+ IN CHAR16 *RequestElement\r
+ )\r
+{\r
+ CHAR16 *NewStr;\r
+ CHAR16 *DestStr;\r
+\r
+ ASSERT (Storage->ConfigRequest != NULL && RequestElement != NULL);\r
+\r
+ NewStr = StrStr (Storage->ConfigRequest, RequestElement);\r
+\r
+ if (NewStr == NULL) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Remove this element from this ConfigRequest.\r
+ //\r
+ DestStr = NewStr;\r
+ NewStr += StrLen (RequestElement);\r
+ CopyMem (DestStr, NewStr, StrSize (NewStr));\r
+\r
+ Storage->SpareStrLen += StrLen (RequestElement);\r
+}\r
+\r
+/**\r
+ Adjust config request in storage, remove the request elements existed in the input ConfigRequest.\r
+\r
+ @param Storage Pointer to the formset storage.\r
+ @param ConfigRequest The pointer to the Request element.\r
+\r
+**/\r
+VOID\r
+RemoveConfigRequest (\r
+ FORMSET_STORAGE *Storage,\r
+ CHAR16 *ConfigRequest\r
+ )\r
+{\r
+ CHAR16 *RequestElement;\r
+ CHAR16 *NextRequestElement;\r
+ CHAR16 *SearchKey;\r
+\r
+ //\r
+ // No request element in it, just return.\r
+ //\r
+ if (ConfigRequest == NULL) {\r
+ return;\r
+ }\r
+\r
+ if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
+ //\r
+ SearchKey = L"&";\r
+ } else {\r
+ //\r
+ // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
+ //\r
+ SearchKey = L"&OFFSET";\r
+ }\r
+\r
+ //\r
+ // Find SearchKey storage\r
+ //\r
+ if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ RequestElement = StrStr (ConfigRequest, L"PATH");\r
+ ASSERT (RequestElement != NULL);\r
+ RequestElement = StrStr (RequestElement, SearchKey);\r
+ } else {\r
+ RequestElement = StrStr (ConfigRequest, SearchKey);\r
+ }\r
+\r
+ while (RequestElement != NULL) {\r
+ //\r
+ // +1 to avoid find header itself.\r
+ //\r
+ NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
+\r
+ //\r
+ // The last Request element in configRequest string.\r
+ //\r
+ if (NextRequestElement != NULL) {\r
+ //\r
+ // Replace "&" with '\0'.\r
+ //\r
+ *NextRequestElement = L'\0';\r
+ }\r
+\r
+ RemoveElement (Storage->BrowserStorage, RequestElement);\r
+\r
+ if (NextRequestElement != NULL) {\r
+ //\r
+ // Restore '&' with '\0' for later used.\r
+ //\r
+ *NextRequestElement = L'&';\r
+ }\r
+\r
+ RequestElement = NextRequestElement;\r
+ }\r
+\r
+ //\r
+ // If no request element remain, just remove the ConfigRequest string.\r
+ //\r
+ if (StrCmp (Storage->BrowserStorage->ConfigRequest, Storage->ConfigHdr) == 0) {\r
+ FreePool (Storage->BrowserStorage->ConfigRequest);\r
+ Storage->BrowserStorage->ConfigRequest = NULL;\r
+ Storage->BrowserStorage->SpareStrLen = 0;\r
+ }\r
+}\r
+\r
+/**\r
+ Base on the current formset info, clean the ConfigRequest string in browser storage.\r
+\r
+ @param FormSet Pointer of the FormSet\r
+\r
+**/\r
+VOID\r
+CleanBrowserStorage (\r
+ IN OUT FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORMSET_STORAGE *Storage;\r
+\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+ if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+ if ((Storage->ConfigRequest == NULL) || (Storage->BrowserStorage->ConfigRequest == NULL)) {\r
+ continue;\r
+ }\r
+\r
+ RemoveConfigRequest (Storage, Storage->ConfigRequest);\r
+ } else if ((Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+ (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE))\r
+ {\r
+ if (Storage->BrowserStorage->ConfigRequest != NULL) {\r
+ FreePool (Storage->BrowserStorage->ConfigRequest);\r
+ Storage->BrowserStorage->ConfigRequest = NULL;\r
+ }\r
+\r
+ Storage->BrowserStorage->Initialized = FALSE;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Check whether current element in the ConfigReqeust string.\r
+\r
+ @param BrowserStorage Storage which includes ConfigReqeust.\r
+ @param RequestElement New element need to check.\r
+\r
+ @retval TRUE The Element is in the ConfigReqeust string.\r
+ @retval FALSE The Element not in the configReqeust String.\r
+\r
+**/\r
+BOOLEAN\r
+ElementValidation (\r
+ BROWSER_STORAGE *BrowserStorage,\r
+ CHAR16 *RequestElement\r
+ )\r
+{\r
+ return StrStr (BrowserStorage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;\r
+}\r
+\r
+/**\r
+ Append the Request element to the Config Request.\r
+\r
+ @param ConfigRequest Current ConfigRequest info.\r
+ @param SpareStrLen Current remain free buffer for config reqeust.\r
+ @param RequestElement New Request element.\r
+\r
+**/\r
+VOID\r
+AppendConfigRequest (\r
+ IN OUT CHAR16 **ConfigRequest,\r
+ IN OUT UINTN *SpareStrLen,\r
+ IN CHAR16 *RequestElement\r
+ )\r
+{\r
+ CHAR16 *NewStr;\r
+ UINTN StringSize;\r
+ UINTN StrLength;\r
+ UINTN MaxLen;\r
+\r
+ StrLength = StrLen (RequestElement);\r
+ StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);\r
+ MaxLen = StringSize / sizeof (CHAR16) + *SpareStrLen;\r
+\r
+ //\r
+ // Append <RequestElement> to <ConfigRequest>\r
+ //\r
+ if (StrLength > *SpareStrLen) {\r
+ //\r
+ // Old String buffer is not sufficient for RequestElement, allocate a new one\r
+ //\r
+ MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;\r
+ NewStr = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
+ ASSERT (NewStr != NULL);\r
+\r
+ if (*ConfigRequest != NULL) {\r
+ CopyMem (NewStr, *ConfigRequest, StringSize);\r
+ FreePool (*ConfigRequest);\r
+ }\r
+\r
+ *ConfigRequest = NewStr;\r
+ *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;\r
+ }\r
+\r
+ StrCatS (*ConfigRequest, MaxLen, RequestElement);\r
+ *SpareStrLen -= StrLength;\r
+}\r
+\r
+/**\r
+ Adjust the config request info, remove the request elements which already in AllConfigRequest string.\r
+\r
+ @param Storage Form set Storage.\r
+ @param Request The input request string.\r
+ @param RespString Whether the input is ConfigRequest or ConfigResp format.\r
+\r
+ @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig\r
+ @retval FALSE All elements covered by current used elements.\r
+\r
+**/\r
+BOOLEAN\r
+ConfigRequestAdjust (\r
+ IN BROWSER_STORAGE *Storage,\r
+ IN CHAR16 *Request,\r
+ IN BOOLEAN RespString\r
+ )\r
+{\r
+ CHAR16 *RequestElement;\r
+ CHAR16 *NextRequestElement;\r
+ CHAR16 *NextElementBakup;\r
+ CHAR16 *SearchKey;\r
+ CHAR16 *ValueKey;\r
+ BOOLEAN RetVal;\r
+ CHAR16 *ConfigRequest;\r
+\r
+ RetVal = FALSE;\r
+ NextElementBakup = NULL;\r
+ ValueKey = NULL;\r
+\r
+ if (Request != NULL) {\r
+ ConfigRequest = Request;\r
+ } else {\r
+ ConfigRequest = Storage->ConfigRequest;\r
+ }\r
+\r
+ if (Storage->ConfigRequest == NULL) {\r
+ Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
+ return TRUE;\r
+ }\r
+\r
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
+ //\r
+ SearchKey = L"&";\r
+ } else {\r
+ //\r
+ // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
+ //\r
+ SearchKey = L"&OFFSET";\r
+ ValueKey = L"&VALUE";\r
+ }\r
+\r
+ //\r
+ // Find SearchKey storage\r
+ //\r
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ RequestElement = StrStr (ConfigRequest, L"PATH");\r
+ ASSERT (RequestElement != NULL);\r
+ RequestElement = StrStr (RequestElement, SearchKey);\r
+ } else {\r
+ RequestElement = StrStr (ConfigRequest, SearchKey);\r
+ }\r
+\r
+ while (RequestElement != NULL) {\r
+ //\r
+ // +1 to avoid find header itself.\r
+ //\r
+ NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
+\r
+ //\r
+ // The last Request element in configRequest string.\r
+ //\r
+ if (NextRequestElement != NULL) {\r
+ if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+ NextElementBakup = NextRequestElement;\r
+ NextRequestElement = StrStr (RequestElement, ValueKey);\r
+ ASSERT (NextRequestElement != NULL);\r
+ }\r
+\r
+ //\r
+ // Replace "&" with '\0'.\r
+ //\r
+ *NextRequestElement = L'\0';\r
+ } else {\r
+ if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+ NextElementBakup = NextRequestElement;\r
+ NextRequestElement = StrStr (RequestElement, ValueKey);\r
+ ASSERT (NextRequestElement != NULL);\r
+ //\r
+ // Replace "&" with '\0'.\r
+ //\r
+ *NextRequestElement = L'\0';\r
+ }\r
+ }\r
+\r
+ if (!ElementValidation (Storage, RequestElement)) {\r
+ //\r
+ // Add this element to the Storage->BrowserStorage->AllRequestElement.\r
+ //\r
+ AppendConfigRequest (&Storage->ConfigRequest, &Storage->SpareStrLen, RequestElement);\r
+ RetVal = TRUE;\r
+ }\r
+\r
+ if (NextRequestElement != NULL) {\r
+ //\r
+ // Restore '&' with '\0' for later used.\r
+ //\r
+ *NextRequestElement = L'&';\r
+ }\r
+\r
+ if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+ RequestElement = NextElementBakup;\r
+ } else {\r
+ RequestElement = NextRequestElement;\r
+ }\r
+ }\r
+\r
+ return RetVal;\r
+}\r
+\r
+/**\r
+ Fill storage's edit copy with settings requested from Configuration Driver.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Storage Buffer Storage.\r
+\r
+**/\r
+VOID\r
+LoadStorage (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORMSET_STORAGE *Storage\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING Progress;\r
+ EFI_STRING Result;\r
+ CHAR16 *StrPtr;\r
+ EFI_STRING ConfigRequest;\r
+ UINTN StrLen;\r
+\r
+ ConfigRequest = NULL;\r
+\r
+ switch (Storage->BrowserStorage->Type) {\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+ return;\r
+\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+ if (Storage->BrowserStorage->ConfigRequest != NULL) {\r
+ ConfigRequestAdjust (Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
+ return;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_BUFFER:\r
+ case EFI_HII_VARSTORE_NAME_VALUE:\r
+ //\r
+ // Skip if there is no RequestElement.\r
+ //\r
+ if (Storage->ElementCount == 0) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Just update the ConfigRequest, if storage already initialized.\r
+ //\r
+ if (Storage->BrowserStorage->Initialized) {\r
+ ConfigRequestAdjust (Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
+ return;\r
+ }\r
+\r
+ Storage->BrowserStorage->Initialized = TRUE;\r
+ break;\r
+\r
+ default:\r
+ return;\r
+ }\r
+\r
+ if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // Create the config request string to get all fields for this storage.\r
+ // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
+ // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator\r
+ //\r
+ StrLen = StrSize (Storage->ConfigHdr) + 20 * sizeof (CHAR16);\r
+ ConfigRequest = AllocateZeroPool (StrLen);\r
+ ASSERT (ConfigRequest != NULL);\r
+ UnicodeSPrint (\r
+ ConfigRequest,\r
+ StrLen,\r
+ L"%s&OFFSET=0&WIDTH=%04x",\r
+ Storage->ConfigHdr,\r
+ Storage->BrowserStorage->Size\r
+ );\r
+ } else {\r
+ ConfigRequest = Storage->ConfigRequest;\r
+ }\r
+\r
+ //\r
+ // Request current settings from Configuration Driver\r
+ //\r
+ Status = mHiiConfigRouting->ExtractConfig (\r
+ mHiiConfigRouting,\r
+ ConfigRequest,\r
+ &Progress,\r
+ &Result\r
+ );\r
+\r
+ //\r
+ // If get value fail, extract default from IFR binary\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE, TRUE);\r
+ } else {\r
+ //\r
+ // Convert Result from <ConfigAltResp> to <ConfigResp>\r
+ //\r
+ StrPtr = StrStr (Result, L"&GUID=");\r
+ if (StrPtr != NULL) {\r
+ *StrPtr = L'\0';\r
+ }\r
+\r
+ Status = ConfigRespToStorage (Storage->BrowserStorage, Result);\r
+ FreePool (Result);\r
+ }\r
+\r
+ Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
+\r
+ //\r
+ // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.\r
+ //\r
+ SynchronizeStorage (Storage->BrowserStorage, NULL, TRUE);\r
+\r
+ if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
+ if (ConfigRequest != NULL) {\r
+ FreePool (ConfigRequest);\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Get Value changed status from old question.\r
+\r
+ @param NewFormSet FormSet data structure.\r
+ @param OldQuestion Old question which has value changed.\r
+\r
+**/\r
+VOID\r
+SyncStatusForQuestion (\r
+ IN OUT FORM_BROWSER_FORMSET *NewFormSet,\r
+ IN FORM_BROWSER_STATEMENT *OldQuestion\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *QuestionLink;\r
+ FORM_BROWSER_FORM *Form;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ //\r
+ // For each form in one formset.\r
+ //\r
+ Link = GetFirstNode (&NewFormSet->FormListHead);\r
+ while (!IsNull (&NewFormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ Link = GetNextNode (&NewFormSet->FormListHead, Link);\r
+\r
+ //\r
+ // for each question in one form.\r
+ //\r
+ QuestionLink = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
+ QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
+\r
+ if (Question->QuestionId == OldQuestion->QuestionId) {\r
+ Question->ValueChanged = TRUE;\r
+ return;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Get Value changed status from old formset.\r
+\r
+ @param NewFormSet FormSet data structure.\r
+ @param OldFormSet FormSet data structure.\r
+\r
+**/\r
+VOID\r
+SyncStatusForFormSet (\r
+ IN OUT FORM_BROWSER_FORMSET *NewFormSet,\r
+ IN FORM_BROWSER_FORMSET *OldFormSet\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *QuestionLink;\r
+ FORM_BROWSER_FORM *Form;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ //\r
+ // For each form in one formset.\r
+ //\r
+ Link = GetFirstNode (&OldFormSet->FormListHead);\r
+ while (!IsNull (&OldFormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ Link = GetNextNode (&OldFormSet->FormListHead, Link);\r
+\r
+ //\r
+ // for each question in one form.\r
+ //\r
+ QuestionLink = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
+ QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
+\r
+ if (!Question->ValueChanged) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Find the same question in new formset and update the value changed flag.\r
+ //\r
+ SyncStatusForQuestion (NewFormSet, Question);\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Get current setting of Questions.\r
+\r
+ @param FormSet FormSet data structure.\r
+\r
+**/\r
+VOID\r
+InitializeCurrentSetting (\r
+ IN OUT FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORMSET_STORAGE *Storage;\r
+ FORM_BROWSER_FORMSET *OldFormSet;\r
+\r
+ //\r
+ // Try to find pre FormSet in the maintain backup list.\r
+ // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.\r
+ //\r
+ OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle);\r
+ if (OldFormSet != NULL) {\r
+ SyncStatusForFormSet (FormSet, OldFormSet);\r
+ RemoveEntryList (&OldFormSet->Link);\r
+ DestroyFormSet (OldFormSet);\r
+ }\r
+\r
+ InsertTailList (&gBrowserFormSetList, &FormSet->Link);\r
+\r
+ //\r
+ // Extract default from IFR binary for no storage questions.\r
+ //\r
+ ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForNoStorage, NULL, TRUE, FALSE);\r
+\r
+ //\r
+ // Request current settings from Configuration Driver\r
+ //\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+\r
+ LoadStorage (FormSet, Storage);\r
+\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+ }\r
+}\r
+\r
+/**\r
+ Fetch the Ifr binary data of a FormSet.\r
+\r
+ @param Handle PackageList Handle\r
+ @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
+ specified (NULL or zero GUID), take the first\r
+ FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+ found in package list.\r
+ On output, GUID of the formset found(if not NULL).\r
+ @param BinaryLength The length of the FormSet IFR binary.\r
+ @param BinaryData The buffer designed to receive the FormSet.\r
+\r
+ @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
+ BufferLength was updated.\r
+ @retval EFI_INVALID_PARAMETER The handle is unknown.\r
+ @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
+ be found with the requested FormId.\r
+\r
+**/\r
+EFI_STATUS\r
+GetIfrBinaryData (\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT EFI_GUID *FormSetGuid,\r
+ OUT UINTN *BinaryLength,\r
+ OUT UINT8 **BinaryData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
+ UINTN BufferSize;\r
+ UINT8 *Package;\r
+ UINT8 *OpCodeData;\r
+ UINT32 Offset;\r
+ UINT32 Offset2;\r
+ UINT32 PackageListLength;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ UINT8 Index;\r
+ UINT8 NumberOfClassGuid;\r
+ BOOLEAN ClassGuidMatch;\r
+ EFI_GUID *ClassGuid;\r
+ EFI_GUID *ComparingGuid;\r
+\r
+ OpCodeData = NULL;\r
+ Package = NULL;\r
+ ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ //\r
+ // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
+ //\r
+ if (FormSetGuid == NULL) {\r
+ ComparingGuid = &gZeroGuid;\r
+ } else {\r
+ ComparingGuid = FormSetGuid;\r
+ }\r
+\r
+ //\r
+ // Get HII PackageList\r
+ //\r
+ BufferSize = 0;\r
+ HiiPackageList = NULL;\r
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ HiiPackageList = AllocatePool (BufferSize);\r
+ ASSERT (HiiPackageList != NULL);\r
+\r
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ ASSERT (HiiPackageList != NULL);\r
+\r
+ //\r
+ // Get Form package from this HII package List\r
+ //\r
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ Offset2 = 0;\r
+ CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
+\r
+ ClassGuidMatch = FALSE;\r
+ while (Offset < PackageListLength) {\r
+ Package = ((UINT8 *)HiiPackageList) + Offset;\r
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
+ //\r
+ // Search FormSet in this Form Package\r
+ //\r
+ Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ while (Offset2 < PackageHeader.Length) {\r
+ OpCodeData = Package + Offset2;\r
+\r
+ if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
+ //\r
+ // Try to compare against formset GUID\r
+ //\r
+ if (IsZeroGuid (ComparingGuid) ||\r
+ CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER))))\r
+ {\r
+ break;\r
+ }\r
+\r
+ if (((EFI_IFR_OP_HEADER *)OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
+ //\r
+ // Try to compare against formset class GUID\r
+ //\r
+ NumberOfClassGuid = (UINT8)(((EFI_IFR_FORM_SET *)OpCodeData)->Flags & 0x3);\r
+ ClassGuid = (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
+ for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
+ if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
+ ClassGuidMatch = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (ClassGuidMatch) {\r
+ break;\r
+ }\r
+ } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
+ ClassGuidMatch = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ Offset2 += ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;\r
+ }\r
+\r
+ if (Offset2 < PackageHeader.Length) {\r
+ //\r
+ // Target formset found\r
+ //\r
+ break;\r
+ }\r
+ }\r
+\r
+ Offset += PackageHeader.Length;\r
+ }\r
+\r
+ if (Offset >= PackageListLength) {\r
+ //\r
+ // Form package not found in this Package List\r
+ //\r
+ FreePool (HiiPackageList);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (FormSetGuid != NULL) {\r
+ //\r
+ // Return the FormSet GUID\r
+ //\r
+ CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *)OpCodeData)->Guid, sizeof (EFI_GUID));\r
+ }\r
+\r
+ //\r
+ // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
+ // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
+ // of the Form Package.\r
+ //\r
+ *BinaryLength = PackageHeader.Length - Offset2;\r
+ *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
+\r
+ FreePool (HiiPackageList);\r
+\r
+ if (*BinaryData == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Initialize the internal data structure of a FormSet.\r
+\r
+ @param Handle PackageList Handle\r
+ @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
+ specified (NULL or zero GUID), take the first\r
+ FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+ found in package list.\r
+ On output, GUID of the formset found(if not NULL).\r
+ @param FormSet FormSet data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeFormSet (\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT EFI_GUID *FormSetGuid,\r
+ OUT FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE DriverHandle;\r
+\r
+ Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;\r
+ FormSet->HiiHandle = Handle;\r
+ CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
+ FormSet->QuestionInited = FALSE;\r
+\r
+ //\r
+ // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
+ //\r
+ Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ FormSet->DriverHandle = DriverHandle;\r
+ Status = gBS->HandleProtocol (\r
+ DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ (VOID **)&FormSet->ConfigAccess\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
+ // list, then there will be no configuration action required\r
+ //\r
+ FormSet->ConfigAccess = NULL;\r
}\r
\r
- return EFI_SUCCESS;\r
+ //\r
+ // Parse the IFR binary OpCodes\r
+ //\r
+ Status = ParseOpCodes (FormSet);\r
+\r
+ return Status;\r
}\r
\r
/**\r
- Initialize Question's Edit copy from Storage for the whole Formset.\r
-\r
- @param Selection Selection contains the information about \r
- the Selection, form and formset to be displayed.\r
- Selection action may be updated in retrieve callback.\r
- @param FormSet FormSet data structure.\r
-\r
- @retval EFI_SUCCESS The function completed successfully.\r
+ Save globals used by previous call to SendForm(). SendForm() may be called from\r
+ HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
+ So, save globals of previous call to SendForm() and restore them upon exit.\r
\r
**/\r
-EFI_STATUS\r
-LoadFormSetConfig (\r
- IN OUT UI_MENU_SELECTION *Selection,\r
- IN FORM_BROWSER_FORMSET *FormSet\r
+VOID\r
+SaveBrowserContext (\r
+ VOID\r
)\r
{\r
- EFI_STATUS Status;\r
- LIST_ENTRY *Link;\r
- FORM_BROWSER_FORM *Form;\r
-\r
- Link = GetFirstNode (&FormSet->FormListHead);\r
- while (!IsNull (&FormSet->FormListHead, Link)) {\r
- Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ BROWSER_CONTEXT *Context;\r
+ FORM_ENTRY_INFO *MenuList;\r
+ FORM_BROWSER_FORMSET *FormSet;\r
\r
+ gBrowserContextCount++;\r
+ if (gBrowserContextCount == 1) {\r
//\r
- // Initialize local copy of Value for each Form\r
+ // This is not reentry of SendForm(), no context to save\r
//\r
- Status = LoadFormConfig (Selection, FormSet, Form);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ return;\r
+ }\r
\r
- Link = GetNextNode (&FormSet->FormListHead, Link);\r
+ Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
+ ASSERT (Context != NULL);\r
+\r
+ Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
+\r
+ //\r
+ // Save FormBrowser context\r
+ //\r
+ Context->Selection = gCurrentSelection;\r
+ Context->ResetRequired = gResetRequiredFormLevel;\r
+ Context->FlagReconnect = gFlagReconnect;\r
+ Context->CallbackReconnect = gCallbackReconnect;\r
+ Context->ExitRequired = gExitRequired;\r
+ Context->HiiHandle = mCurrentHiiHandle;\r
+ Context->FormId = mCurrentFormId;\r
+ CopyGuid (&Context->FormSetGuid, &mCurrentFormSetGuid);\r
+ Context->SystemLevelFormSet = mSystemLevelFormSet;\r
+ Context->CurFakeQestId = mCurFakeQestId;\r
+ Context->HiiPackageListUpdated = mHiiPackageListUpdated;\r
+ Context->FinishRetrieveCall = mFinishRetrieveCall;\r
+\r
+ //\r
+ // Save the menu history data.\r
+ //\r
+ InitializeListHead (&Context->FormHistoryList);\r
+ while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
+ RemoveEntryList (&MenuList->Link);\r
+\r
+ InsertTailList (&Context->FormHistoryList, &MenuList->Link);\r
}\r
\r
- return EFI_SUCCESS;\r
-}\r
+ //\r
+ // Save formset list.\r
+ //\r
+ InitializeListHead (&Context->FormSetList);\r
+ while (!IsListEmpty (&gBrowserFormSetList)) {\r
+ FormSet = FORM_BROWSER_FORMSET_FROM_LINK (gBrowserFormSetList.ForwardLink);\r
+ RemoveEntryList (&FormSet->Link);\r
\r
-/**\r
- Fill storage's edit copy with settings requested from Configuration Driver.\r
+ InsertTailList (&Context->FormSetList, &FormSet->Link);\r
+ }\r
\r
- @param FormSet FormSet data structure.\r
- @param Storage Buffer Storage.\r
+ //\r
+ // Insert to FormBrowser context list\r
+ //\r
+ InsertHeadList (&gBrowserContextList, &Context->Link);\r
+}\r
\r
- @retval EFI_SUCCESS The function completed successfully.\r
+/**\r
+ Restore globals used by previous call to SendForm().\r
\r
**/\r
-EFI_STATUS\r
-LoadStorage (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORMSET_STORAGE *Storage\r
+VOID\r
+RestoreBrowserContext (\r
+ VOID\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_STRING Progress;\r
- EFI_STRING Result;\r
- CHAR16 *StrPtr;\r
+ LIST_ENTRY *Link;\r
+ BROWSER_CONTEXT *Context;\r
+ FORM_ENTRY_INFO *MenuList;\r
+ FORM_BROWSER_FORMSET *FormSet;\r
\r
- if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
- return EFI_SUCCESS;\r
+ ASSERT (gBrowserContextCount != 0);\r
+ gBrowserContextCount--;\r
+ if (gBrowserContextCount == 0) {\r
+ //\r
+ // This is not reentry of SendForm(), no context to restore\r
+ //\r
+ return;\r
}\r
\r
- if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
- Status = gRT->GetVariable (\r
- Storage->Name,\r
- &Storage->Guid,\r
- NULL,\r
- (UINTN*)&Storage->Size,\r
- Storage->EditBuffer\r
- );\r
- return Status;\r
- }\r
+ ASSERT (!IsListEmpty (&gBrowserContextList));\r
\r
- if (FormSet->ConfigAccess == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
+ Link = GetFirstNode (&gBrowserContextList);\r
+ Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
\r
- if (Storage->ElementCount == 0) {\r
- //\r
- // Skip if there is no RequestElement\r
- //\r
- return EFI_SUCCESS;\r
- }\r
+ //\r
+ // Restore FormBrowser context\r
+ //\r
+ gCurrentSelection = Context->Selection;\r
+ gResetRequiredFormLevel = Context->ResetRequired;\r
+ gFlagReconnect = Context->FlagReconnect;\r
+ gCallbackReconnect = Context->CallbackReconnect;\r
+ gExitRequired = Context->ExitRequired;\r
+ mCurrentHiiHandle = Context->HiiHandle;\r
+ mCurrentFormId = Context->FormId;\r
+ CopyGuid (&mCurrentFormSetGuid, &Context->FormSetGuid);\r
+ mSystemLevelFormSet = Context->SystemLevelFormSet;\r
+ mCurFakeQestId = Context->CurFakeQestId;\r
+ mHiiPackageListUpdated = Context->HiiPackageListUpdated;\r
+ mFinishRetrieveCall = Context->FinishRetrieveCall;\r
\r
//\r
- // Request current settings from Configuration Driver\r
+ // Restore the menu history data.\r
//\r
- Status = FormSet->ConfigAccess->ExtractConfig (\r
- FormSet->ConfigAccess,\r
- Storage->ConfigRequest,\r
- &Progress,\r
- &Result\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ while (!IsListEmpty (&Context->FormHistoryList)) {\r
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (Context->FormHistoryList.ForwardLink);\r
+ RemoveEntryList (&MenuList->Link);\r
+\r
+ InsertTailList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
}\r
\r
//\r
- // Convert Result from <ConfigAltResp> to <ConfigResp>\r
+ // Restore the Formset data.\r
//\r
- StrPtr = StrStr (Result, L"ALTCFG");\r
- if (StrPtr != NULL) {\r
- *StrPtr = L'\0';\r
+ while (!IsListEmpty (&Context->FormSetList)) {\r
+ FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Context->FormSetList.ForwardLink);\r
+ RemoveEntryList (&FormSet->Link);\r
+\r
+ InsertTailList (&gBrowserFormSetList, &FormSet->Link);\r
}\r
\r
- Status = ConfigRespToStorage (Storage, Result);\r
- FreePool (Result);\r
- return Status;\r
+ //\r
+ // Remove from FormBrowser context list\r
+ //\r
+ RemoveEntryList (&Context->Link);\r
+ gBS->FreePool (Context);\r
}\r
\r
-\r
/**\r
- Copy uncommitted data from source Storage to destination Storage.\r
+ Find the matched FormSet context in the backup maintain list based on HiiHandle.\r
\r
- @param Dst Target Storage for uncommitted data.\r
- @param Src Source Storage for uncommitted data.\r
+ @param Handle The Hii Handle.\r
\r
- @retval EFI_SUCCESS The function completed successfully.\r
- @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.\r
+ @return the found FormSet context. If no found, NULL will return.\r
\r
**/\r
-EFI_STATUS\r
-CopyStorage (\r
- IN OUT FORMSET_STORAGE *Dst,\r
- IN FORMSET_STORAGE *Src\r
+FORM_BROWSER_FORMSET *\r
+GetFormSetFromHiiHandle (\r
+ EFI_HII_HANDLE Handle\r
)\r
{\r
- LIST_ENTRY *Link;\r
- NAME_VALUE_NODE *Node;\r
-\r
- if ((Dst->Type != Src->Type) || (Dst->Size != Src->Size)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- switch (Src->Type) {\r
- case EFI_HII_VARSTORE_BUFFER:\r
- case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
- CopyMem (Dst->EditBuffer, Src->EditBuffer, Src->Size);\r
- CopyMem (Dst->Buffer, Src->Buffer, Src->Size);\r
- break;\r
-\r
- case EFI_HII_VARSTORE_NAME_VALUE:\r
- Link = GetFirstNode (&Src->NameValueListHead);\r
- while (!IsNull (&Src->NameValueListHead, Link)) {\r
- Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
-\r
- SetValueByName (Dst, Node->Name, Node->EditValue, TRUE);\r
- SetValueByName (Dst, Node->Name, Node->Value, FALSE);\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORMSET *FormSet;\r
\r
- Link = GetNextNode (&Src->NameValueListHead, Link);\r
+ Link = GetFirstNode (&gBrowserFormSetList);\r
+ while (!IsNull (&gBrowserFormSetList, Link)) {\r
+ FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+ Link = GetNextNode (&gBrowserFormSetList, Link);\r
+ if (!ValidateFormSet (FormSet)) {\r
+ continue;\r
}\r
- break;\r
\r
- case EFI_HII_VARSTORE_EFI_VARIABLE:\r
- default:\r
- break;\r
+ if (FormSet->HiiHandle == Handle) {\r
+ return FormSet;\r
+ }\r
}\r
\r
- return EFI_SUCCESS;\r
+ return NULL;\r
}\r
\r
-\r
/**\r
- Get current setting of Questions.\r
+ Check whether the input HII handle is the FormSet that is being used.\r
\r
- @param FormSet FormSet data structure.\r
+ @param Handle The Hii Handle.\r
\r
- @retval EFI_SUCCESS The function completed successfully.\r
+ @retval TRUE HII handle is being used.\r
+ @retval FALSE HII handle is not being used.\r
\r
**/\r
-EFI_STATUS\r
-InitializeCurrentSetting (\r
- IN OUT FORM_BROWSER_FORMSET *FormSet\r
+BOOLEAN\r
+IsHiiHandleInBrowserContext (\r
+ EFI_HII_HANDLE Handle\r
)\r
{\r
- LIST_ENTRY *Link;\r
- LIST_ENTRY *Link2;\r
- FORMSET_STORAGE *Storage;\r
- FORMSET_STORAGE *StorageSrc;\r
- FORMSET_STORAGE *OldStorage;\r
- FORM_BROWSER_FORM *Form;\r
- FORM_BROWSER_FORM *Form2;\r
- EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ BROWSER_CONTEXT *Context;\r
\r
//\r
- // Extract default from IFR binary\r
+ // HiiHandle is Current FormSet.\r
//\r
- Status = ExtractFormSetDefault (FormSet, EFI_HII_DEFAULT_CLASS_STANDARD);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ if (mCurrentHiiHandle == Handle) {\r
+ return TRUE;\r
}\r
\r
//\r
- // Request current settings from Configuration Driver\r
+ // Check whether HiiHandle is in BrowserContext.\r
//\r
- Link = GetFirstNode (&FormSet->StorageListHead);\r
- while (!IsNull (&FormSet->StorageListHead, Link)) {\r
- Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
-\r
- OldStorage = NULL;\r
- if (gOldFormSet != NULL) {\r
+ Link = GetFirstNode (&gBrowserContextList);\r
+ while (!IsNull (&gBrowserContextList, Link)) {\r
+ Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
+ if (Context->HiiHandle == Handle) {\r
//\r
- // Try to find the Storage in backup formset gOldFormSet\r
+ // HiiHandle is in BrowserContext\r
//\r
- Link2 = GetFirstNode (&gOldFormSet->StorageListHead);\r
- while (!IsNull (&gOldFormSet->StorageListHead, Link2)) {\r
- StorageSrc = FORMSET_STORAGE_FROM_LINK (Link2);\r
+ return TRUE;\r
+ }\r
\r
- if (StorageSrc->VarStoreId == Storage->VarStoreId) {\r
- OldStorage = StorageSrc;\r
- break;\r
- }\r
+ Link = GetNextNode (&gBrowserContextList, Link);\r
+ }\r
\r
- Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2);\r
- }\r
- }\r
+ return FALSE;\r
+}\r
\r
- if (OldStorage == NULL) {\r
- //\r
- // Storage is not found in backup formset, request it from ConfigDriver\r
- //\r
- Status = LoadStorage (FormSet, Storage);\r
- //\r
- // Now Edit Buffer is filled with default values(lower priority) and current\r
- // settings(higher priority), sychronize it to shadow Buffer\r
- //\r
- if (!EFI_ERROR (Status)) {\r
- SynchronizeStorage (Storage, TRUE);\r
- }\r
- } else {\r
- //\r
- // Storage found in backup formset, use it\r
- //\r
- Status = CopyStorage (Storage, OldStorage);\r
+/**\r
+ Perform Password check.\r
+ Passwork may be encrypted by driver that requires the specific check.\r
+\r
+ @param Form Form where Password Statement is in.\r
+ @param Statement Password statement\r
+ @param PasswordString Password string to be checked. It may be NULL.\r
+ NULL means to restore password.\r
+ "" string can be used to checked whether old password does exist.\r
+\r
+ @return Status Status of Password check.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PasswordCheck (\r
+ IN FORM_DISPLAY_ENGINE_FORM *Form,\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
+ IN EFI_STRING PasswordString OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ EFI_IFR_TYPE_VALUE IfrTypeValue;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ ConfigAccess = gCurrentSelection->FormSet->ConfigAccess;\r
+ Question = GetBrowserStatement (Statement);\r
+ ASSERT (Question != NULL);\r
+\r
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) {\r
+ if (ConfigAccess == NULL) {\r
+ return EFI_UNSUPPORTED;\r
}\r
+ } else {\r
+ //\r
+ // If a password doesn't have the CALLBACK flag, browser will not handle it.\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
\r
- Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+ //\r
+ // Prepare password string in HII database\r
+ //\r
+ if (PasswordString != NULL) {\r
+ IfrTypeValue.string = NewString (PasswordString, gCurrentSelection->FormSet->HiiHandle);\r
+ } else {\r
+ IfrTypeValue.string = 0;\r
}\r
\r
//\r
- // If has old formset, get the old nv update status.\r
+ // Send password to Configuration Driver for validation\r
//\r
- if (gOldFormSet != NULL) {\r
- Link = GetFirstNode (&FormSet->FormListHead);\r
- while (!IsNull (&FormSet->FormListHead, Link)) {\r
- Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ Status = ConfigAccess->Callback (\r
+ ConfigAccess,\r
+ EFI_BROWSER_ACTION_CHANGING,\r
+ Question->QuestionId,\r
+ Question->HiiValue.Type,\r
+ &IfrTypeValue,\r
+ &ActionRequest\r
+ );\r
\r
- Link2 = GetFirstNode (&gOldFormSet->FormListHead);\r
- while (!IsNull (&gOldFormSet->FormListHead, Link2)) {\r
- Form2 = FORM_BROWSER_FORM_FROM_LINK (Link2);\r
+ //\r
+ // Remove password string from HII database\r
+ //\r
+ if (PasswordString != NULL) {\r
+ DeleteString (IfrTypeValue.string, gCurrentSelection->FormSet->HiiHandle);\r
+ }\r
\r
- if (Form->FormId == Form2->FormId) {\r
- Form->NvUpdateRequired = Form2->NvUpdateRequired;\r
- break;\r
- }\r
+ return Status;\r
+}\r
\r
- Link2 = GetNextNode (&gOldFormSet->FormListHead, Link2);\r
- }\r
- Link = GetNextNode (&FormSet->FormListHead, Link);\r
- }\r
+/**\r
+ Find the registered HotKey based on KeyData.\r
+\r
+ @param[in] KeyData A pointer to a buffer that describes the keystroke\r
+ information for the hot key.\r
+\r
+ @return The registered HotKey context. If no found, NULL will return.\r
+**/\r
+BROWSER_HOT_KEY *\r
+GetHotKeyFromRegisterList (\r
+ IN EFI_INPUT_KEY *KeyData\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ BROWSER_HOT_KEY *HotKey;\r
+\r
+ Link = GetFirstNode (&gBrowserHotKeyList);\r
+ while (!IsNull (&gBrowserHotKeyList, Link)) {\r
+ HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
+ if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
+ return HotKey;\r
+ }\r
+\r
+ Link = GetNextNode (&gBrowserHotKeyList, Link);\r
}\r
\r
- return EFI_SUCCESS;\r
+ return NULL;\r
}\r
\r
-\r
/**\r
- Fetch the Ifr binary data of a FormSet.\r
+ Configure what scope the hot key will impact.\r
+ All hot keys have the same scope. The mixed hot keys with the different level are not supported.\r
+ If no scope is set, the default scope will be FormSet level.\r
+ After all registered hot keys are removed, previous Scope can reset to another level.\r
\r
- @param Handle PackageList Handle\r
- @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
- specified (NULL or zero GUID), take the first\r
- FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
- found in package list.\r
- On output, GUID of the formset found(if not NULL).\r
- @param BinaryLength The length of the FormSet IFR binary.\r
- @param BinaryData The buffer designed to receive the FormSet.\r
+ @param[in] Scope Scope level to be set.\r
\r
- @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
- BufferLength was updated.\r
- @retval EFI_INVALID_PARAMETER The handle is unknown.\r
- @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
- be found with the requested FormId.\r
+ @retval EFI_SUCCESS Scope is set correctly.\r
+ @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.\r
+ @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.\r
\r
**/\r
EFI_STATUS\r
-GetIfrBinaryData (\r
- IN EFI_HII_HANDLE Handle,\r
- IN OUT EFI_GUID *FormSetGuid,\r
- OUT UINTN *BinaryLength,\r
- OUT UINT8 **BinaryData\r
+EFIAPI\r
+SetScope (\r
+ IN BROWSER_SETTING_SCOPE Scope\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
- UINTN BufferSize;\r
- UINT8 *Package;\r
- UINT8 *OpCodeData;\r
- UINT32 Offset;\r
- UINT32 Offset2;\r
- UINT32 PackageListLength;\r
- EFI_HII_PACKAGE_HEADER PackageHeader;\r
- UINT8 Index;\r
- UINT8 NumberOfClassGuid;\r
- BOOLEAN ClassGuidMatch;\r
- EFI_GUID *ClassGuid;\r
- EFI_GUID *ComparingGuid;\r
+ if (Scope >= MaxLevel) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
- OpCodeData = NULL;\r
- Package = NULL;\r
- ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ //\r
+ // When no hot key registered in system or on the first setting,\r
+ // Scope can be set.\r
+ //\r
+ if (mBrowserScopeFirstSet || IsListEmpty (&gBrowserHotKeyList)) {\r
+ gBrowserSettingScope = Scope;\r
+ mBrowserScopeFirstSet = FALSE;\r
+ } else if (Scope != gBrowserSettingScope) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Register the hot key with its browser action, or unregistered the hot key.\r
+ Only support hot key that is not printable character (control key, function key, etc.).\r
+ If the action value is zero, the hot key will be unregistered if it has been registered.\r
+ If the same hot key has been registered, the new action and help string will override the previous ones.\r
+\r
+ @param[in] KeyData A pointer to a buffer that describes the keystroke\r
+ information for the hot key. Its type is EFI_INPUT_KEY to\r
+ be supported by all ConsoleIn devices.\r
+ @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.\r
+ @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.\r
+ @param[in] HelpString Help string that describes the hot key information.\r
+ Its value may be NULL for the unregistered hot key.\r
+\r
+ @retval EFI_SUCCESS Hot key is registered or unregistered.\r
+ @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.\r
+ @retval EFI_NOT_FOUND KeyData is not found to be unregistered.\r
+ @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.\r
+ @retval EFI_ALREADY_STARTED Key already been registered for one hot key.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterHotKey (\r
+ IN EFI_INPUT_KEY *KeyData,\r
+ IN UINT32 Action,\r
+ IN UINT16 DefaultId,\r
+ IN EFI_STRING HelpString OPTIONAL\r
+ )\r
+{\r
+ BROWSER_HOT_KEY *HotKey;\r
\r
//\r
- // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
+ // Check input parameters.\r
//\r
- if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
- ComparingGuid = &gEfiHiiPlatformSetupFormsetGuid;\r
- } else {\r
- ComparingGuid = FormSetGuid;\r
+ if ((KeyData == NULL) || (KeyData->UnicodeChar != CHAR_NULL) ||\r
+ ((Action != BROWSER_ACTION_UNREGISTER) && (HelpString == NULL)))\r
+ {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
- // Get HII PackageList\r
+ // Check whether the input KeyData is in BrowserHotKeyList.\r
//\r
- BufferSize = 0;\r
- HiiPackageList = NULL;\r
- Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- HiiPackageList = AllocatePool (BufferSize);\r
- ASSERT (HiiPackageList != NULL);\r
+ HotKey = GetHotKeyFromRegisterList (KeyData);\r
\r
- Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+ //\r
+ // Unregister HotKey\r
+ //\r
+ if (Action == BROWSER_ACTION_UNREGISTER) {\r
+ if (HotKey != NULL) {\r
+ //\r
+ // The registered HotKey is found.\r
+ // Remove it from List, and free its resource.\r
+ //\r
+ RemoveEntryList (&HotKey->Link);\r
+ FreePool (HotKey->KeyData);\r
+ FreePool (HotKey->HelpString);\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ //\r
+ // The registered HotKey is not found.\r
+ //\r
+ return EFI_NOT_FOUND;\r
+ }\r
}\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+\r
+ if (HotKey != NULL) {\r
+ return EFI_ALREADY_STARTED;\r
}\r
- ASSERT (HiiPackageList != NULL);\r
\r
//\r
- // Get Form package from this HII package List\r
+ // Create new Key, and add it into List.\r
//\r
- Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
- Offset2 = 0;\r
- CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
+ HotKey = AllocateZeroPool (sizeof (BROWSER_HOT_KEY));\r
+ ASSERT (HotKey != NULL);\r
+ HotKey->Signature = BROWSER_HOT_KEY_SIGNATURE;\r
+ HotKey->KeyData = AllocateCopyPool (sizeof (EFI_INPUT_KEY), KeyData);\r
+ InsertTailList (&gBrowserHotKeyList, &HotKey->Link);\r
\r
- ClassGuidMatch = FALSE;\r
- while (Offset < PackageListLength) {\r
- Package = ((UINT8 *) HiiPackageList) + Offset;\r
- CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ //\r
+ // Fill HotKey information.\r
+ //\r
+ HotKey->Action = Action;\r
+ HotKey->DefaultId = DefaultId;\r
+ if (HotKey->HelpString != NULL) {\r
+ FreePool (HotKey->HelpString);\r
+ }\r
\r
- if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
- //\r
- // Search FormSet in this Form Package\r
- //\r
- Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
- while (Offset2 < PackageHeader.Length) {\r
- OpCodeData = Package + Offset2;\r
+ HotKey->HelpString = AllocateCopyPool (StrSize (HelpString), HelpString);\r
\r
- if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
- //\r
- // Try to compare against formset GUID\r
- //\r
- if (CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
- break;\r
- }\r
+ return EFI_SUCCESS;\r
+}\r
\r
- if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
- //\r
- // Try to compare against formset class GUID\r
- //\r
- NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
- ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
- for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
- if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
- ClassGuidMatch = TRUE;\r
- break;\r
- }\r
- }\r
- if (ClassGuidMatch) {\r
- break;\r
- }\r
- } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
- ClassGuidMatch = TRUE;\r
- break;\r
- }\r
- }\r
+/**\r
+ Register Exit handler function.\r
+ When more than one handler function is registered, the latter one will override the previous one.\r
+ When NULL handler is specified, the previous Exit handler will be unregistered.\r
+\r
+ @param[in] Handler Pointer to handler function.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+RegiserExitHandler (\r
+ IN EXIT_HANDLER Handler\r
+ )\r
+{\r
+ ExitHandlerFunction = Handler;\r
+ return;\r
+}\r
+\r
+/**\r
+ Check whether the browser data has been modified.\r
+\r
+ @retval TRUE Browser data is modified.\r
+ @retval FALSE No browser data is modified.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsBrowserDataModified (\r
+ VOID\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORMSET *FormSet;\r
\r
- Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+ switch (gBrowserSettingScope) {\r
+ case FormLevel:\r
+ if (gCurrentSelection == NULL) {\r
+ return FALSE;\r
}\r
\r
- if (Offset2 < PackageHeader.Length) {\r
- //\r
- // Target formset found\r
- //\r
- break;\r
+ return IsNvUpdateRequiredForForm (gCurrentSelection->Form);\r
+\r
+ case FormSetLevel:\r
+ if (gCurrentSelection == NULL) {\r
+ return FALSE;\r
}\r
- }\r
\r
- Offset += PackageHeader.Length;\r
- }\r
+ return IsNvUpdateRequiredForFormSet (gCurrentSelection->FormSet);\r
\r
- if (Offset >= PackageListLength) {\r
- //\r
- // Form package not found in this Package List\r
- //\r
- FreePool (HiiPackageList);\r
- return EFI_NOT_FOUND;\r
- }\r
+ case SystemLevel:\r
+ Link = GetFirstNode (&gBrowserFormSetList);\r
+ while (!IsNull (&gBrowserFormSetList, Link)) {\r
+ FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+ if (!ValidateFormSet (FormSet)) {\r
+ continue;\r
+ }\r
\r
- if (ClassGuidMatch && (FormSetGuid != NULL)) {\r
- //\r
- // Return the FormSet GUID\r
- //\r
- CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
- }\r
+ if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
+ return TRUE;\r
+ }\r
\r
- //\r
- // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
- // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
- // of the Form Package.\r
- //\r
- *BinaryLength = PackageHeader.Length - Offset2;\r
- *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
+ Link = GetNextNode (&gBrowserFormSetList, Link);\r
+ }\r
\r
- FreePool (HiiPackageList);\r
+ return FALSE;\r
\r
- if (*BinaryData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ default:\r
+ return FALSE;\r
}\r
-\r
- return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
- Initialize the internal data structure of a FormSet.\r
+ Execute the action requested by the Action parameter.\r
\r
- @param Handle PackageList Handle\r
- @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
- specified (NULL or zero GUID), take the first\r
- FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
- found in package list.\r
- On output, GUID of the formset found(if not NULL).\r
- @param FormSet FormSet data structure.\r
+ @param[in] Action Execute the request action.\r
+ @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.\r
\r
- @retval EFI_SUCCESS The function completed successfully.\r
- @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
+ @retval EFI_SUCCESS Execute the request action succss.\r
+ @retval EFI_INVALID_PARAMETER The input action value is invalid.\r
\r
**/\r
EFI_STATUS\r
-InitializeFormSet (\r
- IN EFI_HII_HANDLE Handle,\r
- IN OUT EFI_GUID *FormSetGuid,\r
- OUT FORM_BROWSER_FORMSET *FormSet\r
+EFIAPI\r
+ExecuteAction (\r
+ IN UINT32 Action,\r
+ IN UINT16 DefaultId\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_HANDLE DriverHandle;\r
- UINT16 Index;\r
+ EFI_STATUS Status;\r
+ FORM_BROWSER_FORMSET *FormSet;\r
+ FORM_BROWSER_FORM *Form;\r
\r
- Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ if ((gBrowserSettingScope < SystemLevel) && (gCurrentSelection == NULL)) {\r
+ return EFI_NOT_READY;\r
}\r
\r
- FormSet->HiiHandle = Handle;\r
- CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
-\r
- //\r
- // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
- //\r
- Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- FormSet->DriverHandle = DriverHandle;\r
- Status = gBS->HandleProtocol (\r
- DriverHandle,\r
- &gEfiHiiConfigAccessProtocolGuid,\r
- (VOID **) &FormSet->ConfigAccess\r
- );\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
- // list, then there will be no configuration action required\r
- //\r
- FormSet->ConfigAccess = NULL;\r
+ Status = EFI_SUCCESS;\r
+ FormSet = NULL;\r
+ Form = NULL;\r
+ if (gBrowserSettingScope < SystemLevel) {\r
+ FormSet = gCurrentSelection->FormSet;\r
+ Form = gCurrentSelection->Form;\r
}\r
\r
//\r
- // Parse the IFR binary OpCodes\r
+ // Executet the discard action.\r
//\r
- Status = ParseOpCodes (FormSet);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ if ((Action & BROWSER_ACTION_DISCARD) != 0) {\r
+ Status = DiscardForm (FormSet, Form, gBrowserSettingScope);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
}\r
\r
//\r
- // Set VFR type by FormSet SubClass field\r
+ // Executet the difault action.\r
//\r
- gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;\r
- if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
- gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
+ if ((Action & BROWSER_ACTION_DEFAULT) != 0) {\r
+ Status = ExtractDefault (FormSet, Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ UpdateStatementStatus (FormSet, Form, gBrowserSettingScope);\r
}\r
- \r
+\r
//\r
- // Set VFR type by FormSet class guid\r
+ // Executet the submit action.\r
//\r
- for (Index = 0; Index < 3; Index ++) {\r
- if (CompareGuid (&FormSet->ClassGuid[Index], &gEfiHiiPlatformSetupFormsetGuid)) {\r
- gClassOfVfr |= FORMSET_CLASS_PLATFORM_SETUP;\r
- break;\r
+ if ((Action & BROWSER_ACTION_SUBMIT) != 0) {\r
+ Status = SubmitForm (FormSet, Form, gBrowserSettingScope);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
}\r
\r
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
- gFrontPageHandle = FormSet->HiiHandle;\r
+ //\r
+ // Executet the reset action.\r
+ //\r
+ if ((Action & BROWSER_ACTION_RESET) != 0) {\r
+ gResetRequiredFormLevel = TRUE;\r
+ gResetRequiredSystemLevel = TRUE;\r
}\r
\r
//\r
- // Match GUID to find out the function key setting. If match fail, use the default setting.\r
+ // Executet the exit action.\r
//\r
- for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
- if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
- //\r
- // Update the function key setting.\r
- //\r
- gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
- //\r
- // Function key prompt can not be displayed if the function key has been disabled.\r
- //\r
- if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {\r
- gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
- }\r
-\r
- if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {\r
- gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+ if ((Action & BROWSER_ACTION_EXIT) != 0) {\r
+ DiscardForm (FormSet, Form, gBrowserSettingScope);\r
+ if (gBrowserSettingScope == SystemLevel) {\r
+ if (ExitHandlerFunction != NULL) {\r
+ ExitHandlerFunction ();\r
}\r
}\r
+\r
+ gExitRequired = TRUE;\r
}\r
\r
return Status;\r
}\r
\r
-\r
/**\r
- Save globals used by previous call to SendForm(). SendForm() may be called from \r
- HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
- So, save globals of previous call to SendForm() and restore them upon exit.\r
+ Create reminder to let user to choose save or discard the changed browser data.\r
+ Caller can use it to actively check the changed browser data.\r
+\r
+ @retval BROWSER_NO_CHANGES No browser data is changed.\r
+ @retval BROWSER_SAVE_CHANGES The changed browser data is saved.\r
+ @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.\r
+ @retval BROWSER_KEEP_CURRENT Browser keep current changes.\r
\r
**/\r
-VOID\r
-SaveBrowserContext (\r
+UINT32\r
+EFIAPI\r
+SaveReminder (\r
VOID\r
)\r
{\r
- BROWSER_CONTEXT *Context;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORMSET *FormSet;\r
+ BOOLEAN IsDataChanged;\r
+ UINT32 DataSavedAction;\r
+ UINT32 ConfirmRet;\r
+\r
+ DataSavedAction = BROWSER_NO_CHANGES;\r
+ IsDataChanged = FALSE;\r
+ Link = GetFirstNode (&gBrowserFormSetList);\r
+ while (!IsNull (&gBrowserFormSetList, Link)) {\r
+ FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+ Link = GetNextNode (&gBrowserFormSetList, Link);\r
+ if (!ValidateFormSet (FormSet)) {\r
+ continue;\r
+ }\r
\r
- gBrowserContextCount++;\r
- if (gBrowserContextCount == 1) {\r
- //\r
- // This is not reentry of SendForm(), no context to save\r
- //\r
- return;\r
+ if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
+ IsDataChanged = TRUE;\r
+ break;\r
+ }\r
}\r
\r
- Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
- ASSERT (Context != NULL);\r
-\r
- Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
-\r
//\r
- // Save FormBrowser context\r
+ // No data is changed. No save is required.\r
//\r
- Context->BannerData = gBannerData;\r
- Context->ClassOfVfr = gClassOfVfr;\r
- Context->FunctionKeySetting = gFunctionKeySetting;\r
- Context->ResetRequired = gResetRequired;\r
- Context->Direction = gDirection;\r
- Context->FunctionNineString = gFunctionNineString;\r
- Context->FunctionTenString = gFunctionTenString;\r
- Context->EnterString = gEnterString;\r
- Context->EnterCommitString = gEnterCommitString;\r
- Context->EnterEscapeString = gEnterEscapeString;\r
- Context->EscapeString = gEscapeString;\r
- Context->SaveFailed = gSaveFailed;\r
- Context->MoveHighlight = gMoveHighlight;\r
- Context->MakeSelection = gMakeSelection;\r
- Context->DecNumericInput = gDecNumericInput;\r
- Context->HexNumericInput = gHexNumericInput;\r
- Context->ToggleCheckBox = gToggleCheckBox;\r
- Context->PromptForData = gPromptForData;\r
- Context->PromptForPassword = gPromptForPassword;\r
- Context->PromptForNewPassword = gPromptForNewPassword;\r
- Context->ConfirmPassword = gConfirmPassword;\r
- Context->ConfirmError = gConfirmError;\r
- Context->PassowordInvalid = gPassowordInvalid;\r
- Context->PressEnter = gPressEnter;\r
- Context->EmptyString = gEmptyString;\r
- Context->AreYouSure = gAreYouSure;\r
- Context->YesResponse = gYesResponse;\r
- Context->NoResponse = gNoResponse;\r
- Context->MiniString = gMiniString;\r
- Context->PlusString = gPlusString;\r
- Context->MinusString = gMinusString;\r
- Context->AdjustNumber = gAdjustNumber;\r
- Context->SaveChanges = gSaveChanges;\r
- Context->OptionMismatch = gOptionMismatch;\r
- Context->FormSuppress = gFormSuppress;\r
- Context->PromptBlockWidth = gPromptBlockWidth;\r
- Context->OptionBlockWidth = gOptionBlockWidth;\r
- Context->HelpBlockWidth = gHelpBlockWidth;\r
- Context->OldFormSet = gOldFormSet;\r
- Context->MenuRefreshHead = gMenuRefreshHead;\r
-\r
- CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions));\r
- CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption));\r
+ if (!IsDataChanged) {\r
+ return DataSavedAction;\r
+ }\r
\r
//\r
- // Insert to FormBrowser context list\r
+ // If data is changed, prompt user to save or discard it.\r
//\r
- InsertHeadList (&gBrowserContextList, &Context->Link);\r
-}\r
+ do {\r
+ ConfirmRet = (UINT32)mFormDisplay->ConfirmDataChange ();\r
+\r
+ if (ConfirmRet == BROWSER_ACTION_SUBMIT) {\r
+ SubmitForm (NULL, NULL, SystemLevel);\r
+ DataSavedAction = BROWSER_SAVE_CHANGES;\r
+ break;\r
+ } else if (ConfirmRet == BROWSER_ACTION_DISCARD) {\r
+ DiscardForm (NULL, NULL, SystemLevel);\r
+ DataSavedAction = BROWSER_DISCARD_CHANGES;\r
+ break;\r
+ } else if (ConfirmRet == BROWSER_ACTION_NONE) {\r
+ DataSavedAction = BROWSER_KEEP_CURRENT;\r
+ break;\r
+ }\r
+ } while (1);\r
\r
+ return DataSavedAction;\r
+}\r
\r
/**\r
- Restore globals used by previous call to SendForm().\r
+ Check whether the Reset Required for the browser\r
+\r
+ @retval TRUE Browser required to reset after exit.\r
+ @retval FALSE Browser not need to reset after exit.\r
\r
**/\r
-VOID\r
-RestoreBrowserContext (\r
+BOOLEAN\r
+EFIAPI\r
+IsResetRequired (\r
VOID\r
)\r
{\r
- LIST_ENTRY *Link;\r
- BROWSER_CONTEXT *Context;\r
-\r
- ASSERT (gBrowserContextCount != 0);\r
- gBrowserContextCount--;\r
- if (gBrowserContextCount == 0) {\r
- //\r
- // This is not reentry of SendForm(), no context to restore\r
- //\r
- return;\r
- }\r
-\r
- ASSERT (!IsListEmpty (&gBrowserContextList));\r
-\r
- Link = GetFirstNode (&gBrowserContextList);\r
- Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
-\r
- //\r
- // Restore FormBrowser context\r
- //\r
- gBannerData = Context->BannerData;\r
- gClassOfVfr = Context->ClassOfVfr;\r
- gFunctionKeySetting = Context->FunctionKeySetting;\r
- gResetRequired = Context->ResetRequired;\r
- gDirection = Context->Direction;\r
- gFunctionNineString = Context->FunctionNineString;\r
- gFunctionTenString = Context->FunctionTenString;\r
- gEnterString = Context->EnterString;\r
- gEnterCommitString = Context->EnterCommitString;\r
- gEnterEscapeString = Context->EnterEscapeString;\r
- gEscapeString = Context->EscapeString;\r
- gSaveFailed = Context->SaveFailed;\r
- gMoveHighlight = Context->MoveHighlight;\r
- gMakeSelection = Context->MakeSelection;\r
- gDecNumericInput = Context->DecNumericInput;\r
- gHexNumericInput = Context->HexNumericInput;\r
- gToggleCheckBox = Context->ToggleCheckBox;\r
- gPromptForData = Context->PromptForData;\r
- gPromptForPassword = Context->PromptForPassword;\r
- gPromptForNewPassword = Context->PromptForNewPassword;\r
- gConfirmPassword = Context->ConfirmPassword;\r
- gConfirmError = Context->ConfirmError;\r
- gPassowordInvalid = Context->PassowordInvalid;\r
- gPressEnter = Context->PressEnter;\r
- gEmptyString = Context->EmptyString;\r
- gAreYouSure = Context->AreYouSure;\r
- gYesResponse = Context->YesResponse;\r
- gNoResponse = Context->NoResponse;\r
- gMiniString = Context->MiniString;\r
- gPlusString = Context->PlusString;\r
- gMinusString = Context->MinusString;\r
- gAdjustNumber = Context->AdjustNumber;\r
- gSaveChanges = Context->SaveChanges;\r
- gOptionMismatch = Context->OptionMismatch;\r
- gFormSuppress = Context->FormSuppress;\r
- gPromptBlockWidth = Context->PromptBlockWidth;\r
- gOptionBlockWidth = Context->OptionBlockWidth;\r
- gHelpBlockWidth = Context->HelpBlockWidth;\r
- gOldFormSet = Context->OldFormSet;\r
- gMenuRefreshHead = Context->MenuRefreshHead;\r
-\r
- CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions));\r
- CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption));\r
-\r
- //\r
- // Remove from FormBrowser context list\r
- //\r
- RemoveEntryList (&Context->Link);\r
- gBS->FreePool (Context);\r
+ return gResetRequiredSystemLevel;\r
}\r