2 The application to show the Boot Manager Menu.
4 Copyright (c) 2011 - 2015, 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 chracter 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 lanaguag 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 proccessed.
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 funciton 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 optin.
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 funciton 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 proccessed
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 SavedAttribute
= gST
->ConOut
->Mode
->Attribute
;
378 RePaintItems
= FALSE
;
379 StartCol
= BootMenuData
->MenuScreen
.StartCol
;
380 StartRow
= BootMenuData
->MenuScreen
.StartRow
;
382 // print selectable items again and adjust scroll bar if need
384 if (BootMenuData
->ScrollBarControl
.HasScrollBar
&&
385 (WantSelectItem
< BootMenuData
->ScrollBarControl
.FirstItem
||
386 WantSelectItem
> BootMenuData
->ScrollBarControl
.LastItem
||
387 WantSelectItem
== BootMenuData
->SelectItem
)) {
388 ItemCountPerScreen
= BootMenuData
->ScrollBarControl
.ItemCountPerScreen
;
390 // Set first item and last item
392 if (WantSelectItem
< BootMenuData
->ScrollBarControl
.FirstItem
) {
393 BootMenuData
->ScrollBarControl
.FirstItem
= WantSelectItem
;
394 BootMenuData
->ScrollBarControl
.LastItem
= WantSelectItem
+ ItemCountPerScreen
- 1;
395 } else if (WantSelectItem
> BootMenuData
->ScrollBarControl
.LastItem
) {
396 BootMenuData
->ScrollBarControl
.FirstItem
= WantSelectItem
- ItemCountPerScreen
+ 1;
397 BootMenuData
->ScrollBarControl
.LastItem
= WantSelectItem
;
399 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
400 FirstItem
= BootMenuData
->ScrollBarControl
.FirstItem
;
401 LastItem
= BootMenuData
->ScrollBarControl
.LastItem
;
403 if (FirstItem
!= 0) {
404 TopShadeNum
= (FirstItem
* ItemCountPerScreen
) / BootMenuData
->ItemCount
;
405 if ((FirstItem
* ItemCountPerScreen
) % BootMenuData
->ItemCount
!= 0) {
408 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
409 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
410 for (Index
= 0; Index
< TopShadeNum
; Index
++, PrintRow
++) {
411 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_LIGHT_SHADE
);
415 if (LastItem
!= BootMenuData
->ItemCount
- 1) {
416 LowShadeNum
= ((BootMenuData
->ItemCount
- 1 - LastItem
) * ItemCountPerScreen
) / BootMenuData
->ItemCount
;
417 if (((BootMenuData
->ItemCount
- 1 - LastItem
) * ItemCountPerScreen
) % BootMenuData
->ItemCount
!= 0) {
420 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
421 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + ItemCountPerScreen
- LowShadeNum
;
422 for (Index
= 0; Index
< LowShadeNum
; Index
++, PrintRow
++) {
423 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_LIGHT_SHADE
);
426 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
427 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + TopShadeNum
;
428 for (Index
= TopShadeNum
; Index
< ItemCountPerScreen
- LowShadeNum
; Index
++, PrintRow
++) {
429 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_FULL_BLOCK
);
434 // Clear selectable items first
436 PrintCol
= StartCol
+ 1;
437 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
438 String
= AllocateZeroPool ((BootMenuData
->MenuScreen
.Width
- 2) * sizeof (CHAR16
));
439 ASSERT (String
!= NULL
);
440 for (Index
= 0; Index
< BootMenuData
->MenuScreen
.Width
- 3; Index
++) {
441 String
[Index
] = 0x20;
443 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++) {
444 PrintStringAt (PrintCol
, PrintRow
+ Index
, String
);
448 // print selectable items
450 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++, PrintRow
++) {
451 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[Index
+ FirstItem
], NULL
);
452 PrintStringAt (PrintCol
, PrintRow
, String
);
459 // Print want to select item
461 FirstItem
= BootMenuData
->ScrollBarControl
.FirstItem
;
462 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLACK
);
463 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[WantSelectItem
], NULL
);
464 PrintCol
= StartCol
+ 1;
465 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + WantSelectItem
- FirstItem
;
466 PrintStringAt (PrintCol
, PrintRow
, String
);
470 // if Want Select and selected item isn't the same and doesn't re-draw selectable
471 // items, clear select item
473 if (WantSelectItem
!= BootMenuData
->SelectItem
&& !RePaintItems
) {
474 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
475 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[BootMenuData
->SelectItem
], NULL
);
476 PrintCol
= StartCol
+ 1;
477 PrintRow
= StartRow
+ 3 + BootMenuData
->SelectItem
- FirstItem
;
478 PrintStringAt (PrintCol
, PrintRow
, String
);
482 gST
->ConOut
->SetAttribute (gST
->ConOut
, SavedAttribute
);
483 BootMenuData
->SelectItem
= WantSelectItem
;
488 This funciton uses to draw boot popup menu
490 @param BootMenuData The Input BootMenuData to be processed.
492 @retval EFI_SUCCESS Draw boot popup menu successful.
497 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 Height
= BootMenuData
->MenuScreen
.Height
;
518 StartCol
= BootMenuData
->MenuScreen
.StartCol
;
519 StartRow
= BootMenuData
->MenuScreen
.StartRow
;
520 ItemCountPerScreen
= BootMenuData
->ScrollBarControl
.ItemCountPerScreen
;
523 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
525 // Draw Boot popup menu screen
527 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_DOWN_RIGHT
);
528 for (Index
= 1; Index
< Width
- 1; Index
++) {
529 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
531 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_DOWN_LEFT
);
534 // Draw the screen for title
536 String
= AllocateZeroPool ((Width
- 1) * sizeof (CHAR16
));
537 ASSERT (String
!= NULL
);
538 for (Index
= 0; Index
< Width
- 2; Index
++) {
539 String
[Index
] = 0x20;
542 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++) {
544 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
545 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
546 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
550 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL_RIGHT
);
551 for (Index
= 1; Index
< Width
- 1; Index
++) {
552 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
554 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL_LEFT
);
557 // Draw screen for selectable items
559 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++) {
561 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
562 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
563 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
567 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL_RIGHT
);
568 for (Index
= 1; Index
< Width
- 1; Index
++) {
569 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
571 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL_LEFT
);
574 // Draw screen for Help
576 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++) {
578 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
579 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
580 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
585 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_UP_RIGHT
);
586 for (Index
= 1; Index
< Width
- 1; Index
++) {
587 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
589 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_UP_LEFT
);
593 // print title strings
595 PrintRow
= StartRow
+ 1;
596 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++, PrintRow
++) {
597 String
= HiiGetString (gStringPackHandle
, BootMenuData
->TitleToken
[Index
], NULL
);
598 LineWidth
= GetLineWidth (BootMenuData
->TitleToken
[Index
]);
599 PrintCol
= StartCol
+ (Width
- LineWidth
) / 2;
600 PrintStringAt (PrintCol
, PrintRow
, String
);
605 // print selectable items
607 PrintCol
= StartCol
+ 1;
608 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
609 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++, PrintRow
++) {
610 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[Index
], NULL
);
611 PrintStringAt (PrintCol
, PrintRow
, String
);
616 // Print Help strings
619 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++, PrintRow
++) {
620 String
= HiiGetString (gStringPackHandle
, BootMenuData
->HelpToken
[Index
], NULL
);
621 LineWidth
= GetLineWidth (BootMenuData
->HelpToken
[Index
]);
622 PrintCol
= StartCol
+ (Width
- LineWidth
) / 2;
623 PrintStringAt (PrintCol
, PrintRow
, String
);
628 // Print scroll bar if has scroll bar
630 if (BootMenuData
->ScrollBarControl
.HasScrollBar
) {
631 PrintCol
= StartCol
+ Width
- 2;
632 PrintRow
= StartRow
+ 2;
633 PrintCharAt (PrintCol
, PrintRow
, GEOMETRICSHAPE_UP_TRIANGLE
);
634 PrintCharAt (PrintCol
+ 1, PrintRow
, BOXDRAW_VERTICAL
);
635 PrintRow
+= (ItemCountPerScreen
+ 1);
636 PrintCharAt (PrintCol
, PrintRow
, GEOMETRICSHAPE_DOWN_TRIANGLE
);
637 PrintCharAt (PrintCol
+ 1, PrintRow
, BOXDRAW_VERTICAL
);
640 gST
->ConOut
->SetAttribute (gST
->ConOut
, SavedAttribute
);
642 // Print Selected item
644 BootMenuSelectItem (BootMenuData
->SelectItem
, BootMenuData
);
649 This funciton uses to boot from selected item
651 @param BootOptions Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
652 @param BootOptionCount Number of boot option.
653 @param SelectItem Current selected item.
656 BootFromSelectOption (
657 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
,
658 IN UINTN BootOptionCount
,
665 ASSERT (BootOptions
!= NULL
);
667 for (ItemNum
= 0, Index
= 0; Index
< BootOptionCount
; Index
++) {
668 if (IgnoreBootOption (&BootOptions
[Index
])) {
672 if (ItemNum
++ == SelectItem
) {
673 EfiBootManagerBoot (&BootOptions
[Index
]);
680 This function will change video resolution and text mode
681 according to defined setup mode or defined boot mode
683 @param IsSetupMode Indicate mode is changed to setup mode or boot mode.
685 @retval EFI_SUCCESS Mode is changed successfully.
686 @retval Others Mode failed to be changed.
695 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
696 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
698 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
702 UINT32 NewHorizontalResolution
;
703 UINT32 NewVerticalResolution
;
707 EFI_HANDLE
*HandleBuffer
;
717 // Get current video resolution and text mode
719 Status
= gBS
->HandleProtocol (
720 gST
->ConsoleOutHandle
,
721 &gEfiGraphicsOutputProtocolGuid
,
722 (VOID
**)&GraphicsOutput
724 if (EFI_ERROR (Status
)) {
725 GraphicsOutput
= NULL
;
728 Status
= gBS
->HandleProtocol (
729 gST
->ConsoleOutHandle
,
730 &gEfiSimpleTextOutProtocolGuid
,
731 (VOID
**)&SimpleTextOut
733 if (EFI_ERROR (Status
)) {
734 SimpleTextOut
= NULL
;
737 if ((GraphicsOutput
== NULL
) || (SimpleTextOut
== NULL
)) {
738 return EFI_UNSUPPORTED
;
743 // The requried resolution and text mode is setup mode.
745 NewHorizontalResolution
= mSetupHorizontalResolution
;
746 NewVerticalResolution
= mSetupVerticalResolution
;
747 NewColumns
= mSetupTextModeColumn
;
748 NewRows
= mSetupTextModeRow
;
751 // The required resolution and text mode is boot mode.
753 NewHorizontalResolution
= mBootHorizontalResolution
;
754 NewVerticalResolution
= mBootVerticalResolution
;
755 NewColumns
= mBootTextModeColumn
;
756 NewRows
= mBootTextModeRow
;
759 if (GraphicsOutput
!= NULL
) {
760 MaxGopMode
= GraphicsOutput
->Mode
->MaxMode
;
763 if (SimpleTextOut
!= NULL
) {
764 MaxTextMode
= SimpleTextOut
->Mode
->MaxMode
;
768 // 1. If current video resolution is same with required video resolution,
769 // video resolution need not be changed.
770 // 1.1. If current text mode is same with required text mode, text mode need not be changed.
771 // 1.2. If current text mode is different from required text mode, text mode need be changed.
772 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.
774 for (ModeNumber
= 0; ModeNumber
< MaxGopMode
; ModeNumber
++) {
775 Status
= GraphicsOutput
->QueryMode (
781 if (!EFI_ERROR (Status
)) {
782 if ((Info
->HorizontalResolution
== NewHorizontalResolution
) &&
783 (Info
->VerticalResolution
== NewVerticalResolution
)) {
784 if ((GraphicsOutput
->Mode
->Info
->HorizontalResolution
== NewHorizontalResolution
) &&
785 (GraphicsOutput
->Mode
->Info
->VerticalResolution
== NewVerticalResolution
)) {
787 // Current resolution is same with required resolution, check if text mode need be set
789 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, SimpleTextOut
->Mode
->Mode
, &CurrentColumn
, &CurrentRow
);
790 ASSERT_EFI_ERROR (Status
);
791 if (CurrentColumn
== NewColumns
&& CurrentRow
== NewRows
) {
793 // If current text mode is same with required text mode. Do nothing
799 // If current text mode is different from requried text mode. Set new video mode
801 for (Index
= 0; Index
< MaxTextMode
; Index
++) {
802 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, Index
, &CurrentColumn
, &CurrentRow
);
803 if (!EFI_ERROR(Status
)) {
804 if ((CurrentColumn
== NewColumns
) && (CurrentRow
== NewRows
)) {
806 // Required text mode is supported, set it.
808 Status
= SimpleTextOut
->SetMode (SimpleTextOut
, Index
);
809 ASSERT_EFI_ERROR (Status
);
811 // Update text mode PCD.
813 Status
= PcdSet32S (PcdConOutColumn
, mSetupTextModeColumn
);
814 ASSERT_EFI_ERROR (Status
);
815 Status
= PcdSet32S (PcdConOutRow
, mSetupTextModeRow
);
816 ASSERT_EFI_ERROR (Status
);
822 if (Index
== MaxTextMode
) {
824 // If requried text mode is not supported, return error.
827 return EFI_UNSUPPORTED
;
832 // If current video resolution is not same with the new one, set new video resolution.
833 // In this case, the driver which produces simple text out need be restarted.
835 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, ModeNumber
);
836 if (!EFI_ERROR (Status
)) {
846 if (ModeNumber
== MaxGopMode
) {
848 // If the resolution is not supported, return error.
850 return EFI_UNSUPPORTED
;
854 // Set PCD to Inform GraphicsConsole to change video resolution.
855 // Set PCD to Inform Consplitter to change text mode.
857 Status
= PcdSet32S (PcdVideoHorizontalResolution
, NewHorizontalResolution
);
858 ASSERT_EFI_ERROR (Status
);
859 Status
= PcdSet32S (PcdVideoVerticalResolution
, NewVerticalResolution
);
860 ASSERT_EFI_ERROR (Status
);
861 Status
= PcdSet32S (PcdConOutColumn
, NewColumns
);
862 ASSERT_EFI_ERROR (Status
);
863 Status
= PcdSet32S (PcdConOutRow
, NewRows
);
864 ASSERT_EFI_ERROR (Status
);
867 // Video mode is changed, so restart graphics console driver and higher level driver.
868 // Reconnect graphics console driver and higher level driver.
869 // Locate all the handles with GOP protocol and reconnect it.
871 Status
= gBS
->LocateHandleBuffer (
873 &gEfiSimpleTextOutProtocolGuid
,
878 if (!EFI_ERROR (Status
)) {
879 for (Index
= 0; Index
< HandleCount
; Index
++) {
880 gBS
->DisconnectController (HandleBuffer
[Index
], NULL
, NULL
);
882 for (Index
= 0; Index
< HandleCount
; Index
++) {
883 gBS
->ConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
885 if (HandleBuffer
!= NULL
) {
886 FreePool (HandleBuffer
);
894 Display the boot popup menu and allow user select boot item.
896 @param ImageHandle The image handle.
897 @param SystemTable The system table.
899 @retval EFI_SUCCESS Boot from selected boot option, and return success from boot option
900 @retval EFI_NOT_FOUND User select to enter setup or can not find boot option
905 BootManagerMenuEntry (
906 IN EFI_HANDLE ImageHandle
,
907 IN EFI_SYSTEM_TABLE
*SystemTable
910 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
;
911 UINTN BootOptionCount
;
913 BOOT_MENU_POPUP_DATA BootMenuData
;
916 BOOLEAN ExitApplication
;
918 EFI_BOOT_LOGO_PROTOCOL
*BootLogo
;
919 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
920 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
921 UINTN BootTextColumn
;
925 // Set Logo status invalid when boot manager menu is launched
928 Status
= gBS
->LocateProtocol (&gEfiBootLogoProtocolGuid
, NULL
, (VOID
**) &BootLogo
);
929 if (!EFI_ERROR (Status
) && (BootLogo
!= NULL
)) {
930 Status
= BootLogo
->SetBootLogo (BootLogo
, NULL
, 0, 0, 0, 0);
931 ASSERT_EFI_ERROR (Status
);
934 gBS
->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL
);
936 gStringPackHandle
= HiiAddPackages (
939 BootManagerMenuAppStrings
,
942 ASSERT (gStringPackHandle
!= NULL
);
945 // Connect all prior to entering the platform setup menu.
947 EfiBootManagerConnectAll ();
948 EfiBootManagerRefreshAllBootOption ();
950 BootOption
= EfiBootManagerGetLoadOptions (&BootOptionCount
, LoadOptionTypeBoot
);
952 if (!mModeInitialized
) {
954 // After the console is ready, get current video resolution
955 // and text mode before launching setup at first time.
957 Status
= gBS
->HandleProtocol (
958 gST
->ConsoleOutHandle
,
959 &gEfiGraphicsOutputProtocolGuid
,
960 (VOID
**)&GraphicsOutput
962 if (EFI_ERROR (Status
)) {
963 GraphicsOutput
= NULL
;
966 Status
= gBS
->HandleProtocol (
967 gST
->ConsoleOutHandle
,
968 &gEfiSimpleTextOutProtocolGuid
,
969 (VOID
**)&SimpleTextOut
971 if (EFI_ERROR (Status
)) {
972 SimpleTextOut
= NULL
;
975 if (GraphicsOutput
!= NULL
) {
977 // Get current video resolution and text mode.
979 mBootHorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
980 mBootVerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
983 if (SimpleTextOut
!= NULL
) {
984 Status
= SimpleTextOut
->QueryMode (
986 SimpleTextOut
->Mode
->Mode
,
990 mBootTextModeColumn
= (UINT32
)BootTextColumn
;
991 mBootTextModeRow
= (UINT32
)BootTextRow
;
995 // Get user defined text mode for setup.
997 mSetupHorizontalResolution
= PcdGet32 (PcdSetupVideoHorizontalResolution
);
998 mSetupVerticalResolution
= PcdGet32 (PcdSetupVideoVerticalResolution
);
999 mSetupTextModeColumn
= PcdGet32 (PcdSetupConOutColumn
);
1000 mSetupTextModeRow
= PcdGet32 (PcdSetupConOutRow
);
1001 mModeInitialized
= TRUE
;
1005 // Set back to conventional setup resolution
1007 BdsSetConsoleMode (TRUE
);
1010 // Initialize Boot menu data
1012 Status
= InitializeBootMenuData (BootOption
, BootOptionCount
, &BootMenuData
);
1014 // According to boot menu data to draw boot popup menu
1016 DrawBootPopupMenu (&BootMenuData
);
1019 // check user input to determine want to re-draw or boot from user selected item
1021 ExitApplication
= FALSE
;
1022 while (!ExitApplication
) {
1023 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
1024 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1025 if (!EFI_ERROR (Status
)) {
1026 switch (Key
.UnicodeChar
) {
1029 switch (Key
.ScanCode
) {
1032 SelectItem
= BootMenuData
.SelectItem
== 0 ? BootMenuData
.ItemCount
- 1 : BootMenuData
.SelectItem
- 1;
1033 BootMenuSelectItem (SelectItem
, &BootMenuData
);
1037 SelectItem
= BootMenuData
.SelectItem
== BootMenuData
.ItemCount
- 1 ? 0 : BootMenuData
.SelectItem
+ 1;
1038 BootMenuSelectItem (SelectItem
, &BootMenuData
);
1042 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1043 ExitApplication
= TRUE
;
1045 // Set boot resolution for normal boot
1047 BdsSetConsoleMode (FALSE
);
1055 case CHAR_CARRIAGE_RETURN
:
1056 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1058 // Set boot resolution for normal boot
1060 BdsSetConsoleMode (FALSE
);
1061 BootFromSelectOption (BootOption
, BootOptionCount
, BootMenuData
.SelectItem
);
1063 // Back to boot manager menu again, set back to setup resolution
1065 BdsSetConsoleMode (TRUE
);
1066 DrawBootPopupMenu (&BootMenuData
);
1074 EfiBootManagerFreeLoadOptions (BootOption
, BootOptionCount
);
1075 FreePool (BootMenuData
.PtrTokens
);
1077 HiiRemovePackages (gStringPackHandle
);