]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
index 2ba2165971308580387c3842b0013c5e3fa201db..ded1c7ad1159011d893e51eeeb61e9902e36ded2 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
 Utility functions for UI presentation.\r
 \r
-Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -19,870 +20,1681 @@ UI_MENU_SELECTION  *gCurrentSelection;
 EFI_HII_HANDLE     mCurrentHiiHandle = NULL;\r
 EFI_GUID           mCurrentFormSetGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
 UINT16             mCurrentFormId = 0;\r
+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
+  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
-  Clear retangle with specified text attribute.\r
 \r
-  @param  LeftColumn     Left column of retangle.\r
-  @param  RightColumn    Right column of retangle.\r
-  @param  TopRow         Start row of retangle.\r
-  @param  BottomRow      End row of retangle.\r
-  @param  TextAttribute  The character foreground and background.\r
+  Initialize the Display form structure data.\r
 \r
 **/\r
 VOID\r
-ClearLines (\r
-  IN UINTN               LeftColumn,\r
-  IN UINTN               RightColumn,\r
-  IN UINTN               TopRow,\r
-  IN UINTN               BottomRow,\r
-  IN UINTN               TextAttribute\r
+InitializeDisplayFormData (\r
+  VOID\r
   )\r
 {\r
-  CHAR16  *Buffer;\r
-  UINTN   Row;\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
+        EfiEventEmptyFunction,\r
+        NULL,\r
+        &mValueChangedEvent\r
+        );\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
 \r
-  //\r
-  // For now, allocate an arbitrarily long buffer\r
-  //\r
-  Buffer = AllocateZeroPool (0x10000);\r
-  ASSERT (Buffer != NULL);\r
+/**\r
 \r
-  //\r
-  // Set foreground and background as defined\r
-  //\r
-  gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);\r
+  Free the kotkey info saved in form data.\r
 \r
-  //\r
-  // Much faster to buffer the long string instead of print it a character at a time\r
-  //\r
-  SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');\r
+**/\r
+VOID\r
+FreeHotkeyList (\r
+  VOID\r
+  )\r
+{\r
+  BROWSER_HOT_KEY  *HotKey;\r
+  LIST_ENTRY       *Link;\r
 \r
-  //\r
-  // Clear the desired area with the appropriate foreground/background\r
-  //\r
-  for (Row = TopRow; Row <= BottomRow; Row++) {\r
-    PrintStringAt (LeftColumn, Row, Buffer);\r
-  }\r
+  while (!IsListEmpty (&gDisplayFormData.HotKeyListHead)) {\r
+    Link = GetFirstNode (&gDisplayFormData.HotKeyListHead);\r
+    HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
 \r
-  gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);\r
+    RemoveEntryList (&HotKey->Link);\r
 \r
-  FreePool (Buffer);\r
-  return ;\r
+    FreePool (HotKey->KeyData);\r
+    FreePool (HotKey->HelpString);\r
+    FreePool (HotKey);\r
+  }\r
 }\r
 \r
 /**\r
-  Concatenate a narrow string to another string.\r
 \r
-  @param Destination The destination string.\r
-  @param Source      The source string. The string to be concatenated.\r
-                     to the end of Destination.\r
+  Update the Display form structure data.\r
 \r
 **/\r
 VOID\r
-NewStrCat (\r
-  IN OUT CHAR16               *Destination,\r
-  IN     CHAR16               *Source\r
+UpdateDisplayFormData (\r
+  VOID\r
   )\r
 {\r
-  UINTN Length;\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
-  for (Length = 0; Destination[Length] != 0; Length++)\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
-  // We now have the length of the original string\r
-  // We can safely assume for now that we are concatenating a narrow value to this string.\r
-  // For instance, the string is "XYZ" and cat'ing ">"\r
-  // If this assumption changes, we need to make this routine a bit more complex\r
+  // Free Statements/Questions\r
   //\r
-  Destination[Length] = NARROW_CHAR;\r
-  Length++;\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
-  StrCpy (Destination + Length, Source);\r
+    RemoveEntryList (&Statement->DisplayLink);\r
+    FreePool (Statement);\r
+  }\r
 }\r
 \r
 /**\r
-  Count the storage space of a Unicode string.\r
 \r
-  This function handles the Unicode string with NARROW_CHAR\r
-  and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
-  does not count in the resultant output. If a WIDE_CHAR is\r
-  hit, then 2 Unicode character will consume an output storage\r
-  space with size of CHAR16 till a NARROW_CHAR is hit.\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
-  If String is NULL, then ASSERT ().\r
+  Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.\r
 \r
-  @param String          The input string to be counted.\r
+  @param DisplayStatement        The input FORM_DISPLAY_ENGINE_STATEMENT.\r
 \r
-  @return Storage space for the input string.\r
+  @retval FORM_BROWSER_STATEMENT  The return FORM_BROWSER_STATEMENT info.\r
 \r
 **/\r
