]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/BootManagerUiLib/BootManager.c
MdeModulePkg/BootManagerUiLib: show inactive boot options
[mirror_edk2.git] / MdeModulePkg / Library / BootManagerUiLib / BootManager.c
CommitLineData
3a2dc0f5
DB
1/** @file\r
2 The boot manager reference implementation\r
3\r
d1102dba 4Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
3a2dc0f5
DB
6\r
7**/\r
8\r
9#include "BootManager.h"\r
10\r
11UINT16 mKeyInput;\r
12EFI_GUID mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID;\r
13//\r
14// Boot video resolution and text mode.\r
15//\r
16UINT32 mBmBootHorizontalResolution = 0;\r
17UINT32 mBmBootVerticalResolution = 0;\r
18UINT32 mBmBootTextModeColumn = 0;\r
19UINT32 mBmBootTextModeRow = 0;\r
20//\r
21// BIOS setup video resolution and text mode.\r
22//\r
23UINT32 mBmSetupTextModeColumn = 0;\r
24UINT32 mBmSetupTextModeRow = 0;\r
25UINT32 mBmSetupHorizontalResolution = 0;\r
26UINT32 mBmSetupVerticalResolution = 0;\r
27\r
cb9fcac0
ED
28BOOLEAN mBmModeInitialized = FALSE;\r
29\r
3a2dc0f5
DB
30CHAR16 *mDeviceTypeStr[] = {\r
31 L"Legacy BEV",\r
32 L"Legacy Floppy",\r
33 L"Legacy Hard Drive",\r
34 L"Legacy CD ROM",\r
35 L"Legacy PCMCIA",\r
36 L"Legacy USB",\r
37 L"Legacy Embedded Network",\r
38 L"Legacy Unknown Device"\r
39};\r
40\r
41HII_VENDOR_DEVICE_PATH mBootManagerHiiVendorDevicePath = {\r
42 {\r
43 {\r
44 HARDWARE_DEVICE_PATH,\r
45 HW_VENDOR_DP,\r
46 {\r
47 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
48 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
49 }\r
50 },\r
51 //\r
52 // {1DDDBE15-481D-4d2b-8277-B191EAF66525}\r
53 //\r
54 { 0x1dddbe15, 0x481d, 0x4d2b, { 0x82, 0x77, 0xb1, 0x91, 0xea, 0xf6, 0x65, 0x25 } }\r
55 },\r
56 {\r
57 END_DEVICE_PATH_TYPE,\r
58 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
d1102dba 59 {\r
3a2dc0f5
DB
60 (UINT8) (END_DEVICE_PATH_LENGTH),\r
61 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
62 }\r
63 }\r
64};\r
65\r
66BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = {\r
67 BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,\r
68 NULL,\r
69 NULL,\r
70 {\r
71 BootManagerExtractConfig,\r
72 BootManagerRouteConfig,\r
73 BootManagerCallback\r
74 }\r
75};\r
76\r
77/**\r
78 This function will change video resolution and text mode\r
d1102dba 79 according to defined setup mode or defined boot mode\r
3a2dc0f5 80\r
d1102dba 81 @param IsSetupMode Indicate mode is changed to setup mode or boot mode.\r
3a2dc0f5
DB
82\r
83 @retval EFI_SUCCESS Mode is changed successfully.\r
84 @retval Others Mode failed to be changed.\r
85\r
86**/\r
87EFI_STATUS\r
b6c8ee68 88BmSetConsoleMode (\r
3a2dc0f5
DB
89 BOOLEAN IsSetupMode\r
90 )\r
91{\r
92 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
93 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;\r
94 UINTN SizeOfInfo;\r
95 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
96 UINT32 MaxGopMode;\r
97 UINT32 MaxTextMode;\r
98 UINT32 ModeNumber;\r
99 UINT32 NewHorizontalResolution;\r
100 UINT32 NewVerticalResolution;\r
101 UINT32 NewColumns;\r
102 UINT32 NewRows;\r
103 UINTN HandleCount;\r
104 EFI_HANDLE *HandleBuffer;\r
105 EFI_STATUS Status;\r
106 UINTN Index;\r
107 UINTN CurrentColumn;\r
d1102dba 108 UINTN CurrentRow;\r
3a2dc0f5
DB
109\r
110 MaxGopMode = 0;\r
111 MaxTextMode = 0;\r
112\r
113 //\r
d1102dba 114 // Get current video resolution and text mode\r
3a2dc0f5
DB
115 //\r
116 Status = gBS->HandleProtocol (\r
117 gST->ConsoleOutHandle,\r
118 &gEfiGraphicsOutputProtocolGuid,\r
119 (VOID**)&GraphicsOutput\r
120 );\r
121 if (EFI_ERROR (Status)) {\r
122 GraphicsOutput = NULL;\r
123 }\r
124\r
125 Status = gBS->HandleProtocol (\r
126 gST->ConsoleOutHandle,\r
127 &gEfiSimpleTextOutProtocolGuid,\r
128 (VOID**)&SimpleTextOut\r
129 );\r
130 if (EFI_ERROR (Status)) {\r
131 SimpleTextOut = NULL;\r
132 }\r
133\r
134 if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {\r
135 return EFI_UNSUPPORTED;\r
136 }\r
137\r
138 if (IsSetupMode) {\r
139 //\r
2048c585 140 // The required resolution and text mode is setup mode.\r
3a2dc0f5
DB
141 //\r
142 NewHorizontalResolution = mBmSetupHorizontalResolution;\r
143 NewVerticalResolution = mBmSetupVerticalResolution;\r
144 NewColumns = mBmSetupTextModeColumn;\r
145 NewRows = mBmSetupTextModeRow;\r
146 } else {\r
147 //\r
148 // The required resolution and text mode is boot mode.\r
149 //\r
150 NewHorizontalResolution = mBmBootHorizontalResolution;\r
151 NewVerticalResolution = mBmBootVerticalResolution;\r
152 NewColumns = mBmBootTextModeColumn;\r
d1102dba 153 NewRows = mBmBootTextModeRow;\r
3a2dc0f5
DB
154 }\r
155\r
156 if (GraphicsOutput != NULL) {\r
157 MaxGopMode = GraphicsOutput->Mode->MaxMode;\r
158 }\r
159\r
160 if (SimpleTextOut != NULL) {\r
161 MaxTextMode = SimpleTextOut->Mode->MaxMode;\r
162 }\r
163\r
164 //\r
165 // 1. If current video resolution is same with required video resolution,\r
166 // video resolution need not be changed.\r
167 // 1.1. If current text mode is same with required text mode, text mode need not be changed.\r
168 // 1.2. If current text mode is different from required text mode, text mode need be changed.\r
169 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.\r
170 //\r
171 for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {\r
172 Status = GraphicsOutput->QueryMode (\r
173 GraphicsOutput,\r
174 ModeNumber,\r
175 &SizeOfInfo,\r
176 &Info\r
177 );\r
178 if (!EFI_ERROR (Status)) {\r
179 if ((Info->HorizontalResolution == NewHorizontalResolution) &&\r
180 (Info->VerticalResolution == NewVerticalResolution)) {\r
181 if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) &&\r
182 (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) {\r
183 //\r
184 // Current resolution is same with required resolution, check if text mode need be set\r
185 //\r
186 Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);\r
187 ASSERT_EFI_ERROR (Status);\r
188 if (CurrentColumn == NewColumns && CurrentRow == NewRows) {\r
189 //\r
190 // If current text mode is same with required text mode. Do nothing\r
191 //\r
192 FreePool (Info);\r
193 return EFI_SUCCESS;\r
194 } else {\r
195 //\r
2048c585 196 // If current text mode is different from required text mode. Set new video mode\r
3a2dc0f5
DB
197 //\r
198 for (Index = 0; Index < MaxTextMode; Index++) {\r
199 Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);\r
200 if (!EFI_ERROR(Status)) {\r
201 if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) {\r
202 //\r
203 // Required text mode is supported, set it.\r
204 //\r
205 Status = SimpleTextOut->SetMode (SimpleTextOut, Index);\r
206 ASSERT_EFI_ERROR (Status);\r
207 //\r
208 // Update text mode PCD.\r
209 //\r
e750958b
DB
210 Status = PcdSet32S (PcdConOutColumn, mBmSetupTextModeColumn);\r
211 ASSERT_EFI_ERROR (Status);\r
212 Status = PcdSet32S (PcdConOutRow, mBmSetupTextModeRow);\r
213 ASSERT_EFI_ERROR (Status);\r
3a2dc0f5
DB
214 FreePool (Info);\r
215 return EFI_SUCCESS;\r
216 }\r
217 }\r
218 }\r
219 if (Index == MaxTextMode) {\r
220 //\r
2048c585 221 // If required text mode is not supported, return error.\r
3a2dc0f5
DB
222 //\r
223 FreePool (Info);\r
224 return EFI_UNSUPPORTED;\r
225 }\r
226 }\r
227 } else {\r
228 //\r
229 // If current video resolution is not same with the new one, set new video resolution.\r
230 // In this case, the driver which produces simple text out need be restarted.\r
231 //\r
232 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);\r
233 if (!EFI_ERROR (Status)) {\r
234 FreePool (Info);\r
235 break;\r
236 }\r
237 }\r
238 }\r
239 FreePool (Info);\r
240 }\r
241 }\r
242\r
243 if (ModeNumber == MaxGopMode) {\r
244 //\r
245 // If the resolution is not supported, return error.\r
246 //\r
247 return EFI_UNSUPPORTED;\r
248 }\r
249\r
250 //\r
251 // Set PCD to Inform GraphicsConsole to change video resolution.\r
252 // Set PCD to Inform Consplitter to change text mode.\r
253 //\r
e750958b
DB
254 Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution);\r
255 ASSERT_EFI_ERROR (Status);\r
256 Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution);\r
257 ASSERT_EFI_ERROR (Status);\r
258 Status = PcdSet32S (PcdConOutColumn, NewColumns);\r
259 ASSERT_EFI_ERROR (Status);\r
260 Status = PcdSet32S (PcdConOutRow, NewRows);\r
261 ASSERT_EFI_ERROR (Status);\r
3a2dc0f5
DB
262\r
263 //\r
264 // Video mode is changed, so restart graphics console driver and higher level driver.\r
265 // Reconnect graphics console driver and higher level driver.\r
266 // Locate all the handles with GOP protocol and reconnect it.\r
267 //\r
268 Status = gBS->LocateHandleBuffer (\r
269 ByProtocol,\r
270 &gEfiSimpleTextOutProtocolGuid,\r
271 NULL,\r
272 &HandleCount,\r
273 &HandleBuffer\r
274 );\r
275 if (!EFI_ERROR (Status)) {\r
276 for (Index = 0; Index < HandleCount; Index++) {\r
277 gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);\r
278 }\r
279 for (Index = 0; Index < HandleCount; Index++) {\r
280 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
281 }\r
282 if (HandleBuffer != NULL) {\r
283 FreePool (HandleBuffer);\r
284 }\r
285 }\r
286\r
287 return EFI_SUCCESS;\r
288}\r
289\r
c51f5f17
BD
290/**\r
291\r
292 Check whether a reset is needed,if reset is needed, Popup a menu to notice user.\r
293\r
294**/\r
295VOID\r
296BmSetupResetReminder (\r
297 VOID\r
298 )\r
299{\r
300 EFI_INPUT_KEY Key;\r
301 CHAR16 *StringBuffer1;\r
302 CHAR16 *StringBuffer2;\r
303 EFI_STATUS Status;\r
304 EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2;\r
305\r
306 //\r
307 // Use BrowserEx2 protocol to check whether reset is required.\r
308 //\r
309 Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **) &FormBrowserEx2);\r
310 //\r
311 //check any reset required change is applied? if yes, reset system\r
312 //\r
313 if (!EFI_ERROR(Status) && FormBrowserEx2->IsResetRequired ()) {\r
314 StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
315 ASSERT (StringBuffer1 != NULL);\r
316 StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
317 ASSERT (StringBuffer2 != NULL);\r
318 StrCpyS (StringBuffer1, MAX_STRING_LEN, L"Configuration changed. Reset to apply it Now.");\r
319 StrCpyS (StringBuffer2, MAX_STRING_LEN, L"Press ENTER to reset");\r
320 //\r
321 // Popup a menu to notice user\r
322 //\r
323 do {\r
324 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL);\r
325 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
326\r
327 FreePool (StringBuffer1);\r
328 FreePool (StringBuffer2);\r
329\r
330 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
331 }\r
332}\r
333\r
3a2dc0f5
DB
334/**\r
335 Group the legacy boot options in the BootOption.\r
336\r
d1102dba 337 The routine assumes the boot options in the beginning that covers all the device\r
3a2dc0f5
DB
338 types are ordered properly and re-position the following boot options just after\r
339 the corresponding boot options with the same device type.\r
340 For example:\r
341 1. Input = [Harddisk1 CdRom2 Efi1 Harddisk0 CdRom0 CdRom1 Harddisk2 Efi0]\r
342 Assuming [Harddisk1 CdRom2 Efi1] is ordered properly\r
343 Output = [Harddisk1 Harddisk0 Harddisk2 CdRom2 CdRom0 CdRom1 Efi1 Efi0]\r
344\r
345 2. Input = [Efi1 Efi0 CdRom1 Harddisk0 Harddisk1 Harddisk2 CdRom0 CdRom2]\r
346 Assuming [Efi1 Efi0 CdRom1 Harddisk0] is ordered properly\r
347 Output = [Efi1 Efi0 CdRom1 CdRom0 CdRom2 Harddisk0 Harddisk1 Harddisk2]\r
348\r
349**/\r
350VOID\r
351GroupMultipleLegacyBootOption4SameType (\r
352 VOID\r
353 )\r
354{\r
355 EFI_STATUS Status;\r
356 UINTN Index;\r
357 UINTN DeviceIndex;\r
358 UINTN DeviceTypeIndex[7];\r
359 UINTN *NextIndex;\r
360 UINT16 OptionNumber;\r
361 UINT16 *BootOrder;\r
362 UINTN BootOrderSize;\r
363 CHAR16 OptionName[sizeof ("Boot####")];\r
364 EFI_BOOT_MANAGER_LOAD_OPTION BootOption;\r
365\r
366 SetMem (DeviceTypeIndex, sizeof (DeviceTypeIndex), 0xff);\r
367\r
368 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize);\r
bd69e72c
ED
369 if (BootOrder == NULL) {\r
370 return;\r
371 }\r
3a2dc0f5
DB
372\r
373 for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
374 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]);\r
375 Status = EfiBootManagerVariableToLoadOption (OptionName, &BootOption);\r
376 ASSERT_EFI_ERROR (Status);\r
377\r
378 if ((DevicePathType (BootOption.FilePath) == BBS_DEVICE_PATH) &&\r
379 (DevicePathSubType (BootOption.FilePath) == BBS_BBS_DP)) {\r
380 //\r
381 // Legacy Boot Option\r
382 //\r
383 DEBUG ((EFI_D_ERROR, "[BootManagerDxe] ==== Find Legacy Boot Option 0x%x! ==== \n", Index));\r
a031a53f 384 ASSERT ((((BBS_BBS_DEVICE_PATH *) BootOption.FilePath)->DeviceType & 0xF) < ARRAY_SIZE (DeviceTypeIndex));\r
3a2dc0f5
DB
385 NextIndex = &DeviceTypeIndex[((BBS_BBS_DEVICE_PATH *) BootOption.FilePath)->DeviceType & 0xF];\r
386\r
387 if (*NextIndex == (UINTN) -1) {\r
388 //\r
389 // *NextIndex is the Index in BootOrder to put the next Option Number for the same type\r
390 //\r
391 *NextIndex = Index + 1;\r
392 } else {\r
393 //\r
394 // insert the current boot option before *NextIndex, causing [*Next .. Index] shift right one position\r
395 //\r
396 OptionNumber = BootOrder[Index];\r
397 CopyMem (&BootOrder[*NextIndex + 1], &BootOrder[*NextIndex], (Index - *NextIndex) * sizeof (UINT16));\r
398 BootOrder[*NextIndex] = OptionNumber;\r
399\r
400 //\r
401 // Update the DeviceTypeIndex array to reflect the right shift operation\r
402 //\r
a031a53f 403 for (DeviceIndex = 0; DeviceIndex < ARRAY_SIZE (DeviceTypeIndex); DeviceIndex++) {\r
3a2dc0f5
DB
404 if (DeviceTypeIndex[DeviceIndex] != (UINTN) -1 && DeviceTypeIndex[DeviceIndex] >= *NextIndex) {\r
405 DeviceTypeIndex[DeviceIndex]++;\r
406 }\r
407 }\r
408 }\r
409 }\r
410 EfiBootManagerFreeLoadOption (&BootOption);\r
411 }\r
412\r
413 gRT->SetVariable (\r
414 L"BootOrder",\r
415 &gEfiGlobalVariableGuid,\r
416 VAR_FLAG,\r
417 BootOrderSize,\r
418 BootOrder\r
419 );\r
420 FreePool (BootOrder);\r
421}\r
422\r
423/**\r
424 This function converts an input device structure to a Unicode string.\r
425\r
426 @param DevPath A pointer to the device path structure.\r
427\r
428 @return A new allocated Unicode string that represents the device path.\r
429\r
430**/\r
431CHAR16 *\r
432BmDevicePathToStr (\r
433 IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
434 )\r
435{\r
436 EFI_STATUS Status;\r
437 CHAR16 *ToText;\r
438 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;\r
439\r
440 if (DevPath == NULL) {\r
441 return NULL;\r
442 }\r
443\r
444 Status = gBS->LocateProtocol (\r
445 &gEfiDevicePathToTextProtocolGuid,\r
446 NULL,\r
447 (VOID **) &DevPathToText\r
448 );\r
449 ASSERT_EFI_ERROR (Status);\r
450 ToText = DevPathToText->ConvertDevicePathToText (\r
451 DevPath,\r
452 FALSE,\r
453 TRUE\r
454 );\r
455 ASSERT (ToText != NULL);\r
456 return ToText;\r
457}\r
458\r
459/**\r
7de6db5f 460 This function invokes Boot Manager. It then enumerate all boot options. If\r
3a2dc0f5
DB
461 a boot option from the Boot Manager page is selected, Boot Manager will boot\r
462 from this boot option.\r
d1102dba 463\r
3a2dc0f5
DB
464**/\r
465VOID\r
466UpdateBootManager (\r
467 VOID\r
468 )\r
469{\r
470 UINTN Index;\r
471 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;\r
472 UINTN BootOptionCount;\r
473 EFI_STRING_ID Token;\r
474 CHAR16 *HelpString;\r
475 EFI_STRING_ID HelpToken;\r
476 UINT16 *TempStr;\r
477 EFI_HII_HANDLE HiiHandle;\r
478 UINTN TempSize;\r
479 VOID *StartOpCodeHandle;\r
480 VOID *EndOpCodeHandle;\r
481 EFI_IFR_GUID_LABEL *StartLabel;\r
482 EFI_IFR_GUID_LABEL *EndLabel;\r
483 UINT16 DeviceType;\r
484 BOOLEAN IsLegacyOption;\r
485 BOOLEAN NeedEndOp;\r
486 UINTN MaxLen;\r
487\r
488 DeviceType = (UINT16) -1;\r
489\r
3a2dc0f5
DB
490 //\r
491 // for better user experience\r
492 // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option\r
493 // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option\r
494 //\r
495 EfiBootManagerRefreshAllBootOption ();\r
496\r
497 //\r
498 // BdsDxe doesn't group the legacy boot options for the same device type\r
499 // It's UI's choice.\r
500 //\r
501 GroupMultipleLegacyBootOption4SameType ();\r
502\r
503 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
504\r
505 HiiHandle = gBootManagerPrivate.HiiHandle;\r
506\r
507 //\r
508 // Allocate space for creation of UpdateData Buffer\r
509 //\r
510 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
511 ASSERT (StartOpCodeHandle != NULL);\r
512\r
513 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
514 ASSERT (EndOpCodeHandle != NULL);\r
515\r
516 //\r
517 // Create Hii Extend Label OpCode as the start opcode\r
518 //\r
519 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
520 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
521 StartLabel->Number = LABEL_BOOT_OPTION;\r
522\r
523 //\r
524 // Create Hii Extend Label OpCode as the end opcode\r
525 //\r
526 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
527 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
528 EndLabel->Number = LABEL_BOOT_OPTION_END;\r
529 mKeyInput = 0;\r
530 NeedEndOp = FALSE;\r
531 for (Index = 0; Index < BootOptionCount; Index++) {\r
532 //\r
533 // At this stage we are creating a menu entry, thus the Keys are reproduceable\r
534 //\r
535 mKeyInput++;\r
536\r
537 //\r
4ef72fe0 538 // Don't display hidden boot options, but retain inactive ones.\r
3a2dc0f5 539 //\r
4ef72fe0 540 if ((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) {\r
3a2dc0f5
DB
541 continue;\r
542 }\r
543\r
544 //\r
545 // Group the legacy boot option in the sub title created dynamically\r
546 //\r
547 IsLegacyOption = (BOOLEAN) (\r
548 (DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) &&\r
549 (DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP)\r
550 );\r
551\r
552 if (!IsLegacyOption && NeedEndOp) {\r
553 NeedEndOp = FALSE;\r
554 HiiCreateEndOpCode (StartOpCodeHandle);\r
555 }\r
d1102dba 556\r
3a2dc0f5
DB
557 if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) {\r
558 if (NeedEndOp) {\r
559 HiiCreateEndOpCode (StartOpCodeHandle);\r
560 }\r
561\r
562 DeviceType = ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType;\r
563 Token = HiiSetString (\r
564 HiiHandle,\r
565 0,\r
566 mDeviceTypeStr[\r
a031a53f 567 MIN (DeviceType & 0xF, ARRAY_SIZE (mDeviceTypeStr) - 1)\r
3a2dc0f5
DB
568 ],\r
569 NULL\r
570 );\r
571 HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1);\r
572 NeedEndOp = TRUE;\r
573 }\r
574\r
575 ASSERT (BootOption[Index].Description != NULL);\r
576\r
577 Token = HiiSetString (HiiHandle, 0, BootOption[Index].Description, NULL);\r
578\r
579 TempStr = BmDevicePathToStr (BootOption[Index].FilePath);\r
580 TempSize = StrSize (TempStr);\r
581 HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));\r
582 MaxLen = (TempSize + StrSize (L"Device Path : "))/sizeof(CHAR16);\r
583 ASSERT (HelpString != NULL);\r
584 StrCatS (HelpString, MaxLen, L"Device Path : ");\r
585 StrCatS (HelpString, MaxLen, TempStr);\r
586\r
587 HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL);\r
588\r
589 HiiCreateActionOpCode (\r
590 StartOpCodeHandle,\r
591 mKeyInput,\r
592 Token,\r
593 HelpToken,\r
594 EFI_IFR_FLAG_CALLBACK,\r
595 0\r
596 );\r
597 }\r
598\r
599 if (NeedEndOp) {\r
600 HiiCreateEndOpCode (StartOpCodeHandle);\r
601 }\r
602\r
603 HiiUpdateForm (\r
604 HiiHandle,\r
605 &mBootManagerGuid,\r
606 BOOT_MANAGER_FORM_ID,\r
607 StartOpCodeHandle,\r
608 EndOpCodeHandle\r
609 );\r
610\r
611 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
612 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
613\r
614 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);\r
615}\r
616\r
617/**\r
618 This function allows a caller to extract the current configuration for one\r
619 or more named elements from the target driver.\r
620\r
621\r
622 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
623 @param Request A null-terminated Unicode string in <ConfigRequest> format.\r
624 @param Progress On return, points to a character in the Request string.\r
625 Points to the string's null terminator if request was successful.\r
626 Points to the most recent '&' before the first failing name/value\r
627 pair (or the beginning of the string if the failure is in the\r
628 first name/value pair) if the request was not successful.\r
629 @param Results A null-terminated Unicode string in <ConfigAltResp> format which\r
630 has all values filled in for the names in the Request string.\r
631 String to be allocated by the called function.\r
632\r
633 @retval EFI_SUCCESS The Results is filled with the requested values.\r
634 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
635 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.\r
636 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
637\r
638**/\r
639EFI_STATUS\r
640EFIAPI\r
641BootManagerExtractConfig (\r
642 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
643 IN CONST EFI_STRING Request,\r
644 OUT EFI_STRING *Progress,\r
645 OUT EFI_STRING *Results\r
646 )\r
647{\r
648 if (Progress == NULL || Results == NULL) {\r
649 return EFI_INVALID_PARAMETER;\r
650 }\r
651 *Progress = Request;\r
652 return EFI_NOT_FOUND;\r
653}\r
654\r
655/**\r
656 This function processes the results of changes in configuration.\r
657\r
658\r
659 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
660 @param Configuration A null-terminated Unicode string in <ConfigResp> format.\r
661 @param Progress A pointer to a string filled in with the offset of the most\r
662 recent '&' before the first failing name/value pair (or the\r
663 beginning of the string if the failure is in the first\r
664 name/value pair) or the terminating NULL if all was successful.\r
665\r
666 @retval EFI_SUCCESS The Results is processed successfully.\r
667 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
668 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
669\r
670**/\r
671EFI_STATUS\r
672EFIAPI\r
673BootManagerRouteConfig (\r
674 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
675 IN CONST EFI_STRING Configuration,\r
676 OUT EFI_STRING *Progress\r
677 )\r
678{\r
679 if (Configuration == NULL || Progress == NULL) {\r
680 return EFI_INVALID_PARAMETER;\r
681 }\r
682\r
683 *Progress = Configuration;\r
684\r
685 return EFI_NOT_FOUND;\r
686}\r
687\r
cb9fcac0
ED
688/**\r
689 Initial the boot mode related parameters.\r
690\r
691**/\r
692VOID\r
693BmInitialBootModeInfo (\r
694 VOID\r
695 )\r
696{\r
697 EFI_STATUS Status;\r
698 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
699 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;\r
700 UINTN BootTextColumn;\r
701 UINTN BootTextRow;\r
702\r
703 if (mBmModeInitialized) {\r
704 return;\r
705 }\r
706\r
707 //\r
708 // After the console is ready, get current video resolution\r
709 // and text mode before launching setup at first time.\r
710 //\r
711 Status = gBS->HandleProtocol (\r
712 gST->ConsoleOutHandle,\r
713 &gEfiGraphicsOutputProtocolGuid,\r
714 (VOID**)&GraphicsOutput\r
715 );\r
716 if (EFI_ERROR (Status)) {\r
717 GraphicsOutput = NULL;\r
718 }\r
719\r
720 Status = gBS->HandleProtocol (\r
721 gST->ConsoleOutHandle,\r
722 &gEfiSimpleTextOutProtocolGuid,\r
723 (VOID**)&SimpleTextOut\r
724 );\r
725 if (EFI_ERROR (Status)) {\r
726 SimpleTextOut = NULL;\r
727 }\r
728\r
729 if (GraphicsOutput != NULL) {\r
730 //\r
731 // Get current video resolution and text mode.\r
732 //\r
733 mBmBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;\r
734 mBmBootVerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;\r
735 }\r
736\r
737 if (SimpleTextOut != NULL) {\r
738 Status = SimpleTextOut->QueryMode (\r
739 SimpleTextOut,\r
740 SimpleTextOut->Mode->Mode,\r
741 &BootTextColumn,\r
742 &BootTextRow\r
743 );\r
744 mBmBootTextModeColumn = (UINT32)BootTextColumn;\r
745 mBmBootTextModeRow = (UINT32)BootTextRow;\r
746 }\r
747\r
748 //\r
749 // Get user defined text mode for setup.\r
750 //\r
751 mBmSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);\r
752 mBmSetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution);\r
753 mBmSetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn);\r
754 mBmSetupTextModeRow = PcdGet32 (PcdSetupConOutRow);\r
755\r
756 mBmModeInitialized = TRUE;\r
757}\r
758\r
3a2dc0f5
DB
759/**\r
760 This call back function is registered with Boot Manager formset.\r
761 When user selects a boot option, this call back function will\r
762 be triggered. The boot option is saved for later processing.\r
763\r
764\r
765 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
766 @param Action Specifies the type of action taken by the browser.\r
767 @param QuestionId A unique value which is sent to the original exporting driver\r
768 so that it can identify the type of data to expect.\r
769 @param Type The type of value for the question.\r
770 @param Value A pointer to the data being sent to the original exporting driver.\r
771 @param ActionRequest On return, points to the action requested by the callback function.\r
772\r
773 @retval EFI_SUCCESS The callback successfully handled the action.\r
774 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
775\r
776**/\r
777EFI_STATUS\r
778EFIAPI\r
779BootManagerCallback (\r
780 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
781 IN EFI_BROWSER_ACTION Action,\r
782 IN EFI_QUESTION_ID QuestionId,\r
783 IN UINT8 Type,\r
784 IN EFI_IFR_TYPE_VALUE *Value,\r
785 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
786 )\r
787{\r
788 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;\r
789 UINTN BootOptionCount;\r
790 EFI_INPUT_KEY Key;\r
0034796f
DB
791\r
792 if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {\r
793 //\r
794 //Means enter the boot manager form.\r
795 //Update the boot manage page,because the boot option may changed.\r
796 //\r
797 if (QuestionId == 0x1212){\r
798 UpdateBootManager();\r
799 }\r
800 return EFI_SUCCESS;\r
801 }\r
802\r
3a2dc0f5
DB
803 if (Action != EFI_BROWSER_ACTION_CHANGED) {\r
804 //\r
805 // Do nothing for other UEFI Action. Only do call back when data is changed.\r
806 //\r
807 return EFI_UNSUPPORTED;\r
808 }\r
809\r
810 if ((Value == NULL) || (ActionRequest == NULL)) {\r
811 return EFI_INVALID_PARAMETER;\r
812 }\r
813\r
814 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
1b43162d
DB
815\r
816 //\r
817 // Clear the screen before.\r
818 //\r
819 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
820 gST->ConOut->ClearScreen (gST->ConOut);\r
821\r
c51f5f17
BD
822 //\r
823 //check any reset required change is applied? if yes, reset system\r
824 //\r
825 BmSetupResetReminder ();\r
826\r
3a2dc0f5
DB
827 //\r
828 // parse the selected option\r
829 //\r
b6c8ee68 830 BmSetConsoleMode (FALSE);\r
3a2dc0f5 831 EfiBootManagerBoot (&BootOption[QuestionId - 1]);\r
b6c8ee68 832 BmSetConsoleMode (TRUE);\r
3a2dc0f5
DB
833\r
834 if (EFI_ERROR (BootOption[QuestionId - 1].Status)) {\r
835 gST->ConOut->OutputString (\r
836 gST->ConOut,\r
837 HiiGetString (gBootManagerPrivate.HiiHandle, STRING_TOKEN (STR_ANY_KEY_CONTINUE), NULL)\r
838 );\r
839 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
840 }\r
841\r
842 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);\r
843\r
844 return EFI_SUCCESS;\r
845}\r
846\r
847/**\r
848\r
849 Install Boot Manager Menu driver.\r
850\r
851 @param ImageHandle The image handle.\r
852 @param SystemTable The system table.\r
853\r
854 @retval EFI_SUCEESS Install Boot manager menu success.\r
855 @retval Other Return error status.\r
856\r
857**/\r
858EFI_STATUS\r
859EFIAPI\r
120c8893 860BootManagerUiLibConstructor (\r
3a2dc0f5
DB
861 IN EFI_HANDLE ImageHandle,\r
862 IN EFI_SYSTEM_TABLE *SystemTable\r
863 )\r
864{\r
865 EFI_STATUS Status;\r
866\r
867 //\r
868 // Install Device Path Protocol and Config Access protocol to driver handle\r
869 //\r
870 gBootManagerPrivate.DriverHandle = NULL;\r
871 Status = gBS->InstallMultipleProtocolInterfaces (\r
872 &gBootManagerPrivate.DriverHandle,\r
873 &gEfiDevicePathProtocolGuid,\r
874 &mBootManagerHiiVendorDevicePath,\r
875 &gEfiHiiConfigAccessProtocolGuid,\r
876 &gBootManagerPrivate.ConfigAccess,\r
877 NULL\r
878 );\r
879 ASSERT_EFI_ERROR (Status);\r
880\r
881 //\r
882 // Publish our HII data\r
883 //\r
884 gBootManagerPrivate.HiiHandle = HiiAddPackages (\r
885 &mBootManagerGuid,\r
886 gBootManagerPrivate.DriverHandle,\r
887 BootManagerVfrBin,\r
120c8893 888 BootManagerUiLibStrings,\r
3a2dc0f5
DB
889 NULL\r
890 );\r
891 ASSERT (gBootManagerPrivate.HiiHandle != NULL);\r
892\r
cb9fcac0 893 BmInitialBootModeInfo ();\r
3a2dc0f5
DB
894\r
895 return EFI_SUCCESS;\r
896}\r
897\r
898/**\r
899 Unloads the application and its installed protocol.\r
900\r
901 @param[in] ImageHandle Handle that identifies the image to be unloaded.\r
902 @param[in] SystemTable System Table\r
903\r
904 @retval EFI_SUCCESS The image has been unloaded.\r
905**/\r
906EFI_STATUS\r
907EFIAPI\r
120c8893 908BootManagerUiLibDestructor (\r
3a2dc0f5
DB
909 IN EFI_HANDLE ImageHandle,\r
910 IN EFI_SYSTEM_TABLE *SystemTable\r
911 )\r
912{\r
913 EFI_STATUS Status;\r
914\r
915 Status = gBS->UninstallMultipleProtocolInterfaces (\r
916 gBootManagerPrivate.DriverHandle,\r
917 &gEfiDevicePathProtocolGuid,\r
918 &mBootManagerHiiVendorDevicePath,\r
919 &gEfiHiiConfigAccessProtocolGuid,\r
920 &gBootManagerPrivate.ConfigAccess,\r
921 NULL\r
922 );\r
923 ASSERT_EFI_ERROR (Status);\r
924\r
925 HiiRemovePackages (gBootManagerPrivate.HiiHandle);\r
926\r
927 return EFI_SUCCESS;\r
928}\r
929\r