2 The application to show the Boot Manager Menu.
4 Copyright (c) 2011 - 2018, 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
49 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, Column
, Row
);
50 return Print (L
"%s", String
);
54 Prints a character to the default console, at
55 the supplied cursor position, using L"%c" format.
57 @param Column The cursor position to print the string at.
58 @param Row The cursor position to print the string at.
59 @param Character Character to print.
61 @return Length of string printed to the console.
71 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, Column
, Row
);
72 return Print (L
"%c", Character
);
76 Count the storage space of a Unicode string which uses current language to get
79 @param StringId The input string to be counted.
81 @return Storage space for the input string.
86 IN EFI_STRING_ID StringId
95 String
= HiiGetString (gStringPackHandle
, StringId
, NULL
);
103 // Advance to the null-terminator or to the first width directive
106 (String
[Index
] != NARROW_CHAR
) && (String
[Index
] != WIDE_CHAR
) && (String
[Index
] != 0);
107 Index
++, LineWidth
= LineWidth
+ IncrementValue
112 // We hit the null-terminator, we now have a count
114 if (String
[Index
] == 0) {
118 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
119 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
121 if (String
[Index
] == NARROW_CHAR
) {
123 // Skip to the next character
129 // Skip to the next character
134 } while (String
[Index
] != 0);
142 This function uses calculate the boot menu location, size and scroll bar information.
144 @param BootMenuData The boot menu data to be processed.
146 @return EFI_SUCCESS calculate boot menu information successful.
147 @retval EFI_INVALID_PARAMETER Input parameter is invalid
151 InitializeBootMenuScreen (
152 IN OUT BOOT_MENU_POPUP_DATA
*BootMenuData
161 UINTN UnSelectableItmes
;
163 if (BootMenuData
== NULL
) {
164 return EFI_INVALID_PARAMETER
;
167 // Get maximum string width
170 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++) {
171 StrWidth
= GetLineWidth (BootMenuData
->TitleToken
[Index
]);
172 MaxStrWidth
= MaxStrWidth
> StrWidth
? MaxStrWidth
: StrWidth
;
175 for (Index
= 0; Index
< BootMenuData
->ItemCount
; Index
++) {
176 StrWidth
= GetLineWidth (BootMenuData
->PtrTokens
[Index
]);
177 MaxStrWidth
= MaxStrWidth
> StrWidth
? MaxStrWidth
: StrWidth
;
180 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++) {
181 StrWidth
= GetLineWidth (BootMenuData
->HelpToken
[Index
]);
182 MaxStrWidth
= MaxStrWidth
> StrWidth
? MaxStrWidth
: StrWidth
;
185 // query current row and column to calculate boot menu location
187 gST
->ConOut
->QueryMode (
189 gST
->ConOut
->Mode
->Mode
,
194 MaxPrintRows
= Row
- 6;
195 UnSelectableItmes
= TITLE_TOKEN_COUNT
+ 2 + HELP_TOKEN_COUNT
+ 2;
196 BootMenuData
->MenuScreen
.Width
= MaxStrWidth
+ 8;
197 if (BootMenuData
->ItemCount
+ UnSelectableItmes
> MaxPrintRows
) {
198 BootMenuData
->MenuScreen
.Height
= MaxPrintRows
;
199 BootMenuData
->ScrollBarControl
.HasScrollBar
= TRUE
;
200 BootMenuData
->ScrollBarControl
.ItemCountPerScreen
= MaxPrintRows
- UnSelectableItmes
;
201 BootMenuData
->ScrollBarControl
.FirstItem
= 0;
202 BootMenuData
->ScrollBarControl
.LastItem
= MaxPrintRows
- UnSelectableItmes
- 1;
204 BootMenuData
->MenuScreen
.Height
= BootMenuData
->ItemCount
+ UnSelectableItmes
;
205 BootMenuData
->ScrollBarControl
.HasScrollBar
= FALSE
;
206 BootMenuData
->ScrollBarControl
.ItemCountPerScreen
= BootMenuData
->ItemCount
;
207 BootMenuData
->ScrollBarControl
.FirstItem
= 0;
208 BootMenuData
->ScrollBarControl
.LastItem
= BootMenuData
->ItemCount
- 1;
210 BootMenuData
->MenuScreen
.StartCol
= (Column
- BootMenuData
->MenuScreen
.Width
) / 2;
211 BootMenuData
->MenuScreen
.StartRow
= (Row
- BootMenuData
->MenuScreen
.Height
) / 2;
216 This function uses check boot option is wheher setup application or no
218 @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
220 @retval TRUE This boot option is setup application.
221 @retval FALSE This boot options isn't setup application
226 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
230 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
232 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
233 if (!EFI_ERROR (Status
)) {
234 EfiBootManagerFreeLoadOption (&BootManagerMenu
);
237 return (BOOLEAN
) (!EFI_ERROR (Status
) && (BootOption
->OptionNumber
== BootManagerMenu
.OptionNumber
));
241 Return whether to ignore the boot option.
243 @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION to check.
245 @retval TRUE Ignore the boot option.
246 @retval FALSE Do not ignore the boot option.
250 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
254 EFI_DEVICE_PATH_PROTOCOL
*ImageDevicePath
;
259 Status
= gBS
->HandleProtocol (gImageHandle
, &gEfiLoadedImageDevicePathProtocolGuid
, (VOID
**) &ImageDevicePath
);
260 ASSERT_EFI_ERROR (Status
);
261 if (CompareMem (BootOption
->FilePath
, ImageDevicePath
, GetDevicePathSize (ImageDevicePath
)) == 0) {
266 // Do not ignore Boot Manager Menu.
268 if (IsBootManagerMenu (BootOption
)) {
273 // Ignore the hidden/inactive boot option.
275 if (((BootOption
->Attributes
& LOAD_OPTION_HIDDEN
) != 0) || ((BootOption
->Attributes
& LOAD_OPTION_ACTIVE
) == 0)) {
283 This function uses to initialize boot menu data
285 @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
286 @param BootOptionCount Number of boot option.
287 @param BootMenuData The Input BootMenuData to be initialized.
289 @retval EFI_SUCCESS Initialize boot menu data successful.
290 @retval EFI_INVALID_PARAMETER Input parameter is invalid.
294 InitializeBootMenuData (
295 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
,
296 IN UINTN BootOptionCount
,
297 OUT BOOT_MENU_POPUP_DATA
*BootMenuData
303 if (BootOption
== NULL
|| BootMenuData
== NULL
) {
304 return EFI_INVALID_PARAMETER
;
307 BootMenuData
->TitleToken
[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_TITLE_STRING
);
308 BootMenuData
->PtrTokens
= AllocateZeroPool (BootOptionCount
* sizeof (EFI_STRING_ID
));
309 ASSERT (BootMenuData
->PtrTokens
!= NULL
);
312 // Skip boot option which created by BootNext Variable
314 for (StrIndex
= 0, Index
= 0; Index
< BootOptionCount
; Index
++) {
315 if (IgnoreBootOption (&BootOption
[Index
])) {
319 ASSERT (BootOption
[Index
].Description
!= NULL
);
320 BootMenuData
->PtrTokens
[StrIndex
++] = HiiSetString (
323 BootOption
[Index
].Description
,
328 BootMenuData
->ItemCount
= StrIndex
;
329 BootMenuData
->HelpToken
[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP1_STRING
);
330 BootMenuData
->HelpToken
[1] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP2_STRING
);
331 BootMenuData
->HelpToken
[2] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP3_STRING
);
332 InitializeBootMenuScreen (BootMenuData
);
333 BootMenuData
->SelectItem
= 0;
338 This function uses input select item to highlight selected item
339 and set current selected item in BootMenuData
341 @param WantSelectItem The user wants to select item.
342 @param BootMenuData The boot menu data to be processed
344 @return EFI_SUCCESS Highlight selected item and update current selected
346 @retval EFI_INVALID_PARAMETER Input parameter is invalid
350 IN UINTN WantSelectItem
,
351 IN OUT BOOT_MENU_POPUP_DATA
*BootMenuData
354 INT32 SavedAttribute
;
364 UINTN ItemCountPerScreen
;
366 BOOLEAN RePaintItems
;
368 if (BootMenuData
== NULL
|| WantSelectItem
>= BootMenuData
->ItemCount
) {
369 return EFI_INVALID_PARAMETER
;
371 ASSERT (BootMenuData
->ItemCount
!= 0);
372 SavedAttribute
= gST
->ConOut
->Mode
->Attribute
;
373 RePaintItems
= FALSE
;
374 StartCol
= BootMenuData
->MenuScreen
.StartCol
;
375 StartRow
= BootMenuData
->MenuScreen
.StartRow
;
377 // print selectable items again and adjust scroll bar if need
379 if (BootMenuData
->ScrollBarControl
.HasScrollBar
&&
380 (WantSelectItem
< BootMenuData
->ScrollBarControl
.FirstItem
||
381 WantSelectItem
> BootMenuData
->ScrollBarControl
.LastItem
||
382 WantSelectItem
== BootMenuData
->SelectItem
)) {
383 ItemCountPerScreen
= BootMenuData
->ScrollBarControl
.ItemCountPerScreen
;
385 // Set first item and last item
387 if (WantSelectItem
< BootMenuData
->ScrollBarControl
.FirstItem
) {
388 BootMenuData
->ScrollBarControl
.FirstItem
= WantSelectItem
;
389 BootMenuData
->ScrollBarControl
.LastItem
= WantSelectItem
+ ItemCountPerScreen
- 1;
390 } else if (WantSelectItem
> BootMenuData
->ScrollBarControl
.LastItem
) {
391 BootMenuData
->ScrollBarControl
.FirstItem
= WantSelectItem
- ItemCountPerScreen
+ 1;
392 BootMenuData
->ScrollBarControl
.LastItem
= WantSelectItem
;
394 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
395 FirstItem
= BootMenuData
->ScrollBarControl
.FirstItem
;
396 LastItem
= BootMenuData
->ScrollBarControl
.LastItem
;
398 if (FirstItem
!= 0) {
399 TopShadeNum
= (FirstItem
* ItemCountPerScreen
) / BootMenuData
->ItemCount
;
400 if ((FirstItem
* ItemCountPerScreen
) % BootMenuData
->ItemCount
!= 0) {
403 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
404 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
405 for (Index
= 0; Index
< TopShadeNum
; Index
++, PrintRow
++) {
406 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_LIGHT_SHADE
);
410 if (LastItem
!= BootMenuData
->ItemCount
- 1) {
411 LowShadeNum
= ((BootMenuData
->ItemCount
- 1 - LastItem
) * ItemCountPerScreen
) / BootMenuData
->ItemCount
;
412 if (((BootMenuData
->ItemCount
- 1 - LastItem
) * ItemCountPerScreen
) % BootMenuData
->ItemCount
!= 0) {
415 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
416 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + ItemCountPerScreen
- LowShadeNum
;
417 for (Index
= 0; Index
< LowShadeNum
; Index
++, PrintRow
++) {
418 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_LIGHT_SHADE
);
421 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
422 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + TopShadeNum
;
423 for (Index
= TopShadeNum
; Index
< ItemCountPerScreen
- LowShadeNum
; Index
++, PrintRow
++) {
424 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_FULL_BLOCK
);
429 // Clear selectable items first
431 PrintCol
= StartCol
+ 1;
432 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
433 String
= AllocateZeroPool ((BootMenuData
->MenuScreen
.Width
- 2) * sizeof (CHAR16
));
434 ASSERT (String
!= NULL
);
435 for (Index
= 0; Index
< BootMenuData
->MenuScreen
.Width
- 3; Index
++) {
436 String
[Index
] = 0x20;
438 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++) {
439 PrintStringAt (PrintCol
, PrintRow
+ Index
, String
);
443 // print selectable items
445 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++, PrintRow
++) {
446 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[Index
+ FirstItem
], NULL
);
447 PrintStringAt (PrintCol
, PrintRow
, String
);
454 // Print want to select item
456 FirstItem
= BootMenuData
->ScrollBarControl
.FirstItem
;
457 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLACK
);
458 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[WantSelectItem
], NULL
);
459 PrintCol
= StartCol
+ 1;
460 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + WantSelectItem
- FirstItem
;
461 PrintStringAt (PrintCol
, PrintRow
, String
);
465 // if Want Select and selected item isn't the same and doesn't re-draw selectable
466 // items, clear select item
468 if (WantSelectItem
!= BootMenuData
->SelectItem
&& !RePaintItems
) {
469 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
470 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[BootMenuData
->SelectItem
], NULL
);
471 PrintCol
= StartCol
+ 1;
472 PrintRow
= StartRow
+ 3 + BootMenuData
->SelectItem
- FirstItem
;
473 PrintStringAt (PrintCol
, PrintRow
, String
);
477 gST
->ConOut
->SetAttribute (gST
->ConOut
, SavedAttribute
);
478 BootMenuData
->SelectItem
= WantSelectItem
;
483 This function uses to draw boot popup menu
485 @param BootMenuData The Input BootMenuData to be processed.
487 @retval EFI_SUCCESS Draw boot popup menu successful.
492 IN BOOT_MENU_POPUP_DATA
*BootMenuData
503 INT32 SavedAttribute
;
504 UINTN ItemCountPerScreen
;
506 gST
->ConOut
->ClearScreen (gST
->ConOut
);
508 SavedAttribute
= gST
->ConOut
->Mode
->Attribute
;
509 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
510 Width
= BootMenuData
->MenuScreen
.Width
;
511 StartCol
= BootMenuData
->MenuScreen
.StartCol
;
512 StartRow
= BootMenuData
->MenuScreen
.StartRow
;
513 ItemCountPerScreen
= BootMenuData
->ScrollBarControl
.ItemCountPerScreen
;
516 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
518 // Draw Boot popup menu screen
520 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_DOWN_RIGHT
);
521 for (Index
= 1; Index
< Width
- 1; Index
++) {
522 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
524 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_DOWN_LEFT
);
527 // Draw the screen for title
529 String
= AllocateZeroPool ((Width
- 1) * sizeof (CHAR16
));
530 ASSERT (String
!= NULL
);
531 for (Index
= 0; Index
< Width
- 2; Index
++) {
532 String
[Index
] = 0x20;
535 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++) {
537 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
538 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
539 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
543 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL_RIGHT
);
544 for (Index
= 1; Index
< Width
- 1; Index
++) {
545 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
547 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL_LEFT
);
550 // Draw screen for selectable items
552 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++) {
554 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
555 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
556 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
560 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL_RIGHT
);
561 for (Index
= 1; Index
< Width
- 1; Index
++) {
562 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
564 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL_LEFT
);
567 // Draw screen for Help
569 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++) {
571 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
572 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
573 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
578 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_UP_RIGHT
);
579 for (Index
= 1; Index
< Width
- 1; Index
++) {
580 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
582 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_UP_LEFT
);
586 // print title strings
588 PrintRow
= StartRow
+ 1;
589 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++, PrintRow
++) {
590 String
= HiiGetString (gStringPackHandle
, BootMenuData
->TitleToken
[Index
], NULL
);
591 LineWidth
= GetLineWidth (BootMenuData
->TitleToken
[Index
]);
592 PrintCol
= StartCol
+ (Width
- LineWidth
) / 2;
593 PrintStringAt (PrintCol
, PrintRow
, String
);
598 // print selectable items
600 PrintCol
= StartCol
+ 1;
601 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
602 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++, PrintRow
++) {
603 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[Index
], NULL
);
604 PrintStringAt (PrintCol
, PrintRow
, String
);
609 // Print Help strings
612 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++, PrintRow
++) {
613 String
= HiiGetString (gStringPackHandle
, BootMenuData
->HelpToken
[Index
], NULL
);
614 LineWidth
= GetLineWidth (BootMenuData
->HelpToken
[Index
]);
615 PrintCol
= StartCol
+ (Width
- LineWidth
) / 2;
616 PrintStringAt (PrintCol
, PrintRow
, String
);
621 // Print scroll bar if has scroll bar
623 if (BootMenuData
->ScrollBarControl
.HasScrollBar
) {
624 PrintCol
= StartCol
+ Width
- 2;
625 PrintRow
= StartRow
+ 2;
626 PrintCharAt (PrintCol
, PrintRow
, GEOMETRICSHAPE_UP_TRIANGLE
);
627 PrintCharAt (PrintCol
+ 1, PrintRow
, BOXDRAW_VERTICAL
);
628 PrintRow
+= (ItemCountPerScreen
+ 1);
629 PrintCharAt (PrintCol
, PrintRow
, GEOMETRICSHAPE_DOWN_TRIANGLE
);
630 PrintCharAt (PrintCol
+ 1, PrintRow
, BOXDRAW_VERTICAL
);
633 gST
->ConOut
->SetAttribute (gST
->ConOut
, SavedAttribute
);
635 // Print Selected item
637 BootMenuSelectItem (BootMenuData
->SelectItem
, BootMenuData
);
642 This function uses to boot from selected item
644 @param BootOptions Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
645 @param BootOptionCount Number of boot option.
646 @param SelectItem Current selected item.
649 BootFromSelectOption (
650 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
,
651 IN UINTN BootOptionCount
,
658 ASSERT (BootOptions
!= NULL
);
660 for (ItemNum
= 0, Index
= 0; Index
< BootOptionCount
; Index
++) {
661 if (IgnoreBootOption (&BootOptions
[Index
])) {
665 if (ItemNum
++ == SelectItem
) {
666 EfiBootManagerBoot (&BootOptions
[Index
]);
673 This function will change video resolution and text mode
674 according to defined setup mode or defined boot mode
676 @param IsSetupMode Indicate mode is changed to setup mode or boot mode.
678 @retval EFI_SUCCESS Mode is changed successfully.
679 @retval Others Mode failed to be changed.
688 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
689 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
691 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
695 UINT32 NewHorizontalResolution
;
696 UINT32 NewVerticalResolution
;
700 EFI_HANDLE
*HandleBuffer
;
710 // Get current video resolution and text mode
712 Status
= gBS
->HandleProtocol (
713 gST
->ConsoleOutHandle
,
714 &gEfiGraphicsOutputProtocolGuid
,
715 (VOID
**)&GraphicsOutput
717 if (EFI_ERROR (Status
)) {
718 GraphicsOutput
= NULL
;
721 Status
= gBS
->HandleProtocol (
722 gST
->ConsoleOutHandle
,
723 &gEfiSimpleTextOutProtocolGuid
,
724 (VOID
**)&SimpleTextOut
726 if (EFI_ERROR (Status
)) {
727 SimpleTextOut
= NULL
;
730 if ((GraphicsOutput
== NULL
) || (SimpleTextOut
== NULL
)) {
731 return EFI_UNSUPPORTED
;
736 // The required resolution and text mode is setup mode.
738 NewHorizontalResolution
= mSetupHorizontalResolution
;
739 NewVerticalResolution
= mSetupVerticalResolution
;
740 NewColumns
= mSetupTextModeColumn
;
741 NewRows
= mSetupTextModeRow
;
744 // The required resolution and text mode is boot mode.
746 NewHorizontalResolution
= mBootHorizontalResolution
;
747 NewVerticalResolution
= mBootVerticalResolution
;
748 NewColumns
= mBootTextModeColumn
;
749 NewRows
= mBootTextModeRow
;
752 if (GraphicsOutput
!= NULL
) {
753 MaxGopMode
= GraphicsOutput
->Mode
->MaxMode
;
756 if (SimpleTextOut
!= NULL
) {
757 MaxTextMode
= SimpleTextOut
->Mode
->MaxMode
;
761 // 1. If current video resolution is same with required video resolution,
762 // video resolution need not be changed.
763 // 1.1. If current text mode is same with required text mode, text mode need not be changed.
764 // 1.2. If current text mode is different from required text mode, text mode need be changed.
765 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.
767 for (ModeNumber
= 0; ModeNumber
< MaxGopMode
; ModeNumber
++) {
768 Status
= GraphicsOutput
->QueryMode (
774 if (!EFI_ERROR (Status
)) {
775 if ((Info
->HorizontalResolution
== NewHorizontalResolution
) &&
776 (Info
->VerticalResolution
== NewVerticalResolution
)) {
777 if ((GraphicsOutput
->Mode
->Info
->HorizontalResolution
== NewHorizontalResolution
) &&
778 (GraphicsOutput
->Mode
->Info
->VerticalResolution
== NewVerticalResolution
)) {
780 // Current resolution is same with required resolution, check if text mode need be set
782 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, SimpleTextOut
->Mode
->Mode
, &CurrentColumn
, &CurrentRow
);
783 ASSERT_EFI_ERROR (Status
);
784 if (CurrentColumn
== NewColumns
&& CurrentRow
== NewRows
) {
786 // If current text mode is same with required text mode. Do nothing
792 // If current text mode is different from required text mode. Set new video mode
794 for (Index
= 0; Index
< MaxTextMode
; Index
++) {
795 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, Index
, &CurrentColumn
, &CurrentRow
);
796 if (!EFI_ERROR(Status
)) {
797 if ((CurrentColumn
== NewColumns
) && (CurrentRow
== NewRows
)) {
799 // Required text mode is supported, set it.
801 Status
= SimpleTextOut
->SetMode (SimpleTextOut
, Index
);
802 ASSERT_EFI_ERROR (Status
);
804 // Update text mode PCD.
806 Status
= PcdSet32S (PcdConOutColumn
, mSetupTextModeColumn
);
807 ASSERT_EFI_ERROR (Status
);
808 Status
= PcdSet32S (PcdConOutRow
, mSetupTextModeRow
);
809 ASSERT_EFI_ERROR (Status
);
815 if (Index
== MaxTextMode
) {
817 // If required text mode is not supported, return error.
820 return EFI_UNSUPPORTED
;
825 // If current video resolution is not same with the new one, set new video resolution.
826 // In this case, the driver which produces simple text out need be restarted.
828 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, ModeNumber
);
829 if (!EFI_ERROR (Status
)) {
839 if (ModeNumber
== MaxGopMode
) {
841 // If the resolution is not supported, return error.
843 return EFI_UNSUPPORTED
;
847 // Set PCD to Inform GraphicsConsole to change video resolution.
848 // Set PCD to Inform Consplitter to change text mode.
850 Status
= PcdSet32S (PcdVideoHorizontalResolution
, NewHorizontalResolution
);
851 ASSERT_EFI_ERROR (Status
);
852 Status
= PcdSet32S (PcdVideoVerticalResolution
, NewVerticalResolution
);
853 ASSERT_EFI_ERROR (Status
);
854 Status
= PcdSet32S (PcdConOutColumn
, NewColumns
);
855 ASSERT_EFI_ERROR (Status
);
856 Status
= PcdSet32S (PcdConOutRow
, NewRows
);
857 ASSERT_EFI_ERROR (Status
);
860 // Video mode is changed, so restart graphics console driver and higher level driver.
861 // Reconnect graphics console driver and higher level driver.
862 // Locate all the handles with GOP protocol and reconnect it.
864 Status
= gBS
->LocateHandleBuffer (
866 &gEfiSimpleTextOutProtocolGuid
,
871 if (!EFI_ERROR (Status
)) {
872 for (Index
= 0; Index
< HandleCount
; Index
++) {
873 gBS
->DisconnectController (HandleBuffer
[Index
], NULL
, NULL
);
875 for (Index
= 0; Index
< HandleCount
; Index
++) {
876 gBS
->ConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
878 if (HandleBuffer
!= NULL
) {
879 FreePool (HandleBuffer
);
887 Display the boot popup menu and allow user select boot item.
889 @param ImageHandle The image handle.
890 @param SystemTable The system table.
892 @retval EFI_SUCCESS Boot from selected boot option, and return success from boot option
893 @retval EFI_NOT_FOUND User select to enter setup or can not find boot option
898 BootManagerMenuEntry (
899 IN EFI_HANDLE ImageHandle
,
900 IN EFI_SYSTEM_TABLE
*SystemTable
903 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
;
904 UINTN BootOptionCount
;
906 BOOT_MENU_POPUP_DATA BootMenuData
;
909 BOOLEAN ExitApplication
;
911 EFI_BOOT_LOGO_PROTOCOL
*BootLogo
;
912 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
913 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
914 UINTN BootTextColumn
;
918 // Set Logo status invalid when boot manager menu is launched
921 Status
= gBS
->LocateProtocol (&gEfiBootLogoProtocolGuid
, NULL
, (VOID
**) &BootLogo
);
922 if (!EFI_ERROR (Status
) && (BootLogo
!= NULL
)) {
923 Status
= BootLogo
->SetBootLogo (BootLogo
, NULL
, 0, 0, 0, 0);
924 ASSERT_EFI_ERROR (Status
);
927 gBS
->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL
);
929 gStringPackHandle
= HiiAddPackages (
932 BootManagerMenuAppStrings
,
935 ASSERT (gStringPackHandle
!= NULL
);
938 // Connect all prior to entering the platform setup menu.
940 EfiBootManagerConnectAll ();
941 EfiBootManagerRefreshAllBootOption ();
943 BootOption
= EfiBootManagerGetLoadOptions (&BootOptionCount
, LoadOptionTypeBoot
);
945 if (!mModeInitialized
) {
947 // After the console is ready, get current video resolution
948 // and text mode before launching setup at first time.
950 Status
= gBS
->HandleProtocol (
951 gST
->ConsoleOutHandle
,
952 &gEfiGraphicsOutputProtocolGuid
,
953 (VOID
**)&GraphicsOutput
955 if (EFI_ERROR (Status
)) {
956 GraphicsOutput
= NULL
;
959 Status
= gBS
->HandleProtocol (
960 gST
->ConsoleOutHandle
,
961 &gEfiSimpleTextOutProtocolGuid
,
962 (VOID
**)&SimpleTextOut
964 if (EFI_ERROR (Status
)) {
965 SimpleTextOut
= NULL
;
968 if (GraphicsOutput
!= NULL
) {
970 // Get current video resolution and text mode.
972 mBootHorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
973 mBootVerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
976 if (SimpleTextOut
!= NULL
) {
977 Status
= SimpleTextOut
->QueryMode (
979 SimpleTextOut
->Mode
->Mode
,
983 mBootTextModeColumn
= (UINT32
)BootTextColumn
;
984 mBootTextModeRow
= (UINT32
)BootTextRow
;
988 // Get user defined text mode for setup.
990 mSetupHorizontalResolution
= PcdGet32 (PcdSetupVideoHorizontalResolution
);
991 mSetupVerticalResolution
= PcdGet32 (PcdSetupVideoVerticalResolution
);
992 mSetupTextModeColumn
= PcdGet32 (PcdSetupConOutColumn
);
993 mSetupTextModeRow
= PcdGet32 (PcdSetupConOutRow
);
994 mModeInitialized
= TRUE
;
998 // Set back to conventional setup resolution
1000 BdsSetConsoleMode (TRUE
);
1003 // Initialize Boot menu data
1005 Status
= InitializeBootMenuData (BootOption
, BootOptionCount
, &BootMenuData
);
1007 // According to boot menu data to draw boot popup menu
1009 DrawBootPopupMenu (&BootMenuData
);
1012 // check user input to determine want to re-draw or boot from user selected item
1014 ExitApplication
= FALSE
;
1015 while (!ExitApplication
) {
1016 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
1017 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1018 if (!EFI_ERROR (Status
)) {
1019 switch (Key
.UnicodeChar
) {
1022 switch (Key
.ScanCode
) {
1025 SelectItem
= BootMenuData
.SelectItem
== 0 ? BootMenuData
.ItemCount
- 1 : BootMenuData
.SelectItem
- 1;
1026 BootMenuSelectItem (SelectItem
, &BootMenuData
);
1030 SelectItem
= BootMenuData
.SelectItem
== BootMenuData
.ItemCount
- 1 ? 0 : BootMenuData
.SelectItem
+ 1;
1031 BootMenuSelectItem (SelectItem
, &BootMenuData
);
1035 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1036 ExitApplication
= TRUE
;
1038 // Set boot resolution for normal boot
1040 BdsSetConsoleMode (FALSE
);
1048 case CHAR_CARRIAGE_RETURN
:
1049 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1051 // Set boot resolution for normal boot
1053 BdsSetConsoleMode (FALSE
);
1054 BootFromSelectOption (BootOption
, BootOptionCount
, BootMenuData
.SelectItem
);
1056 // Back to boot manager menu again, set back to setup resolution
1058 BdsSetConsoleMode (TRUE
);
1059 DrawBootPopupMenu (&BootMenuData
);
1067 EfiBootManagerFreeLoadOptions (BootOption
, BootOptionCount
);
1068 FreePool (BootMenuData
.PtrTokens
);
1070 HiiRemovePackages (gStringPackHandle
);