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