+ //\r
+ // Set the extra attribute.\r
+ //\r
+ DisplayStatement->Attribute |= ExtraAttribute;\r
+\r
+ if (Statement->Storage != NULL) {\r
+ FormEditable = TRUE;\r
+ }\r
+\r
+ //\r
+ // Get the minimal refresh interval value for later use.\r
+ //\r
+ if ((Statement->RefreshInterval != 0) && \r
+ (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval)) {\r
+ MinRefreshInterval = Statement->RefreshInterval;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Create the periodic timer for refresh interval statement.\r
+ //\r
+ if (MinRefreshInterval != 0) {\r
+ Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshIntervalProcess, NULL, &RefreshIntervalEvent);\r
+ ASSERT_EFI_ERROR (Status);\r
+ Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, MinRefreshInterval * ONE_SECOND);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));\r
+ ASSERT (EventNode != NULL);\r
+ EventNode->RefreshEvent = RefreshIntervalEvent;\r
+ InsertTailList(&mRefreshEventList, &EventNode->Link);\r
+ }\r
+\r
+ //\r
+ // Create the refresh event process function for Form.\r
+ //\r
+ if (!CompareGuid (&gCurrentSelection->Form->RefreshGuid, &gZeroGuid)) {\r
+ CreateRefreshEventForForm (gCurrentSelection->Form);\r
+ if (gDisplayFormData.FormRefreshEvent == NULL) {\r
+ gDisplayFormData.FormRefreshEvent = mValueChangedEvent;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Update hotkey list field.\r
+ //\r
+ if (gBrowserSettingScope == SystemLevel || FormEditable) {\r
+ UpdateHotkeyList();\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Initialize the SettingChangedFlag variable in the display form.\r
+\r
+**/\r
+VOID\r
+UpdateDataChangedFlag (\r
+ VOID\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORMSET *LocalFormSet;\r
+\r
+ gDisplayFormData.SettingChangedFlag = FALSE;\r
+\r
+ if (IsNvUpdateRequiredForForm (gCurrentSelection->Form)) {\r
+ gDisplayFormData.SettingChangedFlag = TRUE;\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Base on the system level to check whether need to show the NV flag.\r
+ // \r
+ switch (gBrowserSettingScope) {\r
+ case SystemLevel:\r
+ //\r
+ // Check the maintain list to see whether there is any change.\r
+ //\r
+ Link = GetFirstNode (&gBrowserFormSetList);\r
+ while (!IsNull (&gBrowserFormSetList, Link)) {\r
+ LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+ if (IsNvUpdateRequiredForFormSet(LocalFormSet)) {\r
+ gDisplayFormData.SettingChangedFlag = TRUE;\r
+ return;\r
+ }\r
+ Link = GetNextNode (&gBrowserFormSetList, Link);\r
+ }\r
+ break;\r
+\r
+ case FormSetLevel:\r
+ if (IsNvUpdateRequiredForFormSet(gCurrentSelection->FormSet)) {\r
+ gDisplayFormData.SettingChangedFlag = TRUE;\r
+ return;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Initialize the Display form structure data.\r
+\r
+**/\r
+VOID\r
+InitializeDisplayFormData (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ gDisplayFormData.Signature = FORM_DISPLAY_ENGINE_FORM_SIGNATURE;\r
+ gDisplayFormData.Version = FORM_DISPLAY_ENGINE_VERSION_1;\r
+ gDisplayFormData.ImageId = 0;\r
+ gDisplayFormData.AnimationId = 0;\r
+\r
+ InitializeListHead (&gDisplayFormData.StatementListHead);\r
+ InitializeListHead (&gDisplayFormData.StatementListOSF);\r
+ InitializeListHead (&gDisplayFormData.HotKeyListHead);\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT, \r
+ TPL_CALLBACK,\r
+ SetupBrowserEmptyFunction,\r
+ NULL,\r
+ &mValueChangedEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status); \r
+}\r
+\r
+/**\r
+\r
+ Free the kotkey info saved in form data.\r
+\r
+**/\r
+VOID\r
+FreeHotkeyList (\r
+ VOID\r
+ )\r
+{\r
+ BROWSER_HOT_KEY *HotKey;\r
+ LIST_ENTRY *Link;\r
+\r
+ while (!IsListEmpty (&gDisplayFormData.HotKeyListHead)) {\r
+ Link = GetFirstNode (&gDisplayFormData.HotKeyListHead);\r
+ HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
+\r
+ RemoveEntryList (&HotKey->Link);\r
+\r
+ FreePool (HotKey->KeyData);\r
+ FreePool (HotKey->HelpString);\r
+ FreePool (HotKey);\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Update the Display form structure data.\r
+\r
+**/\r
+VOID\r
+UpdateDisplayFormData (\r
+ VOID\r
+ )\r
+{\r
+ gDisplayFormData.FormTitle = gCurrentSelection->Form->FormTitle;\r
+ gDisplayFormData.FormId = gCurrentSelection->FormId;\r
+ gDisplayFormData.HiiHandle = gCurrentSelection->Handle;\r
+ CopyGuid (&gDisplayFormData.FormSetGuid, &gCurrentSelection->FormSetGuid);\r
+\r
+ gDisplayFormData.Attribute = 0;\r
+ gDisplayFormData.Attribute |= gCurrentSelection->Form->ModalForm ? HII_DISPLAY_MODAL : 0;\r
+ gDisplayFormData.Attribute |= gCurrentSelection->Form->Locked ? HII_DISPLAY_LOCK : 0;\r
+\r
+ gDisplayFormData.FormRefreshEvent = NULL;\r
+ gDisplayFormData.HighLightedStatement = NULL;\r
+\r
+ UpdateDataChangedFlag ();\r
+\r
+ AddStatementToDisplayForm ();\r
+}\r
+\r
+/**\r
+\r
+ Free the Display Statement structure data.\r
+\r
+ @param StatementList Point to the statement list which need to be free.\r
+\r
+**/\r
+VOID\r
+FreeStatementData (\r
+ LIST_ENTRY *StatementList\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *OptionLink;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
+ DISPLAY_QUESTION_OPTION *Option;\r
+\r
+ //\r
+ // Free Statements/Questions\r
+ //\r
+ while (!IsListEmpty (StatementList)) {\r
+ Link = GetFirstNode (StatementList);\r
+ Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
+\r
+ //\r
+ // Free Options List\r
+ //\r
+ while (!IsListEmpty (&Statement->OptionListHead)) {\r
+ OptionLink = GetFirstNode (&Statement->OptionListHead);\r
+ Option = DISPLAY_QUESTION_OPTION_FROM_LINK (OptionLink);\r
+ RemoveEntryList (&Option->Link);\r
+ FreePool (Option);\r
+ }\r
+\r
+ //\r
+ // Free nest statement List\r
+ //\r
+ if (!IsListEmpty (&Statement->NestStatementList)) {\r
+ FreeStatementData(&Statement->NestStatementList);\r
+ }\r
+\r
+ RemoveEntryList (&Statement->DisplayLink);\r
+ FreePool (Statement);\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Free the Display form structure data.\r
+\r
+**/\r
+VOID\r
+FreeDisplayFormData (\r
+ VOID\r
+ )\r
+{\r
+ FreeStatementData (&gDisplayFormData.StatementListHead);\r
+ FreeStatementData (&gDisplayFormData.StatementListOSF);\r
+\r
+ FreeRefreshEvent();\r
+\r
+ FreeHotkeyList();\r
+}\r
+\r
+/**\r
+\r
+ Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.\r
+\r
+ @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT.\r
+\r
+ @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info.\r
+\r
+**/\r
+FORM_BROWSER_STATEMENT *\r
+GetBrowserStatement (\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement\r
+ )\r
+{\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+ LIST_ENTRY *Link;\r
+\r
+ Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead);\r
+ while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+ if (Statement->OpCode == DisplayStatement->OpCode) {\r
+ return Statement;\r
+ }\r
+\r
+ Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Update the ValueChanged status for questions in this form.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+\r
+**/\r
+VOID \r
+UpdateStatementStatusForForm (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+ //\r
+ // For password opcode, not set the the value changed flag.\r
+ //\r
+ if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
+ continue;\r
+ }\r
+\r
+ IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBuffer);\r
+ }\r
+}\r
+\r
+/**\r
+ Update the ValueChanged status for questions in this formset.\r
+\r
+ @param FormSet FormSet data structure.\r
+\r
+**/\r
+VOID \r
+UpdateStatementStatusForFormSet (\r
+ IN FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORM *Form;\r
+\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+\r
+ UpdateStatementStatusForForm (FormSet, Form);\r
+ }\r
+}\r
+\r
+/**\r
+ Update the ValueChanged status for questions.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param SettingScope Setting Scope for Default action.\r
+\r
+**/\r
+VOID \r
+UpdateStatementStatus (\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
+ FORM_BROWSER_FORMSET *LocalFormSet;\r
+\r
+ switch (SettingScope) {\r
+ case SystemLevel:\r
+ Link = GetFirstNode (&gBrowserFormSetList);\r
+ while (!IsNull (&gBrowserFormSetList, Link)) {\r
+ LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+ Link = GetNextNode (&gBrowserFormSetList, Link);\r
+ if (!ValidateFormSet(LocalFormSet)) {\r
+ continue;\r
+ }\r
+\r
+ UpdateStatementStatusForFormSet (LocalFormSet);\r
+ }\r
+ break;\r
+\r
+ case FormSetLevel:\r
+ UpdateStatementStatusForFormSet (FormSet);\r
+ break;\r
+\r
+ case FormLevel:\r
+ UpdateStatementStatusForForm (FormSet, Form);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Process the action request in user input.\r
+\r
+ @param Action The user input action request info.\r
+ @param DefaultId The user input default Id info.\r
+\r
+ @retval EFI_SUCESSS This function always return successfully for now.\r
+\r
+**/\r
+EFI_STATUS \r
+ProcessAction (\r
+ IN UINT32 Action,\r
+ IN UINT16 DefaultId\r
+ )\r
+{\r
+ //\r
+ // This is caused by use press ESC, and it should not combine with other action type.\r
+ //\r
+ if ((Action & BROWSER_ACTION_FORM_EXIT) == BROWSER_ACTION_FORM_EXIT) {\r
+ FindNextMenu (gCurrentSelection, FormLevel);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Below is normal hotkey trigged action, these action maybe combine with each other.\r
+ //\r
+ if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
+ DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+ }\r
+\r
+ if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
+ ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE, FALSE);\r
+ UpdateStatementStatus (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+ }\r
+\r
+ if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {\r
+ SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+ }\r
+\r
+ if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
+ gResetRequired = TRUE;\r
+ }\r
+\r
+ if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {\r
+ //\r
+ // Form Exit without saving, Similar to ESC Key.\r
+ // FormSet Exit without saving, Exit SendForm.\r
+ // System Exit without saving, CallExitHandler and Exit SendForm.\r
+ //\r
+ DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+ if (gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) {\r
+ FindNextMenu (gCurrentSelection, gBrowserSettingScope);\r
+ } else if (gBrowserSettingScope == SystemLevel) {\r
+ if (ExitHandlerFunction != NULL) {\r
+ ExitHandlerFunction ();\r
+ }\r
+ gCurrentSelection->Action = UI_ACTION_EXIT;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Check whether the formset guid is in this Hii package list.\r
+\r
+ @param HiiHandle The HiiHandle for this HII package list.\r
+ @param FormSetGuid The formset guid for the request formset.\r
+\r
+ @retval TRUE Find the formset guid.\r
+ @retval FALSE Not found the formset guid.\r
+\r
+**/\r
+BOOLEAN\r
+GetFormsetGuidFromHiiHandle (\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN EFI_GUID *FormSetGuid\r
+ )\r
+{\r
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
+ UINTN BufferSize;\r
+ UINT32 Offset;\r
+ UINT32 Offset2;\r
+ UINT32 PackageListLength;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ UINT8 *Package;\r
+ UINT8 *OpCodeData;\r
+ EFI_STATUS Status;\r
+ BOOLEAN FindGuid;\r
+\r
+ BufferSize = 0;\r
+ HiiPackageList = NULL;\r
+ FindGuid = FALSE;\r
+ \r
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ HiiPackageList = AllocatePool (BufferSize);\r
+ ASSERT (HiiPackageList != NULL);\r
+\r
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+ }\r
+ if (EFI_ERROR (Status) || HiiPackageList == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Get Form package from this HII package List\r
+ //\r
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ Offset2 = 0;\r
+ CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); \r
+\r
+ while (Offset < PackageListLength) {\r
+ Package = ((UINT8 *) HiiPackageList) + Offset;\r
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ Offset += PackageHeader.Length;\r
+\r
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
+ //\r
+ // Search FormSet in this Form Package\r
+ //\r
+ Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ while (Offset2 < PackageHeader.Length) {\r
+ OpCodeData = Package + Offset2;\r
+\r
+ if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
+ if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))){\r
+ FindGuid = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+ }\r
+ }\r
+ if (FindGuid) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ FreePool (HiiPackageList);\r
+\r
+ return FindGuid;\r
+}\r
+\r
+/**\r
+ Find HII Handle in the HII database associated with given Device Path.\r
+\r
+ If DevicePath is NULL, then ASSERT.\r
+\r
+ @param DevicePath Device Path associated with the HII package list\r
+ handle.\r
+ @param FormsetGuid The formset guid for this formset.\r
+\r
+ @retval Handle HII package list Handle associated with the Device\r
+ Path.\r
+ @retval NULL Hii Package list handle is not found.\r
+\r
+**/\r
+EFI_HII_HANDLE\r
+DevicePathToHiiHandle (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN EFI_GUID *FormsetGuid\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
+ UINTN Index;\r
+ EFI_HANDLE Handle;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_HANDLE *HiiHandles;\r
+ EFI_HII_HANDLE HiiHandle;\r
+\r
+ ASSERT (DevicePath != NULL);\r
+\r
+ TmpDevicePath = DevicePath;\r
+ //\r
+ // Locate Device Path Protocol handle buffer\r
+ //\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiDevicePathProtocolGuid,\r
+ &TmpDevicePath,\r
+ &DriverHandle\r
+ );\r
+ if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Retrieve all HII Handles from HII database\r
+ //\r
+ HiiHandles = HiiGetHiiHandles (NULL);\r
+ if (HiiHandles == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Search Hii Handle by Driver Handle\r
+ //\r
+ HiiHandle = NULL;\r
+ for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
+ Status = mHiiDatabase->GetPackageListHandle (\r
+ mHiiDatabase,\r
+ HiiHandles[Index],\r
+ &Handle\r
+ );\r
+ if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
+ if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], FormsetGuid)) {\r
+ HiiHandle = HiiHandles[Index];\r
+ break;\r
+ }\r
+\r
+ if (HiiHandle != NULL) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ FreePool (HiiHandles);\r
+ return HiiHandle;\r
+}\r
+\r
+/**\r
+ Find HII Handle in the HII database associated with given form set guid.\r
+\r
+ If FormSetGuid is NULL, then ASSERT.\r
+\r
+ @param ComparingGuid FormSet Guid associated with the HII package list\r
+ handle.\r
+\r
+ @retval Handle HII package list Handle associated with the Device\r
+ Path.\r
+ @retval NULL Hii Package list handle is not found.\r
+\r
+**/\r
+EFI_HII_HANDLE\r
+FormSetGuidToHiiHandle (\r
+ EFI_GUID *ComparingGuid\r
+ )\r
+{\r
+ EFI_HII_HANDLE *HiiHandles;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ UINTN Index;\r
+\r
+ ASSERT (ComparingGuid != NULL);\r
+\r
+ HiiHandle = NULL;\r
+ //\r
+ // Get all the Hii handles\r
+ //\r
+ HiiHandles = HiiGetHiiHandles (NULL);\r
+ ASSERT (HiiHandles != NULL);\r
+\r
+ //\r
+ // Search for formset of each class type\r
+ //\r
+ for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
+ if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], ComparingGuid)) {\r
+ HiiHandle = HiiHandles[Index];\r
+ break;\r
+ }\r
+\r
+ if (HiiHandle != NULL) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ FreePool (HiiHandles);\r
+\r
+ return HiiHandle;\r
+}\r
+\r
+/**\r
+ check how to process the changed data in current form or form set.\r
+\r
+ @param Selection On input, Selection tell setup browser the information\r
+ about the Selection, form and formset to be displayed.\r
+ On output, Selection return the screen item that is selected\r
+ by user.\r
+\r
+ @param Scope Data save or discard scope, form or formset.\r
+\r
+ @retval TRUE Success process the changed data, will return to the parent form.\r
+ @retval FALSE Reject to process the changed data, will stay at current form.\r
+**/\r
+BOOLEAN\r
+ProcessChangedData (\r
+ IN OUT UI_MENU_SELECTION *Selection,\r
+ IN BROWSER_SETTING_SCOPE Scope\r
+ )\r
+{\r
+ BOOLEAN RetValue;\r
+ EFI_STATUS Status;\r
+\r
+ RetValue = TRUE;\r
+ switch (mFormDisplay->ConfirmDataChange()) {\r
+ case BROWSER_ACTION_DISCARD:\r
+ DiscardForm (Selection->FormSet, Selection->Form, Scope);\r
+ break;\r
+ \r
+ case BROWSER_ACTION_SUBMIT:\r
+ Status = SubmitForm (Selection->FormSet, Selection->Form, Scope);\r
+ if (EFI_ERROR (Status)) {\r
+ RetValue = FALSE;\r
+ }\r
+ break;\r
+\r
+ case BROWSER_ACTION_NONE:\r
+ RetValue = FALSE;\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // if Invalid value return, process same as BROWSER_ACTION_NONE.\r
+ //\r
+ RetValue = FALSE;\r
+ break;\r
+ }\r
+\r
+ return RetValue;\r
+}\r
+\r
+/**\r
+ Find parent formset menu(the first menu which has different formset) for current menu.\r
+ If not find, just return to the first menu.\r
+\r
+ @param Selection The selection info.\r
+\r
+**/\r
+VOID\r
+FindParentFormSet (\r
+ IN OUT UI_MENU_SELECTION *Selection\r
+ )\r
+{\r
+ FORM_ENTRY_INFO *CurrentMenu;\r
+ FORM_ENTRY_INFO *ParentMenu;\r
+\r
+ CurrentMenu = Selection->CurrentMenu;\r
+ ParentMenu = UiFindParentMenu(CurrentMenu, FormSetLevel);\r
+\r
+ if (ParentMenu != NULL) {\r
+ CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
+ Selection->Handle = ParentMenu->HiiHandle;\r
+ Selection->FormId = ParentMenu->FormId;\r
+ Selection->QuestionId = ParentMenu->QuestionId;\r
+ } else {\r
+ Selection->FormId = CurrentMenu->FormId;\r
+ Selection->QuestionId = CurrentMenu->QuestionId;\r
+ }\r
+\r
+ Selection->Statement = NULL;\r
+}\r
+\r
+/**\r
+ Process the goto op code, update the info in the selection structure.\r
+\r
+ @param Statement The statement belong to goto op code.\r
+ @param Selection The selection info.\r
+\r
+ @retval EFI_SUCCESS The menu process successfully.\r
+ @return Other value if the process failed.\r
+**/\r
+EFI_STATUS\r
+ProcessGotoOpCode (\r
+ IN OUT FORM_BROWSER_STATEMENT *Statement,\r
+ IN OUT UI_MENU_SELECTION *Selection\r
+ )\r
+{\r
+ CHAR16 *StringPtr;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ FORM_BROWSER_FORM *RefForm;\r
+ EFI_STATUS Status;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ \r
+ Status = EFI_SUCCESS;\r
+ StringPtr = NULL;\r
+ HiiHandle = NULL;\r
+\r
+ //\r
+ // Prepare the device path check, get the device path info first.\r
+ //\r
+ if (Statement->HiiValue.Value.ref.DevicePath != 0) {\r
+ StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle);\r
+ }\r
+\r
+ //\r
+ // Check whether the device path string is a valid string.\r
+ //\r
+ if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL && StringPtr[0] != L'\0') {\r
+ if (Selection->Form->ModalForm) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Goto another Hii Package list\r
+ //\r
+ if (mPathFromText != NULL) {\r
+ DevicePath = mPathFromText->ConvertTextToDevicePath(StringPtr);\r
+ if (DevicePath != NULL) {\r
+ HiiHandle = DevicePathToHiiHandle (DevicePath, &Statement->HiiValue.Value.ref.FormSetGuid);\r
+ FreePool (DevicePath);\r
+ }\r
+ FreePool (StringPtr);\r
+ } else {\r
+ //\r
+ // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.\r
+ //\r
+ PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND, NULL, NULL, NULL);\r
+ FreePool (StringPtr);\r
+ return Status;\r
+ }\r