]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Change the FormBrowser behavior of "Pressing ESC":
authorxdu2 <xdu2@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 26 Oct 2009 03:03:12 +0000 (03:03 +0000)
committerxdu2 <xdu2@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 26 Oct 2009 03:03:12 +0000 (03:03 +0000)
The old behavior is: if press ESC, it will exit the whole Formset.
The new behavior is: if press ESC, it will return to the parent Form; if current Form is the root Form of a FormSet, it will exit the whole FormSet.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9359 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni
MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
MdeModulePkg/Universal/SetupBrowserDxe/Ui.h

index 6425bea28c0d3b0ca099cc74e48d16a15d46abee..364bc9d0218647a3f0f2829349f3609269744c24 100644 (file)
@@ -106,7 +106,7 @@ NewStrCat (
 \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
+  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
 \r
@@ -236,7 +236,7 @@ DisplayPageFrame (
 \r
         ASSERT (RowIdx < BANNER_HEIGHT);\r
         ASSERT (ColumnIdx < BANNER_COLUMNS);\r
-        \r
+\r
         if (gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {\r
           StrFrontPageBanner = GetToken (\r
                                 gBannerData->Banner[RowIdx][ColumnIdx],\r
@@ -406,7 +406,7 @@ EvaluateFormExpressions (
 \r
 /*\r
 +------------------------------------------------------------------------------+\r
-?F2=Previous Page                 Setup Page                                  ?\r
+?                                 Setup Page                                  ?\r
 +------------------------------------------------------------------------------+\r
 \r
 \r
@@ -433,9 +433,9 @@ EvaluateFormExpressions (
 \r
 /**\r
 \r
-  \r
+\r
   Display form and wait for user to select one menu option, then return it.\r
-  \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
@@ -481,16 +481,6 @@ DisplayForm (
       );\r
   }\r
 \r
-  if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
-    gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
-\r
-    //\r
-    // Display the infrastructure strings\r
-    //\r
-    if (!IsListEmpty (&gMenuList)) {\r
-      PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.TopRow + 1, gFunctionTwoString);\r
-    }\r
-  }\r
   //\r
   // Remove Buffer allocated for StringPtr after it has been used.\r
   //\r
@@ -564,7 +554,6 @@ InitializeBrowserStrings (
   )\r
 {\r
   gFunctionOneString    = GetToken (STRING_TOKEN (FUNCTION_ONE_STRING), gHiiHandle);\r
-  gFunctionTwoString    = GetToken (STRING_TOKEN (FUNCTION_TWO_STRING), gHiiHandle);\r
   gFunctionNineString   = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);\r
   gFunctionTenString    = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);\r
   gEnterString          = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);\r
@@ -608,7 +597,6 @@ FreeBrowserStrings (
   )\r
 {\r
   FreePool (gFunctionOneString);\r
-  FreePool (gFunctionTwoString);\r
   FreePool (gFunctionNineString);\r
   FreePool (gFunctionTenString);\r
   FreePool (gEnterString);\r
@@ -857,15 +845,11 @@ SetupBrowser (
   EFI_HII_VALUE                   *HiiValue;\r
   FORM_BROWSER_STATEMENT          *Statement;\r
   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
-  EFI_INPUT_KEY                   Key;\r
-  CHAR16                          YesResponse;\r
-  CHAR16                          NoResponse;\r
+  FORM_BROWSER_FORMSET            *FormSet;\r
 \r
   gMenuRefreshHead = NULL;\r
   gResetRequired = FALSE;\r
-  gNvUpdateRequired = FALSE;\r
-\r
-  UiInitMenuList ();\r
+  FormSet = Selection->FormSet;\r
 \r
   //\r
   // Register notify for Form package update\r
@@ -882,6 +866,15 @@ SetupBrowser (
     return Status;\r
   }\r
 \r
+  //\r
+  // Initialize current settings of Questions in this FormSet\r
+  //\r
+  Status = InitializeCurrentSetting (Selection->FormSet);\r
+  if (EFI_ERROR (Status)) {\r
+    Selection->Action = UI_ACTION_EXIT;\r
+    goto Done;\r
+  }\r
+\r
   do {\r
     //\r
     // Displays the Header and Footer borders\r
@@ -913,7 +906,7 @@ SetupBrowser (
     //\r
     // Load Questions' Value for display\r
     //\r
-    Status = LoadFormConfig (Selection->FormSet, Selection->Form);\r
+    Status = LoadFormSetConfig (Selection->FormSet);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
@@ -1000,36 +993,19 @@ SetupBrowser (
         // Force to reparse IFR binary of target Formset\r
         //\r
         Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
-\r
-        //\r
-        // Uncommitted data will be lost after IFR binary re-pasing, so confirm on whether to save\r
-        //\r
-        if (gNvUpdateRequired) {\r
-          Status      = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
-\r
-          YesResponse = gYesResponse[0];\r
-          NoResponse  = gNoResponse[0];\r
-\r
-          do {\r
-            CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, 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.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);\r
-          }\r
-        }\r
       }\r
     }\r
   } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
 \r
+  //\r
+  // Record the old formset\r
+  //\r
+  if (gOldFormSet != NULL) {\r
+    DestroyFormSet (gOldFormSet);\r
+  }\r
+  gOldFormSet = FormSet;\r
+\r
+Done:\r
   //\r
   // Unregister notify for Form package update\r
   //\r
index 4f2c92c818aa908bf7366930745a43bd4b3c1f5d..a8393aa502019a6b8b3f64c5cdcceef78dfe2903 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Entry and initialization module for the browser.\r
 \r
-Copyright (c) 2007 - 2008, Intel Corporation\r
+Copyright (c) 2007 - 2009, Intel Corporation\r
 All rights reserved. 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
@@ -45,7 +45,6 @@ BOOLEAN               gDownArrow;
 // Browser Global Strings\r
 //\r
 CHAR16            *gFunctionOneString;\r
-CHAR16            *gFunctionTwoString;\r
 CHAR16            *gFunctionNineString;\r
 CHAR16            *gFunctionTenString;\r
 CHAR16            *gEnterString;\r
@@ -87,6 +86,8 @@ EFI_GUID  gSetupBrowserGuid = {
   0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}\r
 };\r
 \r
+FORM_BROWSER_FORMSET  *gOldFormSet = NULL;\r
+\r
 FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {\r
   //\r
   // Boot Manager\r
@@ -190,7 +191,7 @@ FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
   @param FormId          This field specifies which EFI_IFR_FORM to render as the first\r
                          displayable page. If this field has a value of 0x0000, then\r
                          the forms browser will render the specified forms in their encoded order.\r
-  @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in \r
+  @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in\r
                           characters.\r
   @param ActionRequest   Points to the action recommended by the form.\r
 \r
@@ -287,6 +288,8 @@ SendForm (
       Selection->FormId = FormId;\r
     }\r
 \r
+    gNvUpdateRequired = FALSE;\r
+\r
     do {\r
       FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
       ASSERT (FormSet != NULL);\r
@@ -301,15 +304,6 @@ SendForm (
       }\r
       Selection->FormSet = FormSet;\r
 \r
-      //\r
-      // Initialize current settings of Questions in this FormSet\r
-      //\r
-      Status = InitializeCurrentSetting (FormSet);\r
-      if (EFI_ERROR (Status)) {\r
-        DestroyFormSet (FormSet);\r
-        break;\r
-      }\r
-\r
       //\r
       // Display this formset\r
       //\r
@@ -318,7 +312,6 @@ SendForm (
       Status = SetupBrowser (Selection);\r
 \r
       gCurrentSelection = NULL;\r
-      DestroyFormSet (FormSet);\r
 \r
       if (EFI_ERROR (Status)) {\r
         break;\r
@@ -326,6 +319,11 @@ SendForm (
 \r
     } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
 \r
+    if (gOldFormSet != NULL) {\r
+      DestroyFormSet (gOldFormSet);\r
+      gOldFormSet = NULL;\r
+    }\r
+\r
     FreePool (Selection);\r
   }\r
 \r
@@ -1128,7 +1126,7 @@ GetQuestionValue (
       if (EFI_ERROR (Status)) {\r
         return Status;\r
       }\r
-      \r
+\r
       LengthStr = StrLen (Value);\r
       Status    = EFI_SUCCESS;\r
       if (IsString) {\r
@@ -1529,7 +1527,7 @@ SetQuestionValue (
         TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
       }\r
     }\r
-    \r
+\r
     //\r
     // Convert to lower char.\r
     //\r
@@ -1893,7 +1891,7 @@ GetQuestionDefault (
     //\r
     // Take first oneof option as oneof's default value\r
     //\r
-    if (ValueToOption (Question, HiiValue) == NULL) {    \r
+    if (ValueToOption (Question, HiiValue) == NULL) {\r
       Link = GetFirstNode (&Question->OptionListHead);\r
       if (!IsNull (&Question->OptionListHead, Link)) {\r
         Option = QUESTION_OPTION_FROM_LINK (Link);\r
@@ -2026,6 +2024,42 @@ LoadFormConfig (
 }\r
 \r
 \r
+/**\r
+  Initialize Question's Edit copy from Storage for the whole Formset.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormSetConfig (\r
+  IN FORM_BROWSER_FORMSET             *FormSet\r
+  )\r
+{\r
+  EFI_STATUS          Status;\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
+\r
+    //\r
+    // Initialize local copy of Value for each Form\r
+    //\r
+    Status = LoadFormConfig (FormSet, Form);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
 /**\r
   Fill storage's edit copy with settings requested from Configuration Driver.\r
 \r
@@ -2088,6 +2122,54 @@ LoadStorage (
 }\r
 \r
 \r
+/**\r
+  Copy uncommitted data from source Storage to destination Storage.\r
+\r
+  @param  Dst                    Target Storage for uncommitted data.\r
+  @param  Src                    Source Storage for uncommitted data.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_INVALID_PARAMETER  Source and destination Storage is not the same type.\r
+\r
+**/\r
+EFI_STATUS\r
+CopyStorage (\r
+  IN OUT FORMSET_STORAGE     *Dst,\r
+  IN FORMSET_STORAGE         *Src\r
+  )\r
+{\r
+  LIST_ENTRY          *Link;\r
+  NAME_VALUE_NODE     *Node;\r
+\r
+  if ((Dst->Type != Src->Type) || (Dst->Size != Src->Size)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  switch (Src->Type) {\r
+  case EFI_HII_VARSTORE_BUFFER:\r
+    CopyMem (Dst->EditBuffer, Src->EditBuffer, Src->Size);\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_NAME_VALUE:\r
+    Link = GetFirstNode (&Src->NameValueListHead);\r
+    while (!IsNull (&Src->NameValueListHead, Link)) {\r
+      Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+      SetValueByName (Dst, Node->Name, Node->EditValue);\r
+\r
+      Link = GetNextNode (&Src->NameValueListHead, Link);\r
+    }\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
 /**\r
   Get current setting of Questions.\r
 \r
@@ -2102,7 +2184,10 @@ InitializeCurrentSetting (
   )\r
 {\r
   LIST_ENTRY              *Link;\r
+  LIST_ENTRY              *Link2;\r
   FORMSET_STORAGE         *Storage;\r
+  FORMSET_STORAGE         *StorageSrc;\r
+  FORMSET_STORAGE         *OldStorage;\r
   FORM_BROWSER_FORM       *Form;\r
   EFI_STATUS              Status;\r
 \r
@@ -2125,7 +2210,35 @@ InitializeCurrentSetting (
   while (!IsNull (&FormSet->StorageListHead, Link)) {\r
     Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
 \r
-    Status = LoadStorage (FormSet, Storage);\r
+    OldStorage = NULL;\r
+    if (gOldFormSet != NULL) {\r
+      //\r
+      // Try to find the Storage in backup formset gOldFormSet\r
+      //\r
+      Link2 = GetFirstNode (&gOldFormSet->StorageListHead);\r
+      while (!IsNull (&gOldFormSet->StorageListHead, Link2)) {\r
+        StorageSrc = FORMSET_STORAGE_FROM_LINK (Link2);\r
+\r
+        if (StorageSrc->VarStoreId == Storage->VarStoreId) {\r
+          OldStorage = StorageSrc;\r
+          break;\r
+        }\r
+\r
+        Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2);\r
+      }\r
+    }\r
+\r
+    if (OldStorage == NULL) {\r
+      //\r
+      // Storage is not found in backup formset, request it from ConfigDriver\r
+      //\r
+      Status = LoadStorage (FormSet, Storage);\r
+    } else {\r
+      //\r
+      // Storage found in backup formset, use it\r
+      //\r
+      Status = CopyStorage (Storage, OldStorage);\r
+    }\r
 \r
     //\r
     // Now Edit Buffer is filled with default values(lower priority) and current\r
@@ -2211,7 +2324,7 @@ GetIfrBinaryData (
     return Status;\r
   }\r
   ASSERT (HiiPackageList != NULL);\r
-  \r
+\r
   //\r
   // Get Form package from this HII package List\r
   //\r
@@ -2391,10 +2504,6 @@ InitializeFormSet (
         gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
       }\r
 \r
-      if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {\r
-        gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
-      }\r
-\r
       if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {\r
         gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
       }\r
index 21b289126b8793ee4d30f10819c5d935b46bc9c9..91b5aaee40e6334b8d281396ac2d25abd3aa984d 100644 (file)
@@ -1,5 +1,5 @@
 /** @file\r
-Private MACRO, structure and function definitions for Setup Browser module. \r
+Private MACRO, structure and function definitions for Setup Browser module.\r
 \r
 Copyright (c) 2007 - 2009, Intel Corporation\r
 All rights reserved. This program and the accompanying materials\r
@@ -71,10 +71,9 @@ extern UINT8  SetupBrowserStrings[];
 // Definition for function key setting\r
 //\r
 #define NONE_FUNCTION_KEY_SETTING     0\r
-#define DEFAULT_FUNCTION_KEY_SETTING  (FUNCTION_ONE | FUNCTION_TWO | FUNCTION_NINE | FUNCTION_TEN)\r
+#define DEFAULT_FUNCTION_KEY_SETTING  (FUNCTION_ONE | FUNCTION_NINE | FUNCTION_TEN)\r
 \r
 #define FUNCTION_ONE                  (1 << 0)\r
-#define FUNCTION_TWO                  (1 << 1)\r
 #define FUNCTION_NINE                 (1 << 2)\r
 #define FUNCTION_TEN                  (1 << 3)\r
 \r
@@ -461,11 +460,12 @@ extern EFI_SCREEN_DESCRIPTOR gScreenDimensions;
 extern BOOLEAN               gUpArrow;\r
 extern BOOLEAN               gDownArrow;\r
 \r
+extern FORM_BROWSER_FORMSET  *gOldFormSet;\r
+\r
 //\r
 // Browser Global Strings\r
 //\r
 extern CHAR16            *gFunctionOneString;\r
-extern CHAR16            *gFunctionTwoString;\r
 extern CHAR16            *gFunctionNineString;\r
 extern CHAR16            *gFunctionTenString;\r
 extern CHAR16            *gEnterString;\r
@@ -892,6 +892,19 @@ LoadFormConfig (
   IN FORM_BROWSER_FORM                *Form\r
   );\r
 \r
+/**\r
+  Initialize Question's Edit copy from Storage for the whole Formset.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormSetConfig (\r
+  IN FORM_BROWSER_FORMSET             *FormSet\r
+  );\r
+\r
 /**\r
   Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
 \r
@@ -983,7 +996,7 @@ GetIfrBinaryData (
                          ScreenDimenions - This allows the browser to be called so that it occupies a\r
                          portion of the physical screen instead of dynamically determining the screen dimensions.\r
                          ActionRequest   - Points to the action recommended by the form.\r
-  @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in \r
+  @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in\r
                           characters.\r
   @param ActionRequest       Points to the action recommended by the form.\r
 \r
index e25368052b655a856cfb8de45018de5843f749e6..8339e1fa6f1a1dd16e9c4bf598b35c492408d5f3 100644 (file)
Binary files a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni and b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni differ
index d744c90f19a5300623e9829ac30e94a0b7b33e59..66dc208bbee8c33dceb2c63d2b49f1b131d6ade5 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Utility functions for User Interface functions.\r
 \r
-Copyright (c) 2004 - 2008, Intel Corporation\r
+Copyright (c) 2004 - 2009, Intel Corporation\r
 All rights reserved. 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
@@ -16,7 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "Setup.h"\r
 \r
 LIST_ENTRY          Menu;\r
-LIST_ENTRY          gMenuList;\r
+LIST_ENTRY          gMenuList = INITIALIZE_LIST_HEAD_VARIABLE (gMenuList);\r
 MENU_REFRESH_ENTRY  *gMenuRefreshHead;\r
 \r
 //\r
@@ -43,10 +43,6 @@ SCAN_CODE_TO_SCREEN_OPERATION     gScanCodeToOperation[] = {
     SCAN_ESC,\r
     UiReset,\r
   },\r
-  {\r
-    SCAN_F2,\r
-    UiPrevious,\r
-  },\r
   {\r
     SCAN_LEFT,\r
     UiLeft,\r
@@ -102,10 +98,6 @@ SCREEN_OPERATION_T0_CONTROL_FLAG  gScreenOperationToControlFlag[] = {
     UiSave,\r
     CfUiSave,\r
   },\r
-  {\r
-    UiPrevious,\r
-    CfUiPrevious,\r
-  },\r
   {\r
     UiPageUp,\r
     CfUiPageUp,\r
@@ -127,8 +119,6 @@ BOOLEAN GetLineByWidthFinished = FALSE;
   @param  Size                   Number of bytes to set\r
   @param  Value                  Value of the set operation.\r
 \r
-  @return Value.\r
-\r
 **/\r
 VOID\r
 SetUnicodeMem (\r
@@ -160,113 +150,157 @@ UiInitMenu (
 \r
 \r
 /**\r
-  Initialize Menu option list.\r
+  Free Menu option linked list.\r
 \r
 **/\r
 VOID\r
-UiInitMenuList (\r
+UiFreeMenu (\r
   VOID\r
   )\r
 {\r
-  InitializeListHead (&gMenuList);\r
+  UI_MENU_OPTION  *MenuOption;\r
+\r
+  while (!IsListEmpty (&Menu)) {\r
+    MenuOption = MENU_OPTION_FROM_LINK (Menu.ForwardLink);\r
+    RemoveEntryList (&MenuOption->Link);\r
+\r
+    //\r
+    // We allocated space for this description when we did a GetToken, free it here\r
+    //\r
+    if (MenuOption->Skip != 0) {\r
+      //\r
+      // For date/time, MenuOption->Description is shared by three Menu Options\r
+      // Data format :      [01/02/2004]      [11:22:33]\r
+      // Line number :        0  0    1         0  0  1\r
+      //\r
+      FreePool (MenuOption->Description);\r
+    }\r
+    FreePool (MenuOption);\r
+  }\r
 }\r
 \r
 \r
 /**\r
-  Remove a Menu in list, and return FormId/QuestionId for previous Menu.\r
+  Create a menu with specified formset GUID and form ID, and add it as a child\r
+  of the given parent menu.\r
 \r
-  @param  Selection              Menu selection.\r
+  @param  Parent                 The parent of menu to be added.\r
+  @param  FormSetGuid            The Formset Guid of menu to be added.\r
+  @param  FormId                 The Form ID of menu to be added.\r
+\r
+  @return A pointer to the newly added menu or NULL if memory is insufficient.\r
 \r
 **/\r
-VOID\r
-UiRemoveMenuListEntry (\r
-  OUT UI_MENU_SELECTION  *Selection\r
+UI_MENU_LIST *\r
+UiAddMenuList (\r
+  IN OUT UI_MENU_LIST     *Parent,\r
+  IN EFI_GUID             *FormSetGuid,\r
+  IN UINT16               FormId\r
   )\r
 {\r
-  UI_MENU_LIST  *UiMenuList;\r
+  UI_MENU_LIST  *MenuList;\r
 \r
-  if (!IsListEmpty (&gMenuList)) {\r
-    UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);\r
-\r
-    Selection->FormId = UiMenuList->FormId;\r
-    Selection->QuestionId = UiMenuList->QuestionId;\r
-    RemoveEntryList (&UiMenuList->MenuLink);\r
-    FreePool (UiMenuList);\r
+  MenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));\r
+  if (MenuList == NULL) {\r
+    return NULL;\r
   }\r
-}\r
 \r
+  MenuList->Signature = UI_MENU_LIST_SIGNATURE;\r
+  InitializeListHead (&MenuList->ChildListHead);\r
 \r
-/**\r
-  Free Menu option linked list.\r
+  CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
+  MenuList->FormId = FormId;\r
+  MenuList->Parent = Parent;\r
 \r
-**/\r
-VOID\r
-UiFreeMenuList (\r
-  VOID\r
-  )\r
-{\r
-  UI_MENU_LIST  *UiMenuList;\r
-\r
-  while (!IsListEmpty (&gMenuList)) {\r
-    UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);\r
-    RemoveEntryList (&UiMenuList->MenuLink);\r
-    FreePool (UiMenuList);\r
+  if (Parent == NULL) {\r
+    //\r
+    // If parent is not specified, it is the root Form of a Formset\r
+    //\r
+    InsertTailList (&gMenuList, &MenuList->Link);\r
+  } else {\r
+    InsertTailList (&Parent->ChildListHead, &MenuList->Link);\r
   }\r
+\r
+  return MenuList;\r
 }\r
 \r
 \r
 /**\r
-  Add one menu entry to the linked lst\r
+  Search Menu with given FormId in the parent menu and all its child menus.\r
 \r
-  @param  Selection              Menu selection.\r
+  @param  Parent                 The parent of menu to search.\r
+  @param  FormId                 The Form ID of menu to search.\r
+\r
+  @return A pointer to menu found or NULL if not found.\r
 \r
 **/\r
-VOID\r
-UiAddMenuListEntry (\r
-  IN UI_MENU_SELECTION            *Selection\r
+UI_MENU_LIST *\r
+UiFindChildMenuList (\r
+  IN UI_MENU_LIST         *Parent,\r
+  IN UINT16               FormId\r
   )\r
 {\r
-  UI_MENU_LIST  *UiMenuList;\r
+  LIST_ENTRY      *Link;\r
+  UI_MENU_LIST    *Child;\r
+  UI_MENU_LIST    *MenuList;\r
+\r
+  if (Parent->FormId == FormId) {\r
+    return Parent;\r
+  }\r
 \r
-  UiMenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));\r
-  ASSERT (UiMenuList != NULL);\r
+  Link = GetFirstNode (&Parent->ChildListHead);\r
+  while (!IsNull (&Parent->ChildListHead, Link)) {\r
+    Child = UI_MENU_LIST_FROM_LINK (Link);\r
 \r
-  UiMenuList->Signature = UI_MENU_LIST_SIGNATURE;\r
-  UiMenuList->FormId = Selection->FormId;\r
-  UiMenuList->QuestionId = Selection->QuestionId;\r
+    MenuList = UiFindChildMenuList (Child, FormId);\r
+    if (MenuList != NULL) {\r
+      return MenuList;\r
+    }\r
+\r
+    Link = GetNextNode (&Parent->ChildListHead, Link);\r
+  }\r
 \r
-  InsertHeadList (&gMenuList, &UiMenuList->MenuLink);\r
+  return NULL;\r
 }\r
 \r
 \r
 /**\r
-  Free Menu option linked list.\r
+  Search Menu with given FormSetGuid and FormId in all cached menu list.\r
+\r
+  @param  FormSetGuid            The Formset GUID of the menu to search.\r
+  @param  FormId                 The Form ID of menu to search.\r
+\r
+  @return A pointer to menu found or NULL if not found.\r
 \r
 **/\r
-VOID\r
-UiFreeMenu (\r
-  VOID\r
+UI_MENU_LIST *\r
+UiFindMenuList (\r
+  IN EFI_GUID             *FormSetGuid,\r
+  IN UINT16               FormId\r
   )\r
 {\r
-  UI_MENU_OPTION  *MenuOption;\r
+  LIST_ENTRY      *Link;\r
+  UI_MENU_LIST    *MenuList;\r
+  UI_MENU_LIST    *Child;\r
 \r
-  while (!IsListEmpty (&Menu)) {\r
-    MenuOption = MENU_OPTION_FROM_LINK (Menu.ForwardLink);\r
-    RemoveEntryList (&MenuOption->Link);\r
+  Link = GetFirstNode (&gMenuList);\r
+  while (!IsNull (&gMenuList, Link)) {\r
+    MenuList = UI_MENU_LIST_FROM_LINK (Link);\r
 \r
-    //\r
-    // We allocated space for this description when we did a GetToken, free it here\r
-    //\r
-    if (MenuOption->Skip != 0) {\r
+    if (CompareGuid (FormSetGuid, &MenuList->FormSetGuid)) {\r
       //\r
-      // For date/time, MenuOption->Description is shared by three Menu Options\r
-      // Data format :      [01/02/2004]      [11:22:33]\r
-      // Line number :        0  0    1         0  0  1\r
+      // This is the formset we are looking for, find the form in this formset\r
       //\r
-      FreePool (MenuOption->Description);\r
+      Child = UiFindChildMenuList (MenuList, FormId);\r
+      if (Child != NULL) {\r
+        return Child;\r
+      }\r
     }\r
-    FreePool (MenuOption);\r
+\r
+    Link = GetNextNode (&gMenuList, Link);\r
   }\r
+\r
+  return NULL;\r
 }\r
 \r
 \r
@@ -929,7 +963,7 @@ CreateMultiStringPopUp (
   VA_LIST Marker;\r
 \r
   VA_START (Marker, NumberOfLines);\r
-  \r
+\r
   CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker);\r
 \r
   VA_END (Marker);\r
@@ -1275,7 +1309,7 @@ IsSelectable (
   Determine if the menu is the last menu that can be selected.\r
 \r
   This is an internal function.\r
-  \r
+\r
   @param  Direction              The scroll direction. False is down. True is up.\r
   @param  CurrentPos             The current focus.\r
 \r
@@ -1311,9 +1345,9 @@ ValueIsScroll (
 \r
 /**\r
   Move to next selectable statement.\r
-  \r
+\r
   This is an internal function.\r
-  \r
+\r
   @param  GoUp                   The navigation direction. TRUE: up, FALSE: down.\r
   @param  CurrentPosition        Current position.\r
 \r
@@ -1379,7 +1413,7 @@ MoveToNextStatement (
   Adjust Data and Time position accordingly.\r
   Data format :      [01/02/2004]      [11:22:33]\r
   Line number :        0  0    1         0  0  1\r
-  \r
+\r
   This is an internal function.\r
 \r
   @param  DirectionUp            the up or down direction. False is down. True is\r
@@ -1606,6 +1640,8 @@ UiDisplayMenu (
   CHAR16                          TemStr[2];\r
   UINT8                           *DevicePathBuffer;\r
   UINT8                           DigitUint8;\r
+  UI_MENU_LIST                    *CurrentMenu;\r
+  UI_MENU_LIST                    *MenuList;\r
 \r
   CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
 \r
@@ -1651,6 +1687,25 @@ UiDisplayMenu (
   Repaint     = TRUE;\r
   MenuOption  = NULL;\r
 \r
+  //\r
+  // Find current Menu\r
+  //\r
+  CurrentMenu = UiFindMenuList (&Selection->FormSetGuid, Selection->FormId);\r
+  if (CurrentMenu == NULL) {\r
+    //\r
+    // Current menu not found, add it to the menu tree\r
+    //\r
+    CurrentMenu = UiAddMenuList (NULL, &Selection->FormSetGuid, Selection->FormId);\r
+  }\r
+  ASSERT (CurrentMenu != NULL);\r
+\r
+  if (Selection->QuestionId == 0) {\r
+    //\r
+    // Highlight not specified, fetch it from cached menu\r
+    //\r
+    Selection->QuestionId = CurrentMenu->QuestionId;\r
+  }\r
+\r
   //\r
   // Get user's selection\r
   //\r
@@ -2103,6 +2158,10 @@ UiDisplayMenu (
         //\r
         Statement = MenuOption->ThisTag;\r
         Selection->Statement = Statement;\r
+        //\r
+        // Record highlight for current menu\r
+        //\r
+        CurrentMenu->QuestionId = Statement->QuestionId;\r
 \r
         //\r
         // Set reverse attribute\r
@@ -2258,27 +2317,19 @@ UiDisplayMenu (
         //\r
         // IFR is updated in Callback of refresh opcode, re-parse it\r
         //\r
-        ControlFlag = CfUiReset;\r
         Selection->Statement = NULL;\r
-        break;\r
+        return EFI_SUCCESS;\r
       }\r
 \r
       Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
       //\r
-      // if we encounter error, continue to read another key in.\r
+      // If we encounter error, continue to read another key in.\r
       //\r
       if (EFI_ERROR (Status)) {\r
         ControlFlag = CfReadKey;\r
         break;\r
       }\r
 \r
-      if (IsListEmpty (&Menu) && Key.UnicodeChar != CHAR_NULL) {\r
-        //\r
-        // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset\r
-        //\r
-        break;\r
-      }\r
-\r
       switch (Key.UnicodeChar) {\r
       case CHAR_CARRIAGE_RETURN:\r
         ScreenOperation = UiSelect;\r
@@ -2334,7 +2385,6 @@ UiDisplayMenu (
 \r
       case CHAR_NULL:\r
         if (((Key.ScanCode == SCAN_F1) && ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE)) ||\r
-            ((Key.ScanCode == SCAN_F2) && ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO)) ||\r
             ((Key.ScanCode == SCAN_F9) && ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE)) ||\r
             ((Key.ScanCode == SCAN_F10) && ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN))\r
             ) {\r
@@ -2360,9 +2410,9 @@ UiDisplayMenu (
       break;\r
 \r
     case CfScreenOperation:\r
-      if (ScreenOperation != UiPrevious && ScreenOperation != UiReset) {\r
+      if (ScreenOperation != UiReset) {\r
         //\r
-        // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset\r
+        // If the screen has no menu items, and the user didn't select UiReset\r
         // ignore the selection and go back to reading keys.\r
         //\r
         if (IsListEmpty (&Menu)) {\r
@@ -2383,12 +2433,6 @@ UiDisplayMenu (
           ControlFlag = CfPrepareToReadKey;\r
           break;\r
         }\r
-      } else if (ScreenOperation == UiReset) {\r
-        //\r
-        // Press ESC to exit FormSet\r
-        //\r
-        Selection->Action = UI_ACTION_EXIT;\r
-        Selection->Statement = NULL;\r
       }\r
 \r
       for (Index = 0;\r
@@ -2402,26 +2446,6 @@ UiDisplayMenu (
       }\r
       break;\r
 \r
-    case CfUiPrevious:\r
-      ControlFlag = CfCheckSelection;\r
-\r
-      if (IsListEmpty (&gMenuList)) {\r
-        Selection->Action = UI_ACTION_NONE;\r
-        if (IsListEmpty (&Menu)) {\r
-          ControlFlag = CfReadKey;\r
-        }\r
-        break;\r
-      }\r
-\r
-      //\r
-      // Remove the Cached page entry\r
-      //\r
-      UiRemoveMenuListEntry (Selection);\r
-\r
-      Selection->Action = UI_ACTION_REFRESH_FORM;\r
-      Selection->Statement = NULL;\r
-      break;\r
-\r
     case CfUiSelect:\r
       ControlFlag = CfCheckSelection;\r
 \r
@@ -2444,7 +2468,7 @@ UiDisplayMenu (
           //\r
           // Goto another Hii Package list\r
           //\r
-          ControlFlag = CfUiReset;\r
+          ControlFlag = CfCheckSelection;\r
           Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
 \r
           StringPtr = GetToken (Statement->RefDevicePath, Selection->FormSet->HiiHandle);\r
@@ -2458,7 +2482,7 @@ UiDisplayMenu (
           }\r
           BufferSize = StrLen (StringPtr) / 2;\r
           DevicePath = AllocatePool (BufferSize);\r
-          \r
+\r
           //\r
           // Convert from Device Path String to DevicePath Buffer in the reverse order.\r
           //\r
@@ -2499,7 +2523,7 @@ UiDisplayMenu (
           //\r
           // Goto another Formset, check for uncommitted data\r
           //\r
-          ControlFlag = CfUiReset;\r
+          ControlFlag = CfCheckSelection;\r
           Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
 \r
           CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));\r
@@ -2512,9 +2536,12 @@ UiDisplayMenu (
           Selection->Action = UI_ACTION_REFRESH_FORM;\r
 \r
           //\r
-          // Link current form so that we can always go back when someone hits the UiPrevious\r
+          // Link current form so that we can always go back when someone hits the ESC\r
           //\r
-          UiAddMenuListEntry (Selection);\r
+          MenuList = UiFindMenuList (&Selection->FormSetGuid, Statement->RefFormId);\r
+          if (MenuList == NULL) {\r
+            MenuList = UiAddMenuList (CurrentMenu, &Selection->FormSetGuid, Statement->RefFormId);\r
+          }\r
 \r
           Selection->FormId = Statement->RefFormId;\r
           Selection->QuestionId = Statement->RefQuestionId;\r
@@ -2582,21 +2609,44 @@ UiDisplayMenu (
 \r
     case CfUiReset:\r
       //\r
-      // We are going to leave current FormSet, so check uncommited data in this FormSet\r
+      // We come here when someone press ESC\r
       //\r
       ControlFlag = CfCheckSelection;\r
 \r
+      if (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
+        } else {\r
+          Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+        }\r
+        Selection->Statement = NULL;\r
+\r
+        Selection->FormId = CurrentMenu->Parent->FormId;\r
+        Selection->QuestionId = CurrentMenu->Parent->QuestionId;\r
+\r
+        //\r
+        // Clear highlight record for this menu\r
+        //\r
+        CurrentMenu->QuestionId = 0;\r
+        break;\r
+      }\r
+\r
       if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {\r
         //\r
-        // There is no parent menu for FrontPage\r
+        // We never exit FrontPage, so skip the ESC\r
         //\r
         Selection->Action = UI_ACTION_NONE;\r
-        Selection->Statement = MenuOption->ThisTag;\r
         break;\r
       }\r
 \r
       //\r
-      // If NV flag is up, prompt user\r
+      // We are going to leave current FormSet, so check uncommited data in this FormSet\r
       //\r
       if (gNvUpdateRequired) {\r
         Status      = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
@@ -2604,8 +2654,11 @@ UiDisplayMenu (
         YesResponse = gYesResponse[0];\r
         NoResponse  = gNoResponse[0];\r
 \r
+        //\r
+        // If NV flag is up, prompt user\r
+        //\r
         do {\r
-          CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gAreYouSure, gEmptyString);\r
+          CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gAreYouSure, gEmptyString);\r
         } while\r
         (\r
           (Key.ScanCode != SCAN_ESC) &&\r
@@ -2613,24 +2666,29 @@ UiDisplayMenu (
           ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))\r
         );\r
 \r
-        //\r
-        // If the user hits the YesResponse key\r
-        //\r
-        if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
-        } else {\r
+        if (Key.ScanCode == SCAN_ESC) {\r
+          //\r
+          // User hits the ESC key\r
+          //\r
           Repaint = TRUE;\r
           NewLine = TRUE;\r
 \r
           Selection->Action = UI_ACTION_NONE;\r
           break;\r
         }\r
+\r
+        //\r
+        // If the user hits the YesResponse key\r
+        //\r
+        if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
+          Status = SubmitForm (Selection->FormSet, Selection->Form);\r
+        }\r
       }\r
 \r
-      gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
-      gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+      Selection->Action = UI_ACTION_EXIT;\r
+      Selection->Statement = NULL;\r
+      CurrentMenu->QuestionId = 0;\r
 \r
-      UiFreeMenuList ();\r
-      gST->ConOut->ClearScreen (gST->ConOut);\r
       return EFI_SUCCESS;\r
 \r
     case CfUiLeft:\r
@@ -2696,19 +2754,19 @@ UiDisplayMenu (
           TopOfScreen = NewPos;\r
         }\r
 \r
-             Difference = MoveToNextStatement (TRUE, &NewPos);\r
+        Difference = MoveToNextStatement (TRUE, &NewPos);\r
         PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
         DistanceValue += PreviousMenuOption->Skip;\r
-        \r
-             if ((INTN) MenuOption->Row - (INTN) DistanceValue  < (INTN) TopRow) {\r
+\r
+        if ((INTN) MenuOption->Row - (INTN) DistanceValue  < (INTN) TopRow) {\r
           if (Difference > 0) {\r
             //\r
             // Previous focus MenuOption is above the TopOfScreen, so we need to scroll\r
             //\r
             TopOfScreen = NewPos;\r
             Repaint     = TRUE;\r
-                 SkipValue = 0;\r
-                 OldSkipValue = 0;\r
+            SkipValue = 0;\r
+            OldSkipValue = 0;\r
           }\r
         }\r
         if (Difference < 0) {\r
index 2c144486ddbe2c257cdd06817eedde3aff741caa..f7d4ad1d7fdecf31424f84430055a72031dc2717 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Private structure, MACRO and function definitions for User Interface related functionalities.\r
 \r
-Copyright (c) 2004 - 2008, Intel Corporation\r
+Copyright (c) 2004 - 2009, Intel Corporation\r
 All rights reserved. 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
@@ -58,7 +58,6 @@ typedef enum {
   CfPrepareToReadKey,\r
   CfReadKey,\r
   CfScreenOperation,\r
-  CfUiPrevious,\r
   CfUiSelect,\r
   CfUiReset,\r
   CfUiLeft,\r
@@ -145,13 +144,21 @@ typedef struct {
 \r
 #define MENU_OPTION_FROM_LINK(a)  CR (a, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE)\r
 \r
-typedef struct {\r
+typedef struct _UI_MENU_LIST UI_MENU_LIST;\r
+\r
+struct _UI_MENU_LIST {\r
   UINTN           Signature;\r
-  LIST_ENTRY      MenuLink;\r
+  LIST_ENTRY      Link;\r
 \r
+  EFI_GUID        FormSetGuid;\r
   UINT16          FormId;\r
   UINT16          QuestionId;\r
-} UI_MENU_LIST;\r
+\r
+  UI_MENU_LIST    *Parent;\r
+  LIST_ENTRY      ChildListHead;\r
+};\r
+\r
+#define UI_MENU_LIST_FROM_LINK(a)  CR (a, UI_MENU_LIST, Link, UI_MENU_LIST_SIGNATURE)\r
 \r
 typedef struct _MENU_REFRESH_ENTRY {\r
   struct _MENU_REFRESH_ENTRY  *Next;\r
@@ -173,7 +180,6 @@ typedef struct {
 } SCREEN_OPERATION_T0_CONTROL_FLAG;\r
 \r
 \r
-extern LIST_ENTRY          gMenuList;\r
 extern MENU_REFRESH_ENTRY  *gMenuRefreshHead;\r
 extern UI_MENU_SELECTION   *gCurrentSelection;\r
 extern BOOLEAN             mHiiPackageListUpdated;\r
@@ -200,34 +206,60 @@ UiInitMenuList (
   );\r
 \r
 /**\r
-  Remove a Menu in list, and return FormId/QuestionId for previous Menu.\r
-\r
-  @param  Selection              Menu selection.\r
+  Free Menu option linked list.\r
 \r
 **/\r
 VOID\r
-UiRemoveMenuListEntry (\r
-  OUT UI_MENU_SELECTION  *Selection\r
+UiFreeMenu (\r
+  VOID\r
   );\r
 \r
 /**\r
-  Free Menu option linked list.\r
+  Create a menu with specified formset GUID and form ID, and add it as a child\r
+  of the given parent menu.\r
+\r
+  @param  Parent                 The parent of menu to be added.\r
+  @param  FormSetGuid            The Formset Guid of menu to be added.\r
+  @param  FormId                 The Form ID of menu to be added.\r
+\r
+  @return A pointer to the newly added menu or NULL if memory is insufficient.\r
 \r
 **/\r
-VOID\r
-UiFreeMenuList (\r
-  VOID\r
+UI_MENU_LIST *\r
+UiAddMenuList (\r
+  IN OUT UI_MENU_LIST     *Parent,\r
+  IN EFI_GUID             *FormSetGuid,\r
+  IN UINT16               FormId\r
   );\r
 \r
 /**\r
-  Add one menu entry to the linked lst\r
+  Search Menu with given FormId in the parent menu and all its child menus.\r
 \r
-  @param  Selection              Menu selection.\r
+  @param  Parent                 The parent of menu to search.\r
+  @param  FormId                 The Form ID of menu to search.\r
+\r
+  @return A pointer to menu found or NULL if not found.\r
 \r
 **/\r
-VOID\r
-UiAddMenuListEntry (\r
-  IN UI_MENU_SELECTION            *Selection\r
+UI_MENU_LIST *\r
+UiFindChildMenuList (\r
+  IN UI_MENU_LIST         *Parent,\r
+  IN UINT16               FormId\r
+  );\r
+\r
+/**\r
+  Search Menu with given FormSetGuid and FormId in all cached menu list.\r
+\r
+  @param  FormSetGuid            The Formset GUID of the menu to search.\r
+  @param  FormId                 The Form ID of menu to search.\r
+\r
+  @return A pointer to menu found or NULL if not found.\r
+\r
+**/\r
+UI_MENU_LIST *\r
+UiFindMenuList (\r
+  IN EFI_GUID             *FormSetGuid,\r
+  IN UINT16               FormId\r
   );\r
 \r
 /**\r
@@ -235,7 +267,7 @@ UiAddMenuListEntry (
 \r
 **/\r
 VOID\r
-UiFreeMenu (\r
+UiFreeRefreshList (\r
   VOID\r
   );\r
 \r
@@ -557,7 +589,7 @@ ClearLines (
 \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
+  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
 \r