TianoCore EDK2 master
Loading...
Searching...
No Matches
BootManagerMenu.c
Go to the documentation of this file.
1
9#include "BootManagerMenu.h"
10
11EFI_HII_HANDLE gStringPackHandle;
12
13BOOLEAN mModeInitialized = FALSE;
14
15//
16// Boot video resolution and text mode.
17//
18UINT32 mBootHorizontalResolution = 0;
19UINT32 mBootVerticalResolution = 0;
20UINT32 mBootTextModeColumn = 0;
21UINT32 mBootTextModeRow = 0;
22//
23// BIOS setup video resolution and text mode.
24//
25UINT32 mSetupTextModeColumn = 0;
26UINT32 mSetupTextModeRow = 0;
27UINT32 mSetupHorizontalResolution = 0;
28UINT32 mSetupVerticalResolution = 0;
29
43 IN UINTN Column,
44 IN UINTN Row,
45 IN CHAR16 *String
46 )
47{
48 UINTN ScreenWidth;
49 UINTN ScreenRows;
50 CHAR16 *TurncateString;
51 EFI_STATUS Status;
52 UINTN ShowingLength;
53
54 gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
55
56 gST->ConOut->QueryMode (
57 gST->ConOut,
59 &ScreenWidth,
60 &ScreenRows
61 );
62
63 if ((Column > (ScreenWidth - 1)) || (Row > (ScreenRows - 1))) {
64 return 0;
65 }
66
67 if ((StrLen (String) + Column) > (ScreenWidth - 1)) {
68 //
69 // | - ScreenWidth - |
70 // ...Column.....................
71 // TurncateString length should leave one character for draw box and
72 // require one character for string end.
73 //
74 ShowingLength = ScreenWidth - Column - 1;
75 TurncateString = AllocatePool ((ShowingLength + 1) * sizeof (CHAR16));
76
77 if (TurncateString == NULL) {
78 return 0;
79 }
80
81 Status = StrnCpyS (TurncateString, ShowingLength + 1, String, ShowingLength - 3);
82
83 if (EFI_ERROR (Status)) {
84 FreePool (TurncateString);
85 return 0;
86 }
87
88 *(TurncateString + ShowingLength - 3) = L'.';
89 *(TurncateString + ShowingLength - 2) = L'.';
90 *(TurncateString + ShowingLength - 1) = L'.';
91 *(TurncateString + ShowingLength) = L'\0';
92 ShowingLength = Print (L"%s", TurncateString);
93 FreePool (TurncateString);
94 return ShowingLength;
95 } else {
96 return Print (L"%s", String);
97 }
98}
99
111UINTN
113 IN UINTN Column,
114 IN UINTN Row,
115 CHAR16 Character
116 )
117{
118 UINTN ScreenWidth;
119 UINTN ScreenRows;
120
121 gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
122
123 gST->ConOut->QueryMode (
124 gST->ConOut,
125 gST->ConOut->Mode->Mode,
126 &ScreenWidth,
127 &ScreenRows
128 );
129
130 if ((Column > (ScreenWidth - 1)) || (Row > (ScreenRows - 1))) {
131 return 0;
132 }
133
134 return Print (L"%c", Character);
135}
136
146UINTN
148 IN EFI_STRING_ID StringId
149 )
150{
151 UINTN Index;
152 UINTN IncrementValue;
153 EFI_STRING String;
154 UINTN LineWidth;
155
156 LineWidth = 0;
157 String = HiiGetString (gStringPackHandle, StringId, NULL);
158
159 if (String != NULL) {
160 Index = 0;
161 IncrementValue = 1;
162
163 do {
164 //
165 // Advance to the null-terminator or to the first width directive
166 //
167 for ( ;
168 (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);
169 Index++, LineWidth = LineWidth + IncrementValue
170 )
171 {
172 }
173
174 //
175 // We hit the null-terminator, we now have a count
176 //
177 if (String[Index] == 0) {
178 break;
179 }
180
181 //
182 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
183 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
184 //
185 if (String[Index] == NARROW_CHAR) {
186 //
187 // Skip to the next character
188 //
189 Index++;
190 IncrementValue = 1;
191 } else {
192 //
193 // Skip to the next character
194 //
195 Index++;
196 IncrementValue = 2;
197 }
198 } while (String[Index] != 0);
199
200 FreePool (String);
201 }
202
203 return LineWidth;
204}
205
217 IN OUT BOOT_MENU_POPUP_DATA *BootMenuData
218 )
219{
220 UINTN MaxStrWidth;
221 UINTN StrWidth;
222 UINTN Index;
223 UINTN Column;
224 UINTN Row;
225 UINTN MaxPrintRows;
226 UINTN UnSelectableItmes;
227
228 if (BootMenuData == NULL) {
229 return EFI_INVALID_PARAMETER;
230 }
231
232 //
233 // Get maximum string width
234 //
235 MaxStrWidth = 0;
236 for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++) {
237 StrWidth = GetLineWidth (BootMenuData->TitleToken[Index]);
238 MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth;
239 }
240
241 for (Index = 0; Index < BootMenuData->ItemCount; Index++) {
242 StrWidth = GetLineWidth (BootMenuData->PtrTokens[Index]);
243 MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth;
244 }
245
246 for (Index = 0; Index < HELP_TOKEN_COUNT; Index++) {
247 StrWidth = GetLineWidth (BootMenuData->HelpToken[Index]);
248 MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth;
249 }
250
251 //
252 // query current row and column to calculate boot menu location
253 //
254 gST->ConOut->QueryMode (
255 gST->ConOut,
256 gST->ConOut->Mode->Mode,
257 &Column,
258 &Row
259 );
260
261 MaxPrintRows = Row - 6;
262 UnSelectableItmes = TITLE_TOKEN_COUNT + 2 + HELP_TOKEN_COUNT + 2;
263 if (MaxStrWidth + 8 > Column) {
264 BootMenuData->MenuScreen.Width = Column;
265 } else {
266 BootMenuData->MenuScreen.Width = MaxStrWidth + 8;
267 }
268
269 if (BootMenuData->ItemCount + UnSelectableItmes > MaxPrintRows) {
270 BootMenuData->MenuScreen.Height = MaxPrintRows;
271 BootMenuData->ScrollBarControl.HasScrollBar = TRUE;
272 BootMenuData->ScrollBarControl.ItemCountPerScreen = MaxPrintRows - UnSelectableItmes;
273 BootMenuData->ScrollBarControl.FirstItem = 0;
274 BootMenuData->ScrollBarControl.LastItem = MaxPrintRows - UnSelectableItmes - 1;
275 } else {
276 BootMenuData->MenuScreen.Height = BootMenuData->ItemCount + UnSelectableItmes;
277 BootMenuData->ScrollBarControl.HasScrollBar = FALSE;
278 BootMenuData->ScrollBarControl.ItemCountPerScreen = BootMenuData->ItemCount;
279 BootMenuData->ScrollBarControl.FirstItem = 0;
280 BootMenuData->ScrollBarControl.LastItem = BootMenuData->ItemCount - 1;
281 }
282
283 BootMenuData->MenuScreen.StartCol = (Column - BootMenuData->MenuScreen.Width) / 2;
284 BootMenuData->MenuScreen.StartRow = (Row - BootMenuData->MenuScreen.Height) / 2;
285
286 return EFI_SUCCESS;
287}
288
298BOOLEAN
301 )
302{
303 EFI_STATUS Status;
304 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
305
306 Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
307 if (!EFI_ERROR (Status)) {
308 EfiBootManagerFreeLoadOption (&BootManagerMenu);
309 }
310
311 return (BOOLEAN)(!EFI_ERROR (Status) && (BootOption->OptionNumber == BootManagerMenu.OptionNumber));
312}
313
322BOOLEAN
325 )
326{
327 EFI_STATUS Status;
328 EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
329
330 //
331 // Ignore myself.
332 //
333 Status = gBS->HandleProtocol (gImageHandle, &gEfiLoadedImageDevicePathProtocolGuid, (VOID **)&ImageDevicePath);
334 ASSERT_EFI_ERROR (Status);
335 if (CompareMem (BootOption->FilePath, ImageDevicePath, GetDevicePathSize (ImageDevicePath)) == 0) {
336 return TRUE;
337 }
338
339 //
340 // Do not ignore Boot Manager Menu.
341 //
342 if (IsBootManagerMenu (BootOption)) {
343 return FALSE;
344 }
345
346 //
347 // Ignore the hidden/inactive boot option.
348 //
349 if (((BootOption->Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption->Attributes & LOAD_OPTION_ACTIVE) == 0)) {
350 return TRUE;
351 }
352
353 return FALSE;
354}
355
370 IN UINTN BootOptionCount,
371 OUT BOOT_MENU_POPUP_DATA *BootMenuData
372 )
373{
374 UINTN Index;
375 UINTN StrIndex;
376
377 if ((BootOption == NULL) || (BootMenuData == NULL)) {
378 return EFI_INVALID_PARAMETER;
379 }
380
381 BootMenuData->TitleToken[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_TITLE_STRING);
382 BootMenuData->PtrTokens = AllocateZeroPool (BootOptionCount * sizeof (EFI_STRING_ID));
383 ASSERT (BootMenuData->PtrTokens != NULL);
384
385 //
386 // Skip boot option which created by BootNext Variable
387 //
388 for (StrIndex = 0, Index = 0; Index < BootOptionCount; Index++) {
389 if (IgnoreBootOption (&BootOption[Index])) {
390 continue;
391 }
392
393 ASSERT (BootOption[Index].Description != NULL);
394 BootMenuData->PtrTokens[StrIndex++] = HiiSetString (
395 gStringPackHandle,
396 0,
397 BootOption[Index].Description,
398 NULL
399 );
400 }
401
402 BootMenuData->ItemCount = StrIndex;
403 BootMenuData->HelpToken[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP1_STRING);
404 BootMenuData->HelpToken[1] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP2_STRING);
405 BootMenuData->HelpToken[2] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP3_STRING);
406 InitializeBootMenuScreen (BootMenuData);
407 BootMenuData->SelectItem = 0;
408 return EFI_SUCCESS;
409}
410
424 IN UINTN WantSelectItem,
425 IN OUT BOOT_MENU_POPUP_DATA *BootMenuData
426 )
427{
428 INT32 SavedAttribute;
429 EFI_STRING String;
430 UINTN StartCol;
431 UINTN StartRow;
432 UINTN PrintCol;
433 UINTN PrintRow;
434 UINTN TopShadeNum;
435 UINTN LowShadeNum;
436 UINTN FirstItem;
437 UINTN LastItem;
438 UINTN ItemCountPerScreen;
439 UINTN Index;
440 BOOLEAN RePaintItems;
441
442 if ((BootMenuData == NULL) || (WantSelectItem >= BootMenuData->ItemCount)) {
443 return EFI_INVALID_PARAMETER;
444 }
445
446 ASSERT (BootMenuData->ItemCount != 0);
447 SavedAttribute = gST->ConOut->Mode->Attribute;
448 RePaintItems = FALSE;
449 StartCol = BootMenuData->MenuScreen.StartCol;
450 StartRow = BootMenuData->MenuScreen.StartRow;
451 //
452 // print selectable items again and adjust scroll bar if need
453 //
454 if (BootMenuData->ScrollBarControl.HasScrollBar &&
455 ((WantSelectItem < BootMenuData->ScrollBarControl.FirstItem) ||
456 (WantSelectItem > BootMenuData->ScrollBarControl.LastItem) ||
457 (WantSelectItem == BootMenuData->SelectItem)))
458 {
459 ItemCountPerScreen = BootMenuData->ScrollBarControl.ItemCountPerScreen;
460 //
461 // Set first item and last item
462 //
463 if (WantSelectItem < BootMenuData->ScrollBarControl.FirstItem) {
464 BootMenuData->ScrollBarControl.FirstItem = WantSelectItem;
465 BootMenuData->ScrollBarControl.LastItem = WantSelectItem + ItemCountPerScreen - 1;
466 } else if (WantSelectItem > BootMenuData->ScrollBarControl.LastItem) {
467 BootMenuData->ScrollBarControl.FirstItem = WantSelectItem - ItemCountPerScreen + 1;
468 BootMenuData->ScrollBarControl.LastItem = WantSelectItem;
469 }
470
471 gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);
472 FirstItem = BootMenuData->ScrollBarControl.FirstItem;
473 LastItem = BootMenuData->ScrollBarControl.LastItem;
474 TopShadeNum = 0;
475 if (FirstItem != 0) {
476 TopShadeNum = (FirstItem * ItemCountPerScreen) / BootMenuData->ItemCount;
477 if ((FirstItem * ItemCountPerScreen) % BootMenuData->ItemCount != 0) {
478 TopShadeNum++;
479 }
480
481 PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;
482 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;
483 for (Index = 0; Index < TopShadeNum; Index++, PrintRow++) {
484 PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_LIGHT_SHADE);
485 }
486 }
487
488 LowShadeNum = 0;
489 if (LastItem != BootMenuData->ItemCount - 1) {
490 LowShadeNum = ((BootMenuData->ItemCount - 1 - LastItem) * ItemCountPerScreen) / BootMenuData->ItemCount;
491 if (((BootMenuData->ItemCount - 1 - LastItem) * ItemCountPerScreen) % BootMenuData->ItemCount != 0) {
492 LowShadeNum++;
493 }
494
495 PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;
496 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + ItemCountPerScreen - LowShadeNum;
497 for (Index = 0; Index < LowShadeNum; Index++, PrintRow++) {
498 PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_LIGHT_SHADE);
499 }
500 }
501
502 PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;
503 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + TopShadeNum;
504 for (Index = TopShadeNum; Index < ItemCountPerScreen - LowShadeNum; Index++, PrintRow++) {
505 PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_FULL_BLOCK);
506 }
507
508 //
509 // Clear selectable items first
510 //
511 PrintCol = StartCol + 1;
512 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;
513 String = AllocateZeroPool ((BootMenuData->MenuScreen.Width - 2) * sizeof (CHAR16));
514 ASSERT (String != NULL);
515 for (Index = 0; Index < BootMenuData->MenuScreen.Width - 3; Index++) {
516 String[Index] = 0x20;
517 }
518
519 for (Index = 0; Index < ItemCountPerScreen; Index++) {
520 PrintStringAt (PrintCol, PrintRow + Index, String);
521 }
522
523 FreePool (String);
524 //
525 // print selectable items
526 //
527 for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) {
528 String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index + FirstItem], NULL);
529 PrintStringAt (PrintCol, PrintRow, String);
530 FreePool (String);
531 }
532
533 RePaintItems = TRUE;
534 }
535
536 //
537 // if Want Select and selected item isn't the same and doesn't re-draw selectable
538 // items, clear select item
539 //
540 FirstItem = BootMenuData->ScrollBarControl.FirstItem;
541 if ((WantSelectItem != BootMenuData->SelectItem) && !RePaintItems) {
542 gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);
543 String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[BootMenuData->SelectItem], NULL);
544 PrintCol = StartCol + 1;
545 PrintRow = StartRow + 3 + BootMenuData->SelectItem - FirstItem;
546 PrintStringAt (PrintCol, PrintRow, String);
547 FreePool (String);
548 }
549
550 //
551 // Print want to select item
552 //
553 gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLACK);
554 String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[WantSelectItem], NULL);
555 PrintCol = StartCol + 1;
556 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + WantSelectItem - FirstItem;
557 PrintStringAt (PrintCol, PrintRow, String);
558 FreePool (String);
559
560 gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
561 BootMenuData->SelectItem = WantSelectItem;
562 return EFI_SUCCESS;
563}
564
575 IN BOOT_MENU_POPUP_DATA *BootMenuData
576 )
577{
578 EFI_STRING String;
579 UINTN Index;
580 UINTN Width;
581 UINTN StartCol;
582 UINTN StartRow;
583 UINTN PrintRow;
584 UINTN PrintCol;
585 UINTN LineWidth;
586 INT32 SavedAttribute;
587 UINTN ItemCountPerScreen;
588
589 gST->ConOut->ClearScreen (gST->ConOut);
590
591 SavedAttribute = gST->ConOut->Mode->Attribute;
592 gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);
593 Width = BootMenuData->MenuScreen.Width;
594 StartCol = BootMenuData->MenuScreen.StartCol;
595 StartRow = BootMenuData->MenuScreen.StartRow;
596 ItemCountPerScreen = BootMenuData->ScrollBarControl.ItemCountPerScreen;
597 PrintRow = StartRow;
598
599 gST->ConOut->EnableCursor (gST->ConOut, FALSE);
600 //
601 // Draw Boot popup menu screen
602 //
603 PrintCharAt (StartCol, PrintRow, BOXDRAW_DOWN_RIGHT);
604 for (Index = 1; Index < Width - 1; Index++) {
605 PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL);
606 }
607
608 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_DOWN_LEFT);
609
610 //
611 // Draw the screen for title
612 //
613 String = AllocateZeroPool ((Width - 1) * sizeof (CHAR16));
614 ASSERT (String != NULL);
615 for (Index = 0; Index < Width - 2; Index++) {
616 String[Index] = 0x20;
617 }
618
619 for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++) {
620 PrintRow++;
621 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);
622 PrintStringAt (StartCol + 1, PrintRow, String);
623 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);
624 }
625
626 PrintRow++;
627 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL_RIGHT);
628 for (Index = 1; Index < Width - 1; Index++) {
629 PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL);
630 }
631
632 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL_LEFT);
633
634 //
635 // Draw screen for selectable items
636 //
637 for (Index = 0; Index < ItemCountPerScreen; Index++) {
638 PrintRow++;
639 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);
640 PrintStringAt (StartCol + 1, PrintRow, String);
641 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);
642 }
643
644 PrintRow++;
645 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL_RIGHT);
646 for (Index = 1; Index < Width - 1; Index++) {
647 PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL);
648 }
649
650 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL_LEFT);
651
652 //
653 // Draw screen for Help
654 //
655 for (Index = 0; Index < HELP_TOKEN_COUNT; Index++) {
656 PrintRow++;
657 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);
658 PrintStringAt (StartCol + 1, PrintRow, String);
659 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);
660 }
661
662 FreePool (String);
663
664 PrintRow++;
665 PrintCharAt (StartCol, PrintRow, BOXDRAW_UP_RIGHT);
666 for (Index = 1; Index < Width - 1; Index++) {
667 PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL);
668 }
669
670 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_UP_LEFT);
671
672 //
673 // print title strings
674 //
675 PrintRow = StartRow + 1;
676 for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++, PrintRow++) {
677 String = HiiGetString (gStringPackHandle, BootMenuData->TitleToken[Index], NULL);
678 LineWidth = GetLineWidth (BootMenuData->TitleToken[Index]);
679 PrintCol = StartCol + (Width - LineWidth) / 2;
680 PrintStringAt (PrintCol, PrintRow, String);
681 FreePool (String);
682 }
683
684 //
685 // print selectable items
686 //
687 PrintCol = StartCol + 1;
688 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;
689 for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) {
690 String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index], NULL);
691 PrintStringAt (PrintCol, PrintRow, String);
692 FreePool (String);
693 }
694
695 //
696 // Print Help strings
697 //
698 PrintRow++;
699 for (Index = 0; Index < HELP_TOKEN_COUNT; Index++, PrintRow++) {
700 String = HiiGetString (gStringPackHandle, BootMenuData->HelpToken[Index], NULL);
701 LineWidth = GetLineWidth (BootMenuData->HelpToken[Index]);
702 PrintCol = StartCol + (Width - LineWidth) / 2;
703 PrintStringAt (PrintCol, PrintRow, String);
704 FreePool (String);
705 }
706
707 //
708 // Print scroll bar if has scroll bar
709 //
710 if (BootMenuData->ScrollBarControl.HasScrollBar) {
711 PrintCol = StartCol + Width - 2;
712 PrintRow = StartRow + 2;
713 PrintCharAt (PrintCol, PrintRow, GEOMETRICSHAPE_UP_TRIANGLE);
714 PrintCharAt (PrintCol + 1, PrintRow, BOXDRAW_VERTICAL);
715 PrintRow += (ItemCountPerScreen + 1);
716 PrintCharAt (PrintCol, PrintRow, GEOMETRICSHAPE_DOWN_TRIANGLE);
717 PrintCharAt (PrintCol + 1, PrintRow, BOXDRAW_VERTICAL);
718 }
719
720 gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
721 //
722 // Print Selected item
723 //
724 BootMenuSelectItem (BootMenuData->SelectItem, BootMenuData);
725 return EFI_SUCCESS;
726}
727
735VOID
737 IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions,
738 IN UINTN BootOptionCount,
739 IN UINTN SelectItem
740 )
741{
742 UINTN ItemNum;
743 UINTN Index;
744
745 ASSERT (BootOptions != NULL);
746
747 for (ItemNum = 0, Index = 0; Index < BootOptionCount; Index++) {
748 if (IgnoreBootOption (&BootOptions[Index])) {
749 continue;
750 }
751
752 if (ItemNum++ == SelectItem) {
753 EfiBootManagerBoot (&BootOptions[Index]);
754 break;
755 }
756 }
757}
758
770EFIAPI
772 BOOLEAN IsSetupMode
773 )
774{
775 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
776 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
777 UINTN SizeOfInfo;
779 UINT32 MaxGopMode;
780 UINT32 MaxTextMode;
781 UINT32 ModeNumber;
782 UINT32 NewHorizontalResolution;
783 UINT32 NewVerticalResolution;
784 UINT32 NewColumns;
785 UINT32 NewRows;
786 UINTN HandleCount;
787 EFI_HANDLE *HandleBuffer;
788 EFI_STATUS Status;
789 UINTN Index;
790 UINTN CurrentColumn;
791 UINTN CurrentRow;
792
793 MaxGopMode = 0;
794 MaxTextMode = 0;
795
796 //
797 // Get current video resolution and text mode
798 //
799 Status = gBS->HandleProtocol (
801 &gEfiGraphicsOutputProtocolGuid,
802 (VOID **)&GraphicsOutput
803 );
804 if (EFI_ERROR (Status)) {
805 GraphicsOutput = NULL;
806 }
807
808 Status = gBS->HandleProtocol (
810 &gEfiSimpleTextOutProtocolGuid,
811 (VOID **)&SimpleTextOut
812 );
813 if (EFI_ERROR (Status)) {
814 SimpleTextOut = NULL;
815 }
816
817 if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {
818 return EFI_UNSUPPORTED;
819 }
820
821 if (IsSetupMode) {
822 //
823 // The required resolution and text mode is setup mode.
824 //
825 NewHorizontalResolution = mSetupHorizontalResolution;
826 NewVerticalResolution = mSetupVerticalResolution;
827 NewColumns = mSetupTextModeColumn;
828 NewRows = mSetupTextModeRow;
829 } else {
830 //
831 // The required resolution and text mode is boot mode.
832 //
833 NewHorizontalResolution = mBootHorizontalResolution;
834 NewVerticalResolution = mBootVerticalResolution;
835 NewColumns = mBootTextModeColumn;
836 NewRows = mBootTextModeRow;
837 }
838
839 if (GraphicsOutput != NULL) {
840 MaxGopMode = GraphicsOutput->Mode->MaxMode;
841 }
842
843 if (SimpleTextOut != NULL) {
844 MaxTextMode = SimpleTextOut->Mode->MaxMode;
845 }
846
847 //
848 // 1. If current video resolution is same with required video resolution,
849 // video resolution need not be changed.
850 // 1.1. If current text mode is same with required text mode, text mode need not be changed.
851 // 1.2. If current text mode is different from required text mode, text mode need be changed.
852 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.
853 //
854 for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {
855 Status = GraphicsOutput->QueryMode (
856 GraphicsOutput,
857 ModeNumber,
858 &SizeOfInfo,
859 &Info
860 );
861 if (!EFI_ERROR (Status)) {
862 if ((Info->HorizontalResolution == NewHorizontalResolution) &&
863 (Info->VerticalResolution == NewVerticalResolution))
864 {
865 if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) &&
866 (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution))
867 {
868 //
869 // Current resolution is same with required resolution, check if text mode need be set
870 //
871 Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);
872 ASSERT_EFI_ERROR (Status);
873 if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) {
874 //
875 // If current text mode is same with required text mode. Do nothing
876 //
877 FreePool (Info);
878 return EFI_SUCCESS;
879 } else {
880 //
881 // If current text mode is different from required text mode. Set new video mode
882 //
883 for (Index = 0; Index < MaxTextMode; Index++) {
884 Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);
885 if (!EFI_ERROR (Status)) {
886 if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) {
887 //
888 // Required text mode is supported, set it.
889 //
890 Status = SimpleTextOut->SetMode (SimpleTextOut, Index);
891 ASSERT_EFI_ERROR (Status);
892 //
893 // Update text mode PCD.
894 //
895 Status = PcdSet32S (PcdConOutColumn, mSetupTextModeColumn);
896 ASSERT_EFI_ERROR (Status);
897 Status = PcdSet32S (PcdConOutRow, mSetupTextModeRow);
898 ASSERT_EFI_ERROR (Status);
899 FreePool (Info);
900 return EFI_SUCCESS;
901 }
902 }
903 }
904
905 if (Index == MaxTextMode) {
906 //
907 // If required text mode is not supported, return error.
908 //
909 FreePool (Info);
910 return EFI_UNSUPPORTED;
911 }
912 }
913 } else {
914 //
915 // If current video resolution is not same with the new one, set new video resolution.
916 // In this case, the driver which produces simple text out need be restarted.
917 //
918 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
919 if (!EFI_ERROR (Status)) {
920 FreePool (Info);
921 break;
922 }
923 }
924 }
925
926 FreePool (Info);
927 }
928 }
929
930 if (ModeNumber == MaxGopMode) {
931 //
932 // If the resolution is not supported, return error.
933 //
934 return EFI_UNSUPPORTED;
935 }
936
937 //
938 // Set PCD to Inform GraphicsConsole to change video resolution.
939 // Set PCD to Inform Consplitter to change text mode.
940 //
941 Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution);
942 ASSERT_EFI_ERROR (Status);
943 Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution);
944 ASSERT_EFI_ERROR (Status);
945 Status = PcdSet32S (PcdConOutColumn, NewColumns);
946 ASSERT_EFI_ERROR (Status);
947 Status = PcdSet32S (PcdConOutRow, NewRows);
948 ASSERT_EFI_ERROR (Status);
949
950 //
951 // Video mode is changed, so restart graphics console driver and higher level driver.
952 // Reconnect graphics console driver and higher level driver.
953 // Locate all the handles with GOP protocol and reconnect it.
954 //
955 Status = gBS->LocateHandleBuffer (
957 &gEfiSimpleTextOutProtocolGuid,
958 NULL,
959 &HandleCount,
960 &HandleBuffer
961 );
962 if (!EFI_ERROR (Status)) {
963 for (Index = 0; Index < HandleCount; Index++) {
964 gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
965 }
966
967 for (Index = 0; Index < HandleCount; Index++) {
968 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
969 }
970
971 if (HandleBuffer != NULL) {
972 FreePool (HandleBuffer);
973 }
974 }
975
976 return EFI_SUCCESS;
977}
978
990EFIAPI
992 IN EFI_HANDLE ImageHandle,
993 IN EFI_SYSTEM_TABLE *SystemTable
994 )
995{
997 UINTN BootOptionCount;
998 EFI_STATUS Status;
999 BOOT_MENU_POPUP_DATA BootMenuData;
1000 UINTN Index;
1001 EFI_INPUT_KEY Key;
1002 BOOLEAN ExitApplication;
1003 UINTN SelectItem;
1004 EFI_BOOT_LOGO_PROTOCOL *BootLogo;
1005 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1006 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
1007 UINTN BootTextColumn;
1008 UINTN BootTextRow;
1009
1010 //
1011 // Set Logo status invalid when boot manager menu is launched
1012 //
1013 BootLogo = NULL;
1014 Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **)&BootLogo);
1015 if (!EFI_ERROR (Status) && (BootLogo != NULL)) {
1016 Status = BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);
1017 ASSERT_EFI_ERROR (Status);
1018 }
1019
1020 gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
1021
1022 gStringPackHandle = HiiAddPackages (
1023 &gEfiCallerIdGuid,
1025 BootManagerMenuAppStrings,
1026 NULL
1027 );
1028 ASSERT (gStringPackHandle != NULL);
1029
1030 //
1031 // Connect all prior to entering the platform setup menu.
1032 //
1035
1036 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
1037
1038 if (!mModeInitialized) {
1039 //
1040 // After the console is ready, get current video resolution
1041 // and text mode before launching setup at first time.
1042 //
1043 Status = gBS->HandleProtocol (
1045 &gEfiGraphicsOutputProtocolGuid,
1046 (VOID **)&GraphicsOutput
1047 );
1048 if (EFI_ERROR (Status)) {
1049 GraphicsOutput = NULL;
1050 }
1051
1052 Status = gBS->HandleProtocol (
1054 &gEfiSimpleTextOutProtocolGuid,
1055 (VOID **)&SimpleTextOut
1056 );
1057 if (EFI_ERROR (Status)) {
1058 SimpleTextOut = NULL;
1059 }
1060
1061 if (GraphicsOutput != NULL) {
1062 //
1063 // Get current video resolution and text mode.
1064 //
1065 mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
1066 mBootVerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;
1067 }
1068
1069 if (SimpleTextOut != NULL) {
1070 Status = SimpleTextOut->QueryMode (
1071 SimpleTextOut,
1072 SimpleTextOut->Mode->Mode,
1073 &BootTextColumn,
1074 &BootTextRow
1075 );
1076 mBootTextModeColumn = (UINT32)BootTextColumn;
1077 mBootTextModeRow = (UINT32)BootTextRow;
1078 }
1079
1080 //
1081 // Get user defined text mode for setup.
1082 //
1083 mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
1084 mSetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution);
1085 mSetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn);
1086 mSetupTextModeRow = PcdGet32 (PcdSetupConOutRow);
1087 mModeInitialized = TRUE;
1088 }
1089
1090 //
1091 // Set back to conventional setup resolution
1092 //
1094
1095 //
1096 // Initialize Boot menu data
1097 //
1098 Status = InitializeBootMenuData (BootOption, BootOptionCount, &BootMenuData);
1099 //
1100 // According to boot menu data to draw boot popup menu
1101 //
1102 DrawBootPopupMenu (&BootMenuData);
1103
1104 //
1105 // check user input to determine want to re-draw or boot from user selected item
1106 //
1107 ExitApplication = FALSE;
1108 while (!ExitApplication) {
1109 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);
1110 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
1111 if (!EFI_ERROR (Status)) {
1112 switch (Key.UnicodeChar) {
1113 case CHAR_NULL:
1114 switch (Key.ScanCode) {
1115 case SCAN_UP:
1116 SelectItem = BootMenuData.SelectItem == 0 ? BootMenuData.ItemCount - 1 : BootMenuData.SelectItem - 1;
1117 BootMenuSelectItem (SelectItem, &BootMenuData);
1118 break;
1119
1120 case SCAN_DOWN:
1121 SelectItem = BootMenuData.SelectItem == BootMenuData.ItemCount - 1 ? 0 : BootMenuData.SelectItem + 1;
1122 BootMenuSelectItem (SelectItem, &BootMenuData);
1123 break;
1124
1125 case SCAN_ESC:
1126 gST->ConOut->ClearScreen (gST->ConOut);
1127 ExitApplication = TRUE;
1128 //
1129 // Set boot resolution for normal boot
1130 //
1132 break;
1133
1134 default:
1135 break;
1136 }
1137
1138 break;
1139
1140 case CHAR_CARRIAGE_RETURN:
1141 gST->ConOut->ClearScreen (gST->ConOut);
1142 //
1143 // Set boot resolution for normal boot
1144 //
1146 BootFromSelectOption (BootOption, BootOptionCount, BootMenuData.SelectItem);
1147 //
1148 // Back to boot manager menu again, set back to setup resolution
1149 //
1151 DrawBootPopupMenu (&BootMenuData);
1152 break;
1153
1154 default:
1155 break;
1156 }
1157 }
1158 }
1159
1160 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
1161 FreePool (BootMenuData.PtrTokens);
1162
1163 HiiRemovePackages (gStringPackHandle);
1164
1165 return Status;
1166}
UINT64 UINTN
RETURN_STATUS EFIAPI StrnCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source, IN UINTN Length)
Definition: SafeString.c:310
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
UINTN PrintCharAt(IN UINTN Column, IN UINTN Row, CHAR16 Character)
VOID BootFromSelectOption(IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions, IN UINTN BootOptionCount, IN UINTN SelectItem)
EFI_STATUS EFIAPI BdsSetConsoleMode(BOOLEAN IsSetupMode)
EFI_STATUS DrawBootPopupMenu(IN BOOT_MENU_POPUP_DATA *BootMenuData)
EFI_STATUS InitializeBootMenuScreen(IN OUT BOOT_MENU_POPUP_DATA *BootMenuData)
UINTN GetLineWidth(IN EFI_STRING_ID StringId)
EFI_STATUS BootMenuSelectItem(IN UINTN WantSelectItem, IN OUT BOOT_MENU_POPUP_DATA *BootMenuData)
BOOLEAN IsBootManagerMenu(IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption)
UINTN PrintStringAt(IN UINTN Column, IN UINTN Row, IN CHAR16 *String)
BOOLEAN IgnoreBootOption(IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption)
EFI_STATUS InitializeBootMenuData(IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption, IN UINTN BootOptionCount, OUT BOOT_MENU_POPUP_DATA *BootMenuData)
EFI_STATUS EFIAPI BootManagerMenuEntry(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
UINTN EFIAPI GetDevicePathSize(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_HII_HANDLE EFIAPI HiiAddPackages(IN CONST EFI_GUID *PackageListGuid, IN EFI_HANDLE DeviceHandle OPTIONAL,...)
Definition: HiiLib.c:141
EFI_STRING EFIAPI HiiGetString(IN EFI_HII_HANDLE HiiHandle, IN EFI_STRING_ID StringId, IN CONST CHAR8 *Language OPTIONAL)
Definition: HiiString.c:211
EFI_STRING_ID EFIAPI HiiSetString(IN EFI_HII_HANDLE HiiHandle, IN EFI_STRING_ID StringId OPTIONAL, IN CONST EFI_STRING String, IN CONST CHAR8 *SupportedLanguages OPTIONAL)
Definition: HiiString.c:52
VOID EFIAPI HiiRemovePackages(IN EFI_HII_HANDLE HiiHandle)
Definition: HiiLib.c:253
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdSet32S(TokenName, Value)
Definition: PcdLib.h:497
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
VOID EFIAPI EfiBootManagerBoot(IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption)
Definition: BmBoot.c:1846
EFI_STATUS EFIAPI EfiBootManagerFreeLoadOption(IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption)
EFI_BOOT_MANAGER_LOAD_OPTION *EFIAPI EfiBootManagerGetLoadOptions(OUT UINTN *LoadOptionCount, IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType)
VOID EFIAPI EfiBootManagerRefreshAllBootOption(VOID)
Definition: BmBoot.c:2388
EFI_STATUS EFIAPI EfiBootManagerFreeLoadOptions(IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOptions, IN UINTN LoadOptionCount)
VOID EFIAPI EfiBootManagerConnectAll(VOID)
Definition: BmConnect.c:67
EFI_STATUS EFIAPI EfiBootManagerGetBootManagerMenu(EFI_BOOT_MANAGER_LOAD_OPTION *BootOption)
Definition: BmBoot.c:2608
EFI_SYSTEM_TABLE * gST
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
#define STRING_TOKEN(t)
VOID * EFI_HII_HANDLE
UINTN EFIAPI Print(IN CONST CHAR16 *Format,...)
Definition: UefiLibPrint.c:113
@ ByProtocol
Definition: UefiSpec.h:1518
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE * Mode
EFI_SIMPLE_TEXT_OUTPUT_MODE * Mode
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * Info
EFI_HANDLE ConsoleOutHandle
Definition: UefiSpec.h:2059
EFI_SIMPLE_TEXT_INPUT_PROTOCOL * ConIn
Definition: UefiSpec.h:2053
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * ConOut
Definition: UefiSpec.h:2064