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