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