2 The application to show the Boot Manager Menu.
4 Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "BootManagerMenu.h"
11 EFI_HII_HANDLE gStringPackHandle
;
13 BOOLEAN mModeInitialized
= FALSE
;
16 // Boot video resolution and text mode.
18 UINT32 mBootHorizontalResolution
= 0;
19 UINT32 mBootVerticalResolution
= 0;
20 UINT32 mBootTextModeColumn
= 0;
21 UINT32 mBootTextModeRow
= 0;
23 // BIOS setup video resolution and text mode.
25 UINT32 mSetupTextModeColumn
= 0;
26 UINT32 mSetupTextModeRow
= 0;
27 UINT32 mSetupHorizontalResolution
= 0;
28 UINT32 mSetupVerticalResolution
= 0;
31 Prints a unicode string to the default console, at
32 the supplied cursor position, using L"%s" format.
34 @param Column The cursor position to print the string at.
35 @param Row The cursor position to print the string at
36 @param String String pointer.
38 @return Length of string printed to the console
50 CHAR16
*TurncateString
;
54 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, Column
, Row
);
56 gST
->ConOut
->QueryMode (
58 gST
->ConOut
->Mode
->Mode
,
63 if ((Column
> (ScreenWidth
- 1)) || (Row
> (ScreenRows
- 1))) {
67 if ((StrLen (String
) + Column
) > (ScreenWidth
- 1)) {
69 // | - ScreenWidth - |
70 // ...Column.....................
71 // TurncateString length should leave one character for draw box and
72 // require one character for string end.
74 ShowingLength
= ScreenWidth
- Column
- 1;
75 TurncateString
= AllocatePool ((ShowingLength
+ 1) * sizeof (CHAR16
));
77 if (TurncateString
== NULL
) {
81 Status
= StrnCpyS (TurncateString
, ShowingLength
+ 1, String
, ShowingLength
- 3);
83 if (EFI_ERROR (Status
)) {
84 FreePool (TurncateString
);
88 *(TurncateString
+ ShowingLength
- 3) = L
'.';
89 *(TurncateString
+ ShowingLength
- 2) = L
'.';
90 *(TurncateString
+ ShowingLength
- 1) = L
'.';
91 *(TurncateString
+ ShowingLength
) = L
'\0';
92 ShowingLength
= Print (L
"%s", TurncateString
);
93 FreePool (TurncateString
);
96 return Print (L
"%s", String
);
101 Prints a character to the default console, at
102 the supplied cursor position, using L"%c" format.
104 @param Column The cursor position to print the string at.
105 @param Row The cursor position to print the string at.
106 @param Character Character to print.
108 @return Length of string printed to the console.
121 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, Column
, Row
);
123 gST
->ConOut
->QueryMode (
125 gST
->ConOut
->Mode
->Mode
,
130 if ((Column
> (ScreenWidth
- 1)) || (Row
> (ScreenRows
- 1))) {
134 return Print (L
"%c", Character
);
138 Count the storage space of a Unicode string which uses current language to get
139 from input string ID.
141 @param StringId The input string to be counted.
143 @return Storage space for the input string.
148 IN EFI_STRING_ID StringId
152 UINTN IncrementValue
;
157 String
= HiiGetString (gStringPackHandle
, StringId
, NULL
);
159 if (String
!= NULL
) {
165 // Advance to the null-terminator or to the first width directive
168 (String
[Index
] != NARROW_CHAR
) && (String
[Index
] != WIDE_CHAR
) && (String
[Index
] != 0);
169 Index
++, LineWidth
= LineWidth
+ IncrementValue
175 // We hit the null-terminator, we now have a count
177 if (String
[Index
] == 0) {
182 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
183 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
185 if (String
[Index
] == NARROW_CHAR
) {
187 // Skip to the next character
193 // Skip to the next character
198 } while (String
[Index
] != 0);
207 This function uses calculate the boot menu location, size and scroll bar information.
209 @param BootMenuData The boot menu data to be processed.
211 @return EFI_SUCCESS calculate boot menu information successful.
212 @retval EFI_INVALID_PARAMETER Input parameter is invalid
216 InitializeBootMenuScreen (
217 IN OUT BOOT_MENU_POPUP_DATA
*BootMenuData
226 UINTN UnSelectableItmes
;
228 if (BootMenuData
== NULL
) {
229 return EFI_INVALID_PARAMETER
;
233 // Get maximum string width
236 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++) {
237 StrWidth
= GetLineWidth (BootMenuData
->TitleToken
[Index
]);
238 MaxStrWidth
= MaxStrWidth
> StrWidth
? MaxStrWidth
: StrWidth
;
241 for (Index
= 0; Index
< BootMenuData
->ItemCount
; Index
++) {
242 StrWidth
= GetLineWidth (BootMenuData
->PtrTokens
[Index
]);
243 MaxStrWidth
= MaxStrWidth
> StrWidth
? MaxStrWidth
: StrWidth
;
246 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++) {
247 StrWidth
= GetLineWidth (BootMenuData
->HelpToken
[Index
]);
248 MaxStrWidth
= MaxStrWidth
> StrWidth
? MaxStrWidth
: StrWidth
;
252 // query current row and column to calculate boot menu location
254 gST
->ConOut
->QueryMode (
256 gST
->ConOut
->Mode
->Mode
,
261 MaxPrintRows
= Row
- 6;
262 UnSelectableItmes
= TITLE_TOKEN_COUNT
+ 2 + HELP_TOKEN_COUNT
+ 2;
263 if (MaxStrWidth
+ 8 > Column
) {
264 BootMenuData
->MenuScreen
.Width
= Column
;
266 BootMenuData
->MenuScreen
.Width
= MaxStrWidth
+ 8;
269 if (BootMenuData
->ItemCount
+ UnSelectableItmes
> MaxPrintRows
) {
270 BootMenuData
->MenuScreen
.Height
= MaxPrintRows
;
271 BootMenuData
->ScrollBarControl
.HasScrollBar
= TRUE
;
272 BootMenuData
->ScrollBarControl
.ItemCountPerScreen
= MaxPrintRows
- UnSelectableItmes
;
273 BootMenuData
->ScrollBarControl
.FirstItem
= 0;
274 BootMenuData
->ScrollBarControl
.LastItem
= MaxPrintRows
- UnSelectableItmes
- 1;
276 BootMenuData
->MenuScreen
.Height
= BootMenuData
->ItemCount
+ UnSelectableItmes
;
277 BootMenuData
->ScrollBarControl
.HasScrollBar
= FALSE
;
278 BootMenuData
->ScrollBarControl
.ItemCountPerScreen
= BootMenuData
->ItemCount
;
279 BootMenuData
->ScrollBarControl
.FirstItem
= 0;
280 BootMenuData
->ScrollBarControl
.LastItem
= BootMenuData
->ItemCount
- 1;
283 BootMenuData
->MenuScreen
.StartCol
= (Column
- BootMenuData
->MenuScreen
.Width
) / 2;
284 BootMenuData
->MenuScreen
.StartRow
= (Row
- BootMenuData
->MenuScreen
.Height
) / 2;
290 This function uses check boot option is wheher setup application or no
292 @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
294 @retval TRUE This boot option is setup application.
295 @retval FALSE This boot options isn't setup application
300 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
304 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
306 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
307 if (!EFI_ERROR (Status
)) {
308 EfiBootManagerFreeLoadOption (&BootManagerMenu
);
311 return (BOOLEAN
)(!EFI_ERROR (Status
) && (BootOption
->OptionNumber
== BootManagerMenu
.OptionNumber
));
315 Return whether to ignore the boot option.
317 @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION to check.
319 @retval TRUE Ignore the boot option.
320 @retval FALSE Do not ignore the boot option.
324 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
328 EFI_DEVICE_PATH_PROTOCOL
*ImageDevicePath
;
333 Status
= gBS
->HandleProtocol (gImageHandle
, &gEfiLoadedImageDevicePathProtocolGuid
, (VOID
**)&ImageDevicePath
);
334 ASSERT_EFI_ERROR (Status
);
335 if (CompareMem (BootOption
->FilePath
, ImageDevicePath
, GetDevicePathSize (ImageDevicePath
)) == 0) {
340 // Do not ignore Boot Manager Menu.
342 if (IsBootManagerMenu (BootOption
)) {
347 // Ignore the hidden/inactive boot option.
349 if (((BootOption
->Attributes
& LOAD_OPTION_HIDDEN
) != 0) || ((BootOption
->Attributes
& LOAD_OPTION_ACTIVE
) == 0)) {
357 This function uses to initialize boot menu data
359 @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
360 @param BootOptionCount Number of boot option.
361 @param BootMenuData The Input BootMenuData to be initialized.
363 @retval EFI_SUCCESS Initialize boot menu data successful.
364 @retval EFI_INVALID_PARAMETER Input parameter is invalid.
368 InitializeBootMenuData (
369 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
,
370 IN UINTN BootOptionCount
,
371 OUT BOOT_MENU_POPUP_DATA
*BootMenuData
377 if ((BootOption
== NULL
) || (BootMenuData
== NULL
)) {
378 return EFI_INVALID_PARAMETER
;
381 BootMenuData
->TitleToken
[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_TITLE_STRING
);
382 BootMenuData
->PtrTokens
= AllocateZeroPool (BootOptionCount
* sizeof (EFI_STRING_ID
));
383 ASSERT (BootMenuData
->PtrTokens
!= NULL
);
386 // Skip boot option which created by BootNext Variable
388 for (StrIndex
= 0, Index
= 0; Index
< BootOptionCount
; Index
++) {
389 if (IgnoreBootOption (&BootOption
[Index
])) {
393 ASSERT (BootOption
[Index
].Description
!= NULL
);
394 BootMenuData
->PtrTokens
[StrIndex
++] = HiiSetString (
397 BootOption
[Index
].Description
,
402 BootMenuData
->ItemCount
= StrIndex
;
403 BootMenuData
->HelpToken
[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP1_STRING
);
404 BootMenuData
->HelpToken
[1] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP2_STRING
);
405 BootMenuData
->HelpToken
[2] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP3_STRING
);
406 InitializeBootMenuScreen (BootMenuData
);
407 BootMenuData
->SelectItem
= 0;
412 This function uses input select item to highlight selected item
413 and set current selected item in BootMenuData
415 @param WantSelectItem The user wants to select item.
416 @param BootMenuData The boot menu data to be processed
418 @return EFI_SUCCESS Highlight selected item and update current selected
420 @retval EFI_INVALID_PARAMETER Input parameter is invalid
424 IN UINTN WantSelectItem
,
425 IN OUT BOOT_MENU_POPUP_DATA
*BootMenuData
428 INT32 SavedAttribute
;
438 UINTN ItemCountPerScreen
;
440 BOOLEAN RePaintItems
;
442 if ((BootMenuData
== NULL
) || (WantSelectItem
>= BootMenuData
->ItemCount
)) {
443 return EFI_INVALID_PARAMETER
;
446 ASSERT (BootMenuData
->ItemCount
!= 0);
447 SavedAttribute
= gST
->ConOut
->Mode
->Attribute
;
448 RePaintItems
= FALSE
;
449 StartCol
= BootMenuData
->MenuScreen
.StartCol
;
450 StartRow
= BootMenuData
->MenuScreen
.StartRow
;
452 // print selectable items again and adjust scroll bar if need
454 if (BootMenuData
->ScrollBarControl
.HasScrollBar
&&
455 ((WantSelectItem
< BootMenuData
->ScrollBarControl
.FirstItem
) ||
456 (WantSelectItem
> BootMenuData
->ScrollBarControl
.LastItem
) ||
457 (WantSelectItem
== BootMenuData
->SelectItem
)))
459 ItemCountPerScreen
= BootMenuData
->ScrollBarControl
.ItemCountPerScreen
;
461 // Set first item and last item
463 if (WantSelectItem
< BootMenuData
->ScrollBarControl
.FirstItem
) {
464 BootMenuData
->ScrollBarControl
.FirstItem
= WantSelectItem
;
465 BootMenuData
->ScrollBarControl
.LastItem
= WantSelectItem
+ ItemCountPerScreen
- 1;
466 } else if (WantSelectItem
> BootMenuData
->ScrollBarControl
.LastItem
) {
467 BootMenuData
->ScrollBarControl
.FirstItem
= WantSelectItem
- ItemCountPerScreen
+ 1;
468 BootMenuData
->ScrollBarControl
.LastItem
= WantSelectItem
;
471 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
472 FirstItem
= BootMenuData
->ScrollBarControl
.FirstItem
;
473 LastItem
= BootMenuData
->ScrollBarControl
.LastItem
;
475 if (FirstItem
!= 0) {
476 TopShadeNum
= (FirstItem
* ItemCountPerScreen
) / BootMenuData
->ItemCount
;
477 if ((FirstItem
* ItemCountPerScreen
) % BootMenuData
->ItemCount
!= 0) {
481 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
482 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
483 for (Index
= 0; Index
< TopShadeNum
; Index
++, PrintRow
++) {
484 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_LIGHT_SHADE
);
489 if (LastItem
!= BootMenuData
->ItemCount
- 1) {
490 LowShadeNum
= ((BootMenuData
->ItemCount
- 1 - LastItem
) * ItemCountPerScreen
) / BootMenuData
->ItemCount
;
491 if (((BootMenuData
->ItemCount
- 1 - LastItem
) * ItemCountPerScreen
) % BootMenuData
->ItemCount
!= 0) {
495 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
496 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + ItemCountPerScreen
- LowShadeNum
;
497 for (Index
= 0; Index
< LowShadeNum
; Index
++, PrintRow
++) {
498 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_LIGHT_SHADE
);
502 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
503 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + TopShadeNum
;
504 for (Index
= TopShadeNum
; Index
< ItemCountPerScreen
- LowShadeNum
; Index
++, PrintRow
++) {
505 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_FULL_BLOCK
);
509 // Clear selectable items first
511 PrintCol
= StartCol
+ 1;
512 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
513 String
= AllocateZeroPool ((BootMenuData
->MenuScreen
.Width
- 2) * sizeof (CHAR16
));
514 ASSERT (String
!= NULL
);
515 for (Index
= 0; Index
< BootMenuData
->MenuScreen
.Width
- 3; Index
++) {
516 String
[Index
] = 0x20;
519 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++) {
520 PrintStringAt (PrintCol
, PrintRow
+ Index
, String
);
525 // print selectable items
527 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++, PrintRow
++) {
528 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[Index
+ FirstItem
], NULL
);
529 PrintStringAt (PrintCol
, PrintRow
, String
);
537 // if Want Select and selected item isn't the same and doesn't re-draw selectable
538 // items, clear select item
540 FirstItem
= BootMenuData
->ScrollBarControl
.FirstItem
;
541 if ((WantSelectItem
!= BootMenuData
->SelectItem
) && !RePaintItems
) {
542 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
543 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[BootMenuData
->SelectItem
], NULL
);
544 PrintCol
= StartCol
+ 1;
545 PrintRow
= StartRow
+ 3 + BootMenuData
->SelectItem
- FirstItem
;
546 PrintStringAt (PrintCol
, PrintRow
, String
);
551 // Print want to select item
553 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLACK
);
554 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[WantSelectItem
], NULL
);
555 PrintCol
= StartCol
+ 1;
556 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + WantSelectItem
- FirstItem
;
557 PrintStringAt (PrintCol
, PrintRow
, String
);
560 gST
->ConOut
->SetAttribute (gST
->ConOut
, SavedAttribute
);
561 BootMenuData
->SelectItem
= WantSelectItem
;
566 This function uses to draw boot popup menu
568 @param BootMenuData The Input BootMenuData to be processed.
570 @retval EFI_SUCCESS Draw boot popup menu successful.
575 IN BOOT_MENU_POPUP_DATA
*BootMenuData
586 INT32 SavedAttribute
;
587 UINTN ItemCountPerScreen
;
589 gST
->ConOut
->ClearScreen (gST
->ConOut
);
591 SavedAttribute
= gST
->ConOut
->Mode
->Attribute
;
592 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
593 Width
= BootMenuData
->MenuScreen
.Width
;
594 StartCol
= BootMenuData
->MenuScreen
.StartCol
;
595 StartRow
= BootMenuData
->MenuScreen
.StartRow
;
596 ItemCountPerScreen
= BootMenuData
->ScrollBarControl
.ItemCountPerScreen
;
599 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
601 // Draw Boot popup menu screen
603 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_DOWN_RIGHT
);
604 for (Index
= 1; Index
< Width
- 1; Index
++) {
605 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
608 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_DOWN_LEFT
);
611 // Draw the screen for title
613 String
= AllocateZeroPool ((Width
- 1) * sizeof (CHAR16
));
614 ASSERT (String
!= NULL
);
615 for (Index
= 0; Index
< Width
- 2; Index
++) {
616 String
[Index
] = 0x20;
619 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++) {
621 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
622 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
623 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
627 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL_RIGHT
);
628 for (Index
= 1; Index
< Width
- 1; Index
++) {
629 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
632 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL_LEFT
);
635 // Draw screen for selectable items
637 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++) {
639 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
640 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
641 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
645 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL_RIGHT
);
646 for (Index
= 1; Index
< Width
- 1; Index
++) {
647 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
650 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL_LEFT
);
653 // Draw screen for Help
655 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++) {
657 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
658 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
659 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
665 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_UP_RIGHT
);
666 for (Index
= 1; Index
< Width
- 1; Index
++) {
667 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
670 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_UP_LEFT
);
673 // print title strings
675 PrintRow
= StartRow
+ 1;
676 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++, PrintRow
++) {
677 String
= HiiGetString (gStringPackHandle
, BootMenuData
->TitleToken
[Index
], NULL
);
678 LineWidth
= GetLineWidth (BootMenuData
->TitleToken
[Index
]);
679 PrintCol
= StartCol
+ (Width
- LineWidth
) / 2;
680 PrintStringAt (PrintCol
, PrintRow
, String
);
685 // print selectable items
687 PrintCol
= StartCol
+ 1;
688 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
689 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++, PrintRow
++) {
690 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[Index
], NULL
);
691 PrintStringAt (PrintCol
, PrintRow
, String
);
696 // Print Help strings
699 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++, PrintRow
++) {
700 String
= HiiGetString (gStringPackHandle
, BootMenuData
->HelpToken
[Index
], NULL
);
701 LineWidth
= GetLineWidth (BootMenuData
->HelpToken
[Index
]);
702 PrintCol
= StartCol
+ (Width
- LineWidth
) / 2;
703 PrintStringAt (PrintCol
, PrintRow
, String
);
708 // Print scroll bar if has scroll bar
710 if (BootMenuData
->ScrollBarControl
.HasScrollBar
) {
711 PrintCol
= StartCol
+ Width
- 2;
712 PrintRow
= StartRow
+ 2;
713 PrintCharAt (PrintCol
, PrintRow
, GEOMETRICSHAPE_UP_TRIANGLE
);
714 PrintCharAt (PrintCol
+ 1, PrintRow
, BOXDRAW_VERTICAL
);
715 PrintRow
+= (ItemCountPerScreen
+ 1);
716 PrintCharAt (PrintCol
, PrintRow
, GEOMETRICSHAPE_DOWN_TRIANGLE
);
717 PrintCharAt (PrintCol
+ 1, PrintRow
, BOXDRAW_VERTICAL
);
720 gST
->ConOut
->SetAttribute (gST
->ConOut
, SavedAttribute
);
722 // Print Selected item
724 BootMenuSelectItem (BootMenuData
->SelectItem
, BootMenuData
);
729 This function uses to boot from selected item
731 @param BootOptions Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
732 @param BootOptionCount Number of boot option.
733 @param SelectItem Current selected item.
736 BootFromSelectOption (
737 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
,
738 IN UINTN BootOptionCount
,
745 ASSERT (BootOptions
!= NULL
);
747 for (ItemNum
= 0, Index
= 0; Index
< BootOptionCount
; Index
++) {
748 if (IgnoreBootOption (&BootOptions
[Index
])) {
752 if (ItemNum
++ == SelectItem
) {
753 EfiBootManagerBoot (&BootOptions
[Index
]);
760 This function will change video resolution and text mode
761 according to defined setup mode or defined boot mode
763 @param IsSetupMode Indicate mode is changed to setup mode or boot mode.
765 @retval EFI_SUCCESS Mode is changed successfully.
766 @retval Others Mode failed to be changed.
775 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
776 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
778 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
782 UINT32 NewHorizontalResolution
;
783 UINT32 NewVerticalResolution
;
787 EFI_HANDLE
*HandleBuffer
;
797 // Get current video resolution and text mode
799 Status
= gBS
->HandleProtocol (
800 gST
->ConsoleOutHandle
,
801 &gEfiGraphicsOutputProtocolGuid
,
802 (VOID
**)&GraphicsOutput
804 if (EFI_ERROR (Status
)) {
805 GraphicsOutput
= NULL
;
808 Status
= gBS
->HandleProtocol (
809 gST
->ConsoleOutHandle
,
810 &gEfiSimpleTextOutProtocolGuid
,
811 (VOID
**)&SimpleTextOut
813 if (EFI_ERROR (Status
)) {
814 SimpleTextOut
= NULL
;
817 if ((GraphicsOutput
== NULL
) || (SimpleTextOut
== NULL
)) {
818 return EFI_UNSUPPORTED
;
823 // The required resolution and text mode is setup mode.
825 NewHorizontalResolution
= mSetupHorizontalResolution
;
826 NewVerticalResolution
= mSetupVerticalResolution
;
827 NewColumns
= mSetupTextModeColumn
;
828 NewRows
= mSetupTextModeRow
;
831 // The required resolution and text mode is boot mode.
833 NewHorizontalResolution
= mBootHorizontalResolution
;
834 NewVerticalResolution
= mBootVerticalResolution
;
835 NewColumns
= mBootTextModeColumn
;
836 NewRows
= mBootTextModeRow
;
839 if (GraphicsOutput
!= NULL
) {
840 MaxGopMode
= GraphicsOutput
->Mode
->MaxMode
;
843 if (SimpleTextOut
!= NULL
) {
844 MaxTextMode
= SimpleTextOut
->Mode
->MaxMode
;
848 // 1. If current video resolution is same with required video resolution,
849 // video resolution need not be changed.
850 // 1.1. If current text mode is same with required text mode, text mode need not be changed.
851 // 1.2. If current text mode is different from required text mode, text mode need be changed.
852 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.
854 for (ModeNumber
= 0; ModeNumber
< MaxGopMode
; ModeNumber
++) {
855 Status
= GraphicsOutput
->QueryMode (
861 if (!EFI_ERROR (Status
)) {
862 if ((Info
->HorizontalResolution
== NewHorizontalResolution
) &&
863 (Info
->VerticalResolution
== NewVerticalResolution
))
865 if ((GraphicsOutput
->Mode
->Info
->HorizontalResolution
== NewHorizontalResolution
) &&
866 (GraphicsOutput
->Mode
->Info
->VerticalResolution
== NewVerticalResolution
))
869 // Current resolution is same with required resolution, check if text mode need be set
871 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, SimpleTextOut
->Mode
->Mode
, &CurrentColumn
, &CurrentRow
);
872 ASSERT_EFI_ERROR (Status
);
873 if ((CurrentColumn
== NewColumns
) && (CurrentRow
== NewRows
)) {
875 // If current text mode is same with required text mode. Do nothing
881 // If current text mode is different from required text mode. Set new video mode
883 for (Index
= 0; Index
< MaxTextMode
; Index
++) {
884 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, Index
, &CurrentColumn
, &CurrentRow
);
885 if (!EFI_ERROR (Status
)) {
886 if ((CurrentColumn
== NewColumns
) && (CurrentRow
== NewRows
)) {
888 // Required text mode is supported, set it.
890 Status
= SimpleTextOut
->SetMode (SimpleTextOut
, Index
);
891 ASSERT_EFI_ERROR (Status
);
893 // Update text mode PCD.
895 Status
= PcdSet32S (PcdConOutColumn
, mSetupTextModeColumn
);
896 ASSERT_EFI_ERROR (Status
);
897 Status
= PcdSet32S (PcdConOutRow
, mSetupTextModeRow
);
898 ASSERT_EFI_ERROR (Status
);
905 if (Index
== MaxTextMode
) {
907 // If required text mode is not supported, return error.
910 return EFI_UNSUPPORTED
;
915 // If current video resolution is not same with the new one, set new video resolution.
916 // In this case, the driver which produces simple text out need be restarted.
918 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, ModeNumber
);
919 if (!EFI_ERROR (Status
)) {
930 if (ModeNumber
== MaxGopMode
) {
932 // If the resolution is not supported, return error.
934 return EFI_UNSUPPORTED
;
938 // Set PCD to Inform GraphicsConsole to change video resolution.
939 // Set PCD to Inform Consplitter to change text mode.
941 Status
= PcdSet32S (PcdVideoHorizontalResolution
, NewHorizontalResolution
);
942 ASSERT_EFI_ERROR (Status
);
943 Status
= PcdSet32S (PcdVideoVerticalResolution
, NewVerticalResolution
);
944 ASSERT_EFI_ERROR (Status
);
945 Status
= PcdSet32S (PcdConOutColumn
, NewColumns
);
946 ASSERT_EFI_ERROR (Status
);
947 Status
= PcdSet32S (PcdConOutRow
, NewRows
);
948 ASSERT_EFI_ERROR (Status
);
951 // Video mode is changed, so restart graphics console driver and higher level driver.
952 // Reconnect graphics console driver and higher level driver.
953 // Locate all the handles with GOP protocol and reconnect it.
955 Status
= gBS
->LocateHandleBuffer (
957 &gEfiSimpleTextOutProtocolGuid
,
962 if (!EFI_ERROR (Status
)) {
963 for (Index
= 0; Index
< HandleCount
; Index
++) {
964 gBS
->DisconnectController (HandleBuffer
[Index
], NULL
, NULL
);
967 for (Index
= 0; Index
< HandleCount
; Index
++) {
968 gBS
->ConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
971 if (HandleBuffer
!= NULL
) {
972 FreePool (HandleBuffer
);
980 Display the boot popup menu and allow user select boot item.
982 @param ImageHandle The image handle.
983 @param SystemTable The system table.
985 @retval EFI_SUCCESS Boot from selected boot option, and return success from boot option
986 @retval EFI_NOT_FOUND User select to enter setup or can not find boot option
991 BootManagerMenuEntry (
992 IN EFI_HANDLE ImageHandle
,
993 IN EFI_SYSTEM_TABLE
*SystemTable
996 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
;
997 UINTN BootOptionCount
;
999 BOOT_MENU_POPUP_DATA BootMenuData
;
1002 BOOLEAN ExitApplication
;
1004 EFI_BOOT_LOGO_PROTOCOL
*BootLogo
;
1005 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1006 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
1007 UINTN BootTextColumn
;
1011 // Set Logo status invalid when boot manager menu is launched
1014 Status
= gBS
->LocateProtocol (&gEfiBootLogoProtocolGuid
, NULL
, (VOID
**)&BootLogo
);
1015 if (!EFI_ERROR (Status
) && (BootLogo
!= NULL
)) {
1016 Status
= BootLogo
->SetBootLogo (BootLogo
, NULL
, 0, 0, 0, 0);
1017 ASSERT_EFI_ERROR (Status
);
1020 gBS
->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL
);
1022 gStringPackHandle
= HiiAddPackages (
1025 BootManagerMenuAppStrings
,
1028 ASSERT (gStringPackHandle
!= NULL
);
1031 // Connect all prior to entering the platform setup menu.
1033 EfiBootManagerConnectAll ();
1034 EfiBootManagerRefreshAllBootOption ();
1036 BootOption
= EfiBootManagerGetLoadOptions (&BootOptionCount
, LoadOptionTypeBoot
);
1038 if (!mModeInitialized
) {
1040 // After the console is ready, get current video resolution
1041 // and text mode before launching setup at first time.
1043 Status
= gBS
->HandleProtocol (
1044 gST
->ConsoleOutHandle
,
1045 &gEfiGraphicsOutputProtocolGuid
,
1046 (VOID
**)&GraphicsOutput
1048 if (EFI_ERROR (Status
)) {
1049 GraphicsOutput
= NULL
;
1052 Status
= gBS
->HandleProtocol (
1053 gST
->ConsoleOutHandle
,
1054 &gEfiSimpleTextOutProtocolGuid
,
1055 (VOID
**)&SimpleTextOut
1057 if (EFI_ERROR (Status
)) {
1058 SimpleTextOut
= NULL
;
1061 if (GraphicsOutput
!= NULL
) {
1063 // Get current video resolution and text mode.
1065 mBootHorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
1066 mBootVerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
1069 if (SimpleTextOut
!= NULL
) {
1070 Status
= SimpleTextOut
->QueryMode (
1072 SimpleTextOut
->Mode
->Mode
,
1076 mBootTextModeColumn
= (UINT32
)BootTextColumn
;
1077 mBootTextModeRow
= (UINT32
)BootTextRow
;
1081 // Get user defined text mode for setup.
1083 mSetupHorizontalResolution
= PcdGet32 (PcdSetupVideoHorizontalResolution
);
1084 mSetupVerticalResolution
= PcdGet32 (PcdSetupVideoVerticalResolution
);
1085 mSetupTextModeColumn
= PcdGet32 (PcdSetupConOutColumn
);
1086 mSetupTextModeRow
= PcdGet32 (PcdSetupConOutRow
);
1087 mModeInitialized
= TRUE
;
1091 // Set back to conventional setup resolution
1093 BdsSetConsoleMode (TRUE
);
1096 // Initialize Boot menu data
1098 Status
= InitializeBootMenuData (BootOption
, BootOptionCount
, &BootMenuData
);
1100 // According to boot menu data to draw boot popup menu
1102 DrawBootPopupMenu (&BootMenuData
);
1105 // check user input to determine want to re-draw or boot from user selected item
1107 ExitApplication
= FALSE
;
1108 while (!ExitApplication
) {
1109 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
1110 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1111 if (!EFI_ERROR (Status
)) {
1112 switch (Key
.UnicodeChar
) {
1114 switch (Key
.ScanCode
) {
1116 SelectItem
= BootMenuData
.SelectItem
== 0 ? BootMenuData
.ItemCount
- 1 : BootMenuData
.SelectItem
- 1;
1117 BootMenuSelectItem (SelectItem
, &BootMenuData
);
1121 SelectItem
= BootMenuData
.SelectItem
== BootMenuData
.ItemCount
- 1 ? 0 : BootMenuData
.SelectItem
+ 1;
1122 BootMenuSelectItem (SelectItem
, &BootMenuData
);
1126 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1127 ExitApplication
= TRUE
;
1129 // Set boot resolution for normal boot
1131 BdsSetConsoleMode (FALSE
);
1140 case CHAR_CARRIAGE_RETURN
:
1141 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1143 // Set boot resolution for normal boot
1145 BdsSetConsoleMode (FALSE
);
1146 BootFromSelectOption (BootOption
, BootOptionCount
, BootMenuData
.SelectItem
);
1148 // Back to boot manager menu again, set back to setup resolution
1150 BdsSetConsoleMode (TRUE
);
1151 DrawBootPopupMenu (&BootMenuData
);
1160 EfiBootManagerFreeLoadOptions (BootOption
, BootOptionCount
);
1161 FreePool (BootMenuData
.PtrTokens
);
1163 HiiRemovePackages (gStringPackHandle
);