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