]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/BootManagerUiLib/BootManager.c
MdeModulePkg/S3SmmInitDone.h: Fix copyright coding style error.
[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 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 required 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 required 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 required 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
298 Check whether a reset is needed,if reset is needed, Popup a menu to notice user.
299
300 **/
301 VOID
302 BmSetupResetReminder (
303 VOID
304 )
305 {
306 EFI_INPUT_KEY Key;
307 CHAR16 *StringBuffer1;
308 CHAR16 *StringBuffer2;
309 EFI_STATUS Status;
310 EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2;
311
312 //
313 // Use BrowserEx2 protocol to check whether reset is required.
314 //
315 Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **) &FormBrowserEx2);
316 //
317 //check any reset required change is applied? if yes, reset system
318 //
319 if (!EFI_ERROR(Status) && FormBrowserEx2->IsResetRequired ()) {
320 StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));
321 ASSERT (StringBuffer1 != NULL);
322 StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));
323 ASSERT (StringBuffer2 != NULL);
324 StrCpyS (StringBuffer1, MAX_STRING_LEN, L"Configuration changed. Reset to apply it Now.");
325 StrCpyS (StringBuffer2, MAX_STRING_LEN, L"Press ENTER to reset");
326 //
327 // Popup a menu to notice user
328 //
329 do {
330 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL);
331 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
332
333 FreePool (StringBuffer1);
334 FreePool (StringBuffer2);
335
336 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
337 }
338 }
339
340 /**
341 Group the legacy boot options in the BootOption.
342
343 The routine assumes the boot options in the beginning that covers all the device
344 types are ordered properly and re-position the following boot options just after
345 the corresponding boot options with the same device type.
346 For example:
347 1. Input = [Harddisk1 CdRom2 Efi1 Harddisk0 CdRom0 CdRom1 Harddisk2 Efi0]
348 Assuming [Harddisk1 CdRom2 Efi1] is ordered properly
349 Output = [Harddisk1 Harddisk0 Harddisk2 CdRom2 CdRom0 CdRom1 Efi1 Efi0]
350
351 2. Input = [Efi1 Efi0 CdRom1 Harddisk0 Harddisk1 Harddisk2 CdRom0 CdRom2]
352 Assuming [Efi1 Efi0 CdRom1 Harddisk0] is ordered properly
353 Output = [Efi1 Efi0 CdRom1 CdRom0 CdRom2 Harddisk0 Harddisk1 Harddisk2]
354
355 **/
356 VOID
357 GroupMultipleLegacyBootOption4SameType (
358 VOID
359 )
360 {
361 EFI_STATUS Status;
362 UINTN Index;
363 UINTN DeviceIndex;
364 UINTN DeviceTypeIndex[7];
365 UINTN *NextIndex;
366 UINT16 OptionNumber;
367 UINT16 *BootOrder;
368 UINTN BootOrderSize;
369 CHAR16 OptionName[sizeof ("Boot####")];
370 EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
371
372 SetMem (DeviceTypeIndex, sizeof (DeviceTypeIndex), 0xff);
373
374 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize);
375 if (BootOrder == NULL) {
376 return;
377 }
378
379 for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
380 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]);
381 Status = EfiBootManagerVariableToLoadOption (OptionName, &BootOption);
382 ASSERT_EFI_ERROR (Status);
383
384 if ((DevicePathType (BootOption.FilePath) == BBS_DEVICE_PATH) &&
385 (DevicePathSubType (BootOption.FilePath) == BBS_BBS_DP)) {
386 //
387 // Legacy Boot Option
388 //
389 DEBUG ((EFI_D_ERROR, "[BootManagerDxe] ==== Find Legacy Boot Option 0x%x! ==== \n", Index));
390 ASSERT ((((BBS_BBS_DEVICE_PATH *) BootOption.FilePath)->DeviceType & 0xF) < ARRAY_SIZE (DeviceTypeIndex));
391 NextIndex = &DeviceTypeIndex[((BBS_BBS_DEVICE_PATH *) BootOption.FilePath)->DeviceType & 0xF];
392
393 if (*NextIndex == (UINTN) -1) {
394 //
395 // *NextIndex is the Index in BootOrder to put the next Option Number for the same type
396 //
397 *NextIndex = Index + 1;
398 } else {
399 //
400 // insert the current boot option before *NextIndex, causing [*Next .. Index] shift right one position
401 //
402 OptionNumber = BootOrder[Index];
403 CopyMem (&BootOrder[*NextIndex + 1], &BootOrder[*NextIndex], (Index - *NextIndex) * sizeof (UINT16));
404 BootOrder[*NextIndex] = OptionNumber;
405
406 //
407 // Update the DeviceTypeIndex array to reflect the right shift operation
408 //
409 for (DeviceIndex = 0; DeviceIndex < ARRAY_SIZE (DeviceTypeIndex); DeviceIndex++) {
410 if (DeviceTypeIndex[DeviceIndex] != (UINTN) -1 && DeviceTypeIndex[DeviceIndex] >= *NextIndex) {
411 DeviceTypeIndex[DeviceIndex]++;
412 }
413 }
414 }
415 }
416 EfiBootManagerFreeLoadOption (&BootOption);
417 }
418
419 gRT->SetVariable (
420 L"BootOrder",
421 &gEfiGlobalVariableGuid,
422 VAR_FLAG,
423 BootOrderSize,
424 BootOrder
425 );
426 FreePool (BootOrder);
427 }
428
429 /**
430 This function converts an input device structure to a Unicode string.
431
432 @param DevPath A pointer to the device path structure.
433
434 @return A new allocated Unicode string that represents the device path.
435
436 **/
437 CHAR16 *
438 BmDevicePathToStr (
439 IN EFI_DEVICE_PATH_PROTOCOL *DevPath
440 )
441 {
442 EFI_STATUS Status;
443 CHAR16 *ToText;
444 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
445
446 if (DevPath == NULL) {
447 return NULL;
448 }
449
450 Status = gBS->LocateProtocol (
451 &gEfiDevicePathToTextProtocolGuid,
452 NULL,
453 (VOID **) &DevPathToText
454 );
455 ASSERT_EFI_ERROR (Status);
456 ToText = DevPathToText->ConvertDevicePathToText (
457 DevPath,
458 FALSE,
459 TRUE
460 );
461 ASSERT (ToText != NULL);
462 return ToText;
463 }
464
465 /**
466 This function invokes Boot Manager. It then enumerate all boot options. If
467 a boot option from the Boot Manager page is selected, Boot Manager will boot
468 from this boot option.
469
470 **/
471 VOID
472 UpdateBootManager (
473 VOID
474 )
475 {
476 UINTN Index;
477 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;
478 UINTN BootOptionCount;
479 EFI_STRING_ID Token;
480 CHAR16 *HelpString;
481 EFI_STRING_ID HelpToken;
482 UINT16 *TempStr;
483 EFI_HII_HANDLE HiiHandle;
484 UINTN TempSize;
485 VOID *StartOpCodeHandle;
486 VOID *EndOpCodeHandle;
487 EFI_IFR_GUID_LABEL *StartLabel;
488 EFI_IFR_GUID_LABEL *EndLabel;
489 UINT16 DeviceType;
490 BOOLEAN IsLegacyOption;
491 BOOLEAN NeedEndOp;
492 UINTN MaxLen;
493
494 DeviceType = (UINT16) -1;
495
496 //
497 // for better user experience
498 // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option
499 // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option
500 //
501 EfiBootManagerRefreshAllBootOption ();
502
503 //
504 // BdsDxe doesn't group the legacy boot options for the same device type
505 // It's UI's choice.
506 //
507 GroupMultipleLegacyBootOption4SameType ();
508
509 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
510
511 HiiHandle = gBootManagerPrivate.HiiHandle;
512
513 //
514 // Allocate space for creation of UpdateData Buffer
515 //
516 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
517 ASSERT (StartOpCodeHandle != NULL);
518
519 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
520 ASSERT (EndOpCodeHandle != NULL);
521
522 //
523 // Create Hii Extend Label OpCode as the start opcode
524 //
525 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
526 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
527 StartLabel->Number = LABEL_BOOT_OPTION;
528
529 //
530 // Create Hii Extend Label OpCode as the end opcode
531 //
532 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
533 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
534 EndLabel->Number = LABEL_BOOT_OPTION_END;
535 mKeyInput = 0;
536 NeedEndOp = FALSE;
537 for (Index = 0; Index < BootOptionCount; Index++) {
538 //
539 // At this stage we are creating a menu entry, thus the Keys are reproduceable
540 //
541 mKeyInput++;
542
543 //
544 // Don't display the hidden/inactive boot option
545 //
546 if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) {
547 continue;
548 }
549
550 //
551 // Group the legacy boot option in the sub title created dynamically
552 //
553 IsLegacyOption = (BOOLEAN) (
554 (DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) &&
555 (DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP)
556 );
557
558 if (!IsLegacyOption && NeedEndOp) {
559 NeedEndOp = FALSE;
560 HiiCreateEndOpCode (StartOpCodeHandle);
561 }
562
563 if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) {
564 if (NeedEndOp) {
565 HiiCreateEndOpCode (StartOpCodeHandle);
566 }
567
568 DeviceType = ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType;
569 Token = HiiSetString (
570 HiiHandle,
571 0,
572 mDeviceTypeStr[
573 MIN (DeviceType & 0xF, ARRAY_SIZE (mDeviceTypeStr) - 1)
574 ],
575 NULL
576 );
577 HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1);
578 NeedEndOp = TRUE;
579 }
580
581 ASSERT (BootOption[Index].Description != NULL);
582
583 Token = HiiSetString (HiiHandle, 0, BootOption[Index].Description, NULL);
584
585 TempStr = BmDevicePathToStr (BootOption[Index].FilePath);
586 TempSize = StrSize (TempStr);
587 HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));
588 MaxLen = (TempSize + StrSize (L"Device Path : "))/sizeof(CHAR16);
589 ASSERT (HelpString != NULL);
590 StrCatS (HelpString, MaxLen, L"Device Path : ");
591 StrCatS (HelpString, MaxLen, TempStr);
592
593 HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL);
594
595 HiiCreateActionOpCode (
596 StartOpCodeHandle,
597 mKeyInput,
598 Token,
599 HelpToken,
600 EFI_IFR_FLAG_CALLBACK,
601 0
602 );
603 }
604
605 if (NeedEndOp) {
606 HiiCreateEndOpCode (StartOpCodeHandle);
607 }
608
609 HiiUpdateForm (
610 HiiHandle,
611 &mBootManagerGuid,
612 BOOT_MANAGER_FORM_ID,
613 StartOpCodeHandle,
614 EndOpCodeHandle
615 );
616
617 HiiFreeOpCodeHandle (StartOpCodeHandle);
618 HiiFreeOpCodeHandle (EndOpCodeHandle);
619
620 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
621 }
622
623 /**
624 This function allows a caller to extract the current configuration for one
625 or more named elements from the target driver.
626
627
628 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
629 @param Request A null-terminated Unicode string in <ConfigRequest> format.
630 @param Progress On return, points to a character in the Request string.
631 Points to the string's null terminator if request was successful.
632 Points to the most recent '&' before the first failing name/value
633 pair (or the beginning of the string if the failure is in the
634 first name/value pair) if the request was not successful.
635 @param Results A null-terminated Unicode string in <ConfigAltResp> format which
636 has all values filled in for the names in the Request string.
637 String to be allocated by the called function.
638
639 @retval EFI_SUCCESS The Results is filled with the requested values.
640 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
641 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
642 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
643
644 **/
645 EFI_STATUS
646 EFIAPI
647 BootManagerExtractConfig (
648 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
649 IN CONST EFI_STRING Request,
650 OUT EFI_STRING *Progress,
651 OUT EFI_STRING *Results
652 )
653 {
654 if (Progress == NULL || Results == NULL) {
655 return EFI_INVALID_PARAMETER;
656 }
657 *Progress = Request;
658 return EFI_NOT_FOUND;
659 }
660
661 /**
662 This function processes the results of changes in configuration.
663
664
665 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
666 @param Configuration A null-terminated Unicode string in <ConfigResp> format.
667 @param Progress A pointer to a string filled in with the offset of the most
668 recent '&' before the first failing name/value pair (or the
669 beginning of the string if the failure is in the first
670 name/value pair) or the terminating NULL if all was successful.
671
672 @retval EFI_SUCCESS The Results is processed successfully.
673 @retval EFI_INVALID_PARAMETER Configuration is NULL.
674 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
675
676 **/
677 EFI_STATUS
678 EFIAPI
679 BootManagerRouteConfig (
680 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
681 IN CONST EFI_STRING Configuration,
682 OUT EFI_STRING *Progress
683 )
684 {
685 if (Configuration == NULL || Progress == NULL) {
686 return EFI_INVALID_PARAMETER;
687 }
688
689 *Progress = Configuration;
690
691 return EFI_NOT_FOUND;
692 }
693
694 /**
695 Initial the boot mode related parameters.
696
697 **/
698 VOID
699 BmInitialBootModeInfo (
700 VOID
701 )
702 {
703 EFI_STATUS Status;
704 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
705 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
706 UINTN BootTextColumn;
707 UINTN BootTextRow;
708
709 if (mBmModeInitialized) {
710 return;
711 }
712
713 //
714 // After the console is ready, get current video resolution
715 // and text mode before launching setup at first time.
716 //
717 Status = gBS->HandleProtocol (
718 gST->ConsoleOutHandle,
719 &gEfiGraphicsOutputProtocolGuid,
720 (VOID**)&GraphicsOutput
721 );
722 if (EFI_ERROR (Status)) {
723 GraphicsOutput = NULL;
724 }
725
726 Status = gBS->HandleProtocol (
727 gST->ConsoleOutHandle,
728 &gEfiSimpleTextOutProtocolGuid,
729 (VOID**)&SimpleTextOut
730 );
731 if (EFI_ERROR (Status)) {
732 SimpleTextOut = NULL;
733 }
734
735 if (GraphicsOutput != NULL) {
736 //
737 // Get current video resolution and text mode.
738 //
739 mBmBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
740 mBmBootVerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;
741 }
742
743 if (SimpleTextOut != NULL) {
744 Status = SimpleTextOut->QueryMode (
745 SimpleTextOut,
746 SimpleTextOut->Mode->Mode,
747 &BootTextColumn,
748 &BootTextRow
749 );
750 mBmBootTextModeColumn = (UINT32)BootTextColumn;
751 mBmBootTextModeRow = (UINT32)BootTextRow;
752 }
753
754 //
755 // Get user defined text mode for setup.
756 //
757 mBmSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
758 mBmSetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution);
759 mBmSetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn);
760 mBmSetupTextModeRow = PcdGet32 (PcdSetupConOutRow);
761
762 mBmModeInitialized = TRUE;
763 }
764
765 /**
766 This call back function is registered with Boot Manager formset.
767 When user selects a boot option, this call back function will
768 be triggered. The boot option is saved for later processing.
769
770
771 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
772 @param Action Specifies the type of action taken by the browser.
773 @param QuestionId A unique value which is sent to the original exporting driver
774 so that it can identify the type of data to expect.
775 @param Type The type of value for the question.
776 @param Value A pointer to the data being sent to the original exporting driver.
777 @param ActionRequest On return, points to the action requested by the callback function.
778
779 @retval EFI_SUCCESS The callback successfully handled the action.
780 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
781
782 **/
783 EFI_STATUS
784 EFIAPI
785 BootManagerCallback (
786 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
787 IN EFI_BROWSER_ACTION Action,
788 IN EFI_QUESTION_ID QuestionId,
789 IN UINT8 Type,
790 IN EFI_IFR_TYPE_VALUE *Value,
791 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
792 )
793 {
794 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;
795 UINTN BootOptionCount;
796 EFI_INPUT_KEY Key;
797
798 if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
799 //
800 //Means enter the boot manager form.
801 //Update the boot manage page,because the boot option may changed.
802 //
803 if (QuestionId == 0x1212){
804 UpdateBootManager();
805 }
806 return EFI_SUCCESS;
807 }
808
809 if (Action != EFI_BROWSER_ACTION_CHANGED) {
810 //
811 // Do nothing for other UEFI Action. Only do call back when data is changed.
812 //
813 return EFI_UNSUPPORTED;
814 }
815
816 if ((Value == NULL) || (ActionRequest == NULL)) {
817 return EFI_INVALID_PARAMETER;
818 }
819
820 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
821
822 //
823 // Clear the screen before.
824 //
825 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
826 gST->ConOut->ClearScreen (gST->ConOut);
827
828 //
829 //check any reset required change is applied? if yes, reset system
830 //
831 BmSetupResetReminder ();
832
833 //
834 // parse the selected option
835 //
836 BmSetConsoleMode (FALSE);
837 EfiBootManagerBoot (&BootOption[QuestionId - 1]);
838 BmSetConsoleMode (TRUE);
839
840 if (EFI_ERROR (BootOption[QuestionId - 1].Status)) {
841 gST->ConOut->OutputString (
842 gST->ConOut,
843 HiiGetString (gBootManagerPrivate.HiiHandle, STRING_TOKEN (STR_ANY_KEY_CONTINUE), NULL)
844 );
845 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
846 }
847
848 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
849
850 return EFI_SUCCESS;
851 }
852
853 /**
854
855 Install Boot Manager Menu driver.
856
857 @param ImageHandle The image handle.
858 @param SystemTable The system table.
859
860 @retval EFI_SUCEESS Install Boot manager menu success.
861 @retval Other Return error status.
862
863 **/
864 EFI_STATUS
865 EFIAPI
866 BootManagerUiLibConstructor (
867 IN EFI_HANDLE ImageHandle,
868 IN EFI_SYSTEM_TABLE *SystemTable
869 )
870 {
871 EFI_STATUS Status;
872
873 //
874 // Install Device Path Protocol and Config Access protocol to driver handle
875 //
876 gBootManagerPrivate.DriverHandle = NULL;
877 Status = gBS->InstallMultipleProtocolInterfaces (
878 &gBootManagerPrivate.DriverHandle,
879 &gEfiDevicePathProtocolGuid,
880 &mBootManagerHiiVendorDevicePath,
881 &gEfiHiiConfigAccessProtocolGuid,
882 &gBootManagerPrivate.ConfigAccess,
883 NULL
884 );
885 ASSERT_EFI_ERROR (Status);
886
887 //
888 // Publish our HII data
889 //
890 gBootManagerPrivate.HiiHandle = HiiAddPackages (
891 &mBootManagerGuid,
892 gBootManagerPrivate.DriverHandle,
893 BootManagerVfrBin,
894 BootManagerUiLibStrings,
895 NULL
896 );
897 ASSERT (gBootManagerPrivate.HiiHandle != NULL);
898
899 BmInitialBootModeInfo ();
900
901 return EFI_SUCCESS;
902 }
903
904 /**
905 Unloads the application and its installed protocol.
906
907 @param[in] ImageHandle Handle that identifies the image to be unloaded.
908 @param[in] SystemTable System Table
909
910 @retval EFI_SUCCESS The image has been unloaded.
911 **/
912 EFI_STATUS
913 EFIAPI
914 BootManagerUiLibDestructor (
915 IN EFI_HANDLE ImageHandle,
916 IN EFI_SYSTEM_TABLE *SystemTable
917 )
918 {
919 EFI_STATUS Status;
920
921 Status = gBS->UninstallMultipleProtocolInterfaces (
922 gBootManagerPrivate.DriverHandle,
923 &gEfiDevicePathProtocolGuid,
924 &mBootManagerHiiVendorDevicePath,
925 &gEfiHiiConfigAccessProtocolGuid,
926 &gBootManagerPrivate.ConfigAccess,
927 NULL
928 );
929 ASSERT_EFI_ERROR (Status);
930
931 HiiRemovePackages (gBootManagerPrivate.HiiHandle);
932
933 return EFI_SUCCESS;
934 }
935