summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c')
-rw-r--r--MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c2332
1 files changed, 1166 insertions, 1166 deletions
diff --git a/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c b/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c
index ef19319614..da6144b575 100644
--- a/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c
+++ b/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c
@@ -1,1166 +1,1166 @@
-/** @file
- The application to show the Boot Manager Menu.
-
-Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#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
- )
-{
- UINTN ScreenWidth;
- UINTN ScreenRows;
- CHAR16 *TurncateString;
- EFI_STATUS Status;
- UINTN ShowingLength;
-
- gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
-
- gST->ConOut->QueryMode (
- gST->ConOut,
- gST->ConOut->Mode->Mode,
- &ScreenWidth,
- &ScreenRows
- );
-
- if ((Column > (ScreenWidth - 1)) || (Row > (ScreenRows - 1))) {
- return 0;
- }
-
- if ((StrLen (String) + Column) > (ScreenWidth - 1)) {
- //
- // | - ScreenWidth - |
- // ...Column.....................
- // TurncateString length should leave one character for draw box and
- // require one character for string end.
- //
- ShowingLength = ScreenWidth - Column - 1;
- TurncateString = AllocatePool ((ShowingLength + 1) * sizeof (CHAR16));
-
- if (TurncateString == NULL) {
- return 0;
- }
-
- Status = StrnCpyS (TurncateString, ShowingLength + 1, String, ShowingLength - 3);
-
- if (EFI_ERROR (Status)) {
- FreePool (TurncateString);
- return 0;
- }
-
- *(TurncateString + ShowingLength - 3) = L'.';
- *(TurncateString + ShowingLength - 2) = L'.';
- *(TurncateString + ShowingLength - 1) = L'.';
- *(TurncateString + ShowingLength) = L'\0';
- ShowingLength = Print (L"%s", TurncateString);
- FreePool (TurncateString);
- return ShowingLength;
- } else {
- return Print (L"%s", String);
- }
-}
-
-/**
- Prints a character 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
- )
-{
- UINTN ScreenWidth;
- UINTN ScreenRows;
-
- gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
-
- gST->ConOut->QueryMode (
- gST->ConOut,
- gST->ConOut->Mode->Mode,
- &ScreenWidth,
- &ScreenRows
- );
-
- if ((Column > (ScreenWidth - 1)) || (Row > (ScreenRows - 1))) {
- return 0;
- }
-
- return Print (L"%c", Character);
-}
-
-/**
- Count the storage space of a Unicode string which uses current language 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 processed.
-
- @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;
- if (MaxStrWidth + 8 > Column) {
- BootMenuData->MenuScreen.Width = Column;
- } else {
- 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 function 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));
-}
-
-/**
- Return whether to ignore the boot option.
-
- @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION to check.
-
- @retval TRUE Ignore the boot option.
- @retval FALSE Do not ignore the boot option.
-**/
-BOOLEAN
-IgnoreBootOption (
- IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
- )
-{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
-
- //
- // Ignore myself.
- //
- Status = gBS->HandleProtocol (gImageHandle, &gEfiLoadedImageDevicePathProtocolGuid, (VOID **)&ImageDevicePath);
- ASSERT_EFI_ERROR (Status);
- if (CompareMem (BootOption->FilePath, ImageDevicePath, GetDevicePathSize (ImageDevicePath)) == 0) {
- return TRUE;
- }
-
- //
- // Do not ignore Boot Manager Menu.
- //
- if (IsBootManagerMenu (BootOption)) {
- return FALSE;
- }
-
- //
- // Ignore the hidden/inactive boot option.
- //
- if (((BootOption->Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption->Attributes & LOAD_OPTION_ACTIVE) == 0)) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- This function 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++) {
- if (IgnoreBootOption (&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 processed
-
- @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;
- }
-
- ASSERT (BootMenuData->ItemCount != 0);
- 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;
- }
-
- //
- // if Want Select and selected item isn't the same and doesn't re-draw selectable
- // items, clear select item
- //
- FirstItem = BootMenuData->ScrollBarControl.FirstItem;
- 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);
- }
-
- //
- // Print want to select item
- //
- 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);
-
- gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
- BootMenuData->SelectItem = WantSelectItem;
- return EFI_SUCCESS;
-}
-
-/**
- This function 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 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;
- 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 function 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++) {
- if (IgnoreBootOption (&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 required 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 required 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.
- //
- Status = PcdSet32S (PcdConOutColumn, mSetupTextModeColumn);
- ASSERT_EFI_ERROR (Status);
- Status = PcdSet32S (PcdConOutRow, mSetupTextModeRow);
- ASSERT_EFI_ERROR (Status);
- FreePool (Info);
- return EFI_SUCCESS;
- }
- }
- }
-
- if (Index == MaxTextMode) {
- //
- // If required 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.
- //
- Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution);
- ASSERT_EFI_ERROR (Status);
- Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution);
- ASSERT_EFI_ERROR (Status);
- Status = PcdSet32S (PcdConOutColumn, NewColumns);
- ASSERT_EFI_ERROR (Status);
- Status = PcdSet32S (PcdConOutRow, NewRows);
- ASSERT_EFI_ERROR (Status);
-
- //
- // 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;
-}
+/** @file
+ The application to show the Boot Manager Menu.
+
+Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+ )
+{
+ UINTN ScreenWidth;
+ UINTN ScreenRows;
+ CHAR16 *TurncateString;
+ EFI_STATUS Status;
+ UINTN ShowingLength;
+
+ gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
+
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &ScreenWidth,
+ &ScreenRows
+ );
+
+ if ((Column > (ScreenWidth - 1)) || (Row > (ScreenRows - 1))) {
+ return 0;
+ }
+
+ if ((StrLen (String) + Column) > (ScreenWidth - 1)) {
+ //
+ // | - ScreenWidth - |
+ // ...Column.....................
+ // TurncateString length should leave one character for draw box and
+ // require one character for string end.
+ //
+ ShowingLength = ScreenWidth - Column - 1;
+ TurncateString = AllocatePool ((ShowingLength + 1) * sizeof (CHAR16));
+
+ if (TurncateString == NULL) {
+ return 0;
+ }
+
+ Status = StrnCpyS (TurncateString, ShowingLength + 1, String, ShowingLength - 3);
+
+ if (EFI_ERROR (Status)) {
+ FreePool (TurncateString);
+ return 0;
+ }
+
+ *(TurncateString + ShowingLength - 3) = L'.';
+ *(TurncateString + ShowingLength - 2) = L'.';
+ *(TurncateString + ShowingLength - 1) = L'.';
+ *(TurncateString + ShowingLength) = L'\0';
+ ShowingLength = Print (L"%s", TurncateString);
+ FreePool (TurncateString);
+ return ShowingLength;
+ } else {
+ return Print (L"%s", String);
+ }
+}
+
+/**
+ Prints a character 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
+ )
+{
+ UINTN ScreenWidth;
+ UINTN ScreenRows;
+
+ gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
+
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &ScreenWidth,
+ &ScreenRows
+ );
+
+ if ((Column > (ScreenWidth - 1)) || (Row > (ScreenRows - 1))) {
+ return 0;
+ }
+
+ return Print (L"%c", Character);
+}
+
+/**
+ Count the storage space of a Unicode string which uses current language 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 processed.
+
+ @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;
+ if (MaxStrWidth + 8 > Column) {
+ BootMenuData->MenuScreen.Width = Column;
+ } else {
+ 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 function 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));
+}
+
+/**
+ Return whether to ignore the boot option.
+
+ @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION to check.
+
+ @retval TRUE Ignore the boot option.
+ @retval FALSE Do not ignore the boot option.
+**/
+BOOLEAN
+IgnoreBootOption (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
+
+ //
+ // Ignore myself.
+ //
+ Status = gBS->HandleProtocol (gImageHandle, &gEfiLoadedImageDevicePathProtocolGuid, (VOID **)&ImageDevicePath);
+ ASSERT_EFI_ERROR (Status);
+ if (CompareMem (BootOption->FilePath, ImageDevicePath, GetDevicePathSize (ImageDevicePath)) == 0) {
+ return TRUE;
+ }
+
+ //
+ // Do not ignore Boot Manager Menu.
+ //
+ if (IsBootManagerMenu (BootOption)) {
+ return FALSE;
+ }
+
+ //
+ // Ignore the hidden/inactive boot option.
+ //
+ if (((BootOption->Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption->Attributes & LOAD_OPTION_ACTIVE) == 0)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ This function 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++) {
+ if (IgnoreBootOption (&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 processed
+
+ @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;
+ }
+
+ ASSERT (BootMenuData->ItemCount != 0);
+ 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;
+ }
+
+ //
+ // if Want Select and selected item isn't the same and doesn't re-draw selectable
+ // items, clear select item
+ //
+ FirstItem = BootMenuData->ScrollBarControl.FirstItem;
+ 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);
+ }
+
+ //
+ // Print want to select item
+ //
+ 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);
+
+ gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
+ BootMenuData->SelectItem = WantSelectItem;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function 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 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;
+ 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 function 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++) {
+ if (IgnoreBootOption (&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 required 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 required 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.
+ //
+ Status = PcdSet32S (PcdConOutColumn, mSetupTextModeColumn);
+ ASSERT_EFI_ERROR (Status);
+ Status = PcdSet32S (PcdConOutRow, mSetupTextModeRow);
+ ASSERT_EFI_ERROR (Status);
+ FreePool (Info);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ if (Index == MaxTextMode) {
+ //
+ // If required 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.
+ //
+ Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution);
+ ASSERT_EFI_ERROR (Status);
+ Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution);
+ ASSERT_EFI_ERROR (Status);
+ Status = PcdSet32S (PcdConOutColumn, NewColumns);
+ ASSERT_EFI_ERROR (Status);
+ Status = PcdSet32S (PcdConOutRow, NewRows);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // 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;
+}