]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
1. The old refresh string code also update the time/date opcode. But for the reason...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Ui.c
index fecb0248bd15f4e973422b88d6bcdfdb9b34aed4..3ab63be2d61749f593c4ed8cf4e1acfc119f80f4 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Utility functions for User Interface functions.\r
 \r
-Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<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
@@ -341,7 +341,6 @@ RefreshForm (
   UI_MENU_SELECTION               *Selection;\r
   FORM_BROWSER_STATEMENT          *Question;\r
   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
-  EFI_HII_VALUE                   *HiiValue;\r
   EFI_BROWSER_ACTION_REQUEST      ActionRequest;\r
 \r
   if (gMenuRefreshHead != NULL) {\r
@@ -354,8 +353,6 @@ RefreshForm (
     mHiiPackageListUpdated = FALSE;\r
 \r
     do {\r
-      gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);\r
-\r
       Selection = MenuRefreshEntry->Selection;\r
       Question = MenuRefreshEntry->MenuOption->ThisTag;\r
 \r
@@ -374,6 +371,22 @@ RefreshForm (
         for (Index = 0; OptionString[Index] == L' '; Index++)\r
           ;\r
 \r
+        //\r
+        // If old Text is longer than new string, need to clean the old string before paint the newer.\r
+        // This option is no need for time/date opcode, because time/data opcode has fixed string length.\r
+        //\r
+        if ((MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_DATE_OP) &&\r
+          (MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_TIME_OP)) {\r
+          ClearLines (\r
+            MenuRefreshEntry->CurrentColumn, \r
+            MenuRefreshEntry->CurrentColumn + gOptionBlockWidth - 1,\r
+            MenuRefreshEntry->CurrentRow,\r
+            MenuRefreshEntry->CurrentRow,\r
+            PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
+            );\r
+        }\r
+\r
+        gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);\r
         PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, &OptionString[Index]);\r
         FreePool (OptionString);\r
       }\r
@@ -384,31 +397,14 @@ RefreshForm (
       ConfigAccess = Selection->FormSet->ConfigAccess;\r
       if (((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
         ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
-\r
-        HiiValue = &Question->HiiValue;\r
-        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
-          //\r
-          // Create String in HII database for Configuration Driver to retrieve\r
-          //\r
-          HiiValue->Value.string = NewString ((CHAR16 *) Question->BufferValue, Selection->FormSet->HiiHandle);\r
-        }\r
-\r
         Status = ConfigAccess->Callback (\r
                                  ConfigAccess,\r
                                  EFI_BROWSER_ACTION_CHANGING,\r
                                  Question->QuestionId,\r
-                                 HiiValue->Type,\r
-                                 &HiiValue->Value,\r
+                                 Question->HiiValue.Type,\r
+                                 &Question->HiiValue.Value,\r
                                  &ActionRequest\r
                                  );\r
-\r
-        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
-          //\r
-          // Clean the String in HII Database\r
-          //\r
-          DeleteString (HiiValue->Value.string, Selection->FormSet->HiiHandle);\r
-        }\r
-\r
         if (!EFI_ERROR (Status)) {\r
           switch (ActionRequest) {\r
           case EFI_BROWSER_ACTION_REQUEST_RESET:\r
@@ -634,6 +630,15 @@ UiAddMenuOption (
       MenuOption->IsQuestion = TRUE;\r
       break;\r
 \r
+    case EFI_IFR_TEXT_OP:\r
+      if (FeaturePcdGet (PcdBrowserGrayOutTextStatement)) {\r
+        //\r
+        // Initializing GrayOut option as TRUE for Text setup options \r
+        // so that those options will be Gray in colour and un selectable.\r
+        //\r
+        MenuOption->GrayOut = TRUE;\r
+      }\r
+\r
     default:\r
       MenuOption->IsQuestion = FALSE;\r
       break;\r
@@ -678,6 +683,7 @@ UiAddMenuOption (
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 CreateDialog (\r
   IN  UINTN                       NumberOfLines,\r
   IN  BOOLEAN                     HotKey,\r
@@ -978,6 +984,7 @@ CreateSharedPopUp (
 \r
 **/\r
 VOID\r
+EFIAPI\r
 CreateMultiStringPopUp (\r
   IN  UINTN                       RequestedWidth,\r
   IN  UINTN                       NumberOfLines,\r
@@ -1027,7 +1034,7 @@ UpdateStatusBar (
         );\r
       mInputError = TRUE;\r
     } else {\r
-      gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);\r
+      gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor));\r
       for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) {\r
         PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, L"  ");\r
       }\r
@@ -1049,7 +1056,7 @@ UpdateStatusBar (
 \r
         gNvUpdateRequired = TRUE;\r
       } else {\r
-        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);\r
+        gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor));\r
         for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {\r
           PrintAt (\r
             (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index),\r
@@ -1132,7 +1139,7 @@ GetWidth (
     Width -= SUBTITLE_INDENT;\r
   }\r
 \r
-  return Width;\r
+  return (UINT16) (Width - LEFT_SKIPPED_COLUMNS);\r
 }\r
 \r
 /**\r
@@ -1348,7 +1355,6 @@ ValueIsScroll (
   )\r
 {\r
   LIST_ENTRY      *Temp;\r
-  UI_MENU_OPTION  *MenuOption;\r
 \r
   Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;\r
 \r
@@ -1356,14 +1362,7 @@ ValueIsScroll (
     return TRUE;\r
   }\r
 \r
-  for (; Temp != &gMenuOption; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) {\r
-    MenuOption = MENU_OPTION_FROM_LINK (Temp);\r
-    if (IsSelectable (MenuOption)) {\r
-      return FALSE;\r
-    }\r
-  }\r
-\r
-  return TRUE;\r
+  return FALSE;\r
 }\r
 \r
 \r
@@ -1374,6 +1373,7 @@ ValueIsScroll (
 \r
   @param  GoUp                   The navigation direction. TRUE: up, FALSE: down.\r
   @param  CurrentPosition        Current position.\r
+  @param  GapToTop               Gap position to top or bottom.\r
 \r
   @return The row distance from current MenuOption to next selectable MenuOption.\r
 \r
@@ -1381,51 +1381,54 @@ ValueIsScroll (
 INTN\r
 MoveToNextStatement (\r
   IN     BOOLEAN                   GoUp,\r
-  IN OUT LIST_ENTRY                **CurrentPosition\r
+  IN OUT LIST_ENTRY                **CurrentPosition,\r
+  IN     UINTN                     GapToTop\r
   )\r
 {\r
   INTN             Distance;\r
   LIST_ENTRY       *Pos;\r
-  BOOLEAN          HitEnd;\r
   UI_MENU_OPTION   *NextMenuOption;\r
+  UI_MENU_OPTION   *PreMenuOption;\r
 \r
-  Distance = 0;\r
-  Pos      = *CurrentPosition;\r
-  HitEnd   = FALSE;\r
+  Distance      = 0;\r
+  Pos           = *CurrentPosition;\r
+  PreMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
 \r
   while (TRUE) {\r
     NextMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
+    if (GoUp && (PreMenuOption != NextMenuOption)) {\r
+      //\r
+      // Current Position doesn't need to be caculated when go up.\r
+      // Caculate distanct at first when go up\r
+      //\r
+      if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
+        NextMenuOption = PreMenuOption;\r
+        break;\r
+      }\r
+      Distance += NextMenuOption->Skip;\r
+    }\r
     if (IsSelectable (NextMenuOption)) {\r
       break;\r
     }\r
     if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {\r
-      HitEnd = TRUE;\r
+      //\r
+      // Arrive at top.\r
+      //\r
+      Distance = -1;\r
       break;\r
     }\r
-    Distance += NextMenuOption->Skip;\r
-    Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);\r
-  }\r
-\r
-  if (HitEnd) {\r
-    //\r
-    // If we hit end there is still no statement can be focused,\r
-    // we go backwards to find the statement can be focused.\r
-    //\r
-    Distance = 0;\r
-    Pos = *CurrentPosition;\r
-\r
-    while (TRUE) {\r
-      NextMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
-      if (IsSelectable (NextMenuOption)) {\r
-        break;\r
-      }\r
-      if ((!GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {\r
-        ASSERT (FALSE);\r
+    if (!GoUp) {\r
+      //\r
+      // Caculate distanct at later when go down\r
+      //\r
+      if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
+        NextMenuOption = PreMenuOption;\r
         break;\r
       }\r
-      Distance -= NextMenuOption->Skip;\r
-      Pos = (!GoUp ? Pos->BackLink : Pos->ForwardLink);\r
+      Distance += NextMenuOption->Skip;\r
     }\r
+    PreMenuOption = NextMenuOption;\r
+    Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);\r
   }\r
 \r
   *CurrentPosition = &NextMenuOption->Link;\r
@@ -1644,6 +1647,7 @@ UiDisplayMenu (
   BOOLEAN                         SavedValue;\r
   BOOLEAN                         UpArrow;\r
   BOOLEAN                         DownArrow;\r
+  BOOLEAN                         InitializedFlag;\r
   EFI_STATUS                      Status;\r
   EFI_INPUT_KEY                   Key;\r
   LIST_ENTRY                      *Link;\r
@@ -1702,7 +1706,7 @@ UiDisplayMenu (
     Row     = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
   }\r
 \r
-  Col = LocalScreen.LeftColumn;\r
+  Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS;\r
   BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - SCROLL_ARROW_HEIGHT - 1;\r
 \r
   Selection->TopRow = TopRow;\r
@@ -1735,8 +1739,9 @@ UiDisplayMenu (
   }\r
 \r
   //\r
-  // Get user's selection\r
+  // Init option as the current user's selection\r
   //\r
+  InitializedFlag = TRUE;\r
   NewPos = gMenuOption.ForwardLink;\r
 \r
   gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
@@ -1773,15 +1778,15 @@ UiDisplayMenu (
         UpArrow         = FALSE;\r
         Row             = TopRow;\r
 \r
-        Temp            = SkipValue;\r
-        Temp2           = SkipValue;\r
+        Temp            = (UINTN) SkipValue;\r
+        Temp2           = (UINTN) SkipValue;\r
 \r
         ClearLines (\r
           LocalScreen.LeftColumn,\r
           LocalScreen.RightColumn,\r
           TopRow - SCROLL_ARROW_HEIGHT,\r
           BottomRow + SCROLL_ARROW_HEIGHT,\r
-          FIELD_TEXT | FIELD_BACKGROUND\r
+          PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
           );\r
 \r
         UiFreeRefreshList ();\r
@@ -1802,13 +1807,25 @@ UiDisplayMenu (
             gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);\r
           } else {\r
             if (Statement->Operand == EFI_IFR_SUBTITLE_OP) {\r
-              gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);\r
+              gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND);\r
             }\r
           }\r
 \r
           Width       = GetWidth (Statement, MenuOption->Handle);\r
           OriginalRow = Row;\r
 \r
+          if (Statement->Operand == EFI_IFR_REF_OP && MenuOption->Col >= 2) {\r
+            //\r
+            // Print Arrow for Goto button.\r
+            //\r
+            PrintAt (\r
+              MenuOption->Col - 2,\r
+              Row,\r
+              L"%c",\r
+              GEOMETRICSHAPE_RIGHT_TRIANGLE\r
+              );\r
+          }\r
+\r
           for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {\r
             if ((Temp == 0) && (Row <= BottomRow)) {\r
               PrintStringAt (MenuOption->Col, Row, OutputString);\r
@@ -1831,7 +1848,6 @@ UiDisplayMenu (
           Temp  = 0;\r
           Row   = OriginalRow;\r
 \r
-          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
           Status = ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
           if (EFI_ERROR (Status)) {\r
             //\r
@@ -1879,7 +1895,11 @@ UiDisplayMenu (
                 MenuRefreshEntry->Selection         = Selection;\r
                 MenuRefreshEntry->CurrentColumn     = MenuOption->OptCol;\r
                 MenuRefreshEntry->CurrentRow        = MenuOption->Row;\r
-                MenuRefreshEntry->CurrentAttribute  = FIELD_TEXT | FIELD_BACKGROUND;\r
+                if (MenuOption->GrayOut) {\r
+                  MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
+                } else {               \r
+                  MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
+                }\r
                 gMenuRefreshHead                    = MenuRefreshEntry;\r
               } else {\r
                 //\r
@@ -1897,7 +1917,11 @@ UiDisplayMenu (
                 MenuRefreshEntry->Selection         = Selection;\r
                 MenuRefreshEntry->CurrentColumn     = MenuOption->OptCol;\r
                 MenuRefreshEntry->CurrentRow        = MenuOption->Row;\r
-                MenuRefreshEntry->CurrentAttribute  = FIELD_TEXT | FIELD_BACKGROUND;\r
+                if (MenuOption->GrayOut) {\r
+                  MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
+                } else {               \r
+                  MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
+                }\r
               }\r
             }\r
 \r
@@ -1979,6 +2003,7 @@ UiDisplayMenu (
             Row = OriginalRow;\r
             FreePool (StringPtr);\r
           }\r
+          gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
 \r
           //\r
           // Need to handle the bottom of the display\r
@@ -2012,7 +2037,7 @@ UiDisplayMenu (
             L"%c",\r
             ARROW_UP\r
             );\r
-          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+          gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
         }\r
 \r
         if (DownArrow) {\r
@@ -2023,7 +2048,7 @@ UiDisplayMenu (
             L"%c",\r
             ARROW_DOWN\r
             );\r
-          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+          gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
         }\r
 \r
         MenuOption = NULL;\r
@@ -2037,6 +2062,10 @@ UiDisplayMenu (
       // NewPos:     Current menu option that need to hilight\r
       //\r
       ControlFlag = CfUpdateHelpString;\r
+      if (InitializedFlag) {\r
+        InitializedFlag = FALSE;\r
+        MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+      }\r
 \r
       //\r
       // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily\r
@@ -2099,7 +2128,7 @@ UiDisplayMenu (
           //\r
           gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
           ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
-          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+          gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
           if (OptionString != NULL) {\r
             if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||\r
                 (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)\r
@@ -2143,7 +2172,7 @@ UiDisplayMenu (
               if (MenuOption->GrayOut) {\r
                 gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);\r
               } else if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {\r
-                gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);\r
+                gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND);\r
               }\r
 \r
               OriginalRow = MenuOption->Row;\r
@@ -2164,28 +2193,23 @@ UiDisplayMenu (
               }\r
 \r
               MenuOption->Row = OriginalRow;\r
-              gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+              gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
             }\r
           }\r
         }\r
 \r
         //\r
-        // This is only possible if we entered this page and the first menu option is\r
-        // a "non-menu" item.  In that case, force it UiDown\r
+        // This is the current selected statement\r
         //\r
         MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+        Statement = MenuOption->ThisTag;\r
+        Selection->Statement = Statement;\r
         if (!IsSelectable (MenuOption)) {\r
-          ASSERT (ScreenOperation == UiNoOperation);\r
-          ScreenOperation = UiDown;\r
-          ControlFlag     = CfScreenOperation;\r
+          Repaint = SavedValue;\r
+          UpdateKeyHelp (Selection, MenuOption, FALSE);\r
           break;\r
         }\r
 \r
-        //\r
-        // This is the current selected statement\r
-        //\r
-        Statement = MenuOption->ThisTag;\r
-        Selection->Statement = Statement;\r
         //\r
         // Record highlight for current menu\r
         //\r
@@ -2194,7 +2218,7 @@ UiDisplayMenu (
         //\r
         // Set reverse attribute\r
         //\r
-        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);\r
+        gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor));\r
         gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
 \r
         //\r
@@ -2204,9 +2228,13 @@ UiDisplayMenu (
         //\r
         if (gMenuRefreshHead != NULL) {\r
           for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) {\r
-            MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;\r
+            if (MenuRefreshEntry->MenuOption->GrayOut) {\r
+              MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
+            } else {               \r
+              MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
+            }\r
             if (MenuRefreshEntry->MenuOption == MenuOption) {\r
-              MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT;\r
+              MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor);\r
             }\r
           }\r
         }\r
@@ -2278,7 +2306,7 @@ UiDisplayMenu (
         //\r
         // Clear reverse attribute\r
         //\r
-        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+        gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
       }\r
       //\r
       // Repaint flag will be used when process CfUpdateHelpString, so restore its value\r
@@ -2290,11 +2318,12 @@ UiDisplayMenu (
     case CfUpdateHelpString:\r
       ControlFlag = CfPrepareToReadKey;\r
 \r
-        if (Repaint || NewLine) {\r
+      if (Repaint || NewLine) {\r
         //\r
         // Don't print anything if it is a NULL help token\r
         //\r
-        if (MenuOption->ThisTag->Help == 0) {\r
+        ASSERT(MenuOption != NULL);\r
+        if (MenuOption->ThisTag->Help == 0 || !IsSelectable (MenuOption)) {\r
           StringPtr = L"\0";\r
         } else {\r
           StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);\r
@@ -2370,6 +2399,16 @@ UiDisplayMenu (
       //\r
       case '+':\r
       case '-':\r
+        //\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 (&gMenuOption)) {\r
+          ControlFlag = CfReadKey;\r
+          break;\r
+        }\r
+\r
+        ASSERT(MenuOption != NULL);\r
         Statement = MenuOption->ThisTag;\r
         if ((Statement->Operand == EFI_IFR_DATE_OP)\r
           || (Statement->Operand == EFI_IFR_TIME_OP)\r
@@ -2387,6 +2426,8 @@ UiDisplayMenu (
             //\r
             Repaint = TRUE;\r
             NewLine = TRUE;\r
+          } else {\r
+            Selection->Action = UI_ACTION_REFRESH_FORM;\r
           }\r
           if (OptionString != NULL) {\r
             FreePool (OptionString);\r
@@ -2405,6 +2446,16 @@ UiDisplayMenu (
 \r
       case ' ':\r
         if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {\r
+          //\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 (&gMenuOption)) {\r
+            ControlFlag = CfReadKey;\r
+            break;\r
+          }\r
+          \r
+          ASSERT(MenuOption != NULL);\r
           if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut) {\r
             ScreenOperation = UiSelect;\r
           }\r
@@ -2446,20 +2497,6 @@ UiDisplayMenu (
           ControlFlag = CfReadKey;\r
           break;\r
         }\r
-        //\r
-        // if there is nothing logical to place a cursor on, just move on to wait for a key.\r
-        //\r
-        for (Link = gMenuOption.ForwardLink; Link != &gMenuOption; Link = Link->ForwardLink) {\r
-          NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
-          if (IsSelectable (NextMenuOption)) {\r
-            break;\r
-          }\r
-        }\r
-\r
-        if (Link == &gMenuOption) {\r
-          ControlFlag = CfPrepareToReadKey;\r
-          break;\r
-        }\r
       }\r
 \r
       for (Index = 0;\r
@@ -2476,11 +2513,9 @@ UiDisplayMenu (
     case CfUiSelect:\r
       ControlFlag = CfCheckSelection;\r
 \r
+      ASSERT(MenuOption != NULL);\r
       Statement = MenuOption->ThisTag;\r
-      if ((Statement->Operand == EFI_IFR_TEXT_OP) ||\r
-          (Statement->Operand == EFI_IFR_DATE_OP) ||\r
-          (Statement->Operand == EFI_IFR_TIME_OP) ||\r
-          (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) {\r
+      if (Statement->Operand == EFI_IFR_TEXT_OP) {\r
         break;\r
       }\r
 \r
@@ -2508,6 +2543,7 @@ UiDisplayMenu (
           }\r
           BufferSize = StrLen (StringPtr) / 2;\r
           DevicePath = AllocatePool (BufferSize);\r
+          ASSERT (DevicePath != NULL);\r
 \r
           //\r
           // Convert from Device Path String to DevicePath Buffer in the reverse order.\r
@@ -2742,11 +2778,13 @@ UiDisplayMenu (
 \r
     case CfUiLeft:\r
       ControlFlag = CfCheckSelection;\r
+      ASSERT(MenuOption != NULL);\r
       if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
         if (MenuOption->Sequence != 0) {\r
           //\r
           // In the middle or tail of the Date/Time op-code set, go left.\r
           //\r
+          ASSERT(NewPos != NULL);\r
           NewPos = NewPos->BackLink;\r
         }\r
       }\r
@@ -2754,11 +2792,13 @@ UiDisplayMenu (
 \r
     case CfUiRight:\r
       ControlFlag = CfCheckSelection;\r
+      ASSERT(MenuOption != NULL);\r
       if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
         if (MenuOption->Sequence != 2) {\r
           //\r
           // In the middle or tail of the Date/Time op-code set, go left.\r
           //\r
+          ASSERT(NewPos != NULL);\r
           NewPos = NewPos->ForwardLink;\r
         }\r
       }\r
@@ -2767,94 +2807,85 @@ UiDisplayMenu (
     case CfUiUp:\r
       ControlFlag = CfCheckSelection;\r
 \r
-      SavedListEntry = TopOfScreen;\r
+      SavedListEntry = NewPos;\r
 \r
+      ASSERT(NewPos != NULL);\r
+      //\r
+      // Adjust Date/Time position before we advance forward.\r
+      //\r
+      AdjustDateAndTimePosition (TRUE, &NewPos);\r
       if (NewPos->BackLink != &gMenuOption) {\r
-        NewLine = TRUE;\r
-        //\r
-        // Adjust Date/Time position before we advance forward.\r
-        //\r
-        AdjustDateAndTimePosition (TRUE, &NewPos);\r
-\r
-        //\r
-        // Caution that we have already rewind to the top, don't go backward in this situation.\r
-        //\r
-        if (NewPos->BackLink != &gMenuOption) {\r
-          NewPos = NewPos->BackLink;\r
-        }\r
+        MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+        NewLine    = TRUE;\r
+        NewPos     = NewPos->BackLink;\r
 \r
         PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
         DistanceValue = PreviousMenuOption->Skip;\r
-\r
-        //\r
-        // Since the behavior of hitting the up arrow on a Date/Time op-code is intended\r
-        // to be one that back to the previous set of op-codes, we need to advance to the sencond\r
-        // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate\r
-        // checking can be done.\r
-        //\r
-        DistanceValue += AdjustDateAndTimePosition (TRUE, &NewPos);\r
-\r
-        //\r
-        // Check the previous menu entry to see if it was a zero-length advance.  If it was,\r
-        // don't worry about a redraw.\r
-        //\r
-        if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {\r
-          Repaint     = TRUE;\r
-          TopOfScreen = NewPos;\r
-        }\r
-\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
-          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
-          }\r
+        Difference    = 0;\r
+        if (MenuOption->Row >= DistanceValue + TopRow) {\r
+          Difference = MoveToNextStatement (TRUE, &NewPos, MenuOption->Row - TopRow - DistanceValue);\r
         }\r
+        NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+       \r
+        ASSERT (MenuOption != NULL);\r
         if (Difference < 0) {\r
           //\r
-          // We want to goto previous MenuOption, but finally we go down.\r
-          // it means that we hit the begining MenuOption that can be focused\r
-          // so we simply scroll to the top\r
+          // We hit the begining MenuOption that can be focused\r
+          // so we simply scroll to the top.\r
           //\r
-          if (SavedListEntry != gMenuOption.ForwardLink) {\r
+          if (TopOfScreen != gMenuOption.ForwardLink) {\r
             TopOfScreen = gMenuOption.ForwardLink;\r
             Repaint     = TRUE;\r
+          } else {\r
+            //\r
+            // Scroll up to the last page when we have arrived at top page.\r
+            //\r
+            NewPos          = &gMenuOption;\r
+            TopOfScreen     = &gMenuOption;\r
+            MenuOption      = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+            ScreenOperation = UiPageUp;\r
+            ControlFlag     = CfScreenOperation;\r
+            break;\r
           }\r
+        } else if (MenuOption->Row < TopRow + DistanceValue + Difference) {\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
+        } else if (!IsSelectable (NextMenuOption)) {\r
+          //\r
+          // Continue to go up until scroll to next page or the selectable option is found.\r
+          //\r
+          ScreenOperation = UiUp;\r
+          ControlFlag     = CfScreenOperation;\r
         }\r
 \r
         //\r
         // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
         //\r
         AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
-\r
+        AdjustDateAndTimePosition (TRUE, &NewPos);\r
+        MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
         UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
       } else {\r
-        SavedMenuOption = MenuOption;\r
-        MenuOption      = MENU_OPTION_FROM_LINK (NewPos);\r
-        if (!IsSelectable (MenuOption)) {\r
-          //\r
-          // If we are at the end of the list and sitting on a text op, we need to more forward\r
-          //\r
-          ScreenOperation = UiDown;\r
-          ControlFlag     = CfScreenOperation;\r
-          break;\r
-        }\r
-\r
-        MenuOption = SavedMenuOption;\r
+        //\r
+        // Scroll up to the last page.\r
+        //\r
+        NewPos          = &gMenuOption;\r
+        TopOfScreen     = &gMenuOption;\r
+        MenuOption      = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+        ScreenOperation = UiPageUp;\r
+        ControlFlag     = CfScreenOperation;\r
       }\r
       break;\r
 \r
     case CfUiPageUp:\r
       ControlFlag     = CfCheckSelection;\r
 \r
+      ASSERT(NewPos != NULL);\r
       if (NewPos->BackLink == &gMenuOption) {\r
         NewLine = FALSE;\r
         Repaint = FALSE;\r
@@ -2864,38 +2895,59 @@ UiDisplayMenu (
       NewLine   = TRUE;\r
       Repaint   = TRUE;\r
       Link      = TopOfScreen;\r
-      PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
-      Index = BottomRow;\r
+      Index     = BottomRow;\r
       while ((Index >= TopRow) && (Link->BackLink != &gMenuOption)) {\r
-        Index = Index - PreviousMenuOption->Skip;\r
         Link = Link->BackLink;\r
         PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+        if (Index < PreviousMenuOption->Skip) {\r
+          Index = 0;\r
+          break;\r
+        }\r
+        Index = Index - PreviousMenuOption->Skip;\r
       }\r
+      \r
+      if ((Link->BackLink == &gMenuOption) && (Index >= TopRow)) {\r
+        if (TopOfScreen == &gMenuOption) {\r
+          TopOfScreen = gMenuOption.ForwardLink;\r
+          NewPos      = gMenuOption.BackLink;\r
+          MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow);\r
+          Repaint = FALSE;\r
+        } else if (TopOfScreen != Link) {\r
+          TopOfScreen = Link;\r
+          NewPos      = Link;\r
+          MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+        } else {\r
+          //\r
+          // Finally we know that NewPos is the last MenuOption can be focused.\r
+          //\r
+          Repaint = FALSE;\r
+          NewPos  = Link;\r
+          MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+        }\r
+      } else {\r
+        if (Index + 1 < TopRow) {\r
+          //\r
+          // Back up the previous option.\r
+          //\r
+          Link = Link->ForwardLink;\r
+        }\r
 \r
-      TopOfScreen = Link;\r
-      Difference = MoveToNextStatement (TRUE, &Link);\r
-      if (Difference > 0) {\r
         //\r
-        // The focus MenuOption is above the TopOfScreen\r
+        // Move to the option in Next page.\r
         //\r
-        TopOfScreen = Link;\r
-      } else if (Difference < 0) {\r
+        if (TopOfScreen == &gMenuOption) {\r
+          NewPos = gMenuOption.BackLink;\r
+          MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow);\r
+        } else {\r
+          NewPos = Link;\r
+          MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+        }\r
+\r
         //\r
-        // This happens when there is no MenuOption can be focused from\r
-        // Current MenuOption to the first MenuOption\r
+        // There are more MenuOption needing scrolling up.\r
         //\r
-        TopOfScreen = gMenuOption.ForwardLink;\r
-      }\r
-      Index += Difference;\r
-      if (Index < TopRow) {\r
-        MenuOption = NULL;\r
-      }\r
-\r
-      if (NewPos == Link) {\r
-        Repaint = FALSE;\r
-        NewLine = FALSE;\r
-      } else {\r
-        NewPos = Link;\r
+        TopOfScreen = Link;\r
+        MenuOption  = NULL;\r
       }\r
 \r
       //\r
@@ -2909,6 +2961,7 @@ UiDisplayMenu (
     case CfUiPageDown:\r
       ControlFlag     = CfCheckSelection;\r
 \r
+      ASSERT (NewPos != NULL);\r
       if (NewPos->ForwardLink == &gMenuOption) {\r
         NewLine = FALSE;\r
         Repaint = FALSE;\r
@@ -2926,28 +2979,35 @@ UiDisplayMenu (
         NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
       }\r
 \r
-      Index += MoveToNextStatement (FALSE, &Link);\r
-      if (Index > BottomRow) {\r
+      if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow)) {\r
+        //\r
+        // Finally we know that NewPos is the last MenuOption can be focused.\r
         //\r
-        // There are more MenuOption needing scrolling\r
+        Repaint = FALSE;\r
+        MoveToNextStatement (TRUE, &Link, Index - TopRow);\r
+      } else {\r
+        if (Index - 1 > BottomRow) {\r
+          //\r
+          // Back up the previous option.\r
+          //\r
+          Link = Link->BackLink;\r
+        }\r
+        //\r
+        // There are more MenuOption needing scrolling down.\r
         //\r
         TopOfScreen = Link;\r
         MenuOption = NULL;\r
-      }\r
-      if (NewPos == Link && Index <= BottomRow) {\r
         //\r
-        // Finally we know that NewPos is the last MenuOption can be focused.\r
+        // Move to the option in Next page.\r
         //\r
-        NewLine = FALSE;\r
-        Repaint = FALSE;\r
-      } else {\r
-        NewPos  = Link;\r
+        MoveToNextStatement (FALSE, &Link, BottomRow - TopRow);\r
       }\r
 \r
       //\r
       // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
       // Don't do this when we are already in the last page.\r
       //\r
+      NewPos  = Link;\r
       AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
       AdjustDateAndTimePosition (TRUE, &NewPos);\r
       break;\r
@@ -2963,20 +3023,49 @@ UiDisplayMenu (
       // the Date/Time op-code.\r
       //\r
       SavedListEntry = NewPos;\r
-      DistanceValue  = AdjustDateAndTimePosition (FALSE, &NewPos);\r
+      AdjustDateAndTimePosition (FALSE, &NewPos);\r
 \r
       if (NewPos->ForwardLink != &gMenuOption) {\r
         MenuOption      = MENU_OPTION_FROM_LINK (NewPos);\r
         NewLine         = TRUE;\r
         NewPos          = NewPos->ForwardLink;\r
+\r
+        Difference      = 0;\r
+        if (BottomRow >= MenuOption->Row + MenuOption->Skip) {\r
+          Difference    = MoveToNextStatement (FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip);\r
+          //\r
+          // We hit the end of MenuOption that can be focused\r
+          // so we simply scroll to the first page.\r
+          //\r
+          if (Difference < 0) {\r
+            //\r
+            // Scroll to the first page.\r
+            //\r
+            if (TopOfScreen != gMenuOption.ForwardLink) {\r
+              TopOfScreen = gMenuOption.ForwardLink;\r
+              Repaint     = TRUE;\r
+              MenuOption  = NULL;\r
+            } else {\r
+              MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+            }\r
+            NewPos        = gMenuOption.ForwardLink;\r
+            MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+    \r
+            //\r
+            // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
+            //\r
+            AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+            AdjustDateAndTimePosition (TRUE, &NewPos);\r
+            break;\r
+          }\r
+        }\r
         NextMenuOption  = MENU_OPTION_FROM_LINK (NewPos);\r
 \r
-        DistanceValue  += NextMenuOption->Skip;\r
-        DistanceValue  += MoveToNextStatement (FALSE, &NewPos);\r
         //\r
         // An option might be multi-line, so we need to reflect that data in the overall skip value\r
         //\r
-        UpdateOptionSkipLines (Selection, NextMenuOption, &OptionString, SkipValue);\r
+        UpdateOptionSkipLines (Selection, NextMenuOption, &OptionString, (UINTN) SkipValue);\r
+        DistanceValue  = Difference + NextMenuOption->Skip;\r
 \r
         Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;\r
         if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&\r
@@ -3018,26 +3107,13 @@ UiDisplayMenu (
                 //\r
                 // If we have a remainder, skip that many more op-codes until we drain the remainder\r
                 //\r
-                for (;\r
-                     Difference >= (INTN) SavedMenuOption->Skip;\r
-                     Difference = Difference - (INTN) SavedMenuOption->Skip\r
-                    ) {\r
+                while (Difference >= (INTN) SavedMenuOption->Skip) {\r
                   //\r
                   // Since the Difference is greater than or equal to this op-code's skip value, skip it\r
                   //\r
+                  Difference      = Difference - (INTN) SavedMenuOption->Skip;\r
                   TopOfScreen     = TopOfScreen->ForwardLink;\r
                   SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
-                  if (Difference < (INTN) SavedMenuOption->Skip) {\r
-                    Difference = SavedMenuOption->Skip - Difference - 1;\r
-                    break;\r
-                  } else {\r
-                    if (Difference == (INTN) SavedMenuOption->Skip) {\r
-                      TopOfScreen     = TopOfScreen->ForwardLink;\r
-                      SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
-                      Difference      = SavedMenuOption->Skip - Difference;\r
-                      break;\r
-                    }\r
-                  }\r
                 }\r
                 //\r
                 // Since we will act on this op-code in the next routine, and increment the\r
@@ -3070,6 +3146,8 @@ UiDisplayMenu (
               } else {\r
                 SkipValue++;\r
               }\r
+            } else if (SavedMenuOption->Skip == 1) {\r
+              SkipValue   = 0;\r
             } else {\r
               SkipValue   = 0;\r
               TopOfScreen = TopOfScreen->ForwardLink;\r
@@ -3078,6 +3156,12 @@ UiDisplayMenu (
 \r
           Repaint       = TRUE;\r
           OldSkipValue  = SkipValue;\r
+        } else if (!IsSelectable (NextMenuOption)) {\r
+          //\r
+          // Continue to go down until scroll to next page or the selectable option is found.\r
+          //\r
+          ScreenOperation = UiDown;\r
+          ControlFlag     = CfScreenOperation;\r
         }\r
 \r
         MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
@@ -3085,23 +3169,26 @@ UiDisplayMenu (
         UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
 \r
       } else {\r
-        SavedMenuOption = MenuOption;\r
-        MenuOption      = MENU_OPTION_FROM_LINK (NewPos);\r
-        if (!IsSelectable (MenuOption)) {\r
-          //\r
-          // If we are at the end of the list and sitting on a text op, we need to more forward\r
-          //\r
-          ScreenOperation = UiUp;\r
-          ControlFlag     = CfScreenOperation;\r
-          break;\r
-        }\r
-\r
-        MenuOption = SavedMenuOption;\r
         //\r
-        // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
+        // Scroll to the first page.\r
         //\r
-        AdjustDateAndTimePosition (TRUE, &NewPos);\r
+        if (TopOfScreen != gMenuOption.ForwardLink) {\r
+          TopOfScreen = gMenuOption.ForwardLink;\r
+          Repaint     = TRUE;\r
+          MenuOption  = NULL;\r
+        } else {\r
+          MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+        }\r
+        NewLine       = TRUE;\r
+        NewPos        = gMenuOption.ForwardLink;\r
+        MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
       }\r
+\r
+      //\r
+      // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
+      //\r
+      AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+      AdjustDateAndTimePosition (TRUE, &NewPos);\r
       break;\r
 \r
     case CfUiSave:\r
@@ -3113,6 +3200,7 @@ UiDisplayMenu (
       Status = SubmitForm (Selection->FormSet, Selection->Form);\r
 \r
       if (!EFI_ERROR (Status)) {\r
+        ASSERT(MenuOption != NULL);\r
         UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
         UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE);\r
       } else {\r
@@ -3144,6 +3232,7 @@ UiDisplayMenu (
         // Show NV update flag on status bar\r
         //\r
         gNvUpdateRequired = TRUE;\r
+        gResetRequired = TRUE;\r
       }\r
       break;\r
 \r