-UINTN\r
-GetStringWidth (\r
-  IN CHAR16               *String\r
+FORM_BROWSER_STATEMENT *\r
+GetBrowserStatement (\r
+  IN FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement\r
   )\r
 {\r
-  UINTN Index;\r
-  UINTN Count;\r
-  UINTN IncrementValue;\r
+  FORM_BROWSER_STATEMENT *Statement;\r
+  LIST_ENTRY             *Link;\r
 \r
-  ASSERT (String != NULL);\r
-  if (String == NULL) {\r
-    return 0;\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
-  Index           = 0;\r
-  Count           = 0;\r
-  IncrementValue  = 1;\r
+  return NULL;\r
+}\r
 \r
-  do {\r
-    //\r
-    // Advance to the null-terminator or to the first width directive\r
-    //\r
-    for (;\r
-         (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);\r
-         Index++, Count = Count + IncrementValue\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
-    // We hit the null-terminator, we now have a count\r
-    //\r
-    if (String[Index] == 0) {\r
-      break;\r
-    }\r
-    //\r
-    // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed\r
-    // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)\r
+    // For password opcode, not set the the value changed flag.\r
     //\r
-    if (String[Index] == NARROW_CHAR) {\r
-      //\r
-      // Skip to the next character\r
-      //\r
-      Index++;\r
-      IncrementValue = 1;\r
-    } else {\r
-      //\r
-      // Skip to the next character\r
-      //\r
-      Index++;\r
-      IncrementValue = 2;\r
+    if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
+      continue;\r
     }\r
-  } while (String[Index] != 0);\r
 \r
-  //\r
-  // Increment by one to include the null-terminator in the size\r
-  //\r
-  Count++;\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
-  return Count * sizeof (CHAR16);\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
-  This function displays the page frame.\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
-  @param  Selection              Selection contains the information about \r
-                                 the Selection, form and formset to be displayed.\r
-                                 Selection action may be updated in retrieve callback.\r
 **/\r
 VOID\r
-DisplayPageFrame (\r
-  IN UI_MENU_SELECTION    *Selection\r
+UpdateStatementStatus (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN BROWSER_SETTING_SCOPE            SettingScope\r
   )\r
 {\r
-  UINTN                  Index;\r
-  UINT8                  Line;\r
-  UINT8                  Alignment;\r
-  CHAR16                 Character;\r
-  CHAR16                 *Buffer;\r
-  CHAR16                 *StrFrontPageBanner;\r
-  UINTN                  Row;\r
-  EFI_SCREEN_DESCRIPTOR  LocalScreen;\r
-  UINT8                  RowIdx;\r
-  UINT8                  ColumnIdx;\r
-\r
-  ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));\r
-  gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);\r
-  ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);\r
-\r
-  if (Selection->Form->ModalForm) {\r
-    return;\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
-  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\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
-  // For now, allocate an arbitrarily long buffer\r
+  // Below is normal hotkey trigged action, these action maybe combine with each other.\r
   //\r
-  Buffer = AllocateZeroPool (0x10000);\r
-  ASSERT (Buffer != NULL);\r
+  if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
+    DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+  }\r
 \r
-  Character = BOXDRAW_HORIZONTAL;\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
-  for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {\r
-    Buffer[Index] = Character;\r
+  if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {\r
+    SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
   }\r
 \r
-  if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
-    //\r
-    //    ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);\r
-    //\r
-    ClearLines (\r
-      LocalScreen.LeftColumn,\r
-      LocalScreen.RightColumn,\r
-      LocalScreen.TopRow,\r
-      FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,\r
-      BANNER_TEXT | BANNER_BACKGROUND\r
-      );\r
+  if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
+    gResetRequiredFormLevel = TRUE;\r
+    gResetRequiredSystemLevel = TRUE;\r
+  }\r
+\r
+  if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {\r
     //\r
-    //    for (Line = 0; Line < BANNER_HEIGHT; Line++) {\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
-    for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {\r
-      //\r
-      //      for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {\r
-      //\r
-      for (Alignment = (UINT8) LocalScreen.LeftColumn;\r
-           Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;\r
-           Alignment++\r
-          ) {\r
-        RowIdx = (UINT8) (Line - (UINT8) LocalScreen.TopRow);\r
-        ColumnIdx = (UINT8) (Alignment - (UINT8) LocalScreen.LeftColumn);\r
-\r
-        ASSERT (RowIdx < BANNER_HEIGHT);\r
-        ASSERT (ColumnIdx < BANNER_COLUMNS);\r
-\r
-        if (gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {\r
-          StrFrontPageBanner = GetToken (\r
-                                gBannerData->Banner[RowIdx][ColumnIdx],\r
-                                gFrontPageHandle\r
-                                );\r
-        } else {\r
-          continue;\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
-        switch (Alignment - LocalScreen.LeftColumn) {\r
-        case 0:\r
-          //\r
-          // Handle left column\r
-          //\r
-          PrintStringAt (LocalScreen.LeftColumn + BANNER_LEFT_COLUMN_INDENT, Line, StrFrontPageBanner);\r
-          break;\r
+  return EFI_SUCCESS;\r
+}\r
 \r
-        case 1:\r
-          //\r
-          // Handle center column\r
-          //\r
-          PrintStringAt (\r
-            LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,\r
-            Line,\r
-            StrFrontPageBanner\r
-            );\r
-          break;\r
+/**\r
+  Check whether the formset guid is in this Hii package list.\r
 \r
-        case 2:\r
-          //\r
-          // Handle right column\r
-          //\r
-          PrintStringAt (\r
-            LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,\r
-            Line,\r
-            StrFrontPageBanner\r
-            );\r
-          break;\r
-        }\r
+  @param  HiiHandle              The HiiHandle for this HII package list.\r
+  @param  FormSetGuid            The formset guid for the request formset.\r
 \r
-        FreePool (StrFrontPageBanner);\r
-      }\r
-    }\r
-  }\r
+  @retval TRUE                   Find the formset guid.\r
+  @retval FALSE                  Not found the formset guid.\r
 \r
-  ClearLines (\r
-    LocalScreen.LeftColumn,\r
-    LocalScreen.RightColumn,\r
-    LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight,\r
-    LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,\r
-    KEYHELP_TEXT | KEYHELP_BACKGROUND\r
-    );\r
-\r
-  if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {\r
-    ClearLines (\r
-      LocalScreen.LeftColumn,\r
-      LocalScreen.RightColumn,\r
-      LocalScreen.TopRow,\r
-      LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,\r
-      TITLE_TEXT | TITLE_BACKGROUND\r
-      );\r
-    //\r
-    // Print Top border line\r
-    // +------------------------------------------------------------------------------+\r
-    // ?                                                                             ?\r
-    // +------------------------------------------------------------------------------+\r
-    //\r
-    Character = BOXDRAW_DOWN_RIGHT;\r
-\r
-    PrintChar (Character);\r
-    PrintString (Buffer);\r
-\r
-    Character = BOXDRAW_DOWN_LEFT;\r
-    PrintChar (Character);\r
-\r
-    Character = BOXDRAW_VERTICAL;\r
-    for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {\r
-      PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
-      PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\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
-    Character = BOXDRAW_UP_RIGHT;\r
-    PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);\r
-    PrintString (Buffer);\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
-    Character = BOXDRAW_UP_LEFT;\r
-    PrintChar (Character);\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 ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
+    if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
       //\r
-      // Print Bottom border line\r
-      // +------------------------------------------------------------------------------+\r
-      // ?                                                                             ?\r
-      // +------------------------------------------------------------------------------+\r
+      // Search FormSet in this Form Package\r
       //\r
-      Character = BOXDRAW_DOWN_RIGHT;\r
-      PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, Character);\r
-\r
-      PrintString (Buffer);\r
-\r
-      Character = BOXDRAW_DOWN_LEFT;\r
-      PrintChar (Character);\r
-      Character = BOXDRAW_VERTICAL;\r
-      for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;\r
-           Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;\r
-           Row++\r
-          ) {\r
-        PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
-        PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
-      }\r
-\r
-      Character = BOXDRAW_UP_RIGHT;\r
-      PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);\r
-\r
-      PrintString (Buffer);\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
-      Character = BOXDRAW_UP_LEFT;\r
-      PrintChar (Character);\r
+        Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+      }\r
+    }\r
+    if (FindGuid) {\r
+      break;\r
     }\r
   }\r
 \r
-  FreePool (Buffer);\r
+  FreePool (HiiPackageList);\r
 \r
+  return FindGuid;\r
 }\r
 \r
-\r
 /**\r
-  Evaluate all expressions in a Form.\r
+  Find HII Handle in the HII database associated with given Device Path.\r
 \r
-  @param  FormSet        FormSet this Form belongs to.\r
-  @param  Form           The Form.\r
+  If DevicePath is NULL, then ASSERT.\r
 \r
-  @retval EFI_SUCCESS    The expression evaluated successfuly\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_STATUS\r
-EvaluateFormExpressions (\r
-  IN FORM_BROWSER_FORMSET  *FormSet,\r
-  IN FORM_BROWSER_FORM     *Form\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
-  LIST_ENTRY       *Link;\r
-  FORM_EXPRESSION  *Expression;\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
-  Link = GetFirstNode (&Form->ExpressionListHead);\r
-  while (!IsNull (&Form->ExpressionListHead, Link)) {\r
-    Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
-    Link = GetNextNode (&Form->ExpressionListHead, Link);\r
+  ASSERT (DevicePath != NULL);\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_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
+  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
-    Status = EvaluateExpression (FormSet, Form, Expression);\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\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
-  return EFI_SUCCESS;\r
+  FreePool (HiiHandles);\r
+  return HiiHandle;\r
 }\r
 \r
-/*\r
-+------------------------------------------------------------------------------+\r
-?                                 Setup Page                                  ?\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
-+------------------------------------------------------------------------------+\r
-?F1=Scroll Help                 F9=Reset to Defaults        F10=Save and Exit ?\r
-| ^"=Move Highlight          <Spacebar> Toggles Checkbox   Esc=Discard Changes |\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
-  Display form and wait for user to select one menu option, then return it.\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
-  @retval EFI_SUCESSS            This function always return successfully for now.\r
-\r
+  @retval EFI_SUCCESS    The menu process successfully.\r
+  @return Other value if the process failed.\r
 **/\r
 EFI_STATUS\r
-DisplayForm (\r
-  IN OUT UI_MENU_SELECTION           *Selection\r
+ProcessGotoOpCode (\r
+  IN OUT   FORM_BROWSER_STATEMENT      *Statement,\r
+  IN OUT   UI_MENU_SELECTION           *Selection\r
   )\r
 {\r
-  CHAR16                 *StringPtr;\r
-  UINT16                 MenuItemCount;\r
-  EFI_HII_HANDLE         Handle;\r
-  BOOLEAN                Suppress;\r
-  EFI_SCREEN_DESCRIPTOR  LocalScreen;\r
-  UINT16                 Width;\r
-  UINTN                  ArrayEntry;\r
-  CHAR16                 *OutputString;\r
-  LIST_ENTRY             *Link;\r
-  FORM_BROWSER_STATEMENT *Statement;\r
-  UINT16                 NumberOfLines;\r
-  EFI_STATUS             Status;\r
-  UI_MENU_OPTION         *MenuOption;\r
-\r
-  Handle        = Selection->Handle;\r
-  MenuItemCount = 0;\r
-  ArrayEntry    = 0;\r
-  OutputString  = NULL;\r
-\r
-  UiInitMenu ();\r
-\r
-  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
-\r
-  StringPtr = GetToken (Selection->Form->FormTitle, Handle);\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
-  if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {\r
-    if (Selection->Form->ModalForm) {\r
-      gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | EFI_BACKGROUND_BLACK);\r
-    } else {\r
-      gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);\r
-    }\r
-    PrintStringAt (\r
-      (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,\r
-      LocalScreen.TopRow + 1,\r
-      StringPtr\r
-      );\r
-  }\r
+  Status    = EFI_SUCCESS;\r
+  StringPtr = NULL;\r
+  HiiHandle = NULL;\r
 \r
   //\r
-  // Remove Buffer allocated for StringPtr after it has been used.\r
+  // Prepare the device path check, get the device path info first.\r
   //\r
-  FreePool (StringPtr);\r
+  if (Statement->HiiValue.Value.ref.DevicePath != 0) {\r
+    StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle);\r
+  }\r
 \r
   //\r
-  // Evaluate all the Expressions in this Form\r
+  // Check whether the device path string is a valid string.\r
   //\r
-  Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Selection->FormEditable = FALSE;\r
-  Link = GetFirstNode (&Selection->Form->StatementListHead);\r
-  while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
-    Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\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
-    if (Statement->SuppressExpression != NULL) {\r
-      Suppress = Statement->SuppressExpression->Result.Value.b;\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
-      Suppress = FALSE;\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
 \r
-    if (Statement->DisableExpression != NULL) {\r
-      Suppress = (BOOLEAN) (Suppress || Statement->DisableExpression->Result.Value.b);\r
+    if (HiiHandle != Selection->Handle) {\r
+      //\r
+      // Goto another Formset, check for uncommitted data\r
+      //\r
+      if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&\r
+          IsNvUpdateRequiredForFormSet(Selection->FormSet)) {\r
+        if (!ProcessChangedData(Selection, FormSetLevel)) {\r
+          return EFI_SUCCESS;\r
+        }\r
+      }\r
     }\r
 \r
-    if (!Suppress) {\r
-      StringPtr = GetToken (Statement->Prompt, Handle);\r
-      ASSERT (StringPtr != NULL);\r
-\r
-      Width     = GetWidth (Statement, Handle);\r
+    Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+    Selection->Handle = HiiHandle;\r
+    if (Selection->Handle == NULL) {\r
+      //\r
+      // If target Hii Handle not found, exit current formset.\r
+      //\r
+      FindParentFormSet(Selection);\r
+      return EFI_SUCCESS;\r
+    }\r
 \r
-      NumberOfLines = 1;\r
-      ArrayEntry = 0;\r
-      for (; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {\r
-        //\r
-        // If there is more string to process print on the next row and increment the Skip value\r
-        //\r
-        if (StrLen (&StringPtr[ArrayEntry]) != 0) {\r
-          NumberOfLines++;\r
+    CopyMem (&Selection->FormSetGuid,&Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
+    Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
+    Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
+  } else if (!IsZeroGuid (&Statement->HiiValue.Value.ref.FormSetGuid)) {\r
+    if (Selection->Form->ModalForm) {\r
+      return Status;\r
+    }\r
+    if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &Selection->FormSetGuid)) {\r
+      //\r
+      // Goto another Formset, check for uncommitted data\r
+      //\r
+      if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&\r
+         IsNvUpdateRequiredForFormSet(Selection->FormSet)) {\r
+        if (!ProcessChangedData(Selection, FormSetLevel)) {\r
+          return EFI_SUCCESS;\r
         }\r
-\r
-        FreePool (OutputString);\r
       }\r
+    }\r
 \r
+    Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+    Selection->Handle = FormSetGuidToHiiHandle(&Statement->HiiValue.Value.ref.FormSetGuid);\r
+    if (Selection->Handle == NULL) {\r
       //\r
-      // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do\r
-      // it in UiFreeMenu.\r
+      // If target Hii Handle not found, exit current formset.\r
       //\r
-      MenuOption = UiAddMenuOption (StringPtr, Selection->Handle, Selection->Form, Statement, NumberOfLines, MenuItemCount);\r
-      MenuItemCount++;\r
+      FindParentFormSet(Selection);\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    CopyMem (&Selection->FormSetGuid, &Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
+    Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
+    Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
+  } else if (Statement->HiiValue.Value.ref.FormId != 0) {\r
+    //\r
+    // Goto another Form, check for uncommitted data\r
+    //\r
+    if (Statement->HiiValue.Value.ref.FormId != Selection->FormId) {\r
+      if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm(Selection->Form))) {\r
+        if (!ProcessChangedData (Selection, FormLevel)) {\r
+          return EFI_SUCCESS;\r
+        }\r
+      }\r
+    }\r
 \r
-      if (MenuOption->IsQuestion && !MenuOption->ReadOnly) {\r
+    RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId);\r
+    if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) {\r
+      if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) {\r
         //\r
-        // At least one item is not readonly, this Form is considered as editable\r
+        // Form is suppressed.\r
         //\r
-        Selection->FormEditable = TRUE;\r
+        PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL);\r
+        return EFI_SUCCESS;\r
       }\r
     }\r
 \r
-    Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
+    Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
+    Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
+  } else if (Statement->HiiValue.Value.ref.QuestionId != 0) {\r
+    Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
   }\r
 \r
-  Status = UiDisplayMenu (Selection);\r
-\r
-  UiFreeMenu ();\r
-\r
   return Status;\r
 }\r
 \r
+\r
 /**\r
-  Initialize the HII String Token to the correct values.\r
+  Process Question Config.\r
 \r
-**/\r
-VOID\r
-InitializeBrowserStrings (\r
-  VOID\r
-  )\r
-{\r
-  gEnterString          = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);\r
-  gEnterCommitString    = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);\r
-  gEnterEscapeString    = GetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), gHiiHandle);\r
-  gEscapeString         = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);\r
-  gMoveHighlight        = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);\r
-  gMakeSelection        = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);\r
-  gDecNumericInput      = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);\r
-  gHexNumericInput      = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle);\r
-  gToggleCheckBox       = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);\r
-  gPromptForData        = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);\r
-  gPromptForPassword    = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);\r
-  gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);\r
-  gConfirmPassword      = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);\r
-  gConfirmError         = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);\r
-  gPassowordInvalid     = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);\r
-  gPressEnter           = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);\r
-  gEmptyString          = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
-  gAreYouSure           = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);\r
-  gYesResponse          = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);\r
-  gNoResponse           = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);\r
-  gMiniString           = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);\r
-  gPlusString           = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);\r
-  gMinusString          = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);\r
-  gAdjustNumber         = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);\r
-  gSaveChanges          = GetToken (STRING_TOKEN (SAVE_CHANGES), gHiiHandle);\r
-  gOptionMismatch       = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);\r
-  gFormSuppress         = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle);\r
-  return ;\r
-}\r
+  @param  Selection              The UI menu selection.\r
+  @param  Question               The Question to be peocessed.\r
 \r
