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