2 The functions for Boot Maintainence Main menu.
4 Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "BootMaintenanceManager.h"
11 #define FRONT_PAGE_KEY_OFFSET 0x4000
13 // Boot video resolution and text mode.
15 UINT32 mBmmBootHorizontalResolution
= 0;
16 UINT32 mBmmBootVerticalResolution
= 0;
17 UINT32 mBmmBootTextModeColumn
= 0;
18 UINT32 mBmmBootTextModeRow
= 0;
20 // BIOS setup video resolution and text mode.
22 UINT32 mBmmSetupTextModeColumn
= 0;
23 UINT32 mBmmSetupTextModeRow
= 0;
24 UINT32 mBmmSetupHorizontalResolution
= 0;
25 UINT32 mBmmSetupVerticalResolution
= 0;
27 BOOLEAN mBmmModeInitialized
= FALSE
;
29 EFI_DEVICE_PATH_PROTOCOL EndDevicePath
[] = {
32 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
34 END_DEVICE_PATH_LENGTH
,
40 HII_VENDOR_DEVICE_PATH mBmmHiiVendorDevicePath
= {
46 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
47 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
51 // {165A028F-0BB2-4b5f-8747-77592E3F6499}
53 { 0x165a028f, 0xbb2, 0x4b5f, { 0x87, 0x47, 0x77, 0x59, 0x2e, 0x3f, 0x64, 0x99 } }
57 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
59 (UINT8
) (END_DEVICE_PATH_LENGTH
),
60 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
65 EFI_GUID mBootMaintGuid
= BOOT_MAINT_FORMSET_GUID
;
67 CHAR16 mBootMaintStorageName
[] = L
"BmmData";
68 BMM_CALLBACK_DATA gBootMaintenancePrivate
= {
69 BMM_CALLBACK_DATA_SIGNATURE
,
73 BootMaintExtractConfig
,
79 BMM_CALLBACK_DATA
*mBmmCallbackInfo
= &gBootMaintenancePrivate
;
80 BOOLEAN mAllMenuInit
= FALSE
;
81 BOOLEAN mFirstEnterBMMForm
= FALSE
;
86 @param CallbackData The BMM context data.
91 IN BMM_CALLBACK_DATA
*CallbackData
95 Free up all Menu Option list.
105 Update the menus in the BMM page.
114 This function will change video resolution and text mode
115 according to defined setup mode or defined boot mode
117 @param IsSetupMode Indicate mode is changed to setup mode or boot mode.
119 @retval EFI_SUCCESS Mode is changed successfully.
120 @retval Others Mode failed to be changed.
128 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
129 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
131 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
135 UINT32 NewHorizontalResolution
;
136 UINT32 NewVerticalResolution
;
140 EFI_HANDLE
*HandleBuffer
;
150 // Get current video resolution and text mode
152 Status
= gBS
->HandleProtocol (
153 gST
->ConsoleOutHandle
,
154 &gEfiGraphicsOutputProtocolGuid
,
155 (VOID
**)&GraphicsOutput
157 if (EFI_ERROR (Status
)) {
158 GraphicsOutput
= NULL
;
161 Status
= gBS
->HandleProtocol (
162 gST
->ConsoleOutHandle
,
163 &gEfiSimpleTextOutProtocolGuid
,
164 (VOID
**)&SimpleTextOut
166 if (EFI_ERROR (Status
)) {
167 SimpleTextOut
= NULL
;
170 if ((GraphicsOutput
== NULL
) || (SimpleTextOut
== NULL
)) {
171 return EFI_UNSUPPORTED
;
176 // The required resolution and text mode is setup mode.
178 NewHorizontalResolution
= mBmmSetupHorizontalResolution
;
179 NewVerticalResolution
= mBmmSetupVerticalResolution
;
180 NewColumns
= mBmmSetupTextModeColumn
;
181 NewRows
= mBmmSetupTextModeRow
;
184 // The required resolution and text mode is boot mode.
186 NewHorizontalResolution
= mBmmBootHorizontalResolution
;
187 NewVerticalResolution
= mBmmBootVerticalResolution
;
188 NewColumns
= mBmmBootTextModeColumn
;
189 NewRows
= mBmmBootTextModeRow
;
192 if (GraphicsOutput
!= NULL
) {
193 MaxGopMode
= GraphicsOutput
->Mode
->MaxMode
;
196 if (SimpleTextOut
!= NULL
) {
197 MaxTextMode
= SimpleTextOut
->Mode
->MaxMode
;
201 // 1. If current video resolution is same with required video resolution,
202 // video resolution need not be changed.
203 // 1.1. If current text mode is same with required text mode, text mode need not be changed.
204 // 1.2. If current text mode is different from required text mode, text mode need be changed.
205 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.
207 for (ModeNumber
= 0; ModeNumber
< MaxGopMode
; ModeNumber
++) {
208 Status
= GraphicsOutput
->QueryMode (
214 if (!EFI_ERROR (Status
)) {
215 if ((Info
->HorizontalResolution
== NewHorizontalResolution
) &&
216 (Info
->VerticalResolution
== NewVerticalResolution
)) {
217 if ((GraphicsOutput
->Mode
->Info
->HorizontalResolution
== NewHorizontalResolution
) &&
218 (GraphicsOutput
->Mode
->Info
->VerticalResolution
== NewVerticalResolution
)) {
220 // Current resolution is same with required resolution, check if text mode need be set
222 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, SimpleTextOut
->Mode
->Mode
, &CurrentColumn
, &CurrentRow
);
223 ASSERT_EFI_ERROR (Status
);
224 if (CurrentColumn
== NewColumns
&& CurrentRow
== NewRows
) {
226 // If current text mode is same with required text mode. Do nothing
232 // If current text mode is different from required text mode. Set new video mode
234 for (Index
= 0; Index
< MaxTextMode
; Index
++) {
235 Status
= SimpleTextOut
->QueryMode (SimpleTextOut
, Index
, &CurrentColumn
, &CurrentRow
);
236 if (!EFI_ERROR(Status
)) {
237 if ((CurrentColumn
== NewColumns
) && (CurrentRow
== NewRows
)) {
239 // Required text mode is supported, set it.
241 Status
= SimpleTextOut
->SetMode (SimpleTextOut
, Index
);
242 ASSERT_EFI_ERROR (Status
);
244 // Update text mode PCD.
246 Status
= PcdSet32S (PcdConOutColumn
, mBmmSetupTextModeColumn
);
247 ASSERT_EFI_ERROR (Status
);
248 Status
= PcdSet32S (PcdConOutRow
, mBmmSetupTextModeRow
);
249 ASSERT_EFI_ERROR (Status
);
255 if (Index
== MaxTextMode
) {
257 // If required text mode is not supported, return error.
260 return EFI_UNSUPPORTED
;
265 // If current video resolution is not same with the new one, set new video resolution.
266 // In this case, the driver which produces simple text out need be restarted.
268 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, ModeNumber
);
269 if (!EFI_ERROR (Status
)) {
279 if (ModeNumber
== MaxGopMode
) {
281 // If the resolution is not supported, return error.
283 return EFI_UNSUPPORTED
;
287 // Set PCD to Inform GraphicsConsole to change video resolution.
288 // Set PCD to Inform Consplitter to change text mode.
290 Status
= PcdSet32S (PcdVideoHorizontalResolution
, NewHorizontalResolution
);
291 ASSERT_EFI_ERROR (Status
);
292 Status
= PcdSet32S (PcdVideoVerticalResolution
, NewVerticalResolution
);
293 ASSERT_EFI_ERROR (Status
);
294 Status
= PcdSet32S (PcdConOutColumn
, NewColumns
);
295 ASSERT_EFI_ERROR (Status
);
296 Status
= PcdSet32S (PcdConOutRow
, NewRows
);
297 ASSERT_EFI_ERROR (Status
);
300 // Video mode is changed, so restart graphics console driver and higher level driver.
301 // Reconnect graphics console driver and higher level driver.
302 // Locate all the handles with GOP protocol and reconnect it.
304 Status
= gBS
->LocateHandleBuffer (
306 &gEfiSimpleTextOutProtocolGuid
,
311 if (!EFI_ERROR (Status
)) {
312 for (Index
= 0; Index
< HandleCount
; Index
++) {
313 gBS
->DisconnectController (HandleBuffer
[Index
], NULL
, NULL
);
315 for (Index
= 0; Index
< HandleCount
; Index
++) {
316 gBS
->ConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
318 if (HandleBuffer
!= NULL
) {
319 FreePool (HandleBuffer
);
327 This function converts an input device structure to a Unicode string.
329 @param DevPath A pointer to the device path structure.
331 @return A new allocated Unicode string that represents the device path.
336 IN EFI_DEVICE_PATH_PROTOCOL
*DevPath
341 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
*DevPathToText
;
343 if (DevPath
== NULL
) {
347 Status
= gBS
->LocateProtocol (
348 &gEfiDevicePathToTextProtocolGuid
,
350 (VOID
**) &DevPathToText
352 ASSERT_EFI_ERROR (Status
);
353 ToText
= DevPathToText
->ConvertDevicePathToText (
358 ASSERT (ToText
!= NULL
);
363 Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.
364 The caller is responsible for freeing the allocated buffer using FreePool().
366 @param DevicePath Device path.
368 @return A new allocated string that represents the file name.
372 ExtractFileNameFromDevicePath (
373 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
382 ASSERT(DevicePath
!= NULL
);
384 String
= UiDevicePathToStr(DevicePath
);
385 MatchString
= String
;
389 while(MatchString
!= NULL
){
390 LastMatch
= MatchString
+ 1;
391 MatchString
= StrStr(LastMatch
,L
"\\");
394 Length
= StrLen(LastMatch
);
395 FileName
= AllocateCopyPool ((Length
+ 1) * sizeof(CHAR16
), LastMatch
);
396 if (FileName
!= NULL
) {
397 *(FileName
+ Length
) = 0;
406 Extract device path for given HII handle and class guid.
408 @param Handle The HII handle.
410 @retval NULL Fail to get the device path string.
411 @return PathString Get the device path string.
415 BmmExtractDevicePathFromHiiHandle (
416 IN EFI_HII_HANDLE Handle
420 EFI_HANDLE DriverHandle
;
422 ASSERT (Handle
!= NULL
);
424 if (Handle
== NULL
) {
428 Status
= gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, Handle
, &DriverHandle
);
429 if (EFI_ERROR (Status
)) {
434 // Get device path string.
436 return ConvertDevicePathToText(DevicePathFromHandle (DriverHandle
), FALSE
, FALSE
);
441 Converts the unicode character of the string from uppercase to lowercase.
442 This is a internal function.
444 @param ConfigString String to be converted
449 IN EFI_STRING ConfigString
455 ASSERT (ConfigString
!= NULL
);
458 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
460 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
461 if (*String
== L
'=') {
463 } else if (*String
== L
'&') {
465 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
466 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
472 Update the progress string through the offset value.
474 @param Offset The offset value
475 @param Configuration Point to the configuration string.
481 IN EFI_STRING Configuration
485 EFI_STRING StringPtr
;
486 EFI_STRING ReturnString
;
492 // &OFFSET=XXXX followed by a Null-terminator.
493 // Length = StrLen (L"&OFFSET=") + 4 + 1
495 Length
= StrLen (L
"&OFFSET=") + 4 + 1;
497 StringPtr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
499 if (StringPtr
== NULL
) {
505 (8 + 4 + 1) * sizeof (CHAR16
),
510 ReturnString
= StrStr (Configuration
, StringPtr
);
512 if (ReturnString
== NULL
) {
514 // If doesn't find the string in Configuration, convert the string to lower case then search again.
516 HiiToLower (StringPtr
);
517 ReturnString
= StrStr (Configuration
, StringPtr
);
520 FreePool (StringPtr
);
526 Update the terminal content in TerminalMenu.
528 @param BmmData The BMM fake NV data.
532 UpdateTerminalContent (
533 IN BMM_FAKE_NV_DATA
*BmmData
537 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
538 BM_MENU_ENTRY
*NewMenuEntry
;
540 for (Index
= 0; Index
< TerminalMenu
.MenuNumber
; Index
++) {
541 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, Index
);
542 ASSERT (NewMenuEntry
!= NULL
);
543 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
544 NewTerminalContext
->BaudRateIndex
= BmmData
->COMBaudRate
[Index
];
545 ASSERT (BmmData
->COMBaudRate
[Index
] < (ARRAY_SIZE (BaudRateList
)));
546 NewTerminalContext
->BaudRate
= BaudRateList
[BmmData
->COMBaudRate
[Index
]].Value
;
547 NewTerminalContext
->DataBitsIndex
= BmmData
->COMDataRate
[Index
];
548 ASSERT (BmmData
->COMDataRate
[Index
] < (ARRAY_SIZE (DataBitsList
)));
549 NewTerminalContext
->DataBits
= (UINT8
) DataBitsList
[BmmData
->COMDataRate
[Index
]].Value
;
550 NewTerminalContext
->StopBitsIndex
= BmmData
->COMStopBits
[Index
];
551 ASSERT (BmmData
->COMStopBits
[Index
] < (ARRAY_SIZE (StopBitsList
)));
552 NewTerminalContext
->StopBits
= (UINT8
) StopBitsList
[BmmData
->COMStopBits
[Index
]].Value
;
553 NewTerminalContext
->ParityIndex
= BmmData
->COMParity
[Index
];
554 ASSERT (BmmData
->COMParity
[Index
] < (ARRAY_SIZE (ParityList
)));
555 NewTerminalContext
->Parity
= (UINT8
) ParityList
[BmmData
->COMParity
[Index
]].Value
;
556 NewTerminalContext
->TerminalType
= BmmData
->COMTerminalType
[Index
];
557 NewTerminalContext
->FlowControl
= BmmData
->COMFlowControl
[Index
];
558 ChangeTerminalDevicePath (
559 NewTerminalContext
->DevicePath
,
566 Update the console content in ConsoleMenu.
568 @param ConsoleName The name for the console device type.
569 @param BmmData The BMM fake NV data.
573 UpdateConsoleContent(
574 IN CHAR16
*ConsoleName
,
575 IN BMM_FAKE_NV_DATA
*BmmData
579 BM_CONSOLE_CONTEXT
*NewConsoleContext
;
580 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
581 BM_MENU_ENTRY
*NewMenuEntry
;
583 if (StrCmp (ConsoleName
, L
"ConIn") == 0) {
584 for (Index
= 0; Index
< ConsoleInpMenu
.MenuNumber
; Index
++){
585 NewMenuEntry
= BOpt_GetMenuEntry(&ConsoleInpMenu
, Index
);
586 NewConsoleContext
= (BM_CONSOLE_CONTEXT
*)NewMenuEntry
->VariableContext
;
587 ASSERT (Index
< MAX_MENU_NUMBER
);
588 NewConsoleContext
->IsActive
= BmmData
->ConsoleInCheck
[Index
];
590 for (Index
= 0; Index
< TerminalMenu
.MenuNumber
; Index
++) {
591 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, Index
);
592 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
593 ASSERT (Index
+ ConsoleInpMenu
.MenuNumber
< MAX_MENU_NUMBER
);
594 NewTerminalContext
->IsConIn
= BmmData
->ConsoleInCheck
[Index
+ ConsoleInpMenu
.MenuNumber
];
598 if (StrCmp (ConsoleName
, L
"ConOut") == 0) {
599 for (Index
= 0; Index
< ConsoleOutMenu
.MenuNumber
; Index
++){
600 NewMenuEntry
= BOpt_GetMenuEntry(&ConsoleOutMenu
, Index
);
601 NewConsoleContext
= (BM_CONSOLE_CONTEXT
*)NewMenuEntry
->VariableContext
;
602 ASSERT (Index
< MAX_MENU_NUMBER
);
603 NewConsoleContext
->IsActive
= BmmData
->ConsoleOutCheck
[Index
];
605 for (Index
= 0; Index
< TerminalMenu
.MenuNumber
; Index
++) {
606 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, Index
);
607 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
608 ASSERT (Index
+ ConsoleOutMenu
.MenuNumber
< MAX_MENU_NUMBER
);
609 NewTerminalContext
->IsConOut
= BmmData
->ConsoleOutCheck
[Index
+ ConsoleOutMenu
.MenuNumber
];
612 if (StrCmp (ConsoleName
, L
"ErrOut") == 0) {
613 for (Index
= 0; Index
< ConsoleErrMenu
.MenuNumber
; Index
++){
614 NewMenuEntry
= BOpt_GetMenuEntry(&ConsoleErrMenu
, Index
);
615 NewConsoleContext
= (BM_CONSOLE_CONTEXT
*)NewMenuEntry
->VariableContext
;
616 ASSERT (Index
< MAX_MENU_NUMBER
);
617 NewConsoleContext
->IsActive
= BmmData
->ConsoleErrCheck
[Index
];
619 for (Index
= 0; Index
< TerminalMenu
.MenuNumber
; Index
++) {
620 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, Index
);
621 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
622 ASSERT (Index
+ ConsoleErrMenu
.MenuNumber
< MAX_MENU_NUMBER
);
623 NewTerminalContext
->IsStdErr
= BmmData
->ConsoleErrCheck
[Index
+ ConsoleErrMenu
.MenuNumber
];
629 This function allows a caller to extract the current configuration for one
630 or more named elements from the target driver.
632 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
633 @param Request A null-terminated Unicode string in <ConfigRequest> format.
634 @param Progress On return, points to a character in the Request string.
635 Points to the string's null terminator if request was successful.
636 Points to the most recent '&' before the first failing name/value
637 pair (or the beginning of the string if the failure is in the
638 first name/value pair) if the request was not successful.
639 @param Results A null-terminated Unicode string in <ConfigAltResp> format which
640 has all values filled in for the names in the Request string.
641 String to be allocated by the called function.
643 @retval EFI_SUCCESS The Results is filled with the requested values.
644 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
645 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
646 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
651 BootMaintExtractConfig (
652 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
653 IN CONST EFI_STRING Request
,
654 OUT EFI_STRING
*Progress
,
655 OUT EFI_STRING
*Results
660 BMM_CALLBACK_DATA
*Private
;
661 EFI_STRING ConfigRequestHdr
;
662 EFI_STRING ConfigRequest
;
663 BOOLEAN AllocatedRequest
;
666 if (Progress
== NULL
|| Results
== NULL
) {
667 return EFI_INVALID_PARAMETER
;
671 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &mBootMaintGuid
, mBootMaintStorageName
)) {
672 return EFI_NOT_FOUND
;
675 ConfigRequestHdr
= NULL
;
676 ConfigRequest
= NULL
;
677 AllocatedRequest
= FALSE
;
680 Private
= BMM_CALLBACK_DATA_FROM_THIS (This
);
682 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
684 BufferSize
= sizeof (BMM_FAKE_NV_DATA
);
685 ConfigRequest
= Request
;
686 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
688 // Request has no request element, construct full request string.
689 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
690 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
692 ConfigRequestHdr
= HiiConstructConfigHdr (&mBootMaintGuid
, mBootMaintStorageName
, Private
->BmmDriverHandle
);
693 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
694 ConfigRequest
= AllocateZeroPool (Size
);
695 ASSERT (ConfigRequest
!= NULL
);
696 AllocatedRequest
= TRUE
;
697 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
698 FreePool (ConfigRequestHdr
);
701 Status
= gHiiConfigRouting
->BlockToConfig (
704 (UINT8
*) &Private
->BmmFakeNvData
,
710 // Free the allocated config request string.
712 if (AllocatedRequest
) {
713 FreePool (ConfigRequest
);
714 ConfigRequest
= NULL
;
717 // Set Progress string to the original request string.
719 if (Request
== NULL
) {
721 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
722 *Progress
= Request
+ StrLen (Request
);
729 This function applies changes in a driver's configuration.
730 Input is a Configuration, which has the routing data for this
731 driver followed by name / value configuration pairs. The driver
732 must apply those pairs to its configurable storage. If the
733 driver's configuration is stored in a linear block of data
734 and the driver's name / value pairs are in <BlockConfig>
735 format, it may use the ConfigToBlock helper function (above) to
736 simplify the job. Currently not implemented.
738 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
739 @param[in] Configuration A null-terminated Unicode string in
740 <ConfigString> format.
741 @param[out] Progress A pointer to a string filled in with the
742 offset of the most recent '&' before the
743 first failing name / value pair (or the
744 beginn ing of the string if the failure
745 is in the first name / value pair) or
746 the terminating NULL if all was
749 @retval EFI_SUCCESS The results have been distributed or are
750 awaiting distribution.
751 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
752 parts of the results that must be
753 stored awaiting possible future
755 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
756 Results parameter would result
757 in this type of error.
758 @retval EFI_NOT_FOUND Target for the specified routing data
763 BootMaintRouteConfig (
764 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
765 IN CONST EFI_STRING Configuration
,
766 OUT EFI_STRING
*Progress
771 EFI_HII_CONFIG_ROUTING_PROTOCOL
*ConfigRouting
;
772 BMM_FAKE_NV_DATA
*NewBmmData
;
773 BMM_FAKE_NV_DATA
*OldBmmData
;
774 BM_MENU_ENTRY
*NewMenuEntry
;
775 BM_LOAD_CONTEXT
*NewLoadContext
;
777 BOOLEAN TerminalAttChange
;
778 BMM_CALLBACK_DATA
*Private
;
781 if (Progress
== NULL
) {
782 return EFI_INVALID_PARAMETER
;
784 *Progress
= Configuration
;
786 if (Configuration
== NULL
) {
787 return EFI_INVALID_PARAMETER
;
791 // Check routing data in <ConfigHdr>.
792 // Note: there is no name for Name/Value storage, only GUID will be checked
794 if (!HiiIsConfigHdrMatch (Configuration
, &mBootMaintGuid
, mBootMaintStorageName
)) {
795 return EFI_NOT_FOUND
;
798 Status
= gBS
->LocateProtocol (
799 &gEfiHiiConfigRoutingProtocolGuid
,
801 (VOID
**)&ConfigRouting
803 if (EFI_ERROR (Status
)) {
807 Private
= BMM_CALLBACK_DATA_FROM_THIS (This
);
809 // Get Buffer Storage data from EFI variable
811 BufferSize
= sizeof (BMM_FAKE_NV_DATA
);
812 OldBmmData
= &Private
->BmmOldFakeNVData
;
813 NewBmmData
= &Private
->BmmFakeNvData
;
816 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
818 Status
= ConfigRouting
->ConfigToBlock (
821 (UINT8
*) NewBmmData
,
825 ASSERT_EFI_ERROR (Status
);
827 // Compare new and old BMM configuration data and only do action for modified item to
828 // avoid setting unnecessary non-volatile variable
832 // Check data which located in BMM main page and save the settings if need
834 if (CompareMem (&NewBmmData
->BootNext
, &OldBmmData
->BootNext
, sizeof (NewBmmData
->BootNext
)) != 0) {
835 Status
= Var_UpdateBootNext (Private
);
836 if (EFI_ERROR (Status
)) {
837 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, BootNext
);
843 // Check data which located in Boot Options Menu and save the settings if need
845 if (CompareMem (NewBmmData
->BootOptionDel
, OldBmmData
->BootOptionDel
, sizeof (NewBmmData
->BootOptionDel
)) != 0) {
847 ((Index
< BootOptionMenu
.MenuNumber
) && (Index
< (sizeof (NewBmmData
->BootOptionDel
) / sizeof (NewBmmData
->BootOptionDel
[0]))));
849 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index
);
850 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
851 NewLoadContext
->Deleted
= NewBmmData
->BootOptionDel
[Index
];
852 NewBmmData
->BootOptionDel
[Index
] = FALSE
;
853 NewBmmData
->BootOptionDelMark
[Index
] = FALSE
;
856 Status
= Var_DelBootOption ();
857 if (EFI_ERROR (Status
)) {
858 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, BootOptionDel
);
863 if (CompareMem (NewBmmData
->BootOptionOrder
, OldBmmData
->BootOptionOrder
, sizeof (NewBmmData
->BootOptionOrder
)) != 0) {
864 Status
= Var_UpdateBootOrder (Private
);
865 if (EFI_ERROR (Status
)) {
866 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, BootOptionOrder
);
871 if (CompareMem (&NewBmmData
->BootTimeOut
, &OldBmmData
->BootTimeOut
, sizeof (NewBmmData
->BootTimeOut
)) != 0){
872 Status
= gRT
->SetVariable(
874 &gEfiGlobalVariableGuid
,
875 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
877 &(NewBmmData
->BootTimeOut
)
879 if (EFI_ERROR (Status
)) {
880 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, BootTimeOut
);
883 Private
->BmmOldFakeNVData
.BootTimeOut
= NewBmmData
->BootTimeOut
;
887 // Check data which located in Driver Options Menu and save the settings if need
889 if (CompareMem (NewBmmData
->DriverOptionDel
, OldBmmData
->DriverOptionDel
, sizeof (NewBmmData
->DriverOptionDel
)) != 0) {
891 ((Index
< DriverOptionMenu
.MenuNumber
) && (Index
< (sizeof (NewBmmData
->DriverOptionDel
) / sizeof (NewBmmData
->DriverOptionDel
[0]))));
893 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, Index
);
894 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
895 NewLoadContext
->Deleted
= NewBmmData
->DriverOptionDel
[Index
];
896 NewBmmData
->DriverOptionDel
[Index
] = FALSE
;
897 NewBmmData
->DriverOptionDelMark
[Index
] = FALSE
;
899 Status
= Var_DelDriverOption ();
900 if (EFI_ERROR (Status
)) {
901 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, DriverOptionDel
);
906 if (CompareMem (NewBmmData
->DriverOptionOrder
, OldBmmData
->DriverOptionOrder
, sizeof (NewBmmData
->DriverOptionOrder
)) != 0) {
907 Status
= Var_UpdateDriverOrder (Private
);
908 if (EFI_ERROR (Status
)) {
909 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, DriverOptionOrder
);
914 if (CompareMem (&NewBmmData
->ConsoleOutMode
, &OldBmmData
->ConsoleOutMode
, sizeof (NewBmmData
->ConsoleOutMode
)) != 0){
915 Status
= Var_UpdateConMode(Private
);
916 if (EFI_ERROR (Status
)) {
917 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, ConsoleOutMode
);
922 TerminalAttChange
= FALSE
;
923 for (Index
= 0; Index
< TerminalMenu
.MenuNumber
; Index
++) {
926 // only need update modified items
928 if (CompareMem (&NewBmmData
->COMBaudRate
[Index
], &OldBmmData
->COMBaudRate
[Index
], sizeof (NewBmmData
->COMBaudRate
[Index
])) == 0 &&
929 CompareMem (&NewBmmData
->COMDataRate
[Index
], &OldBmmData
->COMDataRate
[Index
], sizeof (NewBmmData
->COMDataRate
[Index
])) == 0 &&
930 CompareMem (&NewBmmData
->COMStopBits
[Index
], &OldBmmData
->COMStopBits
[Index
], sizeof (NewBmmData
->COMStopBits
[Index
])) == 0 &&
931 CompareMem (&NewBmmData
->COMParity
[Index
], &OldBmmData
->COMParity
[Index
], sizeof (NewBmmData
->COMParity
[Index
])) == 0 &&
932 CompareMem (&NewBmmData
->COMTerminalType
[Index
], &OldBmmData
->COMTerminalType
[Index
], sizeof (NewBmmData
->COMTerminalType
[Index
])) == 0 &&
933 CompareMem (&NewBmmData
->COMFlowControl
[Index
], &OldBmmData
->COMFlowControl
[Index
], sizeof (NewBmmData
->COMFlowControl
[Index
])) == 0) {
937 TerminalAttChange
= TRUE
;
939 if (TerminalAttChange
) {
940 if (CompareMem (&NewBmmData
->COMBaudRate
[Index
], &OldBmmData
->COMBaudRate
[Index
], sizeof (NewBmmData
->COMBaudRate
[Index
])) != 0) {
941 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, COMBaudRate
);
942 } else if (CompareMem (&NewBmmData
->COMDataRate
[Index
], &OldBmmData
->COMDataRate
[Index
], sizeof (NewBmmData
->COMDataRate
[Index
])) != 0) {
943 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, COMDataRate
);
944 } else if (CompareMem (&NewBmmData
->COMStopBits
[Index
], &OldBmmData
->COMStopBits
[Index
], sizeof (NewBmmData
->COMStopBits
[Index
])) != 0) {
945 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, COMStopBits
);
946 } else if (CompareMem (&NewBmmData
->COMParity
[Index
], &OldBmmData
->COMParity
[Index
], sizeof (NewBmmData
->COMParity
[Index
])) != 0) {
947 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, COMParity
);
948 } else if (CompareMem (&NewBmmData
->COMTerminalType
[Index
], &OldBmmData
->COMTerminalType
[Index
], sizeof (NewBmmData
->COMTerminalType
[Index
])) != 0) {
949 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, COMTerminalType
);
950 } else if (CompareMem (&NewBmmData
->COMFlowControl
[Index
], &OldBmmData
->COMFlowControl
[Index
], sizeof (NewBmmData
->COMFlowControl
[Index
])) != 0) {
951 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, COMFlowControl
);
953 Status
= Var_UpdateConsoleInpOption ();
954 if (EFI_ERROR (Status
)) {
957 Status
= Var_UpdateConsoleOutOption ();
958 if (EFI_ERROR (Status
)) {
961 Status
= Var_UpdateErrorOutOption ();
962 if (EFI_ERROR (Status
)) {
967 // Check data which located in Console Options Menu and save the settings if need
969 if (CompareMem (NewBmmData
->ConsoleInCheck
, OldBmmData
->ConsoleInCheck
, sizeof (NewBmmData
->ConsoleInCheck
)) != 0){
970 Status
= Var_UpdateConsoleInpOption();
971 if (EFI_ERROR (Status
)) {
972 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, ConsoleInCheck
);
977 if (CompareMem (NewBmmData
->ConsoleOutCheck
, OldBmmData
->ConsoleOutCheck
, sizeof (NewBmmData
->ConsoleOutCheck
)) != 0){
978 Status
= Var_UpdateConsoleOutOption();
979 if (EFI_ERROR (Status
)) {
980 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, ConsoleOutCheck
);
985 if (CompareMem (NewBmmData
->ConsoleErrCheck
, OldBmmData
->ConsoleErrCheck
, sizeof (NewBmmData
->ConsoleErrCheck
)) != 0){
986 Status
= Var_UpdateErrorOutOption();
987 if (EFI_ERROR (Status
)) {
988 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, ConsoleErrCheck
);
993 if (CompareMem (NewBmmData
->BootDescriptionData
, OldBmmData
->BootDescriptionData
, sizeof (NewBmmData
->BootDescriptionData
)) != 0 ||
994 CompareMem (NewBmmData
->BootOptionalData
, OldBmmData
->BootOptionalData
, sizeof (NewBmmData
->BootOptionalData
)) != 0) {
995 Status
= Var_UpdateBootOption (Private
);
996 NewBmmData
->BootOptionChanged
= FALSE
;
997 if (EFI_ERROR (Status
)) {
998 if (CompareMem (NewBmmData
->BootDescriptionData
, OldBmmData
->BootDescriptionData
, sizeof (NewBmmData
->BootDescriptionData
)) != 0) {
999 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, BootDescriptionData
);
1001 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, BootOptionalData
);
1005 BOpt_GetBootOptions (Private
);
1008 if (CompareMem (NewBmmData
->DriverDescriptionData
, OldBmmData
->DriverDescriptionData
, sizeof (NewBmmData
->DriverDescriptionData
)) != 0 ||
1009 CompareMem (NewBmmData
->DriverOptionalData
, OldBmmData
->DriverOptionalData
, sizeof (NewBmmData
->DriverOptionalData
)) != 0) {
1010 Status
= Var_UpdateDriverOption (
1012 Private
->BmmHiiHandle
,
1013 NewBmmData
->DriverDescriptionData
,
1014 NewBmmData
->DriverOptionalData
,
1015 NewBmmData
->ForceReconnect
1017 NewBmmData
->DriverOptionChanged
= FALSE
;
1018 NewBmmData
->ForceReconnect
= TRUE
;
1019 if (EFI_ERROR (Status
)) {
1020 if (CompareMem (NewBmmData
->DriverDescriptionData
, OldBmmData
->DriverDescriptionData
, sizeof (NewBmmData
->DriverDescriptionData
)) != 0) {
1021 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, DriverDescriptionData
);
1023 Offset
= OFFSET_OF (BMM_FAKE_NV_DATA
, DriverOptionalData
);
1028 BOpt_GetDriverOptions (Private
);
1032 // After user do the save action, need to update OldBmmData.
1034 CopyMem (OldBmmData
, NewBmmData
, sizeof (BMM_FAKE_NV_DATA
));
1040 // Fail to save the data, update the progress string.
1042 *Progress
= UpdateProgress (Offset
, Configuration
);
1043 if (Status
== EFI_OUT_OF_RESOURCES
) {
1046 return EFI_NOT_FOUND
;
1051 This function processes the results of changes in configuration.
1054 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1055 @param Action Specifies the type of action taken by the browser.
1056 @param QuestionId A unique value which is sent to the original exporting driver
1057 so that it can identify the type of data to expect.
1058 @param Type The type of value for the question.
1059 @param Value A pointer to the data being sent to the original exporting driver.
1060 @param ActionRequest On return, points to the action requested by the callback function.
1062 @retval EFI_SUCCESS The callback successfully handled the action.
1063 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
1064 @retval EFI_DEVICE_ERROR The variable could not be saved.
1065 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.
1066 @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid.
1071 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1072 IN EFI_BROWSER_ACTION Action
,
1073 IN EFI_QUESTION_ID QuestionId
,
1075 IN EFI_IFR_TYPE_VALUE
*Value
,
1076 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
1079 BMM_CALLBACK_DATA
*Private
;
1080 BM_MENU_ENTRY
*NewMenuEntry
;
1081 BMM_FAKE_NV_DATA
*CurrentFakeNVMap
;
1082 BMM_FAKE_NV_DATA
*OldFakeNVMap
;
1084 EFI_DEVICE_PATH_PROTOCOL
* File
;
1086 if (Action
!= EFI_BROWSER_ACTION_CHANGING
&& Action
!= EFI_BROWSER_ACTION_CHANGED
&& Action
!= EFI_BROWSER_ACTION_FORM_OPEN
) {
1088 // Do nothing for other UEFI Action. Only do call back when data is changed or the form is open.
1090 return EFI_UNSUPPORTED
;
1093 Private
= BMM_CALLBACK_DATA_FROM_THIS (This
);
1095 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
1096 if (QuestionId
== KEY_VALUE_TRIGGER_FORM_OPEN_ACTION
) {
1097 if (!mFirstEnterBMMForm
) {
1099 // BMMUiLib depends on LegacyUi library to show legacy menus.
1100 // If we want to show Legacy menus correctly in BMM page,
1101 // we must do it after the LegacyUi library has already been initialized.
1102 // Opening the BMM form is the appropriate time that the LegacyUi library has already been initialized.
1103 // So we do the tasks which are related to legacy menus here.
1104 // 1. Update the menus (including legacy munu) show in BootMiantenanceManager page.
1105 // 2. Re-scan the BootOption menus (including the legacy boot option).
1108 EfiBootManagerRefreshAllBootOption ();
1109 BOpt_GetBootOptions (Private
);
1110 mFirstEnterBMMForm
= TRUE
;
1115 // Retrieve uncommitted data from Form Browser
1117 CurrentFakeNVMap
= &Private
->BmmFakeNvData
;
1118 OldFakeNVMap
= &Private
->BmmOldFakeNVData
;
1119 HiiGetBrowserData (&mBootMaintGuid
, mBootMaintStorageName
, sizeof (BMM_FAKE_NV_DATA
), (UINT8
*) CurrentFakeNVMap
);
1121 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
1122 if (Value
== NULL
) {
1123 return EFI_INVALID_PARAMETER
;
1126 UpdatePageId (Private
, QuestionId
);
1128 if (QuestionId
< FILE_OPTION_OFFSET
) {
1129 if (QuestionId
< CONFIG_OPTION_OFFSET
) {
1130 switch (QuestionId
) {
1131 case FORM_BOOT_ADD_ID
:
1132 // Leave BMM and enter FileExplorer.
1133 ChooseFile (NULL
, L
".efi", CreateBootOptionFromFile
, &File
);
1136 case FORM_DRV_ADD_FILE_ID
:
1137 // Leave BMM and enter FileExplorer.
1138 ChooseFile (NULL
, L
".efi", CreateDriverOptionFromFile
, &File
);
1141 case FORM_DRV_ADD_HANDLE_ID
:
1142 CleanUpPage (FORM_DRV_ADD_HANDLE_ID
, Private
);
1143 UpdateDrvAddHandlePage (Private
);
1146 case FORM_BOOT_DEL_ID
:
1147 CleanUpPage (FORM_BOOT_DEL_ID
, Private
);
1148 UpdateBootDelPage (Private
);
1151 case FORM_BOOT_CHG_ID
:
1152 case FORM_DRV_CHG_ID
:
1153 UpdatePageBody (QuestionId
, Private
);
1156 case FORM_DRV_DEL_ID
:
1157 CleanUpPage (FORM_DRV_DEL_ID
, Private
);
1158 UpdateDrvDelPage (Private
);
1161 case FORM_CON_IN_ID
:
1162 case FORM_CON_OUT_ID
:
1163 case FORM_CON_ERR_ID
:
1164 UpdatePageBody (QuestionId
, Private
);
1167 case FORM_CON_MODE_ID
:
1168 CleanUpPage (FORM_CON_MODE_ID
, Private
);
1169 UpdateConModePage (Private
);
1172 case FORM_CON_COM_ID
:
1173 CleanUpPage (FORM_CON_COM_ID
, Private
);
1174 UpdateConCOMPage (Private
);
1180 } else if ((QuestionId
>= TERMINAL_OPTION_OFFSET
) && (QuestionId
< CONSOLE_OPTION_OFFSET
)) {
1181 Index
= (UINT16
) (QuestionId
- TERMINAL_OPTION_OFFSET
);
1182 Private
->CurrentTerminal
= Index
;
1184 CleanUpPage (FORM_CON_COM_SETUP_ID
, Private
);
1185 UpdateTerminalPage (Private
);
1187 } else if (QuestionId
>= HANDLE_OPTION_OFFSET
) {
1188 Index
= (UINT16
) (QuestionId
- HANDLE_OPTION_OFFSET
);
1190 NewMenuEntry
= BOpt_GetMenuEntry (&DriverMenu
, Index
);
1191 ASSERT (NewMenuEntry
!= NULL
);
1192 Private
->HandleContext
= (BM_HANDLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
1194 CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID
, Private
);
1196 Private
->MenuEntry
= NewMenuEntry
;
1197 Private
->LoadContext
->FilePathList
= Private
->HandleContext
->DevicePath
;
1199 UpdateDriverAddHandleDescPage (Private
);
1202 if (QuestionId
== KEY_VALUE_BOOT_FROM_FILE
){
1203 // Leave BMM and enter FileExplorer.
1204 ChooseFile (NULL
, L
".efi", BootFromFile
, &File
);
1206 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
1207 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
1208 return EFI_INVALID_PARAMETER
;
1211 if (QuestionId
== KEY_VALUE_SAVE_AND_EXIT_BOOT
) {
1212 CleanUselessBeforeSubmit (Private
);
1213 CurrentFakeNVMap
->BootOptionChanged
= FALSE
;
1214 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
1215 } else if (QuestionId
== KEY_VALUE_SAVE_AND_EXIT_DRIVER
) {
1216 CleanUselessBeforeSubmit (Private
);
1217 CurrentFakeNVMap
->DriverOptionChanged
= FALSE
;
1218 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
1219 } else if (QuestionId
== KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER
) {
1221 // Discard changes and exit formset
1223 ZeroMem (CurrentFakeNVMap
->DriverOptionalData
, sizeof (CurrentFakeNVMap
->DriverOptionalData
));
1224 ZeroMem (CurrentFakeNVMap
->BootDescriptionData
, sizeof (CurrentFakeNVMap
->BootDescriptionData
));
1225 ZeroMem (OldFakeNVMap
->DriverOptionalData
, sizeof (OldFakeNVMap
->DriverOptionalData
));
1226 ZeroMem (OldFakeNVMap
->DriverDescriptionData
, sizeof (OldFakeNVMap
->DriverDescriptionData
));
1227 CurrentFakeNVMap
->DriverOptionChanged
= FALSE
;
1228 CurrentFakeNVMap
->ForceReconnect
= TRUE
;
1229 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
1230 } else if (QuestionId
== KEY_VALUE_NO_SAVE_AND_EXIT_BOOT
) {
1232 // Discard changes and exit formset
1234 ZeroMem (CurrentFakeNVMap
->BootOptionalData
, sizeof (CurrentFakeNVMap
->BootOptionalData
));
1235 ZeroMem (CurrentFakeNVMap
->BootDescriptionData
, sizeof (CurrentFakeNVMap
->BootDescriptionData
));
1236 ZeroMem (OldFakeNVMap
->BootOptionalData
, sizeof (OldFakeNVMap
->BootOptionalData
));
1237 ZeroMem (OldFakeNVMap
->BootDescriptionData
, sizeof (OldFakeNVMap
->BootDescriptionData
));
1238 CurrentFakeNVMap
->BootOptionChanged
= FALSE
;
1239 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
1240 } else if (QuestionId
== KEY_VALUE_BOOT_DESCRIPTION
|| QuestionId
== KEY_VALUE_BOOT_OPTION
) {
1241 CurrentFakeNVMap
->BootOptionChanged
= TRUE
;
1242 } else if (QuestionId
== KEY_VALUE_DRIVER_DESCRIPTION
|| QuestionId
== KEY_VALUE_DRIVER_OPTION
) {
1243 CurrentFakeNVMap
->DriverOptionChanged
= TRUE
;
1246 if ((QuestionId
>= BOOT_OPTION_DEL_QUESTION_ID
) && (QuestionId
< BOOT_OPTION_DEL_QUESTION_ID
+ MAX_MENU_NUMBER
)) {
1249 // Means user try to delete this boot option but not press F10 or "Commit Changes and Exit" menu.
1251 CurrentFakeNVMap
->BootOptionDelMark
[QuestionId
- BOOT_OPTION_DEL_QUESTION_ID
] = TRUE
;
1254 // Means user remove the old check status.
1256 CurrentFakeNVMap
->BootOptionDelMark
[QuestionId
- BOOT_OPTION_DEL_QUESTION_ID
] = FALSE
;
1258 } else if ((QuestionId
>= DRIVER_OPTION_DEL_QUESTION_ID
) && (QuestionId
< DRIVER_OPTION_DEL_QUESTION_ID
+ MAX_MENU_NUMBER
)) {
1260 CurrentFakeNVMap
->DriverOptionDelMark
[QuestionId
- DRIVER_OPTION_DEL_QUESTION_ID
] = TRUE
;
1262 CurrentFakeNVMap
->DriverOptionDelMark
[QuestionId
- DRIVER_OPTION_DEL_QUESTION_ID
] = FALSE
;
1265 switch (QuestionId
) {
1266 case KEY_VALUE_SAVE_AND_EXIT
:
1267 case KEY_VALUE_NO_SAVE_AND_EXIT
:
1268 if (QuestionId
== KEY_VALUE_SAVE_AND_EXIT
) {
1269 CleanUselessBeforeSubmit (Private
);
1270 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
1271 } else if (QuestionId
== KEY_VALUE_NO_SAVE_AND_EXIT
) {
1272 DiscardChangeHandler (Private
, CurrentFakeNVMap
);
1273 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
1279 gRT
->ResetSystem (EfiResetCold
, EFI_SUCCESS
, 0, NULL
);
1280 return EFI_UNSUPPORTED
;
1287 // Update the content in Terminal menu and Console menu here.
1289 if (QuestionId
== COM_BAUD_RATE_QUESTION_ID
+ Private
->CurrentTerminal
|| QuestionId
== COM_DATA_RATE_QUESTION_ID
+ Private
->CurrentTerminal
||
1290 QuestionId
== COM_PARITY_QUESTION_ID
+ Private
->CurrentTerminal
|| QuestionId
== COM_STOP_BITS_QUESTION_ID
+ Private
->CurrentTerminal
||
1291 QuestionId
== COM_TERMINAL_QUESTION_ID
+ Private
->CurrentTerminal
|| QuestionId
== COM_FLOWCONTROL_QUESTION_ID
+ Private
->CurrentTerminal
1293 UpdateTerminalContent(CurrentFakeNVMap
);
1295 if ((QuestionId
>= CON_IN_DEVICE_QUESTION_ID
) && (QuestionId
< CON_IN_DEVICE_QUESTION_ID
+ MAX_MENU_NUMBER
)) {
1296 UpdateConsoleContent (L
"ConIn",CurrentFakeNVMap
);
1297 } else if ((QuestionId
>= CON_OUT_DEVICE_QUESTION_ID
) && (QuestionId
< CON_OUT_DEVICE_QUESTION_ID
+ MAX_MENU_NUMBER
)) {
1298 UpdateConsoleContent (L
"ConOut", CurrentFakeNVMap
);
1299 } else if ((QuestionId
>= CON_ERR_DEVICE_QUESTION_ID
) && (QuestionId
< CON_ERR_DEVICE_QUESTION_ID
+ MAX_MENU_NUMBER
)) {
1300 UpdateConsoleContent (L
"ErrOut", CurrentFakeNVMap
);
1305 // Pass changed uncommitted data back to Form Browser
1307 HiiSetBrowserData (&mBootMaintGuid
, mBootMaintStorageName
, sizeof (BMM_FAKE_NV_DATA
), (UINT8
*) CurrentFakeNVMap
, NULL
);
1313 Discard all changes done to the BMM pages such as Boot Order change,
1314 Driver order change.
1316 @param Private The BMM context data.
1317 @param CurrentFakeNVMap The current Fack NV Map.
1321 DiscardChangeHandler (
1322 IN BMM_CALLBACK_DATA
*Private
,
1323 IN BMM_FAKE_NV_DATA
*CurrentFakeNVMap
1328 switch (Private
->BmmPreviousPageId
) {
1329 case FORM_BOOT_CHG_ID
:
1330 CopyMem (CurrentFakeNVMap
->BootOptionOrder
, Private
->BmmOldFakeNVData
.BootOptionOrder
, sizeof (CurrentFakeNVMap
->BootOptionOrder
));
1333 case FORM_DRV_CHG_ID
:
1334 CopyMem (CurrentFakeNVMap
->DriverOptionOrder
, Private
->BmmOldFakeNVData
.DriverOptionOrder
, sizeof (CurrentFakeNVMap
->DriverOptionOrder
));
1337 case FORM_BOOT_DEL_ID
:
1338 ASSERT (BootOptionMenu
.MenuNumber
<= (sizeof (CurrentFakeNVMap
->BootOptionDel
) / sizeof (CurrentFakeNVMap
->BootOptionDel
[0])));
1339 for (Index
= 0; Index
< BootOptionMenu
.MenuNumber
; Index
++) {
1340 CurrentFakeNVMap
->BootOptionDel
[Index
] = FALSE
;
1344 case FORM_DRV_DEL_ID
:
1345 ASSERT (DriverOptionMenu
.MenuNumber
<= (sizeof (CurrentFakeNVMap
->DriverOptionDel
) / sizeof (CurrentFakeNVMap
->DriverOptionDel
[0])));
1346 for (Index
= 0; Index
< DriverOptionMenu
.MenuNumber
; Index
++) {
1347 CurrentFakeNVMap
->DriverOptionDel
[Index
] = FALSE
;
1351 case FORM_BOOT_NEXT_ID
:
1352 CurrentFakeNVMap
->BootNext
= Private
->BmmOldFakeNVData
.BootNext
;
1355 case FORM_TIME_OUT_ID
:
1356 CurrentFakeNVMap
->BootTimeOut
= Private
->BmmOldFakeNVData
.BootTimeOut
;
1359 case FORM_DRV_ADD_HANDLE_DESC_ID
:
1360 case FORM_DRV_ADD_FILE_ID
:
1361 case FORM_DRV_ADD_HANDLE_ID
:
1362 CurrentFakeNVMap
->DriverAddHandleDesc
[0] = 0x0000;
1363 CurrentFakeNVMap
->DriverAddHandleOptionalData
[0] = 0x0000;
1372 This function is to clean some useless data before submit changes.
1374 @param Private The BMM context data.
1378 CleanUselessBeforeSubmit (
1379 IN BMM_CALLBACK_DATA
*Private
1383 if (Private
->BmmPreviousPageId
!= FORM_BOOT_DEL_ID
) {
1384 for (Index
= 0; Index
< BootOptionMenu
.MenuNumber
; Index
++) {
1385 if (Private
->BmmFakeNvData
.BootOptionDel
[Index
] && !Private
->BmmFakeNvData
.BootOptionDelMark
[Index
]) {
1386 Private
->BmmFakeNvData
.BootOptionDel
[Index
] = FALSE
;
1387 Private
->BmmOldFakeNVData
.BootOptionDel
[Index
] = FALSE
;
1391 if (Private
->BmmPreviousPageId
!= FORM_DRV_DEL_ID
) {
1392 for (Index
= 0; Index
< DriverOptionMenu
.MenuNumber
; Index
++) {
1393 if (Private
->BmmFakeNvData
.DriverOptionDel
[Index
] && !Private
->BmmFakeNvData
.DriverOptionDelMark
[Index
]) {
1394 Private
->BmmFakeNvData
.DriverOptionDel
[Index
] = FALSE
;
1395 Private
->BmmOldFakeNVData
.DriverOptionDel
[Index
] = FALSE
;
1403 Update the menus in the BMM page.
1411 VOID
*StartOpCodeHandle
;
1412 VOID
*EndOpCodeHandle
;
1413 EFI_IFR_GUID_LABEL
*StartGuidLabel
;
1414 EFI_IFR_GUID_LABEL
*EndGuidLabel
;
1417 // Allocate space for creation of UpdateData Buffer
1419 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1420 ASSERT (StartOpCodeHandle
!= NULL
);
1422 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1423 ASSERT (EndOpCodeHandle
!= NULL
);
1425 // Create Hii Extend Label OpCode as the start opcode
1427 StartGuidLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1428 StartGuidLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1429 StartGuidLabel
->Number
= LABEL_FORM_MAIN_START
;
1431 // Create Hii Extend Label OpCode as the end opcode
1433 EndGuidLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1434 EndGuidLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1435 EndGuidLabel
->Number
= LABEL_FORM_MAIN_END
;
1438 //Updata Front Page form
1440 UiCustomizeBMMPage (
1441 mBmmCallbackInfo
->BmmHiiHandle
,
1446 mBmmCallbackInfo
->BmmHiiHandle
,
1453 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1454 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1458 Create dynamic code for BMM and initialize all of BMM configuration data in BmmFakeNvData and
1459 BmmOldFakeNVData member in BMM context data.
1461 @param CallbackData The BMM context data.
1465 InitializeBmmConfig (
1466 IN BMM_CALLBACK_DATA
*CallbackData
1469 BM_MENU_ENTRY
*NewMenuEntry
;
1470 BM_LOAD_CONTEXT
*NewLoadContext
;
1473 ASSERT (CallbackData
!= NULL
);
1476 // Initialize data which located in BMM main page
1478 CallbackData
->BmmFakeNvData
.BootNext
= NONE_BOOTNEXT_VALUE
;
1479 for (Index
= 0; Index
< BootOptionMenu
.MenuNumber
; Index
++) {
1480 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index
);
1481 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
1483 if (NewLoadContext
->IsBootNext
) {
1484 CallbackData
->BmmFakeNvData
.BootNext
= Index
;
1489 CallbackData
->BmmFakeNvData
.BootTimeOut
= PcdGet16 (PcdPlatformBootTimeOut
);
1492 // Initialize data which located in Boot Options Menu
1494 GetBootOrder (CallbackData
);
1497 // Initialize data which located in Driver Options Menu
1499 GetDriverOrder (CallbackData
);
1502 // Initialize data which located in Console Options Menu
1504 GetConsoleOutMode (CallbackData
);
1505 GetConsoleInCheck (CallbackData
);
1506 GetConsoleOutCheck (CallbackData
);
1507 GetConsoleErrCheck (CallbackData
);
1508 GetTerminalAttribute (CallbackData
);
1510 CallbackData
->BmmFakeNvData
.ForceReconnect
= TRUE
;
1513 // Backup Initialize BMM configuartion data to BmmOldFakeNVData
1515 CopyMem (&CallbackData
->BmmOldFakeNVData
, &CallbackData
->BmmFakeNvData
, sizeof (BMM_FAKE_NV_DATA
));
1519 Initialized all Menu Option List.
1521 @param CallbackData The BMM context data.
1526 IN BMM_CALLBACK_DATA
*CallbackData
1529 InitializeListHead (&BootOptionMenu
.Head
);
1530 InitializeListHead (&DriverOptionMenu
.Head
);
1531 BOpt_GetBootOptions (CallbackData
);
1532 BOpt_GetDriverOptions (CallbackData
);
1533 BOpt_FindDrivers ();
1534 InitializeListHead (&ConsoleInpMenu
.Head
);
1535 InitializeListHead (&ConsoleOutMenu
.Head
);
1536 InitializeListHead (&ConsoleErrMenu
.Head
);
1537 InitializeListHead (&TerminalMenu
.Head
);
1540 mAllMenuInit
= TRUE
;
1544 Free up all Menu Option list.
1555 BOpt_FreeMenu (&BootOptionMenu
);
1556 BOpt_FreeMenu (&DriverOptionMenu
);
1557 BOpt_FreeMenu (&DriverMenu
);
1559 mAllMenuInit
= FALSE
;
1563 Initial the boot mode related parameters.
1567 BmmInitialBootModeInfo (
1572 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1573 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOut
;
1574 UINTN BootTextColumn
;
1577 if (mBmmModeInitialized
) {
1582 // After the console is ready, get current video resolution
1583 // and text mode before launching setup at first time.
1585 Status
= gBS
->HandleProtocol (
1586 gST
->ConsoleOutHandle
,
1587 &gEfiGraphicsOutputProtocolGuid
,
1588 (VOID
**)&GraphicsOutput
1590 if (EFI_ERROR (Status
)) {
1591 GraphicsOutput
= NULL
;
1594 Status
= gBS
->HandleProtocol (
1595 gST
->ConsoleOutHandle
,
1596 &gEfiSimpleTextOutProtocolGuid
,
1597 (VOID
**)&SimpleTextOut
1599 if (EFI_ERROR (Status
)) {
1600 SimpleTextOut
= NULL
;
1603 if (GraphicsOutput
!= NULL
) {
1605 // Get current video resolution and text mode.
1607 mBmmBootHorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
1608 mBmmBootVerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
1611 if (SimpleTextOut
!= NULL
) {
1612 Status
= SimpleTextOut
->QueryMode (
1614 SimpleTextOut
->Mode
->Mode
,
1618 mBmmBootTextModeColumn
= (UINT32
)BootTextColumn
;
1619 mBmmBootTextModeRow
= (UINT32
)BootTextRow
;
1623 // Get user defined text mode for setup.
1625 mBmmSetupHorizontalResolution
= PcdGet32 (PcdSetupVideoHorizontalResolution
);
1626 mBmmSetupVerticalResolution
= PcdGet32 (PcdSetupVideoVerticalResolution
);
1627 mBmmSetupTextModeColumn
= PcdGet32 (PcdSetupConOutColumn
);
1628 mBmmSetupTextModeRow
= PcdGet32 (PcdSetupConOutRow
);
1630 mBmmModeInitialized
= TRUE
;
1635 Install Boot Maintenance Manager Menu driver.
1637 @param ImageHandle The image handle.
1638 @param SystemTable The system table.
1640 @retval EFI_SUCEESS Install Boot manager menu success.
1641 @retval Other Return error status.
1646 BootMaintenanceManagerUiLibConstructor (
1647 IN EFI_HANDLE ImageHandle
,
1648 IN EFI_SYSTEM_TABLE
*SystemTable
1655 Status
= EFI_SUCCESS
;
1658 // Install Device Path Protocol and Config Access protocol to driver handle
1660 Status
= gBS
->InstallMultipleProtocolInterfaces (
1661 &mBmmCallbackInfo
->BmmDriverHandle
,
1662 &gEfiDevicePathProtocolGuid
,
1663 &mBmmHiiVendorDevicePath
,
1664 &gEfiHiiConfigAccessProtocolGuid
,
1665 &mBmmCallbackInfo
->BmmConfigAccess
,
1668 ASSERT_EFI_ERROR (Status
);
1671 // Post our Boot Maint VFR binary to the HII database.
1673 mBmmCallbackInfo
->BmmHiiHandle
= HiiAddPackages (
1675 mBmmCallbackInfo
->BmmDriverHandle
,
1676 BootMaintenanceManagerBin
,
1677 BootMaintenanceManagerUiLibStrings
,
1680 ASSERT (mBmmCallbackInfo
->BmmHiiHandle
!= NULL
);
1683 // Locate Formbrowser2 protocol
1685 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**) &mBmmCallbackInfo
->FormBrowser2
);
1686 ASSERT_EFI_ERROR (Status
);
1689 // Create LoadOption in BmmCallbackInfo for Driver Callback
1691 Ptr
= AllocateZeroPool (sizeof (BM_LOAD_CONTEXT
) + sizeof (BM_FILE_CONTEXT
) + sizeof (BM_HANDLE_CONTEXT
) + sizeof (BM_MENU_ENTRY
));
1692 ASSERT (Ptr
!= NULL
);
1695 // Initialize Bmm callback data.
1697 mBmmCallbackInfo
->LoadContext
= (BM_LOAD_CONTEXT
*) Ptr
;
1698 Ptr
+= sizeof (BM_LOAD_CONTEXT
);
1700 mBmmCallbackInfo
->FileContext
= (BM_FILE_CONTEXT
*) Ptr
;
1701 Ptr
+= sizeof (BM_FILE_CONTEXT
);
1703 mBmmCallbackInfo
->HandleContext
= (BM_HANDLE_CONTEXT
*) Ptr
;
1704 Ptr
+= sizeof (BM_HANDLE_CONTEXT
);
1706 mBmmCallbackInfo
->MenuEntry
= (BM_MENU_ENTRY
*) Ptr
;
1708 mBmmCallbackInfo
->BmmPreviousPageId
= FORM_MAIN_ID
;
1709 mBmmCallbackInfo
->BmmCurrentPageId
= FORM_MAIN_ID
;
1711 InitAllMenu (mBmmCallbackInfo
);
1715 // Update boot maintenance manager page
1717 InitializeBmmConfig(mBmmCallbackInfo
);
1719 BmmInitialBootModeInfo();
1725 Unloads the application and its installed protocol.
1727 @param ImageHandle Handle that identifies the image to be unloaded.
1728 @param SystemTable The system table.
1730 @retval EFI_SUCCESS The image has been unloaded.
1735 BootMaintenanceManagerUiLibDestructor (
1736 IN EFI_HANDLE ImageHandle
,
1737 IN EFI_SYSTEM_TABLE
*SystemTable
1741 if (mStartOpCodeHandle
!= NULL
) {
1742 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
1745 if (mEndOpCodeHandle
!= NULL
) {
1746 HiiFreeOpCodeHandle (mEndOpCodeHandle
);
1752 // Remove our IFR data from HII database
1754 HiiRemovePackages (mBmmCallbackInfo
->BmmHiiHandle
);
1756 gBS
->UninstallMultipleProtocolInterfaces (
1757 mBmmCallbackInfo
->BmmDriverHandle
,
1758 &gEfiDevicePathProtocolGuid
,
1759 &mBmmHiiVendorDevicePath
,
1760 &gEfiHiiConfigAccessProtocolGuid
,
1761 &mBmmCallbackInfo
->BmmConfigAccess
,
1765 FreePool (mBmmCallbackInfo
->LoadContext
);
1766 mBmmCallbackInfo
->BmmDriverHandle
= NULL
;