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