]>
Commit | Line | Data |
---|---|---|
a382952f RN |
1 | /** @file\r |
2 | The application to show the Boot Manager Menu.\r | |
3 | \r | |
51a1db9b | 4 | Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>\r |
a382952f RN |
5 | This program and the accompanying materials\r |
6 | are licensed and made available under the terms and conditions of the BSD License\r | |
7 | which accompanies this distribution. The full text of the license may be found at\r | |
8 | http://opensource.org/licenses/bsd-license.php\r | |
9 | \r | |
10 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
11 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
12 | \r | |
13 | **/\r | |
14 | \r | |
15 | #include "BootManagerMenu.h"\r | |
16 | \r | |
17 | EFI_HII_HANDLE gStringPackHandle;\r | |
18 | \r | |
19 | BOOLEAN mModeInitialized = FALSE;\r | |
20 | \r | |
21 | //\r | |
22 | // Boot video resolution and text mode.\r | |
23 | //\r | |
24 | UINT32 mBootHorizontalResolution = 0;\r | |
25 | UINT32 mBootVerticalResolution = 0;\r | |
26 | UINT32 mBootTextModeColumn = 0;\r | |
27 | UINT32 mBootTextModeRow = 0;\r | |
28 | //\r | |
29 | // BIOS setup video resolution and text mode.\r | |
30 | //\r | |
31 | UINT32 mSetupTextModeColumn = 0;\r | |
32 | UINT32 mSetupTextModeRow = 0;\r | |
33 | UINT32 mSetupHorizontalResolution = 0;\r | |
34 | UINT32 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 | |
47 | UINTN\r | |
48 | PrintStringAt (\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 | |
04b34efb | 60 | Prints a character to the default console, at\r |
a382952f RN |
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 | |
70 | UINTN\r | |
71 | PrintCharAt (\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 | |
04b34efb | 82 | Count the storage space of a Unicode string which uses current language to get\r |
a382952f RN |
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 | |
90 | UINTN\r | |
91 | GetLineWidth (\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 | |
04b34efb | 150 | @param BootMenuData The boot menu data to be processed.\r |
a382952f RN |
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 | |
156 | EFI_STATUS \r | |
157 | InitializeBootMenuScreen (\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 | |
04b34efb | 222 | This function uses check boot option is wheher setup application or no\r |
a382952f RN |
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 | |
230 | BOOLEAN\r | |
231 | IsBootManagerMenu (\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 | |
04b34efb | 251 | @retval TRUE Ignore the boot option.\r |
7df23f85 RN |
252 | @retval FALSE Do not ignore the boot option.\r |
253 | **/\r | |
254 | BOOLEAN\r | |
255 | IgnoreBootOption (\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 | |
04b34efb | 289 | This function uses to initialize boot menu data\r |
a382952f RN |
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 | |
299 | EFI_STATUS\r | |
300 | InitializeBootMenuData (\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 | |
04b34efb | 348 | @param BootMenuData The boot menu data to be processed\r |
a382952f RN |
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 | |
354 | EFI_STATUS\r | |
355 | BootMenuSelectItem (\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 | |
51a1db9b | 377 | ASSERT (BootMenuData->ItemCount != 0);\r |
a382952f RN |
378 | SavedAttribute = gST->ConOut->Mode->Attribute;\r |
379 | RePaintItems = FALSE;\r | |
380 | StartCol = BootMenuData->MenuScreen.StartCol;\r | |
381 | StartRow = BootMenuData->MenuScreen.StartRow;\r | |
382 | //\r | |
383 | // print selectable items again and adjust scroll bar if need\r | |
384 | // \r | |
385 | if (BootMenuData->ScrollBarControl.HasScrollBar &&\r | |
386 | (WantSelectItem < BootMenuData->ScrollBarControl.FirstItem ||\r | |
387 | WantSelectItem > BootMenuData->ScrollBarControl.LastItem ||\r | |
388 | WantSelectItem == BootMenuData->SelectItem)) { \r | |
389 | ItemCountPerScreen = BootMenuData->ScrollBarControl.ItemCountPerScreen;\r | |
390 | //\r | |
391 | // Set first item and last item\r | |
392 | // \r | |
393 | if (WantSelectItem < BootMenuData->ScrollBarControl.FirstItem) {\r | |
394 | BootMenuData->ScrollBarControl.FirstItem = WantSelectItem;\r | |
395 | BootMenuData->ScrollBarControl.LastItem = WantSelectItem + ItemCountPerScreen - 1; \r | |
396 | } else if (WantSelectItem > BootMenuData->ScrollBarControl.LastItem) {\r | |
397 | BootMenuData->ScrollBarControl.FirstItem = WantSelectItem - ItemCountPerScreen + 1; \r | |
398 | BootMenuData->ScrollBarControl.LastItem = WantSelectItem;\r | |
399 | }\r | |
400 | gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);\r | |
401 | FirstItem = BootMenuData->ScrollBarControl.FirstItem;\r | |
402 | LastItem = BootMenuData->ScrollBarControl.LastItem;\r | |
403 | TopShadeNum = 0;\r | |
404 | if (FirstItem != 0) {\r | |
405 | TopShadeNum = (FirstItem * ItemCountPerScreen) / BootMenuData->ItemCount;\r | |
406 | if ((FirstItem * ItemCountPerScreen) % BootMenuData->ItemCount != 0) {\r | |
407 | TopShadeNum++;\r | |
408 | }\r | |
409 | PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;\r | |
410 | PrintRow = StartRow + TITLE_TOKEN_COUNT + 2; \r | |
411 | for (Index = 0; Index < TopShadeNum; Index++, PrintRow++) {\r | |
412 | PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_LIGHT_SHADE);\r | |
413 | }\r | |
414 | }\r | |
415 | LowShadeNum = 0;\r | |
416 | if (LastItem != BootMenuData->ItemCount - 1) {\r | |
417 | LowShadeNum = ((BootMenuData->ItemCount - 1 - LastItem) * ItemCountPerScreen) / BootMenuData->ItemCount;\r | |
418 | if (((BootMenuData->ItemCount - 1 - LastItem) * ItemCountPerScreen) % BootMenuData->ItemCount != 0) {\r | |
419 | LowShadeNum++;\r | |
420 | }\r | |
421 | PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;\r | |
422 | PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + ItemCountPerScreen - LowShadeNum; \r | |
423 | for (Index = 0; Index < LowShadeNum; Index++, PrintRow++) {\r | |
424 | PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_LIGHT_SHADE);\r | |
425 | } \r | |
426 | }\r | |
427 | PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;\r | |
428 | PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + TopShadeNum; \r | |
429 | for (Index = TopShadeNum; Index < ItemCountPerScreen - LowShadeNum; Index++, PrintRow++) {\r | |
430 | PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_FULL_BLOCK);\r | |
431 | } \r | |
432 | \r | |
433 | \r | |
434 | //\r | |
435 | // Clear selectable items first\r | |
436 | //\r | |
437 | PrintCol = StartCol + 1;\r | |
438 | PrintRow = StartRow + TITLE_TOKEN_COUNT + 2; \r | |
439 | String = AllocateZeroPool ((BootMenuData->MenuScreen.Width - 2) * sizeof (CHAR16));\r | |
440 | ASSERT (String != NULL);\r | |
441 | for (Index = 0; Index < BootMenuData->MenuScreen.Width - 3; Index++) {\r | |
442 | String[Index] = 0x20;\r | |
443 | } \r | |
444 | for (Index = 0; Index < ItemCountPerScreen; Index++) { \r | |
445 | PrintStringAt (PrintCol, PrintRow + Index, String); \r | |
446 | }\r | |
447 | FreePool (String);\r | |
448 | //\r | |
449 | // print selectable items \r | |
450 | //\r | |
451 | for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) {\r | |
452 | String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index + FirstItem], NULL);\r | |
453 | PrintStringAt (PrintCol, PrintRow, String);\r | |
454 | FreePool (String); \r | |
455 | }\r | |
456 | RePaintItems = TRUE;\r | |
457 | }\r | |
458 | \r | |
459 | //\r | |
460 | // Print want to select item \r | |
461 | //\r | |
462 | FirstItem = BootMenuData->ScrollBarControl.FirstItem;\r | |
463 | gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLACK);\r | |
464 | String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[WantSelectItem], NULL);\r | |
465 | PrintCol = StartCol + 1; \r | |
466 | PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + WantSelectItem - FirstItem; \r | |
467 | PrintStringAt (PrintCol, PrintRow, String);\r | |
468 | FreePool (String);\r | |
469 | \r | |
470 | //\r | |
471 | // if Want Select and selected item isn't the same and doesn't re-draw selectable \r | |
472 | // items, clear select item\r | |
473 | //\r | |
474 | if (WantSelectItem != BootMenuData->SelectItem && !RePaintItems) {\r | |
475 | gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);\r | |
476 | String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[BootMenuData->SelectItem], NULL);\r | |
477 | PrintCol = StartCol + 1; \r | |
478 | PrintRow = StartRow + 3 + BootMenuData->SelectItem - FirstItem; \r | |
479 | PrintStringAt (PrintCol, PrintRow, String);\r | |
480 | FreePool (String); \r | |
481 | }\r | |
482 | \r | |
483 | gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r | |
484 | BootMenuData->SelectItem = WantSelectItem;\r | |
485 | return EFI_SUCCESS;\r | |
486 | }\r | |
487 | \r | |
488 | /**\r | |
04b34efb | 489 | This function uses to draw boot popup menu\r |
a382952f RN |
490 | \r |
491 | @param BootMenuData The Input BootMenuData to be processed.\r | |
492 | \r | |
493 | @retval EFI_SUCCESS Draw boot popup menu successful.\r | |
494 | \r | |
495 | **/\r | |
496 | EFI_STATUS \r | |
497 | DrawBootPopupMenu (\r | |
498 | IN BOOT_MENU_POPUP_DATA *BootMenuData\r | |
499 | )\r | |
500 | {\r | |
501 | EFI_STRING String;\r | |
502 | UINTN Index;\r | |
503 | UINTN Width; \r | |
a382952f RN |
504 | UINTN StartCol;\r |
505 | UINTN StartRow;\r | |
506 | UINTN PrintRow;\r | |
507 | UINTN PrintCol;\r | |
508 | UINTN LineWidth;\r | |
509 | INT32 SavedAttribute; \r | |
510 | UINTN ItemCountPerScreen; \r | |
511 | \r | |
512 | gST->ConOut->ClearScreen (gST->ConOut);\r | |
513 | \r | |
514 | SavedAttribute = gST->ConOut->Mode->Attribute;\r | |
515 | gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);\r | |
516 | Width = BootMenuData->MenuScreen.Width;\r | |
a382952f RN |
517 | StartCol = BootMenuData->MenuScreen.StartCol;\r |
518 | StartRow = BootMenuData->MenuScreen.StartRow;\r | |
519 | ItemCountPerScreen = BootMenuData->ScrollBarControl.ItemCountPerScreen;\r | |
520 | PrintRow = StartRow;\r | |
521 | \r | |
522 | gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r | |
523 | //\r | |
524 | // Draw Boot popup menu screen\r | |
525 | //\r | |
526 | PrintCharAt (StartCol, PrintRow, BOXDRAW_DOWN_RIGHT);\r | |
527 | for (Index = 1; Index < Width - 1; Index++) {\r | |
528 | PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); \r | |
529 | }\r | |
530 | PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_DOWN_LEFT);\r | |
531 | \r | |
532 | //\r | |
533 | // Draw the screen for title\r | |
534 | //\r | |
535 | String = AllocateZeroPool ((Width - 1) * sizeof (CHAR16));\r | |
536 | ASSERT (String != NULL);\r | |
537 | for (Index = 0; Index < Width - 2; Index++) {\r | |
538 | String[Index] = 0x20;\r | |
539 | }\r | |
540 | \r | |
541 | for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++) {\r | |
542 | PrintRow++;\r | |
543 | PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL); \r | |
544 | PrintStringAt (StartCol + 1, PrintRow, String);\r | |
545 | PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);\r | |
546 | }\r | |
547 | \r | |
548 | PrintRow++;\r | |
549 | PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL_RIGHT);\r | |
550 | for (Index = 1; Index < Width - 1; Index++) {\r | |
551 | PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); \r | |
552 | }\r | |
553 | PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL_LEFT); \r | |
554 | \r | |
555 | //\r | |
556 | // Draw screen for selectable items\r | |
557 | //\r | |
558 | for (Index = 0; Index < ItemCountPerScreen; Index++) {\r | |
559 | PrintRow++;\r | |
560 | PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);\r | |
561 | PrintStringAt (StartCol + 1, PrintRow, String);\r | |
562 | PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);\r | |
563 | } \r | |
564 | \r | |
565 | PrintRow++;\r | |
566 | PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL_RIGHT);\r | |
567 | for (Index = 1; Index < Width - 1; Index++) {\r | |
568 | PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); \r | |
569 | }\r | |
570 | PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL_LEFT);\r | |
571 | \r | |
572 | //\r | |
573 | // Draw screen for Help\r | |
574 | //\r | |
575 | for (Index = 0; Index < HELP_TOKEN_COUNT; Index++) {\r | |
576 | PrintRow++;\r | |
577 | PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);\r | |
578 | PrintStringAt (StartCol + 1, PrintRow, String);\r | |
579 | PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);\r | |
580 | }\r | |
581 | FreePool (String); \r | |
582 | \r | |
583 | PrintRow++; \r | |
584 | PrintCharAt (StartCol, PrintRow, BOXDRAW_UP_RIGHT);\r | |
585 | for (Index = 1; Index < Width - 1; Index++) {\r | |
586 | PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); \r | |
587 | }\r | |
588 | PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_UP_LEFT); \r | |
589 | \r | |
590 | \r | |
591 | //\r | |
592 | // print title strings\r | |
593 | //\r | |
594 | PrintRow = StartRow + 1;\r | |
595 | for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++, PrintRow++) {\r | |
596 | String = HiiGetString (gStringPackHandle, BootMenuData->TitleToken[Index], NULL);\r | |
597 | LineWidth = GetLineWidth (BootMenuData->TitleToken[Index]); \r | |
598 | PrintCol = StartCol + (Width - LineWidth) / 2;\r | |
599 | PrintStringAt (PrintCol, PrintRow, String);\r | |
600 | FreePool (String);\r | |
601 | }\r | |
602 | \r | |
603 | //\r | |
604 | // print selectable items\r | |
605 | //\r | |
606 | PrintCol = StartCol + 1;\r | |
607 | PrintRow = StartRow + TITLE_TOKEN_COUNT + 2; \r | |
608 | for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) {\r | |
609 | String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index], NULL);\r | |
610 | PrintStringAt (PrintCol, PrintRow, String);\r | |
611 | FreePool (String); \r | |
612 | }\r | |
613 | \r | |
614 | //\r | |
615 | // Print Help strings\r | |
616 | //\r | |
617 | PrintRow++;\r | |
618 | for (Index = 0; Index < HELP_TOKEN_COUNT; Index++, PrintRow++) {\r | |
619 | String = HiiGetString (gStringPackHandle, BootMenuData->HelpToken[Index], NULL);\r | |
620 | LineWidth = GetLineWidth (BootMenuData->HelpToken[Index]);\r | |
621 | PrintCol = StartCol + (Width - LineWidth) / 2;\r | |
622 | PrintStringAt (PrintCol, PrintRow, String);\r | |
623 | FreePool (String);\r | |
624 | }\r | |
625 | \r | |
626 | //\r | |
627 | // Print scroll bar if has scroll bar\r | |
628 | //\r | |
629 | if (BootMenuData->ScrollBarControl.HasScrollBar) {\r | |
630 | PrintCol = StartCol + Width - 2;\r | |
631 | PrintRow = StartRow + 2; \r | |
632 | PrintCharAt (PrintCol, PrintRow, GEOMETRICSHAPE_UP_TRIANGLE); \r | |
633 | PrintCharAt (PrintCol + 1, PrintRow, BOXDRAW_VERTICAL); \r | |
634 | PrintRow += (ItemCountPerScreen + 1); \r | |
635 | PrintCharAt (PrintCol, PrintRow, GEOMETRICSHAPE_DOWN_TRIANGLE);\r | |
636 | PrintCharAt (PrintCol + 1, PrintRow, BOXDRAW_VERTICAL); \r | |
637 | } \r | |
638 | \r | |
639 | gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r | |
640 | //\r | |
641 | // Print Selected item\r | |
642 | //\r | |
643 | BootMenuSelectItem (BootMenuData->SelectItem, BootMenuData);\r | |
644 | return EFI_SUCCESS;\r | |
645 | }\r | |
646 | \r | |
647 | /**\r | |
04b34efb | 648 | This function uses to boot from selected item \r |
a382952f RN |
649 | \r |
650 | @param BootOptions Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.\r | |
651 | @param BootOptionCount Number of boot option.\r | |
652 | @param SelectItem Current selected item.\r | |
653 | **/\r | |
654 | VOID\r | |
655 | BootFromSelectOption (\r | |
656 | IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions,\r | |
657 | IN UINTN BootOptionCount, \r | |
658 | IN UINTN SelectItem\r | |
659 | )\r | |
660 | {\r | |
661 | UINTN ItemNum;\r | |
662 | UINTN Index;\r | |
663 | \r | |
664 | ASSERT (BootOptions != NULL);\r | |
665 | \r | |
666 | for (ItemNum = 0, Index = 0; Index < BootOptionCount; Index++) {\r | |
7df23f85 | 667 | if (IgnoreBootOption (&BootOptions[Index])) {\r |
a382952f RN |
668 | continue;\r |
669 | }\r | |
7df23f85 | 670 | \r |
a382952f RN |
671 | if (ItemNum++ == SelectItem) {\r |
672 | EfiBootManagerBoot (&BootOptions[Index]);\r | |
673 | break;\r | |
674 | }\r | |
675 | }\r | |
676 | }\r | |
677 | \r | |
678 | /**\r | |
679 | This function will change video resolution and text mode\r | |
680 | according to defined setup mode or defined boot mode \r | |
681 | \r | |
682 | @param IsSetupMode Indicate mode is changed to setup mode or boot mode. \r | |
683 | \r | |
684 | @retval EFI_SUCCESS Mode is changed successfully.\r | |
685 | @retval Others Mode failed to be changed.\r | |
686 | \r | |
687 | **/\r | |
688 | EFI_STATUS\r | |
689 | EFIAPI\r | |
690 | BdsSetConsoleMode (\r | |
691 | BOOLEAN IsSetupMode\r | |
692 | )\r | |
693 | {\r | |
694 | EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r | |
695 | EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;\r | |
696 | UINTN SizeOfInfo;\r | |
697 | EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r | |
698 | UINT32 MaxGopMode;\r | |
699 | UINT32 MaxTextMode;\r | |
700 | UINT32 ModeNumber;\r | |
701 | UINT32 NewHorizontalResolution;\r | |
702 | UINT32 NewVerticalResolution;\r | |
703 | UINT32 NewColumns;\r | |
704 | UINT32 NewRows;\r | |
705 | UINTN HandleCount;\r | |
706 | EFI_HANDLE *HandleBuffer;\r | |
707 | EFI_STATUS Status;\r | |
708 | UINTN Index;\r | |
709 | UINTN CurrentColumn;\r | |
710 | UINTN CurrentRow; \r | |
711 | \r | |
712 | MaxGopMode = 0;\r | |
713 | MaxTextMode = 0;\r | |
714 | \r | |
715 | //\r | |
716 | // Get current video resolution and text mode \r | |
717 | //\r | |
718 | Status = gBS->HandleProtocol (\r | |
719 | gST->ConsoleOutHandle,\r | |
720 | &gEfiGraphicsOutputProtocolGuid,\r | |
721 | (VOID**)&GraphicsOutput\r | |
722 | );\r | |
723 | if (EFI_ERROR (Status)) {\r | |
724 | GraphicsOutput = NULL;\r | |
725 | }\r | |
726 | \r | |
727 | Status = gBS->HandleProtocol (\r | |
728 | gST->ConsoleOutHandle,\r | |
729 | &gEfiSimpleTextOutProtocolGuid,\r | |
730 | (VOID**)&SimpleTextOut\r | |
731 | );\r | |
732 | if (EFI_ERROR (Status)) {\r | |
733 | SimpleTextOut = NULL;\r | |
734 | } \r | |
735 | \r | |
736 | if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {\r | |
737 | return EFI_UNSUPPORTED;\r | |
738 | }\r | |
739 | \r | |
740 | if (IsSetupMode) {\r | |
741 | //\r | |
2048c585 | 742 | // The required resolution and text mode is setup mode.\r |
a382952f RN |
743 | //\r |
744 | NewHorizontalResolution = mSetupHorizontalResolution;\r | |
745 | NewVerticalResolution = mSetupVerticalResolution;\r | |
746 | NewColumns = mSetupTextModeColumn;\r | |
747 | NewRows = mSetupTextModeRow;\r | |
748 | } else {\r | |
749 | //\r | |
750 | // The required resolution and text mode is boot mode.\r | |
751 | //\r | |
752 | NewHorizontalResolution = mBootHorizontalResolution;\r | |
753 | NewVerticalResolution = mBootVerticalResolution;\r | |
754 | NewColumns = mBootTextModeColumn;\r | |
755 | NewRows = mBootTextModeRow; \r | |
756 | }\r | |
757 | \r | |
758 | if (GraphicsOutput != NULL) {\r | |
759 | MaxGopMode = GraphicsOutput->Mode->MaxMode;\r | |
760 | } \r | |
761 | \r | |
762 | if (SimpleTextOut != NULL) {\r | |
763 | MaxTextMode = SimpleTextOut->Mode->MaxMode;\r | |
764 | }\r | |
765 | \r | |
766 | //\r | |
767 | // 1. If current video resolution is same with required video resolution,\r | |
768 | // video resolution need not be changed.\r | |
769 | // 1.1. If current text mode is same with required text mode, text mode need not be changed.\r | |
770 | // 1.2. If current text mode is different from required text mode, text mode need be changed.\r | |
771 | // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.\r | |
772 | //\r | |
773 | for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {\r | |
774 | Status = GraphicsOutput->QueryMode (\r | |
775 | GraphicsOutput,\r | |
776 | ModeNumber,\r | |
777 | &SizeOfInfo,\r | |
778 | &Info\r | |
779 | );\r | |
780 | if (!EFI_ERROR (Status)) {\r | |
781 | if ((Info->HorizontalResolution == NewHorizontalResolution) &&\r | |
782 | (Info->VerticalResolution == NewVerticalResolution)) {\r | |
783 | if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) &&\r | |
784 | (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) {\r | |
785 | //\r | |
786 | // Current resolution is same with required resolution, check if text mode need be set\r | |
787 | //\r | |
788 | Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);\r | |
789 | ASSERT_EFI_ERROR (Status);\r | |
790 | if (CurrentColumn == NewColumns && CurrentRow == NewRows) {\r | |
791 | //\r | |
792 | // If current text mode is same with required text mode. Do nothing\r | |
793 | //\r | |
794 | FreePool (Info);\r | |
795 | return EFI_SUCCESS;\r | |
796 | } else {\r | |
797 | //\r | |
2048c585 | 798 | // If current text mode is different from required text mode. Set new video mode\r |
a382952f RN |
799 | //\r |
800 | for (Index = 0; Index < MaxTextMode; Index++) {\r | |
801 | Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);\r | |
802 | if (!EFI_ERROR(Status)) {\r | |
803 | if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) {\r | |
804 | //\r | |
805 | // Required text mode is supported, set it.\r | |
806 | //\r | |
807 | Status = SimpleTextOut->SetMode (SimpleTextOut, Index);\r | |
808 | ASSERT_EFI_ERROR (Status);\r | |
809 | //\r | |
810 | // Update text mode PCD.\r | |
811 | //\r | |
377680ae ED |
812 | Status = PcdSet32S (PcdConOutColumn, mSetupTextModeColumn);\r |
813 | ASSERT_EFI_ERROR (Status);\r | |
814 | Status = PcdSet32S (PcdConOutRow, mSetupTextModeRow);\r | |
815 | ASSERT_EFI_ERROR (Status);\r | |
a382952f RN |
816 | FreePool (Info);\r |
817 | return EFI_SUCCESS;\r | |
818 | }\r | |
819 | }\r | |
820 | }\r | |
821 | if (Index == MaxTextMode) {\r | |
822 | //\r | |
2048c585 | 823 | // If required text mode is not supported, return error.\r |
a382952f RN |
824 | //\r |
825 | FreePool (Info);\r | |
826 | return EFI_UNSUPPORTED;\r | |
827 | }\r | |
828 | }\r | |
829 | } else {\r | |
830 | //\r | |
831 | // If current video resolution is not same with the new one, set new video resolution.\r | |
832 | // In this case, the driver which produces simple text out need be restarted.\r | |
833 | //\r | |
834 | Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);\r | |
835 | if (!EFI_ERROR (Status)) {\r | |
836 | FreePool (Info);\r | |
837 | break;\r | |
838 | }\r | |
839 | }\r | |
840 | }\r | |
841 | FreePool (Info);\r | |
842 | }\r | |
843 | }\r | |
844 | \r | |
845 | if (ModeNumber == MaxGopMode) {\r | |
846 | //\r | |
847 | // If the resolution is not supported, return error.\r | |
848 | //\r | |
849 | return EFI_UNSUPPORTED;\r | |
850 | }\r | |
851 | \r | |
852 | //\r | |
853 | // Set PCD to Inform GraphicsConsole to change video resolution.\r | |
854 | // Set PCD to Inform Consplitter to change text mode.\r | |
855 | //\r | |
377680ae ED |
856 | Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution);\r |
857 | ASSERT_EFI_ERROR (Status);\r | |
858 | Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution);\r | |
859 | ASSERT_EFI_ERROR (Status);\r | |
860 | Status = PcdSet32S (PcdConOutColumn, NewColumns);\r | |
861 | ASSERT_EFI_ERROR (Status);\r | |
862 | Status = PcdSet32S (PcdConOutRow, NewRows);\r | |
863 | ASSERT_EFI_ERROR (Status);\r | |
a382952f RN |
864 | \r |
865 | //\r | |
866 | // Video mode is changed, so restart graphics console driver and higher level driver.\r | |
867 | // Reconnect graphics console driver and higher level driver.\r | |
868 | // Locate all the handles with GOP protocol and reconnect it.\r | |
869 | //\r | |
870 | Status = gBS->LocateHandleBuffer (\r | |
871 | ByProtocol,\r | |
872 | &gEfiSimpleTextOutProtocolGuid,\r | |
873 | NULL,\r | |
874 | &HandleCount,\r | |
875 | &HandleBuffer\r | |
876 | );\r | |
877 | if (!EFI_ERROR (Status)) {\r | |
878 | for (Index = 0; Index < HandleCount; Index++) {\r | |
879 | gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);\r | |
880 | }\r | |
881 | for (Index = 0; Index < HandleCount; Index++) {\r | |
882 | gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r | |
883 | }\r | |
884 | if (HandleBuffer != NULL) {\r | |
885 | FreePool (HandleBuffer);\r | |
886 | }\r | |
887 | }\r | |
888 | \r | |
889 | return EFI_SUCCESS;\r | |
890 | }\r | |
891 | \r | |
892 | /**\r | |
893 | Display the boot popup menu and allow user select boot item.\r | |
894 | \r | |
895 | @param ImageHandle The image handle.\r | |
896 | @param SystemTable The system table.\r | |
897 | \r | |
898 | @retval EFI_SUCCESS Boot from selected boot option, and return success from boot option\r | |
899 | @retval EFI_NOT_FOUND User select to enter setup or can not find boot option\r | |
900 | \r | |
901 | **/\r | |
902 | EFI_STATUS\r | |
903 | EFIAPI\r | |
904 | BootManagerMenuEntry (\r | |
905 | IN EFI_HANDLE ImageHandle,\r | |
906 | IN EFI_SYSTEM_TABLE *SystemTable\r | |
907 | )\r | |
908 | {\r | |
909 | EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;\r | |
910 | UINTN BootOptionCount; \r | |
911 | EFI_STATUS Status;\r | |
912 | BOOT_MENU_POPUP_DATA BootMenuData;\r | |
913 | UINTN Index;\r | |
914 | EFI_INPUT_KEY Key;\r | |
915 | BOOLEAN ExitApplication;\r | |
916 | UINTN SelectItem;\r | |
917 | EFI_BOOT_LOGO_PROTOCOL *BootLogo;\r | |
918 | EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r | |
919 | EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;\r | |
920 | UINTN BootTextColumn;\r | |
921 | UINTN BootTextRow;\r | |
922 | \r | |
923 | //\r | |
924 | // Set Logo status invalid when boot manager menu is launched\r | |
925 | //\r | |
926 | BootLogo = NULL;\r | |
927 | Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);\r | |
928 | if (!EFI_ERROR (Status) && (BootLogo != NULL)) {\r | |
929 | Status = BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);\r | |
930 | ASSERT_EFI_ERROR (Status);\r | |
931 | }\r | |
932 | \r | |
933 | gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r | |
934 | \r | |
935 | gStringPackHandle = HiiAddPackages (\r | |
936 | &gEfiCallerIdGuid,\r | |
937 | gImageHandle,\r | |
938 | BootManagerMenuAppStrings,\r | |
939 | NULL\r | |
940 | );\r | |
941 | ASSERT (gStringPackHandle != NULL);\r | |
942 | \r | |
943 | //\r | |
944 | // Connect all prior to entering the platform setup menu.\r | |
945 | //\r | |
946 | EfiBootManagerConnectAll ();\r | |
947 | EfiBootManagerRefreshAllBootOption ();\r | |
948 | \r | |
949 | BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r | |
950 | \r | |
951 | if (!mModeInitialized) {\r | |
952 | //\r | |
953 | // After the console is ready, get current video resolution \r | |
954 | // and text mode before launching setup at first time.\r | |
955 | //\r | |
956 | Status = gBS->HandleProtocol (\r | |
957 | gST->ConsoleOutHandle,\r | |
958 | &gEfiGraphicsOutputProtocolGuid,\r | |
959 | (VOID**)&GraphicsOutput\r | |
960 | );\r | |
961 | if (EFI_ERROR (Status)) {\r | |
962 | GraphicsOutput = NULL;\r | |
963 | }\r | |
964 | \r | |
965 | Status = gBS->HandleProtocol (\r | |
966 | gST->ConsoleOutHandle,\r | |
967 | &gEfiSimpleTextOutProtocolGuid,\r | |
968 | (VOID**)&SimpleTextOut\r | |
969 | );\r | |
970 | if (EFI_ERROR (Status)) {\r | |
971 | SimpleTextOut = NULL;\r | |
972 | } \r | |
973 | \r | |
974 | if (GraphicsOutput != NULL) {\r | |
975 | //\r | |
976 | // Get current video resolution and text mode.\r | |
977 | //\r | |
978 | mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;\r | |
979 | mBootVerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;\r | |
980 | }\r | |
981 | \r | |
982 | if (SimpleTextOut != NULL) {\r | |
983 | Status = SimpleTextOut->QueryMode (\r | |
984 | SimpleTextOut,\r | |
985 | SimpleTextOut->Mode->Mode,\r | |
986 | &BootTextColumn,\r | |
987 | &BootTextRow\r | |
988 | );\r | |
989 | mBootTextModeColumn = (UINT32)BootTextColumn;\r | |
990 | mBootTextModeRow = (UINT32)BootTextRow;\r | |
991 | }\r | |
992 | \r | |
993 | //\r | |
994 | // Get user defined text mode for setup.\r | |
995 | // \r | |
996 | mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);\r | |
997 | mSetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution); \r | |
998 | mSetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn);\r | |
999 | mSetupTextModeRow = PcdGet32 (PcdSetupConOutRow);\r | |
1000 | mModeInitialized = TRUE;\r | |
1001 | }\r | |
1002 | \r | |
1003 | //\r | |
1004 | // Set back to conventional setup resolution\r | |
1005 | //\r | |
1006 | BdsSetConsoleMode (TRUE);\r | |
1007 | \r | |
1008 | //\r | |
1009 | // Initialize Boot menu data\r | |
1010 | //\r | |
1011 | Status = InitializeBootMenuData (BootOption, BootOptionCount, &BootMenuData);\r | |
1012 | //\r | |
1013 | // According to boot menu data to draw boot popup menu\r | |
1014 | //\r | |
1015 | DrawBootPopupMenu (&BootMenuData);\r | |
1016 | \r | |
1017 | //\r | |
1018 | // check user input to determine want to re-draw or boot from user selected item\r | |
1019 | //\r | |
1020 | ExitApplication = FALSE;\r | |
1021 | while (!ExitApplication) {\r | |
1022 | gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);\r | |
1023 | Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r | |
1024 | if (!EFI_ERROR (Status)) {\r | |
1025 | switch (Key.UnicodeChar) {\r | |
1026 | \r | |
1027 | case CHAR_NULL: \r | |
1028 | switch (Key.ScanCode) { \r | |
1029 | \r | |
1030 | case SCAN_UP:\r | |
1031 | SelectItem = BootMenuData.SelectItem == 0 ? BootMenuData.ItemCount - 1 : BootMenuData.SelectItem - 1;\r | |
1032 | BootMenuSelectItem (SelectItem, &BootMenuData); \r | |
1033 | break;\r | |
1034 | \r | |
1035 | case SCAN_DOWN:\r | |
1036 | SelectItem = BootMenuData.SelectItem == BootMenuData.ItemCount - 1 ? 0 : BootMenuData.SelectItem + 1;\r | |
1037 | BootMenuSelectItem (SelectItem, &BootMenuData); \r | |
1038 | break;\r | |
1039 | \r | |
1040 | case SCAN_ESC:\r | |
1041 | gST->ConOut->ClearScreen (gST->ConOut);\r | |
1042 | ExitApplication = TRUE;\r | |
1043 | //\r | |
1044 | // Set boot resolution for normal boot\r | |
1045 | //\r | |
1046 | BdsSetConsoleMode (FALSE);\r | |
1047 | break;\r | |
1048 | \r | |
1049 | default:\r | |
1050 | break;\r | |
1051 | }\r | |
1052 | break;\r | |
1053 | \r | |
1054 | case CHAR_CARRIAGE_RETURN:\r | |
1055 | gST->ConOut->ClearScreen (gST->ConOut);\r | |
1056 | //\r | |
1057 | // Set boot resolution for normal boot\r | |
1058 | //\r | |
1059 | BdsSetConsoleMode (FALSE);\r | |
1060 | BootFromSelectOption (BootOption, BootOptionCount, BootMenuData.SelectItem);\r | |
1061 | //\r | |
1062 | // Back to boot manager menu again, set back to setup resolution\r | |
1063 | //\r | |
1064 | BdsSetConsoleMode (TRUE);\r | |
1065 | DrawBootPopupMenu (&BootMenuData);\r | |
1066 | break;\r | |
1067 | \r | |
1068 | default:\r | |
1069 | break;\r | |
1070 | }\r | |
1071 | }\r | |
1072 | }\r | |
1073 | EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);\r | |
1074 | FreePool (BootMenuData.PtrTokens);\r | |
1075 | \r | |
1076 | HiiRemovePackages (gStringPackHandle);\r | |
1077 | \r | |
1078 | return Status;\r | |
1079 | \r | |
1080 | }\r |