-/**\r
-  Free up the resource allocated for all strings required\r
-  by Setup Browser.\r
+  @retval EFI_SUCCESS            Question Config process success.\r
+  @retval Other                  Question Config process fail.\r
 \r
 **/\r
-VOID\r
-FreeBrowserStrings (\r
-  VOID\r
+EFI_STATUS\r
+ProcessQuestionConfig (\r
+  IN  UI_MENU_SELECTION       *Selection,\r
+  IN  FORM_BROWSER_STATEMENT  *Question\r
   )\r
 {\r
-  FreePool (gEnterString);\r
-  FreePool (gEnterCommitString);\r
-  FreePool (gEnterEscapeString);\r
-  FreePool (gEscapeString);\r
-  FreePool (gMoveHighlight);\r
-  FreePool (gMakeSelection);\r
-  FreePool (gDecNumericInput);\r
-  FreePool (gHexNumericInput);\r
-  FreePool (gToggleCheckBox);\r
-  FreePool (gPromptForData);\r
-  FreePool (gPromptForPassword);\r
-  FreePool (gPromptForNewPassword);\r
-  FreePool (gConfirmPassword);\r
-  FreePool (gPassowordInvalid);\r
-  FreePool (gConfirmError);\r
-  FreePool (gPressEnter);\r
-  FreePool (gEmptyString);\r
-  FreePool (gAreYouSure);\r
-  FreePool (gYesResponse);\r
-  FreePool (gNoResponse);\r
-  FreePool (gMiniString);\r
-  FreePool (gPlusString);\r
-  FreePool (gMinusString);\r
-  FreePool (gAdjustNumber);\r
-  FreePool (gSaveChanges);\r
-  FreePool (gOptionMismatch);\r
-  FreePool (gFormSuppress);\r
-  return ;\r
+  EFI_STATUS                      Status;\r
+  CHAR16                          *ConfigResp;\r
+  CHAR16                          *Progress;\r
+\r
+  if (Question->QuestionConfig == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Get <ConfigResp>\r
+  //\r
+  ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle);\r
+  if (ConfigResp == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  } else if (ConfigResp[0] == L'\0') {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Send config to Configuration Driver\r
+  //\r
+  Status = mHiiConfigRouting->RouteConfig (\r
+                           mHiiConfigRouting,\r
+                           ConfigResp,\r
+                           &Progress\r
+                           );\r
+\r
+  return Status;\r
 }\r
 \r
 /**\r
-  Show all registered HotKey help strings on bottom Rows.\r
+\r
+  Process the user input data.\r
+\r
+  @param UserInput               The user input data.\r
+\r
+  @retval EFI_SUCESSS            This function always return successfully for now.\r
 \r
 **/\r
-VOID\r
-PrintHotKeyHelpString (\r
-  VOID\r
+EFI_STATUS\r
+ProcessUserInput (\r
+  IN USER_INPUT               *UserInput\r
   )\r
 {\r
-  UINTN                  CurrentCol;\r
-  UINTN                  CurrentRow;\r
-  UINTN                  BottomRowOfHotKeyHelp;\r
-  UINTN                  ColumnWidth;\r
-  UINTN                  Index;\r
-  EFI_SCREEN_DESCRIPTOR  LocalScreen;\r
-  LIST_ENTRY             *Link;\r
-  BROWSER_HOT_KEY        *HotKey;\r
+  EFI_STATUS                    Status;\r
+  FORM_BROWSER_STATEMENT        *Statement;\r
 \r
-  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
-  ColumnWidth            = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
-  BottomRowOfHotKeyHelp  = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3;\r
+  Status    = EFI_SUCCESS;\r
+  Statement = NULL;\r
 \r
   //\r
-  // Calculate total number of Register HotKeys. \r
+  // When Exit from FormDisplay function, one of the below two cases must be true.\r
   //\r
-  Index = 0;\r
-  Link  = GetFirstNode (&gBrowserHotKeyList);\r
-  while (!IsNull (&gBrowserHotKeyList, Link)) {\r
-    HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
+  ASSERT (UserInput->Action != 0 || UserInput->SelectedStatement != NULL);\r
+\r
+  //\r
+  // Remove the last highligh question id, this id will update when show next form.\r
+  //\r
+  gCurrentSelection->QuestionId = 0;\r
+  if (UserInput->SelectedStatement != NULL){\r
+    Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
+    ASSERT (Statement != NULL);\r
+\r
     //\r
-    // Help string can't exceed ColumnWidth. One Row will show three Help information. \r
+    // This question is the current user select one,record it and later\r
+    // show it as the highlight question.\r
     //\r
-    if (StrLen (HotKey->HelpString) > ColumnWidth) {\r
-      HotKey->HelpString[ColumnWidth] = L'\0';\r
-    }\r
+    gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
     //\r
-    // Calculate help information Column and Row.\r
+    // For statement like text, actio, it not has question id.\r
+    // So use FakeQuestionId to save the question.\r
     //\r
-    if ((Index % 3) != 2) {\r
-      CurrentCol = LocalScreen.LeftColumn + (2 - Index % 3) * ColumnWidth;\r
+    if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
+      mCurFakeQestId = Statement->FakeQuestionId;\r
     } else {\r
-      CurrentCol = LocalScreen.LeftColumn + 2;\r
+      mCurFakeQestId = 0;\r
     }\r
-    CurrentRow = BottomRowOfHotKeyHelp - Index / 3;\r
-    //\r
-    // Print HotKey help string on bottom Row.\r
-    //\r
-    PrintStringAt (CurrentCol, CurrentRow, HotKey->HelpString);\r
-\r
-    //\r
-    // Get Next Hot Key.\r
-    //\r
-    Link = GetNextNode (&gBrowserHotKeyList, Link);\r
-    Index ++;\r
   }\r
-  \r
-  return;\r
-}\r
-\r
-/**\r
-  Update key's help imformation.\r
-\r
-  @param Selection       Tell setup browser the information about the Selection\r
-  @param  MenuOption     The Menu option\r
-  @param  Selected       Whether or not a tag be selected\r
 \r
-**/\r
-VOID\r
-UpdateKeyHelp (\r
-  IN  UI_MENU_SELECTION           *Selection,\r
-  IN  UI_MENU_OPTION              *MenuOption,\r
-  IN  BOOLEAN                     Selected\r
-  )\r
-{\r
-  UINTN                  SecCol;\r
-  UINTN                  ThdCol;\r
-  UINTN                  LeftColumnOfHelp;\r
-  UINTN                  RightColumnOfHelp;\r
-  UINTN                  TopRowOfHelp;\r
-  UINTN                  BottomRowOfHelp;\r
-  UINTN                  StartColumnOfHelp;\r
-  EFI_SCREEN_DESCRIPTOR  LocalScreen;\r
-  FORM_BROWSER_STATEMENT *Statement;\r
+  //\r
+  // First process the Action field in USER_INPUT.\r
+  //\r
+  if (UserInput->Action != 0) {\r
+    Status = ProcessAction (UserInput->Action, UserInput->DefaultId);\r
+    gCurrentSelection->Statement = NULL;\r
+  } else {\r
+    ASSERT (Statement != NULL);\r
+    gCurrentSelection->Statement = Statement;\r
+    switch (Statement->Operand) {\r
+    case EFI_IFR_REF_OP:\r
+      Status = ProcessGotoOpCode(Statement, gCurrentSelection);\r
+      break;\r
 \r
-  gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+    case EFI_IFR_ACTION_OP:\r
+      //\r
+      // Process the Config string <ConfigResp>\r
+      //\r
+      Status = ProcessQuestionConfig (gCurrentSelection, Statement);\r
+      break;\r
 \r
-  if (Selection->Form->ModalForm) {\r
-    return;\r
-  }\r
+    case EFI_IFR_RESET_BUTTON_OP:\r
+      //\r
+      // Reset Question to default value specified by DefaultId\r
+      //\r
+      Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE, FALSE);\r
+      UpdateStatementStatus (gCurrentSelection->FormSet, NULL, FormSetLevel);\r
+      break;\r
 \r
-  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+    default:\r
+      switch (Statement->Operand) {\r
+      case EFI_IFR_STRING_OP:\r
+        DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
+        Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
+        CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
+        FreePool (UserInput->InputValue.Buffer);\r
+        break;\r
 \r
-  SecCol            = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
-  ThdCol            = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3 * 2;\r
+      case EFI_IFR_PASSWORD_OP:\r
+        if (UserInput->InputValue.Buffer == NULL) {\r
+          //\r
+          // User not input new password, just return.\r
+          //\r
+          break;\r
+        }\r
 \r
-  StartColumnOfHelp = LocalScreen.LeftColumn + 2;\r
-  LeftColumnOfHelp  = LocalScreen.LeftColumn + 1;\r
-  RightColumnOfHelp = LocalScreen.RightColumn - 2;\r
-  TopRowOfHelp      = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;\r
-  BottomRowOfHelp   = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;\r
+        DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
+        Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
+        CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
+        ZeroMem (UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
+        FreePool (UserInput->InputValue.Buffer);\r
+        //\r
+        // Two password match, send it to Configuration Driver\r
+        //\r
+        if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+          PasswordCheck (NULL, UserInput->SelectedStatement, (CHAR16 *) Statement->BufferValue);\r
+          //\r
+          // Clean the value after saved it.\r
+          //\r
+          ZeroMem (Statement->BufferValue, (UINTN) UserInput->InputValue.BufferLen);\r
+          HiiSetString (gCurrentSelection->FormSet->HiiHandle, Statement->HiiValue.Value.string, (CHAR16*)Statement->BufferValue, NULL);\r
+        } else {\r
+          SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);\r
+        }\r
+        break;\r
 \r
-  Statement = MenuOption->ThisTag;\r
-  switch (Statement->Operand) {\r
-  case EFI_IFR_ORDERED_LIST_OP:\r
-  case EFI_IFR_ONE_OF_OP:\r
-  case EFI_IFR_NUMERIC_OP:\r
-  case EFI_IFR_TIME_OP:\r
-  case EFI_IFR_DATE_OP:\r
-    ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+      case EFI_IFR_ORDERED_LIST_OP:\r
+        CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, UserInput->InputValue.BufferLen);\r
+        break;\r
 \r
-    if (!Selected) {\r
-      //\r
-      // On system setting, HotKey will show on every form.\r
-      //\r
-      if (gBrowserSettingScope == SystemLevel ||\r
-          (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
-        PrintHotKeyHelpString ();\r
+      default:\r
+        CopyMem (&Statement->HiiValue, &UserInput->InputValue, sizeof (EFI_HII_VALUE));\r
+        break;\r
       }\r
+      break;\r
+    }\r
+  }\r
 \r
-      if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
-        PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
-      }\r
+  return Status;\r
+}\r
 \r
-      if ((Statement->Operand == EFI_IFR_DATE_OP) ||\r
-          (Statement->Operand == EFI_IFR_TIME_OP)) {\r
-        PrintAt (\r
-          StartColumnOfHelp,\r
-          BottomRowOfHelp,\r
-          L"%c%c%c%c%s",\r
-          ARROW_UP,\r
-          ARROW_DOWN,\r
-          ARROW_RIGHT,\r
-          ARROW_LEFT,\r
-          gMoveHighlight\r
-          );\r
-        PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
-        PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber);\r
-      } else {\r
-        PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
-        if (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0) {\r
-          PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber);\r
-        } \r
-        PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
-      }\r
-    } else {\r
-      PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);\r
+/**\r
 \r
-      //\r
-      // If it is a selected numeric with manual input, display different message\r
-      //\r
-      if ((Statement->Operand == EFI_IFR_NUMERIC_OP) || \r
-          (Statement->Operand == EFI_IFR_DATE_OP) ||\r
-          (Statement->Operand == EFI_IFR_TIME_OP)) {\r
-        PrintStringAt (\r
-          SecCol,\r
-          TopRowOfHelp,\r
-          ((Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput\r
-          );\r
-      } else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) {\r
-        PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
-      }\r
+  Display form and wait for user to select one menu option, then return it.\r
 \r
-      if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
-        PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);\r
-        PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);\r
-      }\r
+  @retval EFI_SUCESSS            This function always return successfully for now.\r
 \r
-      PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
-    }\r
-    break;\r
+**/\r
+EFI_STATUS\r
+DisplayForm (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS               Status;\r
+  USER_INPUT               UserInput;\r
+  FORM_ENTRY_INFO          *CurrentMenu;\r
 \r
-  case EFI_IFR_CHECKBOX_OP:\r
-    ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+  ZeroMem (&UserInput, sizeof (USER_INPUT));\r
 \r
+  //\r
+  // Update the menu history data.\r
+  //\r
+  CurrentMenu = UiFindMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid, gCurrentSelection->FormId);\r
+  if (CurrentMenu == NULL) {\r
     //\r
-    // On system setting, HotKey will show on every form.\r
+    // Current menu not found, add it to the menu tree\r
     //\r
-    if (gBrowserSettingScope == SystemLevel ||\r
-        (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
-      PrintHotKeyHelpString ();\r
-    }\r
-    if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
-      PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
-    }\r
+    CurrentMenu = UiAddMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid,\r
+                                 gCurrentSelection->FormId, gCurrentSelection->QuestionId);\r
+    ASSERT (CurrentMenu != NULL);\r
+  }\r
 \r
