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