MdeModulePkg: Add BootManagerMenuApp.
authorRuiyu Ni <ruiyu.ni@intel.com>
Wed, 6 May 2015 04:49:30 +0000 (04:49 +0000)
committerniruiyu <niruiyu@Edk2>
Wed, 6 May 2015 04:49:30 +0000 (04:49 +0000)
BootManagerMenuApp only provides a very simple UI showing all the boot options
recorded by "BootOrder" and user can select any of them to boot.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17329 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c [new file with mode: 0644]
MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.h [new file with mode: 0644]
MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf [new file with mode: 0644]
MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuStrings.uni [new file with mode: 0644]
MdeModulePkg/MdeModulePkg.dsc

diff --git a/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c b/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c
new file mode 100644 (file)
index 0000000..c5a35c0
--- /dev/null
@@ -0,0 +1,1041 @@
+/** @file\r
+  The application to show the Boot Manager Menu.\r
+\r
+Copyright (c) 2011 - 2015, 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
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BootManagerMenu.h"\r
+\r
+EFI_HII_HANDLE gStringPackHandle;\r
+\r
+BOOLEAN   mModeInitialized = FALSE;\r
+\r
+//\r
+// Boot video resolution and text mode.\r
+//\r
+UINT32    mBootHorizontalResolution    = 0;\r
+UINT32    mBootVerticalResolution      = 0;\r
+UINT32    mBootTextModeColumn          = 0;\r
+UINT32    mBootTextModeRow             = 0;\r
+//\r
+// BIOS setup video resolution and text mode.\r
+//\r
+UINT32    mSetupTextModeColumn         = 0;\r
+UINT32    mSetupTextModeRow            = 0;\r
+UINT32    mSetupHorizontalResolution   = 0;\r
+UINT32    mSetupVerticalResolution     = 0;\r
+\r
+/**\r
+  Prints a unicode string to the default console, at\r
+  the supplied cursor position, using L"%s" format.\r
+\r
+  @param  Column     The cursor position to print the string at.\r
+  @param  Row        The cursor position to print the string at\r
+  @param  String     String pointer.\r
+\r
+  @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+PrintStringAt (\r
+  IN UINTN     Column,\r
+  IN UINTN     Row,\r
+  IN CHAR16    *String\r
+  )\r
+{\r
+\r
+  gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);\r
+  return Print (L"%s", String);\r
+}\r
+\r
+/**\r
+  Prints a chracter to the default console, at\r
+  the supplied cursor position, using L"%c" format.\r
+\r
+  @param  Column     The cursor position to print the string at.\r
+  @param  Row        The cursor position to print the string at.\r
+  @param  Character  Character to print.\r
+\r
+  @return Length of string printed to the console.\r
+\r
+**/\r
+UINTN\r
+PrintCharAt (\r
+  IN UINTN     Column,\r
+  IN UINTN     Row,\r
+  CHAR16       Character\r
+  )\r
+{\r
+  gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);\r
+  return Print (L"%c", Character);\r
+}\r
+\r
+/**\r
+  Count the storage space of a Unicode string which uses current lanaguag to get \r
+  from input string ID.\r
+\r
+  @param StringId          The input string to be counted.\r
+\r
+  @return Storage space for the input string.\r
+\r
+**/\r
+UINTN\r
+GetLineWidth (\r
+  IN EFI_STRING_ID       StringId\r
+  )\r
+{  \r
+  UINTN        Index;\r
+  UINTN        IncrementValue;\r
+  EFI_STRING   String;\r
+  UINTN        LineWidth;\r
+  \r
+  LineWidth = 0;\r
+  String = HiiGetString (gStringPackHandle, StringId, NULL); \r
+  \r
+  if (String != NULL) {\r
+    Index           = 0;\r
+    IncrementValue  = 1;\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++, LineWidth = LineWidth + IncrementValue\r
+          )\r
+        ;\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
+      //\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
+      }\r
+    } while (String[Index] != 0);   \r
+    FreePool (String);\r
+  }\r
+  \r
+  return LineWidth;  \r
+}\r
+\r
+/**\r
+  This function uses calculate the boot menu location, size and scroll bar information.\r
+\r
+  @param  BootMenuData            The boot menu data to be proccessed.\r
+\r
+  @return EFI_SUCCESS             calculate boot menu information successful.\r
+  @retval EFI_INVALID_PARAMETER   Input parameter is invalid   \r
+\r
+**/\r
+EFI_STATUS \r
+InitializeBootMenuScreen (\r
+  IN OUT  BOOT_MENU_POPUP_DATA  *BootMenuData\r
+  )\r
+{\r
+  UINTN         MaxStrWidth;\r
+  UINTN         StrWidth;\r
+  UINTN         Index;\r
+  UINTN         Column;\r
+  UINTN         Row;\r
+  UINTN         MaxPrintRows;\r
+  UINTN         UnSelectableItmes;\r
+\r
+  if (BootMenuData == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Get maximum string width\r
+  //\r
+  MaxStrWidth = 0;  \r
+  for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++) {    \r
+    StrWidth = GetLineWidth (BootMenuData->TitleToken[Index]);\r
+    MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth;\r
+  }\r
+   \r
+  for (Index = 0; Index < BootMenuData->ItemCount; Index++) {\r
+    StrWidth = GetLineWidth (BootMenuData->PtrTokens[Index]);\r
+    MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth; \r
+  } \r
+  \r
+  for (Index = 0; Index < HELP_TOKEN_COUNT; Index++) {    \r
+    StrWidth = GetLineWidth (BootMenuData->HelpToken[Index]);\r
+    MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth;\r
+  }  \r
+  //\r
+  // query current row and column to calculate boot menu location\r
+  //\r
+  gST->ConOut->QueryMode (\r
+                 gST->ConOut,\r
+                 gST->ConOut->Mode->Mode,\r
+                 &Column,\r
+                 &Row\r
+                 ); \r
+                 \r
+  MaxPrintRows = Row - 6;    \r
+  UnSelectableItmes = TITLE_TOKEN_COUNT + 2 + HELP_TOKEN_COUNT + 2;           \r
+  BootMenuData->MenuScreen.Width = MaxStrWidth + 8;\r
+  if (BootMenuData->ItemCount + UnSelectableItmes > MaxPrintRows) {\r
+    BootMenuData->MenuScreen.Height = MaxPrintRows;\r
+    BootMenuData->ScrollBarControl.HasScrollBar = TRUE;\r
+    BootMenuData->ScrollBarControl.ItemCountPerScreen = MaxPrintRows - UnSelectableItmes;\r
+    BootMenuData->ScrollBarControl.FirstItem = 0;\r
+    BootMenuData->ScrollBarControl.LastItem = MaxPrintRows - UnSelectableItmes - 1;\r
+  } else {\r
+    BootMenuData->MenuScreen.Height = BootMenuData->ItemCount + UnSelectableItmes;\r
+    BootMenuData->ScrollBarControl.HasScrollBar = FALSE;\r
+    BootMenuData->ScrollBarControl.ItemCountPerScreen = BootMenuData->ItemCount;\r
+    BootMenuData->ScrollBarControl.FirstItem = 0;\r
+    BootMenuData->ScrollBarControl.LastItem = BootMenuData->ItemCount - 1;    \r
+  }\r
+  BootMenuData->MenuScreen.StartCol = (Column -  BootMenuData->MenuScreen.Width) / 2;              \r
+  BootMenuData->MenuScreen.StartRow = (Row -  BootMenuData->MenuScreen.Height) / 2;  \r
+\r
+  return EFI_SUCCESS;\r
+}\r
+/**\r
+  This funciton uses check boot option is wheher setup application or no\r
+\r
+  @param   BootOption   Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.\r
+  \r
+  @retval  TRUE         This boot option is setup application.\r
+  @retval  FALSE        This boot options isn't setup application\r
+\r
+**/\r
+BOOLEAN\r
+IsBootManagerMenu (\r
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION    *BootOption\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION        BootManagerMenu;\r
+\r
+  Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);\r
+  if (!EFI_ERROR (Status)) {\r
+    EfiBootManagerFreeLoadOption (&BootManagerMenu);\r
+  }\r
+\r
+  return (BOOLEAN) (!EFI_ERROR (Status) && (BootOption->OptionNumber == BootManagerMenu.OptionNumber));\r
+}\r
\r
+\r
+/**\r
+  This funciton uses to initialize boot menu data\r
+\r
+  @param   BootOption             Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.\r
+  @param   BootOptionCount        Number of boot option.\r
+  @param   BootMenuData           The Input BootMenuData to be initialized.\r
+  \r
+  @retval  EFI_SUCCESS            Initialize boot menu data successful.\r
+  @retval  EFI_INVALID_PARAMETER  Input parameter is invalid.   \r
+\r
+**/\r
+EFI_STATUS\r
+InitializeBootMenuData (\r
+  IN   EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption,\r
+  IN   UINTN                         BootOptionCount,\r
+  OUT  BOOT_MENU_POPUP_DATA          *BootMenuData\r
+  )\r
+{\r
+  UINTN                         Index;\r
+  UINTN                         StrIndex;\r
+      \r
+  if (BootOption == NULL || BootMenuData == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  } \r
+  \r
+  BootMenuData->TitleToken[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_TITLE_STRING);\r
+  BootMenuData->PtrTokens     = AllocateZeroPool (BootOptionCount * sizeof (EFI_STRING_ID));\r
+  ASSERT (BootMenuData->PtrTokens != NULL);\r
+\r
+  //\r
+  // Skip boot option which created by BootNext Variable\r
+  //\r
+  for (StrIndex = 0, Index = 0; Index < BootOptionCount; Index++) {\r
+    //\r
+    // Don't display the hidden/inactive boot option except setup application.\r
+    //\r
+    if ((((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) &&\r
+        !IsBootManagerMenu (&BootOption[Index])) {      \r
+      continue;\r
+    }\r
+    ASSERT (BootOption[Index].Description != NULL);\r
+    BootMenuData->PtrTokens[StrIndex++] = HiiSetString (\r
+                                            gStringPackHandle, \r
+                                            0,\r
+                                            BootOption[Index].Description,\r
+                                            NULL\r
+                                            );\r
+  }\r
+\r
+  BootMenuData->ItemCount           = StrIndex;   \r
+  BootMenuData->HelpToken[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP1_STRING);\r
+  BootMenuData->HelpToken[1] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP2_STRING);\r
+  BootMenuData->HelpToken[2] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP3_STRING);\r
+  InitializeBootMenuScreen (BootMenuData);\r
+  BootMenuData->SelectItem = 0;\r
+  return EFI_SUCCESS;\r
+}    \r
+\r
+/**\r
+  This function uses input select item to highlight selected item\r
+  and set current selected item in BootMenuData\r
+\r
+  @param  WantSelectItem          The user wants to select item.\r
+  @param  BootMenuData            The boot menu data to be proccessed\r
+\r
+  @return EFI_SUCCESS             Highlight selected item and update current selected \r
+                                  item successful \r
+  @retval EFI_INVALID_PARAMETER   Input parameter is invalid   \r
+**/\r
+EFI_STATUS\r
+BootMenuSelectItem (\r
+  IN     UINTN                 WantSelectItem,\r
+  IN OUT BOOT_MENU_POPUP_DATA  *BootMenuData\r
+  )\r
+{\r
+  INT32                 SavedAttribute;\r
+  EFI_STRING            String;\r
+  UINTN                 StartCol;  \r
+  UINTN                 StartRow;\r
+  UINTN                 PrintCol;\r
+  UINTN                 PrintRow;\r
+  UINTN                 TopShadeNum;\r
+  UINTN                 LowShadeNum;\r
+  UINTN                 FirstItem;\r
+  UINTN                 LastItem;\r
+  UINTN                 ItemCountPerScreen;\r
+  UINTN                 Index;\r
+  BOOLEAN               RePaintItems;\r
+  \r
+  if (BootMenuData == NULL || WantSelectItem >= BootMenuData->ItemCount) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  SavedAttribute = gST->ConOut->Mode->Attribute;\r
+  RePaintItems = FALSE;\r
+  StartCol = BootMenuData->MenuScreen.StartCol;\r
+  StartRow = BootMenuData->MenuScreen.StartRow;\r
+  //\r
+  // print selectable items again and adjust scroll bar if need\r
+  //         \r
+  if (BootMenuData->ScrollBarControl.HasScrollBar &&\r
+      (WantSelectItem < BootMenuData->ScrollBarControl.FirstItem ||\r
+      WantSelectItem > BootMenuData->ScrollBarControl.LastItem ||\r
+      WantSelectItem == BootMenuData->SelectItem)) {          \r
+    ItemCountPerScreen   = BootMenuData->ScrollBarControl.ItemCountPerScreen;\r
+    //\r
+    // Set first item and last item\r
+    //     \r
+    if (WantSelectItem < BootMenuData->ScrollBarControl.FirstItem) {\r
+      BootMenuData->ScrollBarControl.FirstItem = WantSelectItem;\r
+      BootMenuData->ScrollBarControl.LastItem = WantSelectItem + ItemCountPerScreen - 1;  \r
+    } else if (WantSelectItem > BootMenuData->ScrollBarControl.LastItem) {\r
+      BootMenuData->ScrollBarControl.FirstItem = WantSelectItem - ItemCountPerScreen + 1; \r
+      BootMenuData->ScrollBarControl.LastItem = WantSelectItem;\r
+    }\r
+    gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);\r
+    FirstItem = BootMenuData->ScrollBarControl.FirstItem;\r
+    LastItem  = BootMenuData->ScrollBarControl.LastItem;\r
+    TopShadeNum = 0;\r
+    if (FirstItem != 0) {\r
+      TopShadeNum = (FirstItem * ItemCountPerScreen) / BootMenuData->ItemCount;\r
+      if ((FirstItem * ItemCountPerScreen) % BootMenuData->ItemCount != 0) {\r
+        TopShadeNum++;\r
+      }\r
+      PrintCol = StartCol  + BootMenuData->MenuScreen.Width - 2;\r
+      PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;  \r
+      for (Index = 0; Index < TopShadeNum; Index++, PrintRow++) {\r
+        PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_LIGHT_SHADE);\r
+      }\r
+    }\r
+    LowShadeNum = 0;\r
+    if (LastItem != BootMenuData->ItemCount - 1) {\r
+      LowShadeNum = ((BootMenuData->ItemCount - 1 - LastItem) * ItemCountPerScreen) / BootMenuData->ItemCount;\r
+      if (((BootMenuData->ItemCount - 1 - LastItem) * ItemCountPerScreen) % BootMenuData->ItemCount != 0) {\r
+        LowShadeNum++;\r
+      }\r
+      PrintCol = StartCol  + BootMenuData->MenuScreen.Width - 2;\r
+      PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + ItemCountPerScreen - LowShadeNum;  \r
+      for (Index = 0; Index < LowShadeNum; Index++, PrintRow++) {\r
+        PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_LIGHT_SHADE);\r
+      } \r
+    }\r
+    PrintCol = StartCol  + BootMenuData->MenuScreen.Width - 2;\r
+    PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + TopShadeNum;  \r
+    for (Index = TopShadeNum; Index < ItemCountPerScreen - LowShadeNum; Index++, PrintRow++) {\r
+      PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_FULL_BLOCK);\r
+    }      \r
+\r
+\r
+    //\r
+    // Clear selectable items first\r
+    //\r
+    PrintCol = StartCol  + 1;\r
+    PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;  \r
+    String = AllocateZeroPool ((BootMenuData->MenuScreen.Width - 2) * sizeof (CHAR16));\r
+    ASSERT (String != NULL);\r
+    for (Index = 0; Index < BootMenuData->MenuScreen.Width - 3; Index++) {\r
+      String[Index] = 0x20;\r
+    }      \r
+    for (Index = 0; Index < ItemCountPerScreen; Index++) {        \r
+      PrintStringAt (PrintCol, PrintRow + Index, String); \r
+    }\r
+    FreePool (String);\r
+    //\r
+    // print selectable items  \r
+    //\r
+    for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) {\r
+      String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index + FirstItem], NULL);\r
+      PrintStringAt (PrintCol, PrintRow, String);\r
+      FreePool (String); \r
+    }\r
+    RePaintItems = TRUE;\r
+  }\r
+  \r
+  //\r
+  // Print want to select item \r
+  //\r
+  FirstItem = BootMenuData->ScrollBarControl.FirstItem;\r
+  gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLACK);\r
+  String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[WantSelectItem], NULL);\r
+  PrintCol = StartCol  + 1;  \r
+  PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + WantSelectItem - FirstItem;  \r
+  PrintStringAt (PrintCol, PrintRow, String);\r
+  FreePool (String);\r
+  \r
+  //\r
+  // if Want Select and selected item isn't the same and doesn't re-draw selectable \r
+  // items, clear select item\r
+  //\r
+  if (WantSelectItem != BootMenuData->SelectItem && !RePaintItems) {\r
+    gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);\r
+    String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[BootMenuData->SelectItem], NULL);\r
+    PrintCol = StartCol  + 1;  \r
+    PrintRow = StartRow + 3 + BootMenuData->SelectItem - FirstItem;  \r
+    PrintStringAt (PrintCol, PrintRow, String);\r
+    FreePool (String);    \r
+  }\r
+\r
+  gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r
+  BootMenuData->SelectItem = WantSelectItem;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This funciton uses to draw boot popup menu\r
+\r
+  @param   BootMenuData           The Input BootMenuData to be processed.\r
+  \r
+  @retval  EFI_SUCCESS            Draw boot popup menu successful.\r
+\r
+**/\r
+EFI_STATUS \r
+DrawBootPopupMenu (\r
+  IN  BOOT_MENU_POPUP_DATA  *BootMenuData\r
+  )\r
+{\r
+  EFI_STRING            String;\r
+  UINTN                 Index;\r
+  UINTN                 Width;  \r
+  UINTN                 Height;\r
+  UINTN                 StartCol;\r
+  UINTN                 StartRow;\r
+  UINTN                 PrintRow;\r
+  UINTN                 PrintCol;\r
+  UINTN                 LineWidth;\r
+  INT32                 SavedAttribute; \r
+  UINTN                 ItemCountPerScreen;  \r
+\r
+  gST->ConOut->ClearScreen (gST->ConOut);\r
+  \r
+  SavedAttribute = gST->ConOut->Mode->Attribute;\r
+  gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);\r
+  Width    = BootMenuData->MenuScreen.Width;\r
+  Height   = BootMenuData->MenuScreen.Height;\r
+  StartCol = BootMenuData->MenuScreen.StartCol;\r
+  StartRow = BootMenuData->MenuScreen.StartRow;\r
+  ItemCountPerScreen = BootMenuData->ScrollBarControl.ItemCountPerScreen;\r
+  PrintRow = StartRow;\r
\r
+  gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+  //\r
+  // Draw Boot popup menu screen\r
+  //\r
+  PrintCharAt (StartCol, PrintRow, BOXDRAW_DOWN_RIGHT);\r
+  for (Index = 1; Index < Width - 1; Index++) {\r
+    PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); \r
+  }\r
+  PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_DOWN_LEFT);\r
+  \r
+  //\r
+  // Draw the screen for title\r
+  //\r
+  String = AllocateZeroPool ((Width - 1) * sizeof (CHAR16));\r
+  ASSERT (String != NULL);\r
+  for (Index = 0; Index < Width - 2; Index++) {\r
+    String[Index] = 0x20;\r
+  }\r
+\r
+  for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++) {\r
+    PrintRow++;\r
+    PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);  \r
+    PrintStringAt (StartCol + 1, PrintRow, String);\r
+    PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);\r
+  }\r
+  \r
+  PrintRow++;\r
+  PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL_RIGHT);\r
+  for (Index = 1; Index < Width - 1; Index++) {\r
+    PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); \r
+  }\r
+  PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL_LEFT);  \r
+  \r
+  //\r
+  // Draw screen for selectable items\r
+  //\r
+  for (Index = 0; Index < ItemCountPerScreen; Index++) {\r
+    PrintRow++;\r
+    PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);\r
+    PrintStringAt (StartCol + 1, PrintRow, String);\r
+    PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);\r
+  }  \r
+\r
+  PrintRow++;\r
+  PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL_RIGHT);\r
+  for (Index = 1; Index < Width - 1; Index++) {\r
+    PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); \r
+  }\r
+  PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL_LEFT);\r
+  \r
+  //\r
+  // Draw screen for Help\r
+  //\r
+  for (Index = 0; Index < HELP_TOKEN_COUNT; Index++) {\r
+    PrintRow++;\r
+    PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);\r
+    PrintStringAt (StartCol + 1, PrintRow, String);\r
+    PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);\r
+  }\r
+  FreePool (String);  \r
+    \r
+  PrintRow++;  \r
+  PrintCharAt (StartCol, PrintRow, BOXDRAW_UP_RIGHT);\r
+  for (Index = 1; Index < Width - 1; Index++) {\r
+    PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); \r
+  }\r
+  PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_UP_LEFT);        \r
+  \r
+  \r
+  //\r
+  // print title strings\r
+  //\r
+  PrintRow = StartRow + 1;\r
+  for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++, PrintRow++) {\r
+    String = HiiGetString (gStringPackHandle, BootMenuData->TitleToken[Index], NULL);\r
+    LineWidth = GetLineWidth (BootMenuData->TitleToken[Index]);      \r
+    PrintCol = StartCol + (Width - LineWidth) / 2;\r
+    PrintStringAt (PrintCol, PrintRow, String);\r
+    FreePool (String);\r
+  }\r
+  \r
+  //\r
+  // print selectable items\r
+  //\r
+  PrintCol = StartCol + 1;\r
+  PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;  \r
+  for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) {\r
+    String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index], NULL);\r
+    PrintStringAt (PrintCol, PrintRow, String);\r
+    FreePool (String); \r
+  }\r
+  \r
+  //\r
+  // Print Help strings\r
+  //\r
+  PrintRow++;\r
+  for (Index = 0; Index < HELP_TOKEN_COUNT; Index++, PrintRow++) {\r
+    String = HiiGetString (gStringPackHandle, BootMenuData->HelpToken[Index], NULL);\r
+    LineWidth = GetLineWidth (BootMenuData->HelpToken[Index]);\r
+    PrintCol = StartCol + (Width - LineWidth) / 2;\r
+    PrintStringAt (PrintCol, PrintRow, String);\r
+    FreePool (String);\r
+  }\r
+  \r
+  //\r
+  // Print scroll bar if has scroll bar\r
+  //\r
+  if (BootMenuData->ScrollBarControl.HasScrollBar) {\r
+    PrintCol = StartCol + Width - 2;\r
+    PrintRow = StartRow + 2; \r
+    PrintCharAt (PrintCol, PrintRow, GEOMETRICSHAPE_UP_TRIANGLE); \r
+    PrintCharAt (PrintCol + 1, PrintRow, BOXDRAW_VERTICAL); \r
+    PrintRow += (ItemCountPerScreen + 1);    \r
+    PrintCharAt (PrintCol, PrintRow, GEOMETRICSHAPE_DOWN_TRIANGLE);\r
+    PrintCharAt (PrintCol + 1, PrintRow, BOXDRAW_VERTICAL); \r
+  }  \r
+    \r
+  gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r
+  //\r
+  // Print Selected item\r
+  //\r
+  BootMenuSelectItem (BootMenuData->SelectItem, BootMenuData);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This funciton uses to boot from selected item \r
+\r
+  @param   BootOptions            Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.\r
+  @param   BootOptionCount        Number of boot option.\r
+  @param   SelectItem             Current selected item.\r
+**/\r
+VOID\r
+BootFromSelectOption (\r
+  IN   EFI_BOOT_MANAGER_LOAD_OPTION  *BootOptions,\r
+  IN   UINTN                         BootOptionCount, \r
+  IN   UINTN                         SelectItem\r
+  )\r
+{\r
+  UINTN                 ItemNum;\r
+  UINTN                 Index;\r
+\r
+  ASSERT (BootOptions != NULL);\r
+\r
+  for (ItemNum = 0, Index = 0; Index < BootOptionCount; Index++) {\r
+    //\r
+    // Don't display the hidden/inactive boot option except setup application.\r
+    //\r
+    if ((((BootOptions[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOptions[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) &&\r
+        !IsBootManagerMenu (&BootOptions[Index])) {      \r
+      continue;\r
+    }\r
+    if (ItemNum++ == SelectItem) {\r
+      EfiBootManagerBoot (&BootOptions[Index]);\r
+      break;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  This function will change video resolution and text mode\r
+  according to defined setup mode or defined boot mode  \r
+\r
+  @param  IsSetupMode   Indicate mode is changed to setup mode or boot mode. \r
+\r
+  @retval  EFI_SUCCESS  Mode is changed successfully.\r
+  @retval  Others             Mode failed to be changed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsSetConsoleMode (\r
+  BOOLEAN  IsSetupMode\r
+  )\r
+{\r
+  EFI_GRAPHICS_OUTPUT_PROTOCOL          *GraphicsOutput;\r
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL       *SimpleTextOut;\r
+  UINTN                                 SizeOfInfo;\r
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;\r
+  UINT32                                MaxGopMode;\r
+  UINT32                                MaxTextMode;\r
+  UINT32                                ModeNumber;\r
+  UINT32                                NewHorizontalResolution;\r
+  UINT32                                NewVerticalResolution;\r
+  UINT32                                NewColumns;\r
+  UINT32                                NewRows;\r
+  UINTN                                 HandleCount;\r
+  EFI_HANDLE                            *HandleBuffer;\r
+  EFI_STATUS                            Status;\r
+  UINTN                                 Index;\r
+  UINTN                                 CurrentColumn;\r
+  UINTN                                 CurrentRow;  \r
+\r
+  MaxGopMode  = 0;\r
+  MaxTextMode = 0;\r
+\r
+  //\r
+  // Get current video resolution and text mode \r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  gST->ConsoleOutHandle,\r
+                  &gEfiGraphicsOutputProtocolGuid,\r
+                  (VOID**)&GraphicsOutput\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    GraphicsOutput = NULL;\r
+  }\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  gST->ConsoleOutHandle,\r
+                  &gEfiSimpleTextOutProtocolGuid,\r
+                  (VOID**)&SimpleTextOut\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    SimpleTextOut = NULL;\r
+  }  \r
+\r
+  if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (IsSetupMode) {\r
+    //\r
+    // The requried resolution and text mode is setup mode.\r
+    //\r
+    NewHorizontalResolution = mSetupHorizontalResolution;\r
+    NewVerticalResolution   = mSetupVerticalResolution;\r
+    NewColumns              = mSetupTextModeColumn;\r
+    NewRows                 = mSetupTextModeRow;\r
+  } else {\r
+    //\r
+    // The required resolution and text mode is boot mode.\r
+    //\r
+    NewHorizontalResolution = mBootHorizontalResolution;\r
+    NewVerticalResolution   = mBootVerticalResolution;\r
+    NewColumns              = mBootTextModeColumn;\r
+    NewRows                 = mBootTextModeRow;   \r
+  }\r
+  \r
+  if (GraphicsOutput != NULL) {\r
+    MaxGopMode  = GraphicsOutput->Mode->MaxMode;\r
+  } \r
+\r
+  if (SimpleTextOut != NULL) {\r
+    MaxTextMode = SimpleTextOut->Mode->MaxMode;\r
+  }\r
+\r
+  //\r
+  // 1. If current video resolution is same with required video resolution,\r
+  //    video resolution need not be changed.\r
+  //    1.1. If current text mode is same with required text mode, text mode need not be changed.\r
+  //    1.2. If current text mode is different from required text mode, text mode need be changed.\r
+  // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.\r
+  //\r
+  for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {\r
+    Status = GraphicsOutput->QueryMode (\r
+                       GraphicsOutput,\r
+                       ModeNumber,\r
+                       &SizeOfInfo,\r
+                       &Info\r
+                       );\r
+    if (!EFI_ERROR (Status)) {\r
+      if ((Info->HorizontalResolution == NewHorizontalResolution) &&\r
+          (Info->VerticalResolution == NewVerticalResolution)) {\r
+        if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) &&\r
+            (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) {\r
+          //\r
+          // Current resolution is same with required resolution, check if text mode need be set\r
+          //\r
+          Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);\r
+          ASSERT_EFI_ERROR (Status);\r
+          if (CurrentColumn == NewColumns && CurrentRow == NewRows) {\r
+            //\r
+            // If current text mode is same with required text mode. Do nothing\r
+            //\r
+            FreePool (Info);\r
+            return EFI_SUCCESS;\r
+          } else {\r
+            //\r
+            // If current text mode is different from requried text mode.  Set new video mode\r
+            //\r
+            for (Index = 0; Index < MaxTextMode; Index++) {\r
+              Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);\r
+              if (!EFI_ERROR(Status)) {\r
+                if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) {\r
+                  //\r
+                  // Required text mode is supported, set it.\r
+                  //\r
+                  Status = SimpleTextOut->SetMode (SimpleTextOut, Index);\r
+                  ASSERT_EFI_ERROR (Status);\r
+                  //\r
+                  // Update text mode PCD.\r
+                  //\r
+                  PcdSet32 (PcdConOutColumn, mSetupTextModeColumn);\r
+                  PcdSet32 (PcdConOutRow, mSetupTextModeRow);\r
+                  FreePool (Info);\r
+                  return EFI_SUCCESS;\r
+                }\r
+              }\r
+            }\r
+            if (Index == MaxTextMode) {\r
+              //\r
+              // If requried text mode is not supported, return error.\r
+              //\r
+              FreePool (Info);\r
+              return EFI_UNSUPPORTED;\r
+            }\r
+          }\r
+        } else {\r
+          //\r
+          // If current video resolution is not same with the new one, set new video resolution.\r
+          // In this case, the driver which produces simple text out need be restarted.\r
+          //\r
+          Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);\r
+          if (!EFI_ERROR (Status)) {\r
+            FreePool (Info);\r
+            break;\r
+          }\r
+        }\r
+      }\r
+      FreePool (Info);\r
+    }\r
+  }\r
+\r
+  if (ModeNumber == MaxGopMode) {\r
+    //\r
+    // If the resolution is not supported, return error.\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Set PCD to Inform GraphicsConsole to change video resolution.\r
+  // Set PCD to Inform Consplitter to change text mode.\r
+  //\r
+  PcdSet32 (PcdVideoHorizontalResolution, NewHorizontalResolution);\r
+  PcdSet32 (PcdVideoVerticalResolution, NewVerticalResolution);\r
+  PcdSet32 (PcdConOutColumn, NewColumns);\r
+  PcdSet32 (PcdConOutRow, NewRows);\r
+  \r
+  \r
+  //\r
+  // Video mode is changed, so restart graphics console driver and higher level driver.\r
+  // Reconnect graphics console driver and higher level driver.\r
+  // Locate all the handles with GOP protocol and reconnect it.\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                   ByProtocol,\r
+                   &gEfiSimpleTextOutProtocolGuid,\r
+                   NULL,\r
+                   &HandleCount,\r
+                   &HandleBuffer\r
+                   );\r
+  if (!EFI_ERROR (Status)) {\r
+    for (Index = 0; Index < HandleCount; Index++) {\r
+      gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);\r
+    }\r
+    for (Index = 0; Index < HandleCount; Index++) {\r
+      gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
+    }\r
+    if (HandleBuffer != NULL) {\r
+      FreePool (HandleBuffer);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Display the boot popup menu and allow user select boot item.\r
+\r
+  @param   ImageHandle     The image handle.\r
+  @param   SystemTable     The system table.\r
+  \r
+  @retval  EFI_SUCCESS          Boot from selected boot option, and return success from boot option\r
+  @retval  EFI_NOT_FOUND        User select to enter setup or can not find boot option\r
+  \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerMenuEntry (\r
+  IN EFI_HANDLE                            ImageHandle,\r
+  IN EFI_SYSTEM_TABLE                      *SystemTable\r
+  )\r
+{\r
+  EFI_BOOT_MANAGER_LOAD_OPTION    *BootOption;\r
+  UINTN                           BootOptionCount;  \r
+  EFI_STATUS                      Status;\r
+  BOOT_MENU_POPUP_DATA            BootMenuData;\r
+  UINTN                           Index;\r
+  EFI_INPUT_KEY                   Key;\r
+  BOOLEAN                         ExitApplication;\r
+  UINTN                           SelectItem;\r
+  EFI_BOOT_LOGO_PROTOCOL          *BootLogo;\r
+  EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput;\r
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;\r
+  UINTN                           BootTextColumn;\r
+  UINTN                           BootTextRow;\r
+\r
+  //\r
+  // Set Logo status invalid when boot manager menu is launched\r
+  //\r
+  BootLogo = NULL;\r
+  Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);\r
+  if (!EFI_ERROR (Status) && (BootLogo != NULL)) {\r
+    Status = BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
+\r
+  gStringPackHandle = HiiAddPackages (\r
+                         &gEfiCallerIdGuid,\r
+                         gImageHandle,\r
+                         BootManagerMenuAppStrings,\r
+                         NULL\r
+                         );\r
+  ASSERT (gStringPackHandle != NULL);\r
+\r
+  //\r
+  // Connect all prior to entering the platform setup menu.\r
+  //\r
+  EfiBootManagerConnectAll ();\r
+  EfiBootManagerRefreshAllBootOption ();\r
+\r
+  BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
+\r
+  if (!mModeInitialized) {\r
+    //\r
+    // After the console is ready, get current video resolution \r
+    // and text mode before launching setup at first time.\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    gST->ConsoleOutHandle,\r
+                    &gEfiGraphicsOutputProtocolGuid,\r
+                    (VOID**)&GraphicsOutput\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      GraphicsOutput = NULL;\r
+    }\r
+    \r
+    Status = gBS->HandleProtocol (\r
+                    gST->ConsoleOutHandle,\r
+                    &gEfiSimpleTextOutProtocolGuid,\r
+                    (VOID**)&SimpleTextOut\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      SimpleTextOut = NULL;\r
+    }  \r
+\r
+    if (GraphicsOutput != NULL) {\r
+      //\r
+      // Get current video resolution and text mode.\r
+      //\r
+      mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+      mBootVerticalResolution   = GraphicsOutput->Mode->Info->VerticalResolution;\r
+    }\r
+\r
+    if (SimpleTextOut != NULL) {\r
+      Status = SimpleTextOut->QueryMode (\r
+                                SimpleTextOut,\r
+                                SimpleTextOut->Mode->Mode,\r
+                                &BootTextColumn,\r
+                                &BootTextRow\r
+                                );\r
+      mBootTextModeColumn = (UINT32)BootTextColumn;\r
+      mBootTextModeRow    = (UINT32)BootTextRow;\r
+    }\r
+\r
+    //\r
+    // Get user defined text mode for setup.\r
+    //  \r
+    mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);\r
+    mSetupVerticalResolution   = PcdGet32 (PcdSetupVideoVerticalResolution);      \r
+    mSetupTextModeColumn       = PcdGet32 (PcdSetupConOutColumn);\r
+    mSetupTextModeRow          = PcdGet32 (PcdSetupConOutRow);\r
+    mModeInitialized           = TRUE;\r
+  }\r
+  \r
+  //\r
+  // Set back to conventional setup resolution\r
+  //\r
+  BdsSetConsoleMode (TRUE);\r
+\r
+  //\r
+  // Initialize Boot menu data\r
+  //\r
+  Status = InitializeBootMenuData (BootOption, BootOptionCount, &BootMenuData);\r
+  //\r
+  // According to boot menu data to draw boot popup menu\r
+  //\r
+  DrawBootPopupMenu (&BootMenuData);\r
+  \r
+  //\r
+  // check user input to determine want to re-draw or boot from user selected item\r
+  //\r
+  ExitApplication = FALSE;\r
+  while (!ExitApplication) {\r
+    gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);\r
+    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+    if (!EFI_ERROR (Status)) {\r
+      switch (Key.UnicodeChar) {\r
+      \r
+      case CHAR_NULL:        \r
+        switch (Key.ScanCode) {          \r
+          \r
+        case SCAN_UP:\r
+          SelectItem = BootMenuData.SelectItem == 0 ? BootMenuData.ItemCount - 1 : BootMenuData.SelectItem - 1;\r
+          BootMenuSelectItem (SelectItem, &BootMenuData); \r
+          break;\r
+        \r
+        case SCAN_DOWN:\r
+          SelectItem = BootMenuData.SelectItem == BootMenuData.ItemCount - 1 ? 0 : BootMenuData.SelectItem + 1;\r
+          BootMenuSelectItem (SelectItem, &BootMenuData); \r
+          break;\r
+\r
+        case SCAN_ESC:\r
+          gST->ConOut->ClearScreen (gST->ConOut);\r
+          ExitApplication = TRUE;\r
+          //\r
+          // Set boot resolution for normal boot\r
+          //\r
+          BdsSetConsoleMode (FALSE);\r
+          break;\r
+          \r
+        default:\r
+          break;\r
+        }\r
+        break;\r
+        \r
+      case CHAR_CARRIAGE_RETURN:\r
+        gST->ConOut->ClearScreen (gST->ConOut);\r
+        //\r
+        // Set boot resolution for normal boot\r
+        //\r
+        BdsSetConsoleMode (FALSE);\r
+        BootFromSelectOption (BootOption, BootOptionCount, BootMenuData.SelectItem);\r
+        //\r
+        // Back to boot manager menu again, set back to setup resolution\r
+        //\r
+        BdsSetConsoleMode (TRUE);\r
+        DrawBootPopupMenu (&BootMenuData);\r
+        break;\r
+        \r
+      default:\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);\r
+  FreePool (BootMenuData.PtrTokens);\r
+\r
+  HiiRemovePackages (gStringPackHandle);\r
+\r
+  return Status;\r
+  \r
+}\r
diff --git a/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.h b/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.h
new file mode 100644 (file)
index 0000000..26d9a31
--- /dev/null
@@ -0,0 +1,60 @@
+/** @file\r
+  FrontPage routines to handle the callbacks and browser calls\r
+\r
+Copyright (c) 2004 - 2015, 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
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#ifndef _BOOT_MANAGER_MENU_H_\r
+#define _BOOT_MANAGER_MENU_H_\r
+\r
+#include <Uefi.h>\r
+#include <Guid/MdeModuleHii.h>\r
+#include <Library/UefiBootManagerLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/BootLogo.h>\r
+\r
+#define TITLE_TOKEN_COUNT   1\r
+#define HELP_TOKEN_COUNT    3\r
+\r
+typedef struct _BOOT_MENU_SCREEN {\r
+  UINTN        StartCol;\r
+  UINTN        StartRow;\r
+  UINTN        Width;\r
+  UINTN        Height;\r
+} BOOT_MENU_SCREEN; \r
+\r
+typedef struct _BOOT_MENU_SCROLL_BAR_CONTROL {\r
+  BOOLEAN      HasScrollBar;\r
+  UINTN        ItemCountPerScreen;\r
+  UINTN        FirstItem;\r
+  UINTN        LastItem;\r
+} BOOT_MENU_SCROLL_BAR_CONTROL; \r
+\r
+typedef struct _BOOT_MENU_POPUP_DATA {\r
+  EFI_STRING_ID                   TitleToken[TITLE_TOKEN_COUNT]; // Title string ID\r
+  UINTN                           ItemCount;                     // Selectable item count\r
+  EFI_STRING_ID                   *PtrTokens;                    // All of selectable items string ID\r
+  EFI_STRING_ID                   HelpToken[HELP_TOKEN_COUNT];   // All of help string ID\r
+  UINTN                           SelectItem;                    // Current select  item       \r
+  BOOT_MENU_SCREEN                MenuScreen;                    // Boot menu screen information\r
+  BOOT_MENU_SCROLL_BAR_CONTROL    ScrollBarControl;              // Boot menu scroll bar inoformation\r
+} BOOT_MENU_POPUP_DATA;\r
+\r
+#endif \r
+\r
diff --git a/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf b/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf
new file mode 100644 (file)
index 0000000..c92a156
--- /dev/null
@@ -0,0 +1,60 @@
+## @file\r
+#  The application to show the Boot Manager Menu.\r
+#  \r
+#  Copyright (c) 2011 - 2015, 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
+#  http://opensource.org/licenses/bsd-license.php\r
+#  \r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#  \r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = BootManagerMenuApp\r
+  FILE_GUID                      = EEC25BDC-67F2-4D95-B1D5-F81B2039D11D\r
+  MODULE_TYPE                    = UEFI_APPLICATION\r
+  VERSION_STRING                 = 1.0 \r
+  ENTRY_POINT                    = BootManagerMenuEntry\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  BootManagerMenu.c\r
+  BootManagerMenu.h\r
+  BootManagerMenuStrings.uni\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  HiiLib\r
+  DebugLib\r
+  UefiLib\r
+  MemoryAllocationLib\r
+  UefiBootServicesTableLib\r
+  UefiApplicationEntryPoint\r
+  UefiBootManagerLib\r
+  \r
+[Guids]\r
+\r
+[Protocols]\r
+  gEfiBootLogoProtocolGuid                      ## CONSUMES\r
+\r
+[Pcd]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow                          ## PRODUCES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn                       ## PRODUCES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution          ## PRODUCES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution            ## PRODUCES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn                  ## SOMETIMES_CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow                     ## SOMETIMES_CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution     ## SOMETIMES_CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution       ## SOMETIMES_CONSUMES
\ No newline at end of file
diff --git a/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuStrings.uni b/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuStrings.uni
new file mode 100644 (file)
index 0000000..04fdd30
Binary files /dev/null and b/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuStrings.uni differ
index 1573942..14418f9 100644 (file)
   MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf\r
 \r
   MdeModulePkg/Universal/BdsDxe/BdsDxe.inf\r
+  MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf\r
   MdeModulePkg/Universal/CapsulePei/CapsulePei.inf\r
   MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf\r
   MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf\r