VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c@ 77662

最後變更 在這個檔案從77662是 77662,由 vboxsync 提交於 6 年 前

EFI: First step in UDK2018 merge. Does not build yet.

  • 屬性 svn:eol-style 設為 native
檔案大小: 34.3 KB
 
1/** @file
2 The application to show the Boot Manager Menu.
3
4Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>
5This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution. The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13**/
14
15#include "BootManagerMenu.h"
16
17EFI_HII_HANDLE gStringPackHandle;
18
19BOOLEAN mModeInitialized = FALSE;
20
21//
22// Boot video resolution and text mode.
23//
24UINT32 mBootHorizontalResolution = 0;
25UINT32 mBootVerticalResolution = 0;
26UINT32 mBootTextModeColumn = 0;
27UINT32 mBootTextModeRow = 0;
28//
29// BIOS setup video resolution and text mode.
30//
31UINT32 mSetupTextModeColumn = 0;
32UINT32 mSetupTextModeRow = 0;
33UINT32 mSetupHorizontalResolution = 0;
34UINT32 mSetupVerticalResolution = 0;
35
36/**
37 Prints a unicode string to the default console, at
38 the supplied cursor position, using L"%s" format.
39
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.
43
44 @return Length of string printed to the console
45
46**/
47UINTN
48PrintStringAt (
49 IN UINTN Column,
50 IN UINTN Row,
51 IN CHAR16 *String
52 )
53{
54
55 gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
56 return Print (L"%s", String);
57}
58
59/**
60 Prints a character to the default console, at
61 the supplied cursor position, using L"%c" format.
62
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.
66
67 @return Length of string printed to the console.
68
69**/
70UINTN
71PrintCharAt (
72 IN UINTN Column,
73 IN UINTN Row,
74 CHAR16 Character
75 )
76{
77 gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
78 return Print (L"%c", Character);
79}
80
81/**
82 Count the storage space of a Unicode string which uses current language to get
83 from input string ID.
84
85 @param StringId The input string to be counted.
86
87 @return Storage space for the input string.
88
89**/
90UINTN
91GetLineWidth (
92 IN EFI_STRING_ID StringId
93 )
94{
95 UINTN Index;
96 UINTN IncrementValue;
97 EFI_STRING String;
98 UINTN LineWidth;
99
100 LineWidth = 0;
101 String = HiiGetString (gStringPackHandle, StringId, NULL);
102
103 if (String != NULL) {
104 Index = 0;
105 IncrementValue = 1;
106
107 do {
108 //
109 // Advance to the null-terminator or to the first width directive
110 //
111 for (;
112 (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);
113 Index++, LineWidth = LineWidth + IncrementValue
114 )
115 ;
116
117 //
118 // We hit the null-terminator, we now have a count
119 //
120 if (String[Index] == 0) {
121 break;
122 }
123 //
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)
126 //
127 if (String[Index] == NARROW_CHAR) {
128 //
129 // Skip to the next character
130 //
131 Index++;
132 IncrementValue = 1;
133 } else {
134 //
135 // Skip to the next character
136 //
137 Index++;
138 IncrementValue = 2;
139 }
140 } while (String[Index] != 0);
141 FreePool (String);
142 }
143
144 return LineWidth;
145}
146
147/**
148 This function uses calculate the boot menu location, size and scroll bar information.
149
150 @param BootMenuData The boot menu data to be processed.
151
152 @return EFI_SUCCESS calculate boot menu information successful.
153 @retval EFI_INVALID_PARAMETER Input parameter is invalid
154
155**/
156EFI_STATUS
157InitializeBootMenuScreen (
158 IN OUT BOOT_MENU_POPUP_DATA *BootMenuData
159 )
160{
161 UINTN MaxStrWidth;
162 UINTN StrWidth;
163 UINTN Index;
164 UINTN Column;
165 UINTN Row;
166 UINTN MaxPrintRows;
167 UINTN UnSelectableItmes;
168
169 if (BootMenuData == NULL) {
170 return EFI_INVALID_PARAMETER;
171 }
172 //
173 // Get maximum string width
174 //
175 MaxStrWidth = 0;
176 for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++) {
177 StrWidth = GetLineWidth (BootMenuData->TitleToken[Index]);
178 MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth;
179 }
180
181 for (Index = 0; Index < BootMenuData->ItemCount; Index++) {
182 StrWidth = GetLineWidth (BootMenuData->PtrTokens[Index]);
183 MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth;
184 }
185
186 for (Index = 0; Index < HELP_TOKEN_COUNT; Index++) {
187 StrWidth = GetLineWidth (BootMenuData->HelpToken[Index]);
188 MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth;
189 }
190 //
191 // query current row and column to calculate boot menu location
192 //
193 gST->ConOut->QueryMode (
194 gST->ConOut,
195 gST->ConOut->Mode->Mode,
196 &Column,
197 &Row
198 );
199
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;
209 } else {
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;
215 }
216 BootMenuData->MenuScreen.StartCol = (Column - BootMenuData->MenuScreen.Width) / 2;
217 BootMenuData->MenuScreen.StartRow = (Row - BootMenuData->MenuScreen.Height) / 2;
218
219 return EFI_SUCCESS;
220}
221/**
222 This function uses check boot option is wheher setup application or no
223
224 @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
225
226 @retval TRUE This boot option is setup application.
227 @retval FALSE This boot options isn't setup application
228
229**/
230BOOLEAN
231IsBootManagerMenu (
232 IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
233 )
234{
235 EFI_STATUS Status;
236 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
237
238 Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
239 if (!EFI_ERROR (Status)) {
240 EfiBootManagerFreeLoadOption (&BootManagerMenu);
241 }
242
243 return (BOOLEAN) (!EFI_ERROR (Status) && (BootOption->OptionNumber == BootManagerMenu.OptionNumber));
244}
245
246/**
247 Return whether to ignore the boot option.
248
249 @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION to check.
250
251 @retval TRUE Ignore the boot option.
252 @retval FALSE Do not ignore the boot option.
253**/
254BOOLEAN
255IgnoreBootOption (
256 IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
257 )
258{
259 EFI_STATUS Status;
260 EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
261
262 //
263 // Ignore myself.
264 //
265 Status = gBS->HandleProtocol (gImageHandle, &gEfiLoadedImageDevicePathProtocolGuid, (VOID **) &ImageDevicePath);
266 ASSERT_EFI_ERROR (Status);
267 if (CompareMem (BootOption->FilePath, ImageDevicePath, GetDevicePathSize (ImageDevicePath)) == 0) {
268 return TRUE;
269 }
270
271 //
272 // Do not ignore Boot Manager Menu.
273 //
274 if (IsBootManagerMenu (BootOption)) {
275 return FALSE;
276 }
277
278 //
279 // Ignore the hidden/inactive boot option.
280 //
281 if (((BootOption->Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption->Attributes & LOAD_OPTION_ACTIVE) == 0)) {
282 return TRUE;
283 }
284
285 return FALSE;
286}
287
288/**
289 This function uses to initialize boot menu data
290
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.
294
295 @retval EFI_SUCCESS Initialize boot menu data successful.
296 @retval EFI_INVALID_PARAMETER Input parameter is invalid.
297
298**/
299EFI_STATUS
300InitializeBootMenuData (
301 IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption,
302 IN UINTN BootOptionCount,
303 OUT BOOT_MENU_POPUP_DATA *BootMenuData
304 )
305{
306 UINTN Index;
307 UINTN StrIndex;
308
309 if (BootOption == NULL || BootMenuData == NULL) {
310 return EFI_INVALID_PARAMETER;
311 }
312
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);
316
317 //
318 // Skip boot option which created by BootNext Variable
319 //
320 for (StrIndex = 0, Index = 0; Index < BootOptionCount; Index++) {
321 if (IgnoreBootOption (&BootOption[Index])) {
322 continue;
323 }
324
325 ASSERT (BootOption[Index].Description != NULL);
326 BootMenuData->PtrTokens[StrIndex++] = HiiSetString (
327 gStringPackHandle,
328 0,
329 BootOption[Index].Description,
330 NULL
331 );
332 }
333
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;
340 return EFI_SUCCESS;
341}
342
343/**
344 This function uses input select item to highlight selected item
345 and set current selected item in BootMenuData
346
347 @param WantSelectItem The user wants to select item.
348 @param BootMenuData The boot menu data to be processed
349
350 @return EFI_SUCCESS Highlight selected item and update current selected
351 item successful
352 @retval EFI_INVALID_PARAMETER Input parameter is invalid
353**/
354EFI_STATUS
355BootMenuSelectItem (
356 IN UINTN WantSelectItem,
357 IN OUT BOOT_MENU_POPUP_DATA *BootMenuData
358 )
359{
360 INT32 SavedAttribute;
361 EFI_STRING String;
362 UINTN StartCol;
363 UINTN StartRow;
364 UINTN PrintCol;
365 UINTN PrintRow;
366 UINTN TopShadeNum;
367 UINTN LowShadeNum;
368 UINTN FirstItem;
369 UINTN LastItem;
370 UINTN ItemCountPerScreen;
371 UINTN Index;
372 BOOLEAN RePaintItems;
373
374 if (BootMenuData == NULL || WantSelectItem >= BootMenuData->ItemCount) {
375 return EFI_INVALID_PARAMETER;
376 }
377 ASSERT (BootMenuData->ItemCount != 0);
378 SavedAttribute = gST->ConOut->Mode->Attribute;
379 RePaintItems = FALSE;
380 StartCol = BootMenuData->MenuScreen.StartCol;
381 StartRow = BootMenuData->MenuScreen.StartRow;
382 //
383 // print selectable items again and adjust scroll bar if need
384 //
385 if (BootMenuData->ScrollBarControl.HasScrollBar &&
386 (WantSelectItem < BootMenuData->ScrollBarControl.FirstItem ||
387 WantSelectItem > BootMenuData->ScrollBarControl.LastItem ||
388 WantSelectItem == BootMenuData->SelectItem)) {
389 ItemCountPerScreen = BootMenuData->ScrollBarControl.ItemCountPerScreen;
390 //
391 // Set first item and last item
392 //
393 if (WantSelectItem < BootMenuData->ScrollBarControl.FirstItem) {
394 BootMenuData->ScrollBarControl.FirstItem = WantSelectItem;
395 BootMenuData->ScrollBarControl.LastItem = WantSelectItem + ItemCountPerScreen - 1;
396 } else if (WantSelectItem > BootMenuData->ScrollBarControl.LastItem) {
397 BootMenuData->ScrollBarControl.FirstItem = WantSelectItem - ItemCountPerScreen + 1;
398 BootMenuData->ScrollBarControl.LastItem = WantSelectItem;
399 }
400 gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);
401 FirstItem = BootMenuData->ScrollBarControl.FirstItem;
402 LastItem = BootMenuData->ScrollBarControl.LastItem;
403 TopShadeNum = 0;
404 if (FirstItem != 0) {
405 TopShadeNum = (FirstItem * ItemCountPerScreen) / BootMenuData->ItemCount;
406 if ((FirstItem * ItemCountPerScreen) % BootMenuData->ItemCount != 0) {
407 TopShadeNum++;
408 }
409 PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;
410 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;
411 for (Index = 0; Index < TopShadeNum; Index++, PrintRow++) {
412 PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_LIGHT_SHADE);
413 }
414 }
415 LowShadeNum = 0;
416 if (LastItem != BootMenuData->ItemCount - 1) {
417 LowShadeNum = ((BootMenuData->ItemCount - 1 - LastItem) * ItemCountPerScreen) / BootMenuData->ItemCount;
418 if (((BootMenuData->ItemCount - 1 - LastItem) * ItemCountPerScreen) % BootMenuData->ItemCount != 0) {
419 LowShadeNum++;
420 }
421 PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;
422 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + ItemCountPerScreen - LowShadeNum;
423 for (Index = 0; Index < LowShadeNum; Index++, PrintRow++) {
424 PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_LIGHT_SHADE);
425 }
426 }
427 PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;
428 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + TopShadeNum;
429 for (Index = TopShadeNum; Index < ItemCountPerScreen - LowShadeNum; Index++, PrintRow++) {
430 PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_FULL_BLOCK);
431 }
432
433
434 //
435 // Clear selectable items first
436 //
437 PrintCol = StartCol + 1;
438 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;
439 String = AllocateZeroPool ((BootMenuData->MenuScreen.Width - 2) * sizeof (CHAR16));
440 ASSERT (String != NULL);
441 for (Index = 0; Index < BootMenuData->MenuScreen.Width - 3; Index++) {
442 String[Index] = 0x20;
443 }
444 for (Index = 0; Index < ItemCountPerScreen; Index++) {
445 PrintStringAt (PrintCol, PrintRow + Index, String);
446 }
447 FreePool (String);
448 //
449 // print selectable items
450 //
451 for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) {
452 String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index + FirstItem], NULL);
453 PrintStringAt (PrintCol, PrintRow, String);
454 FreePool (String);
455 }
456 RePaintItems = TRUE;
457 }
458
459 //
460 // Print want to select item
461 //
462 FirstItem = BootMenuData->ScrollBarControl.FirstItem;
463 gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLACK);
464 String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[WantSelectItem], NULL);
465 PrintCol = StartCol + 1;
466 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + WantSelectItem - FirstItem;
467 PrintStringAt (PrintCol, PrintRow, String);
468 FreePool (String);
469
470 //
471 // if Want Select and selected item isn't the same and doesn't re-draw selectable
472 // items, clear select item
473 //
474 if (WantSelectItem != BootMenuData->SelectItem && !RePaintItems) {
475 gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);
476 String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[BootMenuData->SelectItem], NULL);
477 PrintCol = StartCol + 1;
478 PrintRow = StartRow + 3 + BootMenuData->SelectItem - FirstItem;
479 PrintStringAt (PrintCol, PrintRow, String);
480 FreePool (String);
481 }
482
483 gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
484 BootMenuData->SelectItem = WantSelectItem;
485 return EFI_SUCCESS;
486}
487
488/**
489 This function uses to draw boot popup menu
490
491 @param BootMenuData The Input BootMenuData to be processed.
492
493 @retval EFI_SUCCESS Draw boot popup menu successful.
494
495**/
496EFI_STATUS
497DrawBootPopupMenu (
498 IN BOOT_MENU_POPUP_DATA *BootMenuData
499 )
500{
501 EFI_STRING String;
502 UINTN Index;
503 UINTN Width;
504 UINTN StartCol;
505 UINTN StartRow;
506 UINTN PrintRow;
507 UINTN PrintCol;
508 UINTN LineWidth;
509 INT32 SavedAttribute;
510 UINTN ItemCountPerScreen;
511
512 gST->ConOut->ClearScreen (gST->ConOut);
513
514 SavedAttribute = gST->ConOut->Mode->Attribute;
515 gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);
516 Width = BootMenuData->MenuScreen.Width;
517 StartCol = BootMenuData->MenuScreen.StartCol;
518 StartRow = BootMenuData->MenuScreen.StartRow;
519 ItemCountPerScreen = BootMenuData->ScrollBarControl.ItemCountPerScreen;
520 PrintRow = StartRow;
521
522 gST->ConOut->EnableCursor (gST->ConOut, FALSE);
523 //
524 // Draw Boot popup menu screen
525 //
526 PrintCharAt (StartCol, PrintRow, BOXDRAW_DOWN_RIGHT);
527 for (Index = 1; Index < Width - 1; Index++) {
528 PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL);
529 }
530 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_DOWN_LEFT);
531
532 //
533 // Draw the screen for title
534 //
535 String = AllocateZeroPool ((Width - 1) * sizeof (CHAR16));
536 ASSERT (String != NULL);
537 for (Index = 0; Index < Width - 2; Index++) {
538 String[Index] = 0x20;
539 }
540
541 for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++) {
542 PrintRow++;
543 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);
544 PrintStringAt (StartCol + 1, PrintRow, String);
545 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);
546 }
547
548 PrintRow++;
549 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL_RIGHT);
550 for (Index = 1; Index < Width - 1; Index++) {
551 PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL);
552 }
553 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL_LEFT);
554
555 //
556 // Draw screen for selectable items
557 //
558 for (Index = 0; Index < ItemCountPerScreen; Index++) {
559 PrintRow++;
560 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);
561 PrintStringAt (StartCol + 1, PrintRow, String);
562 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);
563 }
564
565 PrintRow++;
566 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL_RIGHT);
567 for (Index = 1; Index < Width - 1; Index++) {
568 PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL);
569 }
570 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL_LEFT);
571
572 //
573 // Draw screen for Help
574 //
575 for (Index = 0; Index < HELP_TOKEN_COUNT; Index++) {
576 PrintRow++;
577 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);
578 PrintStringAt (StartCol + 1, PrintRow, String);
579 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);
580 }
581 FreePool (String);
582
583 PrintRow++;
584 PrintCharAt (StartCol, PrintRow, BOXDRAW_UP_RIGHT);
585 for (Index = 1; Index < Width - 1; Index++) {
586 PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL);
587 }
588 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_UP_LEFT);
589
590
591 //
592 // print title strings
593 //
594 PrintRow = StartRow + 1;
595 for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++, PrintRow++) {
596 String = HiiGetString (gStringPackHandle, BootMenuData->TitleToken[Index], NULL);
597 LineWidth = GetLineWidth (BootMenuData->TitleToken[Index]);
598 PrintCol = StartCol + (Width - LineWidth) / 2;
599 PrintStringAt (PrintCol, PrintRow, String);
600 FreePool (String);
601 }
602
603 //
604 // print selectable items
605 //
606 PrintCol = StartCol + 1;
607 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;
608 for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) {
609 String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index], NULL);
610 PrintStringAt (PrintCol, PrintRow, String);
611 FreePool (String);
612 }
613
614 //
615 // Print Help strings
616 //
617 PrintRow++;
618 for (Index = 0; Index < HELP_TOKEN_COUNT; Index++, PrintRow++) {
619 String = HiiGetString (gStringPackHandle, BootMenuData->HelpToken[Index], NULL);
620 LineWidth = GetLineWidth (BootMenuData->HelpToken[Index]);
621 PrintCol = StartCol + (Width - LineWidth) / 2;
622 PrintStringAt (PrintCol, PrintRow, String);
623 FreePool (String);
624 }
625
626 //
627 // Print scroll bar if has scroll bar
628 //
629 if (BootMenuData->ScrollBarControl.HasScrollBar) {
630 PrintCol = StartCol + Width - 2;
631 PrintRow = StartRow + 2;
632 PrintCharAt (PrintCol, PrintRow, GEOMETRICSHAPE_UP_TRIANGLE);
633 PrintCharAt (PrintCol + 1, PrintRow, BOXDRAW_VERTICAL);
634 PrintRow += (ItemCountPerScreen + 1);
635 PrintCharAt (PrintCol, PrintRow, GEOMETRICSHAPE_DOWN_TRIANGLE);
636 PrintCharAt (PrintCol + 1, PrintRow, BOXDRAW_VERTICAL);
637 }
638
639 gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
640 //
641 // Print Selected item
642 //
643 BootMenuSelectItem (BootMenuData->SelectItem, BootMenuData);
644 return EFI_SUCCESS;
645}
646
647/**
648 This function uses to boot from selected item
649
650 @param BootOptions Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
651 @param BootOptionCount Number of boot option.
652 @param SelectItem Current selected item.
653**/
654VOID
655BootFromSelectOption (
656 IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions,
657 IN UINTN BootOptionCount,
658 IN UINTN SelectItem
659 )
660{
661 UINTN ItemNum;
662 UINTN Index;
663
664 ASSERT (BootOptions != NULL);
665
666 for (ItemNum = 0, Index = 0; Index < BootOptionCount; Index++) {
667 if (IgnoreBootOption (&BootOptions[Index])) {
668 continue;
669 }
670
671 if (ItemNum++ == SelectItem) {
672 EfiBootManagerBoot (&BootOptions[Index]);
673 break;
674 }
675 }
676}
677
678/**
679 This function will change video resolution and text mode
680 according to defined setup mode or defined boot mode
681
682 @param IsSetupMode Indicate mode is changed to setup mode or boot mode.
683
684 @retval EFI_SUCCESS Mode is changed successfully.
685 @retval Others Mode failed to be changed.
686
687**/
688EFI_STATUS
689EFIAPI
690BdsSetConsoleMode (
691 BOOLEAN IsSetupMode
692 )
693{
694 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
695 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
696 UINTN SizeOfInfo;
697 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
698 UINT32 MaxGopMode;
699 UINT32 MaxTextMode;
700 UINT32 ModeNumber;
701 UINT32 NewHorizontalResolution;
702 UINT32 NewVerticalResolution;
703 UINT32 NewColumns;
704 UINT32 NewRows;
705 UINTN HandleCount;
706 EFI_HANDLE *HandleBuffer;
707 EFI_STATUS Status;
708 UINTN Index;
709 UINTN CurrentColumn;
710 UINTN CurrentRow;
711
712 MaxGopMode = 0;
713 MaxTextMode = 0;
714
715 //
716 // Get current video resolution and text mode
717 //
718 Status = gBS->HandleProtocol (
719 gST->ConsoleOutHandle,
720 &gEfiGraphicsOutputProtocolGuid,
721 (VOID**)&GraphicsOutput
722 );
723 if (EFI_ERROR (Status)) {
724 GraphicsOutput = NULL;
725 }
726
727 Status = gBS->HandleProtocol (
728 gST->ConsoleOutHandle,
729 &gEfiSimpleTextOutProtocolGuid,
730 (VOID**)&SimpleTextOut
731 );
732 if (EFI_ERROR (Status)) {
733 SimpleTextOut = NULL;
734 }
735
736 if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {
737 return EFI_UNSUPPORTED;
738 }
739
740 if (IsSetupMode) {
741 //
742 // The required resolution and text mode is setup mode.
743 //
744 NewHorizontalResolution = mSetupHorizontalResolution;
745 NewVerticalResolution = mSetupVerticalResolution;
746 NewColumns = mSetupTextModeColumn;
747 NewRows = mSetupTextModeRow;
748 } else {
749 //
750 // The required resolution and text mode is boot mode.
751 //
752 NewHorizontalResolution = mBootHorizontalResolution;
753 NewVerticalResolution = mBootVerticalResolution;
754 NewColumns = mBootTextModeColumn;
755 NewRows = mBootTextModeRow;
756 }
757
758 if (GraphicsOutput != NULL) {
759 MaxGopMode = GraphicsOutput->Mode->MaxMode;
760 }
761
762 if (SimpleTextOut != NULL) {
763 MaxTextMode = SimpleTextOut->Mode->MaxMode;
764 }
765
766 //
767 // 1. If current video resolution is same with required video resolution,
768 // video resolution need not be changed.
769 // 1.1. If current text mode is same with required text mode, text mode need not be changed.
770 // 1.2. If current text mode is different from required text mode, text mode need be changed.
771 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.
772 //
773 for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {
774 Status = GraphicsOutput->QueryMode (
775 GraphicsOutput,
776 ModeNumber,
777 &SizeOfInfo,
778 &Info
779 );
780 if (!EFI_ERROR (Status)) {
781 if ((Info->HorizontalResolution == NewHorizontalResolution) &&
782 (Info->VerticalResolution == NewVerticalResolution)) {
783 if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) &&
784 (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) {
785 //
786 // Current resolution is same with required resolution, check if text mode need be set
787 //
788 Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);
789 ASSERT_EFI_ERROR (Status);
790 if (CurrentColumn == NewColumns && CurrentRow == NewRows) {
791 //
792 // If current text mode is same with required text mode. Do nothing
793 //
794 FreePool (Info);
795 return EFI_SUCCESS;
796 } else {
797 //
798 // If current text mode is different from required text mode. Set new video mode
799 //
800 for (Index = 0; Index < MaxTextMode; Index++) {
801 Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);
802 if (!EFI_ERROR(Status)) {
803 if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) {
804 //
805 // Required text mode is supported, set it.
806 //
807 Status = SimpleTextOut->SetMode (SimpleTextOut, Index);
808 ASSERT_EFI_ERROR (Status);
809 //
810 // Update text mode PCD.
811 //
812 Status = PcdSet32S (PcdConOutColumn, mSetupTextModeColumn);
813 ASSERT_EFI_ERROR (Status);
814 Status = PcdSet32S (PcdConOutRow, mSetupTextModeRow);
815 ASSERT_EFI_ERROR (Status);
816 FreePool (Info);
817 return EFI_SUCCESS;
818 }
819 }
820 }
821 if (Index == MaxTextMode) {
822 //
823 // If required text mode is not supported, return error.
824 //
825 FreePool (Info);
826 return EFI_UNSUPPORTED;
827 }
828 }
829 } else {
830 //
831 // If current video resolution is not same with the new one, set new video resolution.
832 // In this case, the driver which produces simple text out need be restarted.
833 //
834 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
835 if (!EFI_ERROR (Status)) {
836 FreePool (Info);
837 break;
838 }
839 }
840 }
841 FreePool (Info);
842 }
843 }
844
845 if (ModeNumber == MaxGopMode) {
846 //
847 // If the resolution is not supported, return error.
848 //
849 return EFI_UNSUPPORTED;
850 }
851
852 //
853 // Set PCD to Inform GraphicsConsole to change video resolution.
854 // Set PCD to Inform Consplitter to change text mode.
855 //
856 Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution);
857 ASSERT_EFI_ERROR (Status);
858 Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution);
859 ASSERT_EFI_ERROR (Status);
860 Status = PcdSet32S (PcdConOutColumn, NewColumns);
861 ASSERT_EFI_ERROR (Status);
862 Status = PcdSet32S (PcdConOutRow, NewRows);
863 ASSERT_EFI_ERROR (Status);
864
865 //
866 // Video mode is changed, so restart graphics console driver and higher level driver.
867 // Reconnect graphics console driver and higher level driver.
868 // Locate all the handles with GOP protocol and reconnect it.
869 //
870 Status = gBS->LocateHandleBuffer (
871 ByProtocol,
872 &gEfiSimpleTextOutProtocolGuid,
873 NULL,
874 &HandleCount,
875 &HandleBuffer
876 );
877 if (!EFI_ERROR (Status)) {
878 for (Index = 0; Index < HandleCount; Index++) {
879 gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
880 }
881 for (Index = 0; Index < HandleCount; Index++) {
882 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
883 }
884 if (HandleBuffer != NULL) {
885 FreePool (HandleBuffer);
886 }
887 }
888
889 return EFI_SUCCESS;
890}
891
892/**
893 Display the boot popup menu and allow user select boot item.
894
895 @param ImageHandle The image handle.
896 @param SystemTable The system table.
897
898 @retval EFI_SUCCESS Boot from selected boot option, and return success from boot option
899 @retval EFI_NOT_FOUND User select to enter setup or can not find boot option
900
901**/
902EFI_STATUS
903EFIAPI
904BootManagerMenuEntry (
905 IN EFI_HANDLE ImageHandle,
906 IN EFI_SYSTEM_TABLE *SystemTable
907 )
908{
909 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;
910 UINTN BootOptionCount;
911 EFI_STATUS Status;
912 BOOT_MENU_POPUP_DATA BootMenuData;
913 UINTN Index;
914 EFI_INPUT_KEY Key;
915 BOOLEAN ExitApplication;
916 UINTN SelectItem;
917 EFI_BOOT_LOGO_PROTOCOL *BootLogo;
918 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
919 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
920 UINTN BootTextColumn;
921 UINTN BootTextRow;
922
923 //
924 // Set Logo status invalid when boot manager menu is launched
925 //
926 BootLogo = NULL;
927 Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);
928 if (!EFI_ERROR (Status) && (BootLogo != NULL)) {
929 Status = BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);
930 ASSERT_EFI_ERROR (Status);
931 }
932
933 gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
934
935 gStringPackHandle = HiiAddPackages (
936 &gEfiCallerIdGuid,
937 gImageHandle,
938 BootManagerMenuAppStrings,
939 NULL
940 );
941 ASSERT (gStringPackHandle != NULL);
942
943 //
944 // Connect all prior to entering the platform setup menu.
945 //
946 EfiBootManagerConnectAll ();
947 EfiBootManagerRefreshAllBootOption ();
948
949 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
950
951 if (!mModeInitialized) {
952 //
953 // After the console is ready, get current video resolution
954 // and text mode before launching setup at first time.
955 //
956 Status = gBS->HandleProtocol (
957 gST->ConsoleOutHandle,
958 &gEfiGraphicsOutputProtocolGuid,
959 (VOID**)&GraphicsOutput
960 );
961 if (EFI_ERROR (Status)) {
962 GraphicsOutput = NULL;
963 }
964
965 Status = gBS->HandleProtocol (
966 gST->ConsoleOutHandle,
967 &gEfiSimpleTextOutProtocolGuid,
968 (VOID**)&SimpleTextOut
969 );
970 if (EFI_ERROR (Status)) {
971 SimpleTextOut = NULL;
972 }
973
974 if (GraphicsOutput != NULL) {
975 //
976 // Get current video resolution and text mode.
977 //
978 mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
979 mBootVerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;
980 }
981
982 if (SimpleTextOut != NULL) {
983 Status = SimpleTextOut->QueryMode (
984 SimpleTextOut,
985 SimpleTextOut->Mode->Mode,
986 &BootTextColumn,
987 &BootTextRow
988 );
989 mBootTextModeColumn = (UINT32)BootTextColumn;
990 mBootTextModeRow = (UINT32)BootTextRow;
991 }
992
993 //
994 // Get user defined text mode for setup.
995 //
996 mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
997 mSetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution);
998 mSetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn);
999 mSetupTextModeRow = PcdGet32 (PcdSetupConOutRow);
1000 mModeInitialized = TRUE;
1001 }
1002
1003 //
1004 // Set back to conventional setup resolution
1005 //
1006 BdsSetConsoleMode (TRUE);
1007
1008 //
1009 // Initialize Boot menu data
1010 //
1011 Status = InitializeBootMenuData (BootOption, BootOptionCount, &BootMenuData);
1012 //
1013 // According to boot menu data to draw boot popup menu
1014 //
1015 DrawBootPopupMenu (&BootMenuData);
1016
1017 //
1018 // check user input to determine want to re-draw or boot from user selected item
1019 //
1020 ExitApplication = FALSE;
1021 while (!ExitApplication) {
1022 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);
1023 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
1024 if (!EFI_ERROR (Status)) {
1025 switch (Key.UnicodeChar) {
1026
1027 case CHAR_NULL:
1028 switch (Key.ScanCode) {
1029
1030 case SCAN_UP:
1031 SelectItem = BootMenuData.SelectItem == 0 ? BootMenuData.ItemCount - 1 : BootMenuData.SelectItem - 1;
1032 BootMenuSelectItem (SelectItem, &BootMenuData);
1033 break;
1034
1035 case SCAN_DOWN:
1036 SelectItem = BootMenuData.SelectItem == BootMenuData.ItemCount - 1 ? 0 : BootMenuData.SelectItem + 1;
1037 BootMenuSelectItem (SelectItem, &BootMenuData);
1038 break;
1039
1040 case SCAN_ESC:
1041 gST->ConOut->ClearScreen (gST->ConOut);
1042 ExitApplication = TRUE;
1043 //
1044 // Set boot resolution for normal boot
1045 //
1046 BdsSetConsoleMode (FALSE);
1047 break;
1048
1049 default:
1050 break;
1051 }
1052 break;
1053
1054 case CHAR_CARRIAGE_RETURN:
1055 gST->ConOut->ClearScreen (gST->ConOut);
1056 //
1057 // Set boot resolution for normal boot
1058 //
1059 BdsSetConsoleMode (FALSE);
1060 BootFromSelectOption (BootOption, BootOptionCount, BootMenuData.SelectItem);
1061 //
1062 // Back to boot manager menu again, set back to setup resolution
1063 //
1064 BdsSetConsoleMode (TRUE);
1065 DrawBootPopupMenu (&BootMenuData);
1066 break;
1067
1068 default:
1069 break;
1070 }
1071 }
1072 }
1073 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
1074 FreePool (BootMenuData.PtrTokens);
1075
1076 HiiRemovePackages (gStringPackHandle);
1077
1078 return Status;
1079
1080}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette