]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c
MdePkg: Add a new DxeServicesLib GetFileDevicePathFromAnyFv () function
[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
245 \r
246\r
247/**\r
248 This funciton uses to initialize boot menu data\r
249\r
250 @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.\r
251 @param BootOptionCount Number of boot option.\r
252 @param BootMenuData The Input BootMenuData to be initialized.\r
253 \r
254 @retval EFI_SUCCESS Initialize boot menu data successful.\r
255 @retval EFI_INVALID_PARAMETER Input parameter is invalid. \r
256\r
257**/\r
258EFI_STATUS\r
259InitializeBootMenuData (\r
260 IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption,\r
261 IN UINTN BootOptionCount,\r
262 OUT BOOT_MENU_POPUP_DATA *BootMenuData\r
263 )\r
264{\r
265 UINTN Index;\r
266 UINTN StrIndex;\r
267 \r
268 if (BootOption == NULL || BootMenuData == NULL) {\r
269 return EFI_INVALID_PARAMETER;\r
270 } \r
271 \r
272 BootMenuData->TitleToken[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_TITLE_STRING);\r
273 BootMenuData->PtrTokens = AllocateZeroPool (BootOptionCount * sizeof (EFI_STRING_ID));\r
274 ASSERT (BootMenuData->PtrTokens != NULL);\r
275\r
276 //\r
277 // Skip boot option which created by BootNext Variable\r
278 //\r
279 for (StrIndex = 0, Index = 0; Index < BootOptionCount; Index++) {\r
280 //\r
281 // Don't display the hidden/inactive boot option except setup application.\r
282 //\r
283 if ((((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) &&\r
284 !IsBootManagerMenu (&BootOption[Index])) { \r
285 continue;\r
286 }\r
287 ASSERT (BootOption[Index].Description != NULL);\r
288 BootMenuData->PtrTokens[StrIndex++] = HiiSetString (\r
289 gStringPackHandle, \r
290 0,\r
291 BootOption[Index].Description,\r
292 NULL\r
293 );\r
294 }\r
295\r
296 BootMenuData->ItemCount = StrIndex; \r
297 BootMenuData->HelpToken[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP1_STRING);\r
298 BootMenuData->HelpToken[1] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP2_STRING);\r
299 BootMenuData->HelpToken[2] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP3_STRING);\r
300 InitializeBootMenuScreen (BootMenuData);\r
301 BootMenuData->SelectItem = 0;\r
302 return EFI_SUCCESS;\r
303} \r
304\r
305/**\r
306 This function uses input select item to highlight selected item\r
307 and set current selected item in BootMenuData\r
308\r
309 @param WantSelectItem The user wants to select item.\r
310 @param BootMenuData The boot menu data to be proccessed\r
311\r
312 @return EFI_SUCCESS Highlight selected item and update current selected \r
313 item successful \r
314 @retval EFI_INVALID_PARAMETER Input parameter is invalid \r
315**/\r
316EFI_STATUS\r
317BootMenuSelectItem (\r
318 IN UINTN WantSelectItem,\r
319 IN OUT BOOT_MENU_POPUP_DATA *BootMenuData\r
320 )\r
321{\r
322 INT32 SavedAttribute;\r
323 EFI_STRING String;\r
324 UINTN StartCol; \r
325 UINTN StartRow;\r
326 UINTN PrintCol;\r
327 UINTN PrintRow;\r
328 UINTN TopShadeNum;\r
329 UINTN LowShadeNum;\r
330 UINTN FirstItem;\r
331 UINTN LastItem;\r
332 UINTN ItemCountPerScreen;\r
333 UINTN Index;\r
334 BOOLEAN RePaintItems;\r
335 \r
336 if (BootMenuData == NULL || WantSelectItem >= BootMenuData->ItemCount) {\r
337 return EFI_INVALID_PARAMETER;\r
338 }\r
339 SavedAttribute = gST->ConOut->Mode->Attribute;\r
340 RePaintItems = FALSE;\r
341 StartCol = BootMenuData->MenuScreen.StartCol;\r
342 StartRow = BootMenuData->MenuScreen.StartRow;\r
343 //\r
344 // print selectable items again and adjust scroll bar if need\r
345 // \r
346 if (BootMenuData->ScrollBarControl.HasScrollBar &&\r
347 (WantSelectItem < BootMenuData->ScrollBarControl.FirstItem ||\r
348 WantSelectItem > BootMenuData->ScrollBarControl.LastItem ||\r
349 WantSelectItem == BootMenuData->SelectItem)) { \r
350 ItemCountPerScreen = BootMenuData->ScrollBarControl.ItemCountPerScreen;\r
351 //\r
352 // Set first item and last item\r
353 // \r
354 if (WantSelectItem < BootMenuData->ScrollBarControl.FirstItem) {\r
355 BootMenuData->ScrollBarControl.FirstItem = WantSelectItem;\r
356 BootMenuData->ScrollBarControl.LastItem = WantSelectItem + ItemCountPerScreen - 1; \r
357 } else if (WantSelectItem > BootMenuData->ScrollBarControl.LastItem) {\r
358 BootMenuData->ScrollBarControl.FirstItem = WantSelectItem - ItemCountPerScreen + 1; \r
359 BootMenuData->ScrollBarControl.LastItem = WantSelectItem;\r
360 }\r
361 gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);\r
362 FirstItem = BootMenuData->ScrollBarControl.FirstItem;\r
363 LastItem = BootMenuData->ScrollBarControl.LastItem;\r
364 TopShadeNum = 0;\r
365 if (FirstItem != 0) {\r
366 TopShadeNum = (FirstItem * ItemCountPerScreen) / BootMenuData->ItemCount;\r
367 if ((FirstItem * ItemCountPerScreen) % BootMenuData->ItemCount != 0) {\r
368 TopShadeNum++;\r
369 }\r
370 PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;\r
371 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2; \r
372 for (Index = 0; Index < TopShadeNum; Index++, PrintRow++) {\r
373 PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_LIGHT_SHADE);\r
374 }\r
375 }\r
376 LowShadeNum = 0;\r
377 if (LastItem != BootMenuData->ItemCount - 1) {\r
378 LowShadeNum = ((BootMenuData->ItemCount - 1 - LastItem) * ItemCountPerScreen) / BootMenuData->ItemCount;\r
379 if (((BootMenuData->ItemCount - 1 - LastItem) * ItemCountPerScreen) % BootMenuData->ItemCount != 0) {\r
380 LowShadeNum++;\r
381 }\r
382 PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;\r
383 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + ItemCountPerScreen - LowShadeNum; \r
384 for (Index = 0; Index < LowShadeNum; Index++, PrintRow++) {\r
385 PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_LIGHT_SHADE);\r
386 } \r
387 }\r
388 PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;\r
389 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + TopShadeNum; \r
390 for (Index = TopShadeNum; Index < ItemCountPerScreen - LowShadeNum; Index++, PrintRow++) {\r
391 PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_FULL_BLOCK);\r
392 } \r
393\r
394\r
395 //\r
396 // Clear selectable items first\r
397 //\r
398 PrintCol = StartCol + 1;\r
399 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2; \r
400 String = AllocateZeroPool ((BootMenuData->MenuScreen.Width - 2) * sizeof (CHAR16));\r
401 ASSERT (String != NULL);\r
402 for (Index = 0; Index < BootMenuData->MenuScreen.Width - 3; Index++) {\r
403 String[Index] = 0x20;\r
404 } \r
405 for (Index = 0; Index < ItemCountPerScreen; Index++) { \r
406 PrintStringAt (PrintCol, PrintRow + Index, String); \r
407 }\r
408 FreePool (String);\r
409 //\r
410 // print selectable items \r
411 //\r
412 for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) {\r
413 String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index + FirstItem], NULL);\r
414 PrintStringAt (PrintCol, PrintRow, String);\r
415 FreePool (String); \r
416 }\r
417 RePaintItems = TRUE;\r
418 }\r
419 \r
420 //\r
421 // Print want to select item \r
422 //\r
423 FirstItem = BootMenuData->ScrollBarControl.FirstItem;\r
424 gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLACK);\r
425 String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[WantSelectItem], NULL);\r
426 PrintCol = StartCol + 1; \r
427 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + WantSelectItem - FirstItem; \r
428 PrintStringAt (PrintCol, PrintRow, String);\r
429 FreePool (String);\r
430 \r
431 //\r
432 // if Want Select and selected item isn't the same and doesn't re-draw selectable \r
433 // items, clear select item\r
434 //\r
435 if (WantSelectItem != BootMenuData->SelectItem && !RePaintItems) {\r
436 gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);\r
437 String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[BootMenuData->SelectItem], NULL);\r
438 PrintCol = StartCol + 1; \r
439 PrintRow = StartRow + 3 + BootMenuData->SelectItem - FirstItem; \r
440 PrintStringAt (PrintCol, PrintRow, String);\r
441 FreePool (String); \r
442 }\r
443\r
444 gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r
445 BootMenuData->SelectItem = WantSelectItem;\r
446 return EFI_SUCCESS;\r
447}\r
448\r
449/**\r
450 This funciton uses to draw boot popup menu\r
451\r
452 @param BootMenuData The Input BootMenuData to be processed.\r
453 \r
454 @retval EFI_SUCCESS Draw boot popup menu successful.\r
455\r
456**/\r
457EFI_STATUS \r
458DrawBootPopupMenu (\r
459 IN BOOT_MENU_POPUP_DATA *BootMenuData\r
460 )\r
461{\r
462 EFI_STRING String;\r
463 UINTN Index;\r
464 UINTN Width; \r
465 UINTN Height;\r
466 UINTN StartCol;\r
467 UINTN StartRow;\r
468 UINTN PrintRow;\r
469 UINTN PrintCol;\r
470 UINTN LineWidth;\r
471 INT32 SavedAttribute; \r
472 UINTN ItemCountPerScreen; \r
473\r
474 gST->ConOut->ClearScreen (gST->ConOut);\r
475 \r
476 SavedAttribute = gST->ConOut->Mode->Attribute;\r
477 gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);\r
478 Width = BootMenuData->MenuScreen.Width;\r
479 Height = BootMenuData->MenuScreen.Height;\r
480 StartCol = BootMenuData->MenuScreen.StartCol;\r
481 StartRow = BootMenuData->MenuScreen.StartRow;\r
482 ItemCountPerScreen = BootMenuData->ScrollBarControl.ItemCountPerScreen;\r
483 PrintRow = StartRow;\r
484 \r
485 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
486 //\r
487 // Draw Boot popup menu screen\r
488 //\r
489 PrintCharAt (StartCol, PrintRow, BOXDRAW_DOWN_RIGHT);\r
490 for (Index = 1; Index < Width - 1; Index++) {\r
491 PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); \r
492 }\r
493 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_DOWN_LEFT);\r
494 \r
495 //\r
496 // Draw the screen for title\r
497 //\r
498 String = AllocateZeroPool ((Width - 1) * sizeof (CHAR16));\r
499 ASSERT (String != NULL);\r
500 for (Index = 0; Index < Width - 2; Index++) {\r
501 String[Index] = 0x20;\r
502 }\r
503\r
504 for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++) {\r
505 PrintRow++;\r
506 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL); \r
507 PrintStringAt (StartCol + 1, PrintRow, String);\r
508 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);\r
509 }\r
510 \r
511 PrintRow++;\r
512 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL_RIGHT);\r
513 for (Index = 1; Index < Width - 1; Index++) {\r
514 PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); \r
515 }\r
516 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL_LEFT); \r
517 \r
518 //\r
519 // Draw screen for selectable items\r
520 //\r
521 for (Index = 0; Index < ItemCountPerScreen; Index++) {\r
522 PrintRow++;\r
523 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);\r
524 PrintStringAt (StartCol + 1, PrintRow, String);\r
525 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);\r
526 } \r
527\r
528 PrintRow++;\r
529 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL_RIGHT);\r
530 for (Index = 1; Index < Width - 1; Index++) {\r
531 PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); \r
532 }\r
533 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL_LEFT);\r
534 \r
535 //\r
536 // Draw screen for Help\r
537 //\r
538 for (Index = 0; Index < HELP_TOKEN_COUNT; Index++) {\r
539 PrintRow++;\r
540 PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);\r
541 PrintStringAt (StartCol + 1, PrintRow, String);\r
542 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);\r
543 }\r
544 FreePool (String); \r
545 \r
546 PrintRow++; \r
547 PrintCharAt (StartCol, PrintRow, BOXDRAW_UP_RIGHT);\r
548 for (Index = 1; Index < Width - 1; Index++) {\r
549 PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); \r
550 }\r
551 PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_UP_LEFT); \r
552 \r
553 \r
554 //\r
555 // print title strings\r
556 //\r
557 PrintRow = StartRow + 1;\r
558 for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++, PrintRow++) {\r
559 String = HiiGetString (gStringPackHandle, BootMenuData->TitleToken[Index], NULL);\r
560 LineWidth = GetLineWidth (BootMenuData->TitleToken[Index]); \r
561 PrintCol = StartCol + (Width - LineWidth) / 2;\r
562 PrintStringAt (PrintCol, PrintRow, String);\r
563 FreePool (String);\r
564 }\r
565 \r
566 //\r
567 // print selectable items\r
568 //\r
569 PrintCol = StartCol + 1;\r
570 PrintRow = StartRow + TITLE_TOKEN_COUNT + 2; \r
571 for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) {\r
572 String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index], NULL);\r
573 PrintStringAt (PrintCol, PrintRow, String);\r
574 FreePool (String); \r
575 }\r
576 \r
577 //\r
578 // Print Help strings\r
579 //\r
580 PrintRow++;\r
581 for (Index = 0; Index < HELP_TOKEN_COUNT; Index++, PrintRow++) {\r
582 String = HiiGetString (gStringPackHandle, BootMenuData->HelpToken[Index], NULL);\r
583 LineWidth = GetLineWidth (BootMenuData->HelpToken[Index]);\r
584 PrintCol = StartCol + (Width - LineWidth) / 2;\r
585 PrintStringAt (PrintCol, PrintRow, String);\r
586 FreePool (String);\r
587 }\r
588 \r
589 //\r
590 // Print scroll bar if has scroll bar\r
591 //\r
592 if (BootMenuData->ScrollBarControl.HasScrollBar) {\r
593 PrintCol = StartCol + Width - 2;\r
594 PrintRow = StartRow + 2; \r
595 PrintCharAt (PrintCol, PrintRow, GEOMETRICSHAPE_UP_TRIANGLE); \r
596 PrintCharAt (PrintCol + 1, PrintRow, BOXDRAW_VERTICAL); \r
597 PrintRow += (ItemCountPerScreen + 1); \r
598 PrintCharAt (PrintCol, PrintRow, GEOMETRICSHAPE_DOWN_TRIANGLE);\r
599 PrintCharAt (PrintCol + 1, PrintRow, BOXDRAW_VERTICAL); \r
600 } \r
601 \r
602 gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r
603 //\r
604 // Print Selected item\r
605 //\r
606 BootMenuSelectItem (BootMenuData->SelectItem, BootMenuData);\r
607 return EFI_SUCCESS;\r
608}\r
609\r
610/**\r
611 This funciton uses to boot from selected item \r
612\r
613 @param BootOptions Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.\r
614 @param BootOptionCount Number of boot option.\r
615 @param SelectItem Current selected item.\r
616**/\r
617VOID\r
618BootFromSelectOption (\r
619 IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions,\r
620 IN UINTN BootOptionCount, \r
621 IN UINTN SelectItem\r
622 )\r
623{\r
624 UINTN ItemNum;\r
625 UINTN Index;\r
626\r
627 ASSERT (BootOptions != NULL);\r
628\r
629 for (ItemNum = 0, Index = 0; Index < BootOptionCount; Index++) {\r
630 //\r
631 // Don't display the hidden/inactive boot option except setup application.\r
632 //\r
633 if ((((BootOptions[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOptions[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) &&\r
634 !IsBootManagerMenu (&BootOptions[Index])) { \r
635 continue;\r
636 }\r
637 if (ItemNum++ == SelectItem) {\r
638 EfiBootManagerBoot (&BootOptions[Index]);\r
639 break;\r
640 }\r
641 }\r
642}\r
643\r
644/**\r
645 This function will change video resolution and text mode\r
646 according to defined setup mode or defined boot mode \r
647\r
648 @param IsSetupMode Indicate mode is changed to setup mode or boot mode. \r
649\r
650 @retval EFI_SUCCESS Mode is changed successfully.\r
651 @retval Others Mode failed to be changed.\r
652\r
653**/\r
654EFI_STATUS\r
655EFIAPI\r
656BdsSetConsoleMode (\r
657 BOOLEAN IsSetupMode\r
658 )\r
659{\r
660 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
661 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;\r
662 UINTN SizeOfInfo;\r
663 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
664 UINT32 MaxGopMode;\r
665 UINT32 MaxTextMode;\r
666 UINT32 ModeNumber;\r
667 UINT32 NewHorizontalResolution;\r
668 UINT32 NewVerticalResolution;\r
669 UINT32 NewColumns;\r
670 UINT32 NewRows;\r
671 UINTN HandleCount;\r
672 EFI_HANDLE *HandleBuffer;\r
673 EFI_STATUS Status;\r
674 UINTN Index;\r
675 UINTN CurrentColumn;\r
676 UINTN CurrentRow; \r
677\r
678 MaxGopMode = 0;\r
679 MaxTextMode = 0;\r
680\r
681 //\r
682 // Get current video resolution and text mode \r
683 //\r
684 Status = gBS->HandleProtocol (\r
685 gST->ConsoleOutHandle,\r
686 &gEfiGraphicsOutputProtocolGuid,\r
687 (VOID**)&GraphicsOutput\r
688 );\r
689 if (EFI_ERROR (Status)) {\r
690 GraphicsOutput = NULL;\r
691 }\r
692\r
693 Status = gBS->HandleProtocol (\r
694 gST->ConsoleOutHandle,\r
695 &gEfiSimpleTextOutProtocolGuid,\r
696 (VOID**)&SimpleTextOut\r
697 );\r
698 if (EFI_ERROR (Status)) {\r
699 SimpleTextOut = NULL;\r
700 } \r
701\r
702 if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {\r
703 return EFI_UNSUPPORTED;\r
704 }\r
705\r
706 if (IsSetupMode) {\r
707 //\r
708 // The requried resolution and text mode is setup mode.\r
709 //\r
710 NewHorizontalResolution = mSetupHorizontalResolution;\r
711 NewVerticalResolution = mSetupVerticalResolution;\r
712 NewColumns = mSetupTextModeColumn;\r
713 NewRows = mSetupTextModeRow;\r
714 } else {\r
715 //\r
716 // The required resolution and text mode is boot mode.\r
717 //\r
718 NewHorizontalResolution = mBootHorizontalResolution;\r
719 NewVerticalResolution = mBootVerticalResolution;\r
720 NewColumns = mBootTextModeColumn;\r
721 NewRows = mBootTextModeRow; \r
722 }\r
723 \r
724 if (GraphicsOutput != NULL) {\r
725 MaxGopMode = GraphicsOutput->Mode->MaxMode;\r
726 } \r
727\r
728 if (SimpleTextOut != NULL) {\r
729 MaxTextMode = SimpleTextOut->Mode->MaxMode;\r
730 }\r
731\r
732 //\r
733 // 1. If current video resolution is same with required video resolution,\r
734 // video resolution need not be changed.\r
735 // 1.1. If current text mode is same with required text mode, text mode need not be changed.\r
736 // 1.2. If current text mode is different from required text mode, text mode need be changed.\r
737 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.\r
738 //\r
739 for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {\r
740 Status = GraphicsOutput->QueryMode (\r
741 GraphicsOutput,\r
742 ModeNumber,\r
743 &SizeOfInfo,\r
744 &Info\r
745 );\r
746 if (!EFI_ERROR (Status)) {\r
747 if ((Info->HorizontalResolution == NewHorizontalResolution) &&\r
748 (Info->VerticalResolution == NewVerticalResolution)) {\r
749 if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) &&\r
750 (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) {\r
751 //\r
752 // Current resolution is same with required resolution, check if text mode need be set\r
753 //\r
754 Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);\r
755 ASSERT_EFI_ERROR (Status);\r
756 if (CurrentColumn == NewColumns && CurrentRow == NewRows) {\r
757 //\r
758 // If current text mode is same with required text mode. Do nothing\r
759 //\r
760 FreePool (Info);\r
761 return EFI_SUCCESS;\r
762 } else {\r
763 //\r
764 // If current text mode is different from requried text mode. Set new video mode\r
765 //\r
766 for (Index = 0; Index < MaxTextMode; Index++) {\r
767 Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);\r
768 if (!EFI_ERROR(Status)) {\r
769 if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) {\r
770 //\r
771 // Required text mode is supported, set it.\r
772 //\r
773 Status = SimpleTextOut->SetMode (SimpleTextOut, Index);\r
774 ASSERT_EFI_ERROR (Status);\r
775 //\r
776 // Update text mode PCD.\r
777 //\r
377680ae
ED
778 Status = PcdSet32S (PcdConOutColumn, mSetupTextModeColumn);\r
779 ASSERT_EFI_ERROR (Status);\r
780 Status = PcdSet32S (PcdConOutRow, mSetupTextModeRow);\r
781 ASSERT_EFI_ERROR (Status);\r
a382952f
RN
782 FreePool (Info);\r
783 return EFI_SUCCESS;\r
784 }\r
785 }\r
786 }\r
787 if (Index == MaxTextMode) {\r
788 //\r
789 // If requried text mode is not supported, return error.\r
790 //\r
791 FreePool (Info);\r
792 return EFI_UNSUPPORTED;\r
793 }\r
794 }\r
795 } else {\r
796 //\r
797 // If current video resolution is not same with the new one, set new video resolution.\r
798 // In this case, the driver which produces simple text out need be restarted.\r
799 //\r
800 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);\r
801 if (!EFI_ERROR (Status)) {\r
802 FreePool (Info);\r
803 break;\r
804 }\r
805 }\r
806 }\r
807 FreePool (Info);\r
808 }\r
809 }\r
810\r
811 if (ModeNumber == MaxGopMode) {\r
812 //\r
813 // If the resolution is not supported, return error.\r
814 //\r
815 return EFI_UNSUPPORTED;\r
816 }\r
817\r
818 //\r
819 // Set PCD to Inform GraphicsConsole to change video resolution.\r
820 // Set PCD to Inform Consplitter to change text mode.\r
821 //\r
377680ae
ED
822 Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution);\r
823 ASSERT_EFI_ERROR (Status);\r
824 Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution);\r
825 ASSERT_EFI_ERROR (Status);\r
826 Status = PcdSet32S (PcdConOutColumn, NewColumns);\r
827 ASSERT_EFI_ERROR (Status);\r
828 Status = PcdSet32S (PcdConOutRow, NewRows);\r
829 ASSERT_EFI_ERROR (Status);\r
a382952f
RN
830 \r
831 //\r
832 // Video mode is changed, so restart graphics console driver and higher level driver.\r
833 // Reconnect graphics console driver and higher level driver.\r
834 // Locate all the handles with GOP protocol and reconnect it.\r
835 //\r
836 Status = gBS->LocateHandleBuffer (\r
837 ByProtocol,\r
838 &gEfiSimpleTextOutProtocolGuid,\r
839 NULL,\r
840 &HandleCount,\r
841 &HandleBuffer\r
842 );\r
843 if (!EFI_ERROR (Status)) {\r
844 for (Index = 0; Index < HandleCount; Index++) {\r
845 gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);\r
846 }\r
847 for (Index = 0; Index < HandleCount; Index++) {\r
848 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
849 }\r
850 if (HandleBuffer != NULL) {\r
851 FreePool (HandleBuffer);\r
852 }\r
853 }\r
854\r
855 return EFI_SUCCESS;\r
856}\r
857\r
858/**\r
859 Display the boot popup menu and allow user select boot item.\r
860\r
861 @param ImageHandle The image handle.\r
862 @param SystemTable The system table.\r
863 \r
864 @retval EFI_SUCCESS Boot from selected boot option, and return success from boot option\r
865 @retval EFI_NOT_FOUND User select to enter setup or can not find boot option\r
866 \r
867**/\r
868EFI_STATUS\r
869EFIAPI\r
870BootManagerMenuEntry (\r
871 IN EFI_HANDLE ImageHandle,\r
872 IN EFI_SYSTEM_TABLE *SystemTable\r
873 )\r
874{\r
875 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;\r
876 UINTN BootOptionCount; \r
877 EFI_STATUS Status;\r
878 BOOT_MENU_POPUP_DATA BootMenuData;\r
879 UINTN Index;\r
880 EFI_INPUT_KEY Key;\r
881 BOOLEAN ExitApplication;\r
882 UINTN SelectItem;\r
883 EFI_BOOT_LOGO_PROTOCOL *BootLogo;\r
884 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
885 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;\r
886 UINTN BootTextColumn;\r
887 UINTN BootTextRow;\r
888\r
889 //\r
890 // Set Logo status invalid when boot manager menu is launched\r
891 //\r
892 BootLogo = NULL;\r
893 Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);\r
894 if (!EFI_ERROR (Status) && (BootLogo != NULL)) {\r
895 Status = BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);\r
896 ASSERT_EFI_ERROR (Status);\r
897 }\r
898\r
899 gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
900\r
901 gStringPackHandle = HiiAddPackages (\r
902 &gEfiCallerIdGuid,\r
903 gImageHandle,\r
904 BootManagerMenuAppStrings,\r
905 NULL\r
906 );\r
907 ASSERT (gStringPackHandle != NULL);\r
908\r
909 //\r
910 // Connect all prior to entering the platform setup menu.\r
911 //\r
912 EfiBootManagerConnectAll ();\r
913 EfiBootManagerRefreshAllBootOption ();\r
914\r
915 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
916\r
917 if (!mModeInitialized) {\r
918 //\r
919 // After the console is ready, get current video resolution \r
920 // and text mode before launching setup at first time.\r
921 //\r
922 Status = gBS->HandleProtocol (\r
923 gST->ConsoleOutHandle,\r
924 &gEfiGraphicsOutputProtocolGuid,\r
925 (VOID**)&GraphicsOutput\r
926 );\r
927 if (EFI_ERROR (Status)) {\r
928 GraphicsOutput = NULL;\r
929 }\r
930 \r
931 Status = gBS->HandleProtocol (\r
932 gST->ConsoleOutHandle,\r
933 &gEfiSimpleTextOutProtocolGuid,\r
934 (VOID**)&SimpleTextOut\r
935 );\r
936 if (EFI_ERROR (Status)) {\r
937 SimpleTextOut = NULL;\r
938 } \r
939\r
940 if (GraphicsOutput != NULL) {\r
941 //\r
942 // Get current video resolution and text mode.\r
943 //\r
944 mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;\r
945 mBootVerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;\r
946 }\r
947\r
948 if (SimpleTextOut != NULL) {\r
949 Status = SimpleTextOut->QueryMode (\r
950 SimpleTextOut,\r
951 SimpleTextOut->Mode->Mode,\r
952 &BootTextColumn,\r
953 &BootTextRow\r
954 );\r
955 mBootTextModeColumn = (UINT32)BootTextColumn;\r
956 mBootTextModeRow = (UINT32)BootTextRow;\r
957 }\r
958\r
959 //\r
960 // Get user defined text mode for setup.\r
961 // \r
962 mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);\r
963 mSetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution); \r
964 mSetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn);\r
965 mSetupTextModeRow = PcdGet32 (PcdSetupConOutRow);\r
966 mModeInitialized = TRUE;\r
967 }\r
968 \r
969 //\r
970 // Set back to conventional setup resolution\r
971 //\r
972 BdsSetConsoleMode (TRUE);\r
973\r
974 //\r
975 // Initialize Boot menu data\r
976 //\r
977 Status = InitializeBootMenuData (BootOption, BootOptionCount, &BootMenuData);\r
978 //\r
979 // According to boot menu data to draw boot popup menu\r
980 //\r
981 DrawBootPopupMenu (&BootMenuData);\r
982 \r
983 //\r
984 // check user input to determine want to re-draw or boot from user selected item\r
985 //\r
986 ExitApplication = FALSE;\r
987 while (!ExitApplication) {\r
988 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);\r
989 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
990 if (!EFI_ERROR (Status)) {\r
991 switch (Key.UnicodeChar) {\r
992 \r
993 case CHAR_NULL: \r
994 switch (Key.ScanCode) { \r
995 \r
996 case SCAN_UP:\r
997 SelectItem = BootMenuData.SelectItem == 0 ? BootMenuData.ItemCount - 1 : BootMenuData.SelectItem - 1;\r
998 BootMenuSelectItem (SelectItem, &BootMenuData); \r
999 break;\r
1000 \r
1001 case SCAN_DOWN:\r
1002 SelectItem = BootMenuData.SelectItem == BootMenuData.ItemCount - 1 ? 0 : BootMenuData.SelectItem + 1;\r
1003 BootMenuSelectItem (SelectItem, &BootMenuData); \r
1004 break;\r
1005\r
1006 case SCAN_ESC:\r
1007 gST->ConOut->ClearScreen (gST->ConOut);\r
1008 ExitApplication = TRUE;\r
1009 //\r
1010 // Set boot resolution for normal boot\r
1011 //\r
1012 BdsSetConsoleMode (FALSE);\r
1013 break;\r
1014 \r
1015 default:\r
1016 break;\r
1017 }\r
1018 break;\r
1019 \r
1020 case CHAR_CARRIAGE_RETURN:\r
1021 gST->ConOut->ClearScreen (gST->ConOut);\r
1022 //\r
1023 // Set boot resolution for normal boot\r
1024 //\r
1025 BdsSetConsoleMode (FALSE);\r
1026 BootFromSelectOption (BootOption, BootOptionCount, BootMenuData.SelectItem);\r
1027 //\r
1028 // Back to boot manager menu again, set back to setup resolution\r
1029 //\r
1030 BdsSetConsoleMode (TRUE);\r
1031 DrawBootPopupMenu (&BootMenuData);\r
1032 break;\r
1033 \r
1034 default:\r
1035 break;\r
1036 }\r
1037 }\r
1038 }\r
1039 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);\r
1040 FreePool (BootMenuData.PtrTokens);\r
1041\r
1042 HiiRemovePackages (gStringPackHandle);\r
1043\r
1044 return Status;\r
1045 \r
1046}\r