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
));
248 This funciton uses to initialize boot menu data
250 @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
251 @param BootOptionCount Number of boot option.
252 @param BootMenuData The Input BootMenuData to be initialized.
254 @retval EFI_SUCCESS Initialize boot menu data successful.
255 @retval EFI_INVALID_PARAMETER Input parameter is invalid.
259 InitializeBootMenuData (
260 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
,
261 IN UINTN BootOptionCount
,
262 OUT BOOT_MENU_POPUP_DATA
*BootMenuData
268 if (BootOption
== NULL
|| BootMenuData
== NULL
) {
269 return EFI_INVALID_PARAMETER
;
272 BootMenuData
->TitleToken
[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_TITLE_STRING
);
273 BootMenuData
->PtrTokens
= AllocateZeroPool (BootOptionCount
* sizeof (EFI_STRING_ID
));
274 ASSERT (BootMenuData
->PtrTokens
!= NULL
);
277 // Skip boot option which created by BootNext Variable
279 for (StrIndex
= 0, Index
= 0; Index
< BootOptionCount
; Index
++) {
281 // Don't display the hidden/inactive boot option except setup application.
283 if ((((BootOption
[Index
].Attributes
& LOAD_OPTION_HIDDEN
) != 0) || ((BootOption
[Index
].Attributes
& LOAD_OPTION_ACTIVE
) == 0)) &&
284 !IsBootManagerMenu (&BootOption
[Index
])) {
287 ASSERT (BootOption
[Index
].Description
!= NULL
);
288 BootMenuData
->PtrTokens
[StrIndex
++] = HiiSetString (
291 BootOption
[Index
].Description
,
296 BootMenuData
->ItemCount
= StrIndex
;
297 BootMenuData
->HelpToken
[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP1_STRING
);
298 BootMenuData
->HelpToken
[1] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP2_STRING
);
299 BootMenuData
->HelpToken
[2] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP3_STRING
);
300 InitializeBootMenuScreen (BootMenuData
);
301 BootMenuData
->SelectItem
= 0;
306 This function uses input select item to highlight selected item
307 and set current selected item in BootMenuData
309 @param WantSelectItem The user wants to select item.
310 @param BootMenuData The boot menu data to be proccessed
312 @return EFI_SUCCESS Highlight selected item and update current selected
314 @retval EFI_INVALID_PARAMETER Input parameter is invalid
318 IN UINTN WantSelectItem
,
319 IN OUT BOOT_MENU_POPUP_DATA
*BootMenuData
322 INT32 SavedAttribute
;
332 UINTN ItemCountPerScreen
;
334 BOOLEAN RePaintItems
;
336 if (BootMenuData
== NULL
|| WantSelectItem
>= BootMenuData
->ItemCount
) {
337 return EFI_INVALID_PARAMETER
;
339 SavedAttribute
= gST
->ConOut
->Mode
->Attribute
;
340 RePaintItems
= FALSE
;
341 StartCol
= BootMenuData
->MenuScreen
.StartCol
;
342 StartRow
= BootMenuData
->MenuScreen
.StartRow
;
344 // print selectable items again and adjust scroll bar if need
346 if (BootMenuData
->ScrollBarControl
.HasScrollBar
&&
347 (WantSelectItem
< BootMenuData
->ScrollBarControl
.FirstItem
||
348 WantSelectItem
> BootMenuData
->ScrollBarControl
.LastItem
||
349 WantSelectItem
== BootMenuData
->SelectItem
)) {
350 ItemCountPerScreen
= BootMenuData
->ScrollBarControl
.ItemCountPerScreen
;
352 // Set first item and last item
354 if (WantSelectItem
< BootMenuData
->ScrollBarControl
.FirstItem
) {
355 BootMenuData
->ScrollBarControl
.FirstItem
= WantSelectItem
;
356 BootMenuData
->ScrollBarControl
.LastItem
= WantSelectItem
+ ItemCountPerScreen
- 1;
357 } else if (WantSelectItem
> BootMenuData
->ScrollBarControl
.LastItem
) {
358 BootMenuData
->ScrollBarControl
.FirstItem
= WantSelectItem
- ItemCountPerScreen
+ 1;
359 BootMenuData
->ScrollBarControl
.LastItem
= WantSelectItem
;
361 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
362 FirstItem
= BootMenuData
->ScrollBarControl
.FirstItem
;
363 LastItem
= BootMenuData
->ScrollBarControl
.LastItem
;
365 if (FirstItem
!= 0) {
366 TopShadeNum
= (FirstItem
* ItemCountPerScreen
) / BootMenuData
->ItemCount
;
367 if ((FirstItem
* ItemCountPerScreen
) % BootMenuData
->ItemCount
!= 0) {
370 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
371 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
372 for (Index
= 0; Index
< TopShadeNum
; Index
++, PrintRow
++) {
373 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_LIGHT_SHADE
);
377 if (LastItem
!= BootMenuData
->ItemCount
- 1) {
378 LowShadeNum
= ((BootMenuData
->ItemCount
- 1 - LastItem
) * ItemCountPerScreen
) / BootMenuData
->ItemCount
;
379 if (((BootMenuData
->ItemCount
- 1 - LastItem
) * ItemCountPerScreen
) % BootMenuData
->ItemCount
!= 0) {
382 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
383 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + ItemCountPerScreen
- LowShadeNum
;
384 for (Index
= 0; Index
< LowShadeNum
; Index
++, PrintRow
++) {
385 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_LIGHT_SHADE
);
388 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
389 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + TopShadeNum
;
390 for (Index
= TopShadeNum
; Index
< ItemCountPerScreen
- LowShadeNum
; Index
++, PrintRow
++) {
391 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_FULL_BLOCK
);
396 // Clear selectable items first
398 PrintCol
= StartCol
+ 1;
399 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
400 String
= AllocateZeroPool ((BootMenuData
->MenuScreen
.Width
- 2) * sizeof (CHAR16
));
401 ASSERT (String
!= NULL
);
402 for (Index
= 0; Index
< BootMenuData
->MenuScreen
.Width
- 3; Index
++) {
403 String
[Index
] = 0x20;
405 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++) {
406 PrintStringAt (PrintCol
, PrintRow
+ Index
, String
);
410 // print selectable items
412 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++, PrintRow
++) {
413 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[Index
+ FirstItem
], NULL
);
414 PrintStringAt (PrintCol
, PrintRow
, String
);
421 // Print want to select item
423 FirstItem
= BootMenuData
->ScrollBarControl
.FirstItem
;
424 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLACK
);
425 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[WantSelectItem
], NULL
);
426 PrintCol
= StartCol
+ 1;
427 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + WantSelectItem
- FirstItem
;
428 PrintStringAt (PrintCol
, PrintRow
, String
);
432 // if Want Select and selected item isn't the same and doesn't re-draw selectable
433 // items, clear select item
435 if (WantSelectItem
!= BootMenuData
->SelectItem
&& !RePaintItems
) {
436 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
437 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[BootMenuData
->SelectItem
], NULL
);
438 PrintCol
= StartCol
+ 1;
439 PrintRow
= StartRow
+ 3 + BootMenuData
->SelectItem
- FirstItem
;
440 PrintStringAt (PrintCol
, PrintRow
, String
);
444 gST
->ConOut
->SetAttribute (gST
->ConOut
, SavedAttribute
);
445 BootMenuData
->SelectItem
= WantSelectItem
;
450 This funciton uses to draw boot popup menu
452 @param BootMenuData The Input BootMenuData to be processed.
454 @retval EFI_SUCCESS Draw boot popup menu successful.
459 IN BOOT_MENU_POPUP_DATA
*BootMenuData
471 INT32 SavedAttribute
;
472 UINTN ItemCountPerScreen
;
474 gST
->ConOut
->ClearScreen (gST
->ConOut
);
476 SavedAttribute
= gST
->ConOut
->Mode
->Attribute
;
477 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
478 Width
= BootMenuData
->MenuScreen
.Width
;
479 Height
= BootMenuData
->MenuScreen
.Height
;
480 StartCol
= BootMenuData
->MenuScreen
.StartCol
;
481 StartRow
= BootMenuData
->MenuScreen
.StartRow
;
482 ItemCountPerScreen
= BootMenuData
->ScrollBarControl
.ItemCountPerScreen
;
485 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
487 // Draw Boot popup menu screen
489 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_DOWN_RIGHT
);
490 for (Index
= 1; Index
< Width
- 1; Index
++) {
491 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
493 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_DOWN_LEFT
);
496 // Draw the screen for title
498 String
= AllocateZeroPool ((Width
- 1) * sizeof (CHAR16
));
499 ASSERT (String
!= NULL
);
500 for (Index
= 0; Index
< Width
- 2; Index
++) {
501 String
[Index
] = 0x20;
504 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++) {
506 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
507 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
508 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
512 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL_RIGHT
);
513 for (Index
= 1; Index
< Width
- 1; Index
++) {
514 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
516 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL_LEFT
);
519 // Draw screen for selectable items
521 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++) {
523 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
524 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
525 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
529 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL_RIGHT
);
530 for (Index
= 1; Index
< Width
- 1; Index
++) {
531 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
533 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL_LEFT
);
536 // Draw screen for Help
538 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++) {
540 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
541 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
542 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
547 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_UP_RIGHT
);
548 for (Index
= 1; Index
< Width
- 1; Index
++) {
549 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
551 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_UP_LEFT
);
555 // print title strings
557 PrintRow
= StartRow
+ 1;
558 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++, PrintRow
++) {
559 String
= HiiGetString (gStringPackHandle
, BootMenuData
->TitleToken
[Index
], NULL
);
560 LineWidth
= GetLineWidth (BootMenuData
->TitleToken
[Index
]);
561 PrintCol
= StartCol
+ (Width
- LineWidth
) / 2;
562 PrintStringAt (PrintCol
, PrintRow
, String
);
567 // print selectable items
569 PrintCol
= StartCol
+ 1;
570 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
571 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++, PrintRow
++) {
572 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[Index
], NULL
);
573 PrintStringAt (PrintCol
, PrintRow
, String
);
578 // Print Help strings
581 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++, PrintRow
++) {
582 String
= HiiGetString (gStringPackHandle
, BootMenuData
->HelpToken
[Index
], NULL
);
583 LineWidth
= GetLineWidth (BootMenuData
->HelpToken
[Index
]);
584 PrintCol
= StartCol
+ (Width
- LineWidth
) / 2;
585 PrintStringAt (PrintCol
, PrintRow
, String
);
590 // Print scroll bar if has scroll bar
592 if (BootMenuData
->ScrollBarControl
.HasScrollBar
) {
593 PrintCol
= StartCol
+ Width
- 2;
594 PrintRow
= StartRow
+ 2;
595 PrintCharAt (PrintCol
, PrintRow
, GEOMETRICSHAPE_UP_TRIANGLE
);
596 PrintCharAt (PrintCol
+ 1, PrintRow
, BOXDRAW_VERTICAL
);
597 PrintRow
+= (ItemCountPerScreen
+ 1);
598 PrintCharAt (PrintCol
, PrintRow
, GEOMETRICSHAPE_DOWN_TRIANGLE
);
599 PrintCharAt (PrintCol
+ 1, PrintRow
, BOXDRAW_VERTICAL
);
602 gST
->ConOut
->SetAttribute (gST
->ConOut
, SavedAttribute
);
604 // Print Selected item
606 BootMenuSelectItem (BootMenuData
->SelectItem
, BootMenuData
);
611 This funciton uses to boot from selected item
613 @param BootOptions Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
614 @param BootOptionCount Number of boot option.
615 @param SelectItem Current selected item.
618 BootFromSelectOption (
619 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
,
620 IN UINTN BootOptionCount
,
627 ASSERT (BootOptions
!= NULL
);
629 for (ItemNum
= 0, Index
= 0; Index
< BootOptionCount
; Index
++) {
631 // Don't display the hidden/inactive boot option except setup application.
633 if ((((BootOptions
[Index
].Attributes
& LOAD_OPTION_HIDDEN
) != 0) || ((BootOptions
[Index
].Attributes
& LOAD_OPTION_ACTIVE
) == 0)) &&
634 !IsBootManagerMenu (&BootOptions
[Index
])) {
637 if (ItemNum
++ == SelectItem
) {
638 EfiBootManagerBoot (&BootOptions
[Index
]);
645 This function will change video resolution and text mode
646 according to defined setup mode or defined boot mode
648 @param IsSetupMode Indicate mode is changed to setup mode or boot mode.
650 @retval EFI_SUCCESS Mode is changed successfully.
651 @retval Others Mode failed to be changed.
660 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
661 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
663 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
667 UINT32 NewHorizontalResolution
;
668 UINT32 NewVerticalResolution
;
672 EFI_HANDLE
*HandleBuffer
;
682 // Get current video resolution and text mode
684 Status
= gBS
->HandleProtocol (
685 gST
->ConsoleOutHandle
,
686 &gEfiGraphicsOutputProtocolGuid
,
687 (VOID
**)&GraphicsOutput
689 if (EFI_ERROR (Status
)) {
690 GraphicsOutput
= NULL
;
693 Status
= gBS
->HandleProtocol (
694 gST
->ConsoleOutHandle
,
695 &gEfiSimpleTextOutProtocolGuid
,
696 (VOID
**)&SimpleTextOut
698 if (EFI_ERROR (Status
)) {
699 SimpleTextOut
= NULL
;
702 if ((GraphicsOutput
== NULL
) || (SimpleTextOut
== NULL
)) {
703 return EFI_UNSUPPORTED
;
708 // The requried resolution and text mode is setup mode.
710 NewHorizontalResolution
= mSetupHorizontalResolution
;
711 NewVerticalResolution
= mSetupVerticalResolution
;
712 NewColumns
= mSetupTextModeColumn
;
713 NewRows
= mSetupTextModeRow
;
716 // The required resolution and text mode is boot mode.
718 NewHorizontalResolution
= mBootHorizontalResolution
;
719 NewVerticalResolution
= mBootVerticalResolution
;
720 NewColumns
= mBootTextModeColumn
;
721 NewRows
= mBootTextModeRow
;
724 if (GraphicsOutput
!= NULL
) {
725 MaxGopMode
= GraphicsOutput
->Mode
->MaxMode
;
728 if (SimpleTextOut
!= NULL
) {
729 MaxTextMode
= SimpleTextOut
->Mode
->MaxMode
;
733 // 1. If current video resolution is same with required video resolution,
734 // video resolution need not be changed.
735 // 1.1. If current text mode is same with required text mode, text mode need not be changed.
736 // 1.2. If current text mode is different from required text mode, text mode need be changed.
737 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.
739 for (ModeNumber
= 0; ModeNumber
< MaxGopMode
; ModeNumber
++) {
740 Status
= GraphicsOutput
->QueryMode (
746 if (!EFI_ERROR (Status
)) {
747 if ((Info
->HorizontalResolution
== NewHorizontalResolution
) &&
748 (Info
->VerticalResolution
== NewVerticalResolution
)) {
749 if ((GraphicsOutput
->Mode
->Info
->HorizontalResolution
== NewHorizontalResolution
) &&
750 (GraphicsOutput
->Mode
->Info
->VerticalResolution
== NewVerticalResolution
)) {
752 // Current resolution is same with required resolution, check if text mode need be set
754 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, SimpleTextOut
->Mode
->Mode
, &CurrentColumn
, &CurrentRow
);
755 ASSERT_EFI_ERROR (Status
);
756 if (CurrentColumn
== NewColumns
&& CurrentRow
== NewRows
) {
758 // If current text mode is same with required text mode. Do nothing
764 // If current text mode is different from requried text mode. Set new video mode
766 for (Index
= 0; Index
< MaxTextMode
; Index
++) {
767 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, Index
, &CurrentColumn
, &CurrentRow
);
768 if (!EFI_ERROR(Status
)) {
769 if ((CurrentColumn
== NewColumns
) && (CurrentRow
== NewRows
)) {
771 // Required text mode is supported, set it.
773 Status
= SimpleTextOut
->SetMode (SimpleTextOut
, Index
);
774 ASSERT_EFI_ERROR (Status
);
776 // Update text mode PCD.
778 PcdSet32 (PcdConOutColumn
, mSetupTextModeColumn
);
779 PcdSet32 (PcdConOutRow
, mSetupTextModeRow
);
785 if (Index
== MaxTextMode
) {
787 // If requried text mode is not supported, return error.
790 return EFI_UNSUPPORTED
;
795 // If current video resolution is not same with the new one, set new video resolution.
796 // In this case, the driver which produces simple text out need be restarted.
798 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, ModeNumber
);
799 if (!EFI_ERROR (Status
)) {
809 if (ModeNumber
== MaxGopMode
) {
811 // If the resolution is not supported, return error.
813 return EFI_UNSUPPORTED
;
817 // Set PCD to Inform GraphicsConsole to change video resolution.
818 // Set PCD to Inform Consplitter to change text mode.
820 PcdSet32 (PcdVideoHorizontalResolution
, NewHorizontalResolution
);
821 PcdSet32 (PcdVideoVerticalResolution
, NewVerticalResolution
);
822 PcdSet32 (PcdConOutColumn
, NewColumns
);
823 PcdSet32 (PcdConOutRow
, NewRows
);
827 // Video mode is changed, so restart graphics console driver and higher level driver.
828 // Reconnect graphics console driver and higher level driver.
829 // Locate all the handles with GOP protocol and reconnect it.
831 Status
= gBS
->LocateHandleBuffer (
833 &gEfiSimpleTextOutProtocolGuid
,
838 if (!EFI_ERROR (Status
)) {
839 for (Index
= 0; Index
< HandleCount
; Index
++) {
840 gBS
->DisconnectController (HandleBuffer
[Index
], NULL
, NULL
);
842 for (Index
= 0; Index
< HandleCount
; Index
++) {
843 gBS
->ConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
845 if (HandleBuffer
!= NULL
) {
846 FreePool (HandleBuffer
);
854 Display the boot popup menu and allow user select boot item.
856 @param ImageHandle The image handle.
857 @param SystemTable The system table.
859 @retval EFI_SUCCESS Boot from selected boot option, and return success from boot option
860 @retval EFI_NOT_FOUND User select to enter setup or can not find boot option
865 BootManagerMenuEntry (
866 IN EFI_HANDLE ImageHandle
,
867 IN EFI_SYSTEM_TABLE
*SystemTable
870 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
;
871 UINTN BootOptionCount
;
873 BOOT_MENU_POPUP_DATA BootMenuData
;
876 BOOLEAN ExitApplication
;
878 EFI_BOOT_LOGO_PROTOCOL
*BootLogo
;
879 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
880 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
881 UINTN BootTextColumn
;
885 // Set Logo status invalid when boot manager menu is launched
888 Status
= gBS
->LocateProtocol (&gEfiBootLogoProtocolGuid
, NULL
, (VOID
**) &BootLogo
);
889 if (!EFI_ERROR (Status
) && (BootLogo
!= NULL
)) {
890 Status
= BootLogo
->SetBootLogo (BootLogo
, NULL
, 0, 0, 0, 0);
891 ASSERT_EFI_ERROR (Status
);
894 gBS
->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL
);
896 gStringPackHandle
= HiiAddPackages (
899 BootManagerMenuAppStrings
,
902 ASSERT (gStringPackHandle
!= NULL
);
905 // Connect all prior to entering the platform setup menu.
907 EfiBootManagerConnectAll ();
908 EfiBootManagerRefreshAllBootOption ();
910 BootOption
= EfiBootManagerGetLoadOptions (&BootOptionCount
, LoadOptionTypeBoot
);
912 if (!mModeInitialized
) {
914 // After the console is ready, get current video resolution
915 // and text mode before launching setup at first time.
917 Status
= gBS
->HandleProtocol (
918 gST
->ConsoleOutHandle
,
919 &gEfiGraphicsOutputProtocolGuid
,
920 (VOID
**)&GraphicsOutput
922 if (EFI_ERROR (Status
)) {
923 GraphicsOutput
= NULL
;
926 Status
= gBS
->HandleProtocol (
927 gST
->ConsoleOutHandle
,
928 &gEfiSimpleTextOutProtocolGuid
,
929 (VOID
**)&SimpleTextOut
931 if (EFI_ERROR (Status
)) {
932 SimpleTextOut
= NULL
;
935 if (GraphicsOutput
!= NULL
) {
937 // Get current video resolution and text mode.
939 mBootHorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
940 mBootVerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
943 if (SimpleTextOut
!= NULL
) {
944 Status
= SimpleTextOut
->QueryMode (
946 SimpleTextOut
->Mode
->Mode
,
950 mBootTextModeColumn
= (UINT32
)BootTextColumn
;
951 mBootTextModeRow
= (UINT32
)BootTextRow
;
955 // Get user defined text mode for setup.
957 mSetupHorizontalResolution
= PcdGet32 (PcdSetupVideoHorizontalResolution
);
958 mSetupVerticalResolution
= PcdGet32 (PcdSetupVideoVerticalResolution
);
959 mSetupTextModeColumn
= PcdGet32 (PcdSetupConOutColumn
);
960 mSetupTextModeRow
= PcdGet32 (PcdSetupConOutRow
);
961 mModeInitialized
= TRUE
;
965 // Set back to conventional setup resolution
967 BdsSetConsoleMode (TRUE
);
970 // Initialize Boot menu data
972 Status
= InitializeBootMenuData (BootOption
, BootOptionCount
, &BootMenuData
);
974 // According to boot menu data to draw boot popup menu
976 DrawBootPopupMenu (&BootMenuData
);
979 // check user input to determine want to re-draw or boot from user selected item
981 ExitApplication
= FALSE
;
982 while (!ExitApplication
) {
983 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
984 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
985 if (!EFI_ERROR (Status
)) {
986 switch (Key
.UnicodeChar
) {
989 switch (Key
.ScanCode
) {
992 SelectItem
= BootMenuData
.SelectItem
== 0 ? BootMenuData
.ItemCount
- 1 : BootMenuData
.SelectItem
- 1;
993 BootMenuSelectItem (SelectItem
, &BootMenuData
);
997 SelectItem
= BootMenuData
.SelectItem
== BootMenuData
.ItemCount
- 1 ? 0 : BootMenuData
.SelectItem
+ 1;
998 BootMenuSelectItem (SelectItem
, &BootMenuData
);
1002 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1003 ExitApplication
= TRUE
;
1005 // Set boot resolution for normal boot
1007 BdsSetConsoleMode (FALSE
);
1015 case CHAR_CARRIAGE_RETURN
:
1016 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1018 // Set boot resolution for normal boot
1020 BdsSetConsoleMode (FALSE
);
1021 BootFromSelectOption (BootOption
, BootOptionCount
, BootMenuData
.SelectItem
);
1023 // Back to boot manager menu again, set back to setup resolution
1025 BdsSetConsoleMode (TRUE
);
1026 DrawBootPopupMenu (&BootMenuData
);
1034 EfiBootManagerFreeLoadOptions (BootOption
, BootOptionCount
);
1035 FreePool (BootMenuData
.PtrTokens
);
1037 HiiRemovePackages (gStringPackHandle
);