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