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