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 EFI_DEVICE_PATH_PROTOCOL
*ImageDevicePath
;
270 if (BootOption
== NULL
|| BootMenuData
== NULL
) {
271 return EFI_INVALID_PARAMETER
;
274 Status
= gBS
->HandleProtocol (gImageHandle
, &gEfiLoadedImageDevicePathProtocolGuid
, (VOID
**) &ImageDevicePath
);
275 ASSERT_EFI_ERROR (Status
);
277 BootMenuData
->TitleToken
[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_TITLE_STRING
);
278 BootMenuData
->PtrTokens
= AllocateZeroPool (BootOptionCount
* sizeof (EFI_STRING_ID
));
279 ASSERT (BootMenuData
->PtrTokens
!= NULL
);
282 // Skip boot option which created by BootNext Variable
284 for (StrIndex
= 0, Index
= 0; Index
< BootOptionCount
; Index
++) {
286 // Don't display the hidden/inactive boot option except setup application.
288 if ((((BootOption
[Index
].Attributes
& LOAD_OPTION_HIDDEN
) != 0) || ((BootOption
[Index
].Attributes
& LOAD_OPTION_ACTIVE
) == 0)) &&
289 !IsBootManagerMenu (&BootOption
[Index
])) {
294 // Don't display myself
296 if (CompareMem (BootOption
[Index
].FilePath
, ImageDevicePath
, GetDevicePathSize (ImageDevicePath
)) == 0) {
300 ASSERT (BootOption
[Index
].Description
!= NULL
);
301 BootMenuData
->PtrTokens
[StrIndex
++] = HiiSetString (
304 BootOption
[Index
].Description
,
309 BootMenuData
->ItemCount
= StrIndex
;
310 BootMenuData
->HelpToken
[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP1_STRING
);
311 BootMenuData
->HelpToken
[1] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP2_STRING
);
312 BootMenuData
->HelpToken
[2] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP3_STRING
);
313 InitializeBootMenuScreen (BootMenuData
);
314 BootMenuData
->SelectItem
= 0;
319 This function uses input select item to highlight selected item
320 and set current selected item in BootMenuData
322 @param WantSelectItem The user wants to select item.
323 @param BootMenuData The boot menu data to be proccessed
325 @return EFI_SUCCESS Highlight selected item and update current selected
327 @retval EFI_INVALID_PARAMETER Input parameter is invalid
331 IN UINTN WantSelectItem
,
332 IN OUT BOOT_MENU_POPUP_DATA
*BootMenuData
335 INT32 SavedAttribute
;
345 UINTN ItemCountPerScreen
;
347 BOOLEAN RePaintItems
;
349 if (BootMenuData
== NULL
|| WantSelectItem
>= BootMenuData
->ItemCount
) {
350 return EFI_INVALID_PARAMETER
;
352 SavedAttribute
= gST
->ConOut
->Mode
->Attribute
;
353 RePaintItems
= FALSE
;
354 StartCol
= BootMenuData
->MenuScreen
.StartCol
;
355 StartRow
= BootMenuData
->MenuScreen
.StartRow
;
357 // print selectable items again and adjust scroll bar if need
359 if (BootMenuData
->ScrollBarControl
.HasScrollBar
&&
360 (WantSelectItem
< BootMenuData
->ScrollBarControl
.FirstItem
||
361 WantSelectItem
> BootMenuData
->ScrollBarControl
.LastItem
||
362 WantSelectItem
== BootMenuData
->SelectItem
)) {
363 ItemCountPerScreen
= BootMenuData
->ScrollBarControl
.ItemCountPerScreen
;
365 // Set first item and last item
367 if (WantSelectItem
< BootMenuData
->ScrollBarControl
.FirstItem
) {
368 BootMenuData
->ScrollBarControl
.FirstItem
= WantSelectItem
;
369 BootMenuData
->ScrollBarControl
.LastItem
= WantSelectItem
+ ItemCountPerScreen
- 1;
370 } else if (WantSelectItem
> BootMenuData
->ScrollBarControl
.LastItem
) {
371 BootMenuData
->ScrollBarControl
.FirstItem
= WantSelectItem
- ItemCountPerScreen
+ 1;
372 BootMenuData
->ScrollBarControl
.LastItem
= WantSelectItem
;
374 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
375 FirstItem
= BootMenuData
->ScrollBarControl
.FirstItem
;
376 LastItem
= BootMenuData
->ScrollBarControl
.LastItem
;
378 if (FirstItem
!= 0) {
379 TopShadeNum
= (FirstItem
* ItemCountPerScreen
) / BootMenuData
->ItemCount
;
380 if ((FirstItem
* ItemCountPerScreen
) % BootMenuData
->ItemCount
!= 0) {
383 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
384 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
385 for (Index
= 0; Index
< TopShadeNum
; Index
++, PrintRow
++) {
386 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_LIGHT_SHADE
);
390 if (LastItem
!= BootMenuData
->ItemCount
- 1) {
391 LowShadeNum
= ((BootMenuData
->ItemCount
- 1 - LastItem
) * ItemCountPerScreen
) / BootMenuData
->ItemCount
;
392 if (((BootMenuData
->ItemCount
- 1 - LastItem
) * ItemCountPerScreen
) % BootMenuData
->ItemCount
!= 0) {
395 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
396 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + ItemCountPerScreen
- LowShadeNum
;
397 for (Index
= 0; Index
< LowShadeNum
; Index
++, PrintRow
++) {
398 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_LIGHT_SHADE
);
401 PrintCol
= StartCol
+ BootMenuData
->MenuScreen
.Width
- 2;
402 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + TopShadeNum
;
403 for (Index
= TopShadeNum
; Index
< ItemCountPerScreen
- LowShadeNum
; Index
++, PrintRow
++) {
404 PrintCharAt (PrintCol
, PrintRow
, BLOCKELEMENT_FULL_BLOCK
);
409 // Clear selectable items first
411 PrintCol
= StartCol
+ 1;
412 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
413 String
= AllocateZeroPool ((BootMenuData
->MenuScreen
.Width
- 2) * sizeof (CHAR16
));
414 ASSERT (String
!= NULL
);
415 for (Index
= 0; Index
< BootMenuData
->MenuScreen
.Width
- 3; Index
++) {
416 String
[Index
] = 0x20;
418 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++) {
419 PrintStringAt (PrintCol
, PrintRow
+ Index
, String
);
423 // print selectable items
425 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++, PrintRow
++) {
426 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[Index
+ FirstItem
], NULL
);
427 PrintStringAt (PrintCol
, PrintRow
, String
);
434 // Print want to select item
436 FirstItem
= BootMenuData
->ScrollBarControl
.FirstItem
;
437 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLACK
);
438 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[WantSelectItem
], NULL
);
439 PrintCol
= StartCol
+ 1;
440 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2 + WantSelectItem
- FirstItem
;
441 PrintStringAt (PrintCol
, PrintRow
, String
);
445 // if Want Select and selected item isn't the same and doesn't re-draw selectable
446 // items, clear select item
448 if (WantSelectItem
!= BootMenuData
->SelectItem
&& !RePaintItems
) {
449 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
450 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[BootMenuData
->SelectItem
], NULL
);
451 PrintCol
= StartCol
+ 1;
452 PrintRow
= StartRow
+ 3 + BootMenuData
->SelectItem
- FirstItem
;
453 PrintStringAt (PrintCol
, PrintRow
, String
);
457 gST
->ConOut
->SetAttribute (gST
->ConOut
, SavedAttribute
);
458 BootMenuData
->SelectItem
= WantSelectItem
;
463 This funciton uses to draw boot popup menu
465 @param BootMenuData The Input BootMenuData to be processed.
467 @retval EFI_SUCCESS Draw boot popup menu successful.
472 IN BOOT_MENU_POPUP_DATA
*BootMenuData
484 INT32 SavedAttribute
;
485 UINTN ItemCountPerScreen
;
487 gST
->ConOut
->ClearScreen (gST
->ConOut
);
489 SavedAttribute
= gST
->ConOut
->Mode
->Attribute
;
490 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_WHITE
| EFI_BACKGROUND_BLUE
);
491 Width
= BootMenuData
->MenuScreen
.Width
;
492 Height
= BootMenuData
->MenuScreen
.Height
;
493 StartCol
= BootMenuData
->MenuScreen
.StartCol
;
494 StartRow
= BootMenuData
->MenuScreen
.StartRow
;
495 ItemCountPerScreen
= BootMenuData
->ScrollBarControl
.ItemCountPerScreen
;
498 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
500 // Draw Boot popup menu screen
502 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_DOWN_RIGHT
);
503 for (Index
= 1; Index
< Width
- 1; Index
++) {
504 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
506 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_DOWN_LEFT
);
509 // Draw the screen for title
511 String
= AllocateZeroPool ((Width
- 1) * sizeof (CHAR16
));
512 ASSERT (String
!= NULL
);
513 for (Index
= 0; Index
< Width
- 2; Index
++) {
514 String
[Index
] = 0x20;
517 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++) {
519 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
520 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
521 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
525 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL_RIGHT
);
526 for (Index
= 1; Index
< Width
- 1; Index
++) {
527 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
529 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL_LEFT
);
532 // Draw screen for selectable items
534 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++) {
536 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
537 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
538 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
542 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL_RIGHT
);
543 for (Index
= 1; Index
< Width
- 1; Index
++) {
544 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
546 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL_LEFT
);
549 // Draw screen for Help
551 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++) {
553 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_VERTICAL
);
554 PrintStringAt (StartCol
+ 1, PrintRow
, String
);
555 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_VERTICAL
);
560 PrintCharAt (StartCol
, PrintRow
, BOXDRAW_UP_RIGHT
);
561 for (Index
= 1; Index
< Width
- 1; Index
++) {
562 PrintCharAt (StartCol
+ Index
, PrintRow
, BOXDRAW_HORIZONTAL
);
564 PrintCharAt (StartCol
+ Width
- 1, PrintRow
, BOXDRAW_UP_LEFT
);
568 // print title strings
570 PrintRow
= StartRow
+ 1;
571 for (Index
= 0; Index
< TITLE_TOKEN_COUNT
; Index
++, PrintRow
++) {
572 String
= HiiGetString (gStringPackHandle
, BootMenuData
->TitleToken
[Index
], NULL
);
573 LineWidth
= GetLineWidth (BootMenuData
->TitleToken
[Index
]);
574 PrintCol
= StartCol
+ (Width
- LineWidth
) / 2;
575 PrintStringAt (PrintCol
, PrintRow
, String
);
580 // print selectable items
582 PrintCol
= StartCol
+ 1;
583 PrintRow
= StartRow
+ TITLE_TOKEN_COUNT
+ 2;
584 for (Index
= 0; Index
< ItemCountPerScreen
; Index
++, PrintRow
++) {
585 String
= HiiGetString (gStringPackHandle
, BootMenuData
->PtrTokens
[Index
], NULL
);
586 PrintStringAt (PrintCol
, PrintRow
, String
);
591 // Print Help strings
594 for (Index
= 0; Index
< HELP_TOKEN_COUNT
; Index
++, PrintRow
++) {
595 String
= HiiGetString (gStringPackHandle
, BootMenuData
->HelpToken
[Index
], NULL
);
596 LineWidth
= GetLineWidth (BootMenuData
->HelpToken
[Index
]);
597 PrintCol
= StartCol
+ (Width
- LineWidth
) / 2;
598 PrintStringAt (PrintCol
, PrintRow
, String
);
603 // Print scroll bar if has scroll bar
605 if (BootMenuData
->ScrollBarControl
.HasScrollBar
) {
606 PrintCol
= StartCol
+ Width
- 2;
607 PrintRow
= StartRow
+ 2;
608 PrintCharAt (PrintCol
, PrintRow
, GEOMETRICSHAPE_UP_TRIANGLE
);
609 PrintCharAt (PrintCol
+ 1, PrintRow
, BOXDRAW_VERTICAL
);
610 PrintRow
+= (ItemCountPerScreen
+ 1);
611 PrintCharAt (PrintCol
, PrintRow
, GEOMETRICSHAPE_DOWN_TRIANGLE
);
612 PrintCharAt (PrintCol
+ 1, PrintRow
, BOXDRAW_VERTICAL
);
615 gST
->ConOut
->SetAttribute (gST
->ConOut
, SavedAttribute
);
617 // Print Selected item
619 BootMenuSelectItem (BootMenuData
->SelectItem
, BootMenuData
);
624 This funciton uses to boot from selected item
626 @param BootOptions Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
627 @param BootOptionCount Number of boot option.
628 @param SelectItem Current selected item.
631 BootFromSelectOption (
632 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
,
633 IN UINTN BootOptionCount
,
640 ASSERT (BootOptions
!= NULL
);
642 for (ItemNum
= 0, Index
= 0; Index
< BootOptionCount
; Index
++) {
644 // Don't display the hidden/inactive boot option except setup application.
646 if ((((BootOptions
[Index
].Attributes
& LOAD_OPTION_HIDDEN
) != 0) || ((BootOptions
[Index
].Attributes
& LOAD_OPTION_ACTIVE
) == 0)) &&
647 !IsBootManagerMenu (&BootOptions
[Index
])) {
650 if (ItemNum
++ == SelectItem
) {
651 EfiBootManagerBoot (&BootOptions
[Index
]);
658 This function will change video resolution and text mode
659 according to defined setup mode or defined boot mode
661 @param IsSetupMode Indicate mode is changed to setup mode or boot mode.
663 @retval EFI_SUCCESS Mode is changed successfully.
664 @retval Others Mode failed to be changed.
673 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
674 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
676 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
680 UINT32 NewHorizontalResolution
;
681 UINT32 NewVerticalResolution
;
685 EFI_HANDLE
*HandleBuffer
;
695 // Get current video resolution and text mode
697 Status
= gBS
->HandleProtocol (
698 gST
->ConsoleOutHandle
,
699 &gEfiGraphicsOutputProtocolGuid
,
700 (VOID
**)&GraphicsOutput
702 if (EFI_ERROR (Status
)) {
703 GraphicsOutput
= NULL
;
706 Status
= gBS
->HandleProtocol (
707 gST
->ConsoleOutHandle
,
708 &gEfiSimpleTextOutProtocolGuid
,
709 (VOID
**)&SimpleTextOut
711 if (EFI_ERROR (Status
)) {
712 SimpleTextOut
= NULL
;
715 if ((GraphicsOutput
== NULL
) || (SimpleTextOut
== NULL
)) {
716 return EFI_UNSUPPORTED
;
721 // The requried resolution and text mode is setup mode.
723 NewHorizontalResolution
= mSetupHorizontalResolution
;
724 NewVerticalResolution
= mSetupVerticalResolution
;
725 NewColumns
= mSetupTextModeColumn
;
726 NewRows
= mSetupTextModeRow
;
729 // The required resolution and text mode is boot mode.
731 NewHorizontalResolution
= mBootHorizontalResolution
;
732 NewVerticalResolution
= mBootVerticalResolution
;
733 NewColumns
= mBootTextModeColumn
;
734 NewRows
= mBootTextModeRow
;
737 if (GraphicsOutput
!= NULL
) {
738 MaxGopMode
= GraphicsOutput
->Mode
->MaxMode
;
741 if (SimpleTextOut
!= NULL
) {
742 MaxTextMode
= SimpleTextOut
->Mode
->MaxMode
;
746 // 1. If current video resolution is same with required video resolution,
747 // video resolution need not be changed.
748 // 1.1. If current text mode is same with required text mode, text mode need not be changed.
749 // 1.2. If current text mode is different from required text mode, text mode need be changed.
750 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.
752 for (ModeNumber
= 0; ModeNumber
< MaxGopMode
; ModeNumber
++) {
753 Status
= GraphicsOutput
->QueryMode (
759 if (!EFI_ERROR (Status
)) {
760 if ((Info
->HorizontalResolution
== NewHorizontalResolution
) &&
761 (Info
->VerticalResolution
== NewVerticalResolution
)) {
762 if ((GraphicsOutput
->Mode
->Info
->HorizontalResolution
== NewHorizontalResolution
) &&
763 (GraphicsOutput
->Mode
->Info
->VerticalResolution
== NewVerticalResolution
)) {
765 // Current resolution is same with required resolution, check if text mode need be set
767 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, SimpleTextOut
->Mode
->Mode
, &CurrentColumn
, &CurrentRow
);
768 ASSERT_EFI_ERROR (Status
);
769 if (CurrentColumn
== NewColumns
&& CurrentRow
== NewRows
) {
771 // If current text mode is same with required text mode. Do nothing
777 // If current text mode is different from requried text mode. Set new video mode
779 for (Index
= 0; Index
< MaxTextMode
; Index
++) {
780 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, Index
, &CurrentColumn
, &CurrentRow
);
781 if (!EFI_ERROR(Status
)) {
782 if ((CurrentColumn
== NewColumns
) && (CurrentRow
== NewRows
)) {
784 // Required text mode is supported, set it.
786 Status
= SimpleTextOut
->SetMode (SimpleTextOut
, Index
);
787 ASSERT_EFI_ERROR (Status
);
789 // Update text mode PCD.
791 Status
= PcdSet32S (PcdConOutColumn
, mSetupTextModeColumn
);
792 ASSERT_EFI_ERROR (Status
);
793 Status
= PcdSet32S (PcdConOutRow
, mSetupTextModeRow
);
794 ASSERT_EFI_ERROR (Status
);
800 if (Index
== MaxTextMode
) {
802 // If requried text mode is not supported, return error.
805 return EFI_UNSUPPORTED
;
810 // If current video resolution is not same with the new one, set new video resolution.
811 // In this case, the driver which produces simple text out need be restarted.
813 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, ModeNumber
);
814 if (!EFI_ERROR (Status
)) {
824 if (ModeNumber
== MaxGopMode
) {
826 // If the resolution is not supported, return error.
828 return EFI_UNSUPPORTED
;
832 // Set PCD to Inform GraphicsConsole to change video resolution.
833 // Set PCD to Inform Consplitter to change text mode.
835 Status
= PcdSet32S (PcdVideoHorizontalResolution
, NewHorizontalResolution
);
836 ASSERT_EFI_ERROR (Status
);
837 Status
= PcdSet32S (PcdVideoVerticalResolution
, NewVerticalResolution
);
838 ASSERT_EFI_ERROR (Status
);
839 Status
= PcdSet32S (PcdConOutColumn
, NewColumns
);
840 ASSERT_EFI_ERROR (Status
);
841 Status
= PcdSet32S (PcdConOutRow
, NewRows
);
842 ASSERT_EFI_ERROR (Status
);
845 // Video mode is changed, so restart graphics console driver and higher level driver.
846 // Reconnect graphics console driver and higher level driver.
847 // Locate all the handles with GOP protocol and reconnect it.
849 Status
= gBS
->LocateHandleBuffer (
851 &gEfiSimpleTextOutProtocolGuid
,
856 if (!EFI_ERROR (Status
)) {
857 for (Index
= 0; Index
< HandleCount
; Index
++) {
858 gBS
->DisconnectController (HandleBuffer
[Index
], NULL
, NULL
);
860 for (Index
= 0; Index
< HandleCount
; Index
++) {
861 gBS
->ConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
863 if (HandleBuffer
!= NULL
) {
864 FreePool (HandleBuffer
);
872 Display the boot popup menu and allow user select boot item.
874 @param ImageHandle The image handle.
875 @param SystemTable The system table.
877 @retval EFI_SUCCESS Boot from selected boot option, and return success from boot option
878 @retval EFI_NOT_FOUND User select to enter setup or can not find boot option
883 BootManagerMenuEntry (
884 IN EFI_HANDLE ImageHandle
,
885 IN EFI_SYSTEM_TABLE
*SystemTable
888 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOption
;
889 UINTN BootOptionCount
;
891 BOOT_MENU_POPUP_DATA BootMenuData
;
894 BOOLEAN ExitApplication
;
896 EFI_BOOT_LOGO_PROTOCOL
*BootLogo
;
897 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
898 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
899 UINTN BootTextColumn
;
903 // Set Logo status invalid when boot manager menu is launched
906 Status
= gBS
->LocateProtocol (&gEfiBootLogoProtocolGuid
, NULL
, (VOID
**) &BootLogo
);
907 if (!EFI_ERROR (Status
) && (BootLogo
!= NULL
)) {
908 Status
= BootLogo
->SetBootLogo (BootLogo
, NULL
, 0, 0, 0, 0);
909 ASSERT_EFI_ERROR (Status
);
912 gBS
->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL
);
914 gStringPackHandle
= HiiAddPackages (
917 BootManagerMenuAppStrings
,
920 ASSERT (gStringPackHandle
!= NULL
);
923 // Connect all prior to entering the platform setup menu.
925 EfiBootManagerConnectAll ();
926 EfiBootManagerRefreshAllBootOption ();
928 BootOption
= EfiBootManagerGetLoadOptions (&BootOptionCount
, LoadOptionTypeBoot
);
930 if (!mModeInitialized
) {
932 // After the console is ready, get current video resolution
933 // and text mode before launching setup at first time.
935 Status
= gBS
->HandleProtocol (
936 gST
->ConsoleOutHandle
,
937 &gEfiGraphicsOutputProtocolGuid
,
938 (VOID
**)&GraphicsOutput
940 if (EFI_ERROR (Status
)) {
941 GraphicsOutput
= NULL
;
944 Status
= gBS
->HandleProtocol (
945 gST
->ConsoleOutHandle
,
946 &gEfiSimpleTextOutProtocolGuid
,
947 (VOID
**)&SimpleTextOut
949 if (EFI_ERROR (Status
)) {
950 SimpleTextOut
= NULL
;
953 if (GraphicsOutput
!= NULL
) {
955 // Get current video resolution and text mode.
957 mBootHorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
958 mBootVerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
961 if (SimpleTextOut
!= NULL
) {
962 Status
= SimpleTextOut
->QueryMode (
964 SimpleTextOut
->Mode
->Mode
,
968 mBootTextModeColumn
= (UINT32
)BootTextColumn
;
969 mBootTextModeRow
= (UINT32
)BootTextRow
;
973 // Get user defined text mode for setup.
975 mSetupHorizontalResolution
= PcdGet32 (PcdSetupVideoHorizontalResolution
);
976 mSetupVerticalResolution
= PcdGet32 (PcdSetupVideoVerticalResolution
);
977 mSetupTextModeColumn
= PcdGet32 (PcdSetupConOutColumn
);
978 mSetupTextModeRow
= PcdGet32 (PcdSetupConOutRow
);
979 mModeInitialized
= TRUE
;
983 // Set back to conventional setup resolution
985 BdsSetConsoleMode (TRUE
);
988 // Initialize Boot menu data
990 Status
= InitializeBootMenuData (BootOption
, BootOptionCount
, &BootMenuData
);
992 // According to boot menu data to draw boot popup menu
994 DrawBootPopupMenu (&BootMenuData
);
997 // check user input to determine want to re-draw or boot from user selected item
999 ExitApplication
= FALSE
;
1000 while (!ExitApplication
) {
1001 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
1002 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1003 if (!EFI_ERROR (Status
)) {
1004 switch (Key
.UnicodeChar
) {
1007 switch (Key
.ScanCode
) {
1010 SelectItem
= BootMenuData
.SelectItem
== 0 ? BootMenuData
.ItemCount
- 1 : BootMenuData
.SelectItem
- 1;
1011 BootMenuSelectItem (SelectItem
, &BootMenuData
);
1015 SelectItem
= BootMenuData
.SelectItem
== BootMenuData
.ItemCount
- 1 ? 0 : BootMenuData
.SelectItem
+ 1;
1016 BootMenuSelectItem (SelectItem
, &BootMenuData
);
1020 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1021 ExitApplication
= TRUE
;
1023 // Set boot resolution for normal boot
1025 BdsSetConsoleMode (FALSE
);
1033 case CHAR_CARRIAGE_RETURN
:
1034 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1036 // Set boot resolution for normal boot
1038 BdsSetConsoleMode (FALSE
);
1039 BootFromSelectOption (BootOption
, BootOptionCount
, BootMenuData
.SelectItem
);
1041 // Back to boot manager menu again, set back to setup resolution
1043 BdsSetConsoleMode (TRUE
);
1044 DrawBootPopupMenu (&BootMenuData
);
1052 EfiBootManagerFreeLoadOptions (BootOption
, BootOptionCount
);
1053 FreePool (BootMenuData
.PtrTokens
);
1055 HiiRemovePackages (gStringPackHandle
);