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