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