+EFI_EVENT mValueChangedEvent = NULL;\r
+LIST_ENTRY mRefreshEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEventList);\r
+UINT16 mCurFakeQestId;\r
+FORM_DISPLAY_ENGINE_FORM gDisplayFormData;\r
+BOOLEAN mFinishRetrieveCall = FALSE;\r
+\r
+/**\r
+ Evaluate all expressions in a Form.\r
+\r
+ @param FormSet FormSet this Form belongs to.\r
+ @param Form The Form.\r
+\r
+ @retval EFI_SUCCESS The expression evaluated successfuly\r
+\r
+**/\r
+EFI_STATUS\r
+EvaluateFormExpressions (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_EXPRESSION *Expression;\r
+\r
+ Link = GetFirstNode (&Form->ExpressionListHead);\r
+ while (!IsNull (&Form->ExpressionListHead, Link)) {\r
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->ExpressionListHead, Link);\r
+\r
+ if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||\r
+ Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF ||\r
+ Expression->Type == EFI_HII_EXPRESSION_WARNING_IF ||\r
+ Expression->Type == EFI_HII_EXPRESSION_WRITE ||\r
+ (Expression->Type == EFI_HII_EXPRESSION_READ && Form->FormType != STANDARD_MAP_FORM_TYPE)) {\r
+ //\r
+ // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.\r
+ //\r
+ continue;\r
+ }\r
+\r
+ Status = EvaluateExpression (FormSet, Form, Expression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Add empty function for event process function.\r
+\r
+ @param Event The Event need to be process\r
+ @param Context The context of the event.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SetupBrowserEmptyFunction (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+}\r
+\r
+/**\r
+ Base on the opcode buffer info to get the display statement.\r
+\r
+ @param OpCode The input opcode buffer for this statement.\r
+ \r
+ @retval Statement The statement use this opcode buffer.\r
+\r
+**/\r
+FORM_DISPLAY_ENGINE_STATEMENT *\r
+GetDisplayStatement (\r
+ IN EFI_IFR_OP_HEADER *OpCode\r
+ )\r
+{\r
+ FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement;\r
+ LIST_ENTRY *Link;\r
+\r
+ Link = GetFirstNode (&gDisplayFormData.StatementListHead);\r
+ while (!IsNull (&gDisplayFormData.StatementListHead, Link)) {\r
+ DisplayStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
+\r
+ if (DisplayStatement->OpCode == OpCode) {\r
+ return DisplayStatement;\r
+ }\r
+ Link = GetNextNode (&gDisplayFormData.StatementListHead, Link);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Free the refresh event list.\r
+\r
+**/\r
+VOID \r
+FreeRefreshEvent (\r
+ VOID\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;\r
+\r
+ while (!IsListEmpty (&mRefreshEventList)) {\r
+ Link = GetFirstNode (&mRefreshEventList);\r
+ EventNode = FORM_BROWSER_REFRESH_EVENT_FROM_LINK (Link);\r
+ RemoveEntryList (&EventNode->Link);\r
+\r
+ gBS->CloseEvent (EventNode->RefreshEvent);\r
+\r
+ FreePool (EventNode);\r
+ }\r
+}\r
+\r
+/**\r
+ Check whether this statement value is changed. If yes, update the statement value and return TRUE; \r
+ else return FALSE.\r
+\r
+ @param Statement The statement need to check.\r
+\r
+**/\r
+VOID\r
+UpdateStatement (\r
+ IN OUT FORM_BROWSER_STATEMENT *Statement\r
+ )\r
+{\r
+ GetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);\r
+\r
+ //\r
+ // Reset FormPackage update flag\r
+ //\r
+ mHiiPackageListUpdated = FALSE;\r
+\r
+ //\r
+ // Question value may be changed, need invoke its Callback()\r
+ //\r
+ ProcessCallBackFunction (gCurrentSelection, gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
+ \r
+ if (mHiiPackageListUpdated) {\r
+ //\r
+ // Package list is updated, force to reparse IFR binary of target Formset\r
+ //\r
+ mHiiPackageListUpdated = FALSE;\r
+ gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ }\r
+}\r
+\r
+/**\r
+ Refresh the question which has refresh guid event attribute.\r
+ \r
+ @param Event The event which has this function related. \r
+ @param Context The input context info related to this event or the status code return to the caller.\r
+**/\r
+VOID\r
+EFIAPI\r
+RefreshEventNotifyForStatement(\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+\r
+ Statement = (FORM_BROWSER_STATEMENT *)Context;\r
+ UpdateStatement(Statement);\r
+ gBS->SignalEvent (mValueChangedEvent);\r
+}\r
+\r
+/**\r
+ Refresh the questions within this form.\r
+ \r
+ @param Event The event which has this function related.\r
+ @param Context The input context info related to this event or the status code return to the caller.\r
+**/\r
+VOID\r
+EFIAPI\r
+RefreshEventNotifyForForm(\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
+\r
+ gBS->SignalEvent (mValueChangedEvent);\r
+}\r
+\r
+/**\r
+ Create refresh hook event for statement which has refresh event or interval.\r
+\r
+ @param Statement The statement need to check.\r
+\r
+**/\r
+VOID\r
+CreateRefreshEventForStatement (\r
+ IN FORM_BROWSER_STATEMENT *Statement\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_EVENT RefreshEvent;\r
+ FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;\r
+\r
+ //\r
+ // If question has refresh guid, create the notify function.\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ RefreshEventNotifyForStatement,\r
+ Statement,\r
+ &Statement->RefreshGuid,\r
+ &RefreshEvent);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));\r
+ ASSERT (EventNode != NULL);\r
+ EventNode->RefreshEvent = RefreshEvent;\r
+ InsertTailList(&mRefreshEventList, &EventNode->Link);\r
+}\r
+\r
+/**\r
+ Create refresh hook event for form which has refresh event or interval.\r
+\r
+ @param Form The form need to check.\r
+\r
+**/\r
+VOID\r
+CreateRefreshEventForForm (\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_EVENT RefreshEvent;\r
+ FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;\r
+\r
+ //\r
+ // If question has refresh guid, create the notify function.\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ RefreshEventNotifyForForm,\r
+ Form,\r
+ &Form->RefreshGuid,\r
+ &RefreshEvent);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));\r
+ ASSERT (EventNode != NULL);\r
+ EventNode->RefreshEvent = RefreshEvent;\r
+ InsertTailList(&mRefreshEventList, &EventNode->Link);\r
+}\r
+\r
+/**\r
+\r
+ Initialize the Display statement structure data.\r
+\r
+ @param DisplayStatement Pointer to the display Statement data strucure.\r
+ @param Statement The statement need to check.\r
+**/\r
+VOID\r
+InitializeDisplayStatement (\r
+ IN OUT FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement,\r
+ IN FORM_BROWSER_STATEMENT *Statement\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ QUESTION_OPTION *Option;\r
+ DISPLAY_QUESTION_OPTION *DisplayOption;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *ParentStatement;\r
+\r
+ DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE;\r
+ DisplayStatement->Version = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1;\r
+ DisplayStatement->OpCode = Statement->OpCode;\r
+ InitializeListHead (&DisplayStatement->NestStatementList);\r
+ InitializeListHead (&DisplayStatement->OptionListHead);\r
+\r
+ if ((EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) == ExpressGrayOut) || Statement->Locked) {\r
+ DisplayStatement->Attribute |= HII_DISPLAY_GRAYOUT;\r
+ }\r
+ if ((Statement->ValueExpression != NULL) || ((Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY) != 0)) {\r
+ DisplayStatement->Attribute |= HII_DISPLAY_READONLY;\r
+ }\r
+\r
+ //\r
+ // Initilize the option list in statement.\r
+ //\r
+ Link = GetFirstNode (&Statement->OptionListHead);\r
+ while (!IsNull (&Statement->OptionListHead, Link)) {\r
+ Option = QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Statement->OptionListHead, Link);\r
+ if ((Option->SuppressExpression != NULL) &&\r
+ ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {\r
+ continue;\r
+ }\r
+\r
+ DisplayOption = AllocateZeroPool (sizeof (DISPLAY_QUESTION_OPTION));\r
+ ASSERT (DisplayOption != NULL);\r
+\r
+ DisplayOption->ImageId = Option->ImageId;\r
+ DisplayOption->Signature = DISPLAY_QUESTION_OPTION_SIGNATURE;\r
+ DisplayOption->OptionOpCode = Option->OpCode;\r
+ InsertTailList(&DisplayStatement->OptionListHead, &DisplayOption->Link);\r
+ }\r
+\r
+ CopyMem (&DisplayStatement->CurrentValue, &Statement->HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+ //\r
+ // Some special op code need an extra buffer to save the data.\r
+ // Such as string, password, orderedlist...\r
+ //\r
+ if (Statement->BufferValue != NULL) {\r
+ //\r
+ // Ordered list opcode may not initilized, get default value here.\r
+ //\r
+ if (Statement->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP && GetArrayData (Statement->BufferValue, Statement->ValueType, 0) == 0) {\r
+ GetQuestionDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, 0);\r
+ }\r
+\r
+ DisplayStatement->CurrentValue.Buffer = AllocateCopyPool(Statement->StorageWidth,Statement->BufferValue);\r
+ DisplayStatement->CurrentValue.BufferLen = Statement->StorageWidth;\r
+ }\r
+\r
+ DisplayStatement->SettingChangedFlag = Statement->ValueChanged;\r
+\r
+ //\r
+ // Get the highlight statement for current form.\r
+ //\r
+ if (((gCurrentSelection->QuestionId != 0) && (Statement->QuestionId == gCurrentSelection->QuestionId)) ||\r
+ ((mCurFakeQestId != 0) && (Statement->FakeQuestionId == mCurFakeQestId))) {\r
+ gDisplayFormData.HighLightedStatement = DisplayStatement;\r
+ }\r
+\r
+ //\r
+ // Create the refresh event process function.\r
+ //\r
+ if (!IsZeroGuid (&Statement->RefreshGuid)) {\r
+ CreateRefreshEventForStatement (Statement);\r
+ }\r
+\r
+ //\r
+ // For RTC type of date/time, set default refresh interval to be 1 second.\r
+ //\r
+ if ((Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) && Statement->Storage == NULL) {\r
+ Statement->RefreshInterval = 1;\r
+ }\r
+\r
+ //\r
+ // Create the refresh guid hook event.\r
+ // If the statement in this form has refresh event or refresh interval, browser will create this event for display engine.\r
+ //\r
+ if ((!IsZeroGuid (&Statement->RefreshGuid)) || (Statement->RefreshInterval != 0)) {\r
+ gDisplayFormData.FormRefreshEvent = mValueChangedEvent;\r
+ }\r
+\r
+ //\r
+ // Save the password check function for later use.\r
+ //\r
+ if (Statement->Operand == EFI_IFR_PASSWORD_OP) {\r
+ DisplayStatement->PasswordCheck = PasswordCheck;\r
+ }\r
+\r
+ //\r
+ // If this statement is nest in the subtitle, insert to the host statement.\r
+ // else insert to the form it belongs to.\r
+ //\r
+ if (Statement->ParentStatement != NULL) {\r
+ ParentStatement = GetDisplayStatement(Statement->ParentStatement->OpCode);\r
+ ASSERT (ParentStatement != NULL);\r
+ InsertTailList(&ParentStatement->NestStatementList, &DisplayStatement->DisplayLink);\r
+ } else {\r
+ InsertTailList(&gDisplayFormData.StatementListHead, &DisplayStatement->DisplayLink);\r
+ }\r
+}\r
+\r
+/**\r
+ Process for the refresh interval statement.\r
+\r
+ @param Event The Event need to be process\r
+ @param Context The context of the event.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+RefreshIntervalProcess (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\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
+ Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);\r
+\r
+ if (Statement->RefreshInterval == 0) {\r
+ continue;\r
+ }\r
+\r
+ UpdateStatement(Statement);\r
+ }\r
+\r
+ gBS->SignalEvent (mValueChangedEvent);\r
+}\r
+\r
+/**\r
+\r
+ Make a copy of the global hotkey info.\r
+\r
+**/\r
+VOID\r
+UpdateHotkeyList (\r
+ VOID\r
+ )\r
+{\r
+ BROWSER_HOT_KEY *HotKey;\r
+ BROWSER_HOT_KEY *CopyKey;\r
+ LIST_ENTRY *Link;\r
+\r
+ Link = GetFirstNode (&gBrowserHotKeyList);\r
+ while (!IsNull (&gBrowserHotKeyList, Link)) {\r
+ HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
+\r
+ CopyKey = AllocateCopyPool(sizeof (BROWSER_HOT_KEY), HotKey);\r
+ ASSERT (CopyKey != NULL);\r
+ CopyKey->KeyData = AllocateCopyPool(sizeof (EFI_INPUT_KEY), HotKey->KeyData);\r
+ ASSERT (CopyKey->KeyData != NULL);\r
+ CopyKey->HelpString = AllocateCopyPool(StrSize (HotKey->HelpString), HotKey->HelpString);\r
+ ASSERT (CopyKey->HelpString != NULL);\r
+\r
+ InsertTailList(&gDisplayFormData.HotKeyListHead, &CopyKey->Link);\r
+\r
+ Link = GetNextNode (&gBrowserHotKeyList, Link);\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Get the extra question attribute from override question list.\r
+\r
+ @param QuestionId The question id for this request question.\r
+\r
+ @retval The attribute for this question or NULL if not found this \r
+ question in the list.\r
+\r
+**/\r
+UINT32 \r
+ProcessQuestionExtraAttr (\r
+ IN EFI_QUESTION_ID QuestionId\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ QUESTION_ATTRIBUTE_OVERRIDE *QuestionDesc;\r
+\r
+ //\r
+ // Return HII_DISPLAY_NONE if input a invalid question id.\r
+ //\r
+ if (QuestionId == 0) {\r
+ return HII_DISPLAY_NONE;\r
+ }\r
+\r
+ Link = GetFirstNode (&mPrivateData.FormBrowserEx2.OverrideQestListHead);\r
+ while (!IsNull (&mPrivateData.FormBrowserEx2.OverrideQestListHead, Link)) {\r
+ QuestionDesc = FORM_QUESTION_ATTRIBUTE_OVERRIDE_FROM_LINK (Link);\r
+ Link = GetNextNode (&mPrivateData.FormBrowserEx2.OverrideQestListHead, Link);\r
+\r
+ if ((QuestionDesc->QuestionId == QuestionId) &&\r
+ (QuestionDesc->FormId == gCurrentSelection->FormId) &&\r
+ (QuestionDesc->HiiHandle == gCurrentSelection->Handle) &&\r
+ CompareGuid (&QuestionDesc->FormSetGuid, &gCurrentSelection->FormSetGuid)) {\r
+ return QuestionDesc->Attribute;\r
+ }\r
+ }\r
+\r
+ return HII_DISPLAY_NONE;\r
+}\r
+\r
+/**\r
+\r
+ Enum all statement in current form, find all the statement can be display and\r
+ add to the display form.\r
+\r
+**/\r
+VOID\r
+AddStatementToDisplayForm (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement;\r
+ UINT8 MinRefreshInterval;\r
+ EFI_EVENT RefreshIntervalEvent;\r
+ FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;\r
+ BOOLEAN FormEditable;\r
+ UINT32 ExtraAttribute;\r
+\r
+ MinRefreshInterval = 0;\r
+ FormEditable = FALSE;\r
+\r
+ //\r
+ // Process the statement outside the form, these statements are not recognized\r
+ // by browser core.\r
+ //\r
+ Link = GetFirstNode (&gCurrentSelection->FormSet->StatementListOSF);\r
+ while (!IsNull (&gCurrentSelection->FormSet->StatementListOSF, Link)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&gCurrentSelection->FormSet->StatementListOSF, Link);\r
+\r
+ DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));\r
+ ASSERT (DisplayStatement != NULL);\r
+ DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE;\r
+ DisplayStatement->Version = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1;\r
+ DisplayStatement->OpCode = Statement->OpCode;\r
+\r
+ InitializeListHead (&DisplayStatement->NestStatementList);\r
+ InitializeListHead (&DisplayStatement->OptionListHead);\r
+\r
+ InsertTailList(&gDisplayFormData.StatementListOSF, &DisplayStatement->DisplayLink);\r
+ }\r
+\r
+ //\r
+ // treat formset as statement outside the form,get its opcode.\r
+ //\r
+ DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));\r
+ ASSERT (DisplayStatement != NULL);\r
+\r
+ DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE;\r
+ DisplayStatement->Version = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1;\r
+ DisplayStatement->OpCode = gCurrentSelection->FormSet->OpCode;\r
+\r
+ InitializeListHead (&DisplayStatement->NestStatementList);\r
+ InitializeListHead (&DisplayStatement->OptionListHead);\r
+\r
+ InsertTailList(&gDisplayFormData.StatementListOSF, &DisplayStatement->DisplayLink);\r
+\r
+ //\r
+ // Process the statement in this form.\r
+ //\r
+ Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead);\r
+ while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);\r
+\r
+ //\r
+ // This statement can't be show, skip it.\r
+ //\r
+ if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) > ExpressGrayOut) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Check the extra attribute.\r
+ //\r
+ ExtraAttribute = ProcessQuestionExtraAttr (Statement->QuestionId);\r
+ if ((ExtraAttribute & HII_DISPLAY_SUPPRESS) != 0) {\r
+ continue;\r
+ }\r
+\r
+ DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));\r
+ ASSERT (DisplayStatement != NULL);\r
+\r
+ //\r
+ // Initialize this statement and add it to the display form.\r
+ //\r
+ InitializeDisplayStatement(DisplayStatement, Statement);\r
+\r
+ //\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 (!IsZeroGuid (&gCurrentSelection->Form->RefreshGuid)) {\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