X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FSetupBrowserDxe%2FPresentation.c;h=97713ebb603910dc20e612f97dc324be5e9fb854;hb=b4e96b82b4e2e47e95014b51787ba5b43abac784;hp=531829014433d4cec4f94edfc4a7348cccc720a1;hpb=184f3a02d60e994a1a78a7f16ea8cc0b9d0df3e9;p=mirror_edk2.git diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c index 5318290144..97713ebb60 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c @@ -1,7 +1,8 @@ /** @file Utility functions for UI presentation. -Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
+Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -21,10 +22,9 @@ EFI_GUID mCurrentFormSetGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}; UINT16 mCurrentFormId = 0; EFI_EVENT mValueChangedEvent = NULL; LIST_ENTRY mRefreshEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEventList); -UINT32 gBrowserStatus = BROWSER_SUCCESS; -CHAR16 *gErrorInfo; UINT16 mCurFakeQestId; FORM_DISPLAY_ENGINE_FORM gDisplayFormData; +BOOLEAN mFinishRetrieveCall = FALSE; /** Evaluate all expressions in a Form. @@ -70,22 +70,6 @@ EvaluateFormExpressions ( return EFI_SUCCESS; } -/** - Add empty function for event process function. - - @param Event The Event need to be process - @param Context The context of the event. - -**/ -VOID -EFIAPI -SetupBrowserEmptyFunction ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ -} - /** Base on the opcode buffer info to get the display statement. @@ -160,7 +144,7 @@ UpdateStatement ( // // Question value may be changed, need invoke its Callback() // - ProcessCallBackFunction (gCurrentSelection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE); + ProcessCallBackFunction (gCurrentSelection, gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, EFI_BROWSER_ACTION_RETRIEVE, FALSE); if (mHiiPackageListUpdated) { // @@ -179,7 +163,7 @@ UpdateStatement ( **/ VOID EFIAPI -RefreshEventNotify( +RefreshEventNotifyForStatement( IN EFI_EVENT Event, IN VOID *Context ) @@ -191,6 +175,23 @@ RefreshEventNotify( gBS->SignalEvent (mValueChangedEvent); } +/** + Refresh the questions within this form. + + @param Event The event which has this function related. + @param Context The input context info related to this event or the status code return to the caller. +**/ +VOID +EFIAPI +RefreshEventNotifyForForm( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET; + + gBS->SignalEvent (mValueChangedEvent); +} /** Create refresh hook event for statement which has refresh event or interval. @@ -199,7 +200,7 @@ RefreshEventNotify( **/ VOID -CreateRefreshEvent ( +CreateRefreshEventForStatement ( IN FORM_BROWSER_STATEMENT *Statement ) { @@ -213,7 +214,7 @@ CreateRefreshEvent ( Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_CALLBACK, - RefreshEventNotify, + RefreshEventNotifyForStatement, Statement, &Statement->RefreshGuid, &RefreshEvent); @@ -226,159 +227,36 @@ CreateRefreshEvent ( } /** - Perform value check for a question. - - @param Question The question need to do check. - @param Type Condition type need to check. - @param ErrorInfo Return info about the error. - - @retval The check result. -**/ -UINT32 -ConditionCheck ( - IN FORM_BROWSER_STATEMENT *Question, - IN UINT8 Type, - OUT STATEMENT_ERROR_INFO *ErrorInfo - ) -{ - EFI_STATUS Status; - LIST_ENTRY *Link; - FORM_EXPRESSION *Expression; - LIST_ENTRY *ListHead; - UINT32 RetVal; - - RetVal = STATEMENT_VALID; - ListHead = NULL; - - switch (Type) { - case EFI_HII_EXPRESSION_INCONSISTENT_IF: - ListHead = &Question->InconsistentListHead; - break; - - case EFI_HII_EXPRESSION_WARNING_IF: - ListHead = &Question->WarningListHead; - break; + Create refresh hook event for form which has refresh event or interval. - default: - ASSERT (FALSE); - return RetVal; - } - - ASSERT (ListHead != NULL); - Link = GetFirstNode (ListHead); - while (!IsNull (ListHead, Link)) { - Expression = FORM_EXPRESSION_FROM_LINK (Link); - Link = GetNextNode (ListHead, Link); + @param Form The form need to check. - // - // Evaluate the expression - // - Status = EvaluateExpression (gCurrentSelection->FormSet, gCurrentSelection->Form, Expression); - if (EFI_ERROR (Status)) { - continue; - } - - if ((Expression->Result.Type == EFI_IFR_TYPE_BOOLEAN) && Expression->Result.Value.b) { - ErrorInfo->StringId = Expression->Error; - switch (Type) { - case EFI_HII_EXPRESSION_INCONSISTENT_IF: - ErrorInfo->TimeOut = 0; - RetVal = INCOSISTENT_IF_TRUE; - break; - - case EFI_HII_EXPRESSION_WARNING_IF: - ErrorInfo->TimeOut = Expression->TimeOut; - RetVal = WARNING_IF_TRUE; - break; - - default: - ASSERT (FALSE); - break; - } - break; - } - } - - return RetVal; -} - -/** - Perform value check for a question. - - @param Form Form where Statement is in. - @param Statement Value will check for it. - @param InputValue New value will be checked. - @param ErrorInfo Return the error info for this check. - - @retval TRUE Input Value is valid. - @retval FALSE Input Value is invalid. **/ -UINT32 -EFIAPI -QuestionCheck ( - IN FORM_DISPLAY_ENGINE_FORM *Form, - IN FORM_DISPLAY_ENGINE_STATEMENT *Statement, - IN EFI_HII_VALUE *InputValue, - OUT STATEMENT_ERROR_INFO *ErrorInfo +VOID +CreateRefreshEventForForm ( + IN FORM_BROWSER_FORM *Form ) { - FORM_BROWSER_STATEMENT *Question; - EFI_HII_VALUE BackUpValue; - UINT8 *BackUpBuffer; - UINT32 RetVal; - - BackUpBuffer = NULL; - RetVal = STATEMENT_VALID; - - ASSERT (Form != NULL && Statement != NULL && InputValue != NULL && ErrorInfo != NULL); - - Question = GetBrowserStatement(Statement); - ASSERT (Question != NULL); - - // - // Back up the quesion value. - // - switch (Question->Operand) { - case EFI_IFR_ORDERED_LIST_OP: - BackUpBuffer = AllocateCopyPool (Question->StorageWidth, Question->BufferValue); - ASSERT (BackUpBuffer != NULL); - CopyMem (Question->BufferValue, InputValue->Buffer, Question->StorageWidth); - break; - - default: - CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)); - CopyMem (&Question->HiiValue, InputValue, sizeof (EFI_HII_VALUE)); - break; - } - - // - // Do the inconsistentif check. - // - if (!IsListEmpty (&Question->InconsistentListHead)) { - RetVal = ConditionCheck(Question, EFI_HII_EXPRESSION_INCONSISTENT_IF, ErrorInfo); - } - - // - // Do the warningif check. - // - if (RetVal == STATEMENT_VALID && !IsListEmpty (&Question->WarningListHead)) { - RetVal = ConditionCheck(Question, EFI_HII_EXPRESSION_WARNING_IF, ErrorInfo); - } + EFI_STATUS Status; + EFI_EVENT RefreshEvent; + FORM_BROWSER_REFRESH_EVENT_NODE *EventNode; // - // Restore the quesion value. + // If question has refresh guid, create the notify function. // - switch (Question->Operand) { - case EFI_IFR_ORDERED_LIST_OP: - CopyMem (Question->BufferValue, BackUpBuffer, Question->StorageWidth); - break; - - default: - CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE)); - break; - } + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + RefreshEventNotifyForForm, + Form, + &Form->RefreshGuid, + &RefreshEvent); + ASSERT_EFI_ERROR (Status); - return RetVal; + EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE)); + ASSERT (EventNode != NULL); + EventNode->RefreshEvent = RefreshEvent; + InsertTailList(&mRefreshEventList, &EventNode->Link); } /** @@ -387,18 +265,17 @@ QuestionCheck ( @param DisplayStatement Pointer to the display Statement data strucure. @param Statement The statement need to check. - @param HostDisplayStatement Pointer to the display Statement data strucure which is an host statement. **/ VOID InitializeDisplayStatement ( IN OUT FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement, - IN FORM_BROWSER_STATEMENT *Statement, - IN FORM_DISPLAY_ENGINE_STATEMENT *HostDisplayStatement + IN FORM_BROWSER_STATEMENT *Statement ) { LIST_ENTRY *Link; QUESTION_OPTION *Option; DISPLAY_QUESTION_OPTION *DisplayOption; + FORM_DISPLAY_ENGINE_STATEMENT *ParentStatement; DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE; DisplayStatement->Version = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1; @@ -465,8 +342,8 @@ InitializeDisplayStatement ( // // Create the refresh event process function. // - if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) { - CreateRefreshEvent (Statement); + if (!IsZeroGuid (&Statement->RefreshGuid)) { + CreateRefreshEventForStatement (Statement); } // @@ -480,7 +357,7 @@ InitializeDisplayStatement ( // Create the refresh guid hook event. // If the statement in this form has refresh event or refresh interval, browser will create this event for display engine. // - if ((!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) || (Statement->RefreshInterval != 0)) { + if ((!IsZeroGuid (&Statement->RefreshGuid)) || (Statement->RefreshInterval != 0)) { gDisplayFormData.FormRefreshEvent = mValueChangedEvent; } @@ -491,19 +368,14 @@ InitializeDisplayStatement ( DisplayStatement->PasswordCheck = PasswordCheck; } - // - // Save the validate check question for later use. - // - if (!IsListEmpty (&Statement->InconsistentListHead) || !IsListEmpty (&Statement->WarningListHead)) { - DisplayStatement->ValidateQuestion = QuestionCheck; - } - // // If this statement is nest in the subtitle, insert to the host statement. // else insert to the form it belongs to. // - if (Statement->InSubtitle) { - InsertTailList(&HostDisplayStatement->NestStatementList, &DisplayStatement->DisplayLink); + if (Statement->ParentStatement != NULL) { + ParentStatement = GetDisplayStatement(Statement->ParentStatement->OpCode); + ASSERT (ParentStatement != NULL); + InsertTailList(&ParentStatement->NestStatementList, &DisplayStatement->DisplayLink); } else { InsertTailList(&gDisplayFormData.StatementListHead, &DisplayStatement->DisplayLink); } @@ -560,8 +432,11 @@ UpdateHotkeyList ( HotKey = BROWSER_HOT_KEY_FROM_LINK (Link); CopyKey = AllocateCopyPool(sizeof (BROWSER_HOT_KEY), HotKey); + ASSERT (CopyKey != NULL); CopyKey->KeyData = AllocateCopyPool(sizeof (EFI_INPUT_KEY), HotKey->KeyData); + ASSERT (CopyKey->KeyData != NULL); CopyKey->HelpString = AllocateCopyPool(StrSize (HotKey->HelpString), HotKey->HelpString); + ASSERT (CopyKey->HelpString != NULL); InsertTailList(&gDisplayFormData.HotKeyListHead, &CopyKey->Link); @@ -625,14 +500,12 @@ AddStatementToDisplayForm ( LIST_ENTRY *Link; FORM_BROWSER_STATEMENT *Statement; FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement; - FORM_DISPLAY_ENGINE_STATEMENT *HostDisplayStatement; UINT8 MinRefreshInterval; EFI_EVENT RefreshIntervalEvent; FORM_BROWSER_REFRESH_EVENT_NODE *EventNode; BOOLEAN FormEditable; UINT32 ExtraAttribute; - HostDisplayStatement = NULL; MinRefreshInterval = 0; FormEditable = FALSE; @@ -657,6 +530,21 @@ AddStatementToDisplayForm ( InsertTailList(&gDisplayFormData.StatementListOSF, &DisplayStatement->DisplayLink); } + // + // treat formset as statement outside the form,get its opcode. + // + DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT)); + ASSERT (DisplayStatement != NULL); + + DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE; + DisplayStatement->Version = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1; + DisplayStatement->OpCode = gCurrentSelection->FormSet->OpCode; + + InitializeListHead (&DisplayStatement->NestStatementList); + InitializeListHead (&DisplayStatement->OptionListHead); + + InsertTailList(&gDisplayFormData.StatementListOSF, &DisplayStatement->DisplayLink); + // // Process the statement in this form. // @@ -686,21 +574,13 @@ AddStatementToDisplayForm ( // // Initialize this statement and add it to the display form. // - InitializeDisplayStatement(DisplayStatement, Statement, HostDisplayStatement); + InitializeDisplayStatement(DisplayStatement, Statement); // // Set the extra attribute. // DisplayStatement->Attribute |= ExtraAttribute; - // - // Save the Host statement info. - // Host statement may has nest statement follow it. - // - if (!Statement->InSubtitle) { - HostDisplayStatement = DisplayStatement; - } - if (Statement->Storage != NULL) { FormEditable = TRUE; } @@ -729,6 +609,16 @@ AddStatementToDisplayForm ( InsertTailList(&mRefreshEventList, &EventNode->Link); } + // + // Create the refresh event process function for Form. + // + if (!IsZeroGuid (&gCurrentSelection->Form->RefreshGuid)) { + CreateRefreshEventForForm (gCurrentSelection->Form); + if (gDisplayFormData.FormRefreshEvent == NULL) { + gDisplayFormData.FormRefreshEvent = mValueChangedEvent; + } + } + // // Update hotkey list field. // @@ -812,7 +702,7 @@ InitializeDisplayFormData ( Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_CALLBACK, - SetupBrowserEmptyFunction, + EfiEventEmptyFunction, NULL, &mValueChangedEvent ); @@ -866,12 +756,6 @@ UpdateDisplayFormData ( gDisplayFormData.FormRefreshEvent = NULL; gDisplayFormData.HighLightedStatement = NULL; - gDisplayFormData.BrowserStatus = gBrowserStatus; - gDisplayFormData.ErrorString = gErrorInfo; - - gBrowserStatus = BROWSER_SUCCESS; - gErrorInfo = NULL; - UpdateDataChangedFlag (); AddStatementToDisplayForm (); @@ -972,6 +856,106 @@ GetBrowserStatement ( return NULL; } +/** + Update the ValueChanged status for questions in this form. + + @param FormSet FormSet data structure. + @param Form Form data structure. + +**/ +VOID +UpdateStatementStatusForForm ( + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_FORM *Form + ) +{ + LIST_ENTRY *Link; + FORM_BROWSER_STATEMENT *Question; + + Link = GetFirstNode (&Form->StatementListHead); + while (!IsNull (&Form->StatementListHead, Link)) { + Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link); + Link = GetNextNode (&Form->StatementListHead, Link); + + // + // For password opcode, not set the the value changed flag. + // + if (Question->Operand == EFI_IFR_PASSWORD_OP) { + continue; + } + + IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBuffer); + } +} + +/** + Update the ValueChanged status for questions in this formset. + + @param FormSet FormSet data structure. + +**/ +VOID +UpdateStatementStatusForFormSet ( + IN FORM_BROWSER_FORMSET *FormSet + ) +{ + LIST_ENTRY *Link; + FORM_BROWSER_FORM *Form; + + Link = GetFirstNode (&FormSet->FormListHead); + while (!IsNull (&FormSet->FormListHead, Link)) { + Form = FORM_BROWSER_FORM_FROM_LINK (Link); + Link = GetNextNode (&FormSet->FormListHead, Link); + + UpdateStatementStatusForForm (FormSet, Form); + } +} + +/** + Update the ValueChanged status for questions. + + @param FormSet FormSet data structure. + @param Form Form data structure. + @param SettingScope Setting Scope for Default action. + +**/ +VOID +UpdateStatementStatus ( + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_FORM *Form, + IN BROWSER_SETTING_SCOPE SettingScope + ) +{ + LIST_ENTRY *Link; + FORM_BROWSER_FORMSET *LocalFormSet; + + switch (SettingScope) { + case SystemLevel: + Link = GetFirstNode (&gBrowserFormSetList); + while (!IsNull (&gBrowserFormSetList, Link)) { + LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link); + Link = GetNextNode (&gBrowserFormSetList, Link); + if (!ValidateFormSet(LocalFormSet)) { + continue; + } + + UpdateStatementStatusForFormSet (LocalFormSet); + } + break; + + case FormSetLevel: + UpdateStatementStatusForFormSet (FormSet); + break; + + case FormLevel: + UpdateStatementStatusForForm (FormSet, Form); + break; + + default: + break; + } +} + /** Process the action request in user input. @@ -988,8 +972,6 @@ ProcessAction ( IN UINT16 DefaultId ) { - EFI_STATUS Status; - // // This is caused by use press ESC, and it should not combine with other action type. // @@ -1006,18 +988,17 @@ ProcessAction ( } if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) { - ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE); + ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE, FALSE); + UpdateStatementStatus (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope); } if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) { - Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope); - if (EFI_ERROR (Status)) { - gBrowserStatus = BROWSER_SUBMIT_FAIL; - } + SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope); } if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) { - gResetRequired = TRUE; + gResetRequiredFormLevel = TRUE; + gResetRequiredSystemLevel = TRUE; } if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) { @@ -1040,6 +1021,87 @@ ProcessAction ( return EFI_SUCCESS; } +/** + Check whether the formset guid is in this Hii package list. + + @param HiiHandle The HiiHandle for this HII package list. + @param FormSetGuid The formset guid for the request formset. + + @retval TRUE Find the formset guid. + @retval FALSE Not found the formset guid. + +**/ +BOOLEAN +GetFormsetGuidFromHiiHandle ( + IN EFI_HII_HANDLE HiiHandle, + IN EFI_GUID *FormSetGuid + ) +{ + EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; + UINTN BufferSize; + UINT32 Offset; + UINT32 Offset2; + UINT32 PackageListLength; + EFI_HII_PACKAGE_HEADER PackageHeader; + UINT8 *Package; + UINT8 *OpCodeData; + EFI_STATUS Status; + BOOLEAN FindGuid; + + BufferSize = 0; + HiiPackageList = NULL; + FindGuid = FALSE; + + Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandle, &BufferSize, HiiPackageList); + if (Status == EFI_BUFFER_TOO_SMALL) { + HiiPackageList = AllocatePool (BufferSize); + ASSERT (HiiPackageList != NULL); + + Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandle, &BufferSize, HiiPackageList); + } + if (EFI_ERROR (Status) || HiiPackageList == NULL) { + return FALSE; + } + + // + // Get Form package from this HII package List + // + Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); + Offset2 = 0; + CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); + + while (Offset < PackageListLength) { + Package = ((UINT8 *) HiiPackageList) + Offset; + CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); + Offset += PackageHeader.Length; + + if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { + // + // Search FormSet in this Form Package + // + Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); + while (Offset2 < PackageHeader.Length) { + OpCodeData = Package + Offset2; + + if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { + if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))){ + FindGuid = TRUE; + break; + } + } + + Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; + } + } + if (FindGuid) { + break; + } + } + + FreePool (HiiPackageList); + + return FindGuid; +} /** Find HII Handle in the HII database associated with given Device Path. @@ -1048,6 +1110,7 @@ ProcessAction ( @param DevicePath Device Path associated with the HII package list handle. + @param FormsetGuid The formset guid for this formset. @retval Handle HII package list Handle associated with the Device Path. @@ -1055,15 +1118,13 @@ ProcessAction ( **/ EFI_HII_HANDLE -EFIAPI DevicePathToHiiHandle ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_GUID *FormsetGuid ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; - UINTN BufferSize; - UINTN HandleCount; UINTN Index; EFI_HANDLE Handle; EFI_HANDLE DriverHandle; @@ -1088,32 +1149,8 @@ DevicePathToHiiHandle ( // // Retrieve all HII Handles from HII database // - BufferSize = 0x1000; - HiiHandles = AllocatePool (BufferSize); - ASSERT (HiiHandles != NULL); - Status = mHiiDatabase->ListPackageLists ( - mHiiDatabase, - EFI_HII_PACKAGE_TYPE_ALL, - NULL, - &BufferSize, - HiiHandles - ); - if (Status == EFI_BUFFER_TOO_SMALL) { - FreePool (HiiHandles); - HiiHandles = AllocatePool (BufferSize); - ASSERT (HiiHandles != NULL); - - Status = mHiiDatabase->ListPackageLists ( - mHiiDatabase, - EFI_HII_PACKAGE_TYPE_ALL, - NULL, - &BufferSize, - HiiHandles - ); - } - - if (EFI_ERROR (Status)) { - FreePool (HiiHandles); + HiiHandles = HiiGetHiiHandles (NULL); + if (HiiHandles == NULL) { return NULL; } @@ -1121,16 +1158,21 @@ DevicePathToHiiHandle ( // Search Hii Handle by Driver Handle // HiiHandle = NULL; - HandleCount = BufferSize / sizeof (EFI_HII_HANDLE); - for (Index = 0; Index < HandleCount; Index++) { + for (Index = 0; HiiHandles[Index] != NULL; Index++) { Status = mHiiDatabase->GetPackageListHandle ( mHiiDatabase, HiiHandles[Index], &Handle ); if (!EFI_ERROR (Status) && (Handle == DriverHandle)) { - HiiHandle = HiiHandles[Index]; - break; + if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], FormsetGuid)) { + HiiHandle = HiiHandles[Index]; + break; + } + + if (HiiHandle != NULL) { + break; + } } } @@ -1157,17 +1199,8 @@ FormSetGuidToHiiHandle ( ) { EFI_HII_HANDLE *HiiHandles; - UINTN Index; - EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; - UINTN BufferSize; - UINT32 Offset; - UINT32 Offset2; - UINT32 PackageListLength; - EFI_HII_PACKAGE_HEADER PackageHeader; - UINT8 *Package; - UINT8 *OpCodeData; - EFI_STATUS Status; EFI_HII_HANDLE HiiHandle; + UINTN Index; ASSERT (ComparingGuid != NULL); @@ -1178,65 +1211,18 @@ FormSetGuidToHiiHandle ( HiiHandles = HiiGetHiiHandles (NULL); ASSERT (HiiHandles != NULL); - // - // Search for formset of each class type - // - for (Index = 0; HiiHandles[Index] != NULL; Index++) { - BufferSize = 0; - HiiPackageList = NULL; - Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList); - if (Status == EFI_BUFFER_TOO_SMALL) { - HiiPackageList = AllocatePool (BufferSize); - ASSERT (HiiPackageList != NULL); - - Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList); - } - if (EFI_ERROR (Status) || HiiPackageList == NULL) { - return NULL; - } - - // - // Get Form package from this HII package List - // - Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); - Offset2 = 0; - CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); - - while (Offset < PackageListLength) { - Package = ((UINT8 *) HiiPackageList) + Offset; - CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); - - if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { - // - // Search FormSet in this Form Package - // - Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); - while (Offset2 < PackageHeader.Length) { - OpCodeData = Package + Offset2; - - if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { - // - // Try to compare against formset GUID - // - if (CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) { - HiiHandle = HiiHandles[Index]; - break; - } - } + // + // Search for formset of each class type + // + for (Index = 0; HiiHandles[Index] != NULL; Index++) { + if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], ComparingGuid)) { + HiiHandle = HiiHandles[Index]; + break; + } - Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; - } - } - if (HiiHandle != NULL) { - break; - } - Offset += PackageHeader.Length; + if (HiiHandle != NULL) { + break; } - - FreePool (HiiPackageList); - if (HiiHandle != NULL) { - break; - } } FreePool (HiiHandles); @@ -1263,7 +1249,8 @@ ProcessChangedData ( IN BROWSER_SETTING_SCOPE Scope ) { - BOOLEAN RetValue; + BOOLEAN RetValue; + EFI_STATUS Status; RetValue = TRUE; switch (mFormDisplay->ConfirmDataChange()) { @@ -1272,7 +1259,10 @@ ProcessChangedData ( break; case BROWSER_ACTION_SUBMIT: - SubmitForm (Selection->FormSet, Selection->Form, Scope); + Status = SubmitForm (Selection->FormSet, Selection->Form, Scope); + if (EFI_ERROR (Status)) { + RetValue = FALSE; + } break; case BROWSER_ACTION_NONE: @@ -1306,15 +1296,7 @@ FindParentFormSet ( FORM_ENTRY_INFO *ParentMenu; CurrentMenu = Selection->CurrentMenu; - ParentMenu = UiFindParentMenu(CurrentMenu); - - // - // Find a menu which has different formset guid with current. - // - while (ParentMenu != NULL && CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) { - CurrentMenu = ParentMenu; - ParentMenu = UiFindParentMenu(CurrentMenu); - } + ParentMenu = UiFindParentMenu(CurrentMenu, FormSetLevel); if (ParentMenu != NULL) { CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID)); @@ -1364,7 +1346,7 @@ ProcessGotoOpCode ( // // Check whether the device path string is a valid string. // - if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL) { + if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL && StringPtr[0] != L'\0') { if (Selection->Form->ModalForm) { return Status; } @@ -1375,7 +1357,7 @@ ProcessGotoOpCode ( if (mPathFromText != NULL) { DevicePath = mPathFromText->ConvertTextToDevicePath(StringPtr); if (DevicePath != NULL) { - HiiHandle = DevicePathToHiiHandle (DevicePath); + HiiHandle = DevicePathToHiiHandle (DevicePath, &Statement->HiiValue.Value.ref.FormSetGuid); FreePool (DevicePath); } FreePool (StringPtr); @@ -1383,7 +1365,7 @@ ProcessGotoOpCode ( // // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol. // - gBrowserStatus = BROWSER_PROTOCOL_NOT_FOUND; + PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND, NULL, NULL, NULL); FreePool (StringPtr); return Status; } @@ -1413,7 +1395,7 @@ ProcessGotoOpCode ( CopyMem (&Selection->FormSetGuid,&Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID)); Selection->FormId = Statement->HiiValue.Value.ref.FormId; Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId; - } else if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) { + } else if (!IsZeroGuid (&Statement->HiiValue.Value.ref.FormSetGuid)) { if (Selection->Form->ModalForm) { return Status; } @@ -1460,7 +1442,7 @@ ProcessGotoOpCode ( // // Form is suppressed. // - gBrowserStatus = BROWSER_FORM_SUPPRESS; + PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL); return EFI_SUCCESS; } } @@ -1494,7 +1476,6 @@ ProcessQuestionConfig ( EFI_STATUS Status; CHAR16 *ConfigResp; CHAR16 *Progress; - EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; if (Question->QuestionConfig == 0) { return EFI_SUCCESS; @@ -1506,17 +1487,15 @@ ProcessQuestionConfig ( ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle); if (ConfigResp == NULL) { return EFI_NOT_FOUND; + } else if (ConfigResp[0] == L'\0') { + return EFI_SUCCESS; } // // Send config to Configuration Driver // - ConfigAccess = Selection->FormSet->ConfigAccess; - if (ConfigAccess == NULL) { - return EFI_UNSUPPORTED; - } - Status = ConfigAccess->RouteConfig ( - ConfigAccess, + Status = mHiiConfigRouting->RouteConfig ( + mHiiConfigRouting, ConfigResp, &Progress ); @@ -1529,21 +1508,20 @@ ProcessQuestionConfig ( Process the user input data. @param UserInput The user input data. - @param ChangeHighlight Whether need to change the highlight statement. @retval EFI_SUCESSS This function always return successfully for now. **/ EFI_STATUS ProcessUserInput ( - IN USER_INPUT *UserInput, - IN BOOLEAN ChangeHighlight + IN USER_INPUT *UserInput ) { EFI_STATUS Status; FORM_BROWSER_STATEMENT *Statement; - Status = EFI_SUCCESS; + Status = EFI_SUCCESS; + Statement = NULL; // // When Exit from FormDisplay function, one of the below two cases must be true. @@ -1554,62 +1532,35 @@ ProcessUserInput ( // Remove the last highligh question id, this id will update when show next form. // gCurrentSelection->QuestionId = 0; + if (UserInput->SelectedStatement != NULL){ + Statement = GetBrowserStatement(UserInput->SelectedStatement); + ASSERT (Statement != NULL); + + // + // This question is the current user select one,record it and later + // show it as the highlight question. + // + gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId; + // + // For statement like text, actio, it not has question id. + // So use FakeQuestionId to save the question. + // + if (gCurrentSelection->CurrentMenu->QuestionId == 0) { + mCurFakeQestId = Statement->FakeQuestionId; + } else { + mCurFakeQestId = 0; + } + } // // First process the Action field in USER_INPUT. // if (UserInput->Action != 0) { Status = ProcessAction (UserInput->Action, UserInput->DefaultId); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Clear the highlight info. - // gCurrentSelection->Statement = NULL; - - if (UserInput->SelectedStatement != NULL) { - Statement = GetBrowserStatement(UserInput->SelectedStatement); - ASSERT (Statement != NULL); - // - // Save the current highlight menu in the menu history data. - // which will be used when later browse back to this form. - // - gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId; - // - // For statement like text, actio, it not has question id. - // So use FakeQuestionId to save the question. - // - if (gCurrentSelection->CurrentMenu->QuestionId == 0) { - mCurFakeQestId = Statement->FakeQuestionId; - } else { - mCurFakeQestId = 0; - } - } } else { - Statement = GetBrowserStatement(UserInput->SelectedStatement); ASSERT (Statement != NULL); - gCurrentSelection->Statement = Statement; - - if (ChangeHighlight) { - // - // This question is the current user select one,record it and later - // show it as the highlight question. - // - gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId; - // - // For statement like text, actio, it not has question id. - // So use FakeQuestionId to save the question. - // - if (gCurrentSelection->CurrentMenu->QuestionId == 0) { - mCurFakeQestId = Statement->FakeQuestionId; - } else { - mCurFakeQestId = 0; - } - } - switch (Statement->Operand) { case EFI_IFR_REF_OP: Status = ProcessGotoOpCode(Statement, gCurrentSelection); @@ -1626,7 +1577,8 @@ ProcessUserInput ( // // Reset Question to default value specified by DefaultId // - Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE); + Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE, FALSE); + UpdateStatementStatus (gCurrentSelection->FormSet, NULL, FormSetLevel); break; default: @@ -1649,6 +1601,7 @@ ProcessUserInput ( DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle); Statement->HiiValue.Value.string = UserInput->InputValue.Value.string; CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen); + ZeroMem (UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen); FreePool (UserInput->InputValue.Buffer); // // Two password match, send it to Configuration Driver @@ -1695,7 +1648,6 @@ DisplayForm ( EFI_STATUS Status; USER_INPUT UserInput; FORM_ENTRY_INFO *CurrentMenu; - BOOLEAN ChangeHighlight; ZeroMem (&UserInput, sizeof (USER_INPUT)); @@ -1711,11 +1663,14 @@ DisplayForm ( gCurrentSelection->FormId, gCurrentSelection->QuestionId); ASSERT (CurrentMenu != NULL); } - gCurrentSelection->CurrentMenu = CurrentMenu; // - // Find currrent highlight statement. + // Back up the form view history data for this form. // + UiCopyMenuList(&gCurrentSelection->Form->FormViewListHead, &mPrivateData.FormBrowserEx2.FormViewHistoryHead); + + gCurrentSelection->CurrentMenu = CurrentMenu; + if (gCurrentSelection->QuestionId == 0) { // // Highlight not specified, fetch it from cached menu @@ -1723,9 +1678,6 @@ DisplayForm ( gCurrentSelection->QuestionId = CurrentMenu->QuestionId; } - // - // Evaluate all the Expressions in this Form - // Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form); if (EFI_ERROR (Status)) { return Status; @@ -1733,33 +1685,15 @@ DisplayForm ( UpdateDisplayFormData (); - // - // Three possible status maybe return. - // - // EFI_INVALID_PARAMETER: The input dimension info is not valid. - // EFI_NOT_FOUND: The input value for oneof/orderedlist opcode is not valid - // and an valid value has return. - // EFI_SUCCESS: Success shows form and get user input in UserInput paramenter. - // + ASSERT (gDisplayFormData.BrowserStatus == BROWSER_SUCCESS); Status = mFormDisplay->FormDisplay (&gDisplayFormData, &UserInput); - if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) { + if (EFI_ERROR (Status)) { FreeDisplayFormData(); return Status; } - // - // If status is EFI_SUCCESS, means user has change the highlight menu and new user input return. - // in this case, browser need to change the highlight menu. - // If status is EFI_NOT_FOUND, means the input DisplayFormData has error for oneof/orderedlist - // opcode and new valid value has return, browser core need to adjust - // value for this opcode and shows this form again. - // - ChangeHighlight = (Status == EFI_SUCCESS ? TRUE :FALSE); - - Status = ProcessUserInput (&UserInput, ChangeHighlight); - + Status = ProcessUserInput (&UserInput); FreeDisplayFormData(); - return Status; } @@ -1871,70 +1805,6 @@ IsNvUpdateRequiredForForm ( return FALSE; } -/** - Check whether the storage data for current form set is changed. - - @param FormSet FormSet data structure. - - @retval TRUE Data is changed. - @retval FALSE Data is not changed. -**/ -BOOLEAN -IsStorageDataChangedForFormSet ( - IN FORM_BROWSER_FORMSET *FormSet - ) -{ - LIST_ENTRY *Link; - FORMSET_STORAGE *Storage; - BROWSER_STORAGE *BrowserStorage; - CHAR16 *ConfigRespNew; - CHAR16 *ConfigRespOld; - BOOLEAN RetVal; - - RetVal = FALSE; - ConfigRespNew = NULL; - ConfigRespOld = NULL; - - // - // Request current settings from Configuration Driver - // - Link = GetFirstNode (&FormSet->StorageListHead); - while (!IsNull (&FormSet->StorageListHead, Link)) { - Storage = FORMSET_STORAGE_FROM_LINK (Link); - Link = GetNextNode (&FormSet->StorageListHead, Link); - - BrowserStorage = Storage->BrowserStorage; - - if (BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { - continue; - } - - if (Storage->ElementCount == 0) { - continue; - } - - StorageToConfigResp (BrowserStorage, &ConfigRespNew, Storage->ConfigRequest, TRUE); - StorageToConfigResp (BrowserStorage, &ConfigRespOld, Storage->ConfigRequest, FALSE); - ASSERT (ConfigRespNew != NULL && ConfigRespOld != NULL); - - if (StrCmp (ConfigRespNew, ConfigRespOld) != 0) { - RetVal = TRUE; - } - - FreePool (ConfigRespNew); - ConfigRespNew = NULL; - - FreePool (ConfigRespOld); - ConfigRespOld = NULL; - - if (RetVal) { - break; - } - } - - return RetVal; -} - /** Find menu which will show next time. @@ -1951,7 +1821,7 @@ IsStorageDataChangedForFormSet ( BOOLEAN FindNextMenu ( IN OUT UI_MENU_SELECTION *Selection, - IN BROWSER_SETTING_SCOPE SettingLevel + IN BROWSER_SETTING_SCOPE SettingLevel ) { FORM_ENTRY_INFO *CurrentMenu; @@ -1959,31 +1829,16 @@ FindNextMenu ( BROWSER_SETTING_SCOPE Scope; CurrentMenu = Selection->CurrentMenu; - ParentMenu = NULL; Scope = FormSetLevel; - if (CurrentMenu != NULL && (ParentMenu = UiFindParentMenu(CurrentMenu)) != NULL) { - // - // we have a parent, so go to the parent menu - // - if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) { - if (SettingLevel == FormSetLevel) { - // - // Find a menu which has different formset guid with current. - // - while (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) { - CurrentMenu = ParentMenu; - if ((ParentMenu = UiFindParentMenu(CurrentMenu)) == NULL) { - break; - } - } + ParentMenu = UiFindParentMenu(CurrentMenu, SettingLevel); + while (ParentMenu != NULL && !ValidateHiiHandle(ParentMenu->HiiHandle)) { + ParentMenu = UiFindParentMenu(ParentMenu, SettingLevel); + } - if (ParentMenu != NULL) { - Scope = FormSetLevel; - } - } else { - Scope = FormLevel; - } + if (ParentMenu != NULL) { + if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) { + Scope = FormLevel; } else { Scope = FormSetLevel; } @@ -1994,7 +1849,7 @@ FindNextMenu ( // if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm (Selection->Form)) || (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet(Selection->FormSet) && Scope == FormSetLevel)) { - if (!ProcessChangedData(Selection, Scope)) { + if (!ProcessChangedData(Selection, gBrowserSettingScope)) { return FALSE; } } @@ -2031,6 +1886,30 @@ FindNextMenu ( return TRUE; } +/** + Reconnect the controller. + + @param DriverHandle The controller handle which need to be reconnect. + + @retval TRUE do the reconnect behavior success. + @retval FALSE do the reconnect behavior failed. + +**/ +BOOLEAN +ReconnectController ( + IN EFI_HANDLE DriverHandle + ) +{ + EFI_STATUS Status; + + Status = gBS->DisconnectController(DriverHandle, NULL, NULL); + if (!EFI_ERROR (Status)) { + Status = gBS->ConnectController(DriverHandle, NULL, NULL, TRUE); + } + + return Status == EFI_SUCCESS; +} + /** Call the call back function for the question and process the return action. @@ -2038,22 +1917,27 @@ FindNextMenu ( about the Selection, form and formset to be displayed. On output, Selection return the screen item that is selected by user. + @param FormSet The formset this question belong to. + @param Form The form this question belong to. @param Question The Question which need to call. @param Action The action request. @param SkipSaveOrDiscard Whether skip save or discard action. - @retval EFI_SUCCESS The call back function excutes successfully. - @return Other value if the call back function failed to excute. + @retval EFI_SUCCESS The call back function executes successfully. + @return Other value if the call back function failed to execute. **/ EFI_STATUS ProcessCallBackFunction ( IN OUT UI_MENU_SELECTION *Selection, + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_FORM *Form, IN FORM_BROWSER_STATEMENT *Question, IN EFI_BROWSER_ACTION Action, IN BOOLEAN SkipSaveOrDiscard ) { EFI_STATUS Status; + EFI_STATUS InternalStatus; EFI_BROWSER_ACTION_REQUEST ActionRequest; EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; EFI_HII_VALUE *HiiValue; @@ -2066,8 +1950,9 @@ ProcessCallBackFunction ( BROWSER_SETTING_SCOPE SettingLevel; EFI_IFR_TYPE_VALUE BackUpValue; UINT8 *BackUpBuffer; + CHAR16 *NewString; - ConfigAccess = Selection->FormSet->ConfigAccess; + ConfigAccess = FormSet->ConfigAccess; SubmitFormIsRequired = FALSE; SettingLevel = FormSetLevel; DiscardFormIsRequired = FALSE; @@ -2080,10 +1965,10 @@ ProcessCallBackFunction ( return EFI_SUCCESS; } - Link = GetFirstNode (&Selection->Form->StatementListHead); - while (!IsNull (&Selection->Form->StatementListHead, Link)) { + Link = GetFirstNode (&Form->StatementListHead); + while (!IsNull (&Form->StatementListHead, Link)) { Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link); - Link = GetNextNode (&Selection->Form->StatementListHead, Link); + Link = GetNextNode (&Form->StatementListHead, Link); // // if Question != NULL, only process the question. Else, process all question in this form. @@ -2100,7 +1985,7 @@ ProcessCallBackFunction ( // Check whether Statement is disabled. // if (Statement->Expression != NULL) { - if (EvaluateExpressionList(Statement->Expression, TRUE, Selection->FormSet, Selection->Form) == ExpressDisable) { + if (EvaluateExpressionList(Statement->Expression, TRUE, FormSet, Form) == ExpressDisable) { continue; } } @@ -2120,6 +2005,7 @@ ProcessCallBackFunction ( if (Action == EFI_BROWSER_ACTION_CHANGING) { if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) { BackUpBuffer = AllocateCopyPool(Statement->StorageWidth + sizeof(CHAR16), Statement->BufferValue); + ASSERT (BackUpBuffer != NULL); } else { CopyMem (&BackUpValue, &HiiValue->Value, sizeof (EFI_IFR_TYPE_VALUE)); } @@ -2135,14 +2021,33 @@ ProcessCallBackFunction ( &ActionRequest ); if (!EFI_ERROR (Status)) { + // + // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue + // + if (HiiValue->Type == EFI_IFR_TYPE_STRING) { + NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle); + ASSERT (NewString != NULL); + + ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth); + if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) { + ZeroMem (Statement->BufferValue, Statement->StorageWidth); + CopyMem (Statement->BufferValue, NewString, StrSize (NewString)); + } else { + CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth); + } + FreePool (NewString); + } + // // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest. // - if (Action == EFI_BROWSER_ACTION_CHANGED) { + switch (Action) { + case EFI_BROWSER_ACTION_CHANGED: switch (ActionRequest) { case EFI_BROWSER_ACTION_REQUEST_RESET: DiscardFormIsRequired = TRUE; - gResetRequired = TRUE; + gResetRequiredFormLevel = TRUE; + gResetRequiredSystemLevel = TRUE; NeedExit = TRUE; break; @@ -2178,17 +2083,44 @@ ProcessCallBackFunction ( SettingLevel = FormLevel; break; + case EFI_BROWSER_ACTION_REQUEST_RECONNECT: + gCallbackReconnect = TRUE; + break; + default: break; } - } + break; - // - // According the spec, return value from call back of "changing" and - // "retrieve" should update to the question's temp buffer. - // - if (Action == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) { - SetQuestionValue(Selection->FormSet, Selection->Form, Statement, GetSetValueWithEditBuffer); + case EFI_BROWSER_ACTION_CHANGING: + // + // Do the question validation. + // + Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement); + if (!EFI_ERROR (Status)) { + // + //check whether the question value changed compared with edit buffer before updating edit buffer + // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function + // + IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer); + // + // According the spec, return value from call back of "changing" and + // "retrieve" should update to the question's temp buffer. + // + SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer); + } + break; + + case EFI_BROWSER_ACTION_RETRIEVE: + // + // According the spec, return value from call back of "changing" and + // "retrieve" should update to the question's temp buffer. + // + SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer); + break; + + default: + break; } } else { // @@ -2202,17 +2134,35 @@ ProcessCallBackFunction ( } else { CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE)); } - - SetQuestionValue(Selection->FormSet, Selection->Form, Statement, GetSetValueWithEditBuffer); + + // + // Do the question validation. + // + InternalStatus = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement); + if (!EFI_ERROR (InternalStatus)) { + // + //check whether the question value changed compared with edit buffer before updating edit buffer + // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function + // + IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer); + SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer); + } } // // According the spec, return fail from call back of "changing" and // "retrieve", should restore the question's value. // - if ((Action == EFI_BROWSER_ACTION_CHANGING && Status != EFI_UNSUPPORTED) || - Action == EFI_BROWSER_ACTION_RETRIEVE) { - GetQuestionValue(Selection->FormSet, Selection->Form, Statement, GetSetValueWithEditBuffer); + if (Action == EFI_BROWSER_ACTION_CHANGING && Status != EFI_UNSUPPORTED) { + if (Statement->Storage != NULL) { + GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer); + } else if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { + ProcessCallBackFunction (Selection, FormSet, Form, Question, EFI_BROWSER_ACTION_RETRIEVE, FALSE); + } + } + + if (Action == EFI_BROWSER_ACTION_RETRIEVE) { + GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer); } if (Status == EFI_UNSUPPORTED) { @@ -2226,14 +2176,45 @@ ProcessCallBackFunction ( if (BackUpBuffer != NULL) { FreePool (BackUpBuffer); } + + // + // If Question != NULL, means just process one question + // and if code reach here means this question has finished + // processing, so just break. + // + if (Question != NULL) { + break; + } + } + + if (gCallbackReconnect && (EFI_BROWSER_ACTION_CHANGED == Action)) { + // + // Confirm changes with user first. + // + if (IsNvUpdateRequiredForFormSet(FormSet)) { + if (BROWSER_ACTION_DISCARD == PopupErrorMessage(BROWSER_RECONNECT_SAVE_CHANGES, NULL, NULL, NULL)) { + gCallbackReconnect = FALSE; + DiscardFormIsRequired = TRUE; + } else { + SubmitFormIsRequired = TRUE; + } + } else { + PopupErrorMessage(BROWSER_RECONNECT_REQUIRED, NULL, NULL, NULL); + } + + // + // Exit current formset before do the reconnect. + // + NeedExit = TRUE; + SettingLevel = FormSetLevel; } if (SubmitFormIsRequired && !SkipSaveOrDiscard) { - SubmitForm (Selection->FormSet, Selection->Form, SettingLevel); + SubmitForm (FormSet, Form, SettingLevel); } if (DiscardFormIsRequired && !SkipSaveOrDiscard) { - DiscardForm (Selection->FormSet, Selection->Form, SettingLevel); + DiscardForm (FormSet, Form, SettingLevel); } if (NeedExit) { @@ -2251,25 +2232,28 @@ ProcessCallBackFunction ( @param ConfigAccess The config access protocol produced by the hii driver. @param Statement The Question which need to call. + @param FormSet The formset this question belong to. - @retval EFI_SUCCESS The call back function excutes successfully. - @return Other value if the call back function failed to excute. + @retval EFI_SUCCESS The call back function executes successfully. + @return Other value if the call back function failed to execute. **/ EFI_STATUS ProcessRetrieveForQuestion ( IN EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess, - IN FORM_BROWSER_STATEMENT *Statement + IN FORM_BROWSER_STATEMENT *Statement, + IN FORM_BROWSER_FORMSET *FormSet ) { EFI_STATUS Status; EFI_BROWSER_ACTION_REQUEST ActionRequest; EFI_HII_VALUE *HiiValue; EFI_IFR_TYPE_VALUE *TypeValue; + CHAR16 *NewString; Status = EFI_SUCCESS; ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; - - if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) { + + if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) || ConfigAccess == NULL) { return EFI_UNSUPPORTED; } @@ -2291,6 +2275,20 @@ ProcessRetrieveForQuestion ( TypeValue, &ActionRequest ); + if (!EFI_ERROR (Status) && HiiValue->Type == EFI_IFR_TYPE_STRING) { + NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle); + ASSERT (NewString != NULL); + + ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth); + if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) { + ZeroMem (Statement->BufferValue, Statement->StorageWidth); + CopyMem (Statement->BufferValue, NewString, StrSize (NewString)); + } else { + CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth); + } + FreePool (NewString); + } + return Status; } @@ -2351,8 +2349,16 @@ SetupBrowser ( mCurFakeQestId = 0; do { + + // + // Reset Status to prevent the next break from returning incorrect error status. + // + Status = EFI_SUCCESS; + // // IFR is updated, force to reparse the IFR binary + // This check is shared by EFI_BROWSER_ACTION_FORM_CLOSE and + // EFI_BROWSER_ACTION_RETRIEVE, so code place here. // if (mHiiPackageListUpdated) { Selection->Action = UI_ACTION_REFRESH_FORMSET; @@ -2391,7 +2397,7 @@ SetupBrowser ( // // Form is suppressed. // - gBrowserStatus = BROWSER_FORM_SUPPRESS; + PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL); Status = EFI_NOT_FOUND; goto Done; } @@ -2402,10 +2408,14 @@ SetupBrowser ( // for each question with callback flag. // New form may be the first form, or the different form after another form close. // - if ((ConfigAccess != NULL) && - ((Selection->Handle != mCurrentHiiHandle) || + if (((Selection->Handle != mCurrentHiiHandle) || (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) || (Selection->FormId != mCurrentFormId))) { + // + // Update Retrieve flag. + // + mFinishRetrieveCall = FALSE; + // // Keep current form information // @@ -2413,18 +2423,20 @@ SetupBrowser ( CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid); mCurrentFormId = Selection->FormId; - Status = ProcessCallBackFunction (Selection, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE); - if (EFI_ERROR (Status)) { - goto Done; - } + if (ConfigAccess != NULL) { + Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE); + if (EFI_ERROR (Status)) { + goto Done; + } - // - // IFR is updated during callback of open form, force to reparse the IFR binary - // - if (mHiiPackageListUpdated) { - Selection->Action = UI_ACTION_REFRESH_FORMSET; - mHiiPackageListUpdated = FALSE; - break; + // + // IFR is updated during callback of EFI_BROWSER_ACTION_FORM_OPEN, force to reparse the IFR binary + // + if (mHiiPackageListUpdated) { + Selection->Action = UI_ACTION_REFRESH_FORMSET; + mHiiPackageListUpdated = FALSE; + break; + } } } @@ -2436,13 +2448,27 @@ SetupBrowser ( goto Done; } - // - // IFR is updated during callback of read value, force to reparse the IFR binary - // - if (mHiiPackageListUpdated) { - Selection->Action = UI_ACTION_REFRESH_FORMSET; - mHiiPackageListUpdated = FALSE; - break; + if (!mFinishRetrieveCall) { + // + // Finish call RETRIEVE callback for this form. + // + mFinishRetrieveCall = TRUE; + + if (ConfigAccess != NULL) { + Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_RETRIEVE, FALSE); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // IFR is updated during callback of open form, force to reparse the IFR binary + // + if (mHiiPackageListUpdated) { + Selection->Action = UI_ACTION_REFRESH_FORMSET; + mHiiPackageListUpdated = FALSE; + break; + } + } } // @@ -2461,7 +2487,7 @@ SetupBrowser ( if ((ConfigAccess != NULL) && ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) { - Status = ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE); + Status = ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE); if (Statement->Operand == EFI_IFR_REF_OP) { // // Process dynamic update ref opcode. @@ -2475,18 +2501,58 @@ SetupBrowser ( // if (EFI_ERROR (Status)) { // - // Cross reference will not be taken + // Cross reference will not be taken, restore all essential field // - Selection->FormId = Selection->Form->FormId; + Selection->Handle = mCurrentHiiHandle; + CopyMem (&Selection->FormSetGuid, &mCurrentFormSetGuid, sizeof (EFI_GUID)); + Selection->FormId = mCurrentFormId; Selection->QuestionId = 0; + Selection->Action = UI_ACTION_REFRESH_FORM; } } - if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) { - ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE); + + if (!EFI_ERROR (Status) && + (Statement->Operand != EFI_IFR_REF_OP) && + ((Statement->Storage == NULL) || (Statement->Storage != NULL && Statement->ValueChanged))) { + // + // Only question value has been changed, browser will trig CHANGED callback. + // + ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE); + // + //check whether the question value changed compared with buffer value + //if doesn't change ,set the ValueChanged flag to FALSE ,in order not to display the "configuration changed "information on the screen + // + IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer); + } + } else { + // + // Do the question validation. + // + Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement); + if (!EFI_ERROR (Status) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) { + SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer); + // + // Verify whether question value has checked, update the ValueChanged flag in Question. + // + IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer); + } + } + + // + // If question has EFI_IFR_FLAG_RESET_REQUIRED/EFI_IFR_FLAG_RECONNECT_REQUIRED flag and without storage + // and process question success till here, trig the gResetFlag/gFlagReconnect. + // + if ((Status == EFI_SUCCESS) && + (Statement->Storage == NULL)) { + if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0) { + gResetRequiredFormLevel = TRUE; + gResetRequiredSystemLevel = TRUE; + } + + if ((Statement->QuestionFlags & EFI_IFR_FLAG_RECONNECT_REQUIRED) != 0) { + gFlagReconnect = TRUE; } - } else if (Statement->Operand != EFI_IFR_PASSWORD_OP) { - SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer); } } @@ -2521,7 +2587,7 @@ SetupBrowser ( (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) || (Selection->FormId != mCurrentFormId))) { - Status = ProcessCallBackFunction (Selection, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE); + Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE); if (EFI_ERROR (Status)) { goto Done; }