2 The application to show the Boot Manager Menu.
4 Copyright (c) 2011 - 2016, 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
508 INT32 SavedAttribute
;
509 UINTN ItemCountPerScreen
;
511 gST
->ConOut
->ClearScreen (gST
->ConOut
);
513 SavedAttribute
= gST
->ConOut
->Mode
->Attribute
;
514 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
515 Width
= BootMenuData
->MenuScreen
.Width
;
516 StartCol
= BootMenuData
->MenuScreen
.StartCol
;
517 StartRow
= BootMenuData
->MenuScreen
.StartRow
;
518 ItemCountPerScreen
= BootMenuData
->ScrollBarControl
.ItemCountPerScreen
;
521 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
523 // Draw Boot popup menu screen
525 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_DOWN_RIGHT
);
526 for (Index
= 1; Index
< Width
- 1; Index
++) {
527 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
529 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_DOWN_LEFT
);
532 // Draw the screen for title
534 String
= AllocateZeroPool ((Width
- 1) * sizeof (CHAR16
));
535 ASSERT (String
!= NULL
);
536 for (Index
= 0; Index
< Width
- 2; Index
++) {
537 String
[Index
] = 0x20;
540 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++) {
542 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
543 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
544 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
548 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL_RIGHT
);
549 for (Index
= 1; Index
< Width
- 1; Index
++) {
550 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
552 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL_LEFT
);
555 // Draw screen for selectable items
557 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++) {
559 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
560 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
561 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
565 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL_RIGHT
);
566 for (Index
= 1; Index
< Width
- 1; Index
++) {
567 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
569 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL_LEFT
);
572 // Draw screen for Help
574 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++) {
576 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
577 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
578 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
583 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_UP_RIGHT
);
584 for (Index
= 1; Index
< Width
- 1; Index
++) {
585 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
587 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_UP_LEFT
);
591 // print title strings
593 PrintRow
= StartRow
+ 1;
594 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++, PrintRow
++) {
595 String
= HiiGetString (gStringPackHandle
, BootMenuData
->TitleToken
[Index
], NULL
);
596 LineWidth
= GetLineWidth (BootMenuData
->TitleToken
[Index
]);
597 PrintCol
= StartCol
+ (Width
- LineWidth
) / 2;
598 PrintStringAt (PrintCol
, PrintRow
, String
);
603 // print selectable items
605 PrintCol
= StartCol
+ 1;
606 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
607 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++, PrintRow
++) {
608 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[Index
], NULL
);
609 PrintStringAt (PrintCol
, PrintRow
, String
);
614 // Print Help strings
617 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++, PrintRow
++) {
618 String
= HiiGetString (gStringPackHandle
, BootMenuData
->HelpToken
[Index
], NULL
);
619 LineWidth
= GetLineWidth (BootMenuData
->HelpToken
[Index
]);
620 PrintCol
= StartCol
+ (Width
- LineWidth
) / 2;
621 PrintStringAt (PrintCol
, PrintRow
, String
);
626 // Print scroll bar if has scroll bar
628 if (BootMenuData
->ScrollBarControl
.HasScrollBar
) {
629 PrintCol
= StartCol
+ Width
- 2;
630 PrintRow
= StartRow
+ 2;
631 PrintCharAt (PrintCol
, PrintRow
, GEOMETRICSHAPE_UP_TRIANGLE
);
632 PrintCharAt (PrintCol
+ 1, PrintRow
, BOXDRAW_VERTICAL
);
633 PrintRow
+= (ItemCountPerScreen
+ 1);
634 PrintCharAt (PrintCol
, PrintRow
, GEOMETRICSHAPE_DOWN_TRIANGLE
);
635 PrintCharAt (PrintCol
+ 1, PrintRow
, BOXDRAW_VERTICAL
);
638 gST
->ConOut
->SetAttribute (gST
->ConOut
, SavedAttribute
);
640 // Print Selected item
642 BootMenuSelectItem (BootMenuData
->SelectItem
, BootMenuData
);
647 This funciton uses to boot from selected item
649 @param BootOptions Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
650 @param BootOptionCount Number of boot option.
651 @param SelectItem Current selected item.
654 BootFromSelectOption (
655 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
,
656 IN UINTN BootOptionCount
,
663 ASSERT (BootOptions
!= NULL
);
665 for (ItemNum
= 0, Index
= 0; Index
< BootOptionCount
; Index
++) {
666 if (IgnoreBootOption (&BootOptions
[Index
])) {
670 if (ItemNum
++ == SelectItem
) {
671 EfiBootManagerBoot (&BootOptions
[Index
]);
678 This function will change video resolution and text mode
679 according to defined setup mode or defined boot mode
681 @param IsSetupMode Indicate mode is changed to setup mode or boot mode.
683 @retval EFI_SUCCESS Mode is changed successfully.
684 @retval Others Mode failed to be changed.
693 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
694 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
696 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
700 UINT32 NewHorizontalResolution
;
701 UINT32 NewVerticalResolution
;
705 EFI_HANDLE
*HandleBuffer
;
715 // Get current video resolution and text mode
717 Status
= gBS
->HandleProtocol (
718 gST
->ConsoleOutHandle
,
719 &gEfiGraphicsOutputProtocolGuid
,
720 (VOID
**)&GraphicsOutput
722 if (EFI_ERROR (Status
)) {
723 GraphicsOutput
= NULL
;
726 Status
= gBS
->HandleProtocol (
727 gST
->ConsoleOutHandle
,
728 &gEfiSimpleTextOutProtocolGuid
,
729 (VOID
**)&SimpleTextOut
731 if (EFI_ERROR (Status
)) {
732 SimpleTextOut
= NULL
;
735 if ((GraphicsOutput
== NULL
) || (SimpleTextOut
== NULL
)) {
736 return EFI_UNSUPPORTED
;
741 // The required resolution and text mode is setup mode.
743 NewHorizontalResolution
= mSetupHorizontalResolution
;
744 NewVerticalResolution
= mSetupVerticalResolution
;
745 NewColumns
= mSetupTextModeColumn
;
746 NewRows
= mSetupTextModeRow
;
749 // The required resolution and text mode is boot mode.
751 NewHorizontalResolution
= mBootHorizontalResolution
;
752 NewVerticalResolution
= mBootVerticalResolution
;
753 NewColumns
= mBootTextModeColumn
;
754 NewRows
= mBootTextModeRow
;
757 if (GraphicsOutput
!= NULL
) {
758 MaxGopMode
= GraphicsOutput
->Mode
->MaxMode
;
761 if (SimpleTextOut
!= NULL
) {
762 MaxTextMode
= SimpleTextOut
->Mode
->MaxMode
;
766 // 1. If current video resolution is same with required video resolution,
767 // video resolution need not be changed.
768 // 1.1. If current text mode is same with required text mode, text mode need not be changed.
769 // 1.2. If current text mode is different from required text mode, text mode need be changed.
770 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.
772 for (ModeNumber
= 0; ModeNumber
< MaxGopMode
; ModeNumber
++) {
773 Status
= GraphicsOutput
->QueryMode (
779 if (!EFI_ERROR (Status
)) {
780 if ((Info
->HorizontalResolution
== NewHorizontalResolution
) &&
781 (Info
->VerticalResolution
== NewVerticalResolution
)) {
782 if ((GraphicsOutput
->Mode
->Info
->HorizontalResolution
== NewHorizontalResolution
) &&
783 (GraphicsOutput
->Mode
->Info
->VerticalResolution
== NewVerticalResolution
)) {
785 // Current resolution is same with required resolution, check if text mode need be set
787 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, SimpleTextOut
->Mode
->Mode
, &CurrentColumn
, &CurrentRow
);
788 ASSERT_EFI_ERROR (Status
);
789 if (CurrentColumn
== NewColumns
&& CurrentRow
== NewRows
) {
791 // If current text mode is same with required text mode. Do nothing
797 // If current text mode is different from required text mode. Set new video mode
799 for (Index
= 0; Index
< MaxTextMode
; Index
++) {
800 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, Index
, &CurrentColumn
, &CurrentRow
);
801 if (!EFI_ERROR(Status
)) {
802 if ((CurrentColumn
== NewColumns
) && (CurrentRow
== NewRows
)) {
804 // Required text mode is supported, set it.
806 Status
= SimpleTextOut
->SetMode (SimpleTextOut
, Index
);
807 ASSERT_EFI_ERROR (Status
);
809 // Update text mode PCD.
811 Status
= PcdSet32S (PcdConOutColumn
, mSetupTextModeColumn
);
812 ASSERT_EFI_ERROR (Status
);
813 Status
= PcdSet32S (PcdConOutRow
, mSetupTextModeRow
);
814 ASSERT_EFI_ERROR (Status
);
820 if (Index
== MaxTextMode
) {
822 // If required text mode is not supported, return error.
825 return EFI_UNSUPPORTED
;
830 // If current video resolution is not same with the new one, set new video resolution.
831 // In this case, the driver which produces simple text out need be restarted.
833 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, ModeNumber
);
834 if (!EFI_ERROR (Status
)) {
844 if (ModeNumber
== MaxGopMode
) {
846 // If the resolution is not supported, return error.
848 return EFI_UNSUPPORTED
;
852 // Set PCD to Inform GraphicsConsole to change video resolution.
853 // Set PCD to Inform Consplitter to change text mode.
855 Status
= PcdSet32S (PcdVideoHorizontalResolution
, NewHorizontalResolution
);
856 ASSERT_EFI_ERROR (Status
);
857 Status
= PcdSet32S (PcdVideoVerticalResolution
, NewVerticalResolution
);
858 ASSERT_EFI_ERROR (Status
);
859 Status
= PcdSet32S (PcdConOutColumn
, NewColumns
);
860 ASSERT_EFI_ERROR (Status
);
861 Status
= PcdSet32S (PcdConOutRow
, NewRows
);
862 ASSERT_EFI_ERROR (Status
);
865 // Video mode is changed, so restart graphics console driver and higher level driver.
866 // Reconnect graphics console driver and higher level driver.
867 // Locate all the handles with GOP protocol and reconnect it.
869 Status
= gBS
->LocateHandleBuffer (
871 &gEfiSimpleTextOutProtocolGuid
,
876 if (!EFI_ERROR (Status
)) {
877 for (Index
= 0; Index
< HandleCount
; Index
++) {
878 gBS
->DisconnectController (HandleBuffer
[Index
], NULL
, NULL
);
880 for (Index
= 0; Index
< HandleCount
; Index
++) {
881 gBS
->ConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
883 if (HandleBuffer
!= NULL
) {
884 FreePool (HandleBuffer
);
892 Display the boot popup menu and allow user select boot item.
894 @param ImageHandle The image handle.
895 @param SystemTable The system table.
897 @retval EFI_SUCCESS Boot from selected boot option, and return success from boot option
898 @retval EFI_NOT_FOUND User select to enter setup or can not find boot option
903 BootManagerMenuEntry (
904 IN EFI_HANDLE ImageHandle
,
905 IN EFI_SYSTEM_TABLE
*SystemTable
908 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
;
909 UINTN BootOptionCount
;
911 BOOT_MENU_POPUP_DATA BootMenuData
;
914 BOOLEAN ExitApplication
;
916 EFI_BOOT_LOGO_PROTOCOL
*BootLogo
;
917 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
918 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
919 UINTN BootTextColumn
;
923 // Set Logo status invalid when boot manager menu is launched
926 Status
= gBS
->LocateProtocol (&gEfiBootLogoProtocolGuid
, NULL
, (VOID
**) &BootLogo
);
927 if (!EFI_ERROR (Status
) && (BootLogo
!= NULL
)) {
928 Status
= BootLogo
->SetBootLogo (BootLogo
, NULL
, 0, 0, 0, 0);
929 ASSERT_EFI_ERROR (Status
);
932 gBS
->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL
);
934 gStringPackHandle
= HiiAddPackages (
937 BootManagerMenuAppStrings
,
940 ASSERT (gStringPackHandle
!= NULL
);
943 // Connect all prior to entering the platform setup menu.
945 EfiBootManagerConnectAll ();
946 EfiBootManagerRefreshAllBootOption ();
948 BootOption
= EfiBootManagerGetLoadOptions (&BootOptionCount
, LoadOptionTypeBoot
);
950 if (!mModeInitialized
) {
952 // After the console is ready, get current video resolution
953 // and text mode before launching setup at first time.
955 Status
= gBS
->HandleProtocol (
956 gST
->ConsoleOutHandle
,
957 &gEfiGraphicsOutputProtocolGuid
,
958 (VOID
**)&GraphicsOutput
960 if (EFI_ERROR (Status
)) {
961 GraphicsOutput
= NULL
;
964 Status
= gBS
->HandleProtocol (
965 gST
->ConsoleOutHandle
,
966 &gEfiSimpleTextOutProtocolGuid
,
967 (VOID
**)&SimpleTextOut
969 if (EFI_ERROR (Status
)) {
970 SimpleTextOut
= NULL
;
973 if (GraphicsOutput
!= NULL
) {
975 // Get current video resolution and text mode.
977 mBootHorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
978 mBootVerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
981 if (SimpleTextOut
!= NULL
) {
982 Status
= SimpleTextOut
->QueryMode (
984 SimpleTextOut
->Mode
->Mode
,
988 mBootTextModeColumn
= (UINT32
)BootTextColumn
;
989 mBootTextModeRow
= (UINT32
)BootTextRow
;
993 // Get user defined text mode for setup.
995 mSetupHorizontalResolution
= PcdGet32 (PcdSetupVideoHorizontalResolution
);
996 mSetupVerticalResolution
= PcdGet32 (PcdSetupVideoVerticalResolution
);
997 mSetupTextModeColumn
= PcdGet32 (PcdSetupConOutColumn
);
998 mSetupTextModeRow
= PcdGet32 (PcdSetupConOutRow
);
999 mModeInitialized
= TRUE
;
1003 // Set back to conventional setup resolution
1005 BdsSetConsoleMode (TRUE
);
1008 // Initialize Boot menu data
1010 Status
= InitializeBootMenuData (BootOption
, BootOptionCount
, &BootMenuData
);
1012 // According to boot menu data to draw boot popup menu
1014 DrawBootPopupMenu (&BootMenuData
);
1017 // check user input to determine want to re-draw or boot from user selected item
1019 ExitApplication
= FALSE
;
1020 while (!ExitApplication
) {
1021 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
1022 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1023 if (!EFI_ERROR (Status
)) {
1024 switch (Key
.UnicodeChar
) {
1027 switch (Key
.ScanCode
) {
1030 SelectItem
= BootMenuData
.SelectItem
== 0 ? BootMenuData
.ItemCount
- 1 : BootMenuData
.SelectItem
- 1;
1031 BootMenuSelectItem (SelectItem
, &BootMenuData
);
1035 SelectItem
= BootMenuData
.SelectItem
== BootMenuData
.ItemCount
- 1 ? 0 : BootMenuData
.SelectItem
+ 1;
1036 BootMenuSelectItem (SelectItem
, &BootMenuData
);
1040 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1041 ExitApplication
= TRUE
;
1043 // Set boot resolution for normal boot
1045 BdsSetConsoleMode (FALSE
);
1053 case CHAR_CARRIAGE_RETURN
:
1054 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1056 // Set boot resolution for normal boot
1058 BdsSetConsoleMode (FALSE
);
1059 BootFromSelectOption (BootOption
, BootOptionCount
, BootMenuData
.SelectItem
);
1061 // Back to boot manager menu again, set back to setup resolution
1063 BdsSetConsoleMode (TRUE
);
1064 DrawBootPopupMenu (&BootMenuData
);
1072 EfiBootManagerFreeLoadOptions (BootOption
, BootOptionCount
);
1073 FreePool (BootMenuData
.PtrTokens
);
1075 HiiRemovePackages (gStringPackHandle
);