2 The application to show the Boot Manager Menu.
4 Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "BootManagerMenu.h"
17 EFI_HII_HANDLE gStringPackHandle
;
19 BOOLEAN mModeInitialized
= FALSE
;
22 // Boot video resolution and text mode.
24 UINT32 mBootHorizontalResolution
= 0;
25 UINT32 mBootVerticalResolution
= 0;
26 UINT32 mBootTextModeColumn
= 0;
27 UINT32 mBootTextModeRow
= 0;
29 // BIOS setup video resolution and text mode.
31 UINT32 mSetupTextModeColumn
= 0;
32 UINT32 mSetupTextModeRow
= 0;
33 UINT32 mSetupHorizontalResolution
= 0;
34 UINT32 mSetupVerticalResolution
= 0;
37 Prints a unicode string to the default console, at
38 the supplied cursor position, using L"%s" format.
40 @param Column The cursor position to print the string at.
41 @param Row The cursor position to print the string at
42 @param String String pointer.
44 @return Length of string printed to the console
55 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, Column
, Row
);
56 return Print (L
"%s", String
);
60 Prints a character to the default console, at
61 the supplied cursor position, using L"%c" format.
63 @param Column The cursor position to print the string at.
64 @param Row The cursor position to print the string at.
65 @param Character Character to print.
67 @return Length of string printed to the console.
77 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, Column
, Row
);
78 return Print (L
"%c", Character
);
82 Count the storage space of a Unicode string which uses current language to get
85 @param StringId The input string to be counted.
87 @return Storage space for the input string.
92 IN EFI_STRING_ID StringId
101 String
= HiiGetString (gStringPackHandle
, StringId
, NULL
);
103 if (String
!= NULL
) {
109 // Advance to the null-terminator or to the first width directive
112 (String
[Index
] != NARROW_CHAR
) && (String
[Index
] != WIDE_CHAR
) && (String
[Index
] != 0);
113 Index
++, LineWidth
= LineWidth
+ IncrementValue
118 // We hit the null-terminator, we now have a count
120 if (String
[Index
] == 0) {
124 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
125 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
127 if (String
[Index
] == NARROW_CHAR
) {
129 // Skip to the next character
135 // Skip to the next character
140 } while (String
[Index
] != 0);
148 This function uses calculate the boot menu location, size and scroll bar information.
150 @param BootMenuData The boot menu data to be processed.
152 @return EFI_SUCCESS calculate boot menu information successful.
153 @retval EFI_INVALID_PARAMETER Input parameter is invalid
157 InitializeBootMenuScreen (
158 IN OUT BOOT_MENU_POPUP_DATA
*BootMenuData
167 UINTN UnSelectableItmes
;
169 if (BootMenuData
== NULL
) {
170 return EFI_INVALID_PARAMETER
;
173 // Get maximum string width
176 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++) {
177 StrWidth
= GetLineWidth (BootMenuData
->TitleToken
[Index
]);
178 MaxStrWidth
= MaxStrWidth
> StrWidth
? MaxStrWidth
: StrWidth
;
181 for (Index
= 0; Index
< BootMenuData
->ItemCount
; Index
++) {
182 StrWidth
= GetLineWidth (BootMenuData
->PtrTokens
[Index
]);
183 MaxStrWidth
= MaxStrWidth
> StrWidth
? MaxStrWidth
: StrWidth
;
186 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++) {
187 StrWidth
= GetLineWidth (BootMenuData
->HelpToken
[Index
]);
188 MaxStrWidth
= MaxStrWidth
> StrWidth
? MaxStrWidth
: StrWidth
;
191 // query current row and column to calculate boot menu location
193 gST
->ConOut
->QueryMode (
195 gST
->ConOut
->Mode
->Mode
,
200 MaxPrintRows
= Row
- 6;
201 UnSelectableItmes
= TITLE_TOKEN_COUNT
+ 2 + HELP_TOKEN_COUNT
+ 2;
202 BootMenuData
->MenuScreen
.Width
= MaxStrWidth
+ 8;
203 if (BootMenuData
->ItemCount
+ UnSelectableItmes
> MaxPrintRows
) {
204 BootMenuData
->MenuScreen
.Height
= MaxPrintRows
;
205 BootMenuData
->ScrollBarControl
.HasScrollBar
= TRUE
;
206 BootMenuData
->ScrollBarControl
.ItemCountPerScreen
= MaxPrintRows
- UnSelectableItmes
;
207 BootMenuData
->ScrollBarControl
.FirstItem
= 0;
208 BootMenuData
->ScrollBarControl
.LastItem
= MaxPrintRows
- UnSelectableItmes
- 1;
210 BootMenuData
->MenuScreen
.Height
= BootMenuData
->ItemCount
+ UnSelectableItmes
;
211 BootMenuData
->ScrollBarControl
.HasScrollBar
= FALSE
;
212 BootMenuData
->ScrollBarControl
.ItemCountPerScreen
= BootMenuData
->ItemCount
;
213 BootMenuData
->ScrollBarControl
.FirstItem
= 0;
214 BootMenuData
->ScrollBarControl
.LastItem
= BootMenuData
->ItemCount
- 1;
216 BootMenuData
->MenuScreen
.StartCol
= (Column
- BootMenuData
->MenuScreen
.Width
) / 2;
217 BootMenuData
->MenuScreen
.StartRow
= (Row
- BootMenuData
->MenuScreen
.Height
) / 2;
222 This function uses check boot option is wheher setup application or no
224 @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
226 @retval TRUE This boot option is setup application.
227 @retval FALSE This boot options isn't setup application
232 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
236 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
238 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
239 if (!EFI_ERROR (Status
)) {
240 EfiBootManagerFreeLoadOption (&BootManagerMenu
);
243 return (BOOLEAN
) (!EFI_ERROR (Status
) && (BootOption
->OptionNumber
== BootManagerMenu
.OptionNumber
));
247 Return whether to ignore the boot option.
249 @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION to check.
251 @retval TRUE Ignore the boot option.
252 @retval FALSE Do not ignore the boot option.
256 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
260 EFI_DEVICE_PATH_PROTOCOL
*ImageDevicePath
;
265 Status
= gBS
->HandleProtocol (gImageHandle
, &gEfiLoadedImageDevicePathProtocolGuid
, (VOID
**) &ImageDevicePath
);
266 ASSERT_EFI_ERROR (Status
);
267 if (CompareMem (BootOption
->FilePath
, ImageDevicePath
, GetDevicePathSize (ImageDevicePath
)) == 0) {
272 // Do not ignore Boot Manager Menu.
274 if (IsBootManagerMenu (BootOption
)) {
279 // Ignore the hidden/inactive boot option.
281 if (((BootOption
->Attributes
& LOAD_OPTION_HIDDEN
) != 0) || ((BootOption
->Attributes
& LOAD_OPTION_ACTIVE
) == 0)) {
289 This function uses to initialize boot menu data
291 @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
292 @param BootOptionCount Number of boot option.
293 @param BootMenuData The Input BootMenuData to be initialized.
295 @retval EFI_SUCCESS Initialize boot menu data successful.
296 @retval EFI_INVALID_PARAMETER Input parameter is invalid.
300 InitializeBootMenuData (
301 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
,
302 IN UINTN BootOptionCount
,
303 OUT BOOT_MENU_POPUP_DATA
*BootMenuData
309 if (BootOption
== NULL
|| BootMenuData
== NULL
) {
310 return EFI_INVALID_PARAMETER
;
313 BootMenuData
->TitleToken
[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_TITLE_STRING
);
314 BootMenuData
->PtrTokens
= AllocateZeroPool (BootOptionCount
* sizeof (EFI_STRING_ID
));
315 ASSERT (BootMenuData
->PtrTokens
!= NULL
);
318 // Skip boot option which created by BootNext Variable
320 for (StrIndex
= 0, Index
= 0; Index
< BootOptionCount
; Index
++) {
321 if (IgnoreBootOption (&BootOption
[Index
])) {
325 ASSERT (BootOption
[Index
].Description
!= NULL
);
326 BootMenuData
->PtrTokens
[StrIndex
++] = HiiSetString (
329 BootOption
[Index
].Description
,
334 BootMenuData
->ItemCount
= StrIndex
;
335 BootMenuData
->HelpToken
[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP1_STRING
);
336 BootMenuData
->HelpToken
[1] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP2_STRING
);
337 BootMenuData
->HelpToken
[2] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP3_STRING
);
338 InitializeBootMenuScreen (BootMenuData
);
339 BootMenuData
->SelectItem
= 0;
344 This function uses input select item to highlight selected item
345 and set current selected item in BootMenuData
347 @param WantSelectItem The user wants to select item.
348 @param BootMenuData The boot menu data to be processed
350 @return EFI_SUCCESS Highlight selected item and update current selected
352 @retval EFI_INVALID_PARAMETER Input parameter is invalid
356 IN UINTN WantSelectItem
,
357 IN OUT BOOT_MENU_POPUP_DATA
*BootMenuData
360 INT32 SavedAttribute
;
370 UINTN ItemCountPerScreen
;
372 BOOLEAN RePaintItems
;
374 if (BootMenuData
== NULL
|| WantSelectItem
>= BootMenuData
->ItemCount
) {
375 return EFI_INVALID_PARAMETER
;
377 ASSERT (BootMenuData
->ItemCount
!= 0);
378 SavedAttribute
= gST
->ConOut
->Mode
->Attribute
;
379 RePaintItems
= FALSE
;
380 StartCol
= BootMenuData
->MenuScreen
.StartCol
;
381 StartRow
= BootMenuData
->MenuScreen
.StartRow
;
383 // print selectable items again and adjust scroll bar if need
385 if (BootMenuData
->ScrollBarControl
.HasScrollBar
&&
386 (WantSelectItem
< BootMenuData
->ScrollBarControl
.FirstItem
||
387 WantSelectItem
> BootMenuData
->ScrollBarControl
.LastItem
||
388 WantSelectItem
== BootMenuData
->SelectItem
)) {
389 ItemCountPerScreen
= BootMenuData
->ScrollBarControl
.ItemCountPerScreen
;
391 // Set first item and last item
393 if (WantSelectItem
< BootMenuData
->ScrollBarControl
.FirstItem
) {
394 BootMenuData
->ScrollBarControl
.FirstItem
= WantSelectItem
;
395 BootMenuData
->ScrollBarControl
.LastItem
= WantSelectItem
+ ItemCountPerScreen
- 1;
396 } else if (WantSelectItem
> BootMenuData
->ScrollBarControl
.LastItem
) {
397 BootMenuData
->ScrollBarControl
.FirstItem
= WantSelectItem
- ItemCountPerScreen
+ 1;
398 BootMenuData
->ScrollBarControl
.LastItem
= WantSelectItem
;
400 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
401 FirstItem
= BootMenuData
->ScrollBarControl
.FirstItem
;
402 LastItem
= BootMenuData
->ScrollBarControl
.LastItem
;
404 if (FirstItem
!= 0) {
405 TopShadeNum
= (FirstItem
* ItemCountPerScreen
) / BootMenuData
->ItemCount
;
406 if ((FirstItem
* ItemCountPerScreen
) % BootMenuData
->ItemCount
!= 0) {
409 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
410 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
411 for (Index
= 0; Index
< TopShadeNum
; Index
++, PrintRow
++) {
412 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_LIGHT_SHADE
);
416 if (LastItem
!= BootMenuData
->ItemCount
- 1) {
417 LowShadeNum
= ((BootMenuData
->ItemCount
- 1 - LastItem
) * ItemCountPerScreen
) / BootMenuData
->ItemCount
;
418 if (((BootMenuData
->ItemCount
- 1 - LastItem
) * ItemCountPerScreen
) % BootMenuData
->ItemCount
!= 0) {
421 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
422 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + ItemCountPerScreen
- LowShadeNum
;
423 for (Index
= 0; Index
< LowShadeNum
; Index
++, PrintRow
++) {
424 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_LIGHT_SHADE
);
427 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
428 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + TopShadeNum
;
429 for (Index
= TopShadeNum
; Index
< ItemCountPerScreen
- LowShadeNum
; Index
++, PrintRow
++) {
430 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_FULL_BLOCK
);
435 // Clear selectable items first
437 PrintCol
= StartCol
+ 1;
438 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
439 String
= AllocateZeroPool ((BootMenuData
->MenuScreen
.Width
- 2) * sizeof (CHAR16
));
440 ASSERT (String
!= NULL
);
441 for (Index
= 0; Index
< BootMenuData
->MenuScreen
.Width
- 3; Index
++) {
442 String
[Index
] = 0x20;
444 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++) {
445 PrintStringAt (PrintCol
, PrintRow
+ Index
, String
);
449 // print selectable items
451 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++, PrintRow
++) {
452 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[Index
+ FirstItem
], NULL
);
453 PrintStringAt (PrintCol
, PrintRow
, String
);
460 // Print want to select item
462 FirstItem
= BootMenuData
->ScrollBarControl
.FirstItem
;
463 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLACK
);
464 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[WantSelectItem
], NULL
);
465 PrintCol
= StartCol
+ 1;
466 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + WantSelectItem
- FirstItem
;
467 PrintStringAt (PrintCol
, PrintRow
, String
);
471 // if Want Select and selected item isn't the same and doesn't re-draw selectable
472 // items, clear select item
474 if (WantSelectItem
!= BootMenuData
->SelectItem
&& !RePaintItems
) {
475 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
476 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[BootMenuData
->SelectItem
], NULL
);
477 PrintCol
= StartCol
+ 1;
478 PrintRow
= StartRow
+ 3 + BootMenuData
->SelectItem
- FirstItem
;
479 PrintStringAt (PrintCol
, PrintRow
, String
);
483 gST
->ConOut
->SetAttribute (gST
->ConOut
, SavedAttribute
);
484 BootMenuData
->SelectItem
= WantSelectItem
;
489 This function uses to draw boot popup menu
491 @param BootMenuData The Input BootMenuData to be processed.
493 @retval EFI_SUCCESS Draw boot popup menu successful.
498 IN BOOT_MENU_POPUP_DATA
*BootMenuData
509 INT32 SavedAttribute
;
510 UINTN ItemCountPerScreen
;
512 gST
->ConOut
->ClearScreen (gST
->ConOut
);
514 SavedAttribute
= gST
->ConOut
->Mode
->Attribute
;
515 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
516 Width
= BootMenuData
->MenuScreen
.Width
;
517 StartCol
= BootMenuData
->MenuScreen
.StartCol
;
518 StartRow
= BootMenuData
->MenuScreen
.StartRow
;
519 ItemCountPerScreen
= BootMenuData
->ScrollBarControl
.ItemCountPerScreen
;
522 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
524 // Draw Boot popup menu screen
526 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_DOWN_RIGHT
);
527 for (Index
= 1; Index
< Width
- 1; Index
++) {
528 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
530 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_DOWN_LEFT
);
533 // Draw the screen for title
535 String
= AllocateZeroPool ((Width
- 1) * sizeof (CHAR16
));
536 ASSERT (String
!= NULL
);
537 for (Index
= 0; Index
< Width
- 2; Index
++) {
538 String
[Index
] = 0x20;
541 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++) {
543 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
544 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
545 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
549 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL_RIGHT
);
550 for (Index
= 1; Index
< Width
- 1; Index
++) {
551 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
553 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL_LEFT
);
556 // Draw screen for selectable items
558 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++) {
560 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
561 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
562 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
566 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL_RIGHT
);
567 for (Index
= 1; Index
< Width
- 1; Index
++) {
568 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
570 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL_LEFT
);
573 // Draw screen for Help
575 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++) {
577 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
578 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
579 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
584 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_UP_RIGHT
);
585 for (Index
= 1; Index
< Width
- 1; Index
++) {
586 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
588 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_UP_LEFT
);
592 // print title strings
594 PrintRow
= StartRow
+ 1;
595 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++, PrintRow
++) {
596 String
= HiiGetString (gStringPackHandle
, BootMenuData
->TitleToken
[Index
], NULL
);
597 LineWidth
= GetLineWidth (BootMenuData
->TitleToken
[Index
]);
598 PrintCol
= StartCol
+ (Width
- LineWidth
) / 2;
599 PrintStringAt (PrintCol
, PrintRow
, String
);
604 // print selectable items
606 PrintCol
= StartCol
+ 1;
607 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
608 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++, PrintRow
++) {
609 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[Index
], NULL
);
610 PrintStringAt (PrintCol
, PrintRow
, String
);
615 // Print Help strings
618 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++, PrintRow
++) {
619 String
= HiiGetString (gStringPackHandle
, BootMenuData
->HelpToken
[Index
], NULL
);
620 LineWidth
= GetLineWidth (BootMenuData
->HelpToken
[Index
]);
621 PrintCol
= StartCol
+ (Width
- LineWidth
) / 2;
622 PrintStringAt (PrintCol
, PrintRow
, String
);
627 // Print scroll bar if has scroll bar
629 if (BootMenuData
->ScrollBarControl
.HasScrollBar
) {
630 PrintCol
= StartCol
+ Width
- 2;
631 PrintRow
= StartRow
+ 2;
632 PrintCharAt (PrintCol
, PrintRow
, GEOMETRICSHAPE_UP_TRIANGLE
);
633 PrintCharAt (PrintCol
+ 1, PrintRow
, BOXDRAW_VERTICAL
);
634 PrintRow
+= (ItemCountPerScreen
+ 1);
635 PrintCharAt (PrintCol
, PrintRow
, GEOMETRICSHAPE_DOWN_TRIANGLE
);
636 PrintCharAt (PrintCol
+ 1, PrintRow
, BOXDRAW_VERTICAL
);
639 gST
->ConOut
->SetAttribute (gST
->ConOut
, SavedAttribute
);
641 // Print Selected item
643 BootMenuSelectItem (BootMenuData
->SelectItem
, BootMenuData
);
648 This function uses to boot from selected item
650 @param BootOptions Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
651 @param BootOptionCount Number of boot option.
652 @param SelectItem Current selected item.
655 BootFromSelectOption (
656 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
,
657 IN UINTN BootOptionCount
,
664 ASSERT (BootOptions
!= NULL
);
666 for (ItemNum
= 0, Index
= 0; Index
< BootOptionCount
; Index
++) {
667 if (IgnoreBootOption (&BootOptions
[Index
])) {
671 if (ItemNum
++ == SelectItem
) {
672 EfiBootManagerBoot (&BootOptions
[Index
]);
679 This function will change video resolution and text mode
680 according to defined setup mode or defined boot mode
682 @param IsSetupMode Indicate mode is changed to setup mode or boot mode.
684 @retval EFI_SUCCESS Mode is changed successfully.
685 @retval Others Mode failed to be changed.
694 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
695 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
697 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
701 UINT32 NewHorizontalResolution
;
702 UINT32 NewVerticalResolution
;
706 EFI_HANDLE
*HandleBuffer
;
716 // Get current video resolution and text mode
718 Status
= gBS
->HandleProtocol (
719 gST
->ConsoleOutHandle
,
720 &gEfiGraphicsOutputProtocolGuid
,
721 (VOID
**)&GraphicsOutput
723 if (EFI_ERROR (Status
)) {
724 GraphicsOutput
= NULL
;
727 Status
= gBS
->HandleProtocol (
728 gST
->ConsoleOutHandle
,
729 &gEfiSimpleTextOutProtocolGuid
,
730 (VOID
**)&SimpleTextOut
732 if (EFI_ERROR (Status
)) {
733 SimpleTextOut
= NULL
;
736 if ((GraphicsOutput
== NULL
) || (SimpleTextOut
== NULL
)) {
737 return EFI_UNSUPPORTED
;
742 // The required resolution and text mode is setup mode.
744 NewHorizontalResolution
= mSetupHorizontalResolution
;
745 NewVerticalResolution
= mSetupVerticalResolution
;
746 NewColumns
= mSetupTextModeColumn
;
747 NewRows
= mSetupTextModeRow
;
750 // The required resolution and text mode is boot mode.
752 NewHorizontalResolution
= mBootHorizontalResolution
;
753 NewVerticalResolution
= mBootVerticalResolution
;
754 NewColumns
= mBootTextModeColumn
;
755 NewRows
= mBootTextModeRow
;
758 if (GraphicsOutput
!= NULL
) {
759 MaxGopMode
= GraphicsOutput
->Mode
->MaxMode
;
762 if (SimpleTextOut
!= NULL
) {
763 MaxTextMode
= SimpleTextOut
->Mode
->MaxMode
;
767 // 1. If current video resolution is same with required video resolution,
768 // video resolution need not be changed.
769 // 1.1. If current text mode is same with required text mode, text mode need not be changed.
770 // 1.2. If current text mode is different from required text mode, text mode need be changed.
771 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.
773 for (ModeNumber
= 0; ModeNumber
< MaxGopMode
; ModeNumber
++) {
774 Status
= GraphicsOutput
->QueryMode (
780 if (!EFI_ERROR (Status
)) {
781 if ((Info
->HorizontalResolution
== NewHorizontalResolution
) &&
782 (Info
->VerticalResolution
== NewVerticalResolution
)) {
783 if ((GraphicsOutput
->Mode
->Info
->HorizontalResolution
== NewHorizontalResolution
) &&
784 (GraphicsOutput
->Mode
->Info
->VerticalResolution
== NewVerticalResolution
)) {
786 // Current resolution is same with required resolution, check if text mode need be set
788 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, SimpleTextOut
->Mode
->Mode
, &CurrentColumn
, &CurrentRow
);
789 ASSERT_EFI_ERROR (Status
);
790 if (CurrentColumn
== NewColumns
&& CurrentRow
== NewRows
) {
792 // If current text mode is same with required text mode. Do nothing
798 // If current text mode is different from required text mode. Set new video mode
800 for (Index
= 0; Index
< MaxTextMode
; Index
++) {
801 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, Index
, &CurrentColumn
, &CurrentRow
);
802 if (!EFI_ERROR(Status
)) {
803 if ((CurrentColumn
== NewColumns
) && (CurrentRow
== NewRows
)) {
805 // Required text mode is supported, set it.
807 Status
= SimpleTextOut
->SetMode (SimpleTextOut
, Index
);
808 ASSERT_EFI_ERROR (Status
);
810 // Update text mode PCD.
812 Status
= PcdSet32S (PcdConOutColumn
, mSetupTextModeColumn
);
813 ASSERT_EFI_ERROR (Status
);
814 Status
= PcdSet32S (PcdConOutRow
, mSetupTextModeRow
);
815 ASSERT_EFI_ERROR (Status
);
821 if (Index
== MaxTextMode
) {
823 // If required text mode is not supported, return error.
826 return EFI_UNSUPPORTED
;
831 // If current video resolution is not same with the new one, set new video resolution.
832 // In this case, the driver which produces simple text out need be restarted.
834 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, ModeNumber
);
835 if (!EFI_ERROR (Status
)) {
845 if (ModeNumber
== MaxGopMode
) {
847 // If the resolution is not supported, return error.
849 return EFI_UNSUPPORTED
;
853 // Set PCD to Inform GraphicsConsole to change video resolution.
854 // Set PCD to Inform Consplitter to change text mode.
856 Status
= PcdSet32S (PcdVideoHorizontalResolution
, NewHorizontalResolution
);
857 ASSERT_EFI_ERROR (Status
);
858 Status
= PcdSet32S (PcdVideoVerticalResolution
, NewVerticalResolution
);
859 ASSERT_EFI_ERROR (Status
);
860 Status
= PcdSet32S (PcdConOutColumn
, NewColumns
);
861 ASSERT_EFI_ERROR (Status
);
862 Status
= PcdSet32S (PcdConOutRow
, NewRows
);
863 ASSERT_EFI_ERROR (Status
);
866 // Video mode is changed, so restart graphics console driver and higher level driver.
867 // Reconnect graphics console driver and higher level driver.
868 // Locate all the handles with GOP protocol and reconnect it.
870 Status
= gBS
->LocateHandleBuffer (
872 &gEfiSimpleTextOutProtocolGuid
,
877 if (!EFI_ERROR (Status
)) {
878 for (Index
= 0; Index
< HandleCount
; Index
++) {
879 gBS
->DisconnectController (HandleBuffer
[Index
], NULL
, NULL
);
881 for (Index
= 0; Index
< HandleCount
; Index
++) {
882 gBS
->ConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
884 if (HandleBuffer
!= NULL
) {
885 FreePool (HandleBuffer
);
893 Display the boot popup menu and allow user select boot item.
895 @param ImageHandle The image handle.
896 @param SystemTable The system table.
898 @retval EFI_SUCCESS Boot from selected boot option, and return success from boot option
899 @retval EFI_NOT_FOUND User select to enter setup or can not find boot option
904 BootManagerMenuEntry (
905 IN EFI_HANDLE ImageHandle
,
906 IN EFI_SYSTEM_TABLE
*SystemTable
909 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
;
910 UINTN BootOptionCount
;
912 BOOT_MENU_POPUP_DATA BootMenuData
;
915 BOOLEAN ExitApplication
;
917 EFI_BOOT_LOGO_PROTOCOL
*BootLogo
;
918 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
919 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
920 UINTN BootTextColumn
;
924 // Set Logo status invalid when boot manager menu is launched
927 Status
= gBS
->LocateProtocol (&gEfiBootLogoProtocolGuid
, NULL
, (VOID
**) &BootLogo
);
928 if (!EFI_ERROR (Status
) && (BootLogo
!= NULL
)) {
929 Status
= BootLogo
->SetBootLogo (BootLogo
, NULL
, 0, 0, 0, 0);
930 ASSERT_EFI_ERROR (Status
);
933 gBS
->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL
);
935 gStringPackHandle
= HiiAddPackages (
938 BootManagerMenuAppStrings
,
941 ASSERT (gStringPackHandle
!= NULL
);
944 // Connect all prior to entering the platform setup menu.
946 EfiBootManagerConnectAll ();
947 EfiBootManagerRefreshAllBootOption ();
949 BootOption
= EfiBootManagerGetLoadOptions (&BootOptionCount
, LoadOptionTypeBoot
);
951 if (!mModeInitialized
) {
953 // After the console is ready, get current video resolution
954 // and text mode before launching setup at first time.
956 Status
= gBS
->HandleProtocol (
957 gST
->ConsoleOutHandle
,
958 &gEfiGraphicsOutputProtocolGuid
,
959 (VOID
**)&GraphicsOutput
961 if (EFI_ERROR (Status
)) {
962 GraphicsOutput
= NULL
;
965 Status
= gBS
->HandleProtocol (
966 gST
->ConsoleOutHandle
,
967 &gEfiSimpleTextOutProtocolGuid
,
968 (VOID
**)&SimpleTextOut
970 if (EFI_ERROR (Status
)) {
971 SimpleTextOut
= NULL
;
974 if (GraphicsOutput
!= NULL
) {
976 // Get current video resolution and text mode.
978 mBootHorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
979 mBootVerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
982 if (SimpleTextOut
!= NULL
) {
983 Status
= SimpleTextOut
->QueryMode (
985 SimpleTextOut
->Mode
->Mode
,
989 mBootTextModeColumn
= (UINT32
)BootTextColumn
;
990 mBootTextModeRow
= (UINT32
)BootTextRow
;
994 // Get user defined text mode for setup.
996 mSetupHorizontalResolution
= PcdGet32 (PcdSetupVideoHorizontalResolution
);
997 mSetupVerticalResolution
= PcdGet32 (PcdSetupVideoVerticalResolution
);
998 mSetupTextModeColumn
= PcdGet32 (PcdSetupConOutColumn
);
999 mSetupTextModeRow
= PcdGet32 (PcdSetupConOutRow
);
1000 mModeInitialized
= TRUE
;
1004 // Set back to conventional setup resolution
1006 BdsSetConsoleMode (TRUE
);
1009 // Initialize Boot menu data
1011 Status
= InitializeBootMenuData (BootOption
, BootOptionCount
, &BootMenuData
);
1013 // According to boot menu data to draw boot popup menu
1015 DrawBootPopupMenu (&BootMenuData
);
1018 // check user input to determine want to re-draw or boot from user selected item
1020 ExitApplication
= FALSE
;
1021 while (!ExitApplication
) {
1022 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
1023 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1024 if (!EFI_ERROR (Status
)) {
1025 switch (Key
.UnicodeChar
) {
1028 switch (Key
.ScanCode
) {
1031 SelectItem
= BootMenuData
.SelectItem
== 0 ? BootMenuData
.ItemCount
- 1 : BootMenuData
.SelectItem
- 1;
1032 BootMenuSelectItem (SelectItem
, &BootMenuData
);
1036 SelectItem
= BootMenuData
.SelectItem
== BootMenuData
.ItemCount
- 1 ? 0 : BootMenuData
.SelectItem
+ 1;
1037 BootMenuSelectItem (SelectItem
, &BootMenuData
);
1041 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1042 ExitApplication
= TRUE
;
1044 // Set boot resolution for normal boot
1046 BdsSetConsoleMode (FALSE
);
1054 case CHAR_CARRIAGE_RETURN
:
1055 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1057 // Set boot resolution for normal boot
1059 BdsSetConsoleMode (FALSE
);
1060 BootFromSelectOption (BootOption
, BootOptionCount
, BootMenuData
.SelectItem
);
1062 // Back to boot manager menu again, set back to setup resolution
1064 BdsSetConsoleMode (TRUE
);
1065 DrawBootPopupMenu (&BootMenuData
);
1073 EfiBootManagerFreeLoadOptions (BootOption
, BootOptionCount
);
1074 FreePool (BootMenuData
.PtrTokens
);
1076 HiiRemovePackages (gStringPackHandle
);