-    PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
-    PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);\r
-    break;\r
+  //\r
+  // Back up the form view history data for this form.\r
+  //\r
+  UiCopyMenuList(&gCurrentSelection->Form->FormViewListHead, &mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
 \r
-  case EFI_IFR_REF_OP:\r
-  case EFI_IFR_PASSWORD_OP:\r
-  case EFI_IFR_STRING_OP:\r
-  case EFI_IFR_TEXT_OP:\r
-  case EFI_IFR_ACTION_OP:\r
-  case EFI_IFR_RESET_BUTTON_OP:\r
-  case EFI_IFR_SUBTITLE_OP:\r
-    ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+  gCurrentSelection->CurrentMenu = CurrentMenu;\r
 \r
-    if (!Selected) {\r
-      //\r
-      // On system setting, HotKey will show on every form.\r
-      //\r
-      if (gBrowserSettingScope == SystemLevel ||\r
-          (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
-        PrintHotKeyHelpString ();\r
-      }\r
-      if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
-        PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
-      }\r
+  if (gCurrentSelection->QuestionId == 0) {\r
+    //\r
+    // Highlight not specified, fetch it from cached menu\r
+    //\r
+    gCurrentSelection->QuestionId = CurrentMenu->QuestionId;\r
+  }\r
 \r
-      PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
-      if (Statement->Operand != EFI_IFR_TEXT_OP && Statement->Operand != EFI_IFR_SUBTITLE_OP) {\r
-        PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
-      }\r
-    } else {\r
-      if (Statement->Operand != EFI_IFR_REF_OP) {\r
-        PrintStringAt (\r
-          (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,\r
-          BottomRowOfHelp,\r
-          gEnterCommitString\r
-          );\r
-        PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
-      }\r
-    }\r
-    break;\r
+  Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
-  default:\r
-    break;\r
+  UpdateDisplayFormData ();\r
+\r
+  ASSERT (gDisplayFormData.BrowserStatus == BROWSER_SUCCESS);\r
+  Status = mFormDisplay->FormDisplay (&gDisplayFormData, &UserInput);\r
+  if (EFI_ERROR (Status)) {\r
+    FreeDisplayFormData();\r
+    return Status;\r
   }\r
+\r
+  Status = ProcessUserInput (&UserInput);\r
+  FreeDisplayFormData();\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -927,60 +1739,72 @@ FormUpdateNotify (
 }\r
 \r
 /**\r
-  check whether the formset need to update the NV.\r
+  Update the NV flag info for this form set.\r
 \r
   @param  FormSet                FormSet data structure.\r
 \r
-  @retval TRUE                   Need to update the NV.\r
-  @retval FALSE                  No need to update the NV.\r
 **/\r
-BOOLEAN \r
-IsNvUpdateRequired (\r
+BOOLEAN\r
+IsNvUpdateRequiredForFormSet (\r
   IN FORM_BROWSER_FORMSET  *FormSet\r
   )\r
 {\r
   LIST_ENTRY              *Link;\r
   FORM_BROWSER_FORM       *Form;\r
+  BOOLEAN                 RetVal;\r
+\r
+  //\r
+  // Not finished question initialization, return FALSE.\r
+  //\r
+  if (!FormSet->QuestionInited) {\r
+    return FALSE;\r
+  }\r
+\r
+  RetVal = FALSE;\r
 \r
   Link = GetFirstNode (&FormSet->FormListHead);\r
   while (!IsNull (&FormSet->FormListHead, Link)) {\r
     Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
 \r
-    if (Form->NvUpdateRequired ) {\r
-      return TRUE;\r
+    RetVal = IsNvUpdateRequiredForForm(Form);\r
+    if (RetVal) {\r
+      break;\r
     }\r
 \r
     Link = GetNextNode (&FormSet->FormListHead, Link);\r
   }\r
 \r
-  return FALSE;\r
+  return RetVal;\r
 }\r
 \r
 /**\r
-  check whether the formset need to update the NV.\r
+  Update the NvUpdateRequired flag for a form.\r
 \r
-  @param  FormSet                FormSet data structure.\r
-  @param  SetValue               Whether set new value or clear old value.\r
+  @param  Form                Form data structure.\r
 \r
 **/\r
-VOID\r
-UpdateNvInfoInForm (\r
-  IN FORM_BROWSER_FORMSET  *FormSet,\r
-  IN BOOLEAN               SetValue\r
+BOOLEAN\r
+IsNvUpdateRequiredForForm (\r
+  IN FORM_BROWSER_FORM    *Form\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
+  FORM_BROWSER_STATEMENT  *Statement;\r
 \r
-    Form->NvUpdateRequired = SetValue;\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
 \r
-    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+    if (Statement->ValueChanged) {\r
+      return TRUE;\r
+    }\r
+\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
   }\r
+\r
+  return FALSE;\r
 }\r
+\r
 /**\r
   Find menu which will show next time.\r
 \r
@@ -988,98 +1812,64 @@ UpdateNvInfoInForm (
                          about the Selection, form and formset to be displayed.\r
                          On output, Selection return the screen item that is selected\r
                          by user.\r
-  @param Repaint         Whether need to repaint the menu.\r
-  @param NewLine         Whether need to show at new line.\r
-  \r
-  @retval TRUE           Need return.\r
-  @retval FALSE          No need to return.\r
+  @param SettingLevel    Input Settting level, if it is FormLevel, just exit current form.\r
+                         else, we need to exit current formset.\r
+\r
+  @retval TRUE           Exit current form.\r
+  @retval FALSE          User press ESC and keep in current form.\r
 **/\r
 BOOLEAN\r
 FindNextMenu (\r
-  IN OUT UI_MENU_SELECTION    *Selection,\r
-  IN     BOOLEAN              *Repaint, \r
-  IN     BOOLEAN              *NewLine  \r
+  IN OUT UI_MENU_SELECTION        *Selection,\r
+  IN     BROWSER_SETTING_SCOPE     SettingLevel\r
   )\r
 {\r
-  UI_MENU_LIST            *CurrentMenu;\r
-  CHAR16                  YesResponse;\r
-  CHAR16                  NoResponse;\r
-  EFI_INPUT_KEY           Key;\r
-  BROWSER_SETTING_SCOPE   Scope;\r
-  \r
+  FORM_ENTRY_INFO            *CurrentMenu;\r
+  FORM_ENTRY_INFO            *ParentMenu;\r
+  BROWSER_SETTING_SCOPE      Scope;\r
+\r
   CurrentMenu = Selection->CurrentMenu;\r
+  Scope       = FormSetLevel;\r
 \r
-  if (CurrentMenu != NULL && CurrentMenu->Parent != NULL) {\r
-    //\r
-    // we have a parent, so go to the parent menu\r
-    //\r
-    if (CompareGuid (&CurrentMenu->FormSetGuid, &CurrentMenu->Parent->FormSetGuid)) {\r
-      //\r
-      // The parent menu and current menu are in the same formset\r
-      //\r
-      Selection->Action = UI_ACTION_REFRESH_FORM;\r
-      Scope             = FormLevel;\r
+  ParentMenu = UiFindParentMenu(CurrentMenu, SettingLevel);\r
+  while (ParentMenu != NULL && !ValidateHiiHandle(ParentMenu->HiiHandle)) {\r
+    ParentMenu = UiFindParentMenu(ParentMenu, SettingLevel);\r
+  }\r
+\r
+  if (ParentMenu != NULL) {\r
+    if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
+      Scope = FormLevel;\r
     } else {\r
-      Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
-      CopyMem (&Selection->FormSetGuid, &CurrentMenu->Parent->FormSetGuid, sizeof (EFI_GUID));\r
-      Selection->Handle = CurrentMenu->Parent->HiiHandle;\r
-      Scope             = FormSetLevel;\r
+      Scope = FormSetLevel;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Form Level Check whether the data is changed.\r
+  //\r
+  if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm (Selection->Form)) ||\r
+      (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet(Selection->FormSet) && Scope == FormSetLevel)) {\r
+    if (!ProcessChangedData(Selection, gBrowserSettingScope)) {\r
+      return FALSE;\r
     }\r
+  }\r
 \r
+  if (ParentMenu != NULL) {\r
     //\r
-    // Form Level Check whether the data is changed.\r
+    // ParentMenu is found. Then, go to it.\r
     //\r
-    if ((gBrowserSettingScope == FormLevel && Selection->Form->NvUpdateRequired) ||\r
-        (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequired(Selection->FormSet) && Scope == FormSetLevel)) {\r
-      gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
-  \r
-      YesResponse = gYesResponse[0];\r
-      NoResponse  = gNoResponse[0];\r
-  \r
-      //\r
-      // If NV flag is up, prompt user\r
-      //\r
-      do {\r
-        CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gAreYouSure, gEmptyString);\r
-      } while\r
-      (\r
-        (Key.ScanCode != SCAN_ESC) &&\r
-        ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&\r
-        ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))\r
-      );\r
-  \r
-      if (Key.ScanCode == SCAN_ESC) {\r
-        //\r
-        // User hits the ESC key, Ingore. \r
-        //\r
-        if (Repaint != NULL) {\r
-          *Repaint = TRUE;\r
-        }\r
-        if (NewLine != NULL) {\r
-          *NewLine = TRUE;\r
-        }\r
-\r
-        Selection->Action = UI_ACTION_NONE;\r
-        return FALSE;\r
-      }\r
-  \r
-      if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
-        //\r
-        // If the user hits the YesResponse key\r
-        //\r
-        SubmitForm (Selection->FormSet, Selection->Form, Scope);\r
-      } else {\r
-        //\r
-        // If the user hits the NoResponse key\r
-        //\r
-        DiscardForm (Selection->FormSet, Selection->Form, Scope);\r
-      }\r
+    if (Scope == FormLevel) {\r
+      Selection->Action = UI_ACTION_REFRESH_FORM;\r
+    } else {\r
+      Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+      CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
+      Selection->Handle = ParentMenu->HiiHandle;\r
     }\r
 \r
     Selection->Statement = NULL;\r
 \r
-    Selection->FormId = CurrentMenu->Parent->FormId;\r
-    Selection->QuestionId = CurrentMenu->Parent->QuestionId;\r
+    Selection->FormId = ParentMenu->FormId;\r
+    Selection->QuestionId = ParentMenu->QuestionId;\r
 \r
     //\r
     // Clear highlight record for this menu\r
@@ -1088,71 +1878,36 @@ FindNextMenu (
     return FALSE;\r
   }\r
 \r
-  if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
-    //\r
-    // We never exit FrontPage, so skip the ESC\r
-    //\r
-    Selection->Action = UI_ACTION_NONE;\r
-    return FALSE;\r
-  }\r
-\r
   //\r
-  // We are going to leave current FormSet, so check uncommited data in this FormSet\r
+  // Current in root page, exit the SendForm\r
   //\r
-  if (gBrowserSettingScope != SystemLevel && IsNvUpdateRequired(Selection->FormSet)) {\r
-    gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
-\r
-    YesResponse = gYesResponse[0];\r
-    NoResponse  = gNoResponse[0];\r
+  Selection->Action = UI_ACTION_EXIT;\r
 \r
-    //\r
-    // If NV flag is up, prompt user\r
-    //\r
-    do {\r
-      CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gAreYouSure, gEmptyString);\r
-    } while\r
-    (\r
-      (Key.ScanCode != SCAN_ESC) &&\r
-      ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&\r
-      ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))\r
-    );\r
+  return TRUE;\r
+}\r
 \r
