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