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