summaryrefslogtreecommitdiff
path: root/MdeModulePkg
diff options
context:
space:
mode:
authorDandan Bi <dandan.bi@intel.com>2015-11-23 09:34:55 +0000
committerdandanbi <dandanbi@Edk2>2015-11-23 09:34:55 +0000
commit4af04335ac9aeb1802b995b102117b6f9de46809 (patch)
tree7272d503d4e06b8eded17235ffd9acf34d19e179 /MdeModulePkg
parent32465d9ae7eed891154780f0b13fabf0b15ae7c3 (diff)
downloadedk2-platforms-4af04335ac9aeb1802b995b102117b6f9de46809.tar.xz
MdeModulePkg:Create Boot Maintenance Manager Library
Split the boot maintenance manager library from UiApp in MdeModulePkg/Application and put the library in MdeModulePkg/Library. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Dandan Bi <dandan.bi@intel.com> Reviewed-by: Eric Dong <eric.dong@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18923 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Library/BootMaintenanceManagerLib/BmLib.c89
-rw-r--r--MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenance.c1512
-rw-r--r--MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManager.h1386
-rw-r--r--MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManager.vfr440
-rw-r--r--MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManagerLib.inf100
-rw-r--r--MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManagerStrings.unibin0 -> 43398 bytes
-rw-r--r--MdeModulePkg/Library/BootMaintenanceManagerLib/BootOption.c984
-rw-r--r--MdeModulePkg/Library/BootMaintenanceManagerLib/ConsoleOption.c1162
-rw-r--r--MdeModulePkg/Library/BootMaintenanceManagerLib/Data.c263
-rw-r--r--MdeModulePkg/Library/BootMaintenanceManagerLib/FormGuid.h209
-rw-r--r--MdeModulePkg/Library/BootMaintenanceManagerLib/UpdatePage.c1272
-rw-r--r--MdeModulePkg/Library/BootMaintenanceManagerLib/Variable.c1051
12 files changed, 8468 insertions, 0 deletions
diff --git a/MdeModulePkg/Library/BootMaintenanceManagerLib/BmLib.c b/MdeModulePkg/Library/BootMaintenanceManagerLib/BmLib.c
new file mode 100644
index 0000000000..0ef9bf0934
--- /dev/null
+++ b/MdeModulePkg/Library/BootMaintenanceManagerLib/BmLib.c
@@ -0,0 +1,89 @@
+/** @file
+Utility routines used by boot maintenance modules.
+
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BootMaintenanceManager.h"
+
+/**
+ Function deletes the variable specified by VarName and VarGuid.
+
+ @param VarName A Null-terminated Unicode string that is
+ the name of the vendor's variable.
+
+ @param VarGuid A unique identifier for the vendor.
+
+ @retval EFI_SUCCESS The variable was found and removed
+ @retval EFI_UNSUPPORTED The variable store was inaccessible
+ @retval EFI_NOT_FOUND The variable was not found
+
+**/
+EFI_STATUS
+EfiLibDeleteVariable (
+ IN CHAR16 *VarName,
+ IN EFI_GUID *VarGuid
+ )
+{
+ return gRT->SetVariable (
+ VarName,
+ VarGuid,
+ 0,
+ 0,
+ NULL
+ );
+}
+
+/**
+ Function is used to determine the number of device path instances
+ that exist in a device path.
+
+
+ @param DevicePath A pointer to a device path data structure.
+
+ @return This function counts and returns the number of device path instances
+ in DevicePath.
+
+**/
+UINTN
+EfiDevicePathInstanceCount (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ UINTN Count;
+ UINTN Size;
+
+ Count = 0;
+ while (GetNextDevicePathInstance (&DevicePath, &Size) != NULL) {
+ Count += 1;
+ }
+
+ return Count;
+}
+
+/**
+ Get a string from the Data Hub record based on
+ a device path.
+
+ @param DevPath The device Path.
+
+ @return A string located from the Data Hub records based on
+ the device path.
+ @retval NULL If failed to get the String from Data Hub.
+
+**/
+UINT16 *
+EfiLibStrFromDatahub (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath
+ )
+{
+ return NULL;
+}
diff --git a/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenance.c b/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenance.c
new file mode 100644
index 0000000000..9b0653c4a9
--- /dev/null
+++ b/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenance.c
@@ -0,0 +1,1512 @@
+/** @file
+The functions for Boot Maintainence Main menu.
+
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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;
+
+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;
+
+/**
+ 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
+ );
+
+/**
+ 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
+EFIAPI
+BmmBdsSetConsoleMode (
+ 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 requried 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 requried 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.
+ //
+ PcdSet32 (PcdConOutColumn, mBmmSetupTextModeColumn);
+ PcdSet32 (PcdConOutRow, mBmmSetupTextModeRow);
+ FreePool (Info);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ if (Index == MaxTextMode) {
+ //
+ // If requried 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.
+ //
+ PcdSet32 (PcdVideoHorizontalResolution, NewHorizontalResolution);
+ PcdSet32 (PcdVideoVerticalResolution, NewVerticalResolution);
+ PcdSet32 (PcdConOutColumn, NewColumns);
+ PcdSet32 (PcdConOutRow, NewRows);
+
+ //
+ // 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;
+
+ while(MatchString != NULL){
+ LastMatch = MatchString + 1;
+ MatchString = StrStr(LastMatch,L"\\");
+ }
+
+ Length = StrLen(LastMatch);
+ FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);
+ *(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);
+
+}
+
+/**
+ 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_CONSOLE_CONTEXT *NewConsoleContext;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT16 Index;
+ BOOLEAN TerminalAttChange;
+ BMM_CALLBACK_DATA *Private;
+
+ 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;
+ //
+ // 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);
+ }
+
+ //
+ // 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;
+ }
+
+ Var_DelBootOption ();
+ }
+
+ if (CompareMem (NewBmmData->BootOptionOrder, OldBmmData->BootOptionOrder, sizeof (NewBmmData->BootOptionOrder)) != 0) {
+ Status = Var_UpdateBootOrder (Private);
+ }
+
+ 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)
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ 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;
+ }
+ Var_DelDriverOption ();
+ }
+
+ if (CompareMem (NewBmmData->DriverOptionOrder, OldBmmData->DriverOptionOrder, sizeof (NewBmmData->DriverOptionOrder)) != 0) {
+ Status = Var_UpdateDriverOrder (Private);
+ }
+
+ if (CompareMem (&NewBmmData->ConsoleOutMode, &OldBmmData->ConsoleOutMode, sizeof (NewBmmData->ConsoleOutMode)) != 0){
+ Var_UpdateConMode(Private);
+ }
+
+ 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;
+ }
+
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ ASSERT (NewMenuEntry != NULL);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ NewTerminalContext->BaudRateIndex = NewBmmData->COMBaudRate[Index];
+ ASSERT (NewBmmData->COMBaudRate[Index] < (sizeof (BaudRateList) / sizeof (BaudRateList[0])));
+ NewTerminalContext->BaudRate = BaudRateList[NewBmmData->COMBaudRate[Index]].Value;
+ NewTerminalContext->DataBitsIndex = NewBmmData->COMDataRate[Index];
+ ASSERT (NewBmmData->COMDataRate[Index] < (sizeof (DataBitsList) / sizeof (DataBitsList[0])));
+ NewTerminalContext->DataBits = (UINT8) DataBitsList[NewBmmData->COMDataRate[Index]].Value;
+ NewTerminalContext->StopBitsIndex = NewBmmData->COMStopBits[Index];
+ ASSERT (NewBmmData->COMStopBits[Index] < (sizeof (StopBitsList) / sizeof (StopBitsList[0])));
+ NewTerminalContext->StopBits = (UINT8) StopBitsList[NewBmmData->COMStopBits[Index]].Value;
+ NewTerminalContext->ParityIndex = NewBmmData->COMParity[Index];
+ ASSERT (NewBmmData->COMParity[Index] < (sizeof (ParityList) / sizeof (ParityList[0])));
+ NewTerminalContext->Parity = (UINT8) ParityList[NewBmmData->COMParity[Index]].Value;
+ NewTerminalContext->TerminalType = NewBmmData->COMTerminalType[Index];
+ NewTerminalContext->FlowControl = NewBmmData->COMFlowControl[Index];
+ ChangeTerminalDevicePath (
+ NewTerminalContext->DevicePath,
+ FALSE
+ );
+ TerminalAttChange = TRUE;
+ }
+ if (TerminalAttChange) {
+ Var_UpdateConsoleInpOption ();
+ Var_UpdateConsoleOutOption ();
+ Var_UpdateErrorOutOption ();
+ }
+ //
+ // Check data which located in Console Options Menu and save the settings if need
+ //
+ if (CompareMem (NewBmmData->ConsoleInCheck, OldBmmData->ConsoleInCheck, sizeof (NewBmmData->ConsoleInCheck)) != 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 = NewBmmData->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 = NewBmmData->ConsoleInCheck[Index + ConsoleInpMenu.MenuNumber];
+ }
+ Var_UpdateConsoleInpOption();
+ }
+
+ if (CompareMem (NewBmmData->ConsoleOutCheck, OldBmmData->ConsoleOutCheck, sizeof (NewBmmData->ConsoleOutCheck)) != 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 = NewBmmData->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 = NewBmmData->ConsoleOutCheck[Index + ConsoleOutMenu.MenuNumber];
+ }
+ Var_UpdateConsoleOutOption();
+ }
+
+ if (CompareMem (NewBmmData->ConsoleErrCheck, OldBmmData->ConsoleErrCheck, sizeof (NewBmmData->ConsoleErrCheck)) != 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 = NewBmmData->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 = NewBmmData->ConsoleErrCheck[Index + ConsoleErrMenu.MenuNumber];
+ }
+ Var_UpdateErrorOutOption();
+ }
+
+ 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)) {
+ return Status;
+ }
+ 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)) {
+ return Status;
+ }
+
+ BOpt_GetDriverOptions (Private);
+ }
+
+ //
+ // After user do the save action, need to update OldBmmData.
+ //
+ CopyMem (OldBmmData, NewBmmData, sizeof (BMM_FAKE_NV_DATA));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ 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;
+ UINTN OldValue;
+ UINTN NewValue;
+ UINTN Number;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL * File;
+
+ if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) {
+ //
+ // Do nothing for other UEFI Action. Only do call back when data is changed.
+ //
+ return EFI_UNSUPPORTED;
+ }
+ OldValue = 0;
+ NewValue = 0;
+ Number = 0;
+
+ Private = BMM_CALLBACK_DATA_FROM_THIS (This);
+ //
+ // Retrive uncommitted data from Form Browser
+ //
+ CurrentFakeNVMap = &Private->BmmFakeNvData;
+ 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", (CHOOSE_HANDLER) CreateBootOptionFromFile, &File);
+ break;
+
+ case FORM_DRV_ADD_FILE_ID:
+ // Leave BMM and enter FileExplorer.
+ ChooseFile( NULL, L".efi", (CHOOSE_HANDLER) 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_BOOT_NEXT_ID:
+ CleanUpPage (FORM_BOOT_NEXT_ID, Private);
+ UpdateBootNextPage (Private);
+ break;
+
+ case FORM_TIME_OUT_ID:
+ CleanUpPage (FORM_TIME_OUT_ID, Private);
+ UpdateTimeOutPage (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", (CHOOSE_HANDLER) 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) {
+ CurrentFakeNVMap->BootOptionChanged = FALSE;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
+ } else if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) {
+ 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
+ //
+ CurrentFakeNVMap->DriverOptionalData[0] = 0x0000;
+ CurrentFakeNVMap->DriverDescriptionData[0] = 0x0000;
+ 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
+ //
+ CurrentFakeNVMap->BootOptionalData[0] = 0x0000;
+ CurrentFakeNVMap->BootDescriptionData[0] = 0x0000;
+ 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) {
+ *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;
+ }
+ }
+ }
+
+ //
+ // 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;
+ }
+}
+
+/**
+ Create dynamic code for BMM.
+
+ @param BmmCallbackInfo The BMM context data.
+
+**/
+VOID
+InitializeDrivers(
+ IN BMM_CALLBACK_DATA *BmmCallbackInfo
+ )
+{
+ EFI_HII_HANDLE HiiHandle;
+ VOID *StartOpCodeHandle;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ EFI_IFR_GUID_LABEL *EndLabel;
+ UINTN Index;
+ EFI_STRING String;
+ EFI_STRING_ID Token;
+ EFI_STRING_ID TokenHelp;
+ EFI_HII_HANDLE *HiiHandles;
+ EFI_GUID FormSetGuid;
+ CHAR16 *DevicePathStr;
+ EFI_STRING_ID DevicePathId;
+ EFI_IFR_FORM_SET *Buffer;
+ UINTN BufferSize;
+ UINT8 ClassGuidNum;
+ EFI_GUID *ClassGuid;
+ UINTN TempSize;
+ UINT8 *Ptr;
+ EFI_STATUS Status;
+
+ TempSize =0;
+ BufferSize = 0;
+ Buffer = NULL;
+
+ HiiHandle = BmmCallbackInfo->BmmHiiHandle;
+ //
+ // 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
+ //
+ StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ StartLabel->Number = LABEL_BMM_PLATFORM_INFORMATION;
+
+ //
+ // Create Hii Extend Label OpCode as the end opcode
+ //
+ EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ EndLabel->Number = LABEL_END;
+
+ //
+ // Get all the Hii handles
+ //
+ HiiHandles = HiiGetHiiHandles (NULL);
+ ASSERT (HiiHandles != NULL);
+
+ //
+ // Search for formset of each class type
+ //
+ for (Index = 0; HiiHandles[Index] != NULL; Index++) {
+ Status = HiiGetFormSetFromHiiHandle(HiiHandles[Index], &Buffer,&BufferSize);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Ptr = (UINT8 *)Buffer;
+ while(TempSize < BufferSize) {
+ TempSize += ((EFI_IFR_OP_HEADER *) Ptr)->Length;
+
+ if (((EFI_IFR_OP_HEADER *) Ptr)->Length <= OFFSET_OF (EFI_IFR_FORM_SET, Flags)){
+ Ptr += ((EFI_IFR_OP_HEADER *) Ptr)->Length;
+ continue;
+ }
+
+ //
+ // Find FormSet OpCode
+ //
+ ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *)Ptr)->Flags & 0x3);
+ ClassGuid = (EFI_GUID *) (VOID *)(Ptr + sizeof (EFI_IFR_FORM_SET));
+ while (ClassGuidNum-- > 0) {
+ if (CompareGuid (&gEfiIfrBootMaintenanceGuid, ClassGuid) == 0){
+ ClassGuid ++;
+ continue;
+ }
+
+ String = HiiGetString (HiiHandles[Index], ((EFI_IFR_FORM_SET *)Ptr)->FormSetTitle, NULL);
+ if (String == NULL) {
+ String = HiiGetString (HiiHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);
+ ASSERT (String != NULL);
+ }
+ Token = HiiSetString (HiiHandle, 0, String, NULL);
+ FreePool (String);
+
+ String = HiiGetString (HiiHandles[Index], ((EFI_IFR_FORM_SET *)Ptr)->Help, NULL);
+ if (String == NULL) {
+ String = HiiGetString (HiiHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);
+ ASSERT (String != NULL);
+ }
+ TokenHelp = HiiSetString (HiiHandle, 0, String, NULL);
+ FreePool (String);
+
+ FormSetGuid = ((EFI_IFR_FORM_SET *)Ptr)->Guid;
+
+ DevicePathStr = BmmExtractDevicePathFromHiiHandle(HiiHandles[Index]);
+ DevicePathId = 0;
+ if (DevicePathStr != NULL){
+ DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL);
+ FreePool (DevicePathStr);
+ }
+ HiiCreateGotoExOpCode (
+ StartOpCodeHandle,
+ 0,
+ Token,
+ TokenHelp,
+ 0,
+ (EFI_QUESTION_ID) (Index + FRONT_PAGE_KEY_OFFSET),
+ 0,
+ &FormSetGuid,
+ DevicePathId
+ );
+ break;
+ }
+ Ptr += ((EFI_IFR_OP_HEADER *) Ptr)->Length;
+ }
+
+ FreePool(Buffer);
+ Buffer = NULL;
+ TempSize = 0;
+ BufferSize = 0;
+ }
+
+ HiiUpdateForm (
+ HiiHandle,
+ &mBootMaintGuid,
+ FORM_MAIN_ID,
+ StartOpCodeHandle,
+ EndOpCodeHandle
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+ FreePool (HiiHandles);
+}
+
+/**
+ 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);
+
+ InitializeDrivers (CallbackData);
+
+ //
+ // Initialize data which located in BMM main page
+ //
+ CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber);
+ 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;
+}
+
+/**
+
+ 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
+BootMaintenanceManagerLibConstructor (
+ 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,
+ BootMaintenanceManagerLibStrings,
+ NULL
+ );
+ ASSERT (mBmmCallbackInfo->BmmHiiHandle != NULL);
+
+ //
+ // Locate Formbrowser2 protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mBmmCallbackInfo->FormBrowser2);
+ ASSERT_EFI_ERROR (Status);
+
+ EfiBootManagerRefreshAllBootOption ();
+
+ //
+ // 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);
+
+ 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
+BootMaintenanceManagerLibDestructor (
+ 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);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManager.h b/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManager.h
new file mode 100644
index 0000000000..6934a692a6
--- /dev/null
+++ b/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManager.h
@@ -0,0 +1,1386 @@
+/** @file
+Header file for boot maintenance module.
+
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _BOOT_MAINT_H_
+#define _BOOT_MAINT_H_
+
+#include "FormGuid.h"
+
+#include <Guid/TtyTerm.h>
+#include <Guid/MdeModuleHii.h>
+#include <Guid/FileSystemVolumeLabelInfo.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/HiiBootMaintenanceFormset.h>
+
+#include <Protocol/LoadFile.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/SerialIo.h>
+#include <Protocol/DevicePathToText.h>
+
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/UefiHiiServicesLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/FileExplorerLib.h>
+
+#pragma pack(1)
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+#pragma pack()
+
+//
+// Constants which are variable names used to access variables
+//
+
+#define VAR_CON_OUT_MODE L"ConOutMode"
+
+//
+// Variable created with this flag will be "Efi:...."
+//
+#define VAR_FLAG EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE
+
+extern EFI_GUID mBootMaintGuid;
+extern CHAR16 mBootMaintStorageName[];
+//
+// These are the VFR compiler generated data representing our VFR data.
+//
+extern UINT8 BootMaintenanceManagerBin[];
+
+//
+// Below are the number of options in Baudrate, Databits,
+// Parity and Stopbits selection for serial ports.
+//
+#define BM_COM_ATTR_BUADRATE 19
+#define BM_COM_ATTR_DATABITS 4
+#define BM_COM_ATTR_PARITY 5
+#define BM_COM_ATTR_STOPBITS 3
+
+//
+// Callback function helper
+//
+#define BMM_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('C', 'b', 'c', 'k')
+#define BMM_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, BmmConfigAccess, BMM_CALLBACK_DATA_SIGNATURE)
+
+//
+// Enumeration type definition
+//
+typedef UINT8 BBS_TYPE;
+
+typedef enum _TYPE_OF_TERMINAL {
+ TerminalTypePcAnsi = 0,
+ TerminalTypeVt100,
+ TerminalTypeVt100Plus,
+ TerminalTypeVtUtf8,
+ TerminalTypeTtyTerm
+} TYPE_OF_TERMINAL;
+
+//
+// All of the signatures that will be used in list structure
+//
+#define BM_MENU_OPTION_SIGNATURE SIGNATURE_32 ('m', 'e', 'n', 'u')
+#define BM_LOAD_OPTION_SIGNATURE SIGNATURE_32 ('l', 'o', 'a', 'd')
+#define BM_CONSOLE_OPTION_SIGNATURE SIGNATURE_32 ('c', 'n', 's', 'l')
+#define BM_FILE_OPTION_SIGNATURE SIGNATURE_32 ('f', 'i', 'l', 'e')
+#define BM_HANDLE_OPTION_SIGNATURE SIGNATURE_32 ('h', 'n', 'd', 'l')
+#define BM_TERMINAL_OPTION_SIGNATURE SIGNATURE_32 ('t', 'r', 'm', 'l')
+#define BM_MENU_ENTRY_SIGNATURE SIGNATURE_32 ('e', 'n', 't', 'r')
+
+#define BM_LOAD_CONTEXT_SELECT 0x0
+#define BM_CONSOLE_CONTEXT_SELECT 0x1
+#define BM_FILE_CONTEXT_SELECT 0x2
+#define BM_HANDLE_CONTEXT_SELECT 0x3
+#define BM_TERMINAL_CONTEXT_SELECT 0x5
+
+#define BM_CONSOLE_IN_CONTEXT_SELECT 0x6
+#define BM_CONSOLE_OUT_CONTEXT_SELECT 0x7
+#define BM_CONSOLE_ERR_CONTEXT_SELECT 0x8
+
+//
+// Buffer size for update data
+//
+#define UPDATE_DATA_SIZE 0x100000
+
+//
+// Namespace of callback keys used in display and file system navigation
+//
+#define MAX_BBS_OFFSET 0xE000
+#define NET_OPTION_OFFSET 0xD800
+#define BEV_OPTION_OFFSET 0xD000
+#define FD_OPTION_OFFSET 0xC000
+#define HD_OPTION_OFFSET 0xB000
+#define CD_OPTION_OFFSET 0xA000
+#define FILE_OPTION_OFFSET 0x8000
+#define FILE_OPTION_MASK 0x7FFF
+#define HANDLE_OPTION_OFFSET 0x7000
+#define CONSOLE_OPTION_OFFSET 0x6000
+#define TERMINAL_OPTION_OFFSET 0x5000
+#define CONFIG_OPTION_OFFSET 0x1200
+#define KEY_VALUE_OFFSET 0x1100
+#define FORM_ID_OFFSET 0x1000
+
+//
+// VarOffset that will be used to create question
+// all these values are computed from the structure
+// defined below
+//
+#define VAR_OFFSET(Field) ((UINT16) ((UINTN) &(((BMM_FAKE_NV_DATA *) 0)->Field)))
+
+//
+// Question Id of Zero is invalid, so add an offset to it
+//
+#define QUESTION_ID(Field) (VAR_OFFSET (Field) + CONFIG_OPTION_OFFSET)
+
+#define BOOT_TIME_OUT_VAR_OFFSET VAR_OFFSET (BootTimeOut)
+#define BOOT_NEXT_VAR_OFFSET VAR_OFFSET (BootNext)
+#define COM1_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM1BaudRate)
+#define COM1_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM1DataRate)
+#define COM1_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM1StopBits)
+#define COM1_PARITY_VAR_OFFSET VAR_OFFSET (COM1Parity)
+#define COM1_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType)
+#define COM2_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM2BaudRate)
+#define COM2_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM2DataRate)
+#define COM2_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM2StopBits)
+#define COM2_PARITY_VAR_OFFSET VAR_OFFSET (COM2Parity)
+#define COM2_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType)
+#define DRV_ADD_HANDLE_DESC_VAR_OFFSET VAR_OFFSET (DriverAddHandleDesc)
+#define DRV_ADD_ACTIVE_VAR_OFFSET VAR_OFFSET (DriverAddActive)
+#define DRV_ADD_RECON_VAR_OFFSET VAR_OFFSET (DriverAddForceReconnect)
+#define CON_IN_COM1_VAR_OFFSET VAR_OFFSET (ConsoleInputCOM1)
+#define CON_IN_COM2_VAR_OFFSET VAR_OFFSET (ConsoleInputCOM2)
+#define CON_OUT_COM1_VAR_OFFSET VAR_OFFSET (ConsoleOutputCOM1)
+#define CON_OUT_COM2_VAR_OFFSET VAR_OFFSET (ConsoleOutputCOM2)
+#define CON_ERR_COM1_VAR_OFFSET VAR_OFFSET (ConsoleErrorCOM1)
+#define CON_ERR_COM2_VAR_OFFSET VAR_OFFSET (ConsoleErrorCOM2)
+#define CON_MODE_VAR_OFFSET VAR_OFFSET (ConsoleOutMode)
+#define CON_DEVICE_VAR_OFFSET VAR_OFFSET (ConsoleCheck)
+#define CON_IN_DEVICE_VAR_OFFSET VAR_OFFSET (ConsoleInCheck)
+#define CON_OUT_DEVICE_VAR_OFFSET VAR_OFFSET (ConsoleOutCheck)
+#define CON_ERR_DEVICE_VAR_OFFSET VAR_OFFSET (ConsoleErrCheck)
+#define BOOT_OPTION_ORDER_VAR_OFFSET VAR_OFFSET (BootOptionOrder)
+#define DRIVER_OPTION_ORDER_VAR_OFFSET VAR_OFFSET (DriverOptionOrder)
+#define BOOT_OPTION_DEL_VAR_OFFSET VAR_OFFSET (BootOptionDel)
+#define DRIVER_OPTION_DEL_VAR_OFFSET VAR_OFFSET (DriverOptionDel)
+#define DRIVER_ADD_OPTION_VAR_OFFSET VAR_OFFSET (DriverAddHandleOptionalData)
+#define COM_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COMBaudRate)
+#define COM_DATA_RATE_VAR_OFFSET VAR_OFFSET (COMDataRate)
+#define COM_STOP_BITS_VAR_OFFSET VAR_OFFSET (COMStopBits)
+#define COM_PARITY_VAR_OFFSET VAR_OFFSET (COMParity)
+#define COM_TERMINAL_VAR_OFFSET VAR_OFFSET (COMTerminalType)
+#define COM_FLOWCONTROL_VAR_OFFSET VAR_OFFSET (COMFlowControl)
+
+#define BOOT_TIME_OUT_QUESTION_ID QUESTION_ID (BootTimeOut)
+#define BOOT_NEXT_QUESTION_ID QUESTION_ID (BootNext)
+#define COM1_BAUD_RATE_QUESTION_ID QUESTION_ID (COM1BaudRate)
+#define COM1_DATA_RATE_QUESTION_ID QUESTION_ID (COM1DataRate)
+#define COM1_STOP_BITS_QUESTION_ID QUESTION_ID (COM1StopBits)
+#define COM1_PARITY_QUESTION_ID QUESTION_ID (COM1Parity)
+#define COM1_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType)
+#define COM2_BAUD_RATE_QUESTION_ID QUESTION_ID (COM2BaudRate)
+#define COM2_DATA_RATE_QUESTION_ID QUESTION_ID (COM2DataRate)
+#define COM2_STOP_BITS_QUESTION_ID QUESTION_ID (COM2StopBits)
+#define COM2_PARITY_QUESTION_ID QUESTION_ID (COM2Parity)
+#define COM2_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType)
+#define DRV_ADD_HANDLE_DESC_QUESTION_ID QUESTION_ID (DriverAddHandleDesc)
+#define DRV_ADD_ACTIVE_QUESTION_ID QUESTION_ID (DriverAddActive)
+#define DRV_ADD_RECON_QUESTION_ID QUESTION_ID (DriverAddForceReconnect)
+#define CON_IN_COM1_QUESTION_ID QUESTION_ID (ConsoleInputCOM1)
+#define CON_IN_COM2_QUESTION_ID QUESTION_ID (ConsoleInputCOM2)
+#define CON_OUT_COM1_QUESTION_ID QUESTION_ID (ConsoleOutputCOM1)
+#define CON_OUT_COM2_QUESTION_ID QUESTION_ID (ConsoleOutputCOM2)
+#define CON_ERR_COM1_QUESTION_ID QUESTION_ID (ConsoleErrorCOM1)
+#define CON_ERR_COM2_QUESTION_ID QUESTION_ID (ConsoleErrorCOM2)
+#define CON_MODE_QUESTION_ID QUESTION_ID (ConsoleOutMode)
+#define CON_DEVICE_QUESTION_ID QUESTION_ID (ConsoleCheck)
+#define CON_IN_DEVICE_QUESTION_ID QUESTION_ID (ConsoleInCheck)
+#define CON_OUT_DEVICE_QUESTION_ID QUESTION_ID (ConsoleOutCheck)
+#define CON_ERR_DEVICE_QUESTION_ID QUESTION_ID (ConsoleErrCheck)
+#define BOOT_OPTION_ORDER_QUESTION_ID QUESTION_ID (BootOptionOrder)
+#define DRIVER_OPTION_ORDER_QUESTION_ID QUESTION_ID (DriverOptionOrder)
+#define BOOT_OPTION_DEL_QUESTION_ID QUESTION_ID (BootOptionDel)
+#define DRIVER_OPTION_DEL_QUESTION_ID QUESTION_ID (DriverOptionDel)
+#define DRIVER_ADD_OPTION_QUESTION_ID QUESTION_ID (DriverAddHandleOptionalData)
+#define COM_BAUD_RATE_QUESTION_ID QUESTION_ID (COMBaudRate)
+#define COM_DATA_RATE_QUESTION_ID QUESTION_ID (COMDataRate)
+#define COM_STOP_BITS_QUESTION_ID QUESTION_ID (COMStopBits)
+#define COM_PARITY_QUESTION_ID QUESTION_ID (COMParity)
+#define COM_TERMINAL_QUESTION_ID QUESTION_ID (COMTerminalType)
+#define COM_FLOWCONTROL_QUESTION_ID QUESTION_ID (COMFlowControl)
+
+#define STRING_DEPOSITORY_NUMBER 8
+
+///
+/// Serial Ports attributes, first one is the value for
+/// return from callback function, stringtoken is used to
+/// display the value properly
+///
+typedef struct {
+ UINTN Value;
+ UINT16 StringToken;
+} COM_ATTR;
+
+typedef struct {
+ UINT64 BaudRate;
+ UINT8 DataBits;
+ UINT8 Parity;
+ UINT8 StopBits;
+
+ UINT8 BaudRateIndex;
+ UINT8 DataBitsIndex;
+ UINT8 ParityIndex;
+ UINT8 StopBitsIndex;
+
+ UINT8 FlowControl;
+
+ UINT8 IsConIn;
+ UINT8 IsConOut;
+ UINT8 IsStdErr;
+ UINT8 TerminalType;
+
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+} BM_TERMINAL_CONTEXT;
+
+typedef struct {
+ BOOLEAN IsBootNext;
+ BOOLEAN LoadOptionModified;
+ BOOLEAN Deleted;
+
+ BOOLEAN IsLegacy;
+ BOOLEAN IsActive;
+ BOOLEAN ForceReconnect;
+ UINTN OptionalDataSize;
+
+ UINTN LoadOptionSize;
+ UINT8 *LoadOption;
+
+ UINT32 Attributes;
+ UINT16 FilePathListLength;
+ UINT16 *Description;
+ EFI_DEVICE_PATH_PROTOCOL *FilePathList;
+ UINT8 *OptionalData;
+
+ UINT16 BbsIndex;
+} BM_LOAD_CONTEXT;
+
+typedef struct {
+
+ BOOLEAN IsActive;
+
+ BOOLEAN IsTerminal;
+
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+} BM_CONSOLE_CONTEXT;
+
+typedef struct {
+ UINTN Column;
+ UINTN Row;
+} CONSOLE_OUT_MODE;
+
+typedef struct {
+ EFI_HANDLE Handle;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_FILE_HANDLE FHandle;
+ UINT16 *FileName;
+ EFI_FILE_SYSTEM_VOLUME_LABEL *Info;
+
+ BOOLEAN IsRoot;
+ BOOLEAN IsDir;
+ BOOLEAN IsRemovableMedia;
+ BOOLEAN IsLoadFile;
+ BOOLEAN IsBootLegacy;
+} BM_FILE_CONTEXT;
+
+typedef struct {
+ EFI_HANDLE Handle;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+} BM_HANDLE_CONTEXT;
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Head;
+ UINTN MenuNumber;
+} BM_MENU_OPTION;
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ UINTN OptionNumber;
+ UINT16 *DisplayString;
+ UINT16 *HelpString;
+ EFI_STRING_ID DisplayStringToken;
+ EFI_STRING_ID HelpStringToken;
+ UINTN ContextSelection;
+ VOID *VariableContext;
+} BM_MENU_ENTRY;
+
+typedef struct {
+
+ UINTN Signature;
+
+ EFI_HII_HANDLE BmmHiiHandle;
+ EFI_HANDLE BmmDriverHandle;
+ ///
+ /// Boot Maintenance Manager Produced protocols
+ ///
+ EFI_HII_CONFIG_ACCESS_PROTOCOL BmmConfigAccess;
+ EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
+
+ BM_MENU_ENTRY *MenuEntry;
+ BM_HANDLE_CONTEXT *HandleContext;
+ BM_FILE_CONTEXT *FileContext;
+ BM_LOAD_CONTEXT *LoadContext;
+ BM_TERMINAL_CONTEXT *TerminalContext;
+ UINTN CurrentTerminal;
+ BBS_TYPE BbsType;
+
+ //
+ // BMM main formset callback data.
+ //
+
+ EFI_FORM_ID BmmCurrentPageId;
+ EFI_FORM_ID BmmPreviousPageId;
+ BOOLEAN BmmAskSaveOrNot;
+ BMM_FAKE_NV_DATA BmmFakeNvData;
+ BMM_FAKE_NV_DATA BmmOldFakeNVData;
+
+} BMM_CALLBACK_DATA;
+
+/**
+
+ Find drivers that will be added as Driver#### variables from handles
+ in current system environment
+ All valid handles in the system except those consume SimpleFs, LoadFile
+ are stored in DriverMenu for future use.
+
+ @retval EFI_SUCCESS The function complets successfully.
+ @return Other value if failed to build the DriverMenu.
+
+**/
+EFI_STATUS
+BOpt_FindDrivers (
+ VOID
+ );
+
+/**
+
+ Build the BootOptionMenu according to BootOrder Variable.
+ This Routine will access the Boot#### to get EFI_LOAD_OPTION.
+
+ @param CallbackData The BMM context data.
+
+ @return The number of the Var Boot####.
+
+**/
+EFI_STATUS
+BOpt_GetBootOptions (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+
+ Build up all DriverOptionMenu
+
+ @param CallbackData The BMM context data.
+
+ @return EFI_SUCESS The functin completes successfully.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.
+
+
+**/
+EFI_STATUS
+BOpt_GetDriverOptions (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Free resources allocated in Allocate Rountine.
+
+ @param FreeMenu Menu to be freed
+
+**/
+VOID
+BOpt_FreeMenu (
+ BM_MENU_OPTION *FreeMenu
+ );
+
+/**
+
+ Get the Option Number that has not been allocated for use.
+
+ @param Type The type of Option.
+
+ @return The available Option Number.
+
+**/
+UINT16
+BOpt_GetOptionNumber (
+ CHAR16 *Type
+ );
+
+/**
+
+ Get the Option Number for Boot#### that does not used.
+
+ @return The available Option Number.
+
+**/
+UINT16
+BOpt_GetBootOptionNumber (
+ VOID
+ );
+
+/**
+
+Get the Option Number for Driver#### that does not used.
+
+@return The unused Option Number.
+
+**/
+UINT16
+BOpt_GetDriverOptionNumber (
+ VOID
+ );
+
+/**
+ Create a menu entry give a Menu type.
+
+ @param MenuType The Menu type to be created.
+
+
+ @retval NULL If failed to create the menu.
+ @return The menu.
+
+**/
+BM_MENU_ENTRY *
+BOpt_CreateMenuEntry (
+ UINTN MenuType
+ );
+
+/**
+ Free up all resource allocated for a BM_MENU_ENTRY.
+
+ @param MenuEntry A pointer to BM_MENU_ENTRY.
+
+**/
+VOID
+BOpt_DestroyMenuEntry (
+ BM_MENU_ENTRY *MenuEntry
+ );
+
+/**
+ Get the Menu Entry from the list in Menu Entry List.
+
+ If MenuNumber is great or equal to the number of Menu
+ Entry in the list, then ASSERT.
+
+ @param MenuOption The Menu Entry List to read the menu entry.
+ @param MenuNumber The index of Menu Entry.
+
+ @return The Menu Entry.
+
+**/
+BM_MENU_ENTRY *
+BOpt_GetMenuEntry (
+ BM_MENU_OPTION *MenuOption,
+ UINTN MenuNumber
+ );
+
+/**
+ Get option number according to Boot#### and BootOrder variable.
+ The value is saved as #### + 1.
+
+ @param CallbackData The BMM context data.
+**/
+VOID
+GetBootOrder (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Get driver option order from globalc DriverOptionMenu.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+GetDriverOrder (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+//
+// Locate all serial io devices for console
+//
+/**
+ Build a list containing all serial devices.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @retval EFI_UNSUPPORTED No serial ports present.
+
+**/
+EFI_STATUS
+LocateSerialIo (
+ VOID
+ );
+
+//
+// Initializing Console menu
+//
+/**
+ Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
+
+ @retval EFI_SUCCESS The function always complete successfully.
+
+**/
+EFI_STATUS
+GetAllConsoles(
+ VOID
+ );
+
+//
+// Get current mode information
+//
+/**
+ Get mode number according to column and row
+
+ @param CallbackData The BMM context data.
+**/
+VOID
+GetConsoleOutMode (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+//
+// Cleaning up console menu
+//
+/**
+ Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
+
+ @retval EFI_SUCCESS The function always complete successfully.
+**/
+EFI_STATUS
+FreeAllConsoles (
+ VOID
+ );
+
+/**
+ Update the device path that describing a terminal device
+ based on the new BaudRate, Data Bits, parity and Stop Bits
+ set.
+
+ @param DevicePath The devicepath protocol instance wanted to be updated.
+
+**/
+VOID
+ChangeVariableDevicePath (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+/**
+ Update the multi-instance device path of Terminal Device based on
+ the global TerminalMenu. If ChangeTernimal is TRUE, the terminal
+ device path in the Terminal Device in TerminalMenu is also updated.
+
+ @param DevicePath The multi-instance device path.
+ @param ChangeTerminal TRUE, then device path in the Terminal Device
+ in TerminalMenu is also updated; FALSE, no update.
+
+ @return EFI_SUCCESS The function completes successfully.
+
+**/
+EFI_STATUS
+ChangeTerminalDevicePath (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN BOOLEAN ChangeTerminal
+ );
+
+//
+// Variable operation by menu selection
+//
+/**
+ This function create a currently loaded Boot Option from
+ the BMM. It then appends this Boot Option to the end of
+ the "BootOrder" list. It also append this Boot Opotion to the end
+ of BootOptionMenu.
+
+ @param CallbackData The BMM context data.
+
+ @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
+ @retval EFI_SUCCESS If function completes successfully.
+
+**/
+EFI_STATUS
+Var_UpdateBootOption (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Delete Boot Option that represent a Deleted state in BootOptionMenu.
+ After deleting this boot option, call Var_ChangeBootOrder to
+ make sure BootOrder is in valid state.
+
+ @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to
+ BM_LOAD_CONTEXT marked for deletion is deleted
+ @return Others If failed to update the "BootOrder" variable after deletion.
+
+**/
+EFI_STATUS
+Var_DelBootOption (
+ VOID
+ );
+
+/**
+ After any operation on Boot####, there will be a discrepancy in BootOrder.
+ Since some are missing but in BootOrder, while some are present but are
+ not reflected by BootOrder. Then a function rebuild BootOrder from
+ scratch by content from BootOptionMenu is needed.
+
+ @retval EFI_SUCCESS The boot order is updated successfully.
+ @return other than EFI_SUCCESS if failed to change the "BootOrder" EFI Variable.
+
+**/
+EFI_STATUS
+Var_ChangeBootOrder (
+ VOID
+ );
+
+/**
+ This function create a currently loaded Drive Option from
+ the BMM. It then appends this Driver Option to the end of
+ the "DriverOrder" list. It append this Driver Opotion to the end
+ of DriverOptionMenu.
+
+ @param CallbackData The BMM context data.
+ @param HiiHandle The HII handle associated with the BMM formset.
+ @param DescriptionData The description of this driver option.
+ @param OptionalData The optional load option.
+ @param ForceReconnect If to force reconnect.
+
+ @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
+ @retval EFI_SUCCESS If function completes successfully.
+
+**/
+EFI_STATUS
+Var_UpdateDriverOption (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN UINT16 *DescriptionData,
+ IN UINT16 *OptionalData,
+ IN UINT8 ForceReconnect
+ );
+
+/**
+ Delete Load Option that represent a Deleted state in BootOptionMenu.
+ After deleting this Driver option, call Var_ChangeDriverOrder to
+ make sure DriverOrder is in valid state.
+
+ @retval EFI_SUCCESS Load Option is successfully updated.
+ @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI
+ Variable.
+
+**/
+EFI_STATUS
+Var_DelDriverOption (
+ VOID
+ );
+
+/**
+ After any operation on Driver####, there will be a discrepancy in
+ DriverOrder. Since some are missing but in DriverOrder, while some
+ are present but are not reflected by DriverOrder. Then a function
+ rebuild DriverOrder from scratch by content from DriverOptionMenu is
+ needed.
+
+ @retval EFI_SUCCESS The driver order is updated successfully.
+ @return other than EFI_SUCCESS if failed to set the "DriverOrder" EFI Variable.
+
+**/
+EFI_STATUS
+Var_ChangeDriverOrder (
+ VOID
+ );
+
+/**
+ This function delete and build multi-instance device path ConIn
+ console device.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
+**/
+EFI_STATUS
+Var_UpdateConsoleInpOption (
+ VOID
+ );
+
+/**
+ This function delete and build multi-instance device path ConOut console device.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
+**/
+EFI_STATUS
+Var_UpdateConsoleOutOption (
+ VOID
+ );
+
+/**
+ This function delete and build multi-instance device path ErrOut console device.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
+**/
+EFI_STATUS
+Var_UpdateErrorOutOption (
+ VOID
+ );
+
+/**
+ This function delete and build Out of Band console device.
+
+ @param MenuIndex Menu index which user select in the terminal menu list.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
+**/
+EFI_STATUS
+Var_UpdateOutOfBandOption (
+ IN UINT16 MenuIndex
+ );
+
+/**
+ Update the device path of "ConOut", "ConIn" and "ErrOut" based on the new BaudRate, Data Bits,
+ parity and stop Bits set.
+
+**/
+VOID
+Var_UpdateAllConsoleOption (
+ VOID
+ );
+
+/**
+ This function update the "BootNext" EFI Variable. If there is no "BootNex" specified in BMM,
+ this EFI Variable is deleted.
+ It also update the BMM context data specified the "BootNext" value.
+
+ @param CallbackData The BMM context data.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
+
+**/
+EFI_STATUS
+Var_UpdateBootNext (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ This function update the "BootOrder" EFI Variable based on BMM Formset's NV map. It then refresh
+ BootOptionMenu with the new "BootOrder" list.
+
+ @param CallbackData The BMM context data.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
+ @return not The EFI variable can not be saved. See gRT->SetVariable for detail return information.
+
+**/
+EFI_STATUS
+Var_UpdateBootOrder (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ This function update the "DriverOrder" EFI Variable based on
+ BMM Formset's NV map. It then refresh DriverOptionMenu
+ with the new "DriverOrder" list.
+
+ @param CallbackData The BMM context data.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
+
+**/
+EFI_STATUS
+Var_UpdateDriverOrder (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Update the Text Mode of Console.
+
+ @param CallbackData The context data for BMM.
+
+ @retval EFI_SUCCSS If the Text Mode of Console is updated.
+ @return Other value if the Text Mode of Console is not updated.
+
+**/
+EFI_STATUS
+Var_UpdateConMode (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+//
+// Following are page create and refresh functions
+//
+/**
+ Create the global UpdateData structure.
+
+**/
+VOID
+CreateUpdateData (
+ VOID
+ );
+
+/**
+ Refresh the global UpdateData structure.
+
+**/
+VOID
+RefreshUpdateData (
+ VOID
+ );
+
+/**
+ Clean up the dynamic opcode at label and form specified by
+ both LabelId.
+
+ @param LabelId It is both the Form ID and Label ID for
+ opcode deletion.
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+CleanUpPage (
+ IN UINT16 LabelId,
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Create a lit of boot option from global BootOptionMenu. It
+ allow user to delete the boot option.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+UpdateBootDelPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Create a lit of driver option from global DriverMenu.
+
+ @param CallbackData The BMM context data.
+**/
+VOID
+UpdateDrvAddHandlePage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Create a lit of driver option from global DriverOptionMenu. It
+ allow user to delete the driver option.
+
+ @param CallbackData The BMM context data.
+**/
+VOID
+UpdateDrvDelPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Prepare the page to allow user to add description for a Driver Option.
+
+ @param CallbackData The BMM context data.
+**/
+VOID
+UpdateDriverAddHandleDescPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Dispatch the correct update page function to call based on the UpdatePageId.
+
+ @param UpdatePageId The form ID.
+ @param CallbackData The BMM context data.
+**/
+VOID
+UpdatePageBody (
+ IN UINT16 UpdatePageId,
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Create the dynamic page to allow user to set the "BootNext" vaule.
+
+ @param CallbackData The BMM context data.
+**/
+VOID
+UpdateBootNextPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Create the dynamic page to allow user to set the "TimeOut" vaule.
+
+ @param CallbackData The BMM context data.
+**/
+VOID
+UpdateTimeOutPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Create the dynamic page which allows user to set the property such as Baud Rate, Data Bits,
+ Parity, Stop Bits, Terminal Type.
+
+ @param CallbackData The BMM context data.
+**/
+VOID
+UpdateTerminalPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Refresh the text mode page
+
+ @param CallbackData The BMM context data.
+**/
+VOID
+UpdateConModePage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Create a list of Goto Opcode for all terminal devices logged
+ by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID.
+
+ @param CallbackData The BMM context data.
+**/
+VOID
+UpdateConCOMPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Update add boot/driver option page.
+
+ @param CallbackData The BMM context data.
+ @param FormId The form ID to be updated.
+ @param DevicePath Device path.
+
+**/
+VOID
+UpdateOptionPage(
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN EFI_FORM_ID FormId,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+/**
+ Function deletes the variable specified by VarName and VarGuid.
+
+
+ @param VarName A Null-terminated Unicode string that is
+ the name of the vendor's variable.
+
+ @param VarGuid A unique identifier for the vendor.
+
+ @retval EFI_SUCCESS The variable was found and removed
+ @retval EFI_UNSUPPORTED The variable store was inaccessible
+ @retval EFI_OUT_OF_RESOURCES The temporary buffer was not available
+ @retval EFI_NOT_FOUND The variable was not found
+
+**/
+EFI_STATUS
+EfiLibDeleteVariable (
+ IN CHAR16 *VarName,
+ IN EFI_GUID *VarGuid
+ );
+
+/**
+ Function is used to determine the number of device path instances
+ that exist in a device path.
+
+
+ @param DevicePath A pointer to a device path data structure.
+
+ @return This function counts and returns the number of device path instances
+ in DevicePath.
+
+**/
+UINTN
+EfiDevicePathInstanceCount (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+/**
+ Get a string from the Data Hub record based on
+ a device path.
+
+ @param DevPath The device Path.
+
+ @return A string located from the Data Hub records based on
+ the device path.
+ @retval NULL If failed to get the String from Data Hub.
+
+**/
+UINT16 *
+EfiLibStrFromDatahub (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath
+ );
+
+/**
+ Get the index number (#### in Boot####) for the boot option pointed to a BBS legacy device type
+ specified by DeviceType.
+
+ @param DeviceType The legacy device type. It can be floppy, network, harddisk, cdrom,
+ etc.
+ @param OptionIndex Returns the index number (#### in Boot####).
+ @param OptionSize Return the size of the Boot### variable.
+
+**/
+VOID *
+GetLegacyBootOptionVar (
+ IN UINTN DeviceType,
+ OUT UINTN *OptionIndex,
+ OUT UINTN *OptionSize
+ );
+
+/**
+ 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
+ );
+
+/**
+ Dispatch the display to the next page based on NewPageId.
+
+ @param Private The BMM context data.
+ @param NewPageId The original page ID.
+
+**/
+VOID
+UpdatePageId (
+ BMM_CALLBACK_DATA *Private,
+ UINT16 NewPageId
+ );
+
+/**
+ Remove the installed BootMaint and FileExplorer HiiPackages.
+
+**/
+VOID
+FreeBMPackage(
+ VOID
+ );
+
+/**
+ Install BootMaint and FileExplorer HiiPackages.
+
+**/
+VOID
+InitBootMaintenance(
+ VOID
+ );
+
+/**
+
+ Initialize console input device check box to ConsoleInCheck[MAX_MENU_NUMBER]
+ in BMM_FAKE_NV_DATA structure.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+GetConsoleInCheck (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+
+ Initialize console output device check box to ConsoleOutCheck[MAX_MENU_NUMBER]
+ in BMM_FAKE_NV_DATA structure.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+GetConsoleOutCheck (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+
+ Initialize standard error output device check box to ConsoleErrCheck[MAX_MENU_NUMBER]
+ in BMM_FAKE_NV_DATA structure.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+GetConsoleErrCheck (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+
+ Initialize terminal attributes (baudrate, data rate, stop bits, parity and terminal type)
+ to BMM_FAKE_NV_DATA structure.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+GetTerminalAttribute (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ 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
+EFIAPI
+BmmBdsSetConsoleMode (
+ BOOLEAN IsSetupMode
+ );
+
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ Create boot option base on the input file path info.
+
+ @param FilePath Point to the file path.
+
+ @retval TRUE Exit caller function.
+ @retval FALSE Not exit caller function.
+
+**/
+BOOLEAN
+CreateBootOptionFromFile (
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath
+ );
+
+/**
+ Create driver option base on the input file path info.
+
+ @param FilePath Point to the file path.
+
+ @retval TRUE Exit caller function.
+ @retval FALSE Not exit caller function.
+**/
+BOOLEAN
+CreateDriverOptionFromFile (
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath
+ );
+
+/**
+ Boot the file specified by the input file path info.
+
+ @param FilePath Point to the file path.
+
+ @retval TRUE Exit caller function.
+ @retval FALSE Not exit caller function.
+
+**/
+BOOLEAN
+BootFromFile (
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath
+ );
+
+//
+// Global variable in this program (defined in data.c)
+//
+extern BM_MENU_OPTION BootOptionMenu;
+extern BM_MENU_OPTION DriverOptionMenu;
+extern BM_MENU_OPTION ConsoleInpMenu;
+extern BM_MENU_OPTION ConsoleOutMenu;
+extern BM_MENU_OPTION ConsoleErrMenu;
+extern BM_MENU_OPTION DriverMenu;
+extern BM_MENU_OPTION TerminalMenu;
+extern UINT16 TerminalType[5];
+extern COM_ATTR BaudRateList[19];
+extern COM_ATTR DataBitsList[4];
+extern COM_ATTR ParityList[5];
+extern COM_ATTR StopBitsList[3];
+extern EFI_GUID TerminalTypeGuid[5];
+extern EFI_DEVICE_PATH_PROTOCOL EndDevicePath[];
+extern UINT16 mFlowControlType[2];
+extern UINT32 mFlowControlValue[2];
+
+//
+// Shared IFR form update data
+//
+extern VOID *mStartOpCodeHandle;
+extern VOID *mEndOpCodeHandle;
+extern EFI_IFR_GUID_LABEL *mStartLabel;
+extern EFI_IFR_GUID_LABEL *mEndLabel;
+extern BMM_CALLBACK_DATA gBootMaintenancePrivate;
+extern BMM_CALLBACK_DATA *mBmmCallbackInfo;
+
+#endif
diff --git a/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManager.vfr b/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManager.vfr
new file mode 100644
index 0000000000..afce340476
--- /dev/null
+++ b/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManager.vfr
@@ -0,0 +1,440 @@
+///** @file
+// Boot Maintenance Utility Formset
+//
+// Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+//**/
+
+#include "FormGuid.h"
+
+formset
+ guid = BOOT_MAINT_FORMSET_GUID,
+ title = STRING_TOKEN(STR_FORM_MAIN_TITLE),
+ help = STRING_TOKEN(STR_BOOT_MAINT_MANAGER_HELP),
+ classguid = gEfiIfrFrontPageGuid,
+
+ varstore BMM_FAKE_NV_DATA,
+ varid = VARSTORE_ID_BOOT_MAINT,
+ name = BmmData,
+ guid = BOOT_MAINT_FORMSET_GUID;
+
+ form formid = FORM_MAIN_ID,
+ title = STRING_TOKEN(STR_FORM_MAIN_TITLE);
+
+ goto FORM_BOOT_SETUP_ID,
+ prompt = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE),
+ help = STRING_TOKEN(STR_FORM_BOOT_SETUP_HELP),
+ flags = INTERACTIVE,
+ key = FORM_BOOT_SETUP_ID;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ goto FORM_DRIVER_SETUP_ID,
+ prompt = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE),
+ help = STRING_TOKEN(STR_FORM_DRIVER_SETUP_HELP),
+ flags = INTERACTIVE,
+ key = FORM_DRIVER_SETUP_ID;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ goto FORM_CON_MAIN_ID,
+ prompt = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE),
+ help = STRING_TOKEN(STR_FORM_CON_MAIN_HELP),
+ flags = INTERACTIVE,
+ key = FORM_CON_MAIN_ID;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ goto FORM_MAIN_ID,
+ prompt = STRING_TOKEN(STR_BOOT_FROM_FILE),
+ help = STRING_TOKEN(STR_BOOT_FROM_FILE_HELP),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_BOOT_FROM_FILE;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+// label FORM_MAIN_ID;
+
+ goto FORM_BOOT_NEXT_ID,
+ prompt = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE),
+ help = STRING_TOKEN(STR_FORM_BOOT_NEXT_HELP),
+ flags = INTERACTIVE,
+ key = FORM_BOOT_NEXT_ID;
+
+ goto FORM_TIME_OUT_ID,
+ prompt = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE),
+ help = STRING_TOKEN(STR_FORM_TIME_OUT_HELP),
+ flags = INTERACTIVE,
+ key = FORM_TIME_OUT_ID;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ text
+ help = STRING_TOKEN(STR_RESET),
+ text = STRING_TOKEN(STR_RESET),
+ flags = INTERACTIVE,
+ key = FORM_RESET;
+
+ label LABEL_BMM_PLATFORM_INFORMATION;
+ //
+ // This is where we will dynamically add a Action type op-code to show
+ // the platform information.
+ //
+
+ //
+ // This is where we will dynamically add a Action type op-code to show
+ // the advanced menu.
+ //
+
+ //
+ // This is where we will dynamically add a Action type op-code to show
+ // the intel test menu.
+ //
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_BOOT_SETUP_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE);
+
+ goto FORM_MAIN_ID,
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);
+ //flags = INTERACTIVE,
+ //key = FORM_MAIN_ID;
+
+ goto FORM_BOOT_SETUP_ID,
+ prompt = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE),
+ help = STRING_TOKEN(STR_FORM_BOOT_ADD_HELP),
+ flags = INTERACTIVE,
+ key = FORM_BOOT_ADD_ID;
+
+ goto FORM_BOOT_DEL_ID,
+ prompt = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE),
+ help = STRING_TOKEN(STR_FORM_BOOT_IMMEDIATE_HELP),
+ flags = INTERACTIVE,
+ key = FORM_BOOT_DEL_ID;
+
+ goto FORM_BOOT_CHG_ID,
+ prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE),
+ help = STRING_TOKEN(STR_FORM_BOOT_IMMEDIATE_HELP),
+ flags = INTERACTIVE,
+ key = FORM_BOOT_CHG_ID;
+ endform;
+
+ form formid = FORM_DRIVER_SETUP_ID,
+ title = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE);
+
+ goto FORM_MAIN_ID,
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);
+ //help = STRING_TOKEN(STR_FORM_GOTO_MAIN),
+ //flags = INTERACTIVE,
+ //key = FORM_MAIN_ID;
+
+ goto FORM_DRV_ADD_ID,
+ prompt = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE),
+ help = STRING_TOKEN(STR_FORM_DRV_ADD_HELP),
+ flags = INTERACTIVE,
+ key = FORM_DRV_ADD_ID;
+
+ goto FORM_DRV_DEL_ID,
+ prompt = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE),
+ help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),
+ flags = INTERACTIVE,
+ key = FORM_DRV_DEL_ID;
+
+ goto FORM_DRV_CHG_ID,
+ prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE),
+ help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),
+ flags = INTERACTIVE,
+ key = FORM_DRV_CHG_ID;
+ endform;
+
+ form formid = FORM_BOOT_ADD_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_DESC_TITLE);
+
+ label FORM_BOOT_ADD_ID;
+ label LABEL_END;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ string varid = BmmData.BootDescriptionData,
+ questionid = KEY_VALUE_BOOT_DESCRIPTION,
+ prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ minsize = 6,
+ maxsize = 75,
+ endstring;
+
+ string varid = BmmData.BootOptionalData,
+ questionid = KEY_VALUE_BOOT_OPTION,
+ prompt = STRING_TOKEN(STR_OPTIONAL_DATA),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ minsize = 0,
+ maxsize = 120,
+ endstring;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ text
+ help = STRING_TOKEN(STR_SAVE_AND_EXIT),
+ text = STRING_TOKEN(STR_SAVE_AND_EXIT),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_SAVE_AND_EXIT_BOOT;
+
+ text
+ help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),
+ text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_NO_SAVE_AND_EXIT_BOOT;
+
+ endform;
+
+ form formid = FORM_BOOT_DEL_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE);
+
+ label FORM_BOOT_DEL_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_BOOT_CHG_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE);
+
+ label FORM_BOOT_CHG_ID;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_BOOT_NEXT_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE);
+
+ label FORM_BOOT_NEXT_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_TIME_OUT_ID,
+ title = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE);
+
+ label FORM_TIME_OUT_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_MEMORY_CHECK_ID,
+ title = STRING_TOKEN(STR_FORM_MEMORY_CHECK_TITLE);
+
+ label FORM_MEMORY_CHECK_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_UEFI_OPTIMIZED_BOOT_ID,
+ title = STRING_TOKEN(STR_FORM_UEFI_OPTIMIZED_BOOT_TITLE);
+
+ label FORM_UEFI_OPTIMIZED_BOOT_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_DRV_ADD_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE);
+
+ goto FORM_MAIN_ID,
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);
+ //flags = INTERACTIVE,
+ //key = FORM_MAIN_ID;
+
+ goto FORM_DRIVER_SETUP_ID,
+ prompt = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE),
+ help = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE),
+ flags = INTERACTIVE,
+ key = FORM_DRV_ADD_FILE_ID;
+
+ endform;
+
+ form formid = FORM_DRV_ADD_FILE_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);
+
+ label FORM_DRV_ADD_FILE_ID;
+ label LABEL_END;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ string varid = BmmData.DriverDescriptionData,
+ questionid = KEY_VALUE_DRIVER_DESCRIPTION,
+ prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ minsize = 6,
+ maxsize = 75,
+ endstring;
+
+ string varid = BmmData.DriverOptionalData,
+ questionid = KEY_VALUE_DRIVER_OPTION,
+ prompt = STRING_TOKEN(STR_OPTIONAL_DATA),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ minsize = 0,
+ maxsize = 120,
+ endstring;
+
+ checkbox varid = BmmData.ForceReconnect,
+ prompt = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON),
+ help = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON),
+ flags = CHECKBOX_DEFAULT,
+ key = 0,
+ endcheckbox;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ text
+ help = STRING_TOKEN(STR_SAVE_AND_EXIT),
+ text = STRING_TOKEN(STR_SAVE_AND_EXIT),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_SAVE_AND_EXIT_DRIVER; //BUGBUB: allow duplicate key in one formset???
+
+ text
+ help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),
+ text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER;
+ endform;
+
+ form formid = FORM_DRV_DEL_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE);
+
+ label FORM_DRV_DEL_ID;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_DRV_CHG_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE);
+
+ label FORM_DRV_CHG_ID;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_CON_MAIN_ID,
+ title = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE);
+
+ goto FORM_MAIN_ID,
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);
+ //flags = INTERACTIVE,
+ //key = FORM_MAIN_ID;
+
+ goto FORM_CON_IN_ID,
+ prompt = STRING_TOKEN(STR_FORM_CON_IN_TITLE),
+ help = STRING_TOKEN(STR_FORM_CON_IN_HELP),
+ flags = INTERACTIVE,
+ key = FORM_CON_IN_ID;
+
+ goto FORM_CON_OUT_ID,
+ prompt = STRING_TOKEN(STR_FORM_CON_OUT_TITLE),
+ help = STRING_TOKEN(STR_FORM_CON_OUT_HELP),
+ flags = INTERACTIVE,
+ key = FORM_CON_OUT_ID;
+
+ goto FORM_CON_ERR_ID,
+ prompt = STRING_TOKEN(STR_FORM_STD_ERR_TITLE),
+ help = STRING_TOKEN(STR_FORM_STD_ERR_HELP),
+ flags = INTERACTIVE,
+ key = FORM_CON_ERR_ID;
+
+ goto FORM_CON_MODE_ID,
+ prompt = STRING_TOKEN(STR_FORM_MODE_TITLE),
+ help = STRING_TOKEN(STR_FORM_MODE_HELP),
+ flags = INTERACTIVE,
+ key = FORM_CON_MODE_ID;
+
+ goto FORM_CON_COM_ID,
+ prompt = STRING_TOKEN(STR_FORM_COM_TITLE),
+ help = STRING_TOKEN(STR_FORM_COM_HELP),
+ flags = INTERACTIVE,
+ key = FORM_CON_COM_ID;
+ endform;
+
+ form formid = FORM_CON_MODE_ID,
+ title = STRING_TOKEN(STR_FORM_MODE_TITLE);
+
+ label FORM_CON_MODE_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_CON_COM_ID,
+ title = STRING_TOKEN(STR_FORM_COM_TITLE);
+
+ label FORM_CON_COM_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_CON_COM_SETUP_ID,
+ title = STRING_TOKEN(STR_CON_COM_SETUP);
+
+ label FORM_CON_COM_SETUP_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_FILE_SEEK_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);
+
+ label FORM_FILE_SEEK_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_FILE_NEW_SEEK_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);
+
+ label FORM_FILE_NEW_SEEK_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_DRV_ADD_HANDLE_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_HANDLE_TITLE);
+
+ label FORM_DRV_ADD_HANDLE_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_DRV_ADD_HANDLE_DESC_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);
+
+ label FORM_DRV_ADD_HANDLE_DESC_ID;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_CON_IN_ID,
+ title = STRING_TOKEN(STR_FORM_CON_IN_TITLE);
+
+ label FORM_CON_IN_ID;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_CON_OUT_ID,
+ title = STRING_TOKEN(STR_FORM_CON_OUT_TITLE);
+
+ label FORM_CON_OUT_ID;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_CON_ERR_ID,
+ title = STRING_TOKEN(STR_FORM_STD_ERR_TITLE);
+
+ label FORM_CON_ERR_ID;
+ label LABEL_END;
+
+ endform;
+
+endformset;
diff --git a/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManagerLib.inf b/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManagerLib.inf
new file mode 100644
index 0000000000..c2e1bd8c20
--- /dev/null
+++ b/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManagerLib.inf
@@ -0,0 +1,100 @@
+## @file
+# Boot Maintenance Manager Library used by UiApp.
+#
+# Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BootMaintenanceManagerLib
+ FILE_GUID = CA9E4824-4198-4715-AA22-E2935E703A07
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|DXE_DRIVER UEFI_APPLICATION
+ CONSTRUCTOR = BootMaintenanceManagerLibConstructor
+ DESTRUCTOR = BootMaintenanceManagerLibDestructor
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ BootMaintenanceManager.h
+ BootMaintenanceManager.vfr
+ BootMaintenanceManagerStrings.uni
+ BootMaintenance.c
+ FormGuid.h
+ BootOption.c
+ ConsoleOption.c
+ Data.c
+ Variable.c
+ UpdatePage.c
+ BmLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ DevicePathLib
+ BaseLib
+ UefiRuntimeServicesTableLib
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ HiiLib
+ UefiHiiServicesLib
+ UefiBootManagerLib
+ FileExplorerLib
+
+[Guids]
+ gEfiGlobalVariableGuid ## SOMETIMES_PRODUCES ## Variable:L"BootNext" (The number of next boot option)
+ ## SOMETIMES_PRODUCES ## Variable:L"BootXX" (Boot option variable)
+ ## SOMETIMES_PRODUCES ## Variable:L"PlatformLang" (Platform supported languange in Rfc4646 format)
+ ## SOMETIMES_PRODUCES ## Variable:L"Lang" (Platform supported languange in Iso639 format)
+ ## SOMETIMES_PRODUCES ## Variable:L"KeyXX" (Hotkey option variable)
+ ## PRODUCES ## Variable:L"HwErrRecSupport" (The level of platform supported hardware Error Record Persistence)
+ ## SOMETIMES_PRODUCES ## Variable:L"BootOptionSupport" (The feature supported in boot option menu, value could be: EFI_BOOT_OPTION_SUPPORT_KEY, EFI_BOOT_OPTION_SUPPORT_APP
+ ## SOMETIMES_PRODUCES (not PcdUefiVariableDefaultLangDeprecate)## Variable:L"LangCodes" (Value of PcdUefiVariableDefaultLangCodes)
+ ## PRODUCES ## Variable:L"PlatformLangCodes" (Value of PcdUefiVariableDefaultPlatformLangCodes)
+ ## PRODUCES ## Variable:L"Timeout" (The time out value in second of showing progress bar)
+ ## SOMETIMES_PRODUCES ## Variable:L"BootOrder" (The boot option array)
+ ## SOMETIMES_PRODUCES ## Variable:L"DriverOrder" (The driver order list)
+ ## SOMETIMES_CONSUMES ## Variable:L"ConIn" (The device path of console in device)
+ ## SOMETIMES_CONSUMES ## Variable:L"ConOut" (The device path of console out device)
+ ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" (The device path of error out device)
+ gEfiFileSystemVolumeLabelInfoIdGuid ## CONSUMES ## GUID (Indicate the information type is volume)
+ gEfiFileInfoGuid ## CONSUMES ## GUID (Indicate the information type is file)
+ gEfiIfrTianoGuid ## CONSUMES ## GUID (Extended IFR Guid Opcode)
+ gEfiIfrFrontPageGuid ## CONSUMES ## GUID
+ gEfiIfrBootMaintenanceGuid ## CONSUMES ## GUID
+
+[Protocols]
+ gEfiSimpleFileSystemProtocolGuid ## CONSUMES
+ gEfiLoadFileProtocolGuid ## CONSUMES
+ gEfiHiiConfigAccessProtocolGuid ## CONSUMES
+ gEfiSerialIoProtocolGuid ## CONSUMES
+ gEfiDevicePathToTextProtocolGuid ## CONSUMES
+
+[FeaturePcd]
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn
+ gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow
diff --git a/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManagerStrings.uni b/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManagerStrings.uni
new file mode 100644
index 0000000000..e574e93eb7
--- /dev/null
+++ b/MdeModulePkg/Library/BootMaintenanceManagerLib/BootMaintenanceManagerStrings.uni
Binary files differ
diff --git a/MdeModulePkg/Library/BootMaintenanceManagerLib/BootOption.c b/MdeModulePkg/Library/BootMaintenanceManagerLib/BootOption.c
new file mode 100644
index 0000000000..a375d61dd3
--- /dev/null
+++ b/MdeModulePkg/Library/BootMaintenanceManagerLib/BootOption.c
@@ -0,0 +1,984 @@
+/** @file
+ Provide boot option support for Application "BootMaint"
+
+ Include file system navigation, system handle selection
+
+ Boot option manipulation
+
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BootMaintenanceManager.h"
+
+///
+/// Define the maximum characters that will be accepted.
+///
+#define MAX_CHAR 480
+
+/**
+ Create a menu entry by given menu type.
+
+ @param MenuType The Menu type to be created.
+
+ @retval NULL If failed to create the menu.
+ @return the new menu entry.
+
+**/
+BM_MENU_ENTRY *
+BOpt_CreateMenuEntry (
+ UINTN MenuType
+ )
+{
+ BM_MENU_ENTRY *MenuEntry;
+ UINTN ContextSize;
+
+ //
+ // Get context size according to menu type
+ //
+ switch (MenuType) {
+ case BM_LOAD_CONTEXT_SELECT:
+ ContextSize = sizeof (BM_LOAD_CONTEXT);
+ break;
+
+ case BM_FILE_CONTEXT_SELECT:
+ ContextSize = sizeof (BM_FILE_CONTEXT);
+ break;
+
+ case BM_CONSOLE_CONTEXT_SELECT:
+ ContextSize = sizeof (BM_CONSOLE_CONTEXT);
+ break;
+
+ case BM_TERMINAL_CONTEXT_SELECT:
+ ContextSize = sizeof (BM_TERMINAL_CONTEXT);
+ break;
+
+ case BM_HANDLE_CONTEXT_SELECT:
+ ContextSize = sizeof (BM_HANDLE_CONTEXT);
+ break;
+
+ default:
+ ContextSize = 0;
+ break;
+ }
+
+ if (ContextSize == 0) {
+ return NULL;
+ }
+
+ //
+ // Create new menu entry
+ //
+ MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY));
+ if (MenuEntry == NULL) {
+ return NULL;
+ }
+
+ MenuEntry->VariableContext = AllocateZeroPool (ContextSize);
+ if (MenuEntry->VariableContext == NULL) {
+ FreePool (MenuEntry);
+ return NULL;
+ }
+
+ MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE;
+ MenuEntry->ContextSelection = MenuType;
+ return MenuEntry;
+}
+
+/**
+ Free up all resource allocated for a BM_MENU_ENTRY.
+
+ @param MenuEntry A pointer to BM_MENU_ENTRY.
+
+**/
+VOID
+BOpt_DestroyMenuEntry (
+ BM_MENU_ENTRY *MenuEntry
+ )
+{
+ BM_LOAD_CONTEXT *LoadContext;
+ BM_FILE_CONTEXT *FileContext;
+ BM_CONSOLE_CONTEXT *ConsoleContext;
+ BM_TERMINAL_CONTEXT *TerminalContext;
+ BM_HANDLE_CONTEXT *HandleContext;
+
+ //
+ // Select by the type in Menu entry for current context type
+ //
+ switch (MenuEntry->ContextSelection) {
+ case BM_LOAD_CONTEXT_SELECT:
+ LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext;
+ FreePool (LoadContext->FilePathList);
+ FreePool (LoadContext->LoadOption);
+ if (LoadContext->OptionalData != NULL) {
+ FreePool (LoadContext->OptionalData);
+ }
+ FreePool (LoadContext);
+ break;
+
+ case BM_FILE_CONTEXT_SELECT:
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
+
+ if (!FileContext->IsRoot) {
+ FreePool (FileContext->DevicePath);
+ } else {
+ if (FileContext->FHandle != NULL) {
+ FileContext->FHandle->Close (FileContext->FHandle);
+ }
+ }
+
+ if (FileContext->FileName != NULL) {
+ FreePool (FileContext->FileName);
+ }
+ if (FileContext->Info != NULL) {
+ FreePool (FileContext->Info);
+ }
+ FreePool (FileContext);
+ break;
+
+ case BM_CONSOLE_CONTEXT_SELECT:
+ ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext;
+ FreePool (ConsoleContext->DevicePath);
+ FreePool (ConsoleContext);
+ break;
+
+ case BM_TERMINAL_CONTEXT_SELECT:
+ TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext;
+ FreePool (TerminalContext->DevicePath);
+ FreePool (TerminalContext);
+ break;
+
+ case BM_HANDLE_CONTEXT_SELECT:
+ HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext;
+ FreePool (HandleContext);
+ break;
+
+ default:
+ break;
+ }
+
+ FreePool (MenuEntry->DisplayString);
+ if (MenuEntry->HelpString != NULL) {
+ FreePool (MenuEntry->HelpString);
+ }
+
+ FreePool (MenuEntry);
+}
+
+/**
+ Get the Menu Entry from the list in Menu Entry List.
+
+ If MenuNumber is great or equal to the number of Menu
+ Entry in the list, then ASSERT.
+
+ @param MenuOption The Menu Entry List to read the menu entry.
+ @param MenuNumber The index of Menu Entry.
+
+ @return The Menu Entry.
+
+**/
+BM_MENU_ENTRY *
+BOpt_GetMenuEntry (
+ BM_MENU_OPTION *MenuOption,
+ UINTN MenuNumber
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINTN Index;
+ LIST_ENTRY *List;
+
+ ASSERT (MenuNumber < MenuOption->MenuNumber);
+
+ List = MenuOption->Head.ForwardLink;
+ for (Index = 0; Index < MenuNumber; Index++) {
+ List = List->ForwardLink;
+ }
+
+ NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE);
+
+ return NewMenuEntry;
+}
+
+/**
+ Free resources allocated in Allocate Rountine.
+
+ @param FreeMenu Menu to be freed
+**/
+VOID
+BOpt_FreeMenu (
+ BM_MENU_OPTION *FreeMenu
+ )
+{
+ BM_MENU_ENTRY *MenuEntry;
+ while (!IsListEmpty (&FreeMenu->Head)) {
+ MenuEntry = CR (
+ FreeMenu->Head.ForwardLink,
+ BM_MENU_ENTRY,
+ Link,
+ BM_MENU_ENTRY_SIGNATURE
+ );
+ RemoveEntryList (&MenuEntry->Link);
+ BOpt_DestroyMenuEntry (MenuEntry);
+ }
+ FreeMenu->MenuNumber = 0;
+}
+
+/**
+
+ Build the BootOptionMenu according to BootOrder Variable.
+ This Routine will access the Boot#### to get EFI_LOAD_OPTION.
+
+ @param CallbackData The BMM context data.
+
+ @return EFI_NOT_FOUND Fail to find "BootOrder" variable.
+ @return EFI_SUCESS Success build boot option menu.
+
+**/
+EFI_STATUS
+BOpt_GetBootOptions (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINTN Index;
+ UINT16 BootString[10];
+ UINT8 *LoadOptionFromVar;
+ UINT8 *LoadOption;
+ UINTN BootOptionSize;
+ BOOLEAN BootNextFlag;
+ UINT16 *BootOrderList;
+ UINTN BootOrderListSize;
+ UINT16 *BootNext;
+ UINTN BootNextSize;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT8 *LoadOptionPtr;
+ UINTN StringSize;
+ UINTN OptionalDataSize;
+ UINT8 *LoadOptionEnd;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN MenuCount;
+ UINT8 *Ptr;
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;
+ UINTN BootOptionCount;
+
+ MenuCount = 0;
+ BootOrderListSize = 0;
+ BootNextSize = 0;
+ BootOrderList = NULL;
+ BootNext = NULL;
+ LoadOptionFromVar = NULL;
+ BOpt_FreeMenu (&BootOptionMenu);
+ InitializeListHead (&BootOptionMenu.Head);
+
+ //
+ // Get the BootOrder from the Var
+ //
+ GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize);
+ if (BootOrderList == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get the BootNext from the Var
+ //
+ GetEfiGlobalVariable2 (L"BootNext", (VOID **) &BootNext, &BootNextSize);
+ if (BootNext != NULL) {
+ if (BootNextSize != sizeof (UINT16)) {
+ FreePool (BootNext);
+ BootNext = NULL;
+ }
+ }
+ BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+ for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {
+ //
+ // Don't display the hidden/inactive boot option
+ //
+ if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) {
+ continue;
+ }
+
+ UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);
+ //
+ // Get all loadoptions from the VAR
+ //
+ GetEfiGlobalVariable2 (BootString, (VOID **) &LoadOptionFromVar, &BootOptionSize);
+ if (LoadOptionFromVar == NULL) {
+ continue;
+ }
+
+ LoadOption = AllocateZeroPool (BootOptionSize);
+ if (LoadOption == NULL) {
+ continue;
+ }
+
+ CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize);
+ FreePool (LoadOptionFromVar);
+
+ if (BootNext != NULL) {
+ BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]);
+ } else {
+ BootNextFlag = FALSE;
+ }
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
+ ASSERT (NULL != NewMenuEntry);
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+
+ LoadOptionPtr = LoadOption;
+ LoadOptionEnd = LoadOption + BootOptionSize;
+
+ NewMenuEntry->OptionNumber = BootOrderList[Index];
+ NewLoadContext->LoadOptionModified = FALSE;
+ NewLoadContext->Deleted = FALSE;
+ NewLoadContext->IsBootNext = BootNextFlag;
+
+ //
+ // Is a Legacy Device?
+ //
+ Ptr = (UINT8 *) LoadOption;
+
+ //
+ // Attribute = *(UINT32 *)Ptr;
+ //
+ Ptr += sizeof (UINT32);
+
+ //
+ // FilePathSize = *(UINT16 *)Ptr;
+ //
+ Ptr += sizeof (UINT16);
+
+ //
+ // Description = (CHAR16 *)Ptr;
+ //
+ Ptr += StrSize ((CHAR16 *) Ptr);
+
+ //
+ // Now Ptr point to Device Path
+ //
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
+ if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {
+ NewLoadContext->IsLegacy = TRUE;
+ } else {
+ NewLoadContext->IsLegacy = FALSE;
+ }
+ //
+ // LoadOption is a pointer type of UINT8
+ // for easy use with following LOAD_OPTION
+ // embedded in this struct
+ //
+ NewLoadContext->LoadOption = LoadOption;
+ NewLoadContext->LoadOptionSize = BootOptionSize;
+
+ NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;
+ NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);
+
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
+
+ LoadOptionPtr += sizeof (UINT32);
+
+ NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;
+ LoadOptionPtr += sizeof (UINT16);
+
+ StringSize = StrSize((UINT16*)LoadOptionPtr);
+
+ NewLoadContext->Description = AllocateZeroPool (StrSize((UINT16*)LoadOptionPtr));
+ ASSERT (NewLoadContext->Description != NULL);
+ StrCpyS (NewLoadContext->Description, StrSize((UINT16*)LoadOptionPtr) / sizeof (UINT16), (UINT16*)LoadOptionPtr);
+
+ ASSERT (NewLoadContext->Description != NULL);
+ NewMenuEntry->DisplayString = NewLoadContext->Description;
+ NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
+
+ LoadOptionPtr += StringSize;
+
+ NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);
+ ASSERT (NewLoadContext->FilePathList != NULL);
+ CopyMem (
+ NewLoadContext->FilePathList,
+ (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,
+ NewLoadContext->FilePathListLength
+ );
+
+ NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
+ NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL);
+
+ LoadOptionPtr += NewLoadContext->FilePathListLength;
+
+ if (LoadOptionPtr < LoadOptionEnd) {
+ OptionalDataSize = BootOptionSize -
+ sizeof (UINT32) -
+ sizeof (UINT16) -
+ StringSize -
+ NewLoadContext->FilePathListLength;
+
+ NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);
+ ASSERT (NewLoadContext->OptionalData != NULL);
+ CopyMem (
+ NewLoadContext->OptionalData,
+ LoadOptionPtr,
+ OptionalDataSize
+ );
+
+ NewLoadContext->OptionalDataSize = OptionalDataSize;
+ }
+
+ InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
+ MenuCount++;
+ }
+ EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
+
+ if (BootNext != NULL) {
+ FreePool (BootNext);
+ }
+ if (BootOrderList != NULL) {
+ FreePool (BootOrderList);
+ }
+ BootOptionMenu.MenuNumber = MenuCount;
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Find drivers that will be added as Driver#### variables from handles
+ in current system environment
+ All valid handles in the system except those consume SimpleFs, LoadFile
+ are stored in DriverMenu for future use.
+
+ @retval EFI_SUCCESS The function complets successfully.
+ @return Other value if failed to build the DriverMenu.
+
+**/
+EFI_STATUS
+BOpt_FindDrivers (
+ VOID
+ )
+{
+ UINTN NoDevicePathHandles;
+ EFI_HANDLE *DevicePathHandle;
+ UINTN Index;
+ EFI_STATUS Status;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_HANDLE_CONTEXT *NewHandleContext;
+ EFI_HANDLE CurHandle;
+ UINTN OptionNumber;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;
+ EFI_LOAD_FILE_PROTOCOL *LoadFile;
+
+ SimpleFs = NULL;
+ LoadFile = NULL;
+
+ InitializeListHead (&DriverMenu.Head);
+
+ //
+ // At first, get all handles that support Device Path
+ // protocol which is the basic requirement for
+ // Driver####
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ &NoDevicePathHandles,
+ &DevicePathHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OptionNumber = 0;
+ for (Index = 0; Index < NoDevicePathHandles; Index++) {
+ CurHandle = DevicePathHandle[Index];
+
+ Status = gBS->HandleProtocol (
+ CurHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID **) &SimpleFs
+ );
+ if (Status == EFI_SUCCESS) {
+ continue;
+ }
+
+ Status = gBS->HandleProtocol (
+ CurHandle,
+ &gEfiLoadFileProtocolGuid,
+ (VOID **) &LoadFile
+ );
+ if (Status == EFI_SUCCESS) {
+ continue;
+ }
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ FreePool (DevicePathHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;
+ NewHandleContext->Handle = CurHandle;
+ NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle);
+ NewMenuEntry->DisplayString = UiDevicePathToStr (NewHandleContext->DevicePath);
+ NewMenuEntry->DisplayStringToken = HiiSetString (mBmmCallbackInfo->BmmHiiHandle,0,NewMenuEntry->DisplayString,NULL);
+ NewMenuEntry->HelpString = NULL;
+ NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;
+ NewMenuEntry->OptionNumber = OptionNumber;
+ OptionNumber++;
+ InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link);
+
+ }
+
+ if (DevicePathHandle != NULL) {
+ FreePool (DevicePathHandle);
+ }
+
+ DriverMenu.MenuNumber = OptionNumber;
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Get the Option Number that has not been allocated for use.
+
+ @param Type The type of Option.
+
+ @return The available Option Number.
+
+**/
+UINT16
+BOpt_GetOptionNumber (
+ CHAR16 *Type
+ )
+{
+ UINT16 *OrderList;
+ UINTN OrderListSize;
+ UINTN Index;
+ CHAR16 StrTemp[20];
+ UINT16 *OptionBuffer;
+ UINT16 OptionNumber;
+ UINTN OptionSize;
+
+ OrderListSize = 0;
+ OrderList = NULL;
+ OptionNumber = 0;
+ Index = 0;
+
+ UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%sOrder", Type);
+
+ GetEfiGlobalVariable2 (StrTemp, (VOID **) &OrderList, &OrderListSize);
+ for (OptionNumber = 0; ; OptionNumber++) {
+ if (OrderList != NULL) {
+ for (Index = 0; Index < OrderListSize / sizeof (UINT16); Index++) {
+ if (OptionNumber == OrderList[Index]) {
+ break;
+ }
+ }
+ }
+
+ if (Index < OrderListSize / sizeof (UINT16)) {
+ //
+ // The OptionNumber occurs in the OrderList, continue to use next one
+ //
+ continue;
+ }
+ UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%s%04x", Type, (UINTN) OptionNumber);
+ DEBUG((EFI_D_ERROR,"Option = %s\n", StrTemp));
+ GetEfiGlobalVariable2 (StrTemp, (VOID **) &OptionBuffer, &OptionSize);
+ if (NULL == OptionBuffer) {
+ //
+ // The Boot[OptionNumber] / Driver[OptionNumber] NOT occurs, we found it
+ //
+ break;
+ }
+ }
+
+ return OptionNumber;
+}
+
+/**
+
+ Get the Option Number for Boot#### that does not used.
+
+ @return The available Option Number.
+
+**/
+UINT16
+BOpt_GetBootOptionNumber (
+ VOID
+ )
+{
+ return BOpt_GetOptionNumber (L"Boot");
+}
+
+/**
+
+ Get the Option Number for Driver#### that does not used.
+
+ @return The unused Option Number.
+
+**/
+UINT16
+BOpt_GetDriverOptionNumber (
+ VOID
+ )
+{
+ return BOpt_GetOptionNumber (L"Driver");
+}
+
+/**
+
+ Build up all DriverOptionMenu
+
+ @param CallbackData The BMM context data.
+
+ @retval EFI_SUCESS The functin completes successfully.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.
+ @retval EFI_NOT_FOUND Fail to get "DriverOrder" variable.
+
+**/
+EFI_STATUS
+BOpt_GetDriverOptions (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINTN Index;
+ UINT16 DriverString[12];
+ UINT8 *LoadOptionFromVar;
+ UINT8 *LoadOption;
+ UINTN DriverOptionSize;
+
+ UINT16 *DriverOrderList;
+ UINTN DriverOrderListSize;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT8 *LoadOptionPtr;
+ UINTN StringSize;
+ UINTN OptionalDataSize;
+ UINT8 *LoadOptionEnd;
+
+ DriverOrderListSize = 0;
+ DriverOrderList = NULL;
+ DriverOptionSize = 0;
+ LoadOptionFromVar = NULL;
+ BOpt_FreeMenu (&DriverOptionMenu);
+ InitializeListHead (&DriverOptionMenu.Head);
+ //
+ // Get the DriverOrder from the Var
+ //
+ GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);
+ if (DriverOrderList == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {
+ UnicodeSPrint (
+ DriverString,
+ sizeof (DriverString),
+ L"Driver%04x",
+ DriverOrderList[Index]
+ );
+ //
+ // Get all loadoptions from the VAR
+ //
+ GetEfiGlobalVariable2 (DriverString, (VOID **) &LoadOptionFromVar, &DriverOptionSize);
+ if (LoadOptionFromVar == NULL) {
+ continue;
+ }
+
+ LoadOption = AllocateZeroPool (DriverOptionSize);
+ if (LoadOption == NULL) {
+ continue;
+ }
+
+ CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize);
+ FreePool (LoadOptionFromVar);
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ LoadOptionPtr = LoadOption;
+ LoadOptionEnd = LoadOption + DriverOptionSize;
+ NewMenuEntry->OptionNumber = DriverOrderList[Index];
+ NewLoadContext->LoadOptionModified = FALSE;
+ NewLoadContext->Deleted = FALSE;
+ NewLoadContext->IsLegacy = FALSE;
+
+ //
+ // LoadOption is a pointer type of UINT8
+ // for easy use with following LOAD_OPTION
+ // embedded in this struct
+ //
+ NewLoadContext->LoadOption = LoadOption;
+ NewLoadContext->LoadOptionSize = DriverOptionSize;
+
+ NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;
+ NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);
+
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
+
+ LoadOptionPtr += sizeof (UINT32);
+
+ NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;
+ LoadOptionPtr += sizeof (UINT16);
+
+ StringSize = StrSize ((UINT16 *) LoadOptionPtr);
+ NewLoadContext->Description = AllocateZeroPool (StringSize);
+ ASSERT (NewLoadContext->Description != NULL);
+ CopyMem (
+ NewLoadContext->Description,
+ (UINT16 *) LoadOptionPtr,
+ StringSize
+ );
+ NewMenuEntry->DisplayString = NewLoadContext->Description;
+ NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
+
+ LoadOptionPtr += StringSize;
+
+ NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);
+ ASSERT (NewLoadContext->FilePathList != NULL);
+ CopyMem (
+ NewLoadContext->FilePathList,
+ (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,
+ NewLoadContext->FilePathListLength
+ );
+
+ NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
+ NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL);
+
+ LoadOptionPtr += NewLoadContext->FilePathListLength;
+
+ if (LoadOptionPtr < LoadOptionEnd) {
+ OptionalDataSize = DriverOptionSize -
+ sizeof (UINT32) -
+ sizeof (UINT16) -
+ StringSize -
+ NewLoadContext->FilePathListLength;
+
+ NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);
+ ASSERT (NewLoadContext->OptionalData != NULL);
+ CopyMem (
+ NewLoadContext->OptionalData,
+ LoadOptionPtr,
+ OptionalDataSize
+ );
+
+ NewLoadContext->OptionalDataSize = OptionalDataSize;
+ }
+
+ InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
+
+ }
+
+ if (DriverOrderList != NULL) {
+ FreePool (DriverOrderList);
+ }
+ DriverOptionMenu.MenuNumber = Index;
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Get option number according to Boot#### and BootOrder variable.
+ The value is saved as #### + 1.
+
+ @param CallbackData The BMM context data.
+**/
+VOID
+GetBootOrder (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BMM_FAKE_NV_DATA *BmmConfig;
+ UINT16 Index;
+ UINT16 OptionOrderIndex;
+ UINTN DeviceType;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+
+ ASSERT (CallbackData != NULL);
+
+ DeviceType = (UINTN) -1;
+ BmmConfig = &CallbackData->BmmFakeNvData;
+ ZeroMem (BmmConfig->BootOptionOrder, sizeof (BmmConfig->BootOptionOrder));
+
+ for (Index = 0, OptionOrderIndex = 0; ((Index < BootOptionMenu.MenuNumber) &&
+ (OptionOrderIndex < (sizeof (BmmConfig->BootOptionOrder) / sizeof (BmmConfig->BootOptionOrder[0]))));
+ Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+
+ if (NewLoadContext->IsLegacy) {
+ if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) {
+ DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType;
+ } else {
+ //
+ // Only show one legacy boot option for the same device type
+ // assuming the boot options are grouped by the device type
+ //
+ continue;
+ }
+ }
+ BmmConfig->BootOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1);
+ }
+}
+
+/**
+ Get driver option order from globalc DriverOptionMenu.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+GetDriverOrder (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BMM_FAKE_NV_DATA *BmmConfig;
+ UINT16 Index;
+ UINT16 OptionOrderIndex;
+ UINTN DeviceType;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+
+
+ ASSERT (CallbackData != NULL);
+
+ DeviceType = (UINTN) -1;
+ BmmConfig = &CallbackData->BmmFakeNvData;
+ ZeroMem (BmmConfig->DriverOptionOrder, sizeof (BmmConfig->DriverOptionOrder));
+
+ for (Index = 0, OptionOrderIndex = 0; ((Index < DriverOptionMenu.MenuNumber) &&
+ (OptionOrderIndex < (sizeof (BmmConfig->DriverOptionOrder) / sizeof (BmmConfig->DriverOptionOrder[0]))));
+ Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+
+ if (NewLoadContext->IsLegacy) {
+ if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) {
+ DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType;
+ } else {
+ //
+ // Only show one legacy boot option for the same device type
+ // assuming the boot options are grouped by the device type
+ //
+ continue;
+ }
+ }
+ BmmConfig->DriverOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1);
+ }
+}
+
+/**
+ Boot the file specified by the input file path info.
+
+ @param FilePath Point to the file path.
+
+ @retval TRUE Exit caller function.
+ @retval FALSE Not exit caller function.
+**/
+BOOLEAN
+BootFromFile (
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath
+ )
+{
+ EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
+ CHAR16 *FileName;
+
+ FileName = ExtractFileNameFromDevicePath(FilePath);
+ EfiBootManagerInitializeLoadOption (
+ &BootOption,
+ 0,
+ LoadOptionTypeBoot,
+ LOAD_OPTION_ACTIVE,
+ FileName,
+ FilePath,
+ NULL,
+ 0
+ );
+ //
+ // Since current no boot from removable media directly is allowed */
+ //
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ BmmBdsSetConsoleMode (FALSE);
+ EfiBootManagerBoot (&BootOption);
+ BmmBdsSetConsoleMode (TRUE);
+
+ FreePool(FileName);
+
+ EfiBootManagerFreeLoadOption (&BootOption);
+
+ return FALSE;
+}
+
+/**
+ Display the form base on the selected file.
+
+ @param FilePath Point to the file path.
+ @param FormId The form need to display.
+
+**/
+BOOLEAN
+ReSendForm(
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN EFI_FORM_ID FormId
+ )
+{
+ gBootMaintenancePrivate.LoadContext->FilePathList = FilePath;
+
+ UpdateOptionPage(&gBootMaintenancePrivate, FormId, FilePath);
+
+ gBootMaintenancePrivate.FormBrowser2->SendForm (
+ gBootMaintenancePrivate.FormBrowser2,
+ &gBootMaintenancePrivate.BmmHiiHandle,
+ 1,
+ &mBootMaintGuid,
+ FormId,
+ NULL,
+ NULL
+ );
+ return TRUE;
+}
+
+/**
+ Create boot option base on the input file path info.
+
+ @param FilePath Point to the file path.
+
+ @retval TRUE Exit caller function.
+ @retval FALSE Not exit caller function.
+**/
+BOOLEAN
+CreateBootOptionFromFile (
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath
+ )
+{
+ return ReSendForm(FilePath, FORM_BOOT_ADD_ID);
+}
+
+/**
+ Create driver option base on the input file path info.
+
+ @param FilePath Point to the file path.
+
+ @retval TRUE Exit caller function.
+ @retval FALSE Not exit caller function.
+
+**/
+BOOLEAN
+CreateDriverOptionFromFile (
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath
+ )
+{
+ return ReSendForm(FilePath, FORM_DRV_ADD_FILE_ID);
+}
+
diff --git a/MdeModulePkg/Library/BootMaintenanceManagerLib/ConsoleOption.c b/MdeModulePkg/Library/BootMaintenanceManagerLib/ConsoleOption.c
new file mode 100644
index 0000000000..fd48d5d4cd
--- /dev/null
+++ b/MdeModulePkg/Library/BootMaintenanceManagerLib/ConsoleOption.c
@@ -0,0 +1,1162 @@
+/** @file
+handles console redirection from boot manager
+
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BootMaintenanceManager.h"
+
+/**
+ Function compares a device path data structure to that of all the nodes of a
+ second device path instance.
+
+ @param Multi A pointer to a multi-instance device path data
+ structure.
+ @param Single A pointer to a single-instance device path data
+ structure.
+
+ @retval TRUE If the Single device path is contained within Multi device path.
+ @retval FALSE The Single device path is not match within Multi device path.
+
+**/
+BOOLEAN
+MatchDevicePaths (
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,
+ IN EFI_DEVICE_PATH_PROTOCOL *Single
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
+ UINTN Size;
+
+ if (Multi == NULL || Single == NULL) {
+ return FALSE;
+ }
+
+ DevicePath = Multi;
+ DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
+
+ //
+ // Search for the match of 'Single' in 'Multi'
+ //
+ while (DevicePathInst != NULL) {
+ //
+ // If the single device path is found in multiple device paths,
+ // return success
+ //
+ if (CompareMem (Single, DevicePathInst, Size) == 0) {
+ FreePool (DevicePathInst);
+ return TRUE;
+ }
+
+ FreePool (DevicePathInst);
+ DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
+ }
+
+ return FALSE;
+}
+
+/**
+ Check whether the device path node is ISA Serial Node.
+
+ @param Acpi Device path node to be checked
+
+ @retval TRUE It's ISA Serial Node.
+ @retval FALSE It's NOT ISA Serial Node.
+
+**/
+BOOLEAN
+IsIsaSerialNode (
+ IN ACPI_HID_DEVICE_PATH *Acpi
+ )
+{
+ return (BOOLEAN) (
+ (DevicePathType (Acpi) == ACPI_DEVICE_PATH) &&
+ (DevicePathSubType (Acpi) == ACPI_DP) &&
+ (ReadUnaligned32 (&Acpi->HID) == EISA_PNP_ID (0x0501))
+ );
+}
+
+/**
+ Update Com Ports attributes from DevicePath
+
+ @param DevicePath DevicePath that contains Com ports
+
+ @retval EFI_SUCCESS The update is successful.
+
+**/
+EFI_STATUS
+UpdateComAttributeFromVariable (
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+/**
+ Update the multi-instance device path of Terminal Device based on
+ the global TerminalMenu. If ChangeTernimal is TRUE, the terminal
+ device path in the Terminal Device in TerminalMenu is also updated.
+
+ @param DevicePath The multi-instance device path.
+ @param ChangeTerminal TRUE, then device path in the Terminal Device
+ in TerminalMenu is also updated; FALSE, no update.
+
+ @return EFI_SUCCESS The function completes successfully.
+
+**/
+EFI_STATUS
+ChangeTerminalDevicePath (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN BOOLEAN ChangeTerminal
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+ EFI_DEVICE_PATH_PROTOCOL *Node1;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ UART_DEVICE_PATH *Uart;
+ UART_DEVICE_PATH *Uart1;
+ UINTN Com;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ BM_MENU_ENTRY *NewMenuEntry;
+
+ Node = DevicePath;
+ Node = NextDevicePathNode (Node);
+ Com = 0;
+ while (!IsDevicePathEnd (Node)) {
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;
+ if (IsIsaSerialNode (Acpi)) {
+ CopyMem (&Com, &Acpi->UID, sizeof (UINT32));
+ }
+
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com);
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
+ Uart = (UART_DEVICE_PATH *) Node;
+ CopyMem (
+ &Uart->BaudRate,
+ &NewTerminalContext->BaudRate,
+ sizeof (UINT64)
+ );
+
+ CopyMem (
+ &Uart->DataBits,
+ &NewTerminalContext->DataBits,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &Uart->Parity,
+ &NewTerminalContext->Parity,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &Uart->StopBits,
+ &NewTerminalContext->StopBits,
+ sizeof (UINT8)
+ );
+ //
+ // Change the device path in the ComPort
+ //
+ if (ChangeTerminal) {
+ Node1 = NewTerminalContext->DevicePath;
+ Node1 = NextDevicePathNode (Node1);
+ while (!IsDevicePathEnd (Node1)) {
+ if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) {
+ Uart1 = (UART_DEVICE_PATH *) Node1;
+ CopyMem (
+ &Uart1->BaudRate,
+ &NewTerminalContext->BaudRate,
+ sizeof (UINT64)
+ );
+
+ CopyMem (
+ &Uart1->DataBits,
+ &NewTerminalContext->DataBits,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &Uart1->Parity,
+ &NewTerminalContext->Parity,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &Uart1->StopBits,
+ &NewTerminalContext->StopBits,
+ sizeof (UINT8)
+ );
+ break;
+ }
+ //
+ // end if
+ //
+ Node1 = NextDevicePathNode (Node1);
+ }
+ //
+ // end while
+ //
+ break;
+ }
+ }
+
+ Node = NextDevicePathNode (Node);
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Update the device path that describing a terminal device
+ based on the new BaudRate, Data Bits, parity and Stop Bits
+ set.
+
+ @param DevicePath terminal device's path
+
+**/
+VOID
+ChangeVariableDevicePath (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ UART_DEVICE_PATH *Uart;
+ UINTN Com;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ BM_MENU_ENTRY *NewMenuEntry;
+
+ Node = DevicePath;
+ Node = NextDevicePathNode (Node);
+ Com = 0;
+ while (!IsDevicePathEnd (Node)) {
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;
+ if (IsIsaSerialNode (Acpi)) {
+ CopyMem (&Com, &Acpi->UID, sizeof (UINT32));
+ }
+
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
+ NewMenuEntry = BOpt_GetMenuEntry (
+ &TerminalMenu,
+ Com
+ );
+ ASSERT (NewMenuEntry != NULL);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ Uart = (UART_DEVICE_PATH *) Node;
+ CopyMem (
+ &Uart->BaudRate,
+ &NewTerminalContext->BaudRate,
+ sizeof (UINT64)
+ );
+
+ CopyMem (
+ &Uart->DataBits,
+ &NewTerminalContext->DataBits,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &Uart->Parity,
+ &NewTerminalContext->Parity,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &Uart->StopBits,
+ &NewTerminalContext->StopBits,
+ sizeof (UINT8)
+ );
+ }
+
+ Node = NextDevicePathNode (Node);
+ }
+}
+
+/**
+ Retrieve ACPI UID of UART from device path
+
+ @param Handle The handle for the UART device.
+ @param AcpiUid The ACPI UID on output.
+
+ @retval TRUE Find valid UID from device path
+ @retval FALSE Can't find
+
+**/
+BOOLEAN
+RetrieveUartUid (
+ IN EFI_HANDLE Handle,
+ IN OUT UINT32 *AcpiUid
+ )
+{
+ EFI_STATUS Status;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Acpi = NULL;
+ for (; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) {
+ if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePath) == MSG_UART_DP)) {
+ break;
+ }
+ //
+ // Acpi points to the node before the Uart node
+ //
+ Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;
+ }
+
+ if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) {
+ if (AcpiUid != NULL) {
+ CopyMem (AcpiUid, &Acpi->UID, sizeof (UINT32));
+ }
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Sort Uart handles array with Acpi->UID from low to high.
+
+ @param Handles EFI_SERIAL_IO_PROTOCOL handle buffer
+ @param NoHandles EFI_SERIAL_IO_PROTOCOL handle count
+**/
+VOID
+SortedUartHandle (
+ IN EFI_HANDLE *Handles,
+ IN UINTN NoHandles
+ )
+{
+ UINTN Index1;
+ UINTN Index2;
+ UINTN Position;
+ UINT32 AcpiUid1;
+ UINT32 AcpiUid2;
+ UINT32 TempAcpiUid;
+ EFI_HANDLE TempHandle;
+
+ for (Index1 = 0; Index1 < NoHandles-1; Index1++) {
+ if (!RetrieveUartUid (Handles[Index1], &AcpiUid1)) {
+ continue;
+ }
+ TempHandle = Handles[Index1];
+ Position = Index1;
+ TempAcpiUid = AcpiUid1;
+
+ for (Index2 = Index1+1; Index2 < NoHandles; Index2++) {
+ if (!RetrieveUartUid (Handles[Index2], &AcpiUid2)) {
+ continue;
+ }
+ if (AcpiUid2 < TempAcpiUid) {
+ TempAcpiUid = AcpiUid2;
+ TempHandle = Handles[Index2];
+ Position = Index2;
+ }
+ }
+ Handles[Position] = Handles[Index1];
+ Handles[Index1] = TempHandle;
+ }
+}
+
+/**
+ Test whether DevicePath is a valid Terminal
+
+
+ @param DevicePath DevicePath to be checked
+ @param Termi If DevicePath is valid Terminal, terminal type is returned.
+ @param Com If DevicePath is valid Terminal, Com Port type is returned.
+
+ @retval TRUE If DevicePath point to a Terminal.
+ @retval FALSE If DevicePath does not point to a Terminal.
+
+**/
+BOOLEAN
+IsTerminalDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT TYPE_OF_TERMINAL *Termi,
+ OUT UINTN *Com
+ );
+
+/**
+ Build a list containing all serial devices.
+
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @retval EFI_UNSUPPORTED No serial ports present.
+
+**/
+EFI_STATUS
+LocateSerialIo (
+ VOID
+ )
+{
+ UINTN Index;
+ UINTN Index2;
+ UINTN NoHandles;
+ EFI_HANDLE *Handles;
+ EFI_STATUS Status;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+ EFI_DEVICE_PATH_PROTOCOL *OutDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *InpDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+ VENDOR_DEVICE_PATH Vendor;
+
+ //
+ // Get all handles that have SerialIo protocol installed
+ //
+ InitializeListHead (&TerminalMenu.Head);
+ TerminalMenu.MenuNumber = 0;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSerialIoProtocolGuid,
+ NULL,
+ &NoHandles,
+ &Handles
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // No serial ports present
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Sort Uart handles array with Acpi->UID from low to high
+ // then Terminal menu can be built from low Acpi->UID to high Acpi->UID
+ //
+ SortedUartHandle (Handles, NoHandles);
+
+ for (Index = 0; Index < NoHandles; Index++) {
+ //
+ // Check to see whether the handle has DevicePath Protocol installed
+ //
+ gBS->HandleProtocol (
+ Handles[Index],
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath
+ );
+
+ Acpi = NULL;
+ for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
+ break;
+ }
+ //
+ // Acpi points to the node before Uart node
+ //
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;
+ }
+
+ if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) {
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT);
+ if (NewMenuEntry == NULL) {
+ FreePool (Handles);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32));
+ NewTerminalContext->DevicePath = DuplicateDevicePath (DevicePath);
+ //
+ // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!
+ // coz' the misc data for each platform is not correct, actually it's the device path stored in
+ // datahub which is not completed, so a searching for end of device path will enter a
+ // dead-loop.
+ //
+ NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath);
+ if (NULL == NewMenuEntry->DisplayString) {
+ NewMenuEntry->DisplayString = UiDevicePathToStr (DevicePath);
+ }
+
+ NewMenuEntry->HelpString = NULL;
+
+ NewMenuEntry->DisplayStringToken = HiiSetString (mBmmCallbackInfo->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
+
+ NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;
+
+ gBS->HandleProtocol (
+ Handles[Index],
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &SerialIo
+ );
+
+ CopyMem (
+ &NewTerminalContext->BaudRate,
+ &SerialIo->Mode->BaudRate,
+ sizeof (UINT64)
+ );
+
+ CopyMem (
+ &NewTerminalContext->DataBits,
+ &SerialIo->Mode->DataBits,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &NewTerminalContext->Parity,
+ &SerialIo->Mode->Parity,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &NewTerminalContext->StopBits,
+ &SerialIo->Mode->StopBits,
+ sizeof (UINT8)
+ );
+ InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link);
+ TerminalMenu.MenuNumber++;
+ }
+ }
+ if (Handles != NULL) {
+ FreePool (Handles);
+ }
+
+ //
+ // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var
+ //
+ GetEfiGlobalVariable2 (L"ConOut", (VOID**)&OutDevicePath, NULL);
+ GetEfiGlobalVariable2 (L"ConIn", (VOID**)&InpDevicePath, NULL);
+ GetEfiGlobalVariable2 (L"ErrOut", (VOID**)&ErrDevicePath, NULL);
+ if (OutDevicePath != NULL) {
+ UpdateComAttributeFromVariable (OutDevicePath);
+ }
+
+ if (InpDevicePath != NULL) {
+ UpdateComAttributeFromVariable (InpDevicePath);
+ }
+
+ if (ErrDevicePath != NULL) {
+ UpdateComAttributeFromVariable (ErrDevicePath);
+ }
+
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+
+ NewTerminalContext->TerminalType = 0;
+ NewTerminalContext->IsConIn = FALSE;
+ NewTerminalContext->IsConOut = FALSE;
+ NewTerminalContext->IsStdErr = FALSE;
+
+ Vendor.Header.Type = MESSAGING_DEVICE_PATH;
+ Vendor.Header.SubType = MSG_VENDOR_DP;
+
+ for (Index2 = 0; Index2 < (sizeof (TerminalTypeGuid) / sizeof (TerminalTypeGuid[0])); Index2++) {
+ CopyMem (&Vendor.Guid, &TerminalTypeGuid[Index2], sizeof (EFI_GUID));
+ SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));
+ NewDevicePath = AppendDevicePathNode (
+ NewTerminalContext->DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &Vendor
+ );
+ if (NewMenuEntry->HelpString != NULL) {
+ FreePool (NewMenuEntry->HelpString);
+ }
+ //
+ // NewMenuEntry->HelpString = UiDevicePathToStr (NewDevicePath);
+ // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;
+ //
+ NewMenuEntry->HelpString = NULL;
+
+ NewMenuEntry->DisplayStringToken = HiiSetString (mBmmCallbackInfo->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
+
+ NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;
+
+ if (MatchDevicePaths (OutDevicePath, NewDevicePath)) {
+ NewTerminalContext->IsConOut = TRUE;
+ NewTerminalContext->TerminalType = (UINT8) Index2;
+ }
+
+ if (MatchDevicePaths (InpDevicePath, NewDevicePath)) {
+ NewTerminalContext->IsConIn = TRUE;
+ NewTerminalContext->TerminalType = (UINT8) Index2;
+ }
+
+ if (MatchDevicePaths (ErrDevicePath, NewDevicePath)) {
+ NewTerminalContext->IsStdErr = TRUE;
+ NewTerminalContext->TerminalType = (UINT8) Index2;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update Com Ports attributes from DevicePath
+
+ @param DevicePath DevicePath that contains Com ports
+
+ @retval EFI_SUCCESS The update is successful.
+ @retval EFI_NOT_FOUND Can not find specific menu entry
+**/
+EFI_STATUS
+UpdateComAttributeFromVariable (
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+ EFI_DEVICE_PATH_PROTOCOL *SerialNode;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ UART_DEVICE_PATH *Uart;
+ UART_DEVICE_PATH *Uart1;
+ UINTN TerminalNumber;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ UINTN Index;
+
+ Node = DevicePath;
+ Node = NextDevicePathNode (Node);
+ TerminalNumber = 0;
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ while (!IsDevicePathEnd (Node)) {
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;
+ if (IsIsaSerialNode (Acpi)) {
+ CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32));
+ }
+
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
+ Uart = (UART_DEVICE_PATH *) Node;
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber);
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ CopyMem (
+ &NewTerminalContext->BaudRate,
+ &Uart->BaudRate,
+ sizeof (UINT64)
+ );
+
+ CopyMem (
+ &NewTerminalContext->DataBits,
+ &Uart->DataBits,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &NewTerminalContext->Parity,
+ &Uart->Parity,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &NewTerminalContext->StopBits,
+ &Uart->StopBits,
+ sizeof (UINT8)
+ );
+
+ SerialNode = NewTerminalContext->DevicePath;
+ SerialNode = NextDevicePathNode (SerialNode);
+ while (!IsDevicePathEnd (SerialNode)) {
+ if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) {
+ //
+ // Update following device paths according to
+ // previous acquired uart attributes
+ //
+ Uart1 = (UART_DEVICE_PATH *) SerialNode;
+ CopyMem (
+ &Uart1->BaudRate,
+ &NewTerminalContext->BaudRate,
+ sizeof (UINT64)
+ );
+
+ CopyMem (
+ &Uart1->DataBits,
+ &NewTerminalContext->DataBits,
+ sizeof (UINT8)
+ );
+ CopyMem (
+ &Uart1->Parity,
+ &NewTerminalContext->Parity,
+ sizeof (UINT8)
+ );
+ CopyMem (
+ &Uart1->StopBits,
+ &NewTerminalContext->StopBits,
+ sizeof (UINT8)
+ );
+
+ break;
+ }
+
+ SerialNode = NextDevicePathNode (SerialNode);
+ }
+ //
+ // end while
+ //
+ }
+
+ Node = NextDevicePathNode (Node);
+ }
+ //
+ // end while
+ //
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Build up Console Menu based on types passed in. The type can
+ be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT
+ and BM_CONSOLE_ERR_CONTEXT_SELECT.
+
+ @param ConsoleMenuType Can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT
+ and BM_CONSOLE_ERR_CONTEXT_SELECT.
+
+ @retval EFI_UNSUPPORTED The type passed in is not in the 3 types defined.
+ @retval EFI_NOT_FOUND If the EFI Variable defined in UEFI spec with name "ConOutDev",
+ "ConInDev" or "ConErrDev" doesn't exists.
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operations.
+ @retval EFI_SUCCESS Function completes successfully.
+
+**/
+EFI_STATUS
+GetConsoleMenu (
+ IN UINTN ConsoleMenuType
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *AllDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *MultiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
+ UINTN Size;
+ UINTN AllCount;
+ UINTN Index;
+ UINTN Index2;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_CONSOLE_CONTEXT *NewConsoleContext;
+ TYPE_OF_TERMINAL Terminal;
+ UINTN Com;
+ BM_MENU_OPTION *ConsoleMenu;
+
+ DevicePath = NULL;
+ AllDevicePath = NULL;
+ AllCount = 0;
+ switch (ConsoleMenuType) {
+ case BM_CONSOLE_IN_CONTEXT_SELECT:
+ ConsoleMenu = &ConsoleInpMenu;
+ GetEfiGlobalVariable2 (L"ConIn", (VOID**)&DevicePath, NULL);
+ GetEfiGlobalVariable2 (L"ConInDev", (VOID**)&AllDevicePath, NULL);
+ break;
+
+ case BM_CONSOLE_OUT_CONTEXT_SELECT:
+ ConsoleMenu = &ConsoleOutMenu;
+ GetEfiGlobalVariable2 (L"ConOut", (VOID**)&DevicePath, NULL);
+ GetEfiGlobalVariable2 (L"ConOutDev", (VOID**)&AllDevicePath, NULL);
+ break;
+
+ case BM_CONSOLE_ERR_CONTEXT_SELECT:
+ ConsoleMenu = &ConsoleErrMenu;
+ GetEfiGlobalVariable2 (L"ErrOut", (VOID**)&DevicePath, NULL);
+ GetEfiGlobalVariable2 (L"ErrOutDev", (VOID**)&AllDevicePath, NULL);
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ if (NULL == AllDevicePath) {
+ return EFI_NOT_FOUND;
+ }
+
+ InitializeListHead (&ConsoleMenu->Head);
+
+ AllCount = EfiDevicePathInstanceCount (AllDevicePath);
+ ConsoleMenu->MenuNumber = 0;
+ //
+ // Following is menu building up for Console Devices selected.
+ //
+ MultiDevicePath = AllDevicePath;
+ Index2 = 0;
+ for (Index = 0; Index < AllCount; Index++) {
+ DevicePathInst = GetNextDevicePathInstance (&MultiDevicePath, &Size);
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ NewMenuEntry->OptionNumber = Index2;
+
+ NewConsoleContext->DevicePath = DuplicateDevicePath (DevicePathInst);
+ ASSERT (NewConsoleContext->DevicePath != NULL);
+ NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath);
+ if (NULL == NewMenuEntry->DisplayString) {
+ NewMenuEntry->DisplayString = UiDevicePathToStr (NewConsoleContext->DevicePath);
+ }
+
+ NewMenuEntry->DisplayStringToken = HiiSetString (mBmmCallbackInfo->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
+
+ if (NULL == NewMenuEntry->HelpString) {
+ NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;
+ } else {
+ NewMenuEntry->HelpStringToken = HiiSetString (mBmmCallbackInfo->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL);
+ }
+
+ NewConsoleContext->IsTerminal = IsTerminalDevicePath (
+ NewConsoleContext->DevicePath,
+ &Terminal,
+ &Com
+ );
+
+ NewConsoleContext->IsActive = MatchDevicePaths (
+ DevicePath,
+ NewConsoleContext->DevicePath
+ );
+
+ if (NewConsoleContext->IsTerminal) {
+ BOpt_DestroyMenuEntry (NewMenuEntry);
+ } else {
+ Index2++;
+ ConsoleMenu->MenuNumber++;
+ InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
+
+ @retval EFI_SUCCESS The function always complete successfully.
+
+**/
+EFI_STATUS
+GetAllConsoles (
+ VOID
+ )
+{
+ GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT);
+ GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT);
+ GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT);
+ return EFI_SUCCESS;
+}
+
+/**
+ Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
+
+ @retval EFI_SUCCESS The function always complete successfully.
+**/
+EFI_STATUS
+FreeAllConsoles (
+ VOID
+ )
+{
+ BOpt_FreeMenu (&ConsoleOutMenu);
+ BOpt_FreeMenu (&ConsoleInpMenu);
+ BOpt_FreeMenu (&ConsoleErrMenu);
+ BOpt_FreeMenu (&TerminalMenu);
+ return EFI_SUCCESS;
+}
+
+/**
+ Test whether DevicePath is a valid Terminal
+
+
+ @param DevicePath DevicePath to be checked
+ @param Termi If DevicePath is valid Terminal, terminal type is returned.
+ @param Com If DevicePath is valid Terminal, Com Port type is returned.
+
+ @retval TRUE If DevicePath point to a Terminal.
+ @retval FALSE If DevicePath does not point to a Terminal.
+
+**/
+BOOLEAN
+IsTerminalDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT TYPE_OF_TERMINAL *Termi,
+ OUT UINTN *Com
+ )
+{
+ BOOLEAN IsTerminal;
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+ VENDOR_DEVICE_PATH *Vendor;
+ UART_DEVICE_PATH *Uart;
+ ACPI_HID_DEVICE_PATH *Acpi;
+
+ IsTerminal = FALSE;
+
+ Uart = NULL;
+ Vendor = NULL;
+ Acpi = NULL;
+ for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {
+ //
+ // Vendor points to the node before the End node
+ //
+ Vendor = (VENDOR_DEVICE_PATH *) Node;
+
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
+ Uart = (UART_DEVICE_PATH *) Node;
+ }
+
+ if (Uart == NULL) {
+ //
+ // Acpi points to the node before the UART node
+ //
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;
+ }
+ }
+
+ if (Vendor == NULL ||
+ DevicePathType (Vendor) != MESSAGING_DEVICE_PATH ||
+ DevicePathSubType (Vendor) != MSG_VENDOR_DP ||
+ Uart == NULL) {
+ return FALSE;
+ }
+
+ //
+ // There are four kinds of Terminal types
+ // check to see whether this devicepath
+ // is one of that type
+ //
+ if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[0])) {
+ *Termi = TerminalTypePcAnsi;
+ IsTerminal = TRUE;
+ } else {
+ if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[1])) {
+ *Termi = TerminalTypeVt100;
+ IsTerminal = TRUE;
+ } else {
+ if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[2])) {
+ *Termi = TerminalTypeVt100Plus;
+ IsTerminal = TRUE;
+ } else {
+ if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[3])) {
+ *Termi = TerminalTypeVtUtf8;
+ IsTerminal = TRUE;
+ } else {
+ if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[4])) {
+ *Termi = TerminalTypeTtyTerm;
+ IsTerminal = TRUE;
+ } else {
+ IsTerminal = FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ if (!IsTerminal) {
+ return FALSE;
+ }
+
+ if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) {
+ CopyMem (Com, &Acpi->UID, sizeof (UINT32));
+ } else {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Get mode number according to column and row
+
+ @param CallbackData The BMM context data.
+**/
+VOID
+GetConsoleOutMode (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINTN Col;
+ UINTN Row;
+ UINTN CurrentCol;
+ UINTN CurrentRow;
+ UINTN Mode;
+ UINTN MaxMode;
+ EFI_STATUS Status;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
+
+ ConOut = gST->ConOut;
+ MaxMode = (UINTN) (ConOut->Mode->MaxMode);
+
+ CurrentCol = PcdGet32 (PcdSetupConOutColumn);
+ CurrentRow = PcdGet32 (PcdSetupConOutRow);
+ for (Mode = 0; Mode < MaxMode; Mode++) {
+ Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
+ if (!EFI_ERROR(Status)) {
+ if (CurrentCol == Col && CurrentRow == Row) {
+ CallbackData->BmmFakeNvData.ConsoleOutMode = (UINT16) Mode;
+ break;
+ }
+ }
+ }
+}
+
+/**
+
+ Initialize console input device check box to ConsoleInCheck[MAX_MENU_NUMBER]
+ in BMM_FAKE_NV_DATA structure.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+GetConsoleInCheck (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINT16 Index;
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT8 *ConInCheck;
+ BM_CONSOLE_CONTEXT *NewConsoleContext;
+
+ ASSERT (CallbackData != NULL);
+
+ ConInCheck = &CallbackData->BmmFakeNvData.ConsoleInCheck[0];
+ for (Index = 0; ((Index < ConsoleInpMenu.MenuNumber) && \
+ (Index < MAX_MENU_NUMBER)) ; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ ConInCheck[Index] = NewConsoleContext->IsActive;
+ }
+}
+
+/**
+
+ Initialize console output device check box to ConsoleOutCheck[MAX_MENU_NUMBER]
+ in BMM_FAKE_NV_DATA structure.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+GetConsoleOutCheck (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINT16 Index;
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT8 *ConOutCheck;
+ BM_CONSOLE_CONTEXT *NewConsoleContext;
+
+ ASSERT (CallbackData != NULL);
+ ConOutCheck = &CallbackData->BmmFakeNvData.ConsoleOutCheck[0];
+ for (Index = 0; ((Index < ConsoleOutMenu.MenuNumber) && \
+ (Index < MAX_MENU_NUMBER)) ; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ ConOutCheck[Index] = NewConsoleContext->IsActive;
+ }
+}
+
+/**
+
+ Initialize standard error output device check box to ConsoleErrCheck[MAX_MENU_NUMBER]
+ in BMM_FAKE_NV_DATA structure.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+GetConsoleErrCheck (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINT16 Index;
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT8 *ConErrCheck;
+ BM_CONSOLE_CONTEXT *NewConsoleContext;
+
+ ASSERT (CallbackData != NULL);
+ ConErrCheck = &CallbackData->BmmFakeNvData.ConsoleErrCheck[0];
+ for (Index = 0; ((Index < ConsoleErrMenu.MenuNumber) && \
+ (Index < MAX_MENU_NUMBER)) ; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ ConErrCheck[Index] = NewConsoleContext->IsActive;
+ }
+}
+
+/**
+
+ Initialize terminal attributes (baudrate, data rate, stop bits, parity and terminal type)
+ to BMM_FAKE_NV_DATA structure.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+GetTerminalAttribute (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BMM_FAKE_NV_DATA *CurrentFakeNVMap;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ UINT16 TerminalIndex;
+ UINT8 AttributeIndex;
+
+ ASSERT (CallbackData != NULL);
+
+ CurrentFakeNVMap = &CallbackData->BmmFakeNvData;
+ for (TerminalIndex = 0; ((TerminalIndex < TerminalMenu.MenuNumber) && \
+ (TerminalIndex < MAX_MENU_NUMBER)); TerminalIndex++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalIndex);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ for (AttributeIndex = 0; AttributeIndex < sizeof (BaudRateList) / sizeof (BaudRateList [0]); AttributeIndex++) {
+ if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[AttributeIndex].Value)) {
+ NewTerminalContext->BaudRateIndex = AttributeIndex;
+ break;
+ }
+ }
+ for (AttributeIndex = 0; AttributeIndex < sizeof (DataBitsList) / sizeof (DataBitsList[0]); AttributeIndex++) {
+ if (NewTerminalContext->DataBits == (UINT64) (DataBitsList[AttributeIndex].Value)) {
+ NewTerminalContext->DataBitsIndex = AttributeIndex;
+ break;
+ }
+ }
+
+ for (AttributeIndex = 0; AttributeIndex < sizeof (ParityList) / sizeof (ParityList[0]); AttributeIndex++) {
+ if (NewTerminalContext->Parity == (UINT64) (ParityList[AttributeIndex].Value)) {
+ NewTerminalContext->ParityIndex = AttributeIndex;
+ break;
+ }
+ }
+
+ for (AttributeIndex = 0; AttributeIndex < sizeof (StopBitsList) / sizeof (StopBitsList[0]); AttributeIndex++) {
+ if (NewTerminalContext->StopBits == (UINT64) (StopBitsList[AttributeIndex].Value)) {
+ NewTerminalContext->StopBitsIndex = AttributeIndex;
+ break;
+ }
+ }
+ CurrentFakeNVMap->COMBaudRate[TerminalIndex] = NewTerminalContext->BaudRateIndex;
+ CurrentFakeNVMap->COMDataRate[TerminalIndex] = NewTerminalContext->DataBitsIndex;
+ CurrentFakeNVMap->COMStopBits[TerminalIndex] = NewTerminalContext->StopBitsIndex;
+ CurrentFakeNVMap->COMParity[TerminalIndex] = NewTerminalContext->ParityIndex;
+ CurrentFakeNVMap->COMTerminalType[TerminalIndex] = NewTerminalContext->TerminalType;
+ CurrentFakeNVMap->COMFlowControl[TerminalIndex] = NewTerminalContext->FlowControl;
+ }
+}
+
diff --git a/MdeModulePkg/Library/BootMaintenanceManagerLib/Data.c b/MdeModulePkg/Library/BootMaintenanceManagerLib/Data.c
new file mode 100644
index 0000000000..4257e1a6ea
--- /dev/null
+++ b/MdeModulePkg/Library/BootMaintenanceManagerLib/Data.c
@@ -0,0 +1,263 @@
+/** @file
+Define some data used for Boot Maint
+
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BootMaintenanceManager.h"
+
+VOID *mStartOpCodeHandle = NULL;
+VOID *mEndOpCodeHandle = NULL;
+EFI_IFR_GUID_LABEL *mStartLabel = NULL;
+EFI_IFR_GUID_LABEL *mEndLabel = NULL;
+
+///
+/// Terminal type string token storage
+///
+UINT16 TerminalType[] = {
+ STRING_TOKEN(STR_COM_TYPE_0),
+ STRING_TOKEN(STR_COM_TYPE_1),
+ STRING_TOKEN(STR_COM_TYPE_2),
+ STRING_TOKEN(STR_COM_TYPE_3),
+ STRING_TOKEN(STR_COM_TYPE_4),
+};
+
+///
+/// Flow Control type string token storage
+///
+UINT16 mFlowControlType[2] = {
+ STRING_TOKEN(STR_NONE_FLOW_CONTROL),
+ STRING_TOKEN(STR_HARDWARE_FLOW_CONTROL)
+};
+
+UINT32 mFlowControlValue[2] = {
+ 0,
+ UART_FLOW_CONTROL_HARDWARE
+};
+
+///
+/// Console Input Device Selection Menu
+///
+BM_MENU_OPTION ConsoleInpMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ {NULL},
+ 0
+};
+
+///
+/// Console Output Device Selection Menu
+///
+BM_MENU_OPTION ConsoleOutMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ {NULL},
+ 0
+};
+
+///
+/// Error Output Device Selection Menu
+///
+BM_MENU_OPTION ConsoleErrMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ {NULL},
+ 0
+};
+
+///
+/// Boot Option from variable Menu
+///
+BM_MENU_OPTION BootOptionMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ {NULL},
+ 0
+};
+
+///
+/// Driver Option from variable menu
+///
+BM_MENU_OPTION DriverOptionMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ {NULL},
+ 0
+};
+
+///
+/// Handles in current system selection menu
+///
+BM_MENU_OPTION DriverMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ {NULL},
+ 0
+};
+
+BM_MENU_OPTION TerminalMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ {NULL},
+ 0
+};
+
+///
+/// Value and string token correspondency for BaudRate
+///
+COM_ATTR BaudRateList[19] = {
+ {
+ 115200,
+ STRING_TOKEN(STR_COM_BAUD_RATE_0)
+ },
+ {
+ 57600,
+ STRING_TOKEN(STR_COM_BAUD_RATE_1)
+ },
+ {
+ 38400,
+ STRING_TOKEN(STR_COM_BAUD_RATE_2)
+ },
+ {
+ 19200,
+ STRING_TOKEN(STR_COM_BAUD_RATE_3)
+ },
+ {
+ 9600,
+ STRING_TOKEN(STR_COM_BAUD_RATE_4)
+ },
+ {
+ 7200,
+ STRING_TOKEN(STR_COM_BAUD_RATE_5)
+ },
+ {
+ 4800,
+ STRING_TOKEN(STR_COM_BAUD_RATE_6)
+ },
+ {
+ 3600,
+ STRING_TOKEN(STR_COM_BAUD_RATE_7)
+ },
+ {
+ 2400,
+ STRING_TOKEN(STR_COM_BAUD_RATE_8)
+ },
+ {
+ 2000,
+ STRING_TOKEN(STR_COM_BAUD_RATE_9)
+ },
+ {
+ 1800,
+ STRING_TOKEN(STR_COM_BAUD_RATE_10)
+ },
+ {
+ 1200,
+ STRING_TOKEN(STR_COM_BAUD_RATE_11)
+ },
+ {
+ 600,
+ STRING_TOKEN(STR_COM_BAUD_RATE_12)
+ },
+ {
+ 300,
+ STRING_TOKEN(STR_COM_BAUD_RATE_13)
+ },
+ {
+ 150,
+ STRING_TOKEN(STR_COM_BAUD_RATE_14)
+ },
+ {
+ 134,
+ STRING_TOKEN(STR_COM_BAUD_RATE_15)
+ },
+ {
+ 110,
+ STRING_TOKEN(STR_COM_BAUD_RATE_16)
+ },
+ {
+ 75,
+ STRING_TOKEN(STR_COM_BAUD_RATE_17)
+ },
+ {
+ 50,
+ STRING_TOKEN(STR_COM_BAUD_RATE_18)
+ }
+};
+
+///
+/// Value and string token correspondency for DataBits
+///
+COM_ATTR DataBitsList[4] = {
+ {
+ 5,
+ STRING_TOKEN(STR_COM_DATA_BITS_0)
+ },
+ {
+ 6,
+ STRING_TOKEN(STR_COM_DATA_BITS_1)
+ },
+ {
+ 7,
+ STRING_TOKEN(STR_COM_DATA_BITS_2)
+ },
+ {
+ 8,
+ STRING_TOKEN(STR_COM_DATA_BITS_3)
+ }
+};
+
+///
+/// Value and string token correspondency for Parity
+///
+COM_ATTR ParityList[5] = {
+ {
+ NoParity,
+ STRING_TOKEN(STR_COM_PAR_0)
+ },
+ {
+ EvenParity,
+ STRING_TOKEN(STR_COM_PAR_1)
+ },
+ {
+ OddParity,
+ STRING_TOKEN(STR_COM_PAR_2)
+ },
+ {
+ MarkParity,
+ STRING_TOKEN(STR_COM_PAR_3)
+ },
+ {
+ SpaceParity,
+ STRING_TOKEN(STR_COM_PAR_4)
+ }
+};
+
+///
+/// Value and string token correspondency for Baudreate
+///
+COM_ATTR StopBitsList[3] = {
+ {
+ OneStopBit,
+ STRING_TOKEN(STR_COM_STOP_BITS_0)
+ },
+ {
+ OneFiveStopBits,
+ STRING_TOKEN(STR_COM_STOP_BITS_1)
+ },
+ {
+ TwoStopBits,
+ STRING_TOKEN(STR_COM_STOP_BITS_2)
+ }
+};
+
+///
+/// Guid for messaging path, used in Serial port setting.
+///
+EFI_GUID TerminalTypeGuid[] = {
+ DEVICE_PATH_MESSAGING_PC_ANSI,
+ DEVICE_PATH_MESSAGING_VT_100,
+ DEVICE_PATH_MESSAGING_VT_100_PLUS,
+ DEVICE_PATH_MESSAGING_VT_UTF8,
+ EFI_TTY_TERM_GUID
+};
diff --git a/MdeModulePkg/Library/BootMaintenanceManagerLib/FormGuid.h b/MdeModulePkg/Library/BootMaintenanceManagerLib/FormGuid.h
new file mode 100644
index 0000000000..3e1990dfc6
--- /dev/null
+++ b/MdeModulePkg/Library/BootMaintenanceManagerLib/FormGuid.h
@@ -0,0 +1,209 @@
+/** @file
+Formset guids, form id and VarStore data structure for Boot Maintenance Manager.
+
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _FORM_GUID_H_
+#define _FORM_GUID_H_
+
+#define BOOT_MAINT_FORMSET_GUID \
+ { \
+ 0x642237c7, 0x35d4, 0x472d, {0x83, 0x65, 0x12, 0xe0, 0xcc, 0xf2, 0x7a, 0x22} \
+ }
+
+#define FORM_MAIN_ID 0x1001
+#define FORM_BOOT_ADD_ID 0x1002
+#define FORM_BOOT_DEL_ID 0x1003
+#define FORM_BOOT_CHG_ID 0x1004
+#define FORM_DRV_ADD_ID 0x1005
+#define FORM_DRV_DEL_ID 0x1006
+#define FORM_DRV_CHG_ID 0x1007
+#define FORM_CON_MAIN_ID 0x1008
+#define FORM_CON_IN_ID 0x1009
+#define FORM_CON_OUT_ID 0x100A
+#define FORM_CON_ERR_ID 0x100B
+#define FORM_FILE_SEEK_ID 0x100C
+#define FORM_FILE_NEW_SEEK_ID 0x100D
+#define FORM_DRV_ADD_FILE_ID 0x100E
+#define FORM_DRV_ADD_HANDLE_ID 0x100F
+#define FORM_DRV_ADD_HANDLE_DESC_ID 0x1010
+#define FORM_BOOT_NEXT_ID 0x1011
+#define FORM_TIME_OUT_ID 0x1012
+#define FORM_BOOT_SETUP_ID 0x1014
+#define FORM_DRIVER_SETUP_ID 0x1015
+#define FORM_BOOT_LEGACY_DEVICE_ID 0x1016
+#define FORM_CON_COM_ID 0x1017
+#define FORM_CON_COM_SETUP_ID 0x1018
+#define FORM_BOOT_ADD_DESCRIPTION_ID 0x101F
+#define FORM_DRIVER_ADD_FILE_DESCRIPTION_ID 0x1020
+#define FORM_CON_MODE_ID 0x1021
+#define FORM_MEMORY_CHECK_ID 0x1022
+#define FORM_UEFI_OPTIMIZED_BOOT_ID 0x1023
+#define FORM_BOOT_FROM_FILE_ID 0x1024
+
+
+#define MAXIMUM_FORM_ID 0x10FF
+
+#define KEY_VALUE_COM_SET_BAUD_RATE 0x1101
+#define KEY_VALUE_COM_SET_DATA_BITS 0x1102
+#define KEY_VALUE_COM_SET_STOP_BITS 0x1103
+#define KEY_VALUE_COM_SET_PARITY 0x1104
+#define KEY_VALUE_COM_SET_TERMI_TYPE 0x1105
+#define KEY_VALUE_MAIN_BOOT_NEXT 0x1106
+#define KEY_VALUE_BOOT_ADD_DESC_DATA 0x1107
+#define KEY_VALUE_BOOT_ADD_OPT_DATA 0x1108
+#define KEY_VALUE_DRIVER_ADD_DESC_DATA 0x1109
+#define KEY_VALUE_DRIVER_ADD_OPT_DATA 0x110A
+#define KEY_VALUE_SAVE_AND_EXIT 0x110B
+#define KEY_VALUE_NO_SAVE_AND_EXIT 0x110C
+#define KEY_VALUE_BOOT_FROM_FILE 0x110D
+#define FORM_RESET 0x110E
+#define KEY_VALUE_BOOT_DESCRIPTION 0x110F
+#define KEY_VALUE_BOOT_OPTION 0x1110
+#define KEY_VALUE_DRIVER_DESCRIPTION 0x1111
+#define KEY_VALUE_DRIVER_OPTION 0x1112
+#define KEY_VALUE_SAVE_AND_EXIT_BOOT 0x1113
+#define KEY_VALUE_NO_SAVE_AND_EXIT_BOOT 0x1114
+#define KEY_VALUE_SAVE_AND_EXIT_DRIVER 0x1115
+#define KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER 0x1116
+
+#define MAXIMUM_NORMAL_KEY_VALUE 0x11FF
+
+//
+// Varstore ID defined for Buffer Storage
+//
+#define VARSTORE_ID_BOOT_MAINT 0x1000
+
+//
+// End Label
+//
+#define LABEL_BMM_PLATFORM_INFORMATION 0xfffe
+#define LABEL_END 0xffff
+#define MAX_MENU_NUMBER 100
+
+///
+/// This is the structure that will be used to store the
+/// question's current value. Use it at initialize time to
+/// set default value for each question. When using at run
+/// time, this map is returned by the callback function,
+/// so dynamically changing the question's value will be
+/// possible through this mechanism
+///
+typedef struct {
+ //
+ // Three questions displayed at the main page
+ // for Timeout, BootNext, Variables respectively
+ //
+ UINT16 BootTimeOut;
+ UINT16 BootNext;
+
+ //
+ // This is the COM1 Attributes value storage
+ //
+ UINT8 COM1BaudRate;
+ UINT8 COM1DataRate;
+ UINT8 COM1StopBits;
+ UINT8 COM1Parity;
+ UINT8 COM1TerminalType;
+
+ //
+ // This is the COM2 Attributes value storage
+ //
+ UINT8 COM2BaudRate;
+ UINT8 COM2DataRate;
+ UINT8 COM2StopBits;
+ UINT8 COM2Parity;
+ UINT8 COM2TerminalType;
+
+ //
+ // Driver Option Add Handle page storage
+ //
+ UINT16 DriverAddHandleDesc[MAX_MENU_NUMBER];
+ UINT16 DriverAddHandleOptionalData[MAX_MENU_NUMBER];
+ UINT8 DriverAddActive;
+ UINT8 DriverAddForceReconnect;
+
+ //
+ // Console Input/Output/Errorout using COM port check storage
+ //
+ UINT8 ConsoleInputCOM1;
+ UINT8 ConsoleInputCOM2;
+ UINT8 ConsoleOutputCOM1;
+ UINT8 ConsoleOutputCOM2;
+ UINT8 ConsoleErrorCOM1;
+ UINT8 ConsoleErrorCOM2;
+
+ //
+ // At most 100 input/output/errorout device for console storage
+ //
+ UINT8 ConsoleCheck[MAX_MENU_NUMBER];
+
+ //
+ // At most 100 input/output/errorout device for console storage
+ //
+ UINT8 ConsoleInCheck[MAX_MENU_NUMBER];
+ UINT8 ConsoleOutCheck[MAX_MENU_NUMBER];
+ UINT8 ConsoleErrCheck[MAX_MENU_NUMBER];
+
+ //
+ // Boot or Driver Option Order storage
+ // The value is the OptionNumber+1 because the order list value cannot be 0
+ // Use UINT32 to hold the potential value 0xFFFF+1=0x10000
+ //
+ UINT32 BootOptionOrder[MAX_MENU_NUMBER];
+ UINT32 DriverOptionOrder[MAX_MENU_NUMBER];
+ //
+ // Boot or Driver Option Delete storage
+ //
+ BOOLEAN BootOptionDel[MAX_MENU_NUMBER];
+ BOOLEAN DriverOptionDel[MAX_MENU_NUMBER];
+ BOOLEAN BootOptionDelMark[MAX_MENU_NUMBER];
+ BOOLEAN DriverOptionDelMark[MAX_MENU_NUMBER];
+
+ //
+ // This is the Terminal Attributes value storage
+ //
+ UINT8 COMBaudRate[MAX_MENU_NUMBER];
+ UINT8 COMDataRate[MAX_MENU_NUMBER];
+ UINT8 COMStopBits[MAX_MENU_NUMBER];
+ UINT8 COMParity[MAX_MENU_NUMBER];
+ UINT8 COMTerminalType[MAX_MENU_NUMBER];
+ UINT8 COMFlowControl[MAX_MENU_NUMBER];
+
+ //
+ // We use DisableMap array to record the enable/disable state of each boot device
+ // It should be taken as a bit array, from left to right there are totally 256 bits
+ // the most left one stands for BBS table item 0, and the most right one stands for item 256
+ // If the bit is 1, it means the boot device has been disabled.
+ //
+ UINT8 DisableMap[32];
+
+ //
+ // Console Output Text Mode
+ //
+ UINT16 ConsoleOutMode;
+
+ //
+ // UINT16 PadArea[10];
+ //
+
+ UINT16 BootDescriptionData[MAX_MENU_NUMBER];
+ UINT16 BootOptionalData[127];
+ UINT16 DriverDescriptionData[MAX_MENU_NUMBER];
+ UINT16 DriverOptionalData[127];
+ BOOLEAN BootOptionChanged;
+ BOOLEAN DriverOptionChanged;
+ UINT8 Active;
+ UINT8 ForceReconnect;
+} BMM_FAKE_NV_DATA;
+
+#endif
+
diff --git a/MdeModulePkg/Library/BootMaintenanceManagerLib/UpdatePage.c b/MdeModulePkg/Library/BootMaintenanceManagerLib/UpdatePage.c
new file mode 100644
index 0000000000..78ace0c135
--- /dev/null
+++ b/MdeModulePkg/Library/BootMaintenanceManagerLib/UpdatePage.c
@@ -0,0 +1,1272 @@
+/** @file
+Dynamically update the pages.
+
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BootMaintenanceManager.h"
+
+/**
+ Create the global UpdateData structure.
+
+**/
+VOID
+CreateUpdateData (
+ VOID
+ )
+{
+ //
+ // Init OpCode Handle and Allocate space for creation of Buffer
+ //
+ mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (mStartOpCodeHandle != NULL);
+
+ mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (mEndOpCodeHandle != NULL);
+
+ //
+ // Create Hii Extend Label OpCode as the start opcode
+ //
+ mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+
+ //
+ // Create Hii Extend Label OpCode as the end opcode
+ //
+ mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mEndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ mEndLabel->Number = LABEL_END;
+}
+
+/**
+ Refresh the global UpdateData structure.
+
+**/
+VOID
+RefreshUpdateData (
+ VOID
+ )
+{
+ //
+ // Free current updated date
+ //
+ if (mStartOpCodeHandle != NULL) {
+ HiiFreeOpCodeHandle (mStartOpCodeHandle);
+ }
+
+ //
+ // Create new OpCode Handle
+ //
+ mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
+
+ //
+ // Create Hii Extend Label OpCode as the start opcode
+ //
+ mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+
+}
+
+/**
+ Add a "Go back to main page" tag in front of the form when there are no
+ "Apply changes" and "Discard changes" tags in the end of the form.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+UpdatePageStart (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ RefreshUpdateData ();
+ mStartLabel->Number = CallbackData->BmmCurrentPageId;
+
+ if (!(CallbackData->BmmAskSaveOrNot)) {
+ //
+ // Add a "Go back to main page" tag in front of the form when there are no
+ // "Apply changes" and "Discard changes" tags in the end of the form.
+ //
+ HiiCreateGotoOpCode (
+ mStartOpCodeHandle,
+ FORM_MAIN_ID,
+ STRING_TOKEN (STR_FORM_GOTO_MAIN),
+ STRING_TOKEN (STR_FORM_GOTO_MAIN),
+ 0,
+ FORM_MAIN_ID
+ );
+ }
+}
+
+/**
+ Create the "Apply changes" and "Discard changes" tags. And
+ ensure user can return to the main page.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+UpdatePageEnd (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ //
+ // Create the "Apply changes" and "Discard changes" tags.
+ //
+ if (CallbackData->BmmAskSaveOrNot) {
+ HiiCreateSubTitleOpCode (
+ mStartOpCodeHandle,
+ STRING_TOKEN (STR_NULL_STRING),
+ 0,
+ 0,
+ 0
+ );
+
+ HiiCreateActionOpCode (
+ mStartOpCodeHandle,
+ KEY_VALUE_SAVE_AND_EXIT,
+ STRING_TOKEN (STR_SAVE_AND_EXIT),
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ 0
+ );
+ }
+
+ //
+ // Ensure user can return to the main page.
+ //
+ HiiCreateActionOpCode (
+ mStartOpCodeHandle,
+ KEY_VALUE_NO_SAVE_AND_EXIT,
+ STRING_TOKEN (STR_NO_SAVE_AND_EXIT),
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ 0
+ );
+
+ HiiUpdateForm (
+ CallbackData->BmmHiiHandle,
+ &mBootMaintGuid,
+ CallbackData->BmmCurrentPageId,
+ mStartOpCodeHandle, // Label CallbackData->BmmCurrentPageId
+ mEndOpCodeHandle // LABEL_END
+ );
+}
+
+/**
+ Clean up the dynamic opcode at label and form specified by both LabelId.
+
+ @param LabelId It is both the Form ID and Label ID for opcode deletion.
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+CleanUpPage (
+ IN UINT16 LabelId,
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ RefreshUpdateData ();
+
+ //
+ // Remove all op-codes from dynamic page
+ //
+ mStartLabel->Number = LabelId;
+ HiiUpdateForm (
+ CallbackData->BmmHiiHandle,
+ &mBootMaintGuid,
+ LabelId,
+ mStartOpCodeHandle, // Label LabelId
+ mEndOpCodeHandle // LABEL_END
+ );
+}
+
+/**
+ Create a list of Goto Opcode for all terminal devices logged
+ by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID.
+
+ @param CallbackData The BMM context data.
+**/
+VOID
+UpdateConCOMPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 Index;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+
+ HiiCreateGotoOpCode (
+ mStartOpCodeHandle,
+ FORM_CON_COM_SETUP_ID,
+ NewMenuEntry->DisplayStringToken,
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ (UINT16) (TERMINAL_OPTION_OFFSET + Index)
+ );
+ }
+
+ UpdatePageEnd (CallbackData);
+}
+
+
+/**
+ Create a list of boot option from global BootOptionMenu. It
+ allow user to delete the boot option.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+UpdateBootDelPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT16 Index;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionDel) / sizeof (CallbackData->BmmFakeNvData.BootOptionDel[0])));
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ if (NewLoadContext->IsLegacy) {
+ continue;
+ }
+
+ NewLoadContext->Deleted = FALSE;
+
+ if (CallbackData->BmmFakeNvData.BootOptionDel[Index] && !CallbackData->BmmFakeNvData.BootOptionDelMark[Index]) {
+ //
+ // CallbackData->BmmFakeNvData.BootOptionDel[Index] == TRUE means browser knows this boot option is selected
+ // CallbackData->BmmFakeNvData.BootOptionDelMark[Index] = FALSE means BDS knows the selected boot option has
+ // deleted, browser maintains old useless info. So clear this info here, and later update this info to browser
+ // through HiiSetBrowserData function.
+ //
+ CallbackData->BmmFakeNvData.BootOptionDel[Index] = FALSE;
+ }
+
+ HiiCreateCheckBoxOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) (BOOT_OPTION_DEL_QUESTION_ID + Index),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (BOOT_OPTION_DEL_VAR_OFFSET + Index),
+ NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->HelpStringToken,
+ EFI_IFR_FLAG_CALLBACK,
+ 0,
+ NULL
+ );
+ }
+ UpdatePageEnd (CallbackData);
+}
+
+/**
+ Create a lit of driver option from global DriverMenu.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+UpdateDrvAddHandlePage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 Index;
+
+ CallbackData->BmmAskSaveOrNot = FALSE;
+
+ UpdatePageStart (CallbackData);
+
+ for (Index = 0; Index < DriverMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index);
+
+ HiiCreateGotoOpCode (
+ mStartOpCodeHandle,
+ FORM_DRV_ADD_HANDLE_DESC_ID,
+ NewMenuEntry->DisplayStringToken,
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ (UINT16) (HANDLE_OPTION_OFFSET + Index)
+ );
+ }
+
+ UpdatePageEnd (CallbackData);
+}
+
+/**
+ Create a lit of driver option from global DriverOptionMenu. It
+ allow user to delete the driver option.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+UpdateDrvDelPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT16 Index;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionDel) / sizeof (CallbackData->BmmFakeNvData.DriverOptionDel[0])));
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->Deleted = FALSE;
+
+ if (CallbackData->BmmFakeNvData.DriverOptionDel[Index] && !CallbackData->BmmFakeNvData.DriverOptionDelMark[Index]) {
+ //
+ // CallbackData->BmmFakeNvData.BootOptionDel[Index] == TRUE means browser knows this boot option is selected
+ // CallbackData->BmmFakeNvData.BootOptionDelMark[Index] = FALSE means BDS knows the selected boot option has
+ // deleted, browser maintains old useless info. So clear this info here, and later update this info to browser
+ // through HiiSetBrowserData function.
+ //
+ CallbackData->BmmFakeNvData.DriverOptionDel[Index] = FALSE;
+ }
+ HiiCreateCheckBoxOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) (DRIVER_OPTION_DEL_QUESTION_ID + Index),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (DRIVER_OPTION_DEL_VAR_OFFSET + Index),
+ NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->HelpStringToken,
+ EFI_IFR_FLAG_CALLBACK,
+ 0,
+ NULL
+ );
+ }
+
+ UpdatePageEnd (CallbackData);
+}
+
+/**
+ Prepare the page to allow user to add description for
+ a Driver Option.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+UpdateDriverAddHandleDescPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+
+ CallbackData->BmmFakeNvData.DriverAddActive = 0x01;
+ CallbackData->BmmFakeNvData.DriverAddForceReconnect = 0x00;
+ CallbackData->BmmAskSaveOrNot = TRUE;
+ NewMenuEntry = CallbackData->MenuEntry;
+
+ UpdatePageStart (CallbackData);
+
+ HiiCreateSubTitleOpCode (
+ mStartOpCodeHandle,
+ NewMenuEntry->DisplayStringToken,
+ 0,
+ 0,
+ 0
+ );
+
+ HiiCreateStringOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) DRV_ADD_HANDLE_DESC_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ DRV_ADD_HANDLE_DESC_VAR_OFFSET,
+ STRING_TOKEN (STR_LOAD_OPTION_DESC),
+ STRING_TOKEN (STR_NULL_STRING),
+ 0,
+ 0,
+ 6,
+ 75,
+ NULL
+ );
+
+ HiiCreateCheckBoxOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) DRV_ADD_RECON_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ DRV_ADD_RECON_VAR_OFFSET,
+ STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),
+ STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),
+ 0,
+ 0,
+ NULL
+ );
+
+ HiiCreateStringOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) DRIVER_ADD_OPTION_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ DRIVER_ADD_OPTION_VAR_OFFSET,
+ STRING_TOKEN (STR_OPTIONAL_DATA),
+ STRING_TOKEN (STR_NULL_STRING),
+ 0,
+ 0,
+ 6,
+ 75,
+ NULL
+ );
+
+ UpdatePageEnd (CallbackData);
+}
+
+/**
+ Update console page.
+
+ @param UpdatePageId The form ID to be updated.
+ @param ConsoleMenu The console menu list.
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+UpdateConsolePage (
+ IN UINT16 UpdatePageId,
+ IN BM_MENU_OPTION *ConsoleMenu,
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_CONSOLE_CONTEXT *NewConsoleContext;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ UINT16 Index;
+ UINT16 Index2;
+ UINT8 CheckFlags;
+ UINT8 *ConsoleCheck;
+ UINT8 *OldConsoleCheck;
+ UINTN ConsoleCheckSize;
+ EFI_QUESTION_ID QuestionIdBase;
+ UINT16 VariableOffsetBase;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ ConsoleCheck = NULL;
+ OldConsoleCheck = NULL;
+ QuestionIdBase = 0;
+ VariableOffsetBase = 0;
+ ConsoleCheckSize = 0;
+
+ switch (UpdatePageId) {
+ case FORM_CON_IN_ID:
+ ConsoleCheck = &CallbackData->BmmFakeNvData.ConsoleInCheck[0];
+ OldConsoleCheck = &CallbackData->BmmOldFakeNVData.ConsoleInCheck[0];
+ ConsoleCheckSize = sizeof (CallbackData->BmmFakeNvData.ConsoleInCheck);
+ QuestionIdBase = CON_IN_DEVICE_QUESTION_ID;
+ VariableOffsetBase = CON_IN_DEVICE_VAR_OFFSET;
+ break;
+
+ case FORM_CON_OUT_ID:
+ ConsoleCheck = &CallbackData->BmmFakeNvData.ConsoleOutCheck[0];
+ OldConsoleCheck = &CallbackData->BmmOldFakeNVData.ConsoleOutCheck[0];
+ ConsoleCheckSize = sizeof (CallbackData->BmmFakeNvData.ConsoleOutCheck);
+ QuestionIdBase = CON_OUT_DEVICE_QUESTION_ID;
+ VariableOffsetBase = CON_OUT_DEVICE_VAR_OFFSET;
+ break;
+
+ case FORM_CON_ERR_ID:
+ ConsoleCheck = &CallbackData->BmmFakeNvData.ConsoleErrCheck[0];
+ OldConsoleCheck = &CallbackData->BmmOldFakeNVData.ConsoleErrCheck[0];
+ ConsoleCheckSize = sizeof (CallbackData->BmmFakeNvData.ConsoleErrCheck);
+ QuestionIdBase = CON_ERR_DEVICE_QUESTION_ID;
+ VariableOffsetBase = CON_ERR_DEVICE_VAR_OFFSET;
+ break;
+ }
+ ASSERT (ConsoleCheck != NULL);
+
+ for (Index = 0; ((Index < ConsoleMenu->MenuNumber) && \
+ (Index < MAX_MENU_NUMBER)) ; Index++) {
+ CheckFlags = 0;
+ NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ if (NewConsoleContext->IsActive) {
+ CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;
+ ConsoleCheck[Index] = TRUE;
+ } else {
+ ConsoleCheck[Index] = FALSE;
+ }
+ HiiCreateCheckBoxOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) (QuestionIdBase + Index),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (VariableOffsetBase + Index),
+ NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->HelpStringToken,
+ 0,
+ CheckFlags,
+ NULL
+ );
+ }
+
+ for (Index2 = 0; ((Index2 < TerminalMenu.MenuNumber) && \
+ (Index2 < MAX_MENU_NUMBER)); Index2++) {
+ CheckFlags = 0;
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index2);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+
+ ASSERT (Index < MAX_MENU_NUMBER);
+ if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) ||
+ ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) ||
+ ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID))
+ ) {
+ CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;
+ ConsoleCheck[Index] = TRUE;
+ } else {
+ ConsoleCheck[Index] = FALSE;
+ }
+ HiiCreateCheckBoxOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) (QuestionIdBase + Index),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (VariableOffsetBase + Index),
+ NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->HelpStringToken,
+ 0,
+ CheckFlags,
+ NULL
+ );
+
+ Index++;
+ }
+
+ CopyMem (OldConsoleCheck, ConsoleCheck, ConsoleCheckSize);
+
+ UpdatePageEnd (CallbackData);
+}
+
+/**
+ Update the page's NV Map if user has changed the order
+ a list. This list can be Boot Order or Driver Order.
+
+ @param UpdatePageId The form ID to be updated.
+ @param OptionMenu The new list.
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+UpdateOrderPage (
+ IN UINT16 UpdatePageId,
+ IN BM_MENU_OPTION *OptionMenu,
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 Index;
+ UINT16 OptionIndex;
+ VOID *OptionsOpCodeHandle;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ BOOLEAN BootOptionFound;
+ UINT32 *OptionOrder;
+ EFI_QUESTION_ID QuestionId;
+ UINT16 VarOffset;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+ UpdatePageStart (CallbackData);
+
+ OptionOrder = NULL;
+ QuestionId = 0;
+ VarOffset = 0;
+ switch (UpdatePageId) {
+
+ case FORM_BOOT_CHG_ID:
+ GetBootOrder (CallbackData);
+ OptionOrder = CallbackData->BmmFakeNvData.BootOptionOrder;
+ QuestionId = BOOT_OPTION_ORDER_QUESTION_ID;
+ VarOffset = BOOT_OPTION_ORDER_VAR_OFFSET;
+ break;
+
+ case FORM_DRV_CHG_ID:
+ GetDriverOrder (CallbackData);
+ OptionOrder = CallbackData->BmmFakeNvData.DriverOptionOrder;
+ QuestionId = DRIVER_OPTION_ORDER_QUESTION_ID;
+ VarOffset = DRIVER_OPTION_ORDER_VAR_OFFSET;
+ break;
+ }
+ ASSERT (OptionOrder != NULL);
+
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ NewMenuEntry = NULL;
+ for (OptionIndex = 0; (OptionOrder[OptionIndex] != 0 && OptionIndex < MAX_MENU_NUMBER); OptionIndex++) {
+ BootOptionFound = FALSE;
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ if ((UINT32) (NewMenuEntry->OptionNumber + 1) == OptionOrder[OptionIndex]) {
+ BootOptionFound = TRUE;
+ break;
+ }
+ }
+ if (BootOptionFound) {
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ NewMenuEntry->DisplayStringToken,
+ 0,
+ EFI_IFR_TYPE_NUM_SIZE_32,
+ OptionOrder[OptionIndex]
+ );
+ }
+ }
+
+ if (OptionMenu->MenuNumber > 0) {
+ HiiCreateOrderedListOpCode (
+ mStartOpCodeHandle, // Container for dynamic created opcodes
+ QuestionId, // Question ID
+ VARSTORE_ID_BOOT_MAINT, // VarStore ID
+ VarOffset, // Offset in Buffer Storage
+ STRING_TOKEN (STR_CHANGE_ORDER), // Question prompt text
+ STRING_TOKEN (STR_CHANGE_ORDER), // Question help text
+ 0, // Question flag
+ 0, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
+ EFI_IFR_TYPE_NUM_SIZE_32, // Data type of Question value
+ 100, // Maximum container
+ OptionsOpCodeHandle, // Option Opcode list
+ NULL // Default Opcode is NULL
+ );
+ }
+
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+
+ UpdatePageEnd (CallbackData);
+
+}
+
+/**
+ Create the dynamic page to allow user to set
+ the "BootNext" value.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+UpdateBootNextPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINTN NumberOfOptions;
+ UINT16 Index;
+ VOID *OptionsOpCodeHandle;
+
+ NumberOfOptions = BootOptionMenu.MenuNumber;
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ if (NumberOfOptions > 0) {
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber);
+
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+
+ if (NewLoadContext->IsBootNext) {
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ NewMenuEntry->DisplayStringToken,
+ EFI_IFR_OPTION_DEFAULT,
+ EFI_IFR_TYPE_NUM_SIZE_16,
+ Index
+ );
+ CallbackData->BmmFakeNvData.BootNext = Index;
+ } else {
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ NewMenuEntry->DisplayStringToken,
+ 0,
+ EFI_IFR_TYPE_NUM_SIZE_16,
+ Index
+ );
+ }
+ }
+
+ if (CallbackData->BmmFakeNvData.BootNext == Index) {
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_NONE),
+ EFI_IFR_OPTION_DEFAULT,
+ EFI_IFR_TYPE_NUM_SIZE_16,
+ Index
+ );
+ } else {
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_NONE),
+ 0,
+ EFI_IFR_TYPE_NUM_SIZE_16,
+ Index
+ );
+ }
+
+ HiiCreateOneOfOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) BOOT_NEXT_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ BOOT_NEXT_VAR_OFFSET,
+ STRING_TOKEN (STR_BOOT_NEXT),
+ STRING_TOKEN (STR_BOOT_NEXT_HELP),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_2,
+ OptionsOpCodeHandle,
+ NULL
+ );
+
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+ }
+
+ UpdatePageEnd (CallbackData);
+}
+
+/**
+ Create the dynamic page to allow user to set the "TimeOut" value.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+UpdateTimeOutPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ VOID *DefaultOpCodeHandle;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ DefaultOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (DefaultOpCodeHandle != NULL);
+ HiiCreateDefaultOpCode (DefaultOpCodeHandle, EFI_HII_DEFAULT_CLASS_STANDARD, EFI_IFR_TYPE_NUM_SIZE_16, CallbackData->BmmFakeNvData.BootTimeOut);
+
+ HiiCreateNumericOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) BOOT_TIME_OUT_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ BOOT_TIME_OUT_VAR_OFFSET,
+ STRING_TOKEN (STR_NUM_AUTO_BOOT),
+ STRING_TOKEN (STR_HLP_AUTO_BOOT),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC,
+ 0,
+ 65535,
+ 0,
+ DefaultOpCodeHandle
+ );
+
+ HiiFreeOpCodeHandle (DefaultOpCodeHandle);
+
+ UpdatePageEnd (CallbackData);
+}
+
+
+/**
+ Refresh the text mode page.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+UpdateConModePage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINTN Mode;
+ UINTN Index;
+ UINTN Col;
+ UINTN Row;
+ CHAR16 ModeString[50];
+ CHAR16 *PStr;
+ UINTN MaxMode;
+ UINTN ValidMode;
+ EFI_STRING_ID *ModeToken;
+ EFI_STATUS Status;
+ VOID *OptionsOpCodeHandle;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
+
+ ConOut = gST->ConOut;
+ Index = 0;
+ ValidMode = 0;
+ MaxMode = (UINTN) (ConOut->Mode->MaxMode);
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ //
+ // Check valid mode
+ //
+ for (Mode = 0; Mode < MaxMode; Mode++) {
+ Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ ValidMode++;
+ }
+
+ if (ValidMode == 0) {
+ return;
+ }
+
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ ModeToken = AllocateZeroPool (sizeof (EFI_STRING_ID) * ValidMode);
+ ASSERT(ModeToken != NULL);
+
+ //
+ // Determin which mode should be the first entry in menu
+ //
+ GetConsoleOutMode (CallbackData);
+
+ //
+ // Build text mode options
+ //
+ for (Mode = 0; Mode < MaxMode; Mode++) {
+ Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Build mode string Column x Row
+ //
+ UnicodeValueToString (ModeString, 0, Col, 0);
+ PStr = &ModeString[0];
+ StrnCatS (PStr, sizeof (ModeString) / sizeof (ModeString[0]), L" x ", StrLen(L" x ") + 1);
+ PStr = PStr + StrLen (PStr);
+ UnicodeValueToString (PStr , 0, Row, 0);
+
+ ModeToken[Index] = HiiSetString (CallbackData->BmmHiiHandle, 0, ModeString, NULL);
+
+ if (Mode == CallbackData->BmmFakeNvData.ConsoleOutMode) {
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ ModeToken[Index],
+ EFI_IFR_OPTION_DEFAULT,
+ EFI_IFR_TYPE_NUM_SIZE_16,
+ (UINT16) Mode
+ );
+ } else {
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ ModeToken[Index],
+ 0,
+ EFI_IFR_TYPE_NUM_SIZE_16,
+ (UINT16) Mode
+ );
+ }
+ Index++;
+ }
+
+ HiiCreateOneOfOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) CON_MODE_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ CON_MODE_VAR_OFFSET,
+ STRING_TOKEN (STR_CON_MODE_SETUP),
+ STRING_TOKEN (STR_CON_MODE_SETUP),
+ EFI_IFR_FLAG_RESET_REQUIRED,
+ EFI_IFR_NUMERIC_SIZE_2,
+ OptionsOpCodeHandle,
+ NULL
+ );
+
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+ FreePool (ModeToken);
+
+ UpdatePageEnd (CallbackData);
+}
+
+ /**
+ Create the dynamic page which allows user to set the property such as Baud Rate, Data Bits,
+ Parity, Stop Bits, Terminal Type.
+
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+UpdateTerminalPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINT8 Index;
+ UINT8 CheckFlags;
+ BM_MENU_ENTRY *NewMenuEntry;
+ VOID *OptionsOpCodeHandle;
+ UINTN CurrentTerminal;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ CurrentTerminal = CallbackData->CurrentTerminal;
+ NewMenuEntry = BOpt_GetMenuEntry (
+ &TerminalMenu,
+ CurrentTerminal
+ );
+
+ if (NewMenuEntry == NULL) {
+ return ;
+ }
+
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ for (Index = 0; Index < sizeof (BaudRateList) / sizeof (BaudRateList [0]); Index++) {
+ CheckFlags = 0;
+ if (BaudRateList[Index].Value == 115200) {
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ }
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ BaudRateList[Index].StringToken,
+ CheckFlags,
+ EFI_IFR_TYPE_NUM_SIZE_8,
+ Index
+ );
+ }
+
+ HiiCreateOneOfOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) (COM_BAUD_RATE_QUESTION_ID + CurrentTerminal),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (COM_BAUD_RATE_VAR_OFFSET + CurrentTerminal),
+ STRING_TOKEN (STR_COM_BAUD_RATE),
+ STRING_TOKEN (STR_COM_BAUD_RATE),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ OptionsOpCodeHandle,
+ NULL
+ );
+
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ for (Index = 0; Index < sizeof (DataBitsList) / sizeof (DataBitsList[0]); Index++) {
+ CheckFlags = 0;
+
+ if (DataBitsList[Index].Value == 8) {
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ }
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ DataBitsList[Index].StringToken,
+ CheckFlags,
+ EFI_IFR_TYPE_NUM_SIZE_8,
+ Index
+ );
+ }
+
+ HiiCreateOneOfOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) (COM_DATA_RATE_QUESTION_ID + CurrentTerminal),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (COM_DATA_RATE_VAR_OFFSET + CurrentTerminal),
+ STRING_TOKEN (STR_COM_DATA_BITS),
+ STRING_TOKEN (STR_COM_DATA_BITS),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ OptionsOpCodeHandle,
+ NULL
+ );
+
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ for (Index = 0; Index < sizeof (ParityList) / sizeof (ParityList[0]); Index++) {
+ CheckFlags = 0;
+ if (ParityList[Index].Value == NoParity) {
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ }
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ ParityList[Index].StringToken,
+ CheckFlags,
+ EFI_IFR_TYPE_NUM_SIZE_8,
+ Index
+ );
+ }
+
+ HiiCreateOneOfOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) (COM_PARITY_QUESTION_ID + CurrentTerminal),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (COM_PARITY_VAR_OFFSET + CurrentTerminal),
+ STRING_TOKEN (STR_COM_PARITY),
+ STRING_TOKEN (STR_COM_PARITY),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ OptionsOpCodeHandle,
+ NULL
+ );
+
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ for (Index = 0; Index < sizeof (StopBitsList) / sizeof (StopBitsList[0]); Index++) {
+ CheckFlags = 0;
+ if (StopBitsList[Index].Value == OneStopBit) {
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ }
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ StopBitsList[Index].StringToken,
+ CheckFlags,
+ EFI_IFR_TYPE_NUM_SIZE_8,
+ Index
+ );
+ }
+
+ HiiCreateOneOfOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) (COM_STOP_BITS_QUESTION_ID + CurrentTerminal),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (COM_STOP_BITS_VAR_OFFSET + CurrentTerminal),
+ STRING_TOKEN (STR_COM_STOP_BITS),
+ STRING_TOKEN (STR_COM_STOP_BITS),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ OptionsOpCodeHandle,
+ NULL
+ );
+
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ for (Index = 0; Index < sizeof (TerminalType) / sizeof (TerminalType[0]); Index++) {
+ CheckFlags = 0;
+ if (Index == 0) {
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ }
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ (EFI_STRING_ID) TerminalType[Index],
+ CheckFlags,
+ EFI_IFR_TYPE_NUM_SIZE_8,
+ Index
+ );
+ }
+
+ HiiCreateOneOfOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) (COM_TERMINAL_QUESTION_ID + CurrentTerminal),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (COM_TERMINAL_VAR_OFFSET + CurrentTerminal),
+ STRING_TOKEN (STR_COM_TERMI_TYPE),
+ STRING_TOKEN (STR_COM_TERMI_TYPE),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ OptionsOpCodeHandle,
+ NULL
+ );
+
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ for (Index = 0; Index < sizeof (mFlowControlType) / sizeof (mFlowControlType[0]); Index++) {
+ CheckFlags = 0;
+ if (Index == 0) {
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ }
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ (EFI_STRING_ID) mFlowControlType[Index],
+ CheckFlags,
+ EFI_IFR_TYPE_NUM_SIZE_8,
+ mFlowControlValue[Index]
+ );
+ }
+
+ HiiCreateOneOfOpCode (
+ mStartOpCodeHandle,
+ (EFI_QUESTION_ID) (COM_FLOWCONTROL_QUESTION_ID + CurrentTerminal),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (COM_FLOWCONTROL_VAR_OFFSET + CurrentTerminal),
+ STRING_TOKEN (STR_COM_FLOW_CONTROL),
+ STRING_TOKEN (STR_COM_FLOW_CONTROL),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ OptionsOpCodeHandle,
+ NULL
+ );
+
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+
+ UpdatePageEnd (CallbackData);
+}
+
+/**
+Update add boot/driver option page.
+
+@param CallbackData The BMM context data.
+@param FormId The form ID to be updated.
+@param DevicePath Device path.
+
+**/
+VOID
+UpdateOptionPage(
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN EFI_FORM_ID FormId,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ CHAR16 *String;
+ EFI_STRING_ID StringToken;
+
+ if (DevicePath != NULL){
+ String = ExtractFileNameFromDevicePath(DevicePath);
+ StringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, String, NULL);
+ FreePool(String);
+ } else {
+ String = HiiGetString (CallbackData->BmmHiiHandle, STRING_TOKEN (STR_NULL_STRING), NULL);
+ ASSERT (String != NULL);
+ StringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, String, NULL);
+ FreePool (String);
+ }
+
+ if(FormId == FORM_BOOT_ADD_ID){
+ if (!CallbackData->BmmFakeNvData.BootOptionChanged) {
+ ZeroMem (CallbackData->BmmFakeNvData.BootOptionalData, sizeof (CallbackData->BmmFakeNvData.BootOptionalData));
+ ZeroMem (CallbackData->BmmFakeNvData.BootDescriptionData, sizeof (CallbackData->BmmFakeNvData.BootDescriptionData));
+ }
+ } else if (FormId == FORM_DRV_ADD_FILE_ID){
+ if (!CallbackData->BmmFakeNvData.DriverOptionChanged) {
+ ZeroMem (CallbackData->BmmFakeNvData.DriverOptionalData, sizeof (CallbackData->BmmFakeNvData.DriverOptionalData));
+ ZeroMem (CallbackData->BmmFakeNvData.DriverDescriptionData, sizeof (CallbackData->BmmFakeNvData.DriverDescriptionData));
+ }
+ }
+
+ RefreshUpdateData();
+ mStartLabel->Number = FormId;
+
+ HiiCreateSubTitleOpCode (
+ mStartOpCodeHandle,
+ StringToken,
+ 0,
+ 0,
+ 0
+ );
+
+ HiiUpdateForm (
+ CallbackData->BmmHiiHandle,
+ &mBootMaintGuid,
+ FormId,
+ mStartOpCodeHandle,// Label FormId
+ mEndOpCodeHandle // LABEL_END
+ );
+}
+
+/**
+ Dispatch the correct update page function to call based on
+ the UpdatePageId.
+
+ @param UpdatePageId The form ID.
+ @param CallbackData The BMM context data.
+
+**/
+VOID
+UpdatePageBody (
+ IN UINT16 UpdatePageId,
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ CleanUpPage (UpdatePageId, CallbackData);
+ switch (UpdatePageId) {
+ case FORM_CON_IN_ID:
+ UpdateConsolePage (UpdatePageId, &ConsoleInpMenu, CallbackData);
+ break;
+
+ case FORM_CON_OUT_ID:
+ UpdateConsolePage (UpdatePageId, &ConsoleOutMenu, CallbackData);
+ break;
+
+ case FORM_CON_ERR_ID:
+ UpdateConsolePage (UpdatePageId, &ConsoleErrMenu, CallbackData);
+ break;
+
+ case FORM_BOOT_CHG_ID:
+ UpdateOrderPage (UpdatePageId, &BootOptionMenu, CallbackData);
+ break;
+
+ case FORM_DRV_CHG_ID:
+ UpdateOrderPage (UpdatePageId, &DriverOptionMenu, CallbackData);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ Dispatch the display to the next page based on NewPageId.
+
+ @param Private The BMM context data.
+ @param NewPageId The original page ID.
+
+**/
+VOID
+UpdatePageId (
+ BMM_CALLBACK_DATA *Private,
+ UINT16 NewPageId
+ )
+{
+ if ((NewPageId < FILE_OPTION_OFFSET) && (NewPageId >= HANDLE_OPTION_OFFSET)) {
+ //
+ // If we select a handle to add driver option, advance to the add handle description page.
+ //
+ NewPageId = FORM_DRV_ADD_HANDLE_DESC_ID;
+ } else if ((NewPageId == KEY_VALUE_SAVE_AND_EXIT) || (NewPageId == KEY_VALUE_NO_SAVE_AND_EXIT)) {
+ //
+ // Return to main page after "Save Changes" or "Discard Changes".
+ //
+ NewPageId = FORM_MAIN_ID;
+ } else if ((NewPageId >= TERMINAL_OPTION_OFFSET) && (NewPageId < CONSOLE_OPTION_OFFSET)) {
+ NewPageId = FORM_CON_COM_SETUP_ID;
+ }
+
+ if ((NewPageId > 0) && (NewPageId < MAXIMUM_FORM_ID)) {
+ Private->BmmPreviousPageId = Private->BmmCurrentPageId;
+ Private->BmmCurrentPageId = NewPageId;
+ }
+}
diff --git a/MdeModulePkg/Library/BootMaintenanceManagerLib/Variable.c b/MdeModulePkg/Library/BootMaintenanceManagerLib/Variable.c
new file mode 100644
index 0000000000..cd2da4a905
--- /dev/null
+++ b/MdeModulePkg/Library/BootMaintenanceManagerLib/Variable.c
@@ -0,0 +1,1051 @@
+/** @file
+Variable operation that will be used by bootmaint
+
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BootMaintenanceManager.h"
+
+/**
+ Delete Boot Option that represent a Deleted state in BootOptionMenu.
+ After deleting this boot option, call Var_ChangeBootOrder to
+ make sure BootOrder is in valid state.
+
+ @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to
+ BM_LOAD_CONTEXT marked for deletion is deleted.
+ @retval EFI_NOT_FOUND If can not find the boot option want to be deleted.
+ @return Others If failed to update the "BootOrder" variable after deletion.
+
+**/
+EFI_STATUS
+Var_DelBootOption (
+ VOID
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT16 BootString[10];
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN Index2;
+
+ Status = EFI_SUCCESS;
+ Index2 = 0;
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2));
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ if (!NewLoadContext->Deleted) {
+ continue;
+ }
+
+ UnicodeSPrint (
+ BootString,
+ sizeof (BootString),
+ L"Boot%04x",
+ NewMenuEntry->OptionNumber
+ );
+
+ EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid);
+ Index2++;
+ //
+ // If current Load Option is the same as BootNext,
+ // must delete BootNext in order to make sure
+ // there will be no panic on next boot
+ //
+ if (NewLoadContext->IsBootNext) {
+ EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);
+ }
+
+ RemoveEntryList (&NewMenuEntry->Link);
+ BOpt_DestroyMenuEntry (NewMenuEntry);
+ NewMenuEntry = NULL;
+ }
+
+ BootOptionMenu.MenuNumber -= Index2;
+
+ Status = Var_ChangeBootOrder ();
+ return Status;
+}
+
+/**
+ After any operation on Boot####, there will be a discrepancy in BootOrder.
+ Since some are missing but in BootOrder, while some are present but are
+ not reflected by BootOrder. Then a function rebuild BootOrder from
+ scratch by content from BootOptionMenu is needed.
+
+
+
+
+ @retval EFI_SUCCESS The boot order is updated successfully.
+ @return EFI_STATUS other than EFI_SUCCESS if failed to
+ Set the "BootOrder" EFI Variable.
+
+**/
+EFI_STATUS
+Var_ChangeBootOrder (
+ VOID
+ )
+{
+
+ EFI_STATUS Status;
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 *BootOrderList;
+ UINT16 *BootOrderListPtr;
+ UINTN BootOrderListSize;
+ UINTN Index;
+
+ BootOrderList = NULL;
+ BootOrderListSize = 0;
+ //
+ // First check whether BootOrder is present in current configuration
+ //
+ GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize);
+
+ //
+ // If exists, delete it to hold new BootOrder
+ //
+ if (BootOrderList != NULL) {
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
+ FreePool (BootOrderList);
+ BootOrderList = NULL;
+ }
+ //
+ // Maybe here should be some check method to ensure that
+ // no new added boot options will be added
+ // but the setup engine now will give only one callback
+ // that is to say, user are granted only one chance to
+ // decide whether the boot option will be added or not
+ // there should be no indictor to show whether this
+ // is a "new" boot option
+ //
+ BootOrderListSize = BootOptionMenu.MenuNumber;
+
+ if (BootOrderListSize > 0) {
+ BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16));
+ ASSERT (BootOrderList != NULL);
+ BootOrderListPtr = BootOrderList;
+
+ //
+ // Get all current used Boot#### from BootOptionMenu.
+ // OptionNumber in each BM_LOAD_OPTION is really its
+ // #### value.
+ //
+ for (Index = 0; Index < BootOrderListSize; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ *BootOrderList = (UINT16) NewMenuEntry->OptionNumber;
+ BootOrderList++;
+ }
+
+ BootOrderList = BootOrderListPtr;
+
+ //
+ // After building the BootOrderList, write it back
+ //
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BootOrderListSize * sizeof (UINT16),
+ BootOrderList
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Delete Load Option that represent a Deleted state in BootOptionMenu.
+ After deleting this Driver option, call Var_ChangeDriverOrder to
+ make sure DriverOrder is in valid state.
+
+ @retval EFI_SUCCESS Load Option is successfully updated.
+ @retval EFI_NOT_FOUND Fail to find the driver option want to be deleted.
+ @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI
+ Variable.
+
+**/
+EFI_STATUS
+Var_DelDriverOption (
+ VOID
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT16 DriverString[12];
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN Index2;
+
+ Status = EFI_SUCCESS;
+ Index2 = 0;
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2));
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ if (!NewLoadContext->Deleted) {
+ continue;
+ }
+
+ UnicodeSPrint (
+ DriverString,
+ sizeof (DriverString),
+ L"Driver%04x",
+ NewMenuEntry->OptionNumber
+ );
+
+ EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid);
+ Index2++;
+
+ RemoveEntryList (&NewMenuEntry->Link);
+ BOpt_DestroyMenuEntry (NewMenuEntry);
+ NewMenuEntry = NULL;
+ }
+
+ DriverOptionMenu.MenuNumber -= Index2;
+
+ Status = Var_ChangeDriverOrder ();
+ return Status;
+}
+
+/**
+ After any operation on Driver####, there will be a discrepancy in
+ DriverOrder. Since some are missing but in DriverOrder, while some
+ are present but are not reflected by DriverOrder. Then a function
+ rebuild DriverOrder from scratch by content from DriverOptionMenu is
+ needed.
+
+ @retval EFI_SUCCESS The driver order is updated successfully.
+ @return Other status than EFI_SUCCESS if failed to set the "DriverOrder" EFI Variable.
+
+**/
+EFI_STATUS
+Var_ChangeDriverOrder (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 *DriverOrderList;
+ UINT16 *DriverOrderListPtr;
+ UINTN DriverOrderListSize;
+ UINTN Index;
+
+ DriverOrderList = NULL;
+ DriverOrderListSize = 0;
+
+ //
+ // First check whether DriverOrder is present in current configuration
+ //
+ GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);
+ //
+ // If exists, delete it to hold new DriverOrder
+ //
+ if (DriverOrderList != NULL) {
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
+ FreePool (DriverOrderList);
+ DriverOrderList = NULL;
+ }
+
+ DriverOrderListSize = DriverOptionMenu.MenuNumber;
+
+ if (DriverOrderListSize > 0) {
+ DriverOrderList = AllocateZeroPool (DriverOrderListSize * sizeof (UINT16));
+ ASSERT (DriverOrderList != NULL);
+ DriverOrderListPtr = DriverOrderList;
+
+ //
+ // Get all current used Driver#### from DriverOptionMenu.
+ // OptionNumber in each BM_LOAD_OPTION is really its
+ // #### value.
+ //
+ for (Index = 0; Index < DriverOrderListSize; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
+ *DriverOrderList = (UINT16) NewMenuEntry->OptionNumber;
+ DriverOrderList++;
+ }
+
+ DriverOrderList = DriverOrderListPtr;
+
+ //
+ // After building the DriverOrderList, write it back
+ //
+ Status = gRT->SetVariable (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ DriverOrderListSize * sizeof (UINT16),
+ DriverOrderList
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Update the device path of "ConOut", "ConIn" and "ErrOut"
+ based on the new BaudRate, Data Bits, parity and Stop Bits
+ set.
+
+**/
+VOID
+Var_UpdateAllConsoleOption (
+ VOID
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *OutDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *InpDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath;
+ EFI_STATUS Status;
+
+ GetEfiGlobalVariable2 (L"ConOut", (VOID**)&OutDevicePath, NULL);
+ GetEfiGlobalVariable2 (L"ConIn", (VOID**)&InpDevicePath, NULL);
+ GetEfiGlobalVariable2 (L"ErrOut", (VOID**)&ErrDevicePath, NULL);
+ if (OutDevicePath != NULL) {
+ ChangeVariableDevicePath (OutDevicePath);
+ Status = gRT->SetVariable (
+ L"ConOut",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ GetDevicePathSize (OutDevicePath),
+ OutDevicePath
+ );
+ ASSERT (!EFI_ERROR (Status));
+ }
+
+ if (InpDevicePath != NULL) {
+ ChangeVariableDevicePath (InpDevicePath);
+ Status = gRT->SetVariable (
+ L"ConIn",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ GetDevicePathSize (InpDevicePath),
+ InpDevicePath
+ );
+ ASSERT (!EFI_ERROR (Status));
+ }
+
+ if (ErrDevicePath != NULL) {
+ ChangeVariableDevicePath (ErrDevicePath);
+ Status = gRT->SetVariable (
+ L"ErrOut",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ GetDevicePathSize (ErrDevicePath),
+ ErrDevicePath
+ );
+ ASSERT (!EFI_ERROR (Status));
+ }
+}
+
+/**
+ This function delete and build multi-instance device path for
+ specified type of console device.
+
+ This function clear the EFI variable defined by ConsoleName and
+ gEfiGlobalVariableGuid. It then build the multi-instance device
+ path by appending the device path of the Console (In/Out/Err) instance
+ in ConsoleMenu. Then it scan all corresponding console device by
+ scanning Terminal (built from device supporting Serial I/O instances)
+ devices in TerminalMenu. At last, it save a EFI variable specifed
+ by ConsoleName and gEfiGlobalVariableGuid.
+
+ @param ConsoleName The name for the console device type. They are
+ usually "ConIn", "ConOut" and "ErrOut".
+ @param ConsoleMenu The console memu which is a list of console devices.
+ @param UpdatePageId The flag specifying which type of console device
+ to be processed.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
+
+**/
+EFI_STATUS
+Var_UpdateConsoleOption (
+ IN UINT16 *ConsoleName,
+ IN BM_MENU_OPTION *ConsoleMenu,
+ IN UINT16 UpdatePageId
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_CONSOLE_CONTEXT *NewConsoleContext;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ EFI_STATUS Status;
+ VENDOR_DEVICE_PATH Vendor;
+ EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;
+ UINTN Index;
+
+ GetEfiGlobalVariable2 (ConsoleName, (VOID**)&ConDevicePath, NULL);
+ if (ConDevicePath != NULL) {
+ EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid);
+ FreePool (ConDevicePath);
+ ConDevicePath = NULL;
+ };
+
+ //
+ // First add all console input device from console input menu
+ //
+ for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);
+
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ if (NewConsoleContext->IsActive) {
+ ConDevicePath = AppendDevicePathInstance (
+ ConDevicePath,
+ NewConsoleContext->DevicePath
+ );
+ }
+ }
+
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) ||
+ ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) ||
+ ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID))
+ ) {
+ Vendor.Header.Type = MESSAGING_DEVICE_PATH;
+ Vendor.Header.SubType = MSG_VENDOR_DP;
+
+ ASSERT (NewTerminalContext->TerminalType < (sizeof (TerminalTypeGuid) / sizeof (TerminalTypeGuid[0])));
+ CopyMem (
+ &Vendor.Guid,
+ &TerminalTypeGuid[NewTerminalContext->TerminalType],
+ sizeof (EFI_GUID)
+ );
+ SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));
+ TerminalDevicePath = AppendDevicePathNode (
+ NewTerminalContext->DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &Vendor
+ );
+ ASSERT (TerminalDevicePath != NULL);
+ ChangeTerminalDevicePath (TerminalDevicePath, TRUE);
+ ConDevicePath = AppendDevicePathInstance (
+ ConDevicePath,
+ TerminalDevicePath
+ );
+ }
+ }
+
+ if (ConDevicePath != NULL) {
+ Status = gRT->SetVariable (
+ ConsoleName,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ GetDevicePathSize (ConDevicePath),
+ ConDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ This function delete and build multi-instance device path ConIn
+ console device.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
+**/
+EFI_STATUS
+Var_UpdateConsoleInpOption (
+ VOID
+ )
+{
+ return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);
+}
+
+/**
+ This function delete and build multi-instance device path ConOut
+ console device.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
+**/
+EFI_STATUS
+Var_UpdateConsoleOutOption (
+ VOID
+ )
+{
+ return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);
+}
+
+/**
+ This function delete and build multi-instance device path ErrOut
+ console device.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
+**/
+EFI_STATUS
+Var_UpdateErrorOutOption (
+ VOID
+ )
+{
+ return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);
+}
+
+/**
+ This function create a currently loaded Drive Option from
+ the BMM. It then appends this Driver Option to the end of
+ the "DriverOrder" list. It append this Driver Opotion to the end
+ of DriverOptionMenu.
+
+ @param CallbackData The BMM context data.
+ @param HiiHandle The HII handle associated with the BMM formset.
+ @param DescriptionData The description of this driver option.
+ @param OptionalData The optional load option.
+ @param ForceReconnect If to force reconnect.
+
+ @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
+ @retval EFI_SUCCESS If function completes successfully.
+
+**/
+EFI_STATUS
+Var_UpdateDriverOption (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN UINT16 *DescriptionData,
+ IN UINT16 *OptionalData,
+ IN UINT8 ForceReconnect
+ )
+{
+ UINT16 Index;
+ UINT16 *DriverOrderList;
+ UINT16 *NewDriverOrderList;
+ UINT16 DriverString[12];
+ UINTN DriverOrderListSize;
+ VOID *Buffer;
+ UINTN BufferSize;
+ UINT8 *Ptr;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ BOOLEAN OptionalDataExist;
+ EFI_STATUS Status;
+
+ OptionalDataExist = FALSE;
+
+ Index = BOpt_GetDriverOptionNumber ();
+ UnicodeSPrint (
+ DriverString,
+ sizeof (DriverString),
+ L"Driver%04x",
+ Index
+ );
+
+ if (*DescriptionData == 0x0000) {
+ StrCpyS (DescriptionData, MAX_MENU_NUMBER, DriverString);
+ }
+
+ BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData);
+ BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+
+ if (*OptionalData != 0x0000) {
+ OptionalDataExist = TRUE;
+ BufferSize += StrSize (OptionalData);
+ }
+
+ Buffer = AllocateZeroPool (BufferSize);
+ if (NULL == Buffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ FreePool (Buffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->Deleted = FALSE;
+ NewLoadContext->LoadOptionSize = BufferSize;
+ Ptr = (UINT8 *) Buffer;
+ NewLoadContext->LoadOption = Ptr;
+ *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);
+ NewLoadContext->Attributes = *((UINT32 *) Ptr);
+ NewLoadContext->IsActive = TRUE;
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
+
+ Ptr += sizeof (UINT32);
+ *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+ NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);
+
+ Ptr += sizeof (UINT16);
+ CopyMem (
+ Ptr,
+ DescriptionData,
+ StrSize (DescriptionData)
+ );
+
+ NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));
+ ASSERT (NewLoadContext->Description != NULL);
+ NewMenuEntry->DisplayString = NewLoadContext->Description;
+ CopyMem (
+ NewLoadContext->Description,
+ (VOID *) Ptr,
+ StrSize (DescriptionData)
+ );
+
+ Ptr += StrSize (DescriptionData);
+ CopyMem (
+ Ptr,
+ CallbackData->LoadContext->FilePathList,
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)
+ );
+
+ NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
+ ASSERT (NewLoadContext->FilePathList != NULL);
+
+ CopyMem (
+ NewLoadContext->FilePathList,
+ (VOID *) Ptr,
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)
+ );
+
+ NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
+ NewMenuEntry->OptionNumber = Index;
+ NewMenuEntry->DisplayStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->DisplayString, NULL);
+ NewMenuEntry->HelpStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->HelpString, NULL);
+
+ if (OptionalDataExist) {
+ Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+
+ CopyMem (
+ Ptr,
+ OptionalData,
+ StrSize (OptionalData)
+ );
+ }
+
+ Status = gRT->SetVariable (
+ DriverString,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BufferSize,
+ Buffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);
+ NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16));
+ ASSERT (NewDriverOrderList != NULL);
+ if (DriverOrderList != NULL){
+ CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);
+ }
+ NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;
+ if (DriverOrderList != NULL) {
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
+ }
+
+ Status = gRT->SetVariable (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ DriverOrderListSize + sizeof (UINT16),
+ NewDriverOrderList
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (DriverOrderList != NULL) {
+ FreePool (DriverOrderList);
+ }
+ DriverOrderList = NULL;
+ FreePool (NewDriverOrderList);
+ InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
+ DriverOptionMenu.MenuNumber++;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function create a currently loaded Boot Option from
+ the BMM. It then appends this Boot Option to the end of
+ the "BootOrder" list. It also append this Boot Opotion to the end
+ of BootOptionMenu.
+
+ @param CallbackData The BMM context data.
+
+ @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
+ @retval EFI_SUCCESS If function completes successfully.
+
+**/
+EFI_STATUS
+Var_UpdateBootOption (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINT16 *BootOrderList;
+ UINT16 *NewBootOrderList;
+ UINTN BootOrderListSize;
+ UINT16 BootString[10];
+ VOID *Buffer;
+ UINTN BufferSize;
+ UINT8 *Ptr;
+ UINT16 Index;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ BOOLEAN OptionalDataExist;
+ EFI_STATUS Status;
+ BMM_FAKE_NV_DATA *NvRamMap;
+
+ OptionalDataExist = FALSE;
+ NvRamMap = &CallbackData->BmmFakeNvData;
+
+ Index = BOpt_GetBootOptionNumber () ;
+ UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);
+
+ if (NvRamMap->BootDescriptionData[0] == 0x0000) {
+ StrCpyS (NvRamMap->BootDescriptionData, sizeof (NvRamMap->BootDescriptionData) / sizeof (NvRamMap->BootDescriptionData[0]), BootString);
+ }
+
+ BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->BootDescriptionData);
+ BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+
+ if (NvRamMap->BootOptionalData[0] != 0x0000) {
+ OptionalDataExist = TRUE;
+ BufferSize += StrSize (NvRamMap->BootOptionalData);
+ }
+
+ Buffer = AllocateZeroPool (BufferSize);
+ if (NULL == Buffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->Deleted = FALSE;
+ NewLoadContext->LoadOptionSize = BufferSize;
+ Ptr = (UINT8 *) Buffer;
+ NewLoadContext->LoadOption = Ptr;
+ *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;
+ NewLoadContext->Attributes = *((UINT32 *) Ptr);
+ NewLoadContext->IsActive = TRUE;
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
+
+ Ptr += sizeof (UINT32);
+ *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+ NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);
+ Ptr += sizeof (UINT16);
+
+ CopyMem (
+ Ptr,
+ NvRamMap->BootDescriptionData,
+ StrSize (NvRamMap->BootDescriptionData)
+ );
+
+ NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->BootDescriptionData));
+ ASSERT (NewLoadContext->Description != NULL);
+
+ NewMenuEntry->DisplayString = NewLoadContext->Description;
+ CopyMem (
+ NewLoadContext->Description,
+ (VOID *) Ptr,
+ StrSize (NvRamMap->BootDescriptionData)
+ );
+
+ Ptr += StrSize (NvRamMap->BootDescriptionData);
+ CopyMem (
+ Ptr,
+ CallbackData->LoadContext->FilePathList,
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)
+ );
+
+ NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
+ ASSERT (NewLoadContext->FilePathList != NULL);
+
+ CopyMem (
+ NewLoadContext->FilePathList,
+ (VOID *) Ptr,
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)
+ );
+
+ NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
+ NewMenuEntry->OptionNumber = Index;
+ NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
+ NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL);
+
+ if (OptionalDataExist) {
+ Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+
+ CopyMem (Ptr, NvRamMap->BootOptionalData, StrSize (NvRamMap->BootOptionalData));
+ }
+
+ Status = gRT->SetVariable (
+ BootString,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BufferSize,
+ Buffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize);
+ NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16));
+ ASSERT (NewBootOrderList != NULL);
+ if (BootOrderList != NULL){
+ CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);
+ }
+ NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;
+
+ if (BootOrderList != NULL) {
+ FreePool (BootOrderList);
+ }
+
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BootOrderListSize + sizeof (UINT16),
+ NewBootOrderList
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ FreePool (NewBootOrderList);
+ NewBootOrderList = NULL;
+ InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
+ BootOptionMenu.MenuNumber++;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function update the "BootNext" EFI Variable. If there is
+ no "BootNext" specified in BMM, this EFI Variable is deleted.
+ It also update the BMM context data specified the "BootNext"
+ vaule.
+
+ @param CallbackData The BMM context data.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @return The EFI variable can be saved. See gRT->SetVariable
+ for detail return information.
+
+**/
+EFI_STATUS
+Var_UpdateBootNext (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ BMM_FAKE_NV_DATA *CurrentFakeNVMap;
+ UINT16 Index;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ CurrentFakeNVMap = &CallbackData->BmmFakeNvData;
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ ASSERT (NULL != NewMenuEntry);
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->IsBootNext = FALSE;
+ }
+
+ if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {
+ EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);
+ return EFI_SUCCESS;
+ }
+
+ NewMenuEntry = BOpt_GetMenuEntry (
+ &BootOptionMenu,
+ CurrentFakeNVMap->BootNext
+ );
+ ASSERT (NewMenuEntry != NULL);
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ Status = gRT->SetVariable (
+ L"BootNext",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ sizeof (UINT16),
+ &NewMenuEntry->OptionNumber
+ );
+ NewLoadContext->IsBootNext = TRUE;
+ CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;
+ return Status;
+}
+
+/**
+ This function update the "BootOrder" EFI Variable based on
+ BMM Formset's NV map. It then refresh BootOptionMenu
+ with the new "BootOrder" list.
+
+ @param CallbackData The BMM context data.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
+
+**/
+EFI_STATUS
+Var_UpdateBootOrder (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Index;
+ UINT16 OrderIndex;
+ UINT16 *BootOrder;
+ UINTN BootOrderSize;
+ UINT16 OptionNumber;
+
+ //
+ // First check whether BootOrder is present in current configuration
+ //
+ GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize);
+ if (BootOrder == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionOrder) / sizeof (CallbackData->BmmFakeNvData.BootOptionOrder[0])));
+
+ //
+ // OptionOrder is subset of BootOrder
+ //
+ for (OrderIndex = 0; (OrderIndex < BootOptionMenu.MenuNumber) && (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] != 0); OrderIndex++) {
+ for (Index = OrderIndex; Index < BootOrderSize / sizeof (UINT16); Index++) {
+ if ((BootOrder[Index] == (UINT16) (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] - 1)) && (OrderIndex != Index)) {
+ OptionNumber = BootOrder[Index];
+ CopyMem (&BootOrder[OrderIndex + 1], &BootOrder[OrderIndex], (Index - OrderIndex) * sizeof (UINT16));
+ BootOrder[OrderIndex] = OptionNumber;
+ }
+ }
+ }
+
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BootOrderSize,
+ BootOrder
+ );
+ FreePool (BootOrder);
+
+ BOpt_FreeMenu (&BootOptionMenu);
+ BOpt_GetBootOptions (CallbackData);
+
+ return Status;
+
+}
+
+/**
+ This function update the "DriverOrder" EFI Variable based on
+ BMM Formset's NV map. It then refresh DriverOptionMenu
+ with the new "DriverOrder" list.
+
+ @param CallbackData The BMM context data.
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
+
+**/
+EFI_STATUS
+Var_UpdateDriverOrder (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Index;
+ UINT16 *DriverOrderList;
+ UINT16 *NewDriverOrderList;
+ UINTN DriverOrderListSize;
+
+ DriverOrderList = NULL;
+ DriverOrderListSize = 0;
+
+ //
+ // First check whether DriverOrder is present in current configuration
+ //
+ GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);
+ NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);
+
+ if (NewDriverOrderList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // If exists, delete it to hold new DriverOrder
+ //
+ if (DriverOrderList != NULL) {
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
+ FreePool (DriverOrderList);
+ }
+
+ ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder) / sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder[0])));
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
+ NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] - 1);
+ }
+
+ Status = gRT->SetVariable (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ DriverOrderListSize,
+ NewDriverOrderList
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BOpt_FreeMenu (&DriverOptionMenu);
+ BOpt_GetDriverOptions (CallbackData);
+ return EFI_SUCCESS;
+}
+
+/**
+ Update the Text Mode of Console.
+
+ @param CallbackData The context data for BMM.
+
+ @retval EFI_SUCCSS If the Text Mode of Console is updated.
+ @return Other value if the Text Mode of Console is not updated.
+
+**/
+EFI_STATUS
+Var_UpdateConMode (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ EFI_STATUS Status;
+ UINTN Mode;
+ CONSOLE_OUT_MODE ModeInfo;
+
+ Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;
+
+ Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));
+ if (!EFI_ERROR(Status)) {
+ Status = PcdSet32S (PcdSetupConOutColumn, (UINT32) ModeInfo.Column);
+ if (!EFI_ERROR (Status)) {
+ Status = PcdSet32S (PcdSetupConOutRow, (UINT32) ModeInfo.Row);
+ }
+ }
+
+ return Status;
+}