-    if (Key.ScanCode == SCAN_ESC) {\r
-      //\r
-      // User hits the ESC key\r
-      //\r
-      if (Repaint != NULL) {\r
-        *Repaint = TRUE;\r
-      }\r
+/**\r
+  Reconnect the controller.\r
 \r
-      if (NewLine != NULL) {\r
-        *NewLine = TRUE;\r
-      }\r
+  @param DriverHandle          The controller handle which need to be reconnect.\r
 \r
-      Selection->Action = UI_ACTION_NONE;\r
-      return FALSE;\r
-    }\r
+  @retval   TRUE     do the reconnect behavior success.\r
+  @retval   FALSE    do the reconnect behavior failed.\r
 \r
-    if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
-      //\r
-      // If the user hits the YesResponse key\r
-      //\r
-      SubmitForm (Selection->FormSet, Selection->Form, FormSetLevel);\r
-    } else {\r
-      //\r
-      // If the user hits the NoResponse key\r
-      //\r
-      DiscardForm (Selection->FormSet, Selection->Form, FormSetLevel);\r
-    }\r
-  }\r
+**/\r
+BOOLEAN\r
+ReconnectController (\r
+  IN EFI_HANDLE   DriverHandle\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
 \r
-  Selection->Statement = NULL;\r
-  if (CurrentMenu != NULL) {\r
-    CurrentMenu->QuestionId = 0;\r
+  Status = gBS->DisconnectController(DriverHandle, NULL, NULL);\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->ConnectController(DriverHandle, NULL, NULL, TRUE);\r
   }\r
 \r
-  Selection->Action = UI_ACTION_EXIT;\r
-  return TRUE;\r
+  return Status == EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -1162,22 +1917,27 @@ FindNextMenu (
                                about the Selection, form and formset to be displayed.\r
                                On output, Selection return the screen item that is selected\r
                                by user.\r
+  @param FormSet               The formset this question belong to.\r
+  @param Form                  The form this question belong to.\r
   @param Question              The Question which need to call.\r
   @param Action                The action request.\r
   @param SkipSaveOrDiscard     Whether skip save or discard action.\r
 \r
-  @retval EFI_SUCCESS          The call back function excutes successfully.\r
-  @return Other value if the call back function failed to excute.  \r
+  @retval EFI_SUCCESS          The call back function executes successfully.\r
+  @return Other value if the call back function failed to execute.\r
 **/\r
-EFI_STATUS \r
+EFI_STATUS\r
 ProcessCallBackFunction (\r
   IN OUT UI_MENU_SELECTION               *Selection,\r
+  IN     FORM_BROWSER_FORMSET            *FormSet,\r
+  IN     FORM_BROWSER_FORM               *Form,\r
   IN     FORM_BROWSER_STATEMENT          *Question,\r
   IN     EFI_BROWSER_ACTION              Action,\r
   IN     BOOLEAN                         SkipSaveOrDiscard\r
   )\r
 {\r
   EFI_STATUS                      Status;\r
+  EFI_STATUS                      InternalStatus;\r
   EFI_BROWSER_ACTION_REQUEST      ActionRequest;\r
   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
   EFI_HII_VALUE                   *HiiValue;\r
@@ -1188,23 +1948,27 @@ ProcessCallBackFunction (
   BOOLEAN                         NeedExit;\r
   LIST_ENTRY                      *Link;\r
   BROWSER_SETTING_SCOPE           SettingLevel;\r
+  EFI_IFR_TYPE_VALUE              BackUpValue;\r
+  UINT8                           *BackUpBuffer;\r
+  CHAR16                          *NewString;\r
 \r
-  ConfigAccess = Selection->FormSet->ConfigAccess;\r
+  ConfigAccess = FormSet->ConfigAccess;\r
   SubmitFormIsRequired  = FALSE;\r
   SettingLevel          = FormSetLevel;\r
   DiscardFormIsRequired = FALSE;\r
   NeedExit              = FALSE;\r
   Status                = EFI_SUCCESS;\r
   ActionRequest         = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+  BackUpBuffer          = NULL;\r
 \r
   if (ConfigAccess == NULL) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
-  Link = GetFirstNode (&Selection->Form->StatementListHead);\r
-  while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
     Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
-    Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
 \r
     //\r
     // if Question != NULL, only process the question. Else, process all question in this form.\r
@@ -1212,7 +1976,7 @@ ProcessCallBackFunction (
     if ((Question != NULL) && (Statement != Question)) {\r
       continue;\r
     }\r
-    \r
+\r
     if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
       continue;\r
     }\r
@@ -1220,11 +1984,8 @@ ProcessCallBackFunction (
     //\r
     // Check whether Statement is disabled.\r
     //\r
-    if (Statement->DisableExpression != NULL) {\r
-      Status = EvaluateExpression (Selection->FormSet, Selection->Form, Statement->DisableExpression);\r
-      if (!EFI_ERROR (Status) && \r
-          (Statement->DisableExpression->Result.Type == EFI_IFR_TYPE_BOOLEAN) && \r
-          (Statement->DisableExpression->Result.Value.b)) {\r
+    if (Statement->Expression != NULL) {\r
+      if (EvaluateExpressionList(Statement->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
         continue;\r
       }\r
     }\r
@@ -1237,7 +1998,19 @@ ProcessCallBackFunction (
       //\r
       TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
     }\r
-      \r
+\r
+    //\r
+    // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.\r
+    //\r
+    if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
+      if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+        BackUpBuffer = AllocateCopyPool(Statement->StorageWidth + sizeof(CHAR16), Statement->BufferValue);\r
+        ASSERT (BackUpBuffer != NULL);\r
+      } else {\r
+        CopyMem (&BackUpValue, &HiiValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+      }\r
+    }\r
+\r
     ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
     Status = ConfigAccess->Callback (\r
                              ConfigAccess,\r
@@ -1248,23 +2021,44 @@ ProcessCallBackFunction (
                              &ActionRequest\r
                              );\r
     if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue\r
+      //\r
+      if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+        NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
+        ASSERT (NewString != NULL);\r
+\r
+        ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth);\r
+        if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) {\r
+          ZeroMem (Statement->BufferValue, Statement->StorageWidth);\r
+          CopyMem (Statement->BufferValue, NewString, StrSize (NewString));\r
+        } else {\r
+          CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);\r
+        }\r
+        FreePool (NewString);\r
+      }\r
+\r
       //\r
       // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.\r
       //\r
-      if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
+      switch (Action) {\r
+      case EFI_BROWSER_ACTION_CHANGED:\r
         switch (ActionRequest) {\r
         case EFI_BROWSER_ACTION_REQUEST_RESET:\r
-          gResetRequired = TRUE;\r
-          Selection->Action = UI_ACTION_EXIT;\r
+          DiscardFormIsRequired = TRUE;\r
+          gResetRequiredFormLevel = TRUE;\r
+          gResetRequiredSystemLevel = TRUE;\r
+          NeedExit              = TRUE;\r
           break;\r
 \r
         case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
           SubmitFormIsRequired = TRUE;\r
-          Selection->Action = UI_ACTION_EXIT;\r
+          NeedExit              = TRUE;\r
           break;\r
 \r
         case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
-          Selection->Action = UI_ACTION_EXIT;\r
+          DiscardFormIsRequired = TRUE;\r
+          NeedExit              = TRUE;\r
           break;\r
 \r
         case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:\r
@@ -1275,7 +2069,7 @@ ProcessCallBackFunction (
 \r
         case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:\r
           DiscardFormIsRequired = TRUE;\r
-          SettingLevel          = FormLevel;      \r
+          SettingLevel          = FormLevel;\r
           NeedExit              = TRUE;\r
           break;\r
 \r
@@ -1289,25 +2083,86 @@ ProcessCallBackFunction (
           SettingLevel          = FormLevel;\r
           break;\r
 \r
+        case EFI_BROWSER_ACTION_REQUEST_RECONNECT:\r
+          gCallbackReconnect    = TRUE;\r
+          break;\r
+\r
         default:\r
           break;\r
         }\r
-      }\r
+        break;\r
+\r
+      case EFI_BROWSER_ACTION_CHANGING:\r
+        //\r
+        // Do the question validation.\r
+        //\r
+        Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
+        if (!EFI_ERROR (Status)) {\r
+          //\r
+          //check whether the question value  changed compared with edit buffer before updating edit buffer\r
+          // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function\r
+          //\r
+          IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
+          //\r
+          // According the spec, return value from call back of "changing" and\r
+          // "retrieve" should update to the question's temp buffer.\r
+          //\r
+          SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
+        }\r
+        break;\r
+\r
+      case EFI_BROWSER_ACTION_RETRIEVE:\r
+        //\r
+        // According the spec, return value from call back of "changing" and\r
+        // "retrieve" should update to the question's temp buffer.\r
+        //\r
+        SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
+        break;\r
 \r
+      default:\r
+        break;\r
+      }\r
+    } else {\r
       //\r
-      // According the spec, return value from call back of "changing" and \r
-      // "retrieve" should update to the question's temp buffer.\r
+      // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING,\r
+      // then the browser will use the value passed to Callback() and ignore the\r
+      // value returned by Callback().\r
       //\r
-      if (Action == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
-        SetQuestionValue(Selection->FormSet, Selection->Form, Statement, TRUE);\r
+      if (Action  == EFI_BROWSER_ACTION_CHANGING && Status == EFI_UNSUPPORTED) {\r
+        if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+          CopyMem (Statement->BufferValue, BackUpBuffer, Statement->StorageWidth + sizeof(CHAR16));\r
+        } else {\r
+          CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
+        }\r
+\r
+        //\r
+        // Do the question validation.\r
+        //\r
+        InternalStatus = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
+        if (!EFI_ERROR (InternalStatus)) {\r
+          //\r
+          //check whether the question value  changed compared with edit buffer before updating edit buffer\r
+          // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function\r
+          //\r
+          IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
+          SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
+        }\r
       }\r
-    } else {\r
+\r
       //\r
-      // According the spec, return fail from call back of "changing" and \r
+      // According the spec, return fail from call back of "changing" and\r
       // "retrieve", should restore the question's value.\r
       //\r
-      if (Action  == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
-        GetQuestionValue(Selection->FormSet, Selection->Form, Statement, TRUE);\r
+      if (Action == EFI_BROWSER_ACTION_CHANGING && Status != EFI_UNSUPPORTED) {\r
+        if (Statement->Storage != NULL) {\r
+          GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
+        } else if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+          ProcessCallBackFunction (Selection, FormSet, Form, Question, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
+        }\r
+      }\r
+\r
+      if (Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
+        GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
       }\r
 \r
       if (Status == EFI_UNSUPPORTED) {\r
@@ -1317,18 +2172,121 @@ ProcessCallBackFunction (
         Status = EFI_SUCCESS;\r
       }\r
     }\r
+\r
+    if (BackUpBuffer != NULL) {\r
+      FreePool (BackUpBuffer);\r
+    }\r
+\r
+    //\r
+    // If Question != NULL, means just process one question\r
+    // and if code reach here means this question has finished\r
+    // processing, so just break.\r
+    //\r
+    if (Question != NULL) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (gCallbackReconnect && (EFI_BROWSER_ACTION_CHANGED == Action)) {\r
+    //\r
+    // Confirm changes with user first.\r
+    //\r
+    if (IsNvUpdateRequiredForFormSet(FormSet)) {\r
+      if (BROWSER_ACTION_DISCARD == PopupErrorMessage(BROWSER_RECONNECT_SAVE_CHANGES, NULL, NULL, NULL)) {\r
+        gCallbackReconnect = FALSE;\r
+        DiscardFormIsRequired = TRUE;\r
+      } else {\r
+        SubmitFormIsRequired = TRUE;\r
+      }\r
+    } else {\r
+      PopupErrorMessage(BROWSER_RECONNECT_REQUIRED, NULL, NULL, NULL);\r
+    }\r
+\r
+    //\r
+    // Exit current formset before do the reconnect.\r
+    //\r
+    NeedExit = TRUE;\r
+    SettingLevel = FormSetLevel;\r
   }\r
 \r
   if (SubmitFormIsRequired && !SkipSaveOrDiscard) {\r
-    SubmitForm (Selection->FormSet, Selection->Form, SettingLevel);\r
+    SubmitForm (FormSet, Form, SettingLevel);\r
   }\r
 \r
   if (DiscardFormIsRequired && !SkipSaveOrDiscard) {\r
-    DiscardForm (Selection->FormSet, Selection->Form, SettingLevel);\r
+    DiscardForm (FormSet, Form, SettingLevel);\r
   }\r
 \r
   if (NeedExit) {\r
-    FindNextMenu (Selection, NULL, NULL);\r
+    FindNextMenu (Selection, SettingLevel);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Call the retrieve type call back function for one question to get the initialize data.\r
+\r
+  This function only used when in the initialize stage, because in this stage, the\r
+  Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.\r
+\r
+  @param ConfigAccess          The config access protocol produced by the hii driver.\r
+  @param Statement             The Question which need to call.\r
+  @param FormSet               The formset this question belong to.\r
+\r
+  @retval EFI_SUCCESS          The call back function executes successfully.\r
+  @return Other value if the call back function failed to execute.\r
+**/\r
+EFI_STATUS\r
+ProcessRetrieveForQuestion (\r
+  IN     EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess,\r
+  IN     FORM_BROWSER_STATEMENT          *Statement,\r
+  IN     FORM_BROWSER_FORMSET            *FormSet\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_BROWSER_ACTION_REQUEST      ActionRequest;\r
+  EFI_HII_VALUE                   *HiiValue;\r
+  EFI_IFR_TYPE_VALUE              *TypeValue;\r
+  CHAR16                          *NewString;\r
+\r
+  Status                = EFI_SUCCESS;\r
+  ActionRequest         = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+  if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) || ConfigAccess == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  HiiValue  = &Statement->HiiValue;\r
+  TypeValue = &HiiValue->Value;\r
+  if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+    //\r
+    // For OrderedList, passing in the value buffer to Callback()\r
+    //\r
+    TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
+  }\r
+\r
+  ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+  Status = ConfigAccess->Callback (\r
+                           ConfigAccess,\r
+                           EFI_BROWSER_ACTION_RETRIEVE,\r
+                           Statement->QuestionId,\r
+                           HiiValue->Type,\r
+                           TypeValue,\r
+                           &ActionRequest\r
+                           );\r
+  if (!EFI_ERROR (Status) && HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+    NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
+    ASSERT (NewString != NULL);\r
+\r
+    ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth);\r
+    if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) {\r
+      ZeroMem (Statement->BufferValue, Statement->StorageWidth);\r
+      CopyMem (Statement->BufferValue, NewString, StrSize (NewString));\r
+    } else {\r
+      CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);\r
+    }\r
+    FreePool (NewString);\r
   }\r
 \r
   return Status;\r
@@ -1357,9 +2315,7 @@ SetupBrowser (
   EFI_HANDLE                      NotifyHandle;\r
   FORM_BROWSER_STATEMENT          *Statement;\r
   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
-  EFI_INPUT_KEY                   Key;\r
 \r
-  gMenuRefreshHead = NULL;\r
   ConfigAccess = Selection->FormSet->ConfigAccess;\r
 \r
   //\r
@@ -1380,23 +2336,36 @@ SetupBrowser (
   //\r
   // Initialize current settings of Questions in this FormSet\r
   //\r
-  Status = InitializeCurrentSetting (Selection->FormSet);\r
-  if (EFI_ERROR (Status)) {\r
-    goto Done;\r
-  }\r
+  InitializeCurrentSetting (Selection->FormSet);\r
 \r
   //\r
-  // Update gOldFormSet on maintain back up FormSet list.\r
-  // And, make gOldFormSet point to current FormSet. \r
+  // Initilize Action field.\r
   //\r
-  if (gOldFormSet != NULL) {\r
-    RemoveEntryList (&gOldFormSet->Link);\r
-    DestroyFormSet (gOldFormSet);\r
-  }\r
-  gOldFormSet = Selection->FormSet;\r
-  InsertTailList (&gBrowserFormSetList, &gOldFormSet->Link);\r
+  Selection->Action = UI_ACTION_REFRESH_FORM;\r
+\r
+  //\r
+  // Clean the mCurFakeQestId value is formset refreshed.\r
+  //\r
+  mCurFakeQestId = 0;\r
 \r
   do {\r
+\r
+    //\r
+    // Reset Status to prevent the next break from returning incorrect error status.\r
+    //\r
+    Status = EFI_SUCCESS;\r
+\r
+    //\r
+    // IFR is updated, force to reparse the IFR binary\r
+    // This check is shared by EFI_BROWSER_ACTION_FORM_CLOSE and\r
+    // EFI_BROWSER_ACTION_RETRIEVE, so code place here.\r
+    //\r
+    if (mHiiPackageListUpdated) {\r
+      Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+      mHiiPackageListUpdated = FALSE;\r
+      break;\r
+    }\r
+\r
     //\r
     // Initialize Selection->Form\r
     //\r
@@ -1424,39 +2393,28 @@ SetupBrowser (
     // Check Form is suppressed.\r
     //\r
     if (Selection->Form->SuppressExpression != NULL) {\r
-      Status = EvaluateExpression (Selection->FormSet, Selection->Form, Selection->Form->SuppressExpression);\r
-      if (EFI_ERROR (Status) || (Selection->Form->SuppressExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN)) {\r
-        Status = EFI_INVALID_PARAMETER;\r
-        goto Done;\r
-      }\r
-\r
-      if (Selection->Form->SuppressExpression->Result.Value.b) {\r
+      if (EvaluateExpressionList(Selection->Form->SuppressExpression, TRUE, Selection->FormSet, Selection->Form) == ExpressSuppress) {\r
         //\r
-        // Form is suppressed. \r
+        // Form is suppressed.\r
         //\r
-        do {\r
-          CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString);\r
-        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
-\r
+        PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL);\r
         Status = EFI_NOT_FOUND;\r
         goto Done;\r
       }\r
     }\r
 \r
-    //\r
-    // Reset FormPackage update flag\r
-    //\r
-    mHiiPackageListUpdated = FALSE;\r
-\r
     //\r
     // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN\r
     // for each question with callback flag.\r
     // New form may be the first form, or the different form after another form close.\r
     //\r
-    if ((ConfigAccess != NULL) &&\r
-        ((Selection->Handle != mCurrentHiiHandle) ||\r
+    if (((Selection->Handle != mCurrentHiiHandle) ||\r
         (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
         (Selection->FormId != mCurrentFormId))) {\r
+      //\r
+      // Update Retrieve flag.\r
+      //\r
+      mFinishRetrieveCall = FALSE;\r
 \r
       //\r
       // Keep current form information\r
@@ -1465,24 +2423,20 @@ SetupBrowser (
       CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid);\r
       mCurrentFormId      = Selection->FormId;\r
 \r
-      Status = ProcessCallBackFunction (Selection, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);\r
-      if (EFI_ERROR (Status)) {\r
-        goto Done;\r
-      }\r
+      if (ConfigAccess != NULL) {\r
+        Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
 \r
-      //\r
-      // EXIT requests to close form.\r
-      //\r
-      if (Selection->Action == UI_ACTION_EXIT) {\r
-        goto Done;\r
-      }\r
-      //\r
-      // IFR is updated during callback of open form, force to reparse the IFR binary\r
-      //\r
-      if (mHiiPackageListUpdated) {\r
-        Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
-        mHiiPackageListUpdated = FALSE;\r
-        break;\r
+        //\r
+        // IFR is updated during callback of EFI_BROWSER_ACTION_FORM_OPEN, force to reparse the IFR binary\r
+        //\r
+        if (mHiiPackageListUpdated) {\r
+          Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+          mHiiPackageListUpdated = FALSE;\r
+          break;\r
+        }\r
       }\r
     }\r
 \r
@@ -1494,30 +2448,33 @@ SetupBrowser (
       goto Done;\r
     }\r
 \r
-    //\r
-    // EXIT requests to close form.\r
-    //\r
-    if (Selection->Action == UI_ACTION_EXIT) {\r
-      goto Done;\r
-    }\r
-    //\r
-    // IFR is updated during callback of read value, force to reparse the IFR binary\r
-    //\r
-    if (mHiiPackageListUpdated) {\r
-      Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
-      mHiiPackageListUpdated = FALSE;\r
-      break;\r
-    }\r
+    if (!mFinishRetrieveCall) {\r
+      //\r
+      // Finish call RETRIEVE callback for this form.\r
+      //\r
+      mFinishRetrieveCall = TRUE;\r
 \r
-    //\r
-    // Displays the Header and Footer borders\r
-    //\r
-    DisplayPageFrame (Selection);\r
+      if (ConfigAccess != NULL) {\r
+        Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // IFR is updated during callback of open form, force to reparse the IFR binary\r
+        //\r
+        if (mHiiPackageListUpdated) {\r
+          Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+          mHiiPackageListUpdated = FALSE;\r
+          break;\r
+        }\r
+      }\r
+    }\r
 \r
     //\r
     // Display form\r
     //\r
-    Status = DisplayForm (Selection);\r
+    Status = DisplayForm ();\r
     if (EFI_ERROR (Status)) {\r
       goto Done;\r
     }\r
@@ -1527,67 +2484,110 @@ SetupBrowser (
     //\r
     Statement = Selection->Statement;\r
     if (Statement != NULL) {\r
-      if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) {\r
-        gResetRequired = TRUE;\r
-      }\r
-\r
-      //\r
-      // Reset FormPackage update flag\r
-      //\r
-      mHiiPackageListUpdated = FALSE;\r
-\r
-      if ((ConfigAccess != NULL) && \r
-          ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && \r
+      if ((ConfigAccess != NULL) &&\r
+          ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) &&\r
           (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
-        Status = ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);         \r
-        if (Statement->Operand == EFI_IFR_REF_OP && Selection->Action != UI_ACTION_EXIT) {\r
+        Status = ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
+        if (Statement->Operand == EFI_IFR_REF_OP) {\r
           //\r
           // Process dynamic update ref opcode.\r
           //\r
           if (!EFI_ERROR (Status)) {\r
-            Status = ProcessGotoOpCode(Statement, Selection, NULL, NULL);\r
+            Status = ProcessGotoOpCode(Statement, Selection);\r
           }\r
-          \r
+\r
           //\r
           // Callback return error status or status return from process goto opcode.\r
           //\r
           if (EFI_ERROR (Status)) {\r
             //\r
-            // Cross reference will not be taken\r
+            // Cross reference will not be taken, restore all essential field\r
             //\r
-            Selection->FormId = Selection->Form->FormId;\r
+            Selection->Handle = mCurrentHiiHandle;\r
+            CopyMem (&Selection->FormSetGuid, &mCurrentFormSetGuid, sizeof (EFI_GUID));\r
+            Selection->FormId = mCurrentFormId;\r
             Selection->QuestionId = 0;\r
+            Selection->Action = UI_ACTION_REFRESH_FORM;\r
           }\r
         }\r
 \r
-        if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) {\r
-          ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\r
+\r
+        if (!EFI_ERROR (Status) &&\r
+            (Statement->Operand != EFI_IFR_REF_OP) &&\r
+            ((Statement->Storage == NULL) || (Statement->Storage != NULL && Statement->ValueChanged))) {\r
+          //\r
+          // Only question value has been changed, browser will trig CHANGED callback.\r
+          //\r
+          ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\r
+          //\r
+          //check whether the question value changed compared with buffer value\r
+          //if doesn't change ,set the ValueChanged flag to FALSE ,in order not to display the "configuration changed "information on the screen\r
+          //\r
+          IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
+        }\r
+      } else {\r
+        //\r
+        // Do the question validation.\r
+        //\r
+        Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
+        if (!EFI_ERROR (Status) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
+          SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
+          //\r
+          // Verify whether question value has checked, update the ValueChanged flag in Question.\r
+          //\r
+          IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
         }\r
       }\r
 \r
       //\r
-      // Check whether Form Package has been updated during Callback\r
+      // If question has EFI_IFR_FLAG_RESET_REQUIRED/EFI_IFR_FLAG_RECONNECT_REQUIRED flag and without storage\r
+      // and process question success till here, trig the gResetFlag/gFlagReconnect.\r
       //\r
-      if (mHiiPackageListUpdated && (Selection->Action == UI_ACTION_REFRESH_FORM)) {\r
-        //\r
-        // Force to reparse IFR binary of target Formset\r
-        //\r
-        mHiiPackageListUpdated = FALSE;\r
-        Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+      if ((Status == EFI_SUCCESS) &&\r
+          (Statement->Storage == NULL)) {\r
+        if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0) {\r
+          gResetRequiredFormLevel = TRUE;\r
+          gResetRequiredSystemLevel = TRUE;\r
+        }\r
+\r
+        if ((Statement->QuestionFlags & EFI_IFR_FLAG_RECONNECT_REQUIRED) != 0) {\r
+          gFlagReconnect = TRUE;\r
+        }\r
+      }\r
+    }\r
+\r
+    //\r
+    // Check whether Exit flag is TRUE.\r
+    //\r
+    if (gExitRequired) {\r
+      switch (gBrowserSettingScope) {\r
+      case SystemLevel:\r
+        Selection->Action = UI_ACTION_EXIT;\r
+        break;\r
+\r
+      case FormSetLevel:\r
+      case FormLevel:\r
+        FindNextMenu (Selection, gBrowserSettingScope);\r
+        break;\r
+\r
+      default:\r
+        break;\r
       }\r
+\r
+      gExitRequired = FALSE;\r
     }\r
 \r
     //\r
     // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
     // for each question with callback flag.\r
     //\r
-    if ((ConfigAccess != NULL) && \r
-        ((Selection->Action == UI_ACTION_EXIT) || \r
+    if ((ConfigAccess != NULL) &&\r
+        ((Selection->Action == UI_ACTION_EXIT) ||\r
          (Selection->Handle != mCurrentHiiHandle) ||\r
          (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
          (Selection->FormId != mCurrentFormId))) {\r
 \r
-      Status = ProcessCallBackFunction (Selection, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE);\r
+      Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE);\r
       if (EFI_ERROR (Status)) {\r
         goto Done;\r
       }\r