X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FSetupBrowserDxe%2FSetup.c;h=66238e055f29b3949dd91ce6e5e4468c1c15a5f6;hb=7248790ee958c41b4ba2284f3b6835f1c3e505be;hp=33b3a8eec570d820aa7fb1b1391f4a3eeaf9e04c;hpb=80a047f04a9005c37580532307d8c7c4b337fe4b;p=mirror_edk2.git diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c index 33b3a8eec5..66238e055f 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c @@ -26,166 +26,294 @@ SETUP_DRIVER_PRIVATE_DATA mPrivateData = { RegisterHotKey, RegiserExitHandler, SaveReminder + }, + { + BROWSER_EXTENSION2_VERSION_1, + SetScope, + RegisterHotKey, + RegiserExitHandler, + IsBrowserDataModified, + ExecuteAction, } }; EFI_HII_DATABASE_PROTOCOL *mHiiDatabase; -EFI_HII_STRING_PROTOCOL *mHiiString; EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting; EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mPathFromText; +EDKII_FORM_DISPLAY_ENGINE_PROTOCOL *mFormDisplay; UINTN gBrowserContextCount = 0; LIST_ENTRY gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList); LIST_ENTRY gBrowserFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList); LIST_ENTRY gBrowserHotKeyList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList); +LIST_ENTRY gBrowserStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList); -BANNER_DATA *gBannerData; -EFI_HII_HANDLE gFrontPageHandle; -UINTN gClassOfVfr; -UINTN gFunctionKeySetting; +BOOLEAN gFinishRetrieveCall; BOOLEAN gResetRequired; -EFI_HII_HANDLE gHiiHandle; -UINT16 gDirection; -EFI_SCREEN_DESCRIPTOR gScreenDimensions; +BOOLEAN gExitRequired; BROWSER_SETTING_SCOPE gBrowserSettingScope = FormSetLevel; BOOLEAN mBrowserScopeFirstSet = TRUE; EXIT_HANDLER ExitHandlerFunction = NULL; -UINTN gFooterHeight; +FORM_BROWSER_FORMSET *mSystemLevelFormSet; // // Browser Global Strings // -CHAR16 *gSaveFailed; -CHAR16 *gDiscardFailed; -CHAR16 *gDefaultFailed; -CHAR16 *gEnterString; -CHAR16 *gEnterCommitString; -CHAR16 *gEnterEscapeString; -CHAR16 *gEscapeString; -CHAR16 *gMoveHighlight; -CHAR16 *gMakeSelection; -CHAR16 *gDecNumericInput; -CHAR16 *gHexNumericInput; -CHAR16 *gToggleCheckBox; -CHAR16 *gPromptForData; -CHAR16 *gPromptForPassword; -CHAR16 *gPromptForNewPassword; -CHAR16 *gConfirmPassword; -CHAR16 *gConfirmError; -CHAR16 *gPassowordInvalid; -CHAR16 *gPressEnter; CHAR16 *gEmptyString; -CHAR16 *gAreYouSure; -CHAR16 *gYesResponse; -CHAR16 *gNoResponse; -CHAR16 *gMiniString; -CHAR16 *gPlusString; -CHAR16 *gMinusString; -CHAR16 *gAdjustNumber; -CHAR16 *gSaveChanges; -CHAR16 *gOptionMismatch; -CHAR16 *gFormSuppress; -CHAR16 *gProtocolNotFound; - CHAR16 *mUnknownString = L"!"; -CHAR16 gPromptBlockWidth; -CHAR16 gOptionBlockWidth; -CHAR16 gHelpBlockWidth; - EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}; -EFI_GUID gSetupBrowserGuid = { - 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32} -}; -FORM_BROWSER_FORMSET *gOldFormSet = NULL; +extern UINT32 gBrowserStatus; +extern CHAR16 *gErrorInfo; +extern EFI_GUID mCurrentFormSetGuid; +extern EFI_HII_HANDLE mCurrentHiiHandle; +extern UINT16 mCurrentFormId; +extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData; + +/** + Create a menu with specified formset GUID and form ID, and add it as a child + of the given parent menu. + + @param HiiHandle Hii handle related to this formset. + @param FormSetGuid The Formset Guid of menu to be added. + @param FormId The Form ID of menu to be added. + @param QuestionId The question id of this menu to be added. + + @return A pointer to the newly added menu or NULL if memory is insufficient. + +**/ +FORM_ENTRY_INFO * +UiAddMenuList ( + IN EFI_HII_HANDLE HiiHandle, + IN EFI_GUID *FormSetGuid, + IN UINT16 FormId, + IN UINT16 QuestionId + ) +{ + FORM_ENTRY_INFO *MenuList; + + MenuList = AllocateZeroPool (sizeof (FORM_ENTRY_INFO)); + if (MenuList == NULL) { + return NULL; + } + + MenuList->Signature = FORM_ENTRY_INFO_SIGNATURE; + + MenuList->HiiHandle = HiiHandle; + CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID)); + MenuList->FormId = FormId; + MenuList->QuestionId = QuestionId; -FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = { // - // Boot Manager + // If parent is not specified, it is the root Form of a Formset // - { - { - 0x847bc3fe, - 0xb974, - 0x446d, - { - 0x94, - 0x49, - 0x5a, - 0xd5, - 0x41, - 0x2e, - 0x99, - 0x3b + InsertTailList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link); + + return MenuList; +} + +/** + Return the form id for the input hiihandle and formset. + + @param HiiHandle HiiHandle for FormSet. + @param FormSetGuid The Formset GUID of the menu to search. + + @return First form's id for this form set. + +**/ +EFI_FORM_ID +GetFirstFormId ( + IN EFI_HII_HANDLE HiiHandle, + IN EFI_GUID *FormSetGuid + ) +{ + LIST_ENTRY *Link; + FORM_BROWSER_FORM *Form; + + Link = GetFirstNode (&gCurrentSelection->FormSet->FormListHead); + Form = FORM_BROWSER_FORM_FROM_LINK (Link); + + return Form->FormId; +} + +/** + Search Menu with given FormSetGuid and FormId in all cached menu list. + + @param HiiHandle HiiHandle for FormSet. + @param FormSetGuid The Formset GUID of the menu to search. + @param FormId The Form ID of menu to search. + + @return A pointer to menu found or NULL if not found. + +**/ +FORM_ENTRY_INFO * +UiFindMenuList ( + IN EFI_HII_HANDLE HiiHandle, + IN EFI_GUID *FormSetGuid, + IN UINT16 FormId + ) +{ + LIST_ENTRY *Link; + FORM_ENTRY_INFO *MenuList; + FORM_ENTRY_INFO *RetMenu; + EFI_FORM_ID FirstFormId; + + RetMenu = NULL; + + Link = GetFirstNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead); + while (!IsNull (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link)) { + MenuList = FORM_ENTRY_INFO_FROM_LINK (Link); + Link = GetNextNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link); + + // + // If already find the menu, free the menus behind it. + // + if (RetMenu != NULL) { + RemoveEntryList (&MenuList->Link); + FreePool (MenuList); + continue; + } + + // + // Find the same FromSet. + // + if (MenuList->HiiHandle == HiiHandle) { + if (CompareGuid (&MenuList->FormSetGuid, &gZeroGuid)) { + // + // FormSetGuid is not specified. + // + RetMenu = MenuList; + } else if (CompareGuid (&MenuList->FormSetGuid, FormSetGuid)) { + if (MenuList->FormId == FormId) { + RetMenu = MenuList; + } else if (FormId == 0 || MenuList->FormId == 0 ) { + FirstFormId = GetFirstFormId (HiiHandle, FormSetGuid); + if ((FormId == 0 && FirstFormId == MenuList->FormId) || (MenuList->FormId ==0 && FirstFormId == FormId)) { + RetMenu = MenuList; + } + } } - }, - NONE_FUNCTION_KEY_SETTING - }, + } + } + + return RetMenu; +} + +/** + Find parent menu for current menu. + + @param CurrentMenu Current Menu + + @retval The parent menu for current menu. +**/ +FORM_ENTRY_INFO * +UiFindParentMenu ( + IN FORM_ENTRY_INFO *CurrentMenu + ) +{ + FORM_ENTRY_INFO *ParentMenu; + + ParentMenu = NULL; + if (CurrentMenu->Link.BackLink != &mPrivateData.FormBrowserEx2.FormViewHistoryHead) { + ParentMenu = FORM_ENTRY_INFO_FROM_LINK (CurrentMenu->Link.BackLink); + } + + return ParentMenu; +} + +/** + Free Menu list linked list. + + @param MenuListHead One Menu list point in the menu list. + +**/ +VOID +UiFreeMenuList ( + LIST_ENTRY *MenuListHead + ) +{ + FORM_ENTRY_INFO *MenuList; + + while (!IsListEmpty (MenuListHead)) { + MenuList = FORM_ENTRY_INFO_FROM_LINK (MenuListHead->ForwardLink); + RemoveEntryList (&MenuList->Link); + + FreePool (MenuList); + } +} + +/** + Load all hii formset to the browser. + +**/ +VOID +LoadAllHiiFormset ( + VOID + ) +{ + FORM_BROWSER_FORMSET *LocalFormSet; + EFI_HII_HANDLE *HiiHandles; + UINTN Index; + EFI_GUID ZeroGuid; + EFI_STATUS Status; + FORM_BROWSER_FORMSET *OldFormset; + BOOLEAN OldRetrieveValue; + + OldFormset = mSystemLevelFormSet; + OldRetrieveValue = gFinishRetrieveCall; + gFinishRetrieveCall = FALSE; + // - // Device Manager + // Get all the Hii handles // - { - { - 0x3ebfa8e6, - 0x511d, - 0x4b5b, - { - 0xa9, - 0x5f, - 0xfb, - 0x38, - 0x26, - 0xf, - 0x1c, - 0x27 - } - }, - NONE_FUNCTION_KEY_SETTING - }, + HiiHandles = HiiGetHiiHandles (NULL); + ASSERT (HiiHandles != NULL); + // - // BMM FormSet. + // Search for formset of each class type // - { - { - 0x642237c7, - 0x35d4, - 0x472d, - { - 0x83, - 0x65, - 0x12, - 0xe0, - 0xcc, - 0xf2, - 0x7a, - 0x22 - } - }, - NONE_FUNCTION_KEY_SETTING - }, + for (Index = 0; HiiHandles[Index] != NULL; Index++) { + // + // Check HiiHandles[Index] does exist in global maintain list. + // + if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) { + continue; + } + + // + // Initilize FormSet Setting + // + LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET)); + ASSERT (LocalFormSet != NULL); + mSystemLevelFormSet = LocalFormSet; + + ZeroMem (&ZeroGuid, sizeof (ZeroGuid)); + Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet); + if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) { + DestroyFormSet (LocalFormSet); + continue; + } + InitializeCurrentSetting (LocalFormSet); + + // + // Initilize Questions' Value + // + Status = LoadFormSetConfig (NULL, LocalFormSet); + if (EFI_ERROR (Status)) { + DestroyFormSet (LocalFormSet); + continue; + } + } + // - // BMM File Explorer FormSet. + // Free resources, and restore gOldFormSet and gClassOfVfr // - { - { - 0x1f2d63e1, - 0xfebd, - 0x4dc7, - { - 0x9c, - 0xc5, - 0xba, - 0x2b, - 0x1c, - 0xef, - 0x9c, - 0x5b - } - }, - NONE_FUNCTION_KEY_SETTING - }, -}; + FreePool (HiiHandles); + + gFinishRetrieveCall = OldRetrieveValue; + mSystemLevelFormSet = OldFormset; +} /** This is the routine which an external caller uses to direct the browser @@ -228,89 +356,26 @@ SendForm ( UI_MENU_SELECTION *Selection; UINTN Index; FORM_BROWSER_FORMSET *FormSet; - LIST_ENTRY *Link; + FORM_ENTRY_INFO *MenuList; // - // Calculate total number of Register HotKeys. + // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED. // - Index = 0; - Link = GetFirstNode (&gBrowserHotKeyList); - while (!IsNull (&gBrowserHotKeyList, Link)) { - Link = GetNextNode (&gBrowserHotKeyList, Link); - Index ++; + if (mFormDisplay == NULL) { + return EFI_UNSUPPORTED; } - // - // Show three HotKeys help information on one ROW. - // - gFooterHeight = FOOTER_HEIGHT + (Index / 3); // // Save globals used by SendForm() // SaveBrowserContext (); + gFinishRetrieveCall = FALSE; gResetRequired = FALSE; - Status = EFI_SUCCESS; - ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); - - // - // Seed the dimensions in the global - // - gST->ConOut->QueryMode ( - gST->ConOut, - gST->ConOut->Mode->Mode, - &gScreenDimensions.RightColumn, - &gScreenDimensions.BottomRow - ); - - if (ScreenDimensions != NULL) { - // - // Check local dimension vs. global dimension. - // - if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) || - (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow) - ) { - Status = EFI_INVALID_PARAMETER; - goto Done; - } else { - // - // Local dimension validation. - // - if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) && - (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) && - ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) && - ( - (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT + - SCROLL_ARROW_HEIGHT * - 2 + - FRONT_PAGE_HEADER_HEIGHT + - gFooterHeight + - 1 - ) - ) { - CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); - } else { - Status = EFI_INVALID_PARAMETER; - goto Done; - } - } - } - - gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3); - gPromptBlockWidth = (CHAR16) (gOptionBlockWidth + LEFT_SKIPPED_COLUMNS); - gHelpBlockWidth = (CHAR16) (gOptionBlockWidth - LEFT_SKIPPED_COLUMNS); - - // - // Initialize the strings for the browser, upon exit of the browser, the strings will be freed - // - InitializeBrowserStrings (); - - gFunctionKeySetting = ENABLE_FUNCTION_KEY_SETTING; - - // - // Ensure we are in Text mode - // - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gExitRequired = FALSE; + Status = EFI_SUCCESS; + gEmptyString = L""; + gDisplayFormData.ScreenDimensions = (EFI_SCREEN_DESCRIPTOR *) ScreenDimensions; for (Index = 0; Index < HandleCount; Index++) { Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION)); @@ -331,17 +396,13 @@ SendForm ( // // Initialize internal data structures of FormSet // - Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet, TRUE); + Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet); if (EFI_ERROR (Status) || IsListEmpty (&FormSet->FormListHead)) { DestroyFormSet (FormSet); break; } Selection->FormSet = FormSet; - - // - // Try to find pre FormSet in the maintain backup list. - // - gOldFormSet = GetFormSetFromHiiHandle (Selection->Handle); + mSystemLevelFormSet = FormSet; // // Display this formset @@ -351,27 +412,38 @@ SendForm ( Status = SetupBrowser (Selection); gCurrentSelection = NULL; + mSystemLevelFormSet = NULL; - if (EFI_ERROR (Status)) { - break; - } - - } while (Selection->Action == UI_ACTION_REFRESH_FORMSET); - - if (gOldFormSet != NULL) { // // If no data is changed, don't need to save current FormSet into the maintain list. // - if (!IsNvUpdateRequired (gOldFormSet)) { - RemoveEntryList (&gOldFormSet->Link); - DestroyFormSet (gOldFormSet); + if (!IsNvUpdateRequiredForFormSet (FormSet) && !IsStorageDataChangedForFormSet(FormSet)) { + CleanBrowserStorage(FormSet); + RemoveEntryList (&FormSet->Link); + DestroyFormSet (FormSet); } - gOldFormSet = NULL; - } + + if (EFI_ERROR (Status)) { + break; + } + } while (Selection->Action == UI_ACTION_REFRESH_FORMSET); FreePool (Selection); } + // + // Still has error info, pop up a message. + // + if (gBrowserStatus != BROWSER_SUCCESS) { + gDisplayFormData.BrowserStatus = gBrowserStatus; + gDisplayFormData.ErrorString = gErrorInfo; + + gBrowserStatus = BROWSER_SUCCESS; + gErrorInfo = NULL; + + mFormDisplay->FormDisplay (&gDisplayFormData, NULL); + } + if (ActionRequest != NULL) { *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; if (gResetRequired) { @@ -379,12 +451,17 @@ SendForm ( } } - FreeBrowserStrings (); + mFormDisplay->ExitDisplay(); - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); - gST->ConOut->ClearScreen (gST->ConOut); + // + // Clear the menu history data. + // + while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) { + MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink); + RemoveEntryList (&MenuList->Link); + FreePool (MenuList); + } -Done: // // Restore globals used by SendForm() // @@ -393,10 +470,93 @@ Done: return Status; } +/** + Get or set data to the storage. + + @param ResultsDataSize The size of the buffer associatedwith ResultsData. + @param ResultsData A string returned from an IFR browser or + equivalent. The results string will have no + routing information in them. + @param RetrieveData A BOOLEAN field which allows an agent to retrieve + (if RetrieveData = TRUE) data from the uncommitted + browser state information or set (if RetrieveData + = FALSE) data in the uncommitted browser state + information. + @param Storage The pointer to the storage. + + @retval EFI_SUCCESS The results have been distributed or are awaiting + distribution. + +**/ +EFI_STATUS +ProcessStorage ( + IN OUT UINTN *ResultsDataSize, + IN OUT EFI_STRING *ResultsData, + IN BOOLEAN RetrieveData, + IN BROWSER_STORAGE *Storage + ) +{ + CHAR16 *ConfigResp; + EFI_STATUS Status; + CHAR16 *StrPtr; + UINTN BufferSize; + UINTN TmpSize; + + if (RetrieveData) { + // + // Generate + // + Status = StorageToConfigResp (Storage, &ConfigResp, Storage->ConfigRequest, TRUE); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Skip and '&' to point to when first copy the configbody. + // Also need to consider add "\0" at first time. + // + StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1; + BufferSize = StrSize (StrPtr); + + + // + // Copy the data if the input buffer is bigger enough. + // + if (*ResultsDataSize >= BufferSize) { + StrCpy (*ResultsData, StrPtr); + } + + *ResultsDataSize = BufferSize; + FreePool (ConfigResp); + } else { + // + // Prepare + // + TmpSize = StrLen (*ResultsData); + BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16); + ConfigResp = AllocateZeroPool (BufferSize); + ASSERT (ConfigResp != NULL); + + StrCpy (ConfigResp, Storage->ConfigHdr); + StrCat (ConfigResp, L"&"); + StrCat (ConfigResp, *ResultsData); + + // + // Update Browser uncommited data + // + Status = ConfigRespToStorage (Storage, ConfigResp); + FreePool (ConfigResp); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} /** - This function is called by a callback handler to retrieve uncommitted state - data from the browser. + This routine called this service in the browser to retrieve or set certain uncommitted + state information that resides in the open formsets. @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL instance. @@ -434,60 +594,79 @@ BrowserCallback ( { EFI_STATUS Status; LIST_ENTRY *Link; - FORMSET_STORAGE *Storage; - FORM_BROWSER_FORMSET *FormSet; + BROWSER_STORAGE *Storage; + FORMSET_STORAGE *FormsetStorage; + UINTN TotalSize; BOOLEAN Found; - CHAR16 *ConfigResp; - CHAR16 *StrPtr; - UINTN BufferSize; - UINTN TmpSize; if (ResultsDataSize == NULL || ResultsData == NULL) { return EFI_INVALID_PARAMETER; } - if (gCurrentSelection == NULL) { - return EFI_NOT_READY; - } - - Storage = NULL; - ConfigResp = NULL; - FormSet = gCurrentSelection->FormSet; + TotalSize = *ResultsDataSize; + Storage = NULL; + Found = FALSE; + Status = EFI_SUCCESS; // - // Find target storage + // If set browser data, pre load all hii formset to avoid set the varstore which is not + // saved in browser. // - Link = GetFirstNode (&FormSet->StorageListHead); - if (IsNull (&FormSet->StorageListHead, Link)) { - return EFI_UNSUPPORTED; + if (!RetrieveData && (gBrowserSettingScope == SystemLevel)) { + LoadAllHiiFormset(); } if (VariableGuid != NULL) { // - // Try to find target storage + // Try to find target storage in the current formset. // - Found = FALSE; - while (!IsNull (&FormSet->StorageListHead, Link)) { - Storage = FORMSET_STORAGE_FROM_LINK (Link); - Link = GetNextNode (&FormSet->StorageListHead, Link); + Link = GetFirstNode (&gBrowserStorageList); + while (!IsNull (&gBrowserStorageList, Link)) { + Storage = BROWSER_STORAGE_FROM_LINK (Link); + Link = GetNextNode (&gBrowserStorageList, Link); + // + // Check the current storage. + // + if (!CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) { + continue; + } - if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) { - if (Storage->Type == EFI_HII_VARSTORE_BUFFER || - Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { - // - // Buffer storage require both GUID and Name - // - if (VariableName == NULL) { - return EFI_NOT_FOUND; - } + if (Storage->Type == EFI_HII_VARSTORE_BUFFER || + Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { + // + // Buffer storage require both GUID and Name + // + if (VariableName == NULL) { + return EFI_NOT_FOUND; + } - if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) { - continue; - } + if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) { + continue; } - Found = TRUE; - break; } + + if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE || + Storage->Type == EFI_HII_VARSTORE_BUFFER) { + if (mSystemLevelFormSet == NULL || mSystemLevelFormSet->HiiHandle == NULL) { + return EFI_NOT_FOUND; + } + + if (Storage->HiiHandle != mSystemLevelFormSet->HiiHandle) { + continue; + } + } + + Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, Storage); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Different formsets may have same varstore, so here just set the flag + // not exit the circle. + // + Found = TRUE; + break; } if (!Found) { @@ -497,125 +676,61 @@ BrowserCallback ( // // GUID/Name is not specified, take the first storage in FormSet // - Storage = FORMSET_STORAGE_FROM_LINK (Link); - } - - if (RetrieveData) { - // - // Skip if there is no RequestElement - // - if (Storage->ElementCount == 0) { - return EFI_SUCCESS; + if (mSystemLevelFormSet == NULL) { + return EFI_NOT_READY; } // // Generate // - Status = StorageToConfigResp (Storage, &ConfigResp, FALSE); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Skip and '&' to point to - // - StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1; - - BufferSize = StrSize (StrPtr); - if (*ResultsDataSize < BufferSize) { - *ResultsDataSize = BufferSize; - - FreePool (ConfigResp); - return EFI_BUFFER_TOO_SMALL; + Link = GetFirstNode (&mSystemLevelFormSet->StorageListHead); + if (IsNull (&mSystemLevelFormSet->StorageListHead, Link)) { + return EFI_UNSUPPORTED; } - *ResultsDataSize = BufferSize; - CopyMem (ResultsData, StrPtr, BufferSize); - - FreePool (ConfigResp); - } else { - // - // Prepare - // - TmpSize = StrLen (ResultsData); - BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16); - ConfigResp = AllocateZeroPool (BufferSize); - ASSERT (ConfigResp != NULL); - - StrCpy (ConfigResp, Storage->ConfigHdr); - StrCat (ConfigResp, L"&"); - StrCat (ConfigResp, ResultsData); - - // - // Update Browser uncommited data - // - Status = ConfigRespToStorage (Storage, ConfigResp); + FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link); + + Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, FormsetStorage->BrowserStorage); if (EFI_ERROR (Status)) { return Status; } } - return EFI_SUCCESS; -} - -/** - Notify function will remove the formset in the maintain list - once this formset is removed. - - Functions which are registered to receive notification of - database events have this prototype. The actual event is encoded - in NotifyType. The following table describes how PackageType, - PackageGuid, Handle, and Package are used for each of the - notification types. - - @param PackageType Package type of the notification. + if (RetrieveData) { + Status = TotalSize <= *ResultsDataSize ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL; + *ResultsDataSize = TotalSize; + } + + return Status; - @param PackageGuid If PackageType is - EFI_HII_PACKAGE_TYPE_GUID, then this is - the pointer to the GUID from the Guid - field of EFI_HII_PACKAGE_GUID_HEADER. - Otherwise, it must be NULL. +} - @param Package Points to the package referred to by the - notification Handle The handle of the package - list which contains the specified package. - @param Handle The HII handle. +/** + Callback function for SimpleTextInEx protocol install events - @param NotifyType The type of change concerning the - database. See - EFI_HII_DATABASE_NOTIFY_TYPE. + @param Event the event that is signaled. + @param Context not used here. **/ -EFI_STATUS +VOID EFIAPI -FormsetRemoveNotify ( - IN UINT8 PackageType, - IN CONST EFI_GUID *PackageGuid, - IN CONST EFI_HII_PACKAGE_HEADER *Package, - IN EFI_HII_HANDLE Handle, - IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType +FormDisplayCallback ( + IN EFI_EVENT Event, + IN VOID *Context ) { - FORM_BROWSER_FORMSET *FormSet; + EFI_STATUS Status; - // - // Ignore the update for current using formset, which is handled by another notify function. - // - if (IsHiiHandleInBrowserContext (Handle)) { - return EFI_SUCCESS; - } - - // - // Remove the backup FormSet data when the Form Package is removed. - // - FormSet = GetFormSetFromHiiHandle (Handle); - if (FormSet != NULL) { - RemoveEntryList (&FormSet->Link); - DestroyFormSet (FormSet); + if (mFormDisplay != NULL) { + return; } - - return EFI_SUCCESS; + + Status = gBS->LocateProtocol ( + &gEdkiiFormDisplayEngineProtocolGuid, + NULL, + (VOID **) &mFormDisplay + ); } /** @@ -636,9 +751,7 @@ InitializeSetup ( ) { EFI_STATUS Status; - EFI_HANDLE NotifyHandle; - EFI_INPUT_KEY DefaultHotKey; - EFI_STRING HelpString; + VOID *Registration; // // Locate required Hii relative protocols @@ -650,13 +763,6 @@ InitializeSetup ( ); ASSERT_EFI_ERROR (Status); - Status = gBS->LocateProtocol ( - &gEfiHiiStringProtocolGuid, - NULL, - (VOID **) &mHiiString - ); - ASSERT_EFI_ERROR (Status); - Status = gBS->LocateProtocol ( &gEfiHiiConfigRoutingProtocolGuid, NULL, @@ -670,30 +776,6 @@ InitializeSetup ( (VOID **) &mPathFromText ); - // - // Publish our HII data - // - gHiiHandle = HiiAddPackages ( - &gSetupBrowserGuid, - ImageHandle, - SetupBrowserStrings, - NULL - ); - ASSERT (gHiiHandle != NULL); - - // - // Initialize Driver private data - // - gBannerData = AllocateZeroPool (sizeof (BANNER_DATA)); - ASSERT (gBannerData != NULL); - - // - // Initialize generic help strings. - // - gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle); - gDiscardFailed = GetToken (STRING_TOKEN (DISCARD_FAILED), gHiiHandle); - gDefaultFailed = GetToken (STRING_TOKEN (DEFAULT_FAILED), gHiiHandle); - // // Install FormBrowser2 protocol // @@ -707,25 +789,19 @@ InitializeSetup ( ASSERT_EFI_ERROR (Status); // - // Install default HotKey F10 for Save - // - DefaultHotKey.UnicodeChar = CHAR_NULL; - HelpString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle); - DefaultHotKey.ScanCode = SCAN_F10; - RegisterHotKey (&DefaultHotKey, BROWSER_ACTION_SUBMIT, 0, HelpString); - FreePool (HelpString); - // - // Install default HotKey F9 for Reset To Defaults - // - DefaultHotKey.ScanCode = SCAN_F9; - HelpString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle); - RegisterHotKey (&DefaultHotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, HelpString); - FreePool (HelpString); - - // - // Install FormBrowserEx protocol + // Install FormBrowserEx2 protocol // + InitializeListHead (&mPrivateData.FormBrowserEx2.FormViewHistoryHead); + InitializeListHead (&mPrivateData.FormBrowserEx2.OverrideQestListHead); mPrivateData.Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &mPrivateData.Handle, + &gEdkiiFormBrowserEx2ProtocolGuid, + EFI_NATIVE_INTERFACE, + &mPrivateData.FormBrowserEx2 + ); + ASSERT_EFI_ERROR (Status); + Status = gBS->InstallProtocolInterface ( &mPrivateData.Handle, &gEfiFormBrowserExProtocolGuid, @@ -734,20 +810,25 @@ InitializeSetup ( ); ASSERT_EFI_ERROR (Status); - // - // Register notify for Form package remove - // - Status = mHiiDatabase->RegisterPackageNotify ( - mHiiDatabase, - EFI_HII_PACKAGE_FORMS, - NULL, - FormsetRemoveNotify, - EFI_HII_DATABASE_NOTIFY_REMOVE_PACK, - &NotifyHandle - ); - ASSERT_EFI_ERROR (Status); + InitializeDisplayFormData (); - return Status; + Status = gBS->LocateProtocol ( + &gEdkiiFormDisplayEngineProtocolGuid, + NULL, + (VOID **) &mFormDisplay + ); + + if (EFI_ERROR (Status)) { + EfiCreateProtocolNotifyEvent ( + &gEdkiiFormDisplayEngineProtocolGuid, + TPL_CALLBACK, + FormDisplayCallback, + NULL, + &Registration + ); + } + + return EFI_SUCCESS; } @@ -883,58 +964,6 @@ NewStringCat ( *Dest = NewString; } - -/** - Synchronize or restore Storage's Edit copy and Shadow copy. - - @param Storage The Storage to be synchronized. - @param SyncOrRestore Sync the buffer to editbuffer or Restore the - editbuffer to buffer - if TRUE, copy the editbuffer to the buffer. - if FALSE, copy the buffer to the editbuffer. - -**/ -VOID -SynchronizeStorage ( - IN FORMSET_STORAGE *Storage, - IN BOOLEAN SyncOrRestore - ) -{ - LIST_ENTRY *Link; - NAME_VALUE_NODE *Node; - - switch (Storage->Type) { - case EFI_HII_VARSTORE_BUFFER: - case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER: - if (SyncOrRestore) { - CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size); - } else { - CopyMem (Storage->EditBuffer, Storage->Buffer, Storage->Size); - } - break; - - case EFI_HII_VARSTORE_NAME_VALUE: - Link = GetFirstNode (&Storage->NameValueListHead); - while (!IsNull (&Storage->NameValueListHead, Link)) { - Node = NAME_VALUE_NODE_FROM_LINK (Link); - - if (SyncOrRestore) { - NewStringCpy (&Node->Value, Node->EditValue); - } else { - NewStringCpy (&Node->EditValue, Node->Value); - } - - Link = GetNextNode (&Storage->NameValueListHead, Link); - } - break; - - case EFI_HII_VARSTORE_EFI_VARIABLE: - default: - break; - } -} - - /** Get Value for given Name from a NameValue Storage. @@ -949,7 +978,7 @@ SynchronizeStorage ( **/ EFI_STATUS GetValueByName ( - IN FORMSET_STORAGE *Storage, + IN BROWSER_STORAGE *Storage, IN CHAR16 *Name, IN OUT CHAR16 **Value, IN GET_SET_QUESTION_VALUE_WITH GetValueFrom @@ -991,6 +1020,7 @@ GetValueByName ( @param Name The Name. @param Value The Value to set. @param SetValueTo Whether update editValue or Value. + @param ReturnNode The node use the input name. @retval EFI_SUCCESS Value found for given Name. @retval EFI_NOT_FOUND No such Name found in NameValue storage. @@ -998,10 +1028,11 @@ GetValueByName ( **/ EFI_STATUS SetValueByName ( - IN FORMSET_STORAGE *Storage, - IN CHAR16 *Name, - IN CHAR16 *Value, - IN GET_SET_QUESTION_VALUE_WITH SetValueTo + IN BROWSER_STORAGE *Storage, + IN CHAR16 *Name, + IN CHAR16 *Value, + IN GET_SET_QUESTION_VALUE_WITH SetValueTo, + OUT NAME_VALUE_NODE **ReturnNode ) { LIST_ENTRY *Link; @@ -1032,6 +1063,11 @@ SetValueByName ( } else { Node->Value = Buffer; } + + if (ReturnNode != NULL) { + *ReturnNode = Node; + } + return EFI_SUCCESS; } @@ -1045,9 +1081,10 @@ SetValueByName ( /** Convert setting of Buffer Storage or NameValue Storage to . - @param Buffer The Storage to be conveted. + @param Storage The Storage to be conveted. @param ConfigResp The returned . - @param SingleForm Whether update data for single form or formset level. + @param ConfigRequest The ConfigRequest string. + @param GetEditBuf Get the data from editbuffer or buffer. @retval EFI_SUCCESS Convert success. @retval EFI_INVALID_PARAMETER Incorrect storage type. @@ -1055,36 +1092,28 @@ SetValueByName ( **/ EFI_STATUS StorageToConfigResp ( - IN VOID *Buffer, + IN BROWSER_STORAGE *Storage, IN CHAR16 **ConfigResp, - IN BOOLEAN SingleForm + IN CHAR16 *ConfigRequest, + IN BOOLEAN GetEditBuf ) { - EFI_STATUS Status; - EFI_STRING Progress; + EFI_STATUS Status; + EFI_STRING Progress; LIST_ENTRY *Link; NAME_VALUE_NODE *Node; - CHAR16 *ConfigRequest; - FORMSET_STORAGE *Storage; - FORM_BROWSER_CONFIG_REQUEST *ConfigInfo; + UINT8 *SourceBuf; Status = EFI_SUCCESS; - if (SingleForm) { - ConfigInfo = (FORM_BROWSER_CONFIG_REQUEST *) Buffer; - Storage = ConfigInfo->Storage; - ConfigRequest = ConfigInfo->ConfigRequest; - } else { - Storage = (FORMSET_STORAGE *) Buffer; - ConfigRequest = Storage->ConfigRequest; - } switch (Storage->Type) { case EFI_HII_VARSTORE_BUFFER: case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER: + SourceBuf = GetEditBuf ? Storage->EditBuffer : Storage->Buffer; Status = mHiiConfigRouting->BlockToConfig ( mHiiConfigRouting, ConfigRequest, - Storage->EditBuffer, + SourceBuf, Storage->Size, ConfigResp, &Progress @@ -1103,7 +1132,11 @@ StorageToConfigResp ( NewStringCat (ConfigResp, L"&"); NewStringCat (ConfigResp, Node->Name); NewStringCat (ConfigResp, L"="); - NewStringCat (ConfigResp, Node->EditValue); + if (GetEditBuf) { + NewStringCat (ConfigResp, Node->EditValue); + } else { + NewStringCat (ConfigResp, Node->Value); + } } Link = GetNextNode (&Storage->NameValueListHead, Link); } @@ -1131,7 +1164,7 @@ StorageToConfigResp ( **/ EFI_STATUS ConfigRespToStorage ( - IN FORMSET_STORAGE *Storage, + IN BROWSER_STORAGE *Storage, IN CHAR16 *ConfigResp ) { @@ -1184,7 +1217,7 @@ ConfigRespToStorage ( if (StrPtr != NULL) { *StrPtr = 0; } - SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer); + SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer, NULL); } break; @@ -1223,7 +1256,7 @@ GetQuestionValue ( UINT8 *Dst; UINTN StorageWidth; EFI_TIME EfiTime; - FORMSET_STORAGE *Storage; + BROWSER_STORAGE *Storage; EFI_IFR_TYPE_VALUE *QuestionValue; CHAR16 *ConfigRequest; CHAR16 *Progress; @@ -1237,7 +1270,6 @@ GetQuestionValue ( BOOLEAN IsString; CHAR16 TemStr[5]; UINT8 DigitUint8; - UINT8 *TemBuffer; Status = EFI_SUCCESS; Value = NULL; @@ -1247,13 +1279,6 @@ GetQuestionValue ( return EFI_INVALID_PARAMETER; } - // - // Statement don't have storage, skip them - // - if (Question->QuestionId == 0) { - return Status; - } - // // Question value is provided by an Expression, evaluate it // @@ -1461,147 +1486,118 @@ GetQuestionValue ( FreePool (Value); } } else { - if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { - // - // Request current settings from Configuration Driver - // - if (FormSet->ConfigAccess == NULL) { + // + // ::= + || + // + "&" + + // + if (IsBufferStorage) { + Length = StrLen (Storage->ConfigHdr); + Length += StrLen (Question->BlockName); + } else { + Length = StrLen (Storage->ConfigHdr); + Length += StrLen (Question->VariableName) + 1; + } + ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16)); + ASSERT (ConfigRequest != NULL); + + StrCpy (ConfigRequest, Storage->ConfigHdr); + if (IsBufferStorage) { + StrCat (ConfigRequest, Question->BlockName); + } else { + StrCat (ConfigRequest, L"&"); + StrCat (ConfigRequest, Question->VariableName); + } + + // + // Request current settings from Configuration Driver + // + Status = mHiiConfigRouting->ExtractConfig ( + mHiiConfigRouting, + ConfigRequest, + &Progress, + &Result + ); + FreePool (ConfigRequest); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Skip + // + if (IsBufferStorage) { + Value = StrStr (Result, L"&VALUE"); + if (Value == NULL) { + FreePool (Result); return EFI_NOT_FOUND; } - // - // ::= + || - // + "&" + + // Skip "&VALUE" // - if (IsBufferStorage) { - Length = StrLen (Storage->ConfigHdr); - Length += StrLen (Question->BlockName); - } else { - Length = StrLen (Storage->ConfigHdr); - Length += StrLen (Question->VariableName) + 1; - } - ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16)); - ASSERT (ConfigRequest != NULL); - - StrCpy (ConfigRequest, Storage->ConfigHdr); - if (IsBufferStorage) { - StrCat (ConfigRequest, Question->BlockName); - } else { - StrCat (ConfigRequest, L"&"); - StrCat (ConfigRequest, Question->VariableName); - } + Value = Value + 6; + } else { + Value = Result + Length; + } + if (*Value != '=') { + FreePool (Result); + return EFI_NOT_FOUND; + } + // + // Skip '=', point to value + // + Value = Value + 1; - Status = FormSet->ConfigAccess->ExtractConfig ( - FormSet->ConfigAccess, - ConfigRequest, - &Progress, - &Result - ); - FreePool (ConfigRequest); - if (EFI_ERROR (Status)) { - return Status; - } + // + // Suppress if any + // + StringPtr = Value; + while (*StringPtr != L'\0' && *StringPtr != L'&') { + StringPtr++; + } + *StringPtr = L'\0'; + LengthStr = StrLen (Value); + Status = EFI_SUCCESS; + if (!IsBufferStorage && IsString) { // - // Skip + // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD" + // Add string tail char L'\0' into Length // - if (IsBufferStorage) { - Value = StrStr (Result, L"&VALUE"); - if (Value == NULL) { - FreePool (Result); - return EFI_NOT_FOUND; + Length = StorageWidth + sizeof (CHAR16); + if (Length < ((LengthStr / 4 + 1) * 2)) { + Status = EFI_BUFFER_TOO_SMALL; + } else { + StringPtr = (CHAR16 *) Dst; + ZeroMem (TemStr, sizeof (TemStr)); + for (Index = 0; Index < LengthStr; Index += 4) { + StrnCpy (TemStr, Value + Index, 4); + StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr); } // - // Skip "&VALUE" + // Add tailing L'\0' character // - Value = Value + 6; + StringPtr[Index/4] = L'\0'; + } + } else { + if (StorageWidth < ((LengthStr + 1) / 2)) { + Status = EFI_BUFFER_TOO_SMALL; } else { - Value = Result + Length; + ZeroMem (TemStr, sizeof (TemStr)); + for (Index = 0; Index < LengthStr; Index ++) { + TemStr[0] = Value[LengthStr - Index - 1]; + DigitUint8 = (UINT8) StrHexToUint64 (TemStr); + if ((Index & 1) == 0) { + Dst [Index/2] = DigitUint8; + } else { + Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]); + } + } } - if (*Value != '=') { - FreePool (Result); - return EFI_NOT_FOUND; - } - // - // Skip '=', point to value - // - Value = Value + 1; - - // - // Suppress if any - // - StringPtr = Value; - while (*StringPtr != L'\0' && *StringPtr != L'&') { - StringPtr++; - } - *StringPtr = L'\0'; - - LengthStr = StrLen (Value); - Status = EFI_SUCCESS; - if (!IsBufferStorage && IsString) { - // - // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD" - // Add string tail char L'\0' into Length - // - Length = StorageWidth + sizeof (CHAR16); - if (Length < ((LengthStr / 4 + 1) * 2)) { - Status = EFI_BUFFER_TOO_SMALL; - } else { - StringPtr = (CHAR16 *) Dst; - ZeroMem (TemStr, sizeof (TemStr)); - for (Index = 0; Index < LengthStr; Index += 4) { - StrnCpy (TemStr, Value + Index, 4); - StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr); - } - // - // Add tailing L'\0' character - // - StringPtr[Index/4] = L'\0'; - } - } else { - if (StorageWidth < ((LengthStr + 1) / 2)) { - Status = EFI_BUFFER_TOO_SMALL; - } else { - ZeroMem (TemStr, sizeof (TemStr)); - for (Index = 0; Index < LengthStr; Index ++) { - TemStr[0] = Value[LengthStr - Index - 1]; - DigitUint8 = (UINT8) StrHexToUint64 (TemStr); - if ((Index & 1) == 0) { - Dst [Index/2] = DigitUint8; - } else { - Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]); - } - } - } - } - - if (EFI_ERROR (Status)) { - FreePool (Result); - return Status; - } - } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { - TemBuffer = NULL; - TemBuffer = AllocateZeroPool (Storage->Size); - if (TemBuffer == NULL) { - Status = EFI_OUT_OF_RESOURCES; - return Status; - } - Length = Storage->Size; - Status = gRT->GetVariable ( - Storage->Name, - &Storage->Guid, - NULL, - &Length, - TemBuffer - ); - if (EFI_ERROR (Status)) { - FreePool (TemBuffer); - return Status; - } - - CopyMem (Dst, TemBuffer + Question->VarStoreInfo.VarOffset, StorageWidth); + } - FreePool (TemBuffer); + if (EFI_ERROR (Status)) { + FreePool (Result); + return Status; } // @@ -1610,7 +1606,7 @@ GetQuestionValue ( if (IsBufferStorage) { CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth); } else { - SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer); + SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer, NULL); } if (Result != NULL) { @@ -1648,7 +1644,7 @@ SetQuestionValue ( EFI_TIME EfiTime; UINTN BufferLen; UINTN StorageWidth; - FORMSET_STORAGE *Storage; + BROWSER_STORAGE *Storage; EFI_IFR_TYPE_VALUE *QuestionValue; CHAR16 *ConfigResp; CHAR16 *Progress; @@ -1660,20 +1656,15 @@ SetQuestionValue ( CHAR16 *TemName; CHAR16 *TemString; UINTN Index; + NAME_VALUE_NODE *Node; Status = EFI_SUCCESS; + Node = NULL; if (SetValueTo >= GetSetValueWithMax) { return EFI_INVALID_PARAMETER; } - // - // Statement don't have storage, skip them - // - if (Question->QuestionId == 0) { - return Status; - } - // // If Question value is provided by an Expression, then it is read only // @@ -1796,6 +1787,14 @@ SetQuestionValue ( // CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth); } + // + // Check whether question value has been changed. + // + if (CompareMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth) != 0) { + Question->ValueChanged = TRUE; + } else { + Question->ValueChanged = FALSE; + } } else { if (IsString) { // @@ -1827,115 +1826,93 @@ SetQuestionValue ( } } - Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo); + Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo, &Node); FreePool (Value); - } - } else if (SetValueTo == GetSetValueWithHiiDriver) { - if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + if (EFI_ERROR (Status)) { + return Status; + } // - // ::= + + "&VALUE=" + "StorageWidth * 2" || - // + "&" + + "=" + "" + // Check whether question value has been changed. // - if (IsBufferStorage) { - Length = StrLen (Question->BlockName) + 7; - } else { - Length = StrLen (Question->VariableName) + 2; - } - if (!IsBufferStorage && IsString) { - Length += (StrLen ((CHAR16 *) Src) * 4); - } else { - Length += (StorageWidth * 2); - } - ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16)); - ASSERT (ConfigResp != NULL); - - StrCpy (ConfigResp, Storage->ConfigHdr); - if (IsBufferStorage) { - StrCat (ConfigResp, Question->BlockName); - StrCat (ConfigResp, L"&VALUE="); + if (StrCmp (Node->Value, Node->EditValue) != 0) { + Question->ValueChanged = TRUE; } else { - StrCat (ConfigResp, L"&"); - StrCat (ConfigResp, Question->VariableName); - StrCat (ConfigResp, L"="); + Question->ValueChanged = FALSE; } + } + } else if (SetValueTo == GetSetValueWithHiiDriver) { + // + // ::= + + "&VALUE=" + "StorageWidth * 2" || + // + "&" + + "=" + "" + // + if (IsBufferStorage) { + Length = StrLen (Question->BlockName) + 7; + } else { + Length = StrLen (Question->VariableName) + 2; + } + if (!IsBufferStorage && IsString) { + Length += (StrLen ((CHAR16 *) Src) * 4); + } else { + Length += (StorageWidth * 2); + } + ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16)); + ASSERT (ConfigResp != NULL); - Value = ConfigResp + StrLen (ConfigResp); + StrCpy (ConfigResp, Storage->ConfigHdr); + if (IsBufferStorage) { + StrCat (ConfigResp, Question->BlockName); + StrCat (ConfigResp, L"&VALUE="); + } else { + StrCat (ConfigResp, L"&"); + StrCat (ConfigResp, Question->VariableName); + StrCat (ConfigResp, L"="); + } - if (!IsBufferStorage && IsString) { - // - // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044" - // - TemName = (CHAR16 *) Src; - TemString = Value; - for (; *TemName != L'\0'; TemName++) { - TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4); - } - } else { - // - // Convert Buffer to Hex String - // - TemBuffer = Src + StorageWidth - 1; - TemString = Value; - for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) { - TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2); - } - } + Value = ConfigResp + StrLen (ConfigResp); + if (!IsBufferStorage && IsString) { // - // Convert to lower char. + // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044" // - for (TemString = Value; *Value != L'\0'; Value++) { - if (*Value >= L'A' && *Value <= L'Z') { - *Value = (CHAR16) (*Value - L'A' + L'a'); - } + TemName = (CHAR16 *) Src; + TemString = Value; + for (; *TemName != L'\0'; TemName++) { + TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4); } - + } else { // - // Submit Question Value to Configuration Driver + // Convert Buffer to Hex String // - if (FormSet->ConfigAccess != NULL) { - Status = FormSet->ConfigAccess->RouteConfig ( - FormSet->ConfigAccess, - ConfigResp, - &Progress - ); - if (EFI_ERROR (Status)) { - FreePool (ConfigResp); - return Status; - } - } - FreePool (ConfigResp); - - } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { - TemBuffer = NULL; - TemBuffer = AllocateZeroPool(Storage->Size); - if (TemBuffer == NULL) { - Status = EFI_OUT_OF_RESOURCES; - return Status; + TemBuffer = Src + StorageWidth - 1; + TemString = Value; + for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) { + TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2); } - Length = Storage->Size; - Status = gRT->GetVariable ( - Storage->Name, - &Storage->Guid, - NULL, - &Length, - TemBuffer - ); - - CopyMem (TemBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth); - - Status = gRT->SetVariable ( - Storage->Name, - &Storage->Guid, - Storage->Attributes, - Storage->Size, - TemBuffer - ); - FreePool (TemBuffer); - if (EFI_ERROR (Status)){ - return Status; + } + + // + // Convert to lower char. + // + for (TemString = Value; *Value != L'\0'; Value++) { + if (*Value >= L'A' && *Value <= L'Z') { + *Value = (CHAR16) (*Value - L'A' + L'a'); } } + + // + // Submit Question Value to Configuration Driver + // + Status = mHiiConfigRouting->RouteConfig ( + mHiiConfigRouting, + ConfigResp, + &Progress + ); + if (EFI_ERROR (Status)) { + FreePool (ConfigResp); + return Status; + } + FreePool (ConfigResp); + // // Sync storage, from editbuffer to buffer. // @@ -1947,12 +1924,12 @@ SetQuestionValue ( /** - Perform inconsistent check for a Form. + Perform nosubmitif check for a Form. @param FormSet FormSet data structure. @param Form Form data structure. @param Question The Question to be validated. - @param Type Validation type: InConsistent or NoSubmit + @param Type Validation type: NoSubmit @retval EFI_SUCCESS Form validation pass. @retval other Form validation failed. @@ -1970,12 +1947,9 @@ ValidateQuestion ( LIST_ENTRY *Link; LIST_ENTRY *ListHead; EFI_STRING PopUp; - EFI_INPUT_KEY Key; FORM_EXPRESSION *Expression; - if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) { - ListHead = &Question->InconsistentListHead; - } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) { + if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) { ListHead = &Question->NoSubmitListHead; } else { return EFI_UNSUPPORTED; @@ -1999,10 +1973,10 @@ ValidateQuestion ( // if (Expression->Error != 0) { PopUp = GetToken (Expression->Error, FormSet->HiiHandle); - do { - CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - FreePool (PopUp); + if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) { + gBrowserStatus = BROWSER_NO_SUBMIT_IF; + gErrorInfo = PopUp; + } } return EFI_NOT_READY; @@ -2066,7 +2040,8 @@ NoSubmitCheck ( Fill storage's edit copy with settings requested from Configuration Driver. @param FormSet FormSet data structure. - @param ConfigInfo The config info related to this form. + @param Storage The storage which need to sync. + @param ConfigRequest The config request string which used to sync storage. @param SyncOrRestore Sync the buffer to editbuffer or Restore the editbuffer to buffer if TRUE, copy the editbuffer to the buffer. @@ -2076,10 +2051,11 @@ NoSubmitCheck ( **/ EFI_STATUS -SynchronizeStorageForForm ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_CONFIG_REQUEST *ConfigInfo, - IN BOOLEAN SyncOrRestore +SynchronizeStorage ( + IN FORM_BROWSER_FORMSET *FormSet, + OUT BROWSER_STORAGE *Storage, + IN CHAR16 *ConfigRequest, + IN BOOLEAN SyncOrRestore ) { EFI_STATUS Status; @@ -2093,57 +2069,52 @@ SynchronizeStorageForForm ( Status = EFI_SUCCESS; Result = NULL; - if (FormSet->ConfigAccess == NULL && ConfigInfo->Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) { - return EFI_NOT_FOUND; - } - - if (ConfigInfo->ElementCount == 0) { - // - // Skip if there is no RequestElement - // - return EFI_SUCCESS; - } - if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_BUFFER || - (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) { - BufferSize = ConfigInfo->Storage->Size; + if (Storage->Type == EFI_HII_VARSTORE_BUFFER || + (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) { + BufferSize = Storage->Size; if (SyncOrRestore) { - Src = ConfigInfo->Storage->EditBuffer; - Dst = ConfigInfo->Storage->Buffer; + Src = Storage->EditBuffer; + Dst = Storage->Buffer; } else { - Src = ConfigInfo->Storage->Buffer; - Dst = ConfigInfo->Storage->EditBuffer; + Src = Storage->Buffer; + Dst = Storage->EditBuffer; } - Status = mHiiConfigRouting->BlockToConfig( - mHiiConfigRouting, - ConfigInfo->ConfigRequest, - Src, - BufferSize, - &Result, - &Progress - ); - if (EFI_ERROR (Status)) { - return Status; - } + if (ConfigRequest != NULL) { + Status = mHiiConfigRouting->BlockToConfig( + mHiiConfigRouting, + ConfigRequest, + Src, + BufferSize, + &Result, + &Progress + ); + if (EFI_ERROR (Status)) { + return Status; + } - Status = mHiiConfigRouting->ConfigToBlock ( - mHiiConfigRouting, - Result, - Dst, - &BufferSize, - &Progress - ); - if (Result != NULL) { - FreePool (Result); + Status = mHiiConfigRouting->ConfigToBlock ( + mHiiConfigRouting, + Result, + Dst, + &BufferSize, + &Progress + ); + if (Result != NULL) { + FreePool (Result); + } + } else { + CopyMem (Dst, Src, BufferSize); } - } else if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { - Link = GetFirstNode (&ConfigInfo->Storage->NameValueListHead); - while (!IsNull (&ConfigInfo->Storage->NameValueListHead, Link)) { + } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + Link = GetFirstNode (&Storage->NameValueListHead); + while (!IsNull (&Storage->NameValueListHead, Link)) { Node = NAME_VALUE_NODE_FROM_LINK (Link); - if (StrStr (ConfigInfo->ConfigRequest, Node->Name) != NULL) { + if ((ConfigRequest != NULL && StrStr (ConfigRequest, Node->Name) != NULL) || + (ConfigRequest == NULL)) { if (SyncOrRestore) { NewStringCpy (&Node->Value, Node->EditValue); } else { @@ -2151,7 +2122,7 @@ SynchronizeStorageForForm ( } } - Link = GetNextNode (&ConfigInfo->Storage->NameValueListHead, Link); + Link = GetNextNode (&Storage->NameValueListHead, Link); } } @@ -2174,20 +2145,9 @@ SendDiscardInfoToDriver ( { LIST_ENTRY *Link; FORM_BROWSER_STATEMENT *Question; - EFI_STATUS Status; - EFI_HII_VALUE HiiValue; - UINT8 *BufferValue; - BOOLEAN ValueChanged; EFI_IFR_TYPE_VALUE *TypeValue; EFI_BROWSER_ACTION_REQUEST ActionRequest; - ValueChanged = FALSE; - BufferValue = NULL; - - if(!Form->NvUpdateRequired) { - return; - } - Link = GetFirstNode (&Form->StatementListHead); while (!IsNull (&Form->StatementListHead, Link)) { Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link); @@ -2201,45 +2161,10 @@ SendDiscardInfoToDriver ( continue; } - if (Question->BufferValue != NULL) { - BufferValue = AllocateZeroPool (Question->StorageWidth); - ASSERT (BufferValue != NULL); - CopyMem (BufferValue, Question->BufferValue, Question->StorageWidth); - } else { - HiiValue.Type = Question->HiiValue.Type; - CopyMem (&HiiValue.Value, &Question->HiiValue.Value, sizeof (EFI_IFR_TYPE_VALUE)); - } - - Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer); - if (EFI_ERROR (Status)) { - if (BufferValue != NULL) { - FreePool (BufferValue); - BufferValue = NULL; - } - continue; - } - - if (Question->BufferValue != NULL) { - if (CompareMem (BufferValue, Question->BufferValue, Question->StorageWidth)) { - ValueChanged = TRUE; - } - } else { - if (CompareMem (&HiiValue.Value, &Question->HiiValue.Value, sizeof (EFI_IFR_TYPE_VALUE))) { - ValueChanged = TRUE; - } - } - - if (BufferValue != NULL) { - FreePool (BufferValue); - BufferValue = NULL; - } - - if (!ValueChanged) { + if (!Question->ValueChanged) { continue; } - ValueChanged = FALSE; - if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) { TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue; } else { @@ -2259,57 +2184,177 @@ SendDiscardInfoToDriver ( } /** - Discard data based on the input setting scope (Form, FormSet or System). + Validate the FormSet. If the formset is not validate, remove it from the list. - @param FormSet FormSet data structure. - @param Form Form data structure. - @param SettingScope Setting Scope for Discard action. + @param FormSet The input FormSet which need to validate. - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_UNSUPPORTED Unsupport SettingScope. + @retval TRUE The handle is validate. + @retval FALSE The handle is invalidate. **/ -EFI_STATUS -DiscardForm ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORM *Form, - IN BROWSER_SETTING_SCOPE SettingScope +BOOLEAN +ValidateFormSet ( + FORM_BROWSER_FORMSET *FormSet ) { - LIST_ENTRY *Link; - FORMSET_STORAGE *Storage; - FORM_BROWSER_CONFIG_REQUEST *ConfigInfo; - FORM_BROWSER_FORMSET *LocalFormSet; + EFI_HII_HANDLE *HiiHandles; + UINTN Index; + BOOLEAN Find; + ASSERT (FormSet != NULL); + Find = FALSE; // - // Check the supported setting level. + // Get all the Hii handles // - if (SettingScope >= MaxLevel) { - return EFI_UNSUPPORTED; + HiiHandles = HiiGetHiiHandles (NULL); + ASSERT (HiiHandles != NULL); + + // + // Search for formset of each class type + // + for (Index = 0; HiiHandles[Index] != NULL; Index++) { + if (HiiHandles[Index] == FormSet->HiiHandle) { + Find = TRUE; + break; + } } - if (SettingScope == FormLevel && Form->NvUpdateRequired) { - ConfigInfo = NULL; - Link = GetFirstNode (&Form->ConfigRequestHead); - while (!IsNull (&Form->ConfigRequestHead, Link)) { - ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link); - Link = GetNextNode (&Form->ConfigRequestHead, Link); + if (!Find) { + CleanBrowserStorage(FormSet); + RemoveEntryList (&FormSet->Link); + DestroyFormSet (FormSet); + } - if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { - continue; - } + FreePool (HiiHandles); - // - // Skip if there is no RequestElement - // - if (ConfigInfo->ElementCount == 0) { - continue; - } + return Find; +} +/** + Check whether need to enable the reset flag in form level. + Also clean all ValueChanged flag in question. - // + @param SetFlag Whether need to set the Reset Flag. + @param Form Form data structure. + +**/ +VOID +UpdateFlagForForm ( + IN BOOLEAN SetFlag, + IN FORM_BROWSER_FORM *Form + ) +{ + LIST_ENTRY *Link; + FORM_BROWSER_STATEMENT *Question; + BOOLEAN FindOne; + + FindOne = FALSE; + Link = GetFirstNode (&Form->StatementListHead); + while (!IsNull (&Form->StatementListHead, Link)) { + Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link); + + if (SetFlag && Question->ValueChanged && ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) { + gResetRequired = TRUE; + } + + if (Question->ValueChanged) { + Question->ValueChanged = FALSE; + } + + Link = GetNextNode (&Form->StatementListHead, Link); + } +} + +/** + Check whether need to enable the reset flag. + Also clean ValueChanged flag for all statements. + + Form level or formset level, only one. + + @param SetFlag Whether need to set the Reset Flag. + @param FormSet FormSet data structure. + @param Form Form data structure. + +**/ +VOID +ValueChangeResetFlagUpdate ( + IN BOOLEAN SetFlag, + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_FORM *Form + ) +{ + FORM_BROWSER_FORM *CurrentForm; + LIST_ENTRY *Link; + + // + // Form != NULL means only check form level. + // + if (Form != NULL) { + UpdateFlagForForm(SetFlag, Form); + return; + } + + Link = GetFirstNode (&FormSet->FormListHead); + while (!IsNull (&FormSet->FormListHead, Link)) { + CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link); + Link = GetNextNode (&FormSet->FormListHead, Link); + + UpdateFlagForForm(SetFlag, CurrentForm); + } +} + +/** + Discard data based on the input setting scope (Form, FormSet or System). + + @param FormSet FormSet data structure. + @param Form Form data structure. + @param SettingScope Setting Scope for Discard action. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_UNSUPPORTED Unsupport SettingScope. + +**/ +EFI_STATUS +DiscardForm ( + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_FORM *Form, + IN BROWSER_SETTING_SCOPE SettingScope + ) +{ + LIST_ENTRY *Link; + FORMSET_STORAGE *Storage; + FORM_BROWSER_CONFIG_REQUEST *ConfigInfo; + FORM_BROWSER_FORMSET *LocalFormSet; + FORM_BROWSER_FORMSET *OldFormSet; + + // + // Check the supported setting level. + // + if (SettingScope >= MaxLevel) { + return EFI_UNSUPPORTED; + } + + if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) { + ConfigInfo = NULL; + Link = GetFirstNode (&Form->ConfigRequestHead); + while (!IsNull (&Form->ConfigRequestHead, Link)) { + ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link); + Link = GetNextNode (&Form->ConfigRequestHead, Link); + + if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { + continue; + } + + // + // Skip if there is no RequestElement + // + if (ConfigInfo->ElementCount == 0) { + continue; + } + + // // Prepare // - SynchronizeStorageForForm(FormSet, ConfigInfo, FALSE); + SynchronizeStorage(FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE); // // Call callback with Changed type to inform the driver. @@ -2317,8 +2362,8 @@ DiscardForm ( SendDiscardInfoToDriver (FormSet, Form); } - Form->NvUpdateRequired = FALSE; - } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) { + ValueChangeResetFlagUpdate (FALSE, NULL, Form); + } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) { // // Discard Buffer storage or Name/Value storage @@ -2328,7 +2373,7 @@ DiscardForm ( Storage = FORMSET_STORAGE_FROM_LINK (Link); Link = GetNextNode (&FormSet->StorageListHead, Link); - if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { + if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { continue; } @@ -2339,7 +2384,7 @@ DiscardForm ( continue; } - SynchronizeStorage(Storage, FALSE); + SynchronizeStorage(FormSet, Storage->BrowserStorage, Storage->ConfigRequest, FALSE); } Link = GetFirstNode (&FormSet->FormListHead); @@ -2353,28 +2398,38 @@ DiscardForm ( SendDiscardInfoToDriver (FormSet, Form); } - UpdateNvInfoInForm (FormSet, FALSE); + ValueChangeResetFlagUpdate(FALSE, FormSet, NULL); } else if (SettingScope == SystemLevel) { // // System Level Discard. // - + OldFormSet = mSystemLevelFormSet; + // // Discard changed value for each FormSet in the maintain list. // Link = GetFirstNode (&gBrowserFormSetList); while (!IsNull (&gBrowserFormSetList, Link)) { LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link); - DiscardForm (LocalFormSet, NULL, FormSetLevel); Link = GetNextNode (&gBrowserFormSetList, Link); + if (!ValidateFormSet(LocalFormSet)) { + continue; + } + + mSystemLevelFormSet = LocalFormSet; + + DiscardForm (LocalFormSet, NULL, FormSetLevel); if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) { // // Remove maintain backup list after discard except for the current using FormSet. // + CleanBrowserStorage(LocalFormSet); RemoveEntryList (&LocalFormSet->Link); DestroyFormSet (LocalFormSet); } } + + mSystemLevelFormSet = OldFormSet; } return EFI_SUCCESS; @@ -2402,9 +2457,8 @@ SubmitForm ( LIST_ENTRY *Link; EFI_STRING ConfigResp; EFI_STRING Progress; - FORMSET_STORAGE *Storage; - UINTN BufferSize; - UINT8 *TmpBuf; + BROWSER_STORAGE *Storage; + FORMSET_STORAGE *FormSetStorage; FORM_BROWSER_FORMSET *LocalFormSet; FORM_BROWSER_CONFIG_REQUEST *ConfigInfo; @@ -2428,7 +2482,7 @@ SubmitForm ( return Status; } - if (SettingScope == FormLevel && Form->NvUpdateRequired) { + if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) { ConfigInfo = NULL; Link = GetFirstNode (&Form->ConfigRequestHead); while (!IsNull (&Form->ConfigRequestHead, Link)) { @@ -2450,96 +2504,43 @@ SubmitForm ( // // 1. Prepare // - Status = StorageToConfigResp (ConfigInfo, &ConfigResp, TRUE); + Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE); if (EFI_ERROR (Status)) { return Status; } // - // 2. Set value to hii driver or efi variable. + // 2. Set value to hii config routine protocol. // - if (Storage->Type == EFI_HII_VARSTORE_BUFFER || - Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { - // - // Send to Configuration Driver - // - if (FormSet->ConfigAccess != NULL) { - Status = FormSet->ConfigAccess->RouteConfig ( - FormSet->ConfigAccess, - ConfigResp, - &Progress - ); - if (EFI_ERROR (Status)) { - FreePool (ConfigResp); - return Status; - } - } - } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { - TmpBuf = NULL; - TmpBuf = AllocateZeroPool(Storage->Size); - if (TmpBuf == NULL) { - Status = EFI_OUT_OF_RESOURCES; - return Status; - } - - BufferSize = Storage->Size; - Status = gRT->GetVariable ( - Storage->Name, - &Storage->Guid, - NULL, - &BufferSize, - TmpBuf - ); - if (EFI_ERROR (Status)) { - FreePool (TmpBuf); - FreePool (ConfigResp); - return Status; - } - ASSERT (BufferSize == Storage->Size); - Status = mHiiConfigRouting->ConfigToBlock ( - mHiiConfigRouting, - ConfigResp, - TmpBuf, - &BufferSize, - &Progress - ); - if (EFI_ERROR (Status)) { - FreePool (TmpBuf); - FreePool (ConfigResp); - return Status; - } - - Status = gRT->SetVariable ( - Storage->Name, - &Storage->Guid, - Storage->Attributes, - Storage->Size, - TmpBuf - ); - FreePool (TmpBuf); - if (EFI_ERROR (Status)) { - FreePool (ConfigResp); - return Status; - } + Status = mHiiConfigRouting->RouteConfig ( + mHiiConfigRouting, + ConfigResp, + &Progress + ); + if (EFI_ERROR (Status)) { + FreePool (ConfigResp); + return Status; } + FreePool (ConfigResp); // // 3. Config success, update storage shadow Buffer, only update the data belong to this form. // - SynchronizeStorageForForm(FormSet, ConfigInfo, TRUE); + SynchronizeStorage (FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE); } // // 4. Update the NV flag. // - Form->NvUpdateRequired = FALSE; - } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) { + ValueChangeResetFlagUpdate(TRUE, NULL, Form); + } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) { // // Submit Buffer storage or Name/Value storage // Link = GetFirstNode (&FormSet->StorageListHead); while (!IsNull (&FormSet->StorageListHead, Link)) { - Storage = FORMSET_STORAGE_FROM_LINK (Link); + FormSetStorage = (FORMSET_STORAGE_FROM_LINK (Link)); + Storage = FormSetStorage->BrowserStorage; Link = GetNextNode (&FormSet->StorageListHead, Link); if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { @@ -2549,92 +2550,42 @@ SubmitForm ( // // Skip if there is no RequestElement // - if (Storage->ElementCount == 0) { + if (FormSetStorage->ElementCount == 0) { continue; } // // 1. Prepare // - Status = StorageToConfigResp (Storage, &ConfigResp, FALSE); + Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE); if (EFI_ERROR (Status)) { return Status; } - if (Storage->Type == EFI_HII_VARSTORE_BUFFER || - Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { - - // - // 2. Send to Configuration Driver - // - if (FormSet->ConfigAccess != NULL) { - Status = FormSet->ConfigAccess->RouteConfig ( - FormSet->ConfigAccess, - ConfigResp, - &Progress - ); - if (EFI_ERROR (Status)) { - FreePool (ConfigResp); - return Status; - } - } - } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { - // - // 1&2. Set the edit data to the variable. - // - TmpBuf = NULL; - TmpBuf = AllocateZeroPool (Storage->Size); - if (TmpBuf == NULL) { - Status = EFI_OUT_OF_RESOURCES; - return Status; - } - BufferSize = Storage->Size; - Status = gRT->GetVariable ( - Storage->Name, - &Storage->Guid, - NULL, - &BufferSize, - TmpBuf - ); - ASSERT (BufferSize == Storage->Size); - Status = mHiiConfigRouting->ConfigToBlock ( - mHiiConfigRouting, - ConfigResp, - TmpBuf, - &BufferSize, - &Progress - ); - if (EFI_ERROR (Status)) { - FreePool (TmpBuf); - FreePool (ConfigResp); - return Status; - } - - Status = gRT->SetVariable ( - Storage->Name, - &Storage->Guid, - Storage->Attributes, - Storage->Size, - TmpBuf - ); - if (EFI_ERROR (Status)) { - FreePool (TmpBuf); - FreePool (ConfigResp); - return Status; - } - FreePool (TmpBuf); + // + // 2. Send to Routine config Protocol. + // + Status = mHiiConfigRouting->RouteConfig ( + mHiiConfigRouting, + ConfigResp, + &Progress + ); + if (EFI_ERROR (Status)) { + FreePool (ConfigResp); + return Status; } + FreePool (ConfigResp); // // 3. Config success, update storage shadow Buffer // - SynchronizeStorage (Storage, TRUE); + SynchronizeStorage (FormSet, Storage, FormSetStorage->ConfigRequest, TRUE); } // // 4. Update the NV flag. // - UpdateNvInfoInForm (FormSet, FALSE); + ValueChangeResetFlagUpdate(TRUE, FormSet, NULL); } else if (SettingScope == SystemLevel) { // // System Level Save. @@ -2646,12 +2597,16 @@ SubmitForm ( Link = GetFirstNode (&gBrowserFormSetList); while (!IsNull (&gBrowserFormSetList, Link)) { LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link); - SubmitForm (LocalFormSet, NULL, FormSetLevel); Link = GetNextNode (&gBrowserFormSetList, Link); + if (!ValidateFormSet(LocalFormSet)) { + continue; + } + SubmitForm (LocalFormSet, NULL, FormSetLevel); if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) { // // Remove maintain backup list after save except for the current using FormSet. // + CleanBrowserStorage(LocalFormSet); RemoveEntryList (&LocalFormSet->Link); DestroyFormSet (LocalFormSet); } @@ -2681,7 +2636,7 @@ GetDefaultValueFromAltCfg ( BOOLEAN IsBufferStorage; BOOLEAN IsString; UINTN Length; - FORMSET_STORAGE *Storage; + BROWSER_STORAGE *Storage; CHAR16 *ConfigRequest; CHAR16 *Progress; CHAR16 *Result; @@ -2704,9 +2659,7 @@ GetDefaultValueFromAltCfg ( Value = NULL; Storage = Question->Storage; - if ((Storage == NULL) || - (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) || - (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) { + if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) { return Status; } @@ -2725,7 +2678,11 @@ GetDefaultValueFromAltCfg ( Dst = (UINT8 *) &Question->HiiValue.Value; } - IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE); + if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { + IsBufferStorage = TRUE; + } else { + IsBufferStorage = FALSE; + } IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE); // @@ -2750,8 +2707,8 @@ GetDefaultValueFromAltCfg ( StrCat (ConfigRequest, Question->VariableName); } - Status = FormSet->ConfigAccess->ExtractConfig ( - FormSet->ConfigAccess, + Status = mHiiConfigRouting->ExtractConfig ( + mHiiConfigRouting, ConfigRequest, &Progress, &Result @@ -2781,6 +2738,11 @@ GetDefaultValueFromAltCfg ( goto Done; } + if (ConfigResp == NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + // // Skip // @@ -2886,6 +2848,138 @@ GetDefaultIdForCallBack ( } } + + +/** + Return data element in an Array by its Index. + + @param Array The data array. + @param Type Type of the data in this array. + @param Index Zero based index for data in this array. + + @retval Value The data to be returned + +**/ +UINT64 +GetArrayData ( + IN VOID *Array, + IN UINT8 Type, + IN UINTN Index + ) +{ + UINT64 Data; + + ASSERT (Array != NULL); + + Data = 0; + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + Data = (UINT64) *(((UINT8 *) Array) + Index); + break; + + case EFI_IFR_TYPE_NUM_SIZE_16: + Data = (UINT64) *(((UINT16 *) Array) + Index); + break; + + case EFI_IFR_TYPE_NUM_SIZE_32: + Data = (UINT64) *(((UINT32 *) Array) + Index); + break; + + case EFI_IFR_TYPE_NUM_SIZE_64: + Data = (UINT64) *(((UINT64 *) Array) + Index); + break; + + default: + break; + } + + return Data; +} + + +/** + Set value of a data element in an Array by its Index. + + @param Array The data array. + @param Type Type of the data in this array. + @param Index Zero based index for data in this array. + @param Value The value to be set. + +**/ +VOID +SetArrayData ( + IN VOID *Array, + IN UINT8 Type, + IN UINTN Index, + IN UINT64 Value + ) +{ + + ASSERT (Array != NULL); + + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + *(((UINT8 *) Array) + Index) = (UINT8) Value; + break; + + case EFI_IFR_TYPE_NUM_SIZE_16: + *(((UINT16 *) Array) + Index) = (UINT16) Value; + break; + + case EFI_IFR_TYPE_NUM_SIZE_32: + *(((UINT32 *) Array) + Index) = (UINT32) Value; + break; + + case EFI_IFR_TYPE_NUM_SIZE_64: + *(((UINT64 *) Array) + Index) = (UINT64) Value; + break; + + default: + break; + } +} + +/** + Search an Option of a Question by its value. + + @param Question The Question + @param OptionValue Value for Option to be searched. + + @retval Pointer Pointer to the found Option. + @retval NULL Option not found. + +**/ +QUESTION_OPTION * +ValueToOption ( + IN FORM_BROWSER_STATEMENT *Question, + IN EFI_HII_VALUE *OptionValue + ) +{ + LIST_ENTRY *Link; + QUESTION_OPTION *Option; + INTN Result; + + Link = GetFirstNode (&Question->OptionListHead); + while (!IsNull (&Question->OptionListHead, Link)) { + Option = QUESTION_OPTION_FROM_LINK (Link); + + if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) { + // + // Check the suppressif condition, only a valid option can be return. + // + if ((Option->SuppressExpression == NULL) || + ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) { + return Option; + } + } + + Link = GetNextNode (&Question->OptionListHead, Link); + } + + return NULL; +} + + /** Reset Question to its default value. @@ -3169,7 +3263,7 @@ ExtractDefault ( IN UINT16 DefaultId, IN BROWSER_SETTING_SCOPE SettingScope, IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope, - IN FORMSET_STORAGE *Storage OPTIONAL, + IN BROWSER_STORAGE *Storage OPTIONAL, IN BOOLEAN RetrieveValueFirst ) { @@ -3177,11 +3271,8 @@ ExtractDefault ( LIST_ENTRY *FormLink; LIST_ENTRY *Link; FORM_BROWSER_STATEMENT *Question; - FORM_BROWSER_FORMSET *BackUpFormSet; FORM_BROWSER_FORMSET *LocalFormSet; - EFI_HII_HANDLE *HiiHandles; - UINTN Index; - EFI_GUID ZeroGuid; + FORM_BROWSER_FORMSET *OldFormSet; Status = EFI_SUCCESS; @@ -3251,10 +3342,6 @@ ExtractDefault ( if ((Question->Storage != NULL) && (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) { SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer); - // - // Update Form NV flag. - // - Form->NvUpdateRequired = TRUE; } } } else if (SettingScope == FormSetLevel) { @@ -3266,80 +3353,109 @@ ExtractDefault ( } } else if (SettingScope == SystemLevel) { // - // Open all FormSet by locate HII packages. - // Initiliaze the maintain FormSet to store default data as back up data. + // Preload all Hii formset. // - BackUpFormSet = gOldFormSet; - gOldFormSet = NULL; + LoadAllHiiFormset(); - // - // Get all the Hii handles - // - HiiHandles = HiiGetHiiHandles (NULL); - ASSERT (HiiHandles != NULL); + OldFormSet = mSystemLevelFormSet; // - // Search for formset of each class type + // Set Default Value for each FormSet in the maintain list. // - for (Index = 0; HiiHandles[Index] != NULL; Index++) { - // - // Check HiiHandles[Index] does exist in global maintain list. - // - if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) { - continue; - } - - // - // Initilize FormSet Setting - // - LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET)); - ASSERT (LocalFormSet != NULL); - ZeroMem (&ZeroGuid, sizeof (ZeroGuid)); - Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet, FALSE); - if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) { - DestroyFormSet (LocalFormSet); - continue; - } - Status = InitializeCurrentSetting (LocalFormSet); - if (EFI_ERROR (Status)) { - DestroyFormSet (LocalFormSet); - continue; - } - // - // Initilize Questions' Value - // - Status = LoadFormSetConfig (NULL, LocalFormSet); - if (EFI_ERROR (Status)) { - DestroyFormSet (LocalFormSet); + Link = GetFirstNode (&gBrowserFormSetList); + while (!IsNull (&gBrowserFormSetList, Link)) { + LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link); + Link = GetNextNode (&gBrowserFormSetList, Link); + if (!ValidateFormSet(LocalFormSet)) { continue; } - // - // Add FormSet into the maintain list. - // - InsertTailList (&gBrowserFormSetList, &LocalFormSet->Link); - } - - // - // Free resources, and restore gOldFormSet and gClassOfVfr - // - FreePool (HiiHandles); - gOldFormSet = BackUpFormSet; - - // - // Set Default Value for each FormSet in the maintain list. - // - Link = GetFirstNode (&gBrowserFormSetList); - while (!IsNull (&gBrowserFormSetList, Link)) { - LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link); + mSystemLevelFormSet = LocalFormSet; + ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst); - Link = GetNextNode (&gBrowserFormSetList, Link); } + + mSystemLevelFormSet = OldFormSet; } return EFI_SUCCESS; } + +/** + Validate whether this question's value has changed. + + @param FormSet FormSet data structure. + @param Form Form data structure. + @param Question Question to be initialized. + @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver. + + @retval TRUE Question's value has changed. + @retval FALSE Question's value has not changed + +**/ +BOOLEAN +IsQuestionValueChanged ( + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_FORM *Form, + IN OUT FORM_BROWSER_STATEMENT *Question, + IN GET_SET_QUESTION_VALUE_WITH GetValueFrom + ) +{ + EFI_HII_VALUE BackUpValue; + CHAR8 *BackUpBuffer; + EFI_STATUS Status; + BOOLEAN ValueChanged; + UINTN BufferWidth; + + // + // For quetion without storage, always mark it as data not changed. + // + if (Question->Storage == NULL && Question->Operand != EFI_IFR_TIME_OP && Question->Operand != EFI_IFR_DATE_OP) { + return FALSE; + } + + BackUpBuffer = NULL; + ValueChanged = FALSE; + + switch (Question->Operand) { + case EFI_IFR_ORDERED_LIST_OP: + BufferWidth = Question->StorageWidth; + BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue); + ASSERT (BackUpBuffer != NULL); + break; + + case EFI_IFR_STRING_OP: + case EFI_IFR_PASSWORD_OP: + BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16); + BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue); + ASSERT (BackUpBuffer != NULL); + break; + + default: + BufferWidth = 0; + break; + } + CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)); + + Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom); + ASSERT_EFI_ERROR(Status); + + if (CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 || + CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0) { + ValueChanged = TRUE; + } + + CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE)); + CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth); + + if (BackUpBuffer != NULL) { + FreePool (BackUpBuffer); + } + + return ValueChanged; +} + /** Initialize Question's Edit copy from Storage. @@ -3373,7 +3489,11 @@ LoadFormConfig ( // // Initialize local copy of Value for each Question // - Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer); + if (Question->Operand == EFI_IFR_PASSWORD_OP && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)== 0) { + Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver); + } else { + Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer); + } if (EFI_ERROR (Status)) { return Status; } @@ -3386,7 +3506,8 @@ LoadFormConfig ( // Call the Retrieve call back function for all questions. // if ((FormSet->ConfigAccess != NULL) && (Selection != NULL) && - ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) { + ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && + !gFinishRetrieveCall) { // // Check QuestionValue does exist. // @@ -3410,9 +3531,14 @@ LoadFormConfig ( ); } - Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE); + Status = ProcessCallBackFunction(Selection, FormSet, Form, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE); } + // + // Update Question Value changed flag. + // + Question->ValueChanged = IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBuffer); + Link = GetNextNode (&Form->StatementListHead, Link); } @@ -3456,204 +3582,570 @@ LoadFormSetConfig ( Link = GetNextNode (&FormSet->FormListHead, Link); } + // + // Finished question initialization. + // + FormSet->QuestionInited = TRUE; + return EFI_SUCCESS; } /** - Fill storage's edit copy with settings requested from Configuration Driver. + Remove the Request element from the Config Request. - @param FormSet FormSet data structure. - @param Storage Buffer Storage. + @param Storage Pointer to the browser storage. + @param RequestElement The pointer to the Request element. - @retval EFI_SUCCESS The function completed successfully. +**/ +VOID +RemoveElement ( + IN OUT BROWSER_STORAGE *Storage, + IN CHAR16 *RequestElement + ) +{ + CHAR16 *NewStr; + CHAR16 *DestStr; + + ASSERT (Storage->ConfigRequest != NULL && RequestElement != NULL); + + NewStr = StrStr (Storage->ConfigRequest, RequestElement); + + if (NewStr == NULL) { + return; + } + + // + // Remove this element from this ConfigRequest. + // + DestStr = NewStr; + NewStr += StrLen (RequestElement); + CopyMem (DestStr, NewStr, StrSize (NewStr)); + + Storage->SpareStrLen += StrLen (RequestElement); +} + +/** + Adjust config request in storage, remove the request elements existed in the input ConfigRequest. + + @param Storage Pointer to the browser storage. + @param ConfigRequest The pointer to the Request element. **/ -EFI_STATUS -LoadStorage ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORMSET_STORAGE *Storage +VOID +RemoveConfigRequest ( + BROWSER_STORAGE *Storage, + CHAR16 *ConfigRequest ) { - EFI_STATUS Status; - EFI_STRING Progress; - EFI_STRING Result; - CHAR16 *StrPtr; + CHAR16 *RequestElement; + CHAR16 *NextRequestElement; + CHAR16 *SearchKey; - if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { - return EFI_SUCCESS; + // + // No request element in it, just return. + // + if (ConfigRequest == NULL) { + return; } - if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { - Status = gRT->GetVariable ( - Storage->Name, - &Storage->Guid, - NULL, - (UINTN*)&Storage->Size, - Storage->EditBuffer - ); - return Status; + if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + // + // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage + // + SearchKey = L"&"; + } else { + // + // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage + // + SearchKey = L"&OFFSET"; } - if (FormSet->ConfigAccess == NULL) { - return EFI_NOT_FOUND; + // + // Find SearchKey storage + // + if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + RequestElement = StrStr (ConfigRequest, L"PATH"); + ASSERT (RequestElement != NULL); + RequestElement = StrStr (RequestElement, SearchKey); + } else { + RequestElement = StrStr (ConfigRequest, SearchKey); } - if (Storage->ElementCount == 0) { + while (RequestElement != NULL) { // - // Skip if there is no RequestElement + // +1 to avoid find header itself. // - return EFI_SUCCESS; + NextRequestElement = StrStr (RequestElement + 1, SearchKey); + + // + // The last Request element in configRequest string. + // + if (NextRequestElement != NULL) { + // + // Replace "&" with '\0'. + // + *NextRequestElement = L'\0'; + } + + RemoveElement (Storage, RequestElement); + + if (NextRequestElement != NULL) { + // + // Restore '&' with '\0' for later used. + // + *NextRequestElement = L'&'; + } + + RequestElement = NextRequestElement; } // - // Request current settings from Configuration Driver + // If no request element remain, just remove the ConfigRequest string. // - Status = FormSet->ConfigAccess->ExtractConfig ( - FormSet->ConfigAccess, - Storage->ConfigRequest, - &Progress, - &Result - ); - if (EFI_ERROR (Status)) { - return Status; + if (StrCmp (Storage->ConfigRequest, Storage->ConfigHdr) == 0) { + FreePool (Storage->ConfigRequest); + Storage->ConfigRequest = NULL; + Storage->SpareStrLen = 0; } +} + +/** + Base on the current formset info, clean the ConfigRequest string in browser storage. + + @param FormSet Pointer of the FormSet + +**/ +VOID +CleanBrowserStorage ( + IN OUT FORM_BROWSER_FORMSET *FormSet + ) +{ + LIST_ENTRY *Link; + FORMSET_STORAGE *Storage; + CHAR16 *ConfigRequest; + + Link = GetFirstNode (&FormSet->StorageListHead); + while (!IsNull (&FormSet->StorageListHead, Link)) { + Storage = FORMSET_STORAGE_FROM_LINK (Link); + Link = GetNextNode (&FormSet->StorageListHead, Link); + + if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { + if (Storage->ConfigRequest == NULL || Storage->BrowserStorage->ConfigRequest == NULL) { + continue; + } + + ConfigRequest = FormSet->QuestionInited ? Storage->ConfigRequest : Storage->ConfigElements; + RemoveConfigRequest (Storage->BrowserStorage, ConfigRequest); + } else if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER || + Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + if (Storage->BrowserStorage->ConfigRequest != NULL) { + FreePool (Storage->BrowserStorage->ConfigRequest); + } + Storage->BrowserStorage->Initialized = FALSE; + } + } +} + +/** + Check whether current element in the ConfigReqeust string. + + @param BrowserStorage Storage which includes ConfigReqeust. + @param RequestElement New element need to check. + + @retval TRUE The Element is in the ConfigReqeust string. + @retval FALSE The Element not in the configReqeust String. + +**/ +BOOLEAN +ElementValidation ( + BROWSER_STORAGE *BrowserStorage, + CHAR16 *RequestElement + ) +{ + return StrStr (BrowserStorage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE; +} + +/** + Append the Request element to the Config Request. + + @param ConfigRequest Current ConfigRequest info. + @param SpareStrLen Current remain free buffer for config reqeust. + @param RequestElement New Request element. + +**/ +VOID +AppendConfigRequest ( + IN OUT CHAR16 **ConfigRequest, + IN OUT UINTN *SpareStrLen, + IN CHAR16 *RequestElement + ) +{ + CHAR16 *NewStr; + UINTN StringSize; + UINTN StrLength; + + StrLength = StrLen (RequestElement); // - // Convert Result from to + // Append to // - StrPtr = StrStr (Result, L"&GUID="); - if (StrPtr != NULL) { - *StrPtr = L'\0'; + if (StrLength > *SpareStrLen) { + // + // Old String buffer is not sufficient for RequestElement, allocate a new one + // + StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16); + NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16)); + ASSERT (NewStr != NULL); + + if (*ConfigRequest != NULL) { + CopyMem (NewStr, *ConfigRequest, StringSize); + FreePool (*ConfigRequest); + } + *ConfigRequest = NewStr; + *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL; } - Status = ConfigRespToStorage (Storage, Result); - FreePool (Result); - return Status; + StrCat (*ConfigRequest, RequestElement); + *SpareStrLen -= StrLength; } - /** - Copy uncommitted data from source Storage to destination Storage. + Adjust the config request info, remove the request elements which already in AllConfigRequest string. - @param Dst Target Storage for uncommitted data. - @param Src Source Storage for uncommitted data. + @param Storage Form set Storage. - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type. + @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig + @retval FALSE All elements covered by current used elements. **/ -EFI_STATUS -CopyStorage ( - IN OUT FORMSET_STORAGE *Dst, - IN FORMSET_STORAGE *Src +BOOLEAN +ConfigRequestAdjust ( + IN FORMSET_STORAGE *Storage ) { - LIST_ENTRY *Link; - NAME_VALUE_NODE *Node; + CHAR16 *RequestElement; + CHAR16 *NextRequestElement; + CHAR16 *RetBuf; + UINTN SpareBufLen; + CHAR16 *SearchKey; + BOOLEAN RetVal; + + SpareBufLen = 0; + RetBuf = NULL; + RetVal = FALSE; + + if (Storage->BrowserStorage->ConfigRequest == NULL) { + Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest); + if (Storage->ConfigElements != NULL) { + FreePool (Storage->ConfigElements); + } + Storage->ConfigElements = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest); + return TRUE; + } - if ((Dst->Type != Src->Type) || (Dst->Size != Src->Size)) { - return EFI_INVALID_PARAMETER; + if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + // + // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage + // + SearchKey = L"&"; + } else { + // + // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage + // + SearchKey = L"&OFFSET"; } - switch (Src->Type) { - case EFI_HII_VARSTORE_BUFFER: - case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER: - CopyMem (Dst->EditBuffer, Src->EditBuffer, Src->Size); - CopyMem (Dst->Buffer, Src->Buffer, Src->Size); - break; + // + // Prepare the config header. + // + RetBuf = AllocateCopyPool(StrSize (Storage->BrowserStorage->ConfigHdr), Storage->BrowserStorage->ConfigHdr); + ASSERT (RetBuf != NULL); - case EFI_HII_VARSTORE_NAME_VALUE: - Link = GetFirstNode (&Src->NameValueListHead); - while (!IsNull (&Src->NameValueListHead, Link)) { - Node = NAME_VALUE_NODE_FROM_LINK (Link); + // + // Find SearchKey storage + // + if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + RequestElement = StrStr (Storage->ConfigRequest, L"PATH"); + ASSERT (RequestElement != NULL); + RequestElement = StrStr (RequestElement, SearchKey); + } else { + RequestElement = StrStr (Storage->ConfigRequest, SearchKey); + } - SetValueByName (Dst, Node->Name, Node->EditValue, GetSetValueWithEditBuffer); - SetValueByName (Dst, Node->Name, Node->Value, GetSetValueWithBuffer); + while (RequestElement != NULL) { + // + // +1 to avoid find header itself. + // + NextRequestElement = StrStr (RequestElement + 1, SearchKey); - Link = GetNextNode (&Src->NameValueListHead, Link); + // + // The last Request element in configRequest string. + // + if (NextRequestElement != NULL) { + // + // Replace "&" with '\0'. + // + *NextRequestElement = L'\0'; + } + + if (!ElementValidation (Storage->BrowserStorage, RequestElement)) { + // + // Add this element to the Storage->BrowserStorage->AllRequestElement. + // + AppendConfigRequest(&Storage->BrowserStorage->ConfigRequest, &Storage->BrowserStorage->SpareStrLen, RequestElement); + AppendConfigRequest (&RetBuf, &SpareBufLen, RequestElement); + RetVal = TRUE; } - break; - case EFI_HII_VARSTORE_EFI_VARIABLE: - default: - break; + if (NextRequestElement != NULL) { + // + // Restore '&' with '\0' for later used. + // + *NextRequestElement = L'&'; + } + + RequestElement = NextRequestElement; } - return EFI_SUCCESS; + if (RetVal) { + if (Storage->ConfigElements != NULL) { + FreePool (Storage->ConfigElements); + } + Storage->ConfigElements = RetBuf; + } else { + FreePool (RetBuf); + } + + return RetVal; } /** - Get old question value from the saved formset. - @param Statement The question which need to get old question value. - @param OldFormSet FormSet data structure saved in the list. + Base on ConfigRequest info to get default value for current formset. + + ConfigRequest info include the info about which questions in current formset need to + get default value. This function only get these questions default value. + + @param FormSet FormSet data structure. + @param Storage Storage need to update value. + @param ConfigRequest The config request string. **/ -VOID -GetOldQuestionValue ( - IN OUT FORM_BROWSER_STATEMENT *Statement, - IN FORM_BROWSER_FORMSET *OldFormSet +VOID +GetDefaultForFormset ( + IN FORM_BROWSER_FORMSET *FormSet, + IN BROWSER_STORAGE *Storage, + IN CHAR16 *ConfigRequest ) { - LIST_ENTRY *FormLink; - LIST_ENTRY *Link; - FORM_BROWSER_STATEMENT *Question; - FORM_BROWSER_FORM *Form; + UINT8 *BackUpBuf; + UINTN BufferSize; + LIST_ENTRY BackUpList; + NAME_VALUE_NODE *Node; + LIST_ENTRY *Link; + LIST_ENTRY *NodeLink; + NAME_VALUE_NODE *TmpNode; + EFI_STATUS Status; + EFI_STRING Progress; + EFI_STRING Result; + + BackUpBuf = NULL; + InitializeListHead(&BackUpList); + + // + // Back update the edit buffer. + // + if (Storage->Type == EFI_HII_VARSTORE_BUFFER || + (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) { + BackUpBuf = AllocateCopyPool (Storage->Size, Storage->EditBuffer); + ASSERT (BackUpBuf != NULL); + } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + Link = GetFirstNode (&Storage->NameValueListHead); + while (!IsNull (&Storage->NameValueListHead, Link)) { + Node = NAME_VALUE_NODE_FROM_LINK (Link); + Link = GetNextNode (&Storage->NameValueListHead, Link); - FormLink = GetFirstNode (&OldFormSet->FormListHead); - while (!IsNull (&OldFormSet->FormListHead, FormLink)) { - Form = FORM_BROWSER_FORM_FROM_LINK (FormLink); - FormLink = GetNextNode (&OldFormSet->FormListHead, FormLink); + // + // Only back Node belong to this formset. + // + if (StrStr (Storage->ConfigRequest, Node->Name) == NULL) { + continue; + } - Link = GetFirstNode (&Form->StatementListHead); - while (!IsNull (&Form->StatementListHead, Link)) { - Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link); - Link = GetNextNode (&Form->StatementListHead, Link); + TmpNode = AllocateCopyPool (sizeof (NAME_VALUE_NODE), Node); + TmpNode->Name = AllocateCopyPool (StrSize(Node->Name) * sizeof (CHAR16), Node->Name); + TmpNode->EditValue = AllocateCopyPool (StrSize(Node->EditValue) * sizeof (CHAR16), Node->EditValue); - if (Question->QuestionId != Statement->QuestionId) { + InsertTailList(&BackUpList, &TmpNode->Link); + } + } + + // + // Get default value. + // + ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage, TRUE); + + // + // Update the question value based on the input ConfigRequest. + // + if (Storage->Type == EFI_HII_VARSTORE_BUFFER || + (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) { + ASSERT (BackUpBuf != NULL); + BufferSize = Storage->Size; + Status = mHiiConfigRouting->BlockToConfig( + mHiiConfigRouting, + ConfigRequest, + Storage->EditBuffer, + BufferSize, + &Result, + &Progress + ); + ASSERT_EFI_ERROR (Status); + + Status = mHiiConfigRouting->ConfigToBlock ( + mHiiConfigRouting, + Result, + BackUpBuf, + &BufferSize, + &Progress + ); + ASSERT_EFI_ERROR (Status); + + if (Result != NULL) { + FreePool (Result); + } + + CopyMem (Storage->EditBuffer, BackUpBuf, Storage->Size); + FreePool (BackUpBuf); + } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + // + // Update question value, only element in ConfigReqeust will be update. + // + Link = GetFirstNode (&BackUpList); + while (!IsNull (&BackUpList, Link)) { + Node = NAME_VALUE_NODE_FROM_LINK (Link); + Link = GetNextNode (&BackUpList, Link); + + if (StrStr (ConfigRequest, Node->Name) != NULL) { continue; } - CopyMem (&Statement->HiiValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)); - return; + NodeLink = GetFirstNode (&Storage->NameValueListHead); + while (!IsNull (&Storage->NameValueListHead, NodeLink)) { + TmpNode = NAME_VALUE_NODE_FROM_LINK (NodeLink); + NodeLink = GetNextNode (&Storage->NameValueListHead, NodeLink); + + if (StrCmp (Node->Name, TmpNode->Name) != 0) { + continue; + } + + FreePool (TmpNode->EditValue); + TmpNode->EditValue = AllocateCopyPool (StrSize(Node->EditValue) * sizeof (CHAR16), Node->EditValue); + + RemoveEntryList (&Node->Link); + FreePool (Node->EditValue); + FreePool (Node->Name); + FreePool (Node); + } + } + + // + // Restore the Name/Value node. + // + Link = GetFirstNode (&BackUpList); + while (!IsNull (&BackUpList, Link)) { + Node = NAME_VALUE_NODE_FROM_LINK (Link); + Link = GetNextNode (&BackUpList, Link); + + // + // Free this node. + // + RemoveEntryList (&Node->Link); + FreePool (Node->EditValue); + FreePool (Node->Name); + FreePool (Node); } } } /** - Get old question value from the saved formset, all these questions not have - storage. + Fill storage's edit copy with settings requested from Configuration Driver. - @param FormSet FormSet data structure which is used now. - @param OldFormSet FormSet data structure saved in the list. + @param FormSet FormSet data structure. + @param Storage Buffer Storage. **/ VOID -CopyOldValueForNoStorageQst ( - IN OUT FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORMSET *OldFormSet +LoadStorage ( + IN FORM_BROWSER_FORMSET *FormSet, + IN FORMSET_STORAGE *Storage ) { - LIST_ENTRY *FormLink; - LIST_ENTRY *Link; - FORM_BROWSER_STATEMENT *Question; - FORM_BROWSER_FORM *Form; + EFI_STATUS Status; + EFI_STRING Progress; + EFI_STRING Result; + CHAR16 *StrPtr; - FormLink = GetFirstNode (&FormSet->FormListHead); - while (!IsNull (&FormSet->FormListHead, FormLink)) { - Form = FORM_BROWSER_FORM_FROM_LINK (FormLink); - FormLink = GetNextNode (&FormSet->FormListHead, FormLink); + switch (Storage->BrowserStorage->Type) { + case EFI_HII_VARSTORE_EFI_VARIABLE: + return; - Link = GetFirstNode (&Form->StatementListHead); - while (!IsNull (&Form->StatementListHead, Link)) { - Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link); - Link = GetNextNode (&Form->StatementListHead, Link); + case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER: + if (Storage->BrowserStorage->ConfigRequest != NULL) { + ConfigRequestAdjust(Storage); + return; + } + break; - if (Question->Storage == NULL) { - GetOldQuestionValue (Question, OldFormSet); + case EFI_HII_VARSTORE_BUFFER: + case EFI_HII_VARSTORE_NAME_VALUE: + // + // Skip if there is no RequestElement or data has initilized. + // + if (Storage->ElementCount == 0 || Storage->BrowserStorage->Initialized) { + return; } + Storage->BrowserStorage->Initialized = TRUE; + break; + + default: + return; + } + + // + // Request current settings from Configuration Driver + // + Status = mHiiConfigRouting->ExtractConfig ( + mHiiConfigRouting, + Storage->ConfigRequest, + &Progress, + &Result + ); + + // + // If get value fail, extract default from IFR binary + // + if (EFI_ERROR (Status)) { + ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE); + } else { + // + // Convert Result from to + // + StrPtr = StrStr (Result, L"&GUID="); + if (StrPtr != NULL) { + *StrPtr = L'\0'; } + + Status = ConfigRespToStorage (Storage->BrowserStorage, Result); + FreePool (Result); } + + Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest); + + // + // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer. + // + SynchronizeStorage(FormSet, Storage->BrowserStorage, NULL, TRUE); } /** @@ -3661,22 +4153,26 @@ CopyOldValueForNoStorageQst ( @param FormSet FormSet data structure. - @retval EFI_SUCCESS The function completed successfully. - **/ -EFI_STATUS +VOID InitializeCurrentSetting ( IN OUT FORM_BROWSER_FORMSET *FormSet ) { LIST_ENTRY *Link; - LIST_ENTRY *Link2; FORMSET_STORAGE *Storage; - FORMSET_STORAGE *StorageSrc; - FORMSET_STORAGE *OldStorage; - FORM_BROWSER_FORM *Form; - FORM_BROWSER_FORM *Form2; - EFI_STATUS Status; + FORM_BROWSER_FORMSET *OldFormSet; + + // + // Try to find pre FormSet in the maintain backup list. + // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList. + // + OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle); + if (OldFormSet != NULL) { + RemoveEntryList (&OldFormSet->Link); + DestroyFormSet (OldFormSet); + } + InsertTailList (&gBrowserFormSetList, &FormSet->Link); // // Extract default from IFR binary for no storage questions. @@ -3690,81 +4186,10 @@ InitializeCurrentSetting ( while (!IsNull (&FormSet->StorageListHead, Link)) { Storage = FORMSET_STORAGE_FROM_LINK (Link); - OldStorage = NULL; - if (gOldFormSet != NULL) { - // - // Try to find the Storage in backup formset gOldFormSet - // - Link2 = GetFirstNode (&gOldFormSet->StorageListHead); - while (!IsNull (&gOldFormSet->StorageListHead, Link2)) { - StorageSrc = FORMSET_STORAGE_FROM_LINK (Link2); - - if (StorageSrc->VarStoreId == Storage->VarStoreId) { - OldStorage = StorageSrc; - break; - } - - Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2); - } - } - - if (OldStorage == NULL) { - // - // Storage is not found in backup formset, request it from ConfigDriver - // - Status = LoadStorage (FormSet, Storage); - - if (EFI_ERROR (Status)) { - // - // If get last time changed value failed, extract default from IFR binary - // - ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage, TRUE); - // - // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag - // in current situation. - // - UpdateNvInfoInForm (FormSet, FALSE); - } - - // - // Now Edit Buffer is filled with default values(lower priority) or current - // settings(higher priority), sychronize it to shadow Buffer - // - SynchronizeStorage (Storage, TRUE); - } else { - // - // Storage found in backup formset, use it - // - Status = CopyStorage (Storage, OldStorage); - } + LoadStorage (FormSet, Storage); Link = GetNextNode (&FormSet->StorageListHead, Link); } - - // - // If has old formset, get the old nv update status. - // - if (gOldFormSet != NULL) { - Link = GetFirstNode (&FormSet->FormListHead); - while (!IsNull (&FormSet->FormListHead, Link)) { - Form = FORM_BROWSER_FORM_FROM_LINK (Link); - - Link2 = GetFirstNode (&gOldFormSet->FormListHead); - while (!IsNull (&gOldFormSet->FormListHead, Link2)) { - Form2 = FORM_BROWSER_FORM_FROM_LINK (Link2); - - if (Form->FormId == Form2->FormId) { - Form->NvUpdateRequired = Form2->NvUpdateRequired; - break; - } - - Link2 = GetNextNode (&gOldFormSet->FormListHead, Link2); - } - Link = GetNextNode (&FormSet->FormListHead, Link); - } - } - - return EFI_SUCCESS; } @@ -3947,7 +4372,6 @@ GetIfrBinaryData ( found in package list. On output, GUID of the formset found(if not NULL). @param FormSet FormSet data structure. - @param UpdateGlobalVar Whether need to update the global variable. @retval EFI_SUCCESS The function completed successfully. @retval EFI_NOT_FOUND The specified FormSet could not be found. @@ -3957,13 +4381,11 @@ EFI_STATUS InitializeFormSet ( IN EFI_HII_HANDLE Handle, IN OUT EFI_GUID *FormSetGuid, - OUT FORM_BROWSER_FORMSET *FormSet, - IN BOOLEAN UpdateGlobalVar + OUT FORM_BROWSER_FORMSET *FormSet ) { EFI_STATUS Status; EFI_HANDLE DriverHandle; - UINT16 Index; Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData); if (EFI_ERROR (Status)) { @@ -3973,6 +4395,7 @@ InitializeFormSet ( FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE; FormSet->HiiHandle = Handle; CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID)); + FormSet->QuestionInited = FALSE; // // Retrieve ConfigAccess Protocol associated with this HiiPackageList @@ -3999,53 +4422,8 @@ InitializeFormSet ( // Parse the IFR binary OpCodes // Status = ParseOpCodes (FormSet); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // If not need to update the global variable, just return. - // - if (!UpdateGlobalVar) { - return Status; - } - - // - // Set VFR type by FormSet SubClass field - // - gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP; - if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) { - gClassOfVfr = FORMSET_CLASS_FRONT_PAGE; - } - - // - // Set VFR type by FormSet class guid - // - for (Index = 0; Index < 3; Index ++) { - if (CompareGuid (&FormSet->ClassGuid[Index], &gEfiHiiPlatformSetupFormsetGuid)) { - gClassOfVfr |= FORMSET_CLASS_PLATFORM_SETUP; - break; - } - } - - if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) { - gFrontPageHandle = FormSet->HiiHandle; - gFunctionKeySetting = NONE_FUNCTION_KEY_SETTING; - } - - // - // Match GUID to find out the function key setting. If match fail, use the default setting. - // - for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) { - if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) { - // - // Update the function key setting. - // - gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting; - } - } - return EFI_SUCCESS; + return Status; } @@ -4061,6 +4439,7 @@ SaveBrowserContext ( ) { BROWSER_CONTEXT *Context; + FORM_ENTRY_INFO *MenuList; gBrowserContextCount++; if (gBrowserContextCount == 1) { @@ -4078,46 +4457,23 @@ SaveBrowserContext ( // // Save FormBrowser context // - Context->BannerData = gBannerData; - Context->ClassOfVfr = gClassOfVfr; - Context->FunctionKeySetting = gFunctionKeySetting; + Context->Selection = gCurrentSelection; Context->ResetRequired = gResetRequired; - Context->Direction = gDirection; - Context->EnterString = gEnterString; - Context->EnterCommitString = gEnterCommitString; - Context->EnterEscapeString = gEnterEscapeString; - Context->EscapeString = gEscapeString; - Context->MoveHighlight = gMoveHighlight; - Context->MakeSelection = gMakeSelection; - Context->DecNumericInput = gDecNumericInput; - Context->HexNumericInput = gHexNumericInput; - Context->ToggleCheckBox = gToggleCheckBox; - Context->PromptForData = gPromptForData; - Context->PromptForPassword = gPromptForPassword; - Context->PromptForNewPassword = gPromptForNewPassword; - Context->ConfirmPassword = gConfirmPassword; - Context->ConfirmError = gConfirmError; - Context->PassowordInvalid = gPassowordInvalid; - Context->PressEnter = gPressEnter; - Context->EmptyString = gEmptyString; - Context->AreYouSure = gAreYouSure; - Context->YesResponse = gYesResponse; - Context->NoResponse = gNoResponse; - Context->MiniString = gMiniString; - Context->PlusString = gPlusString; - Context->MinusString = gMinusString; - Context->AdjustNumber = gAdjustNumber; - Context->SaveChanges = gSaveChanges; - Context->OptionMismatch = gOptionMismatch; - Context->FormSuppress = gFormSuppress; - Context->PromptBlockWidth = gPromptBlockWidth; - Context->OptionBlockWidth = gOptionBlockWidth; - Context->HelpBlockWidth = gHelpBlockWidth; - Context->OldFormSet = gOldFormSet; - Context->MenuRefreshHead = gMenuRefreshHead; - - CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions)); - CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption)); + Context->ExitRequired = gExitRequired; + Context->HiiHandle = mCurrentHiiHandle; + Context->FormId = mCurrentFormId; + CopyGuid (&Context->FormSetGuid, &mCurrentFormSetGuid); + + // + // Save the menu history data. + // + InitializeListHead(&Context->FormHistoryList); + while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) { + MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink); + RemoveEntryList (&MenuList->Link); + + InsertTailList(&Context->FormHistoryList, &MenuList->Link); + } // // Insert to FormBrowser context list @@ -4137,6 +4493,7 @@ RestoreBrowserContext ( { LIST_ENTRY *Link; BROWSER_CONTEXT *Context; + FORM_ENTRY_INFO *MenuList; ASSERT (gBrowserContextCount != 0); gBrowserContextCount--; @@ -4155,47 +4512,22 @@ RestoreBrowserContext ( // // Restore FormBrowser context // - gBannerData = Context->BannerData; - gClassOfVfr = Context->ClassOfVfr; - gFunctionKeySetting = Context->FunctionKeySetting; + gCurrentSelection = Context->Selection; gResetRequired = Context->ResetRequired; - gDirection = Context->Direction; - gEnterString = Context->EnterString; - gEnterCommitString = Context->EnterCommitString; - gEnterEscapeString = Context->EnterEscapeString; - gEscapeString = Context->EscapeString; - gMoveHighlight = Context->MoveHighlight; - gMakeSelection = Context->MakeSelection; - gDecNumericInput = Context->DecNumericInput; - gHexNumericInput = Context->HexNumericInput; - gToggleCheckBox = Context->ToggleCheckBox; - gPromptForData = Context->PromptForData; - gPromptForPassword = Context->PromptForPassword; - gPromptForNewPassword = Context->PromptForNewPassword; - gConfirmPassword = Context->ConfirmPassword; - gConfirmError = Context->ConfirmError; - gPassowordInvalid = Context->PassowordInvalid; - gPressEnter = Context->PressEnter; - gEmptyString = Context->EmptyString; - gAreYouSure = Context->AreYouSure; - gYesResponse = Context->YesResponse; - gNoResponse = Context->NoResponse; - gMiniString = Context->MiniString; - gPlusString = Context->PlusString; - gMinusString = Context->MinusString; - gAdjustNumber = Context->AdjustNumber; - gSaveChanges = Context->SaveChanges; - gOptionMismatch = Context->OptionMismatch; - gFormSuppress = Context->FormSuppress; - gPromptBlockWidth = Context->PromptBlockWidth; - gOptionBlockWidth = Context->OptionBlockWidth; - gHelpBlockWidth = Context->HelpBlockWidth; - gOldFormSet = Context->OldFormSet; - gMenuRefreshHead = Context->MenuRefreshHead; - gProtocolNotFound = Context->ProtocolNotFound; - - CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions)); - CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption)); + gExitRequired = Context->ExitRequired; + mCurrentHiiHandle = Context->HiiHandle; + mCurrentFormId = Context->FormId; + CopyGuid (&mCurrentFormSetGuid, &Context->FormSetGuid); + + // + // Restore the menu history data. + // + while (!IsListEmpty (&Context->FormHistoryList)) { + MenuList = FORM_ENTRY_INFO_FROM_LINK (Context->FormHistoryList.ForwardLink); + RemoveEntryList (&MenuList->Link); + + InsertTailList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link); + } // // Remove from FormBrowser context list @@ -4223,10 +4555,13 @@ GetFormSetFromHiiHandle ( Link = GetFirstNode (&gBrowserFormSetList); while (!IsNull (&gBrowserFormSetList, Link)) { FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link); + Link = GetNextNode (&gBrowserFormSetList, Link); + if (!ValidateFormSet(FormSet)) { + continue; + } if (FormSet->HiiHandle == Handle) { return FormSet; } - Link = GetNextNode (&gBrowserFormSetList, Link); } return NULL; @@ -4252,7 +4587,7 @@ IsHiiHandleInBrowserContext ( // // HiiHandle is Current FormSet. // - if ((gOldFormSet != NULL) && (gOldFormSet->HiiHandle == Handle)) { + if (mCurrentHiiHandle == Handle) { return TRUE; } @@ -4262,7 +4597,7 @@ IsHiiHandleInBrowserContext ( Link = GetFirstNode (&gBrowserContextList); while (!IsNull (&gBrowserContextList, Link)) { Context = BROWSER_CONTEXT_FROM_LINK (Link); - if (Context->OldFormSet->HiiHandle == Handle) { + if (Context->HiiHandle == Handle) { // // HiiHandle is in BrowserContext // @@ -4274,6 +4609,83 @@ IsHiiHandleInBrowserContext ( return FALSE; } +/** + Perform Password check. + Passwork may be encrypted by driver that requires the specific check. + + @param Form Form where Password Statement is in. + @param Statement Password statement + @param PasswordString Password string to be checked. It may be NULL. + NULL means to restore password. + "" string can be used to checked whether old password does exist. + + @return Status Status of Password check. +**/ +EFI_STATUS +EFIAPI +PasswordCheck ( + IN FORM_DISPLAY_ENGINE_FORM *Form, + IN FORM_DISPLAY_ENGINE_STATEMENT *Statement, + IN EFI_STRING PasswordString OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; + EFI_BROWSER_ACTION_REQUEST ActionRequest; + EFI_IFR_TYPE_VALUE IfrTypeValue; + FORM_BROWSER_STATEMENT *Question; + + ConfigAccess = gCurrentSelection->FormSet->ConfigAccess; + Question = GetBrowserStatement(Statement); + ASSERT (Question != NULL); + + if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) { + if (ConfigAccess == NULL) { + return EFI_UNSUPPORTED; + } + } else { + if (PasswordString == NULL) { + return EFI_SUCCESS; + } + + if (StrnCmp (PasswordString, (CHAR16 *) Question->BufferValue, Question->StorageWidth/sizeof (CHAR16)) == 0) { + return EFI_SUCCESS; + } else { + return EFI_NOT_READY; + } + } + + // + // Prepare password string in HII database + // + if (PasswordString != NULL) { + IfrTypeValue.string = NewString (PasswordString, gCurrentSelection->FormSet->HiiHandle); + } else { + IfrTypeValue.string = 0; + } + + // + // Send password to Configuration Driver for validation + // + Status = ConfigAccess->Callback ( + ConfigAccess, + EFI_BROWSER_ACTION_CHANGING, + Question->QuestionId, + Question->HiiValue.Type, + &IfrTypeValue, + &ActionRequest + ); + + // + // Remove password string from HII database + // + if (PasswordString != NULL) { + DeleteString (IfrTypeValue.string, gCurrentSelection->FormSet->HiiHandle); + } + + return Status; +} + /** Find the registered HotKey based on KeyData. @@ -4324,7 +4736,7 @@ SetScope ( if (Scope >= MaxLevel) { return EFI_INVALID_PARAMETER; } - + // // When no hot key registered in system or on the first setting, // Scope can be set. @@ -4448,6 +4860,128 @@ RegiserExitHandler ( return; } +/** + Check whether the browser data has been modified. + + @retval TRUE Browser data is modified. + @retval FALSE No browser data is modified. + +**/ +BOOLEAN +EFIAPI +IsBrowserDataModified ( + VOID + ) +{ + LIST_ENTRY *Link; + FORM_BROWSER_FORMSET *FormSet; + + if (gCurrentSelection == NULL) { + return FALSE; + } + + switch (gBrowserSettingScope) { + case FormLevel: + return IsNvUpdateRequiredForForm (gCurrentSelection->Form); + + case FormSetLevel: + return IsNvUpdateRequiredForFormSet (gCurrentSelection->FormSet); + + case SystemLevel: + Link = GetFirstNode (&gBrowserFormSetList); + while (!IsNull (&gBrowserFormSetList, Link)) { + FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link); + if (IsNvUpdateRequiredForFormSet (FormSet)) { + return TRUE; + } + Link = GetNextNode (&gBrowserFormSetList, Link); + } + return FALSE; + + default: + return FALSE; + } +} + +/** + Execute the action requested by the Action parameter. + + @param[in] Action Execute the request action. + @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT. + + @retval EFI_SUCCESS Execute the request action succss. + @retval EFI_INVALID_PARAMETER The input action value is invalid. + +**/ +EFI_STATUS +EFIAPI +ExecuteAction ( + IN UINT32 Action, + IN UINT16 DefaultId + ) +{ + EFI_STATUS Status; + + if (gCurrentSelection == NULL) { + return EFI_NOT_READY; + } + + Status = EFI_SUCCESS; + + // + // Executet the discard action. + // + if ((Action & BROWSER_ACTION_DISCARD) != 0) { + Status = DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Executet the difault action. + // + if ((Action & BROWSER_ACTION_DEFAULT) != 0) { + Status = ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Executet the submit action. + // + if ((Action & BROWSER_ACTION_SUBMIT) != 0) { + Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Executet the reset action. + // + if ((Action & BROWSER_ACTION_RESET) != 0) { + gResetRequired = TRUE; + } + + // + // Executet the exit action. + // + if ((Action & BROWSER_ACTION_EXIT) != 0) { + DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope); + if (gBrowserSettingScope == SystemLevel) { + if (ExitHandlerFunction != NULL) { + ExitHandlerFunction (); + } + } + + gExitRequired = TRUE; + } + + return Status; +} + /** Create reminder to let user to choose save or discard the changed browser data. Caller can use it to actively check the changed browser data. @@ -4467,23 +5001,20 @@ SaveReminder ( FORM_BROWSER_FORMSET *FormSet; BOOLEAN IsDataChanged; UINT32 DataSavedAction; - CHAR16 *YesResponse; - CHAR16 *NoResponse; - CHAR16 *EmptyString; - CHAR16 *ChangeReminderString; - CHAR16 *SaveConfirmString; - EFI_INPUT_KEY Key; DataSavedAction = BROWSER_NO_CHANGES; IsDataChanged = FALSE; Link = GetFirstNode (&gBrowserFormSetList); while (!IsNull (&gBrowserFormSetList, Link)) { FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link); - if (IsNvUpdateRequired (FormSet)) { + Link = GetNextNode (&gBrowserFormSetList, Link); + if (!ValidateFormSet(FormSet)) { + continue; + } + if (IsNvUpdateRequiredForFormSet (FormSet)) { IsDataChanged = TRUE; break; } - Link = GetNextNode (&gBrowserFormSetList, Link); } // @@ -4494,42 +5025,19 @@ SaveReminder ( } // - // If data is changed, prompt user + // If data is changed, prompt user to save or discard it. // - gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - - YesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle); - ASSERT (YesResponse != NULL); - NoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle); - ASSERT (NoResponse != NULL); - EmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); - ChangeReminderString = GetToken (STRING_TOKEN (CHANGE_REMINDER), gHiiHandle); - SaveConfirmString = GetToken (STRING_TOKEN (SAVE_CONFIRM), gHiiHandle); - do { - CreateDialog (4, TRUE, 0, NULL, &Key, EmptyString, ChangeReminderString, SaveConfirmString, EmptyString); - } while - (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse[0] | UPPER_LOWER_CASE_OFFSET)) && - ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse[0] | UPPER_LOWER_CASE_OFFSET)) - ); + DataSavedAction = (UINT32) mFormDisplay->ConfirmDataChange(); - // - // If the user hits the YesResponse key - // - if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse[0] | UPPER_LOWER_CASE_OFFSET)) { - SubmitForm (NULL, NULL, SystemLevel); - DataSavedAction = BROWSER_SAVE_CHANGES; - } else { - DiscardForm (NULL, NULL, SystemLevel); - DataSavedAction = BROWSER_DISCARD_CHANGES; - gResetRequired = FALSE; - } - - FreePool (YesResponse); - FreePool (NoResponse); - FreePool (EmptyString); - FreePool (SaveConfirmString); - FreePool (ChangeReminderString); + if (DataSavedAction == BROWSER_SAVE_CHANGES) { + SubmitForm (NULL, NULL, SystemLevel); + break; + } else if (DataSavedAction == BROWSER_DISCARD_CHANGES) { + DiscardForm (NULL, NULL, SystemLevel); + break; + } + } while (1); return DataSavedAction; }