]>
Commit | Line | Data |
---|---|---|
1 | /** @file\r | |
2 | The application to show the Boot Manager Menu.\r | |
3 | \r | |
4 | Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.<BR>\r | |
5 | SPDX-License-Identifier: BSD-2-Clause-Patent\r | |
6 | \r | |
7 | **/\r | |
8 | \r | |
9 | #include "BootManagerMenu.h"\r | |
10 | \r | |
11 | EFI_HII_HANDLE gStringPackHandle;\r | |
12 | \r | |
13 | BOOLEAN mModeInitialized = FALSE;\r | |
14 | \r | |
15 | //\r | |
16 | // Boot video resolution and text mode.\r | |
17 | //\r | |
18 | UINT32 mBootHorizontalResolution = 0;\r | |
19 | UINT32 mBootVerticalResolution = 0;\r | |
20 | UINT32 mBootTextModeColumn = 0;\r | |
21 | UINT32 mBootTextModeRow = 0;\r | |
22 | //\r | |
23 | // BIOS setup video resolution and text mode.\r | |
24 | //\r | |
25 | UINT32 mSetupTextModeColumn = 0;\r | |
26 | UINT32 mSetupTextModeRow = 0;\r | |
27 | UINT32 mSetupHorizontalResolution = 0;\r | |
28 | UINT32 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 | |
41 | UINTN\r | |
42 | PrintStringAt (\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 | |
111 | UINTN\r | |
112 | PrintCharAt (\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 | |
146 | UINTN\r | |
147 | GetLineWidth (\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 | |
215 | EFI_STATUS\r | |
216 | InitializeBootMenuScreen (\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 | |
298 | BOOLEAN\r | |
299 | IsBootManagerMenu (\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 | |
322 | BOOLEAN\r | |
323 | IgnoreBootOption (\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 | |
367 | EFI_STATUS\r | |
368 | InitializeBootMenuData (\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 | |
422 | EFI_STATUS\r | |
423 | BootMenuSelectItem (\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 | |
573 | EFI_STATUS\r | |
574 | DrawBootPopupMenu (\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 | |
735 | VOID\r | |
736 | BootFromSelectOption (\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 | |
769 | EFI_STATUS\r | |
770 | EFIAPI\r | |
771 | BdsSetConsoleMode (\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 | |
989 | EFI_STATUS\r | |
990 | EFIAPI\r | |
991 | BootManagerMenuEntry (\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 |