+ GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+\r
+ if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
+ TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;\r
+ } else {\r
+ TypeValue = &Question->HiiValue.Value;\r
+ }\r
+\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ FormSet->ConfigAccess->Callback (\r
+ FormSet->ConfigAccess,\r
+ EFI_BROWSER_ACTION_CHANGED,\r
+ Question->QuestionId,\r
+ Question->HiiValue.Type,\r
+ TypeValue,\r
+ &ActionRequest\r
+ );\r
+ }\r
+}\r
+\r
+/**\r
+ Validate the HiiHandle.\r
+\r
+ @param HiiHandle The input HiiHandle which need to validate.\r
+\r
+ @retval TRUE The handle is validate.\r
+ @retval FALSE The handle is invalidate.\r
+\r
+**/\r
+BOOLEAN\r
+ValidateHiiHandle (\r
+ EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ EFI_HII_HANDLE *HiiHandles;\r
+ UINTN Index;\r
+ BOOLEAN Find;\r
+\r
+ if (HiiHandle == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ Find = FALSE;\r
+\r
+ HiiHandles = HiiGetHiiHandles (NULL);\r
+ ASSERT (HiiHandles != NULL);\r
+\r
+ for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
+ if (HiiHandles[Index] == HiiHandle) {\r
+ Find = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ FreePool (HiiHandles);\r
+\r
+ return Find;\r
+}\r
+\r
+/**\r
+ Validate the FormSet. If the formset is not validate, remove it from the list.\r
+\r
+ @param FormSet The input FormSet which need to validate.\r
+\r
+ @retval TRUE The handle is validate.\r
+ @retval FALSE The handle is invalidate.\r
+\r
+**/\r
+BOOLEAN\r
+ValidateFormSet (\r
+ FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+{\r
+ BOOLEAN Find;\r
+\r
+ ASSERT (FormSet != NULL);\r
+\r
+ Find = ValidateHiiHandle(FormSet->HiiHandle);\r
+ //\r
+ // Should not remove the formset which is being used.\r
+ //\r
+ if (!Find && (FormSet != gCurrentSelection->FormSet)) {\r
+ CleanBrowserStorage(FormSet);\r
+ RemoveEntryList (&FormSet->Link);\r
+ DestroyFormSet (FormSet);\r
+ }\r
+\r
+ return Find;\r
+}\r
+/**\r
+ Check whether need to enable the reset flag in form level.\r
+ Also clean all ValueChanged flag in question.\r
+\r
+ @param SetFlag Whether need to set the Reset Flag.\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+\r
+**/\r
+VOID\r
+UpdateFlagForForm (\r
+ IN BOOLEAN SetFlag,\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+ BOOLEAN OldValue;\r
+\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+ if (!Question->ValueChanged) {\r
+ continue;\r
+ }\r
+\r
+ OldValue = Question->ValueChanged;\r
+\r
+ //\r
+ // Compare the buffer and editbuffer data to see whether the data has been saved.\r
+ //\r
+ Question->ValueChanged = IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBothBuffer);\r
+\r
+ //\r
+ // Only the changed data has been saved, then need to set the reset flag.\r
+ //\r
+ if (SetFlag && OldValue && !Question->ValueChanged && ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {\r
+ gResetRequired = TRUE;\r
+ } \r
+ }\r
+}\r
+\r
+/**\r
+ Check whether need to enable the reset flag.\r
+ Also clean ValueChanged flag for all statements.\r
+\r
+ Form level or formset level, only one.\r
+ \r
+ @param SetFlag Whether need to set the Reset Flag.\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+\r
+**/\r
+VOID\r
+ValueChangeResetFlagUpdate (\r
+ IN BOOLEAN SetFlag,\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form \r
+ )\r
+{\r
+ FORM_BROWSER_FORM *CurrentForm;\r
+ LIST_ENTRY *Link;\r
+\r
+ if (Form != NULL) {\r
+ UpdateFlagForForm(SetFlag, FormSet, Form);\r
+ return;\r
+ }\r
+\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+\r
+ UpdateFlagForForm(SetFlag, FormSet, CurrentForm);\r
+ }\r
+}\r
+\r
+/**\r
+ Base on the return Progress string to find the form. \r
+ \r
+ Base on the first return Offset/Width (Name) string to find the form\r
+ which keep this string.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Storage Storage which has this Progress string.\r
+ @param Progress The Progress string which has the first fail string.\r
+ @param RetForm The return form for this progress string.\r
+ @param RetQuestion The return question for the error progress string.\r
+\r
+ @retval TRUE Find the error form and statement for this error progress string.\r
+ @retval FALSE Not find the error form.\r
+\r
+**/\r
+BOOLEAN\r
+FindQuestionFromProgress (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN BROWSER_STORAGE *Storage,\r
+ IN EFI_STRING Progress,\r
+ OUT FORM_BROWSER_FORM **RetForm,\r
+ OUT FORM_BROWSER_STATEMENT **RetQuestion\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *LinkStorage;\r
+ LIST_ENTRY *LinkStatement;\r
+ FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
+ FORM_BROWSER_FORM *Form;\r
+ EFI_STRING EndStr;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+\r
+ ASSERT ((*Progress == '&') || (*Progress == 'G'));\r
+\r
+ ConfigInfo = NULL;\r
+ *RetForm = NULL;\r
+ *RetQuestion = NULL;\r
+\r
+ //\r
+ // Skip the first "&" or the ConfigHdr part.\r
+ //\r
+ if (*Progress == '&') {\r
+ Progress++;\r
+ } else {\r
+ //\r
+ // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
+ //\r
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // For Name/Value type, Skip the ConfigHdr part.\r
+ //\r
+ EndStr = StrStr (Progress, L"PATH=");\r
+ ASSERT (EndStr != NULL);\r
+ while (*EndStr != '&') {\r
+ EndStr++;\r
+ }\r
+\r
+ *EndStr = '\0';\r
+ } else {\r
+ //\r
+ // For Buffer type, Skip the ConfigHdr part.\r
+ //\r
+ EndStr = StrStr (Progress, L"&OFFSET=");\r
+ ASSERT (EndStr != NULL);\r
+ *EndStr = '\0';\r
+ }\r
+\r
+ Progress = EndStr + 1;\r
+ }\r
+\r
+ //\r
+ // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
+ //\r
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,\r
+ // here, just keep the "Fred" string.\r
+ //\r
+ EndStr = StrStr (Progress, L"=");\r
+ ASSERT (EndStr != NULL);\r
+ *EndStr = '\0';\r
+ } else {\r
+ //\r
+ // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",\r
+ // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.\r
+ //\r
+ EndStr = StrStr (Progress, L"&VALUE=");\r
+ ASSERT (EndStr != NULL);\r
+ *EndStr = '\0';\r
+ }\r
+\r
+ //\r
+ // Search in the form list.\r
+ //\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+\r
+ //\r
+ // Search in the ConfigReqeust list in this form.\r
+ //\r
+ LinkStorage = GetFirstNode (&Form->ConfigRequestHead);\r
+ while (!IsNull (&Form->ConfigRequestHead, LinkStorage)) {\r
+ ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage);\r
+ LinkStorage = GetNextNode (&Form->ConfigRequestHead, LinkStorage);\r
+\r
+ if (Storage != ConfigInfo->Storage) {\r
+ continue;\r
+ }\r
+\r
+ if (StrStr (ConfigInfo->ConfigRequest, Progress) != NULL) {\r
+ //\r
+ // Find the OffsetWidth string in this form.\r
+ //\r
+ *RetForm = Form;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (*RetForm != NULL) {\r
+ LinkStatement = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, LinkStatement)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);\r
+ LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);\r
+\r
+ if (Statement->BlockName != NULL && StrStr (Statement->BlockName, Progress) != NULL) {\r
+ *RetQuestion = Statement;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (*RetForm != NULL) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // restore the OffsetWidth string to the original format.\r
+ //\r
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ *EndStr = '=';\r
+ } else {\r
+ *EndStr = '&';\r
+ }\r
+\r
+ return (BOOLEAN) (*RetForm != NULL);\r
+}\r
+\r
+/**\r
+ Popup an save error info and get user input.\r
+\r
+ @param TitleId The form title id.\r
+ @param HiiHandle The hii handle for this package.\r
+\r
+ @retval UINT32 The user select option for the save fail.\r
+ BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
+**/\r
+UINT32\r
+ConfirmSaveFail (\r
+ IN EFI_STRING_ID TitleId,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ CHAR16 *FormTitle;\r
+ CHAR16 *StringBuffer;\r
+ UINT32 RetVal;\r
+\r
+ FormTitle = GetToken (TitleId, HiiHandle);\r
+\r
+ StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
+ ASSERT (StringBuffer != NULL);\r
+\r
+ UnicodeSPrint (\r
+ StringBuffer, \r
+ 24 * sizeof (CHAR16) + StrSize (FormTitle), \r
+ L"Submit Fail For Form: %s.", \r
+ FormTitle\r
+ );\r
+\r
+ RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL, NULL, NULL, StringBuffer);\r
+\r
+ FreePool (StringBuffer);\r
+ FreePool (FormTitle);\r
+\r
+ return RetVal;\r
+}\r
+\r
+/**\r
+ Popup an NO_SUBMIT_IF error info and get user input.\r
+\r
+ @param TitleId The form title id.\r
+ @param HiiHandle The hii handle for this package.\r
+\r
+ @retval UINT32 The user select option for the save fail.\r
+ BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
+**/\r
+UINT32\r
+ConfirmNoSubmitFail (\r
+ IN EFI_STRING_ID TitleId,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ CHAR16 *FormTitle;\r
+ CHAR16 *StringBuffer;\r
+ UINT32 RetVal;\r
+\r
+ FormTitle = GetToken (TitleId, HiiHandle);\r
+\r
+ StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
+ ASSERT (StringBuffer != NULL);\r
+\r
+ UnicodeSPrint (\r
+ StringBuffer, \r
+ 24 * sizeof (CHAR16) + StrSize (FormTitle), \r
+ L"NO_SUBMIT_IF error For Form: %s.", \r
+ FormTitle\r
+ );\r
+\r
+ RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF, NULL, NULL, StringBuffer);\r
+\r
+ FreePool (StringBuffer);\r
+ FreePool (FormTitle);\r
+\r
+ return RetVal;\r
+}\r
+\r
+/**\r
+ Discard data based on the input setting scope (Form, FormSet or System).\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param SettingScope Setting Scope for Discard action.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+DiscardForm (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN BROWSER_SETTING_SCOPE SettingScope\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORMSET_STORAGE *Storage;\r
+ FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
+ FORM_BROWSER_FORMSET *LocalFormSet;\r
+ FORM_BROWSER_FORMSET *OldFormSet;\r
+\r
+ //\r
+ // Check the supported setting level.\r
+ //\r
+ if (SettingScope >= MaxLevel) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {\r
+ ConfigInfo = NULL;\r
+ Link = GetFirstNode (&Form->ConfigRequestHead);\r
+ while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+ ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+ if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Skip if there is no RequestElement\r
+ //\r
+ if (ConfigInfo->ElementCount == 0) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Prepare <ConfigResp>\r
+ //\r
+ SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
+\r
+ //\r
+ // Call callback with Changed type to inform the driver.\r
+ //\r
+ SendDiscardInfoToDriver (FormSet, Form);\r
+ }\r
+\r
+ ValueChangeResetFlagUpdate (FALSE, FormSet, Form);\r
+ } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {\r
+\r
+ //\r
+ // Discard Buffer storage or Name/Value storage\r
+ //\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r