summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c')
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c1770
1 files changed, 1770 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c
new file mode 100644
index 00000000..bf77cb45
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c
@@ -0,0 +1,1770 @@
+/** @file
+The functions for Boot Maintainence Main menu.
+
+Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BootMaintenanceManager.h"
+
+#define FRONT_PAGE_KEY_OFFSET 0x4000
+//
+// Boot video resolution and text mode.
+//
+UINT32 mBmmBootHorizontalResolution = 0;
+UINT32 mBmmBootVerticalResolution = 0;
+UINT32 mBmmBootTextModeColumn = 0;
+UINT32 mBmmBootTextModeRow = 0;
+//
+// BIOS setup video resolution and text mode.
+//
+UINT32 mBmmSetupTextModeColumn = 0;
+UINT32 mBmmSetupTextModeRow = 0;
+UINT32 mBmmSetupHorizontalResolution = 0;
+UINT32 mBmmSetupVerticalResolution = 0;
+
+BOOLEAN mBmmModeInitialized = FALSE;
+
+EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = {
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+};
+
+HII_VENDOR_DEVICE_PATH mBmmHiiVendorDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ //
+ // {165A028F-0BB2-4b5f-8747-77592E3F6499}
+ //
+ { 0x165a028f, 0xbb2, 0x4b5f, { 0x87, 0x47, 0x77, 0x59, 0x2e, 0x3f, 0x64, 0x99 } }
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8) (END_DEVICE_PATH_LENGTH),
+ (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+EFI_GUID mBootMaintGuid = BOOT_MAINT_FORMSET_GUID;
+
+CHAR16 mBootMaintStorageName[] = L"BmmData";
+BMM_CALLBACK_DATA gBootMaintenancePrivate = {
+ BMM_CALLBACK_DATA_SIGNATURE,
+ NULL,
+ NULL,
+ {
+ BootMaintExtractConfig,
+ BootMaintRouteConfig,
+ BootMaintCallback
+ }
+};
+
+BMM_CALLBACK_DATA *mBmmCallbackInfo = &gBootMaintenancePrivate;
+BOOLEAN mAllMenuInit = FALSE;
+BOOLEAN mFirstEnterBMMForm = FALSE;
+
+/**
+ Init all memu.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+InitAllMenu (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Free up all Menu Option list.
+
+**/
+VOID
+FreeAllMenu (
+ VOID
+ );
+
+/**
+
+ Update the menus in the BMM page.
+
+**/
+VOID
+CustomizeMenus (
+ VOID
+ );
+
+/**
+ This function will change video resolution and text mode
+ according to defined setup mode or defined boot mode
+
+ @param IsSetupMode Indicate mode is changed to setup mode or boot mode.
+
+ @retval EFI_SUCCESS Mode is changed successfully.
+ @retval Others Mode failed to be changed.
+
+**/
+EFI_STATUS
+BmmSetConsoleMode (
+ BOOLEAN IsSetupMode
+ )
+{
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
+ UINTN SizeOfInfo;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+ UINT32 MaxGopMode;
+ UINT32 MaxTextMode;
+ UINT32 ModeNumber;
+ UINT32 NewHorizontalResolution;
+ UINT32 NewVerticalResolution;
+ UINT32 NewColumns;
+ UINT32 NewRows;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN CurrentColumn;
+ UINTN CurrentRow;
+
+ MaxGopMode = 0;
+ MaxTextMode = 0;
+
+ //
+ // Get current video resolution and text mode
+ //
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID**)&GraphicsOutput
+ );
+ if (EFI_ERROR (Status)) {
+ GraphicsOutput = NULL;
+ }
+
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiSimpleTextOutProtocolGuid,
+ (VOID**)&SimpleTextOut
+ );
+ if (EFI_ERROR (Status)) {
+ SimpleTextOut = NULL;
+ }
+
+ if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (IsSetupMode) {
+ //
+ // The required resolution and text mode is setup mode.
+ //
+ NewHorizontalResolution = mBmmSetupHorizontalResolution;
+ NewVerticalResolution = mBmmSetupVerticalResolution;
+ NewColumns = mBmmSetupTextModeColumn;
+ NewRows = mBmmSetupTextModeRow;
+ } else {
+ //
+ // The required resolution and text mode is boot mode.
+ //
+ NewHorizontalResolution = mBmmBootHorizontalResolution;
+ NewVerticalResolution = mBmmBootVerticalResolution;
+ NewColumns = mBmmBootTextModeColumn;
+ NewRows = mBmmBootTextModeRow;
+ }
+
+ if (GraphicsOutput != NULL) {
+ MaxGopMode = GraphicsOutput->Mode->MaxMode;
+ }
+
+ if (SimpleTextOut != NULL) {
+ MaxTextMode = SimpleTextOut->Mode->MaxMode;
+ }
+
+ //
+ // 1. If current video resolution is same with required video resolution,
+ // video resolution need not be changed.
+ // 1.1. If current text mode is same with required text mode, text mode need not be changed.
+ // 1.2. If current text mode is different from required text mode, text mode need be changed.
+ // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.
+ //
+ for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {
+ Status = GraphicsOutput->QueryMode (
+ GraphicsOutput,
+ ModeNumber,
+ &SizeOfInfo,
+ &Info
+ );
+ if (!EFI_ERROR (Status)) {
+ if ((Info->HorizontalResolution == NewHorizontalResolution) &&
+ (Info->VerticalResolution == NewVerticalResolution)) {
+ if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) &&
+ (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) {
+ //
+ // Current resolution is same with required resolution, check if text mode need be set
+ //
+ Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);
+ ASSERT_EFI_ERROR (Status);
+ if (CurrentColumn == NewColumns && CurrentRow == NewRows) {
+ //
+ // If current text mode is same with required text mode. Do nothing
+ //
+ FreePool (Info);
+ return EFI_SUCCESS;
+ } else {
+ //
+ // If current text mode is different from required text mode. Set new video mode
+ //
+ for (Index = 0; Index < MaxTextMode; Index++) {
+ Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);
+ if (!EFI_ERROR(Status)) {
+ if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) {
+ //
+ // Required text mode is supported, set it.
+ //
+ Status = SimpleTextOut->SetMode (SimpleTextOut, Index);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Update text mode PCD.
+ //
+ Status = PcdSet32S (PcdConOutColumn, mBmmSetupTextModeColumn);
+ ASSERT_EFI_ERROR (Status);
+ Status = PcdSet32S (PcdConOutRow, mBmmSetupTextModeRow);
+ ASSERT_EFI_ERROR (Status);
+ FreePool (Info);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ if (Index == MaxTextMode) {
+ //
+ // If required text mode is not supported, return error.
+ //
+ FreePool (Info);
+ return EFI_UNSUPPORTED;
+ }
+ }
+ } else {
+ //
+ // If current video resolution is not same with the new one, set new video resolution.
+ // In this case, the driver which produces simple text out need be restarted.
+ //
+ Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
+ if (!EFI_ERROR (Status)) {
+ FreePool (Info);
+ break;
+ }
+ }
+ }
+ FreePool (Info);
+ }
+ }
+
+ if (ModeNumber == MaxGopMode) {
+ //
+ // If the resolution is not supported, return error.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Set PCD to Inform GraphicsConsole to change video resolution.
+ // Set PCD to Inform Consplitter to change text mode.
+ //
+ Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution);
+ ASSERT_EFI_ERROR (Status);
+ Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution);
+ ASSERT_EFI_ERROR (Status);
+ Status = PcdSet32S (PcdConOutColumn, NewColumns);
+ ASSERT_EFI_ERROR (Status);
+ Status = PcdSet32S (PcdConOutRow, NewRows);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Video mode is changed, so restart graphics console driver and higher level driver.
+ // Reconnect graphics console driver and higher level driver.
+ // Locate all the handles with GOP protocol and reconnect it.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleTextOutProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
+ }
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
+ }
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function converts an input device structure to a Unicode string.
+
+ @param DevPath A pointer to the device path structure.
+
+ @return A new allocated Unicode string that represents the device path.
+
+**/
+CHAR16 *
+UiDevicePathToStr (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *ToText;
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
+
+ if (DevPath == NULL) {
+ return NULL;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiDevicePathToTextProtocolGuid,
+ NULL,
+ (VOID **) &DevPathToText
+ );
+ ASSERT_EFI_ERROR (Status);
+ ToText = DevPathToText->ConvertDevicePathToText (
+ DevPath,
+ FALSE,
+ TRUE
+ );
+ ASSERT (ToText != NULL);
+ return ToText;
+}
+
+/**
+ Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.
+ The caller is responsible for freeing the allocated buffer using FreePool().
+
+ @param DevicePath Device path.
+
+ @return A new allocated string that represents the file name.
+
+**/
+CHAR16 *
+ExtractFileNameFromDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ CHAR16 *String;
+ CHAR16 *MatchString;
+ CHAR16 *LastMatch;
+ CHAR16 *FileName;
+ UINTN Length;
+
+ ASSERT(DevicePath != NULL);
+
+ String = UiDevicePathToStr(DevicePath);
+ MatchString = String;
+ LastMatch = String;
+ FileName = NULL;
+
+ while(MatchString != NULL){
+ LastMatch = MatchString + 1;
+ MatchString = StrStr(LastMatch,L"\\");
+ }
+
+ Length = StrLen(LastMatch);
+ FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);
+ if (FileName != NULL) {
+ *(FileName + Length) = 0;
+ }
+
+ FreePool(String);
+
+ return FileName;
+}
+
+/**
+ Extract device path for given HII handle and class guid.
+
+ @param Handle The HII handle.
+
+ @retval NULL Fail to get the device path string.
+ @return PathString Get the device path string.
+
+**/
+CHAR16 *
+BmmExtractDevicePathFromHiiHandle (
+ IN EFI_HII_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DriverHandle;
+
+ ASSERT (Handle != NULL);
+
+ if (Handle == NULL) {
+ return NULL;
+ }
+
+ Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ //
+ // Get device path string.
+ //
+ return ConvertDevicePathToText(DevicePathFromHandle (DriverHandle), FALSE, FALSE);
+
+}
+
+/**
+ Converts the unicode character of the string from uppercase to lowercase.
+ This is a internal function.
+
+ @param ConfigString String to be converted
+
+**/
+VOID
+HiiToLower (
+ IN EFI_STRING ConfigString
+ )
+{
+ EFI_STRING String;
+ BOOLEAN Lower;
+
+ ASSERT (ConfigString != NULL);
+
+ //
+ // Convert all hex digits in range [A-F] in the configuration header to [a-f]
+ //
+ for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
+ if (*String == L'=') {
+ Lower = TRUE;
+ } else if (*String == L'&') {
+ Lower = FALSE;
+ } else if (Lower && *String >= L'A' && *String <= L'F') {
+ *String = (CHAR16) (*String - L'A' + L'a');
+ }
+ }
+}
+
+/**
+ Update the progress string through the offset value.
+
+ @param Offset The offset value
+ @param Configuration Point to the configuration string.
+
+**/
+EFI_STRING
+UpdateProgress(
+ IN UINTN Offset,
+ IN EFI_STRING Configuration
+)
+{
+ UINTN Length;
+ EFI_STRING StringPtr;
+ EFI_STRING ReturnString;
+
+ StringPtr = NULL;
+ ReturnString = NULL;
+
+ //
+ // &OFFSET=XXXX followed by a Null-terminator.
+ // Length = StrLen (L"&OFFSET=") + 4 + 1
+ //
+ Length = StrLen (L"&OFFSET=") + 4 + 1;
+
+ StringPtr = AllocateZeroPool (Length * sizeof (CHAR16));
+
+ if (StringPtr == NULL) {
+ return NULL;
+ }
+
+ UnicodeSPrint (
+ StringPtr,
+ (8 + 4 + 1) * sizeof (CHAR16),
+ L"&OFFSET=%04x",
+ Offset
+ );
+
+ ReturnString = StrStr (Configuration, StringPtr);
+
+ if (ReturnString == NULL) {
+ //
+ // If doesn't find the string in Configuration, convert the string to lower case then search again.
+ //
+ HiiToLower (StringPtr);
+ ReturnString = StrStr (Configuration, StringPtr);
+ }
+
+ FreePool (StringPtr);
+
+ return ReturnString;
+}
+
+/**
+ Update the terminal content in TerminalMenu.
+
+ @param BmmData The BMM fake NV data.
+
+**/
+VOID
+UpdateTerminalContent (
+ IN BMM_FAKE_NV_DATA *BmmData
+ )
+{
+ UINT16 Index;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ BM_MENU_ENTRY *NewMenuEntry;
+
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ ASSERT (NewMenuEntry != NULL);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ NewTerminalContext->BaudRateIndex = BmmData->COMBaudRate[Index];
+ ASSERT (BmmData->COMBaudRate[Index] < (ARRAY_SIZE (BaudRateList)));
+ NewTerminalContext->BaudRate = BaudRateList[BmmData->COMBaudRate[Index]].Value;
+ NewTerminalContext->DataBitsIndex = BmmData->COMDataRate[Index];
+ ASSERT (BmmData->COMDataRate[Index] < (ARRAY_SIZE (DataBitsList)));
+ NewTerminalContext->DataBits = (UINT8) DataBitsList[BmmData->COMDataRate[Index]].Value;
+ NewTerminalContext->StopBitsIndex = BmmData->COMStopBits[Index];
+ ASSERT (BmmData->COMStopBits[Index] < (ARRAY_SIZE (StopBitsList)));
+ NewTerminalContext->StopBits = (UINT8) StopBitsList[BmmData->COMStopBits[Index]].Value;
+ NewTerminalContext->ParityIndex = BmmData->COMParity[Index];
+ ASSERT (BmmData->COMParity[Index] < (ARRAY_SIZE (ParityList)));
+ NewTerminalContext->Parity = (UINT8) ParityList[BmmData->COMParity[Index]].Value;
+ NewTerminalContext->TerminalType = BmmData->COMTerminalType[Index];
+ NewTerminalContext->FlowControl = BmmData->COMFlowControl[Index];
+ ChangeTerminalDevicePath (
+ NewTerminalContext->DevicePath,
+ FALSE
+ );
+ }
+}
+
+/**
+ Update the console content in ConsoleMenu.
+
+ @param ConsoleName The name for the console device type.
+ @param BmmData The BMM fake NV data.
+
+**/
+VOID
+UpdateConsoleContent(
+ IN CHAR16 *ConsoleName,
+ IN BMM_FAKE_NV_DATA *BmmData
+ )
+{
+ UINT16 Index;
+ BM_CONSOLE_CONTEXT *NewConsoleContext;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ BM_MENU_ENTRY *NewMenuEntry;
+
+ if (StrCmp (ConsoleName, L"ConIn") == 0) {
+ for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++){
+ NewMenuEntry = BOpt_GetMenuEntry(&ConsoleInpMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext;
+ ASSERT (Index < MAX_MENU_NUMBER);
+ NewConsoleContext->IsActive = BmmData->ConsoleInCheck[Index];
+ }
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ ASSERT (Index + ConsoleInpMenu.MenuNumber < MAX_MENU_NUMBER);
+ NewTerminalContext->IsConIn = BmmData->ConsoleInCheck[Index + ConsoleInpMenu.MenuNumber];
+ }
+ }
+
+ if (StrCmp (ConsoleName, L"ConOut") == 0) {
+ for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++){
+ NewMenuEntry = BOpt_GetMenuEntry(&ConsoleOutMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext;
+ ASSERT (Index < MAX_MENU_NUMBER);
+ NewConsoleContext->IsActive = BmmData->ConsoleOutCheck[Index];
+ }
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ ASSERT (Index + ConsoleOutMenu.MenuNumber < MAX_MENU_NUMBER);
+ NewTerminalContext->IsConOut = BmmData->ConsoleOutCheck[Index + ConsoleOutMenu.MenuNumber];
+ }
+ }
+ if (StrCmp (ConsoleName, L"ErrOut") == 0) {
+ for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++){
+ NewMenuEntry = BOpt_GetMenuEntry(&ConsoleErrMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext;
+ ASSERT (Index < MAX_MENU_NUMBER);
+ NewConsoleContext->IsActive = BmmData->ConsoleErrCheck[Index];
+ }
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ ASSERT (Index + ConsoleErrMenu.MenuNumber < MAX_MENU_NUMBER);
+ NewTerminalContext->IsStdErr = BmmData->ConsoleErrCheck[Index + ConsoleErrMenu.MenuNumber];
+ }
+ }
+}
+
+/**
+ This function allows a caller to extract the current configuration for one
+ or more named elements from the target driver.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Request A null-terminated Unicode string in <ConfigRequest> format.
+ @param Progress On return, points to a character in the Request string.
+ Points to the string's null terminator if request was successful.
+ Points to the most recent '&' before the first failing name/value
+ pair (or the beginning of the string if the failure is in the
+ first name/value pair) if the request was not successful.
+ @param Results A null-terminated Unicode string in <ConfigAltResp> format which
+ has all values filled in for the names in the Request string.
+ String to be allocated by the called function.
+
+ @retval EFI_SUCCESS The Results is filled with the requested values.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
+ @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+BootMaintExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ BMM_CALLBACK_DATA *Private;
+ EFI_STRING ConfigRequestHdr;
+ EFI_STRING ConfigRequest;
+ BOOLEAN AllocatedRequest;
+ UINTN Size;
+
+ if (Progress == NULL || Results == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Progress = Request;
+ if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mBootMaintGuid, mBootMaintStorageName)) {
+ return EFI_NOT_FOUND;
+ }
+
+ ConfigRequestHdr = NULL;
+ ConfigRequest = NULL;
+ AllocatedRequest = FALSE;
+ Size = 0;
+
+ Private = BMM_CALLBACK_DATA_FROM_THIS (This);
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ BufferSize = sizeof (BMM_FAKE_NV_DATA);
+ ConfigRequest = Request;
+ if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
+ //
+ // Request has no request element, construct full request string.
+ // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+ // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
+ //
+ ConfigRequestHdr = HiiConstructConfigHdr (&mBootMaintGuid, mBootMaintStorageName, Private->BmmDriverHandle);
+ Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+ ConfigRequest = AllocateZeroPool (Size);
+ ASSERT (ConfigRequest != NULL);
+ AllocatedRequest = TRUE;
+ UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
+ FreePool (ConfigRequestHdr);
+ }
+
+ Status = gHiiConfigRouting->BlockToConfig (
+ gHiiConfigRouting,
+ ConfigRequest,
+ (UINT8 *) &Private->BmmFakeNvData,
+ BufferSize,
+ Results,
+ Progress
+ );
+ //
+ // Free the allocated config request string.
+ //
+ if (AllocatedRequest) {
+ FreePool (ConfigRequest);
+ ConfigRequest = NULL;
+ }
+ //
+ // Set Progress string to the original request string.
+ //
+ if (Request == NULL) {
+ *Progress = NULL;
+ } else if (StrStr (Request, L"OFFSET") == NULL) {
+ *Progress = Request + StrLen (Request);
+ }
+
+ return Status;
+}
+
+/**
+ This function applies changes in a driver's configuration.
+ Input is a Configuration, which has the routing data for this
+ driver followed by name / value configuration pairs. The driver
+ must apply those pairs to its configurable storage. If the
+ driver's configuration is stored in a linear block of data
+ and the driver's name / value pairs are in <BlockConfig>
+ format, it may use the ConfigToBlock helper function (above) to
+ simplify the job. Currently not implemented.
+
+ @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param[in] Configuration A null-terminated Unicode string in
+ <ConfigString> format.
+ @param[out] Progress A pointer to a string filled in with the
+ offset of the most recent '&' before the
+ first failing name / value pair (or the
+ beginn ing of the string if the failure
+ is in the first name / value pair) or
+ the terminating NULL if all was
+ successful.
+
+ @retval EFI_SUCCESS The results have been distributed or are
+ awaiting distribution.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
+ parts of the results that must be
+ stored awaiting possible future
+ protocols.
+ @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
+ Results parameter would result
+ in this type of error.
+ @retval EFI_NOT_FOUND Target for the specified routing data
+ was not found.
+**/
+EFI_STATUS
+EFIAPI
+BootMaintRouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting;
+ BMM_FAKE_NV_DATA *NewBmmData;
+ BMM_FAKE_NV_DATA *OldBmmData;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT16 Index;
+ BOOLEAN TerminalAttChange;
+ BMM_CALLBACK_DATA *Private;
+ UINTN Offset;
+
+ if (Progress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *Progress = Configuration;
+
+ if (Configuration == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check routing data in <ConfigHdr>.
+ // Note: there is no name for Name/Value storage, only GUID will be checked
+ //
+ if (!HiiIsConfigHdrMatch (Configuration, &mBootMaintGuid, mBootMaintStorageName)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiConfigRoutingProtocolGuid,
+ NULL,
+ (VOID **)&ConfigRouting
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Private = BMM_CALLBACK_DATA_FROM_THIS (This);
+ //
+ // Get Buffer Storage data from EFI variable
+ //
+ BufferSize = sizeof (BMM_FAKE_NV_DATA);
+ OldBmmData = &Private->BmmOldFakeNVData;
+ NewBmmData = &Private->BmmFakeNvData;
+ Offset = 0;
+ //
+ // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
+ //
+ Status = ConfigRouting->ConfigToBlock (
+ ConfigRouting,
+ Configuration,
+ (UINT8 *) NewBmmData,
+ &BufferSize,
+ Progress
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Compare new and old BMM configuration data and only do action for modified item to
+ // avoid setting unnecessary non-volatile variable
+ //
+
+ //
+ // Check data which located in BMM main page and save the settings if need
+ //
+ if (CompareMem (&NewBmmData->BootNext, &OldBmmData->BootNext, sizeof (NewBmmData->BootNext)) != 0) {
+ Status = Var_UpdateBootNext (Private);
+ if (EFI_ERROR (Status)) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootNext);
+ goto Exit;
+ }
+ }
+
+ //
+ // Check data which located in Boot Options Menu and save the settings if need
+ //
+ if (CompareMem (NewBmmData->BootOptionDel, OldBmmData->BootOptionDel, sizeof (NewBmmData->BootOptionDel)) != 0) {
+ for (Index = 0;
+ ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->BootOptionDel) / sizeof (NewBmmData->BootOptionDel[0]))));
+ Index ++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->Deleted = NewBmmData->BootOptionDel[Index];
+ NewBmmData->BootOptionDel[Index] = FALSE;
+ NewBmmData->BootOptionDelMark[Index] = FALSE;
+ }
+
+ Status = Var_DelBootOption ();
+ if (EFI_ERROR (Status)) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootOptionDel);
+ goto Exit;
+ }
+ }
+
+ if (CompareMem (NewBmmData->BootOptionOrder, OldBmmData->BootOptionOrder, sizeof (NewBmmData->BootOptionOrder)) != 0) {
+ Status = Var_UpdateBootOrder (Private);
+ if (EFI_ERROR (Status)) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootOptionOrder);
+ goto Exit;
+ }
+ }
+
+ if (CompareMem (&NewBmmData->BootTimeOut, &OldBmmData->BootTimeOut, sizeof (NewBmmData->BootTimeOut)) != 0){
+ Status = gRT->SetVariable(
+ L"Timeout",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ sizeof(UINT16),
+ &(NewBmmData->BootTimeOut)
+ );
+ if (EFI_ERROR (Status)) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootTimeOut);
+ goto Exit;
+ }
+ Private->BmmOldFakeNVData.BootTimeOut = NewBmmData->BootTimeOut;
+ }
+
+ //
+ // Check data which located in Driver Options Menu and save the settings if need
+ //
+ if (CompareMem (NewBmmData->DriverOptionDel, OldBmmData->DriverOptionDel, sizeof (NewBmmData->DriverOptionDel)) != 0) {
+ for (Index = 0;
+ ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->DriverOptionDel) / sizeof (NewBmmData->DriverOptionDel[0]))));
+ Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->Deleted = NewBmmData->DriverOptionDel[Index];
+ NewBmmData->DriverOptionDel[Index] = FALSE;
+ NewBmmData->DriverOptionDelMark[Index] = FALSE;
+ }
+ Status = Var_DelDriverOption ();
+ if (EFI_ERROR (Status)) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, DriverOptionDel);
+ goto Exit;
+ }
+ }
+
+ if (CompareMem (NewBmmData->DriverOptionOrder, OldBmmData->DriverOptionOrder, sizeof (NewBmmData->DriverOptionOrder)) != 0) {
+ Status = Var_UpdateDriverOrder (Private);
+ if (EFI_ERROR (Status)) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, DriverOptionOrder);
+ goto Exit;
+ }
+ }
+
+ if (CompareMem (&NewBmmData->ConsoleOutMode, &OldBmmData->ConsoleOutMode, sizeof (NewBmmData->ConsoleOutMode)) != 0){
+ Status = Var_UpdateConMode(Private);
+ if (EFI_ERROR (Status)) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, ConsoleOutMode);
+ goto Exit;
+ }
+ }
+
+ TerminalAttChange = FALSE;
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+
+ //
+ // only need update modified items
+ //
+ if (CompareMem (&NewBmmData->COMBaudRate[Index], &OldBmmData->COMBaudRate[Index], sizeof (NewBmmData->COMBaudRate[Index])) == 0 &&
+ CompareMem (&NewBmmData->COMDataRate[Index], &OldBmmData->COMDataRate[Index], sizeof (NewBmmData->COMDataRate[Index])) == 0 &&
+ CompareMem (&NewBmmData->COMStopBits[Index], &OldBmmData->COMStopBits[Index], sizeof (NewBmmData->COMStopBits[Index])) == 0 &&
+ CompareMem (&NewBmmData->COMParity[Index], &OldBmmData->COMParity[Index], sizeof (NewBmmData->COMParity[Index])) == 0 &&
+ CompareMem (&NewBmmData->COMTerminalType[Index], &OldBmmData->COMTerminalType[Index], sizeof (NewBmmData->COMTerminalType[Index])) == 0 &&
+ CompareMem (&NewBmmData->COMFlowControl[Index], &OldBmmData->COMFlowControl[Index], sizeof (NewBmmData->COMFlowControl[Index])) == 0) {
+ continue;
+ }
+
+ TerminalAttChange = TRUE;
+ }
+ if (TerminalAttChange) {
+ if (CompareMem (&NewBmmData->COMBaudRate[Index], &OldBmmData->COMBaudRate[Index], sizeof (NewBmmData->COMBaudRate[Index])) != 0) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMBaudRate);
+ } else if (CompareMem (&NewBmmData->COMDataRate[Index], &OldBmmData->COMDataRate[Index], sizeof (NewBmmData->COMDataRate[Index])) != 0) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMDataRate);
+ } else if (CompareMem (&NewBmmData->COMStopBits[Index], &OldBmmData->COMStopBits[Index], sizeof (NewBmmData->COMStopBits[Index])) != 0) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMStopBits);
+ } else if (CompareMem (&NewBmmData->COMParity[Index], &OldBmmData->COMParity[Index], sizeof (NewBmmData->COMParity[Index])) != 0) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMParity);
+ } else if (CompareMem (&NewBmmData->COMTerminalType[Index], &OldBmmData->COMTerminalType[Index], sizeof (NewBmmData->COMTerminalType[Index])) != 0) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMTerminalType);
+ } else if (CompareMem (&NewBmmData->COMFlowControl[Index], &OldBmmData->COMFlowControl[Index], sizeof (NewBmmData->COMFlowControl[Index])) != 0) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMFlowControl);
+ }
+ Status = Var_UpdateConsoleInpOption ();
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ Status = Var_UpdateConsoleOutOption ();
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ Status = Var_UpdateErrorOutOption ();
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ }
+ //
+ // Check data which located in Console Options Menu and save the settings if need
+ //
+ if (CompareMem (NewBmmData->ConsoleInCheck, OldBmmData->ConsoleInCheck, sizeof (NewBmmData->ConsoleInCheck)) != 0){
+ Status = Var_UpdateConsoleInpOption();
+ if (EFI_ERROR (Status)) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, ConsoleInCheck);
+ goto Exit;
+ }
+ }
+
+ if (CompareMem (NewBmmData->ConsoleOutCheck, OldBmmData->ConsoleOutCheck, sizeof (NewBmmData->ConsoleOutCheck)) != 0){
+ Status = Var_UpdateConsoleOutOption();
+ if (EFI_ERROR (Status)) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, ConsoleOutCheck);
+ goto Exit;
+ }
+ }
+
+ if (CompareMem (NewBmmData->ConsoleErrCheck, OldBmmData->ConsoleErrCheck, sizeof (NewBmmData->ConsoleErrCheck)) != 0){
+ Status = Var_UpdateErrorOutOption();
+ if (EFI_ERROR (Status)) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, ConsoleErrCheck);
+ goto Exit;
+ }
+ }
+
+ if (CompareMem (NewBmmData->BootDescriptionData, OldBmmData->BootDescriptionData, sizeof (NewBmmData->BootDescriptionData)) != 0 ||
+ CompareMem (NewBmmData->BootOptionalData, OldBmmData->BootOptionalData, sizeof (NewBmmData->BootOptionalData)) != 0) {
+ Status = Var_UpdateBootOption (Private);
+ NewBmmData->BootOptionChanged = FALSE;
+ if (EFI_ERROR (Status)) {
+ if (CompareMem (NewBmmData->BootDescriptionData, OldBmmData->BootDescriptionData, sizeof (NewBmmData->BootDescriptionData)) != 0) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootDescriptionData);
+ } else {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootOptionalData);
+ }
+ goto Exit;
+ }
+ BOpt_GetBootOptions (Private);
+ }
+
+ if (CompareMem (NewBmmData->DriverDescriptionData, OldBmmData->DriverDescriptionData, sizeof (NewBmmData->DriverDescriptionData)) != 0 ||
+ CompareMem (NewBmmData->DriverOptionalData, OldBmmData->DriverOptionalData, sizeof (NewBmmData->DriverOptionalData)) != 0) {
+ Status = Var_UpdateDriverOption (
+ Private,
+ Private->BmmHiiHandle,
+ NewBmmData->DriverDescriptionData,
+ NewBmmData->DriverOptionalData,
+ NewBmmData->ForceReconnect
+ );
+ NewBmmData->DriverOptionChanged = FALSE;
+ NewBmmData->ForceReconnect = TRUE;
+ if (EFI_ERROR (Status)) {
+ if (CompareMem (NewBmmData->DriverDescriptionData, OldBmmData->DriverDescriptionData, sizeof (NewBmmData->DriverDescriptionData)) != 0) {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, DriverDescriptionData);
+ } else {
+ Offset = OFFSET_OF (BMM_FAKE_NV_DATA, DriverOptionalData);
+ }
+ goto Exit;
+ }
+
+ BOpt_GetDriverOptions (Private);
+ }
+
+ //
+ // After user do the save action, need to update OldBmmData.
+ //
+ CopyMem (OldBmmData, NewBmmData, sizeof (BMM_FAKE_NV_DATA));
+
+ return EFI_SUCCESS;
+
+Exit:
+ //
+ // Fail to save the data, update the progress string.
+ //
+ *Progress = UpdateProgress (Offset, Configuration);
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ return Status;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+}
+
+/**
+ This function processes the results of changes in configuration.
+
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Action Specifies the type of action taken by the browser.
+ @param QuestionId A unique value which is sent to the original exporting driver
+ so that it can identify the type of data to expect.
+ @param Type The type of value for the question.
+ @param Value A pointer to the data being sent to the original exporting driver.
+ @param ActionRequest On return, points to the action requested by the callback function.
+
+ @retval EFI_SUCCESS The callback successfully handled the action.
+ @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
+ @retval EFI_DEVICE_ERROR The variable could not be saved.
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.
+ @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid.
+**/
+EFI_STATUS
+EFIAPI
+BootMaintCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+{
+ BMM_CALLBACK_DATA *Private;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BMM_FAKE_NV_DATA *CurrentFakeNVMap;
+ BMM_FAKE_NV_DATA *OldFakeNVMap;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL * File;
+
+ if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED && Action != EFI_BROWSER_ACTION_FORM_OPEN) {
+ //
+ // Do nothing for other UEFI Action. Only do call back when data is changed or the form is open.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ Private = BMM_CALLBACK_DATA_FROM_THIS (This);
+
+ if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
+ if (QuestionId == KEY_VALUE_TRIGGER_FORM_OPEN_ACTION) {
+ if (!mFirstEnterBMMForm) {
+ //
+ // BMMUiLib depends on LegacyUi library to show legacy menus.
+ // If we want to show Legacy menus correctly in BMM page,
+ // we must do it after the LegacyUi library has already been initialized.
+ // Opening the BMM form is the appropriate time that the LegacyUi library has already been initialized.
+ // So we do the tasks which are related to legacy menus here.
+ // 1. Update the menus (including legacy munu) show in BootMiantenanceManager page.
+ // 2. Re-scan the BootOption menus (including the legacy boot option).
+ //
+ CustomizeMenus ();
+ EfiBootManagerRefreshAllBootOption ();
+ BOpt_GetBootOptions (Private);
+ mFirstEnterBMMForm = TRUE;
+ }
+ }
+ }
+ //
+ // Retrieve uncommitted data from Form Browser
+ //
+ CurrentFakeNVMap = &Private->BmmFakeNvData;
+ OldFakeNVMap = &Private->BmmOldFakeNVData;
+ HiiGetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap);
+
+ if (Action == EFI_BROWSER_ACTION_CHANGING) {
+ if (Value == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UpdatePageId (Private, QuestionId);
+
+ if (QuestionId < FILE_OPTION_OFFSET) {
+ if (QuestionId < CONFIG_OPTION_OFFSET) {
+ switch (QuestionId) {
+ case FORM_BOOT_ADD_ID:
+ // Leave BMM and enter FileExplorer.
+ ChooseFile (NULL, L".efi", CreateBootOptionFromFile, &File);
+ break;
+
+ case FORM_DRV_ADD_FILE_ID:
+ // Leave BMM and enter FileExplorer.
+ ChooseFile (NULL, L".efi", CreateDriverOptionFromFile, &File);
+ break;
+
+ case FORM_DRV_ADD_HANDLE_ID:
+ CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private);
+ UpdateDrvAddHandlePage (Private);
+ break;
+
+ case FORM_BOOT_DEL_ID:
+ CleanUpPage (FORM_BOOT_DEL_ID, Private);
+ UpdateBootDelPage (Private);
+ break;
+
+ case FORM_BOOT_CHG_ID:
+ case FORM_DRV_CHG_ID:
+ UpdatePageBody (QuestionId, Private);
+ break;
+
+ case FORM_DRV_DEL_ID:
+ CleanUpPage (FORM_DRV_DEL_ID, Private);
+ UpdateDrvDelPage (Private);
+ break;
+
+ case FORM_CON_IN_ID:
+ case FORM_CON_OUT_ID:
+ case FORM_CON_ERR_ID:
+ UpdatePageBody (QuestionId, Private);
+ break;
+
+ case FORM_CON_MODE_ID:
+ CleanUpPage (FORM_CON_MODE_ID, Private);
+ UpdateConModePage (Private);
+ break;
+
+ case FORM_CON_COM_ID:
+ CleanUpPage (FORM_CON_COM_ID, Private);
+ UpdateConCOMPage (Private);
+ break;
+
+ default:
+ break;
+ }
+ } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) {
+ Index = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET);
+ Private->CurrentTerminal = Index;
+
+ CleanUpPage (FORM_CON_COM_SETUP_ID, Private);
+ UpdateTerminalPage (Private);
+
+ } else if (QuestionId >= HANDLE_OPTION_OFFSET) {
+ Index = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET);
+
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index);
+ ASSERT (NewMenuEntry != NULL);
+ Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;
+
+ CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private);
+
+ Private->MenuEntry = NewMenuEntry;
+ Private->LoadContext->FilePathList = Private->HandleContext->DevicePath;
+
+ UpdateDriverAddHandleDescPage (Private);
+ }
+ }
+ if (QuestionId == KEY_VALUE_BOOT_FROM_FILE){
+ // Leave BMM and enter FileExplorer.
+ ChooseFile (NULL, L".efi", BootFromFile, &File);
+ }
+ } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
+ if ((Value == NULL) || (ActionRequest == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT) {
+ CleanUselessBeforeSubmit (Private);
+ CurrentFakeNVMap->BootOptionChanged = FALSE;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
+ } else if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) {
+ CleanUselessBeforeSubmit (Private);
+ CurrentFakeNVMap->DriverOptionChanged = FALSE;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
+ } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) {
+ //
+ // Discard changes and exit formset
+ //
+ ZeroMem (CurrentFakeNVMap->DriverOptionalData, sizeof (CurrentFakeNVMap->DriverOptionalData));
+ ZeroMem (CurrentFakeNVMap->BootDescriptionData, sizeof (CurrentFakeNVMap->BootDescriptionData));
+ ZeroMem (OldFakeNVMap->DriverOptionalData, sizeof (OldFakeNVMap->DriverOptionalData));
+ ZeroMem (OldFakeNVMap->DriverDescriptionData, sizeof (OldFakeNVMap->DriverDescriptionData));
+ CurrentFakeNVMap->DriverOptionChanged = FALSE;
+ CurrentFakeNVMap->ForceReconnect = TRUE;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
+ } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT) {
+ //
+ // Discard changes and exit formset
+ //
+ ZeroMem (CurrentFakeNVMap->BootOptionalData, sizeof (CurrentFakeNVMap->BootOptionalData));
+ ZeroMem (CurrentFakeNVMap->BootDescriptionData, sizeof (CurrentFakeNVMap->BootDescriptionData));
+ ZeroMem (OldFakeNVMap->BootOptionalData, sizeof (OldFakeNVMap->BootOptionalData));
+ ZeroMem (OldFakeNVMap->BootDescriptionData, sizeof (OldFakeNVMap->BootDescriptionData));
+ CurrentFakeNVMap->BootOptionChanged = FALSE;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
+ } else if (QuestionId == KEY_VALUE_BOOT_DESCRIPTION || QuestionId == KEY_VALUE_BOOT_OPTION) {
+ CurrentFakeNVMap->BootOptionChanged = TRUE;
+ } else if (QuestionId == KEY_VALUE_DRIVER_DESCRIPTION || QuestionId == KEY_VALUE_DRIVER_OPTION) {
+ CurrentFakeNVMap->DriverOptionChanged = TRUE;
+ }
+
+ if ((QuestionId >= BOOT_OPTION_DEL_QUESTION_ID) && (QuestionId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) {
+ if (Value->b){
+ //
+ // Means user try to delete this boot option but not press F10 or "Commit Changes and Exit" menu.
+ //
+ CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = TRUE;
+ } else {
+ //
+ // Means user remove the old check status.
+ //
+ CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = FALSE;
+ }
+ } else if ((QuestionId >= DRIVER_OPTION_DEL_QUESTION_ID) && (QuestionId < DRIVER_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) {
+ if (Value->b){
+ CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = TRUE;
+ } else {
+ CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = FALSE;
+ }
+ } else {
+ switch (QuestionId) {
+ case KEY_VALUE_SAVE_AND_EXIT:
+ case KEY_VALUE_NO_SAVE_AND_EXIT:
+ if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) {
+ CleanUselessBeforeSubmit (Private);
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
+ } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) {
+ DiscardChangeHandler (Private, CurrentFakeNVMap);
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
+ }
+
+ break;
+
+ case FORM_RESET:
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+ return EFI_UNSUPPORTED;
+
+ default:
+ break;
+ }
+ }
+ //
+ // Update the content in Terminal menu and Console menu here.
+ //
+ if (QuestionId == COM_BAUD_RATE_QUESTION_ID + Private->CurrentTerminal || QuestionId == COM_DATA_RATE_QUESTION_ID + Private->CurrentTerminal ||
+ QuestionId == COM_PARITY_QUESTION_ID + Private->CurrentTerminal || QuestionId == COM_STOP_BITS_QUESTION_ID + Private->CurrentTerminal ||
+ QuestionId == COM_TERMINAL_QUESTION_ID + Private->CurrentTerminal || QuestionId == COM_FLOWCONTROL_QUESTION_ID + Private->CurrentTerminal
+ ) {
+ UpdateTerminalContent(CurrentFakeNVMap);
+ }
+ if ((QuestionId >= CON_IN_DEVICE_QUESTION_ID) && (QuestionId < CON_IN_DEVICE_QUESTION_ID + MAX_MENU_NUMBER)) {
+ UpdateConsoleContent (L"ConIn",CurrentFakeNVMap);
+ } else if ((QuestionId >= CON_OUT_DEVICE_QUESTION_ID) && (QuestionId < CON_OUT_DEVICE_QUESTION_ID + MAX_MENU_NUMBER)) {
+ UpdateConsoleContent (L"ConOut", CurrentFakeNVMap);
+ } else if ((QuestionId >= CON_ERR_DEVICE_QUESTION_ID) && (QuestionId < CON_ERR_DEVICE_QUESTION_ID + MAX_MENU_NUMBER)) {
+ UpdateConsoleContent (L"ErrOut", CurrentFakeNVMap);
+ }
+ }
+
+ //
+ // Pass changed uncommitted data back to Form Browser
+ //
+ HiiSetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap, NULL);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Discard all changes done to the BMM pages such as Boot Order change,
+ Driver order change.
+
+ @param Private The BMM context data.
+ @param CurrentFakeNVMap The current Fack NV Map.
+
+**/
+VOID
+DiscardChangeHandler (
+ IN BMM_CALLBACK_DATA *Private,
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap
+ )
+{
+ UINT16 Index;
+
+ switch (Private->BmmPreviousPageId) {
+ case FORM_BOOT_CHG_ID:
+ CopyMem (CurrentFakeNVMap->BootOptionOrder, Private->BmmOldFakeNVData.BootOptionOrder, sizeof (CurrentFakeNVMap->BootOptionOrder));
+ break;
+
+ case FORM_DRV_CHG_ID:
+ CopyMem (CurrentFakeNVMap->DriverOptionOrder, Private->BmmOldFakeNVData.DriverOptionOrder, sizeof (CurrentFakeNVMap->DriverOptionOrder));
+ break;
+
+ case FORM_BOOT_DEL_ID:
+ ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (CurrentFakeNVMap->BootOptionDel[0])));
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ CurrentFakeNVMap->BootOptionDel[Index] = FALSE;
+ }
+ break;
+
+ case FORM_DRV_DEL_ID:
+ ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (CurrentFakeNVMap->DriverOptionDel[0])));
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
+ CurrentFakeNVMap->DriverOptionDel[Index] = FALSE;
+ }
+ break;
+
+ case FORM_BOOT_NEXT_ID:
+ CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext;
+ break;
+
+ case FORM_TIME_OUT_ID:
+ CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut;
+ break;
+
+ case FORM_DRV_ADD_HANDLE_DESC_ID:
+ case FORM_DRV_ADD_FILE_ID:
+ case FORM_DRV_ADD_HANDLE_ID:
+ CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000;
+ CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ This function is to clean some useless data before submit changes.
+
+ @param Private The BMM context data.
+
+**/
+VOID
+CleanUselessBeforeSubmit (
+ IN BMM_CALLBACK_DATA *Private
+ )
+{
+ UINT16 Index;
+ if (Private->BmmPreviousPageId != FORM_BOOT_DEL_ID) {
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ if (Private->BmmFakeNvData.BootOptionDel[Index] && !Private->BmmFakeNvData.BootOptionDelMark[Index]) {
+ Private->BmmFakeNvData.BootOptionDel[Index] = FALSE;
+ Private->BmmOldFakeNVData.BootOptionDel[Index] = FALSE;
+ }
+ }
+ }
+ if (Private->BmmPreviousPageId != FORM_DRV_DEL_ID) {
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
+ if (Private->BmmFakeNvData.DriverOptionDel[Index] && !Private->BmmFakeNvData.DriverOptionDelMark[Index]) {
+ Private->BmmFakeNvData.DriverOptionDel[Index] = FALSE;
+ Private->BmmOldFakeNVData.DriverOptionDel[Index] = FALSE;
+ }
+ }
+ }
+}
+
+/**
+
+ Update the menus in the BMM page.
+
+**/
+VOID
+CustomizeMenus (
+ VOID
+ )
+{
+ VOID *StartOpCodeHandle;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartGuidLabel;
+ EFI_IFR_GUID_LABEL *EndGuidLabel;
+
+ //
+ // Allocate space for creation of UpdateData Buffer
+ //
+ StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (StartOpCodeHandle != NULL);
+
+ EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (EndOpCodeHandle != NULL);
+ //
+ // Create Hii Extend Label OpCode as the start opcode
+ //
+ StartGuidLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ StartGuidLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ StartGuidLabel->Number = LABEL_FORM_MAIN_START;
+ //
+ // Create Hii Extend Label OpCode as the end opcode
+ //
+ EndGuidLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ EndGuidLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ EndGuidLabel->Number = LABEL_FORM_MAIN_END;
+
+ //
+ //Updata Front Page form
+ //
+ UiCustomizeBMMPage (
+ mBmmCallbackInfo->BmmHiiHandle,
+ StartOpCodeHandle
+ );
+
+ HiiUpdateForm (
+ mBmmCallbackInfo->BmmHiiHandle,
+ &mBootMaintGuid,
+ FORM_MAIN_ID,
+ StartOpCodeHandle,
+ EndOpCodeHandle
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+}
+
+/**
+ Create dynamic code for BMM and initialize all of BMM configuration data in BmmFakeNvData and
+ BmmOldFakeNVData member in BMM context data.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+InitializeBmmConfig (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT16 Index;
+
+ ASSERT (CallbackData != NULL);
+
+ //
+ // Initialize data which located in BMM main page
+ //
+ CallbackData->BmmFakeNvData.BootNext = NONE_BOOTNEXT_VALUE;
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+
+ if (NewLoadContext->IsBootNext) {
+ CallbackData->BmmFakeNvData.BootNext = Index;
+ break;
+ }
+ }
+
+ CallbackData->BmmFakeNvData.BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut);
+
+ //
+ // Initialize data which located in Boot Options Menu
+ //
+ GetBootOrder (CallbackData);
+
+ //
+ // Initialize data which located in Driver Options Menu
+ //
+ GetDriverOrder (CallbackData);
+
+ //
+ // Initialize data which located in Console Options Menu
+ //
+ GetConsoleOutMode (CallbackData);
+ GetConsoleInCheck (CallbackData);
+ GetConsoleOutCheck (CallbackData);
+ GetConsoleErrCheck (CallbackData);
+ GetTerminalAttribute (CallbackData);
+
+ CallbackData->BmmFakeNvData.ForceReconnect = TRUE;
+
+ //
+ // Backup Initialize BMM configuartion data to BmmOldFakeNVData
+ //
+ CopyMem (&CallbackData->BmmOldFakeNVData, &CallbackData->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA));
+}
+
+/**
+ Initialized all Menu Option List.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+InitAllMenu (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ InitializeListHead (&BootOptionMenu.Head);
+ InitializeListHead (&DriverOptionMenu.Head);
+ BOpt_GetBootOptions (CallbackData);
+ BOpt_GetDriverOptions (CallbackData);
+ BOpt_FindDrivers ();
+ InitializeListHead (&ConsoleInpMenu.Head);
+ InitializeListHead (&ConsoleOutMenu.Head);
+ InitializeListHead (&ConsoleErrMenu.Head);
+ InitializeListHead (&TerminalMenu.Head);
+ LocateSerialIo ();
+ GetAllConsoles ();
+ mAllMenuInit = TRUE;
+}
+
+/**
+ Free up all Menu Option list.
+
+**/
+VOID
+FreeAllMenu (
+ VOID
+ )
+{
+ if (!mAllMenuInit){
+ return;
+ }
+ BOpt_FreeMenu (&BootOptionMenu);
+ BOpt_FreeMenu (&DriverOptionMenu);
+ BOpt_FreeMenu (&DriverMenu);
+ FreeAllConsoles ();
+ mAllMenuInit = FALSE;
+}
+
+/**
+ Initial the boot mode related parameters.
+
+**/
+VOID
+BmmInitialBootModeInfo (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
+ UINTN BootTextColumn;
+ UINTN BootTextRow;
+
+ if (mBmmModeInitialized) {
+ return;
+ }
+
+ //
+ // After the console is ready, get current video resolution
+ // and text mode before launching setup at first time.
+ //
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID**)&GraphicsOutput
+ );
+ if (EFI_ERROR (Status)) {
+ GraphicsOutput = NULL;
+ }
+
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiSimpleTextOutProtocolGuid,
+ (VOID**)&SimpleTextOut
+ );
+ if (EFI_ERROR (Status)) {
+ SimpleTextOut = NULL;
+ }
+
+ if (GraphicsOutput != NULL) {
+ //
+ // Get current video resolution and text mode.
+ //
+ mBmmBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
+ mBmmBootVerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;
+ }
+
+ if (SimpleTextOut != NULL) {
+ Status = SimpleTextOut->QueryMode (
+ SimpleTextOut,
+ SimpleTextOut->Mode->Mode,
+ &BootTextColumn,
+ &BootTextRow
+ );
+ mBmmBootTextModeColumn = (UINT32)BootTextColumn;
+ mBmmBootTextModeRow = (UINT32)BootTextRow;
+ }
+
+ //
+ // Get user defined text mode for setup.
+ //
+ mBmmSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
+ mBmmSetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution);
+ mBmmSetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn);
+ mBmmSetupTextModeRow = PcdGet32 (PcdSetupConOutRow);
+
+ mBmmModeInitialized = TRUE;
+}
+
+/**
+
+ Install Boot Maintenance Manager Menu driver.
+
+ @param ImageHandle The image handle.
+ @param SystemTable The system table.
+
+ @retval EFI_SUCEESS Install Boot manager menu success.
+ @retval Other Return error status.
+
+**/
+EFI_STATUS
+EFIAPI
+BootMaintenanceManagerUiLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+
+{
+ EFI_STATUS Status;
+ UINT8 *Ptr;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Install Device Path Protocol and Config Access protocol to driver handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mBmmCallbackInfo->BmmDriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mBmmHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mBmmCallbackInfo->BmmConfigAccess,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Post our Boot Maint VFR binary to the HII database.
+ //
+ mBmmCallbackInfo->BmmHiiHandle = HiiAddPackages (
+ &mBootMaintGuid,
+ mBmmCallbackInfo->BmmDriverHandle,
+ BootMaintenanceManagerBin,
+ BootMaintenanceManagerUiLibStrings,
+ NULL
+ );
+ ASSERT (mBmmCallbackInfo->BmmHiiHandle != NULL);
+
+ //
+ // Locate Formbrowser2 protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mBmmCallbackInfo->FormBrowser2);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create LoadOption in BmmCallbackInfo for Driver Callback
+ //
+ Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY));
+ ASSERT (Ptr != NULL);
+
+ //
+ // Initialize Bmm callback data.
+ //
+ mBmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;
+ Ptr += sizeof (BM_LOAD_CONTEXT);
+
+ mBmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;
+ Ptr += sizeof (BM_FILE_CONTEXT);
+
+ mBmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;
+ Ptr += sizeof (BM_HANDLE_CONTEXT);
+
+ mBmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr;
+
+ mBmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID;
+ mBmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID;
+
+ InitAllMenu (mBmmCallbackInfo);
+
+ CreateUpdateData();
+ //
+ // Update boot maintenance manager page
+ //
+ InitializeBmmConfig(mBmmCallbackInfo);
+
+ BmmInitialBootModeInfo();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unloads the application and its installed protocol.
+
+ @param ImageHandle Handle that identifies the image to be unloaded.
+ @param SystemTable The system table.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+
+**/
+EFI_STATUS
+EFIAPI
+BootMaintenanceManagerUiLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+
+{
+ if (mStartOpCodeHandle != NULL) {
+ HiiFreeOpCodeHandle (mStartOpCodeHandle);
+ }
+
+ if (mEndOpCodeHandle != NULL) {
+ HiiFreeOpCodeHandle (mEndOpCodeHandle);
+ }
+
+ FreeAllMenu ();
+
+ //
+ // Remove our IFR data from HII database
+ //
+ HiiRemovePackages (mBmmCallbackInfo->BmmHiiHandle);
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ mBmmCallbackInfo->BmmDriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mBmmHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mBmmCallbackInfo->BmmConfigAccess,
+ NULL
+ );
+
+ FreePool (mBmmCallbackInfo->LoadContext);
+ mBmmCallbackInfo->BmmDriverHandle = NULL;
+
+ return EFI_SUCCESS;
+}
+