summaryrefslogtreecommitdiff
path: root/IntelFrameworkModulePkg/Universal/BdsDxe
diff options
context:
space:
mode:
authorklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>2009-01-23 07:24:55 +0000
committerklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>2009-01-23 07:24:55 +0000
commit5c08e1173703234cc2913757f237ee916087498a (patch)
tree9f44a4b93f9227b500019f053bbe0ace53050b7a /IntelFrameworkModulePkg/Universal/BdsDxe
parentc516c7178a735366468dd4692d121213bb137888 (diff)
downloadedk2-platforms-5c08e1173703234cc2913757f237ee916087498a.tar.xz
Move BdsDxe and GenericBdsLib to IntelFrameworkModulePkg, these modules need dependent on gEfiLegacyBiosProtocol to provide legacy boot support. But legacy boot is not described by PI/UEFI specification.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7354 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'IntelFrameworkModulePkg/Universal/BdsDxe')
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h141
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf164
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c363
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c1663
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h94
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr383
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c494
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.unibin0 -> 37568 bytes
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c1376
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h1612
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c1661
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c942
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c315
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr126
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c319
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h209
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c1323
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c1417
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c299
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h108
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.unibin0 -> 3316 bytes
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr51
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c257
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c409
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h134
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.unibin0 -> 3588 bytes
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr74
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c976
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h240
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.unibin0 -> 10036 bytes
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr137
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c701
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h90
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c49
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h39
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/Language.c399
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/Language.h32
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c425
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/String.c88
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/String.h75
-rw-r--r--IntelFrameworkModulePkg/Universal/BdsDxe/Strings.unibin0 -> 7342 bytes
41 files changed, 17185 insertions, 0 deletions
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h b/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h
new file mode 100644
index 0000000000..56b709ecca
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h
@@ -0,0 +1,141 @@
+/** @file
+ Head file for BDS Architectural Protocol implementation
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 _BDS_MODULE_H_
+#define _BDS_MODULE_H_
+
+#include <PiDxe.h>
+#include <MdeModuleHii.h>
+
+#include <Guid/FileSystemVolumeLabelInfo.h>
+#include <Protocol/DevicePath.h>
+#include <Guid/BootState.h>
+#include <Guid/DataHubRecords.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/CpuIo.h>
+#include <Guid/FileInfo.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/Bds.h>
+#include <Protocol/DataHub.h>
+#include <Protocol/UgaDraw.h>
+#include <Protocol/BlockIo.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/GenericPlatformVariable.h>
+#include <Guid/CapsuleVendor.h>
+#include <Protocol/ConsoleControl.h>
+#include <Protocol/GenericMemoryTest.h>
+#include <Protocol/FormBrowser2.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+#include <Protocol/SerialIo.h>
+#include <Protocol/LegacyBios.h>
+#include <Protocol/SimpleTextInEx.h>
+#include <Protocol/Performance.h>
+
+#include <Library/UefiDriverEntryPoint.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/PerformanceLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/IfrSupportLib.h>
+#include <Library/ExtendedIfrSupportLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/HiiLib.h>
+#include <Library/ExtendedHiiLib.h>
+
+
+#include <Library/GenericBdsLib.h>
+#include <Library/PlatformBdsLib.h>
+
+#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS(_this) \
+ CR ((_this), \
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE, \
+ Bds, \
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE \
+ )
+
+/**
+
+ Show progress bar with title above it. It only works in Graphics mode.
+
+ @param TitleForeground Foreground color for Title.
+ @param TitleBackground Background color for Title.
+ @param Title Title above progress bar.
+ @param ProgressColor Progress bar color.
+ @param Progress Progress (0-100)
+ @param PreviousValue The previous value of the progress.
+
+ @retval EFI_STATUS Success update the progress bar
+
+**/
+EFI_STATUS
+PlatformBdsShowProgress (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,
+ IN CHAR16 *Title,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,
+ IN UINTN Progress,
+ IN UINTN PreviousValue
+ );
+
+//
+// Prototypes
+//
+
+/**
+
+ Install Boot Device Selection Protocol
+
+ @param ImageHandle The image handle.
+ @param SystemTable The system table.
+
+ @retval EFI_SUCEESS BDS has finished initializing.
+ Return the dispatcher and recall BDS.Entry
+ @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface
+
+**/
+EFI_STATUS
+EFIAPI
+BdsInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+
+ Service routine for BdsInstance->Entry(). Devices are connected, the
+ consoles are initialized, and the boot options are tried.
+
+ @param This Protocol Instance structure.
+
+**/
+VOID
+EFIAPI
+BdsEntry (
+ IN EFI_BDS_ARCH_PROTOCOL *This
+ );
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf b/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf
new file mode 100644
index 0000000000..c8136db4fc
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf
@@ -0,0 +1,164 @@
+#/** @file
+#
+# BDSDxe module is core driver for BDS phase.
+# When DxeCore dispatching all DXE driver, this module will produce architecture protocol
+# gEfiBdsArchProtocolGuid. After DxeCore finish dispatching, DxeCore will invoke Entry
+# interface of protocol gEfiBdsArchProtocolGuid, then BDS phase is entered.
+#
+# Generally, this module take reposiblity to connect all necessary devices for platform boot,
+# these boot device path are hold in PlatformBdsLib library instance produced by platform.
+# For legacy boot, BDS will transfer control to legacy BIOS after legacy boot device is select.
+# For EFI boot, BDS will load boot loader file EFI\BOOT\BOOTIA32.EFI, EFI\BOOT\BOOTX64.EFI,
+# EFI\BOOT\BOOTIA64.EFI file from selected boot device and transfer control to boot loader.
+#
+# BDSDxe also maintain the UI for "Boot Manager, Boot Maintaince Manager, Device Manager" which
+# is used for user to configure boot option or maintain hardware device.
+#
+# Copyright (c) 2008, Intel Corporation. <BR>
+# All rights reserved. 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.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BdsDxe
+ FILE_GUID = FC5C7020-1A48-4198-9BE2-EAD5ABC8CF2F
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EFI_SPECIFICATION_VERSION = 0x00020000
+ ENTRY_POINT = BdsInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ FrontPage.h
+ Language.h
+ Bds.h
+ Hotkey.h
+ BootMaint/BBSsupport.h
+ BootMngr/BootManager.h
+ BootMaint/BootMaint.h
+ String.h
+ BootMaint/FormGuid.h
+ HwErrRecSupport.c
+ HwErrRecSupport.h
+
+ DeviceMngr/DeviceManager.h
+ DeviceMngr/DeviceManagerVfr.Vfr
+ DeviceMngr/DeviceManagerStrings.uni
+ DeviceMngr/DeviceManager.c
+ BootMngr/BootManagerVfr.Vfr
+ BootMngr/BootManagerStrings.uni
+ BootMngr/BootManager.c
+ BootMaint/FE.vfr
+ BootMaint/FileExplorer.c
+ BootMaint/BootMaint.c
+ BootMaint/BBSsupport.c
+ BootMaint/UpdatePage.c
+ BootMaint/Variable.c
+ BootMaint/Data.c
+ BootMaint/ConsoleOption.c
+ BootMaint/BootOption.c
+ BootMaint/BmLib.c
+ BootMaint/Bm.vfr
+ BootMaint/Bmstring.uni
+ Hotkey.c
+ MemoryTest.c
+ Capsules.c
+ Strings.uni
+ String.c
+ Language.c
+ FrontPageVfr.Vfr
+ FrontPageStrings.uni
+ FrontPage.c
+ BdsEntry.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ #
+ #This dependency is because of gEfiLegacyBiosProtocolGuid and gEfiDataHubProtocolGuid. It may be removed if a Library class is created to
+ #abstract away definition in Framework specification or PI spec incorporates the Legacy Booting Protocols and Data Hub Protocols.
+ #
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+
+[LibraryClasses]
+ DevicePathLib
+ BaseLib
+ HobLib
+ UefiRuntimeServicesTableLib
+ IfrSupportLib
+ ExtendedIfrSupportLib
+ GenericBdsLib
+ ReportStatusCodeLib
+ PerformanceLib
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ HiiLib
+ ExtendedHiiLib
+ UefiDriverEntryPoint
+ PlatformBdsLib
+ CapsuleLib
+
+[Guids]
+ gEfiGlobalVariableGuid # ALWAYS_CONSUMED
+ gEfiBootStateGuid # ALWAYS_CONSUMED
+ gEfiFileSystemVolumeLabelInfoIdGuid # ALWAYS_CONSUMED
+ gEfiFileInfoGuid # ALWAYS_CONSUMED
+ gEfiGenericPlatformVariableGuid
+ gEfiMiscSubClassGuid
+ gEfiMemorySubClassGuid
+ gEfiProcessorSubClassGuid
+ gEfiCapsuleVendorGuid
+
+[Protocols]
+ gEfiHiiStringProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSimpleFileSystemProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiLoadFileProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiBdsArchProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiDataHubProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiGenericMemTestProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiLegacyBiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiConsoleControlProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiDatabaseProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiUgaDrawProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiBlockIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiGraphicsOutputProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSimpleTextInputExProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiConfigRoutingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiConfigAccessProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiFormBrowser2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSerialIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[FeaturePcd.common]
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHardwareErrorRecord
+ gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport
+
+[Pcd.common]
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLang
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel
+
+[Depex]
+ gEfiHiiDatabaseProtocolGuid
+
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c
new file mode 100644
index 0000000000..d8bf26a7bb
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c
@@ -0,0 +1,363 @@
+/** @file
+ This module produce main entry for BDS phase - BdsEntry.
+ When this module was dispatched by DxeCore, gEfiBdsArchProtocolGuid will be installed
+ which contains interface of BdsEntry.
+ After DxeCore finish DXE phase, gEfiBdsArchProtocolGuid->BdsEntry will be invoked
+ to enter BDS phase.
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "Bds.h"
+#include "Language.h"
+#include "FrontPage.h"
+#include "Hotkey.h"
+#include "HwErrRecSupport.h"
+
+///
+/// BDS arch protocol instance initial value.
+///
+/// Note: Current BDS not directly get the BootMode, DefaultBoot,
+/// TimeoutDefault, MemoryTestLevel value from the BDS arch protocol.
+/// Please refer to the library useage of BdsLibGetBootMode, BdsLibGetTimeout
+/// and PlatformBdsDiagnostics in BdsPlatform.c
+///
+EFI_BDS_ARCH_PROTOCOL_INSTANCE gBdsInstanceTemplate = {
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE,
+ NULL,
+ {BdsEntry},
+ 0xFFFF,
+ TRUE,
+ 0,
+ EXTENSIVE
+};
+
+UINT16 *mBootNext = NULL;
+
+EFI_HANDLE mBdsImageHandle;
+
+/**
+
+ Install Boot Device Selection Protocol
+
+ @param ImageHandle The image handle.
+ @param SystemTable The system table.
+
+ @retval EFI_SUCEESS BDS has finished initializing.
+ Return the dispatcher and recall BDS.Entry
+ @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface
+
+**/
+EFI_STATUS
+EFIAPI
+BdsInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ mBdsImageHandle = ImageHandle;
+
+ //
+ // Install protocol interface
+ //
+ Status = gBS->InstallProtocolInterface (
+ &gBdsInstanceTemplate.Handle,
+ &gEfiBdsArchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gBdsInstanceTemplate.Bds
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+
+ This function attempts to boot for the boot order specified
+ by platform policy.
+
+**/
+VOID
+BdsBootDeviceSelect (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ BDS_COMMON_OPTION *BootOption;
+ UINTN ExitDataSize;
+ CHAR16 *ExitData;
+ UINT16 Timeout;
+ LIST_ENTRY BootLists;
+ CHAR16 Buffer[20];
+ BOOLEAN BootNextExist;
+ LIST_ENTRY *LinkBootNext;
+
+ //
+ // Got the latest boot option
+ //
+ BootNextExist = FALSE;
+ LinkBootNext = NULL;
+ InitializeListHead (&BootLists);
+
+ //
+ // First check the boot next option
+ //
+ ZeroMem (Buffer, sizeof (Buffer));
+
+ if (mBootNext != NULL) {
+ //
+ // Indicate we have the boot next variable, so this time
+ // boot will always have this boot option
+ //
+ BootNextExist = TRUE;
+
+ //
+ // Clear the this variable so it's only exist in this time boot
+ //
+ gRT->SetVariable (
+ L"BootNext",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ 0,
+ mBootNext
+ );
+
+ //
+ // Add the boot next boot option
+ //
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);
+ BootOption = BdsLibVariableToOption (&BootLists, Buffer);
+
+ //
+ // If fail to get boot option from variable, just return and do nothing.
+ //
+ if (BootOption == NULL) {
+ return;
+ }
+
+ BootOption->BootCurrent = *mBootNext;
+ }
+ //
+ // Parse the boot order to get boot option
+ //
+ BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
+ Link = BootLists.ForwardLink;
+
+ //
+ // Parameter check, make sure the loop will be valid
+ //
+ if (Link == NULL) {
+ return ;
+ }
+ //
+ // Here we make the boot in a loop, every boot success will
+ // return to the front page
+ //
+ for (;;) {
+ //
+ // Check the boot option list first
+ //
+ if (Link == &BootLists) {
+ //
+ // There are two ways to enter here:
+ // 1. There is no active boot option, give user chance to
+ // add new boot option
+ // 2. All the active boot option processed, and there is no
+ // one is success to boot, then we back here to allow user
+ // add new active boot option
+ //
+ Timeout = 0xffff;
+ PlatformBdsEnterFrontPage (Timeout, FALSE);
+ InitializeListHead (&BootLists);
+ BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
+ Link = BootLists.ForwardLink;
+ continue;
+ }
+ //
+ // Get the boot option from the link list
+ //
+ BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
+
+ //
+ // According to EFI Specification, if a load option is not marked
+ // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
+ // load the option.
+ //
+ if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
+ //
+ // skip the header of the link list, becuase it has no boot option
+ //
+ Link = Link->ForwardLink;
+ continue;
+ }
+ //
+ // Make sure the boot option device path connected,
+ // but ignore the BBS device path
+ //
+ if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
+ //
+ // Notes: the internal shell can not been connected with device path
+ // so we do not check the status here
+ //
+ BdsLibConnectDevicePath (BootOption->DevicePath);
+ }
+ //
+ // All the driver options should have been processed since
+ // now boot will be performed.
+ //
+ Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
+ if (EFI_ERROR (Status)) {
+ //
+ // Call platform action to indicate the boot fail
+ //
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
+ PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);
+
+ //
+ // Check the next boot option
+ //
+ Link = Link->ForwardLink;
+
+ } else {
+ //
+ // Call platform action to indicate the boot success
+ //
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
+ PlatformBdsBootSuccess (BootOption);
+
+ //
+ // Boot success, then stop process the boot order, and
+ // present the boot manager menu, front page
+ //
+ Timeout = 0xffff;
+ PlatformBdsEnterFrontPage (Timeout, FALSE);
+
+ //
+ // Rescan the boot option list, avoid pertential risk of the boot
+ // option change in front page
+ //
+ if (BootNextExist) {
+ LinkBootNext = BootLists.ForwardLink;
+ }
+
+ InitializeListHead (&BootLists);
+ if (LinkBootNext != NULL) {
+ //
+ // Reserve the boot next option
+ //
+ InsertTailList (&BootLists, LinkBootNext);
+ }
+
+ BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
+ Link = BootLists.ForwardLink;
+ }
+ }
+
+}
+
+/**
+
+ Service routine for BdsInstance->Entry(). Devices are connected, the
+ consoles are initialized, and the boot options are tried.
+
+ @param This Protocol Instance structure.
+
+**/
+VOID
+EFIAPI
+BdsEntry (
+ IN EFI_BDS_ARCH_PROTOCOL *This
+ )
+{
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData;
+ LIST_ENTRY DriverOptionList;
+ LIST_ENTRY BootOptionList;
+ UINTN BootNextSize;
+
+ //
+ // Insert the performance probe
+ //
+ PERF_END (0, DXE_TOK, NULL, 0);
+ PERF_START (0, BDS_TOK, NULL, 0);
+
+ //
+ // Initialize the global system boot option and driver option
+ //
+ InitializeListHead (&DriverOptionList);
+ InitializeListHead (&BootOptionList);
+
+ //
+ // Initialize hotkey service
+ //
+ InitializeHotkeyService ();
+
+ //
+ // Get the BDS private data
+ //
+ PrivateData = EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This);
+
+ //
+ // Do the platform init, can be customized by OEM/IBV
+ //
+ PERF_START (0, "PlatformBds", "BDS", 0);
+ PlatformBdsInit (PrivateData);
+
+ if (FeaturePcdGet (PcdSupportHardwareErrorRecord)) {
+ InitializeHwErrRecSupport (PcdGet16 (PcdHardwareErrorRecordLevel));
+ }
+ //
+ // bugbug: platform specific code
+ // Initialize the platform specific string and language
+ //
+ InitializeStringSupport ();
+ InitializeLanguage (TRUE);
+ InitializeFrontPage (TRUE);
+
+ //
+ // Set up the device list based on EFI 1.1 variables
+ // process Driver#### and Load the driver's in the
+ // driver option list
+ //
+ BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder");
+ if (!IsListEmpty (&DriverOptionList)) {
+ BdsLibLoadDrivers (&DriverOptionList);
+ }
+ //
+ // Check if we have the boot next option
+ //
+ mBootNext = BdsLibGetVariableAndSize (
+ L"BootNext",
+ &gEfiGlobalVariableGuid,
+ &BootNextSize
+ );
+
+ //
+ // Setup some platform policy here
+ //
+ PlatformBdsPolicyBehavior (PrivateData, &DriverOptionList, &BootOptionList);
+ PERF_END (0, "PlatformBds", "BDS", 0);
+
+ //
+ // BDS select the boot device to load OS
+ //
+ BdsBootDeviceSelect ();
+
+ //
+ // Only assert here since this is the right behavior, we should never
+ // return back to DxeCore.
+ //
+ ASSERT (FALSE);
+
+ return ;
+}
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c
new file mode 100644
index 0000000000..94261a0bef
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c
@@ -0,0 +1,1663 @@
+/** @file
+ This function deal with the legacy boot option, it create, delete
+ and manage the legacy boot option, all legacy boot option is getting from
+ the legacy BBS table.
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "BBSsupport.h"
+
+/**
+
+ Translate the first n characters of an Ascii string to
+ Unicode characters. The count n is indicated by parameter
+ Size. If Size is greater than the length of string, then
+ the entire string is translated.
+
+
+ @param AStr Pointer to input Ascii string.
+ @param Size The number of characters to translate.
+ @param UStr Pointer to output Unicode string buffer.
+
+**/
+VOID
+AsciiToUnicodeSize (
+ IN UINT8 *AStr,
+ IN UINTN Size,
+ OUT UINT16 *UStr
+ )
+{
+ UINTN Idx;
+
+ Idx = 0;
+ while (AStr[Idx] != 0) {
+ UStr[Idx] = (CHAR16) AStr[Idx];
+ if (Idx == Size) {
+ break;
+ }
+
+ Idx++;
+ }
+ UStr[Idx] = 0;
+}
+
+/**
+ Build Legacy Device Name String according.
+
+ @param CurBBSEntry BBS Table.
+ @param Index Index.
+ @param BufSize The buffer size.
+ @param BootString The output string.
+
+**/
+VOID
+BdsBuildLegacyDevNameString (
+ IN BBS_TABLE *CurBBSEntry,
+ IN UINTN Index,
+ IN UINTN BufSize,
+ OUT CHAR16 *BootString
+ )
+{
+ CHAR16 *Fmt;
+ CHAR16 *Type;
+ UINT8 *StringDesc;
+ CHAR16 Temp[80];
+
+ switch (Index) {
+ //
+ // Primary Master
+ //
+ case 1:
+ Fmt = L"Primary Master %s";
+ break;
+
+ //
+ // Primary Slave
+ //
+ case 2:
+ Fmt = L"Primary Slave %s";
+ break;
+
+ //
+ // Secondary Master
+ //
+ case 3:
+ Fmt = L"Secondary Master %s";
+ break;
+
+ //
+ // Secondary Slave
+ //
+ case 4:
+ Fmt = L"Secondary Slave %s";
+ break;
+
+ default:
+ Fmt = L"%s";
+ break;
+ }
+
+ switch (CurBBSEntry->DeviceType) {
+ case BBS_FLOPPY:
+ Type = L"Floppy";
+ break;
+
+ case BBS_HARDDISK:
+ Type = L"Harddisk";
+ break;
+
+ case BBS_CDROM:
+ Type = L"CDROM";
+ break;
+
+ case BBS_PCMCIA:
+ Type = L"PCMCIAe";
+ break;
+
+ case BBS_USB:
+ Type = L"USB";
+ break;
+
+ case BBS_EMBED_NETWORK:
+ Type = L"Network";
+ break;
+
+ case BBS_BEV_DEVICE:
+ Type = L"BEVe";
+ break;
+
+ case BBS_UNKNOWN:
+ default:
+ Type = L"Unknown";
+ break;
+ }
+ //
+ // If current BBS entry has its description then use it.
+ //
+ StringDesc = (UINT8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset);
+ if (NULL != StringDesc) {
+ //
+ // Only get fisrt 32 characters, this is suggested by BBS spec
+ //
+ AsciiToUnicodeSize (StringDesc, 32, Temp);
+ Fmt = L"%s";
+ Type = Temp;
+ }
+
+ //
+ // BbsTable 16 entries are for onboard IDE.
+ // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11
+ //
+ if (Index >= 5 && Index <= 16 && CurBBSEntry->DeviceType == BBS_HARDDISK) {
+ Fmt = L"%s %d";
+ UnicodeSPrint (BootString, BufSize, Fmt, Type, Index - 5);
+ } else {
+ UnicodeSPrint (BootString, BufSize, Fmt, Type);
+ }
+}
+
+/**
+
+ Create a legacy boot option for the specified entry of
+ BBS table, save it as variable, and append it to the boot
+ order list.
+
+
+ @param CurrentBbsEntry Pointer to current BBS table.
+ @param CurrentBbsDevPath Pointer to the Device Path Protocol instance of BBS
+ @param Index Index of the specified entry in BBS table.
+ @param BootOrderList On input, the original boot order list.
+ On output, the new boot order list attached with the
+ created node.
+ @param BootOrderListSize On input, the original size of boot order list.
+ On output, the size of new boot order list.
+
+ @retval EFI_SUCCESS Boot Option successfully created.
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
+ @retval Other Error occurs while setting variable.
+
+**/
+EFI_STATUS
+BdsCreateLegacyBootOption (
+ IN BBS_TABLE *CurrentBbsEntry,
+ IN EFI_DEVICE_PATH_PROTOCOL *CurrentBbsDevPath,
+ IN UINTN Index,
+ IN OUT UINT16 **BootOrderList,
+ IN OUT UINTN *BootOrderListSize
+ )
+{
+ EFI_STATUS Status;
+ UINT16 CurrentBootOptionNo;
+ UINT16 BootString[10];
+ UINT16 BootDesc[100];
+ CHAR8 HelpString[100];
+ UINT16 *NewBootOrderList;
+ UINTN BufferSize;
+ UINTN StringLen;
+ VOID *Buffer;
+ UINT8 *Ptr;
+ UINT16 CurrentBbsDevPathSize;
+ UINTN BootOrderIndex;
+ UINTN BootOrderLastIndex;
+ UINTN ArrayIndex;
+ BOOLEAN IndexNotFound;
+ BBS_BBS_DEVICE_PATH *NewBbsDevPathNode;
+
+ if ((*BootOrderList) == NULL) {
+ CurrentBootOptionNo = 0;
+ } else {
+ for (ArrayIndex = 0; ArrayIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); ArrayIndex++) {
+ IndexNotFound = TRUE;
+ for (BootOrderIndex = 0; BootOrderIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); BootOrderIndex++) {
+ if ((*BootOrderList)[BootOrderIndex] == ArrayIndex) {
+ IndexNotFound = FALSE;
+ break;
+ }
+ }
+
+ if (!IndexNotFound) {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ CurrentBootOptionNo = (UINT16) ArrayIndex;
+ }
+
+ UnicodeSPrint (
+ BootString,
+ sizeof (BootString),
+ L"Boot%04x",
+ CurrentBootOptionNo
+ );
+
+ BdsBuildLegacyDevNameString (CurrentBbsEntry, Index, sizeof (BootDesc), BootDesc);
+
+ //
+ // Create new BBS device path node with description string
+ //
+ UnicodeStrToAsciiStr ((CONST CHAR16*)&BootDesc, (CHAR8*)&HelpString);
+
+ StringLen = AsciiStrLen (HelpString);
+ NewBbsDevPathNode = AllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen);
+ if (NewBbsDevPathNode == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (NewBbsDevPathNode, CurrentBbsDevPath, sizeof (BBS_BBS_DEVICE_PATH));
+ CopyMem (NewBbsDevPathNode->String, HelpString, StringLen + 1);
+ SetDevicePathNodeLength (&(NewBbsDevPathNode->Header), sizeof (BBS_BBS_DEVICE_PATH) + StringLen);
+
+ //
+ // Create entire new CurrentBbsDevPath with end node
+ //
+ CurrentBbsDevPath = AppendDevicePathNode (
+ EndDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) NewBbsDevPathNode
+ );
+ if (CurrentBbsDevPath == NULL) {
+ FreePool (NewBbsDevPathNode);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentBbsDevPathSize = (UINT16) (GetDevicePathSize (CurrentBbsDevPath));
+
+ BufferSize = sizeof (UINT32) +
+ sizeof (UINT16) +
+ StrSize (BootDesc) +
+ CurrentBbsDevPathSize +
+ sizeof (BBS_TABLE) +
+ sizeof (UINT16);
+
+ Buffer = AllocateZeroPool (BufferSize);
+ if (Buffer == NULL) {
+ FreePool (NewBbsDevPathNode);
+ FreePool (CurrentBbsDevPath);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = (UINT8 *) Buffer;
+
+ *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;
+ Ptr += sizeof (UINT32);
+
+ *((UINT16 *) Ptr) = CurrentBbsDevPathSize;
+ Ptr += sizeof (UINT16);
+
+ CopyMem (
+ Ptr,
+ BootDesc,
+ StrSize (BootDesc)
+ );
+ Ptr += StrSize (BootDesc);
+
+ CopyMem (
+ Ptr,
+ CurrentBbsDevPath,
+ CurrentBbsDevPathSize
+ );
+ Ptr += CurrentBbsDevPathSize;
+
+ CopyMem (
+ Ptr,
+ CurrentBbsEntry,
+ sizeof (BBS_TABLE)
+ );
+
+ Ptr += sizeof (BBS_TABLE);
+ *((UINT16 *) Ptr) = (UINT16) Index;
+
+ Status = gRT->SetVariable (
+ BootString,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BufferSize,
+ Buffer
+ );
+
+ FreePool (Buffer);
+
+ Buffer = NULL;
+
+ NewBootOrderList = AllocateZeroPool (*BootOrderListSize + sizeof (UINT16));
+ if (NULL == NewBootOrderList) {
+ FreePool (NewBbsDevPathNode);
+ FreePool (CurrentBbsDevPath);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (*BootOrderList != NULL) {
+ CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize);
+ FreePool (*BootOrderList);
+ }
+
+ BootOrderLastIndex = (UINTN) (*BootOrderListSize / sizeof (UINT16));
+ NewBootOrderList[BootOrderLastIndex] = CurrentBootOptionNo;
+ *BootOrderListSize += sizeof (UINT16);
+ *BootOrderList = NewBootOrderList;
+
+ FreePool (NewBbsDevPathNode);
+ FreePool (CurrentBbsDevPath);
+ return Status;
+}
+
+/**
+ Check if the boot option is a legacy one.
+
+ @param BootOptionVar The boot option data payload.
+ @param BbsEntry The BBS Table.
+ @param BbsIndex The table index.
+
+ @retval TRUE It is a legacy boot option.
+ @retval FALSE It is not a legacy boot option.
+
+**/
+BOOLEAN
+BdsIsLegacyBootOption (
+ IN UINT8 *BootOptionVar,
+ OUT BBS_TABLE **BbsEntry,
+ OUT UINT16 *BbsIndex
+ )
+{
+ UINT8 *Ptr;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ BOOLEAN Ret;
+ UINT16 DevPathLen;
+
+ Ptr = BootOptionVar;
+ Ptr += sizeof (UINT32);
+ DevPathLen = *(UINT16 *) Ptr;
+ Ptr += sizeof (UINT16);
+ Ptr += StrSize ((UINT16 *) Ptr);
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
+ if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {
+ Ptr += DevPathLen;
+ *BbsEntry = (BBS_TABLE *) Ptr;
+ Ptr += sizeof (BBS_TABLE);
+ *BbsIndex = *(UINT16 *) Ptr;
+ Ret = TRUE;
+ } else {
+ *BbsEntry = NULL;
+ Ret = FALSE;
+ }
+
+ return Ret;
+}
+
+/**
+ Delete all the invalid legacy boot options.
+
+ @retval EFI_SUCCESS All invalide legacy boot options are deleted.
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
+ @retval EFI_NOT_FOUND Fail to retrive variable of boot order.
+**/
+EFI_STATUS
+BdsDeleteAllInvalidLegacyBootOptions (
+ VOID
+ )
+{
+ UINT16 *BootOrder;
+ UINT8 *BootOptionVar;
+ UINTN BootOrderSize;
+ UINTN BootOptionSize;
+ EFI_STATUS Status;
+ UINT16 HddCount;
+ UINT16 BbsCount;
+ HDD_INFO *LocalHddInfo;
+ BBS_TABLE *LocalBbsTable;
+ BBS_TABLE *BbsEntry;
+ UINT16 BbsIndex;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINTN Index;
+ UINT16 BootOption[10];
+ UINT16 BootDesc[100];
+ BOOLEAN DescStringMatch;
+
+ Status = EFI_SUCCESS;
+ BootOrder = NULL;
+ BootOrderSize = 0;
+ HddCount = 0;
+ BbsCount = 0;
+ LocalHddInfo = NULL;
+ LocalBbsTable = NULL;
+ BbsEntry = NULL;
+
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ LegacyBios->GetBbsInfo (
+ LegacyBios,
+ &HddCount,
+ &LocalHddInfo,
+ &BbsCount,
+ &LocalBbsTable
+ );
+
+ BootOrder = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderSize
+ );
+ if (NULL == BootOrder) {
+ return EFI_NOT_FOUND;
+ }
+
+ Index = 0;
+ while (Index < BootOrderSize / sizeof (UINT16)) {
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
+ BootOptionVar = BdsLibGetVariableAndSize (
+ BootOption,
+ &gEfiGlobalVariableGuid,
+ &BootOptionSize
+ );
+ if (NULL == BootOptionVar) {
+ if (BootOrder != NULL) {
+ FreePool (BootOrder);
+ }
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Skip Non-Legacy boot options
+ //
+ if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {
+ if (BootOptionVar!= NULL) {
+ FreePool (BootOptionVar);
+ }
+ Index++;
+ continue;
+ }
+
+ //
+ // Check if BBS Description String is changed
+ //
+ DescStringMatch = FALSE;
+
+ BdsBuildLegacyDevNameString (
+ &LocalBbsTable[BbsIndex],
+ BbsIndex,
+ sizeof(BootDesc),
+ BootDesc
+ );
+
+ if (StrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) {
+ DescStringMatch = TRUE;
+ }
+
+ if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) ||
+ (LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM)) &&
+ (LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) &&
+ DescStringMatch) {
+ Index++;
+ continue;
+ }
+
+ if (BootOptionVar != NULL) {
+ FreePool (BootOptionVar);
+ }
+ //
+ // should delete
+ //
+ BdsDeleteBootOption (
+ BootOrder[Index],
+ BootOrder,
+ &BootOrderSize
+ );
+ }
+
+ //
+ // Adjust the number of boot options.
+ //
+ if (BootOrderSize != 0) {
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BootOrderSize,
+ BootOrder
+ );
+ } else {
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
+ }
+
+ if (BootOrder != NULL) {
+ FreePool (BootOrder);
+ }
+
+ return Status;
+}
+
+/**
+ Find all legacy boot option by device type.
+
+ @param BootOrder The boot order array.
+ @param BootOptionNum The number of boot option.
+ @param DevType Device type.
+ @param Attribute The boot option attribute.
+ @param BbsIndex The BBS table index.
+ @param OptionNumber The boot option index.
+
+ @retval TRUE The Legacy boot option is found.
+ @retval FALSE The legacy boot option is not found.
+
+**/
+BOOLEAN
+BdsFindLegacyBootOptionByDevType (
+ IN UINT16 *BootOrder,
+ IN UINTN BootOptionNum,
+ IN UINT16 DevType,
+ OUT UINT32 *Attribute,
+ OUT UINT16 *BbsIndex,
+ OUT UINTN *OptionNumber
+ )
+{
+ UINTN Index;
+ UINTN BootOrderIndex;
+ UINT16 BootOption[100];
+ UINTN BootOptionSize;
+ UINT8 *BootOptionVar;
+ BBS_TABLE *BbsEntry;
+ BOOLEAN Found;
+
+ BbsEntry = NULL;
+ Found = FALSE;
+
+ if (NULL == BootOrder) {
+ return Found;
+ }
+
+ //
+ // Loop all boot option from variable
+ //
+ for (BootOrderIndex = 0; BootOrderIndex < BootOptionNum; BootOrderIndex++) {
+ Index = (UINTN) BootOrder[BootOrderIndex];
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", Index);
+ BootOptionVar = BdsLibGetVariableAndSize (
+ BootOption,
+ &gEfiGlobalVariableGuid,
+ &BootOptionSize
+ );
+ if (NULL == BootOptionVar) {
+ continue;
+ }
+
+ //
+ // Skip Non-legacy boot option
+ //
+ if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {
+ FreePool (BootOptionVar);
+ continue;
+ }
+
+ if (BbsEntry->DeviceType != DevType) {
+ FreePool (BootOptionVar);
+ continue;
+ }
+
+ *Attribute = *(UINT32 *) BootOptionVar;
+ *OptionNumber = Index;
+ Found = TRUE;
+ FreePool (BootOptionVar);
+ break;
+ }
+
+ return Found;
+}
+
+/**
+ Create a legacy boot option.
+
+ @param BbsItem The BBS Table entry.
+ @param Index Index of the specified entry in BBS table.
+ @param BootOrderList The boot order list.
+ @param BootOrderListSize The size of boot order list.
+
+ @retval EFI_OUT_OF_RESOURCE No enough memory.
+ @retval EFI_SUCCESS The function complete successfully.
+ @return Other value if the legacy boot option is not created.
+
+**/
+EFI_STATUS
+BdsCreateOneLegacyBootOption (
+ IN BBS_TABLE *BbsItem,
+ IN UINTN Index,
+ IN OUT UINT16 **BootOrderList,
+ IN OUT UINTN *BootOrderListSize
+ )
+{
+ BBS_BBS_DEVICE_PATH BbsDevPathNode;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+
+ DevPath = NULL;
+
+ //
+ // Create device path node.
+ //
+ BbsDevPathNode.Header.Type = BBS_DEVICE_PATH;
+ BbsDevPathNode.Header.SubType = BBS_BBS_DP;
+ SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));
+ BbsDevPathNode.DeviceType = BbsItem->DeviceType;
+ CopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16));
+
+ DevPath = AppendDevicePathNode (
+ EndDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode
+ );
+ if (NULL == DevPath) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = BdsCreateLegacyBootOption (
+ BbsItem,
+ DevPath,
+ Index,
+ BootOrderList,
+ BootOrderListSize
+ );
+ BbsItem->BootPriority = 0x00;
+
+ FreePool (DevPath);
+
+ return Status;
+}
+
+/**
+
+ Add the legacy boot options from BBS table if they do not exist.
+
+ @retval EFI_SUCCESS The boot options are added successfully
+ or they are already in boot options.
+
+**/
+EFI_STATUS
+BdsAddNonExistingLegacyBootOptions (
+ VOID
+ )
+{
+ UINT16 *BootOrder;
+ UINTN BootOrderSize;
+ EFI_STATUS Status;
+ UINT16 HddCount;
+ UINT16 BbsCount;
+ HDD_INFO *LocalHddInfo;
+ BBS_TABLE *LocalBbsTable;
+ UINT16 BbsIndex;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINTN Index;
+ UINT32 Attribute;
+ UINTN OptionNumber;
+ BOOLEAN Ret;
+
+ BootOrder = NULL;
+ HddCount = 0;
+ BbsCount = 0;
+ LocalHddInfo = NULL;
+ LocalBbsTable = NULL;
+
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ LegacyBios->GetBbsInfo (
+ LegacyBios,
+ &HddCount,
+ &LocalHddInfo,
+ &BbsCount,
+ &LocalBbsTable
+ );
+
+ BootOrder = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderSize
+ );
+ if (NULL == BootOrder) {
+ BootOrderSize = 0;
+ }
+
+ for (Index = 0; Index < BbsCount; Index++) {
+ if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
+ (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
+ ) {
+ continue;
+ }
+
+ Ret = BdsFindLegacyBootOptionByDevType (
+ BootOrder,
+ BootOrderSize / sizeof (UINT16),
+ LocalBbsTable[Index].DeviceType,
+ &Attribute,
+ &BbsIndex,
+ &OptionNumber
+ );
+ if (Ret) {
+ continue;
+ }
+
+ //
+ // Not found such type of legacy device in boot options or we found but it's disabled
+ // so we have to create one and put it to the tail of boot order list
+ //
+ Status = BdsCreateOneLegacyBootOption (
+ &LocalBbsTable[Index],
+ Index,
+ &BootOrder,
+ &BootOrderSize
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ if (BootOrderSize > 0) {
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BootOrderSize,
+ BootOrder
+ );
+ } else {
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
+ }
+
+ if (BootOrder != NULL) {
+ FreePool (BootOrder);
+ }
+
+ return Status;
+}
+
+/**
+ Fill the device order buffer.
+
+ @param BbsTable The BBS table.
+ @param BbsType The BBS Type.
+ @param BbsCount The BBS Count.
+ @param Buf device order buffer.
+
+ @return The device order buffer.
+
+**/
+UINT16 *
+BdsFillDevOrderBuf (
+ IN BBS_TABLE *BbsTable,
+ IN BBS_TYPE BbsType,
+ IN UINTN BbsCount,
+ OUT UINT16 *Buf
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < BbsCount; Index++) {
+ if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
+ continue;
+ }
+
+ if (BbsTable[Index].DeviceType != BbsType) {
+ continue;
+ }
+
+ *Buf = (UINT16) (Index & 0xFF);
+ Buf++;
+ }
+
+ return Buf;
+}
+
+/**
+ Create the device order buffer.
+
+ @param BbsTable The BBS table.
+ @param BbsCount The BBS Count.
+
+ @retval EFI_SUCCES The buffer is created and the EFI variable named
+ VAR_LEGACY_DEV_ORDER and EfiLegacyDevOrderGuid is
+ set correctly.
+ @return Other value if the set of EFI variable fails. Check gRT->SetVariable
+ for detailed information.
+
+**/
+EFI_STATUS
+BdsCreateDevOrder (
+ IN BBS_TABLE *BbsTable,
+ IN UINT16 BbsCount
+ )
+{
+ UINTN Index;
+ UINTN FDCount;
+ UINTN HDCount;
+ UINTN CDCount;
+ UINTN NETCount;
+ UINTN BEVCount;
+ UINTN TotalSize;
+ UINTN HeaderSize;
+ UINT8 *DevOrder;
+ UINT8 *Ptr;
+ EFI_STATUS Status;
+
+ FDCount = 0;
+ HDCount = 0;
+ CDCount = 0;
+ NETCount = 0;
+ BEVCount = 0;
+ TotalSize = 0;
+ HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);
+ DevOrder = NULL;
+ Ptr = NULL;
+ Status = EFI_SUCCESS;
+
+ //
+ // Count all boot devices
+ //
+ for (Index = 0; Index < BbsCount; Index++) {
+ if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
+ continue;
+ }
+
+ switch (BbsTable[Index].DeviceType) {
+ case BBS_FLOPPY:
+ FDCount++;
+ break;
+
+ case BBS_HARDDISK:
+ HDCount++;
+ break;
+
+ case BBS_CDROM:
+ CDCount++;
+ break;
+
+ case BBS_EMBED_NETWORK:
+ NETCount++;
+ break;
+
+ case BBS_BEV_DEVICE:
+ BEVCount++;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);
+ TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);
+ TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);
+ TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);
+ TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);
+
+ //
+ // Create buffer to hold all boot device order
+ //
+ DevOrder = AllocateZeroPool (TotalSize);
+ if (NULL == DevOrder) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = DevOrder;
+
+ *((BBS_TYPE *) Ptr) = BBS_FLOPPY;
+ Ptr += sizeof (BBS_TYPE);
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+ if (FDCount != 0) {
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, (UINT16 *) Ptr);
+ }
+
+ *((BBS_TYPE *) Ptr) = BBS_HARDDISK;
+ Ptr += sizeof (BBS_TYPE);
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+ if (HDCount != 0) {
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, (UINT16 *) Ptr);
+ }
+
+ *((BBS_TYPE *) Ptr) = BBS_CDROM;
+ Ptr += sizeof (BBS_TYPE);
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+ if (CDCount != 0) {
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, (UINT16 *) Ptr);
+ }
+
+ *((BBS_TYPE *) Ptr) = BBS_EMBED_NETWORK;
+ Ptr += sizeof (BBS_TYPE);
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+ if (NETCount != 0) {
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, (UINT16 *) Ptr);
+ }
+
+ *((BBS_TYPE *) Ptr) = BBS_BEV_DEVICE;
+ Ptr += sizeof (BBS_TYPE);
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+ if (BEVCount != 0) {
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr);
+ }
+
+ //
+ // Save device order for legacy boot device to variable.
+ //
+ Status = gRT->SetVariable (
+ VAR_LEGACY_DEV_ORDER,
+ &EfiLegacyDevOrderGuid,
+ VAR_FLAG,
+ TotalSize,
+ DevOrder
+ );
+ FreePool (DevOrder);
+
+ return Status;
+}
+
+/**
+
+ Add the legacy boot devices from BBS table into
+ the legacy device boot order.
+
+ @retval EFI_SUCCESS The boot devices are added successfully.
+
+**/
+EFI_STATUS
+BdsUpdateLegacyDevOrder (
+ VOID
+ )
+{
+ UINT8 *DevOrder;
+ UINT8 *NewDevOrder;
+ UINTN DevOrderSize;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_STATUS Status;
+ UINT16 HddCount;
+ UINT16 BbsCount;
+ HDD_INFO *LocalHddInfo;
+ BBS_TABLE *LocalBbsTable;
+ UINTN Index;
+ UINTN Index2;
+ UINTN *Idx;
+ UINTN FDCount;
+ UINTN HDCount;
+ UINTN CDCount;
+ UINTN NETCount;
+ UINTN BEVCount;
+ UINTN TotalSize;
+ UINTN HeaderSize;
+ UINT8 *Ptr;
+ UINT8 *NewPtr;
+ UINT16 *NewFDPtr;
+ UINT16 *NewHDPtr;
+ UINT16 *NewCDPtr;
+ UINT16 *NewNETPtr;
+ UINT16 *NewBEVPtr;
+ UINT16 *NewDevPtr;
+ UINT16 Length;
+ UINT16 Tmp;
+ UINTN FDIndex;
+ UINTN HDIndex;
+ UINTN CDIndex;
+ UINTN NETIndex;
+ UINTN BEVIndex;
+
+ LocalHddInfo = NULL;
+ LocalBbsTable = NULL;
+ Idx = NULL;
+ FDCount = 0;
+ HDCount = 0;
+ CDCount = 0;
+ NETCount = 0;
+ BEVCount = 0;
+ TotalSize = 0;
+ HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);
+ FDIndex = 0;
+ HDIndex = 0;
+ CDIndex = 0;
+ NETIndex = 0;
+ BEVIndex = 0;
+ NewDevPtr = NULL;
+
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ LegacyBios->GetBbsInfo (
+ LegacyBios,
+ &HddCount,
+ &LocalHddInfo,
+ &BbsCount,
+ &LocalBbsTable
+ );
+
+ DevOrder = (UINT8 *) BdsLibGetVariableAndSize (
+ VAR_LEGACY_DEV_ORDER,
+ &EfiLegacyDevOrderGuid,
+ &DevOrderSize
+ );
+ if (NULL == DevOrder) {
+ return BdsCreateDevOrder (LocalBbsTable, BbsCount);
+ }
+ //
+ // First we figure out how many boot devices with same device type respectively
+ //
+ for (Index = 0; Index < BbsCount; Index++) {
+ if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
+ (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
+ ) {
+ continue;
+ }
+
+ switch (LocalBbsTable[Index].DeviceType) {
+ case BBS_FLOPPY:
+ FDCount++;
+ break;
+
+ case BBS_HARDDISK:
+ HDCount++;
+ break;
+
+ case BBS_CDROM:
+ CDCount++;
+ break;
+
+ case BBS_EMBED_NETWORK:
+ NETCount++;
+ break;
+
+ case BBS_BEV_DEVICE:
+ BEVCount++;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ TotalSize += (HeaderSize + FDCount * sizeof (UINT16));
+ TotalSize += (HeaderSize + HDCount * sizeof (UINT16));
+ TotalSize += (HeaderSize + CDCount * sizeof (UINT16));
+ TotalSize += (HeaderSize + NETCount * sizeof (UINT16));
+ TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));
+
+ NewDevOrder = AllocateZeroPool (TotalSize);
+ if (NULL == NewDevOrder) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewFDPtr = (UINT16 *) (NewDevOrder + HeaderSize);
+ NewHDPtr = (UINT16 *) ((UINT8 *) NewFDPtr + FDCount * sizeof (UINT16) + HeaderSize);
+ NewCDPtr = (UINT16 *) ((UINT8 *) NewHDPtr + HDCount * sizeof (UINT16) + HeaderSize);
+ NewNETPtr = (UINT16 *) ((UINT8 *) NewCDPtr + CDCount * sizeof (UINT16) + HeaderSize);
+ NewBEVPtr = (UINT16 *) ((UINT8 *) NewNETPtr + NETCount * sizeof (UINT16) + HeaderSize);
+
+ //
+ // copy FD
+ //
+ Ptr = DevOrder;
+ NewPtr = NewDevOrder;
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
+ Ptr += sizeof (BBS_TYPE);
+ NewPtr += sizeof (BBS_TYPE);
+ Length = *((UINT16 *) Ptr);
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
+ LocalBbsTable[*Ptr].DeviceType != BBS_FLOPPY
+ ) {
+ Ptr += sizeof (UINT16);
+ continue;
+ }
+
+ NewFDPtr[FDIndex] = *(UINT16 *) Ptr;
+ FDIndex++;
+ Ptr += sizeof (UINT16);
+ }
+ //
+ // copy HD
+ //
+ NewPtr = (UINT8 *) NewHDPtr - HeaderSize;
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
+ Ptr += sizeof (BBS_TYPE);
+ NewPtr += sizeof (BBS_TYPE);
+ Length = *((UINT16 *) Ptr);
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
+ LocalBbsTable[*Ptr].DeviceType != BBS_HARDDISK
+ ) {
+ Ptr += sizeof (UINT16);
+ continue;
+ }
+
+ NewHDPtr[HDIndex] = *(UINT16 *) Ptr;
+ HDIndex++;
+ Ptr += sizeof (UINT16);
+ }
+ //
+ // copy CD
+ //
+ NewPtr = (UINT8 *) NewCDPtr - HeaderSize;
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
+ Ptr += sizeof (BBS_TYPE);
+ NewPtr += sizeof (BBS_TYPE);
+ Length = *((UINT16 *) Ptr);
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
+ LocalBbsTable[*Ptr].DeviceType != BBS_CDROM
+ ) {
+ Ptr += sizeof (UINT16);
+ continue;
+ }
+
+ NewCDPtr[CDIndex] = *(UINT16 *) Ptr;
+ CDIndex++;
+ Ptr += sizeof (UINT16);
+ }
+ //
+ // copy NET
+ //
+ NewPtr = (UINT8 *) NewNETPtr - HeaderSize;
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
+ Ptr += sizeof (BBS_TYPE);
+ NewPtr += sizeof (BBS_TYPE);
+ Length = *((UINT16 *) Ptr);
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
+ LocalBbsTable[*Ptr].DeviceType != BBS_EMBED_NETWORK
+ ) {
+ Ptr += sizeof (UINT16);
+ continue;
+ }
+
+ NewNETPtr[NETIndex] = *(UINT16 *) Ptr;
+ NETIndex++;
+ Ptr += sizeof (UINT16);
+ }
+ //
+ // copy BEV
+ //
+ NewPtr = (UINT8 *) NewBEVPtr - HeaderSize;
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
+ Ptr += sizeof (BBS_TYPE);
+ NewPtr += sizeof (BBS_TYPE);
+ Length = *((UINT16 *) Ptr);
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
+ LocalBbsTable[*Ptr].DeviceType != BBS_BEV_DEVICE
+ ) {
+ Ptr += sizeof (UINT16);
+ continue;
+ }
+
+ NewBEVPtr[BEVIndex] = *(UINT16 *) Ptr;
+ BEVIndex++;
+ Ptr += sizeof (UINT16);
+ }
+
+ for (Index = 0; Index < BbsCount; Index++) {
+ if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
+ (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
+ ) {
+ continue;
+ }
+
+ switch (LocalBbsTable[Index].DeviceType) {
+ case BBS_FLOPPY:
+ Idx = &FDIndex;
+ NewDevPtr = NewFDPtr;
+ break;
+
+ case BBS_HARDDISK:
+ Idx = &HDIndex;
+ NewDevPtr = NewHDPtr;
+ break;
+
+ case BBS_CDROM:
+ Idx = &CDIndex;
+ NewDevPtr = NewCDPtr;
+ break;
+
+ case BBS_EMBED_NETWORK:
+ Idx = &NETIndex;
+ NewDevPtr = NewNETPtr;
+ break;
+
+ case BBS_BEV_DEVICE:
+ Idx = &BEVIndex;
+ NewDevPtr = NewBEVPtr;
+ break;
+
+ default:
+ Idx = NULL;
+ break;
+ }
+ //
+ // at this point we have copied those valid indexes to new buffer
+ // and we should check if there is any new appeared boot device
+ //
+ if (Idx != 0) {
+ for (Index2 = 0; Index2 < *Idx; Index2++) {
+ if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {
+ break;
+ }
+ }
+
+ if (Index2 == *Idx) {
+ //
+ // Index2 == *Idx means we didn't find Index
+ // so Index is a new appeared device's index in BBS table
+ // save it.
+ //
+ NewDevPtr[*Idx] = (UINT16) (Index & 0xFF);
+ (*Idx)++;
+ }
+ }
+ }
+
+ if (FDCount != 0) {
+ //
+ // Just to make sure that disabled indexes are all at the end of the array
+ //
+ for (Index = 0; Index < FDIndex - 1; Index++) {
+ if (0xFF00 != (NewFDPtr[Index] & 0xFF00)) {
+ continue;
+ }
+
+ for (Index2 = Index + 1; Index2 < FDIndex; Index2++) {
+ if (0 == (NewFDPtr[Index2] & 0xFF00)) {
+ Tmp = NewFDPtr[Index];
+ NewFDPtr[Index] = NewFDPtr[Index2];
+ NewFDPtr[Index2] = Tmp;
+ break;
+ }
+ }
+ }
+ }
+
+ if (HDCount != 0) {
+ //
+ // Just to make sure that disabled indexes are all at the end of the array
+ //
+ for (Index = 0; Index < HDIndex - 1; Index++) {
+ if (0xFF00 != (NewHDPtr[Index] & 0xFF00)) {
+ continue;
+ }
+
+ for (Index2 = Index + 1; Index2 < HDIndex; Index2++) {
+ if (0 == (NewHDPtr[Index2] & 0xFF00)) {
+ Tmp = NewHDPtr[Index];
+ NewHDPtr[Index] = NewHDPtr[Index2];
+ NewHDPtr[Index2] = Tmp;
+ break;
+ }
+ }
+ }
+ }
+
+ if (CDCount != 0) {
+ //
+ // Just to make sure that disabled indexes are all at the end of the array
+ //
+ for (Index = 0; Index < CDIndex - 1; Index++) {
+ if (0xFF00 != (NewCDPtr[Index] & 0xFF00)) {
+ continue;
+ }
+
+ for (Index2 = Index + 1; Index2 < CDIndex; Index2++) {
+ if (0 == (NewCDPtr[Index2] & 0xFF00)) {
+ Tmp = NewCDPtr[Index];
+ NewCDPtr[Index] = NewCDPtr[Index2];
+ NewCDPtr[Index2] = Tmp;
+ break;
+ }
+ }
+ }
+ }
+
+ if (NETCount != 0) {
+ //
+ // Just to make sure that disabled indexes are all at the end of the array
+ //
+ for (Index = 0; Index < NETIndex - 1; Index++) {
+ if (0xFF00 != (NewNETPtr[Index] & 0xFF00)) {
+ continue;
+ }
+
+ for (Index2 = Index + 1; Index2 < NETIndex; Index2++) {
+ if (0 == (NewNETPtr[Index2] & 0xFF00)) {
+ Tmp = NewNETPtr[Index];
+ NewNETPtr[Index] = NewNETPtr[Index2];
+ NewNETPtr[Index2] = Tmp;
+ break;
+ }
+ }
+ }
+ }
+
+ if (BEVCount!= 0) {
+ //
+ // Just to make sure that disabled indexes are all at the end of the array
+ //
+ for (Index = 0; Index < BEVIndex - 1; Index++) {
+ if (0xFF00 != (NewBEVPtr[Index] & 0xFF00)) {
+ continue;
+ }
+
+ for (Index2 = Index + 1; Index2 < BEVIndex; Index2++) {
+ if (0 == (NewBEVPtr[Index2] & 0xFF00)) {
+ Tmp = NewBEVPtr[Index];
+ NewBEVPtr[Index] = NewBEVPtr[Index2];
+ NewBEVPtr[Index2] = Tmp;
+ break;
+ }
+ }
+ }
+ }
+
+ FreePool (DevOrder);
+
+ Status = gRT->SetVariable (
+ VAR_LEGACY_DEV_ORDER,
+ &EfiLegacyDevOrderGuid,
+ VAR_FLAG,
+ TotalSize,
+ NewDevOrder
+ );
+ FreePool (NewDevOrder);
+
+ return Status;
+}
+
+/**
+ Set Boot Priority for specified device type.
+
+ @param DeviceType The device type.
+ @param LocalBbsTable The BBS table.
+ @param Priority The prority table.
+
+ @retval EFI_SUCCESS The function completes successfully.
+ @retval EFI_NOT_FOUND Failed to find device.
+
+**/
+EFI_STATUS
+BdsSetBootPriority4SameTypeDev (
+ IN UINT16 DeviceType,
+ IN OUT BBS_TABLE *LocalBbsTable,
+ IN OUT UINT16 *Priority
+ )
+{
+ UINT8 *DevOrder;
+
+ UINT8 *OrigBuffer;
+ UINT16 *DevIndex;
+ UINTN DevOrderSize;
+ UINTN DevCount;
+ UINTN Index;
+
+ DevOrder = BdsLibGetVariableAndSize (
+ VAR_LEGACY_DEV_ORDER,
+ &EfiLegacyDevOrderGuid,
+ &DevOrderSize
+ );
+ if (NULL == DevOrder) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ OrigBuffer = DevOrder;
+ while (DevOrder < OrigBuffer + DevOrderSize) {
+ if (DeviceType == * (BBS_TYPE *) DevOrder) {
+ break;
+ }
+
+ DevOrder += sizeof (BBS_TYPE);
+ DevOrder += *(UINT16 *) DevOrder;
+ }
+
+ if (DevOrder >= OrigBuffer + DevOrderSize) {
+ FreePool (OrigBuffer);
+ return EFI_NOT_FOUND;
+ }
+
+ DevOrder += sizeof (BBS_TYPE);
+ DevCount = (*((UINT16 *) DevOrder) - sizeof (UINT16)) / sizeof (UINT16);
+ DevIndex = (UINT16 *) (DevOrder + sizeof (UINT16));
+ //
+ // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
+ //
+ for (Index = 0; Index < DevCount; Index++) {
+ if ((DevIndex[Index] & 0xFF00) == 0xFF00) {
+ //
+ // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
+ //
+ } else {
+ LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = *Priority;
+ (*Priority)++;
+ }
+ }
+
+ FreePool (OrigBuffer);
+ return EFI_SUCCESS;
+}
+
+/**
+ Print the BBS Table.
+
+ @param LocalBbsTable The BBS table.
+
+**/
+VOID
+PrintBbsTable (
+ IN BBS_TABLE *LocalBbsTable
+ )
+{
+ UINT16 Idx;
+
+ DEBUG ((DEBUG_ERROR, "\n"));
+ DEBUG ((DEBUG_ERROR, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
+ DEBUG ((DEBUG_ERROR, "=============================================\n"));
+ for (Idx = 0; Idx < MAX_BBS_ENTRIES; Idx++) {
+ if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) ||
+ (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) ||
+ (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY)
+ ) {
+ continue;
+ }
+
+ DEBUG (
+ (DEBUG_ERROR,
+ " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",
+ (UINTN) Idx,
+ (UINTN) LocalBbsTable[Idx].BootPriority,
+ (UINTN) LocalBbsTable[Idx].Bus,
+ (UINTN) LocalBbsTable[Idx].Device,
+ (UINTN) LocalBbsTable[Idx].Function,
+ (UINTN) LocalBbsTable[Idx].Class,
+ (UINTN) LocalBbsTable[Idx].SubClass,
+ (UINTN) LocalBbsTable[Idx].DeviceType,
+ (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags,
+ (UINTN) LocalBbsTable[Idx].BootHandlerSegment,
+ (UINTN) LocalBbsTable[Idx].BootHandlerOffset,
+ (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset),
+ (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset))
+ );
+ }
+
+ DEBUG ((DEBUG_ERROR, "\n"));
+}
+
+/**
+
+ Set the boot priority for BBS entries based on boot option entry and boot order.
+
+ @param Entry The boot option is to be checked for refresh BBS table.
+
+ @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully.
+ @return status of BdsSetBootPriority4SameTypeDev()
+**/
+EFI_STATUS
+BdsRefreshBbsTableForBoot (
+ IN BDS_COMMON_OPTION *Entry
+ )
+{
+ EFI_STATUS Status;
+ UINT16 HddCount;
+ UINT16 BbsCount;
+ HDD_INFO *LocalHddInfo;
+ BBS_TABLE *LocalBbsTable;
+ UINT16 DevType;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINTN Index;
+ UINT16 Priority;
+ UINT16 *BootOrder;
+ UINTN BootOrderSize;
+ UINT8 *BootOptionVar;
+ UINTN BootOptionSize;
+ UINT16 BootOption[100];
+ UINT8 *Ptr;
+ UINT16 DevPathLen;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+
+ HddCount = 0;
+ BbsCount = 0;
+ LocalHddInfo = NULL;
+ LocalBbsTable = NULL;
+ DevType = BBS_UNKNOWN;
+
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ LegacyBios->GetBbsInfo (
+ LegacyBios,
+ &HddCount,
+ &LocalHddInfo,
+ &BbsCount,
+ &LocalBbsTable
+ );
+ //
+ // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
+ // We will set them according to the settings setup by user
+ //
+ for (Index = 0; Index < BbsCount; Index++) {
+ if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) ||
+ (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) ||
+ (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) {
+ LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
+ }
+ }
+ //
+ // boot priority always starts at 0
+ //
+ Priority = 0;
+ if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) {
+ //
+ // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
+ //
+ DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType;
+ Status = BdsSetBootPriority4SameTypeDev (
+ DevType,
+ LocalBbsTable,
+ &Priority
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ //
+ // we have to set the boot priority for other BBS entries with different device types
+ //
+ BootOrder = (UINT16 *) BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderSize
+ );
+ for (Index = 0; ((BootOrder != NULL) && (Index < BootOrderSize / sizeof (UINT16))); Index++) {
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
+ BootOptionVar = BdsLibGetVariableAndSize (
+ BootOption,
+ &gEfiGlobalVariableGuid,
+ &BootOptionSize
+ );
+ if (NULL == BootOptionVar) {
+ continue;
+ }
+
+ Ptr = BootOptionVar;
+
+ Ptr += sizeof (UINT32);
+ DevPathLen = *(UINT16 *) Ptr;
+ Ptr += sizeof (UINT16);
+ Ptr += StrSize ((UINT16 *) Ptr);
+ DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
+ if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) {
+ FreePool (BootOptionVar);
+ continue;
+ }
+
+ Ptr += DevPathLen;
+ if (DevType == ((BBS_TABLE *) Ptr)->DeviceType) {
+ //
+ // We don't want to process twice for a device type
+ //
+ FreePool (BootOptionVar);
+ continue;
+ }
+
+ Status = BdsSetBootPriority4SameTypeDev (
+ ((BBS_TABLE *) Ptr)->DeviceType,
+ LocalBbsTable,
+ &Priority
+ );
+ FreePool (BootOptionVar);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ if (BootOrder != NULL) {
+ FreePool (BootOrder);
+ }
+
+ DEBUG_CODE_BEGIN();
+ PrintBbsTable (LocalBbsTable);
+ DEBUG_CODE_END();
+
+ return Status;
+}
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h
new file mode 100644
index 0000000000..fee8bdbac5
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h
@@ -0,0 +1,94 @@
+/** @file
+ declares interface functions
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 _EFI_BDS_BBS_SUPPORT_H_
+#define _EFI_BDS_BBS_SUPPORT_H_
+
+#include "BootMaint.h"
+
+#define MAX_BBS_ENTRIES 0x100
+
+/**
+ Build Legacy Device Name String according.
+
+ @param CurBBSEntry BBS Table.
+ @param Index Index.
+ @param BufSize The buffer size.
+ @param BootString The output string.
+
+ @return VOID No output.
+
+**/
+VOID
+BdsBuildLegacyDevNameString (
+ IN BBS_TABLE *CurBBSEntry,
+ IN UINTN Index,
+ IN UINTN BufSize,
+ OUT CHAR16 *BootString
+ );
+
+/**
+ Delete all the invalid legacy boot options.
+
+
+
+ @retval EFI_SUCCESS All invalide legacy boot options are deleted.
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
+ @retval EFI_NOT_FOUND Fail to retrive variable of boot order.
+**/
+EFI_STATUS
+BdsDeleteAllInvalidLegacyBootOptions (
+ VOID
+ );
+
+/**
+
+ Add the legacy boot options from BBS table if they do not exist.
+
+ @retval EFI_SUCCESS The boot options are added successfully or they are already in boot options.
+ @retval others An error occurred when creating legacy boot options.
+
+**/
+EFI_STATUS
+BdsAddNonExistingLegacyBootOptions (
+ VOID
+ );
+
+/**
+
+ Add the legacy boot devices from BBS table into
+ the legacy device boot order.
+
+ @retval EFI_SUCCESS The boot devices are added successfully.
+
+**/
+EFI_STATUS
+BdsUpdateLegacyDevOrder (
+ VOID
+ );
+
+/**
+ Set the boot priority for BBS entries based on boot option entry and boot order.
+
+ @param Entry The boot option is to be checked for refresh BBS table.
+
+ @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully.
+ @return status of BdsSetBootPriority4SameTypeDev()
+**/
+EFI_STATUS
+BdsRefreshBbsTableForBoot (
+ IN BDS_COMMON_OPTION *Entry
+ );
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr
new file mode 100644
index 0000000000..4f38a34bba
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr
@@ -0,0 +1,383 @@
+///** @file
+//
+// Boot Maintenance Utility Formset
+//
+// Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+// All rights reserved. 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"
+
+#define LABEL_END 0xffff
+
+formset
+ guid = BOOT_MAINT_FORMSET_GUID,
+ title = STRING_TOKEN(STR_FORM_MAIN_TITLE),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ class = 0,
+ subclass = 0,
+
+ 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);
+
+ text
+ help = STRING_TOKEN(STR_BOOT_FROM_FILE_HELP),
+ text = STRING_TOKEN(STR_BOOT_FROM_FILE),
+ text = STRING_TOKEN(STR_NULL_STRING),
+ 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);
+
+ goto FORM_MAIN_ID,
+ prompt = STRING_TOKEN(STR_RESET),
+ help = STRING_TOKEN(STR_RESET),
+ flags = INTERACTIVE,
+ key = FORM_RESET;
+
+ 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_ADD_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_NEXT_BOOT_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_NEXT_BOOT_HELP),
+ flags = INTERACTIVE,
+ key = FORM_BOOT_CHG_ID;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+ //
+ // We will add "Select Legacy Boot Floppy Drive" and "Select Legacy Boot Hard Drive"
+ // here dynamically
+ //
+ label FORM_BOOT_LEGACY_DEVICE_ID;
+ label LABEL_END;
+
+ 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_TITLE);
+
+ label FORM_BOOT_ADD_ID;
+ label LABEL_END;
+ 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_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_DRV_ADD_FILE_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_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_FILE_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE);
+
+ label FORM_DRV_ADD_FILE_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;
+
+ form formid = FORM_SET_FD_ORDER_ID,
+ title = STRING_TOKEN(STR_FORM_SET_FD_ORDER_TITLE);
+
+ label FORM_SET_FD_ORDER_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_SET_HD_ORDER_ID,
+ title = STRING_TOKEN(STR_FORM_SET_HD_ORDER_TITLE);
+
+ label FORM_SET_HD_ORDER_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_SET_CD_ORDER_ID,
+ title = STRING_TOKEN(STR_FORM_SET_CD_ORDER_TITLE);
+
+ label FORM_SET_CD_ORDER_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_SET_NET_ORDER_ID,
+ title = STRING_TOKEN(STR_FORM_SET_NET_ORDER_TITLE);
+
+ label FORM_SET_NET_ORDER_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_SET_BEV_ORDER_ID,
+ title = STRING_TOKEN(STR_FORM_SET_BEV_ORDER_TITLE);
+
+ label FORM_SET_BEV_ORDER_ID;
+ label LABEL_END;
+ endform;
+
+endformset;
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c
new file mode 100644
index 0000000000..aaa64c9458
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c
@@ -0,0 +1,494 @@
+/** @file
+ Utility routines used by boot maintenance modules.
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "BootMaint.h"
+
+/**
+
+ Find the first instance of this Protocol
+ in the system and return it's interface.
+
+
+ @param ProtocolGuid Provides the protocol to search for
+ @param Interface On return, a pointer to the first interface
+ that matches ProtocolGuid
+
+ @retval EFI_SUCCESS A protocol instance matching ProtocolGuid was found
+ @retval EFI_NOT_FOUND No protocol instances were found that match ProtocolGuid
+
+**/
+EFI_STATUS
+EfiLibLocateProtocol (
+ IN EFI_GUID *ProtocolGuid,
+ OUT VOID **Interface
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (
+ ProtocolGuid,
+ NULL,
+ (VOID **) Interface
+ );
+ return Status;
+}
+
+/**
+
+ Function opens and returns a file handle to the root directory of a volume.
+
+ @param DeviceHandle A handle for a device
+
+ @return A valid file handle or NULL is returned
+
+**/
+EFI_FILE_HANDLE
+EfiLibOpenRoot (
+ IN EFI_HANDLE DeviceHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
+ EFI_FILE_HANDLE File;
+
+ File = NULL;
+
+ //
+ // File the file system interface to the device
+ //
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID *) &Volume
+ );
+
+ //
+ // Open the root directory of the volume
+ //
+ if (!EFI_ERROR (Status)) {
+ Status = Volume->OpenVolume (
+ Volume,
+ &File
+ );
+ }
+ //
+ // Done
+ //
+ return EFI_ERROR (Status) ? NULL : File;
+}
+
+/**
+
+ Helper function called as part of the code needed
+ to allocate the proper sized buffer for various
+ EFI interfaces.
+
+
+ @param Status Current status
+ @param Buffer Current allocated buffer, or NULL
+ @param BufferSize Current buffer size needed
+
+ @retval TRUE if the buffer was reallocated and the caller
+ should try the API again.
+ @retval FALSE The caller should not call this function again.
+
+**/
+BOOLEAN
+EfiGrowBuffer (
+ IN OUT EFI_STATUS *Status,
+ IN OUT VOID **Buffer,
+ IN UINTN BufferSize
+ )
+{
+ BOOLEAN TryAgain;
+
+ //
+ // If this is an initial request, buffer will be null with a new buffer size
+ //
+ if ((*Buffer == NULL) && (BufferSize != 0)) {
+ *Status = EFI_BUFFER_TOO_SMALL;
+ }
+ //
+ // If the status code is "buffer too small", resize the buffer
+ //
+ TryAgain = FALSE;
+ if (*Status == EFI_BUFFER_TOO_SMALL) {
+
+ if (*Buffer != NULL) {
+ FreePool (*Buffer);
+ }
+
+ *Buffer = AllocateZeroPool (BufferSize);
+
+ if (*Buffer != NULL) {
+ TryAgain = TRUE;
+ } else {
+ *Status = EFI_OUT_OF_RESOURCES;
+ }
+ }
+ //
+ // If there's an error, free the buffer
+ //
+ if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) {
+ FreePool (*Buffer);
+ *Buffer = NULL;
+ }
+
+ return TryAgain;
+}
+
+/**
+ Function returns the value of the specified variable.
+
+
+ @param Name A Null-terminated Unicode string that is
+ the name of the vendor's variable.
+ @param VendorGuid A unique identifier for the vendor.
+
+ @return The payload of the variable.
+ @retval NULL If the variable can't be read.
+
+**/
+VOID *
+EfiLibGetVariable (
+ IN CHAR16 *Name,
+ IN EFI_GUID *VendorGuid
+ )
+{
+ UINTN VarSize;
+
+ return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize);
+}
+
+/**
+ 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
+ )
+{
+ VOID *VarBuf;
+ EFI_STATUS Status;
+
+ VarBuf = EfiLibGetVariable (VarName, VarGuid);
+ Status = EFI_NOT_FOUND;
+
+ if (VarBuf != NULL) {
+ //
+ // Delete variable from Storage
+ //
+ Status = gRT->SetVariable (VarName, VarGuid, VAR_FLAG, 0, NULL);
+ ASSERT (!EFI_ERROR (Status));
+ FreePool (VarBuf);
+ }
+
+ return Status;
+}
+
+/**
+
+ Function gets the file system information from an open file descriptor,
+ and stores it in a buffer allocated from pool.
+
+
+ @param FHand The file handle.
+
+ @return A pointer to a buffer with file information.
+ @retval NULL is returned if failed to get Vaolume Label Info.
+
+**/
+EFI_FILE_SYSTEM_VOLUME_LABEL *
+EfiLibFileSystemVolumeLabelInfo (
+ IN EFI_FILE_HANDLE FHand
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_SYSTEM_VOLUME_LABEL *Buffer;
+ UINTN BufferSize;
+ //
+ // Initialize for GrowBuffer loop
+ //
+ Buffer = NULL;
+ BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 200;
+
+ //
+ // Call the real function
+ //
+ while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
+ Status = FHand->GetInfo (
+ FHand,
+ &gEfiFileSystemVolumeLabelInfoIdGuid,
+ &BufferSize,
+ Buffer
+ );
+ }
+
+ return Buffer;
+}
+
+/**
+ Duplicate a string.
+
+ @param Src The source.
+
+ @return A new string which is duplicated copy of the source.
+ @retval NULL If there is not enough memory.
+
+**/
+CHAR16 *
+EfiStrDuplicate (
+ IN CHAR16 *Src
+ )
+{
+ CHAR16 *Dest;
+ UINTN Size;
+
+ Size = StrSize (Src);
+ Dest = AllocateZeroPool (Size);
+ ASSERT (Dest != NULL);
+ if (Dest != NULL) {
+ CopyMem (Dest, Src, Size);
+ }
+
+ return Dest;
+}
+
+/**
+
+ Function gets the file information from an open file descriptor, and stores it
+ in a buffer allocated from pool.
+
+ @param FHand File Handle.
+
+ @return A pointer to a buffer with file information or NULL is returned
+
+**/
+EFI_FILE_INFO *
+EfiLibFileInfo (
+ IN EFI_FILE_HANDLE FHand
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_INFO *Buffer;
+ UINTN BufferSize;
+
+ //
+ // Initialize for GrowBuffer loop
+ //
+ Buffer = NULL;
+ BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
+
+ //
+ // Call the real function
+ //
+ while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
+ Status = FHand->GetInfo (
+ FHand,
+ &gEfiFileInfoGuid,
+ &BufferSize,
+ Buffer
+ );
+ }
+
+ return Buffer;
+}
+
+/**
+ 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)) {
+ Count += 1;
+ }
+
+ return Count;
+}
+
+/**
+ Adjusts the size of a previously allocated buffer.
+
+
+ @param OldPool - A pointer to the buffer whose size is being adjusted.
+ @param OldSize - The size of the current buffer.
+ @param NewSize - The size of the new buffer.
+
+ @return The newly allocated buffer.
+ @retval NULL Allocation failed.
+
+**/
+VOID *
+EfiReallocatePool (
+ IN VOID *OldPool,
+ IN UINTN OldSize,
+ IN UINTN NewSize
+ )
+{
+ VOID *NewPool;
+
+ NewPool = NULL;
+ if (NewSize != 0) {
+ NewPool = AllocateZeroPool (NewSize);
+ }
+
+ if (OldPool != NULL) {
+ if (NewPool != NULL) {
+ CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);
+ }
+
+ FreePool (OldPool);
+ }
+
+ return NewPool;
+}
+
+/**
+ Compare two EFI_TIME data.
+
+
+ @param FirstTime - A pointer to the first EFI_TIME data.
+ @param SecondTime - A pointer to the second EFI_TIME data.
+
+ @retval TRUE The FirstTime is not later than the SecondTime.
+ @retval FALSE The FirstTime is later than the SecondTime.
+
+**/
+BOOLEAN
+TimeCompare (
+ IN EFI_TIME *FirstTime,
+ IN EFI_TIME *SecondTime
+ )
+{
+ if (FirstTime->Year != SecondTime->Year) {
+ return (BOOLEAN) (FirstTime->Year < SecondTime->Year);
+ } else if (FirstTime->Month != SecondTime->Month) {
+ return (BOOLEAN) (FirstTime->Month < SecondTime->Month);
+ } else if (FirstTime->Day != SecondTime->Day) {
+ return (BOOLEAN) (FirstTime->Day < SecondTime->Day);
+ } else if (FirstTime->Hour != SecondTime->Hour) {
+ return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);
+ } else if (FirstTime->Minute != SecondTime->Minute) {
+ return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute);
+ } else if (FirstTime->Second != SecondTime->Second) {
+ return (BOOLEAN) (FirstTime->Second < SecondTime->Second);
+ }
+
+ return (BOOLEAN) (FirstTime->Nanosecond <= SecondTime->Nanosecond);
+}
+
+/**
+ 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
+ )
+{
+ EFI_STATUS Status;
+ UINT16 *Desc;
+ EFI_DATA_HUB_PROTOCOL *Datahub;
+ UINT64 Count;
+ EFI_DATA_RECORD_HEADER *Record;
+ EFI_SUBCLASS_TYPE1_HEADER *DataHdr;
+ EFI_GUID MiscGuid;
+ EFI_MISC_ONBOARD_DEVICE_DATA *Ob;
+ EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *Port;
+ EFI_TIME CurTime;
+
+ CopyGuid (&MiscGuid, &gEfiMiscSubClassGuid);
+
+ Status = gBS->LocateProtocol (
+ &gEfiDataHubProtocolGuid,
+ NULL,
+ (VOID **) &Datahub
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Status = gRT->GetTime (&CurTime, NULL);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Count = 0;
+ do {
+ Status = Datahub->GetNextRecord (Datahub, &Count, NULL, &Record);
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA && CompareGuid (&Record->DataRecordGuid, &MiscGuid)) {
+ //
+ // This record is what we need
+ //
+ DataHdr = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);
+ if (EFI_MISC_ONBOARD_DEVICE_RECORD_NUMBER == DataHdr->RecordType) {
+ Ob = (EFI_MISC_ONBOARD_DEVICE_DATA *) (DataHdr + 1);
+ if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Ob->OnBoardDevicePath, DevPath)) {
+ GetProducerString (&Record->ProducerName, Ob->OnBoardDeviceDescription, &Desc);
+ return Desc;
+ }
+ }
+
+ if (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER == DataHdr->RecordType) {
+ Port = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) (DataHdr + 1);
+ if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Port->PortPath, DevPath)) {
+ GetProducerString (&Record->ProducerName, Port->PortExternalConnectorDesignator, &Desc);
+ return Desc;
+ }
+ }
+ }
+
+ } while (TimeCompare (&Record->LogTime, &CurTime) && Count != 0);
+
+ return NULL;
+}
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni
new file mode 100644
index 0000000000..bd94803045
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni
Binary files differ
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c
new file mode 100644
index 0000000000..4598d3d186
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c
@@ -0,0 +1,1376 @@
+/** @file
+ The functions for Boot Maintainence Main menu.
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "BootMaint.h"
+#include "FormGuid.h"
+#include "Bds.h"
+#include "FrontPage.h"
+
+EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = {
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+};
+
+
+EFI_GUID EfiLegacyDevOrderGuid = EFI_LEGACY_DEV_ORDER_VARIABLE_GUID;
+EFI_GUID mBootMaintGuid = BOOT_MAINT_FORMSET_GUID;
+EFI_GUID mFileExplorerGuid = FILE_EXPLORE_FORMSET_GUID;
+
+CHAR16 mBootMaintStorageName[] = L"BmData";
+CHAR16 mFileExplorerStorageName[] = L"FeData";
+
+/**
+ 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
+ );
+
+/**
+ Create string tokens for a menu from its help strings and display strings
+
+ @param CallbackData The BMM context data.
+ @param HiiHandle Hii Handle of the package to be updated.
+ @param MenuOption The Menu whose string tokens need to be created
+
+ @retval EFI_SUCCESS String tokens created successfully
+ @retval others contain some errors
+**/
+EFI_STATUS
+CreateMenuStringToken (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN BM_MENU_OPTION *MenuOption
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINTN Index;
+
+ for (Index = 0; Index < MenuOption->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);
+
+ HiiLibNewString (
+ HiiHandle,
+ &NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->DisplayString
+ );
+
+ if (NULL == NewMenuEntry->HelpString) {
+ NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;
+ } else {
+ HiiLibNewString (
+ HiiHandle,
+ &NewMenuEntry->HelpStringToken,
+ NewMenuEntry->HelpString
+ );
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ 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;
+
+ if (Request == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = BMM_CALLBACK_DATA_FROM_THIS (This);
+
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ BufferSize = sizeof (BMM_FAKE_NV_DATA);
+ Status = gHiiConfigRouting->BlockToConfig (
+ gHiiConfigRouting,
+ Request,
+ (UINT8 *) &Private->BmmFakeNvData,
+ BufferSize,
+ Results,
+ Progress
+ );
+ return Status;
+}
+
+/**
+ 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;
+ EFI_STATUS Status;
+ UINTN OldValue;
+ UINTN NewValue;
+ UINTN Number;
+ UINTN Pos;
+ UINTN Bit;
+ UINT16 NewValuePos;
+ UINT16 Index2;
+ UINT16 Index;
+ UINT8 *OldLegacyDev;
+ UINT8 *NewLegacyDev;
+ UINT8 *DisMap;
+ EFI_FORM_ID FormId;
+ UINTN BufferSize;
+
+ if ((Value == NULL) || (ActionRequest == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldValue = 0;
+ NewValue = 0;
+ Number = 0;
+ OldLegacyDev = NULL;
+ NewLegacyDev = NULL;
+ NewValuePos = 0;
+ DisMap = NULL;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+
+ Private = BMM_CALLBACK_DATA_FROM_THIS (This);
+ UpdatePageId (Private, QuestionId);
+
+ //
+ // Retrive uncommitted data from Form Browser
+ //
+ CurrentFakeNVMap = &Private->BmmFakeNvData;
+ BufferSize = sizeof (BMM_FAKE_NV_DATA);
+ Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) CurrentFakeNVMap);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // need to be subtituded.
+ //
+ // Update Select FD/HD/CD/NET/BEV Order Form
+ //
+ if (FORM_SET_FD_ORDER_ID == Private->BmmPreviousPageId ||
+ FORM_SET_HD_ORDER_ID == Private->BmmPreviousPageId ||
+ FORM_SET_CD_ORDER_ID == Private->BmmPreviousPageId ||
+ FORM_SET_NET_ORDER_ID == Private->BmmPreviousPageId ||
+ FORM_SET_BEV_ORDER_ID == Private->BmmPreviousPageId ||
+ ((FORM_BOOT_SETUP_ID == Private->BmmPreviousPageId) &&
+ (QuestionId >= LEGACY_FD_QUESTION_ID) &&
+ (QuestionId < (LEGACY_BEV_QUESTION_ID + 100)) )
+ ) {
+
+ DisMap = Private->BmmOldFakeNVData.DisableMap;
+
+ FormId = Private->BmmPreviousPageId;
+ if (FormId == FORM_BOOT_SETUP_ID) {
+ FormId = Private->BmmCurrentPageId;
+ }
+
+ switch (FormId) {
+ case FORM_SET_FD_ORDER_ID:
+ Number = (UINT16) LegacyFDMenu.MenuNumber;
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyFD;
+ NewLegacyDev = CurrentFakeNVMap->LegacyFD;
+ break;
+
+ case FORM_SET_HD_ORDER_ID:
+ Number = (UINT16) LegacyHDMenu.MenuNumber;
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyHD;
+ NewLegacyDev = CurrentFakeNVMap->LegacyHD;
+ break;
+
+ case FORM_SET_CD_ORDER_ID:
+ Number = (UINT16) LegacyCDMenu.MenuNumber;
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyCD;
+ NewLegacyDev = CurrentFakeNVMap->LegacyCD;
+ break;
+
+ case FORM_SET_NET_ORDER_ID:
+ Number = (UINT16) LegacyNETMenu.MenuNumber;
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyNET;
+ NewLegacyDev = CurrentFakeNVMap->LegacyNET;
+ break;
+
+ case FORM_SET_BEV_ORDER_ID:
+ Number = (UINT16) LegacyBEVMenu.MenuNumber;
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyBEV;
+ NewLegacyDev = CurrentFakeNVMap->LegacyBEV;
+ break;
+
+ default:
+ break;
+ }
+ //
+ // First, find the different position
+ // if there is change, it should be only one
+ //
+ for (Index = 0; Index < Number; Index++) {
+ if (OldLegacyDev[Index] != NewLegacyDev[Index]) {
+ OldValue = OldLegacyDev[Index];
+ NewValue = NewLegacyDev[Index];
+ break;
+ }
+ }
+
+ if (Index != Number) {
+ //
+ // there is change, now process
+ //
+ if (0xFF == NewValue) {
+ //
+ // This item will be disable
+ // Just move the items behind this forward to overlap it
+ //
+ Pos = OldValue / 8;
+ Bit = 7 - (OldValue % 8);
+ DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
+ for (Index2 = Index; Index2 < Number - 1; Index2++) {
+ NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1];
+ }
+
+ NewLegacyDev[Index2] = 0xFF;
+ } else {
+ for (Index2 = 0; Index2 < Number; Index2++) {
+ if (Index2 == Index) {
+ continue;
+ }
+
+ if (OldLegacyDev[Index2] == NewValue) {
+ //
+ // If NewValue is in OldLegacyDev array
+ // remember its old position
+ //
+ NewValuePos = Index2;
+ break;
+ }
+ }
+
+ if (Index2 != Number) {
+ //
+ // We will change current item to an existing item
+ // (It's hard to describe here, please read code, it's like a cycle-moving)
+ //
+ for (Index2 = NewValuePos; Index2 != Index;) {
+ if (NewValuePos < Index) {
+ NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1];
+ Index2++;
+ } else {
+ NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1];
+ Index2--;
+ }
+ }
+ } else {
+ //
+ // If NewValue is not in OldlegacyDev array, we are changing to a disabled item
+ // so we should modify DisMap to reflect the change
+ //
+ Pos = NewValue / 8;
+ Bit = 7 - (NewValue % 8);
+ DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit)));
+ if (0xFF != OldValue) {
+ //
+ // Because NewValue is a item that was disabled before
+ // so after changing the OldValue should be disabled
+ // actually we are doing a swap of enable-disable states of two items
+ //
+ Pos = OldValue / 8;
+ Bit = 7 - (OldValue % 8);
+ DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
+ }
+ }
+ }
+ //
+ // To prevent DISABLE appears in the middle of the list
+ // we should perform a re-ordering
+ //
+ Index = 0;
+ while (Index < Number) {
+ if (0xFF != NewLegacyDev[Index]) {
+ Index++;
+ continue;
+ }
+
+ Index2 = Index;
+ Index2++;
+ while (Index2 < Number) {
+ if (0xFF != NewLegacyDev[Index2]) {
+ break;
+ }
+
+ Index2++;
+ }
+
+ if (Index2 < Number) {
+ NewLegacyDev[Index] = NewLegacyDev[Index2];
+ NewLegacyDev[Index2] = 0xFF;
+ }
+
+ Index++;
+ }
+
+ CopyMem (
+ OldLegacyDev,
+ NewLegacyDev,
+ Number
+ );
+ }
+ }
+
+ if (QuestionId < FILE_OPTION_OFFSET) {
+ if (QuestionId < CONFIG_OPTION_OFFSET) {
+ switch (QuestionId) {
+ case KEY_VALUE_BOOT_FROM_FILE:
+ Private->FeCurrentState = BOOT_FROM_FILE_STATE;
+
+ //
+ // Exit Bmm main formset to send File Explorer formset.
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ break;
+
+ case FORM_BOOT_ADD_ID:
+ Private->FeCurrentState = ADD_BOOT_OPTION_STATE;
+
+ //
+ // Exit Bmm main formset to send File Explorer formset.
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ break;
+
+ case FORM_DRV_ADD_FILE_ID:
+ Private->FeCurrentState = ADD_DRIVER_OPTION_STATE;
+
+ //
+ // Exit Bmm main formset to send File Explorer formset.
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ 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_RESET:
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+ return EFI_UNSUPPORTED;
+
+ 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;
+
+ case FORM_SET_FD_ORDER_ID:
+ case FORM_SET_HD_ORDER_ID:
+ case FORM_SET_CD_ORDER_ID:
+ case FORM_SET_NET_ORDER_ID:
+ case FORM_SET_BEV_ORDER_ID:
+ CleanUpPage (QuestionId, Private);
+ UpdateSetLegacyDeviceOrderPage (QuestionId, Private);
+ break;
+
+ case KEY_VALUE_SAVE_AND_EXIT:
+ case KEY_VALUE_NO_SAVE_AND_EXIT:
+
+ if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) {
+ Status = ApplyChangeHandler (Private, CurrentFakeNVMap, Private->BmmPreviousPageId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) {
+ DiscardChangeHandler (Private, CurrentFakeNVMap);
+ }
+
+ //
+ // Tell browser not to ask for confirmation of changes,
+ // since we have already applied or discarded.
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
+ break;
+
+ default:
+ break;
+ }
+ } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) {
+ Index2 = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET);
+ Private->CurrentTerminal = Index2;
+
+ CleanUpPage (FORM_CON_COM_SETUP_ID, Private);
+ UpdateTerminalPage (Private);
+
+ } else if (QuestionId >= HANDLE_OPTION_OFFSET) {
+ Index2 = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET);
+
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index2);
+ 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);
+ }
+ }
+
+ //
+ // Pass changed uncommitted data back to Form Browser
+ //
+ BufferSize = sizeof (BMM_FAKE_NV_DATA);
+ Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) CurrentFakeNVMap, NULL);
+
+ return Status;
+}
+
+/**
+ Function handling request to apply changes for BMM pages.
+
+ @param Private Pointer to callback data buffer.
+ @param CurrentFakeNVMap Pointer to buffer holding data of various values used by BMM
+ @param FormId ID of the form which has sent the request to apply change.
+
+ @retval EFI_SUCCESS Change successfully applied.
+ @retval Other Error occurs while trying to apply changes.
+
+**/
+EFI_STATUS
+ApplyChangeHandler (
+ IN BMM_CALLBACK_DATA *Private,
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap,
+ IN EFI_FORM_ID FormId
+ )
+{
+ BM_CONSOLE_CONTEXT *NewConsoleContext;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ BM_MENU_ENTRY *NewMenuEntry;
+ EFI_STATUS Status;
+ UINT16 Index;
+
+ Status = EFI_SUCCESS;
+
+ switch (FormId) {
+ case FORM_SET_FD_ORDER_ID:
+ case FORM_SET_HD_ORDER_ID:
+ case FORM_SET_CD_ORDER_ID:
+ case FORM_SET_NET_ORDER_ID:
+ case FORM_SET_BEV_ORDER_ID:
+ Var_UpdateBBSOption (Private);
+ break;
+
+ case FORM_BOOT_DEL_ID:
+ ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (UINT8)));
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->Deleted = CurrentFakeNVMap->BootOptionDel[Index];
+ }
+
+ Var_DelBootOption ();
+ break;
+
+ case FORM_DRV_DEL_ID:
+ ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (UINT8)));
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->Deleted = CurrentFakeNVMap->DriverOptionDel[Index];
+ }
+
+ Var_DelDriverOption ();
+ break;
+
+ case FORM_BOOT_CHG_ID:
+ Status = Var_UpdateBootOrder (Private);
+ break;
+
+ case FORM_DRV_CHG_ID:
+ Status = Var_UpdateDriverOrder (Private);
+ break;
+
+ case FORM_TIME_OUT_ID:
+ Status = gRT->SetVariable (
+ L"Timeout",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ sizeof (UINT16),
+ &(CurrentFakeNVMap->BootTimeOut)
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ Private->BmmOldFakeNVData.BootTimeOut = CurrentFakeNVMap->BootTimeOut;
+ break;
+
+ case FORM_BOOT_NEXT_ID:
+ Status = Var_UpdateBootNext (Private);
+ break;
+
+ case FORM_CON_MODE_ID:
+ Status = Var_UpdateConMode (Private);
+ break;
+
+ case FORM_CON_COM_SETUP_ID:
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Private->CurrentTerminal);
+
+ ASSERT (NewMenuEntry != NULL);
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+
+ NewTerminalContext->BaudRateIndex = CurrentFakeNVMap->COMBaudRate;
+ ASSERT (CurrentFakeNVMap->COMBaudRate < (sizeof (BaudRateList) / sizeof (BaudRateList[0])));
+ NewTerminalContext->BaudRate = BaudRateList[CurrentFakeNVMap->COMBaudRate].Value;
+ NewTerminalContext->DataBitsIndex = CurrentFakeNVMap->COMDataRate;
+ ASSERT (CurrentFakeNVMap->COMDataRate < (sizeof (DataBitsList) / sizeof (DataBitsList[0])));
+ NewTerminalContext->DataBits = (UINT8) DataBitsList[CurrentFakeNVMap->COMDataRate].Value;
+ NewTerminalContext->StopBitsIndex = CurrentFakeNVMap->COMStopBits;
+ ASSERT (CurrentFakeNVMap->COMStopBits < (sizeof (StopBitsList) / sizeof (StopBitsList[0])));
+ NewTerminalContext->StopBits = (UINT8) StopBitsList[CurrentFakeNVMap->COMStopBits].Value;
+ NewTerminalContext->ParityIndex = CurrentFakeNVMap->COMParity;
+ ASSERT (CurrentFakeNVMap->COMParity < (sizeof (ParityList) / sizeof (ParityList[0])));
+ NewTerminalContext->Parity = (UINT8) ParityList[CurrentFakeNVMap->COMParity].Value;
+ NewTerminalContext->TerminalType = CurrentFakeNVMap->COMTerminalType;
+
+ ChangeTerminalDevicePath (
+ NewTerminalContext->DevicePath,
+ FALSE
+ );
+
+ Var_UpdateConsoleInpOption ();
+ Var_UpdateConsoleOutOption ();
+ Var_UpdateErrorOutOption ();
+ break;
+
+ case FORM_CON_IN_ID:
+ ASSERT ((ConsoleInpMenu.MenuNumber + TerminalMenu.MenuNumber) <= (sizeof (CurrentFakeNVMap->ConsoleCheck) / sizeof (UINT8)));
+ for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];
+ }
+
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ NewTerminalContext->IsConIn = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleInpMenu.MenuNumber];
+ }
+
+ Var_UpdateConsoleInpOption ();
+ break;
+
+ case FORM_CON_OUT_ID:
+ ASSERT ((ConsoleOutMenu.MenuNumber + TerminalMenu.MenuNumber) <= (sizeof (CurrentFakeNVMap->ConsoleCheck) / sizeof (UINT8)));
+ for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];
+ }
+
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ NewTerminalContext->IsConOut = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleOutMenu.MenuNumber];
+ }
+
+ Var_UpdateConsoleOutOption ();
+ break;
+
+ case FORM_CON_ERR_ID:
+ ASSERT ((ConsoleErrMenu.MenuNumber + TerminalMenu.MenuNumber) <= (sizeof (CurrentFakeNVMap->ConsoleCheck) / sizeof (UINT8)));
+ for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];
+ }
+
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ NewTerminalContext->IsStdErr = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleErrMenu.MenuNumber];
+ }
+
+ Var_UpdateErrorOutOption ();
+ break;
+
+ case FORM_DRV_ADD_HANDLE_DESC_ID:
+ Status = Var_UpdateDriverOption (
+ Private,
+ Private->BmmHiiHandle,
+ CurrentFakeNVMap->DriverAddHandleDesc,
+ CurrentFakeNVMap->DriverAddHandleOptionalData,
+ CurrentFakeNVMap->DriverAddForceReconnect
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ BOpt_GetDriverOptions (Private);
+ CreateMenuStringToken (Private, Private->BmmHiiHandle, &DriverOptionMenu);
+ break;
+
+ default:
+ break;
+ }
+
+Error:
+ return Status;
+}
+
+/**
+ 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:
+ case FORM_DRV_CHG_ID:
+ CopyMem (CurrentFakeNVMap->OptionOrder, Private->BmmOldFakeNVData.OptionOrder, 100);
+ 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] = 0x00;
+ }
+ 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] = 0x00;
+ }
+ 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;
+ }
+}
+
+/**
+ Initialize the Boot Maintenance Utitliy.
+
+
+ @retval EFI_SUCCESS utility ended successfully
+ @retval others contain some errors
+
+**/
+EFI_STATUS
+InitializeBM (
+ VOID
+ )
+{
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+ BMM_CALLBACK_DATA *BmmCallbackInfo;
+ EFI_STATUS Status;
+ UINT8 *Ptr;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Create CallbackData structures for Driver Callback
+ //
+ BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA));
+ if (BmmCallbackInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // 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));
+ if (Ptr == NULL) {
+ FreePool (BmmCallbackInfo);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Initialize Bmm callback data.
+ //
+ BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;
+ Ptr += sizeof (BM_LOAD_CONTEXT);
+
+ BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;
+ Ptr += sizeof (BM_FILE_CONTEXT);
+
+ BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;
+ Ptr += sizeof (BM_HANDLE_CONTEXT);
+
+ BmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr;
+
+ BmmCallbackInfo->Signature = BMM_CALLBACK_DATA_SIGNATURE;
+ BmmCallbackInfo->BmmConfigAccess.ExtractConfig = BootMaintExtractConfig;
+ BmmCallbackInfo->BmmConfigAccess.RouteConfig = FakeRouteConfig;
+ BmmCallbackInfo->BmmConfigAccess.Callback = BootMaintCallback;
+ BmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID;
+ BmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID;
+ BmmCallbackInfo->FeConfigAccess.ExtractConfig = FakeExtractConfig;
+ BmmCallbackInfo->FeConfigAccess.RouteConfig = FakeRouteConfig;
+ BmmCallbackInfo->FeConfigAccess.Callback = FileExplorerCallback;
+ BmmCallbackInfo->FeCurrentState = INACTIVE_STATE;
+ BmmCallbackInfo->FeDisplayContext = UNKNOWN_CONTEXT;
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&BmmCallbackInfo->BmmDriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install Config Access protocol to driver handle
+ //
+ Status = gBS->InstallProtocolInterface (
+ &BmmCallbackInfo->BmmDriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &BmmCallbackInfo->BmmConfigAccess
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&BmmCallbackInfo->FeDriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install Config Access protocol to driver handle
+ //
+ Status = gBS->InstallProtocolInterface (
+ &BmmCallbackInfo->FeDriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &BmmCallbackInfo->FeConfigAccess
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Post our Boot Maint VFR binnary to the HII database.
+ //
+ PackageList = HiiLibPreparePackageList (2, &mBootMaintGuid, BmBin, BdsDxeStrings);
+ ASSERT (PackageList != NULL);
+
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ BmmCallbackInfo->BmmDriverHandle,
+ &BmmCallbackInfo->BmmHiiHandle
+ );
+ FreePool (PackageList);
+
+ //
+ // Post our File Explorer VFR binary to the HII database.
+ //
+ PackageList = HiiLibPreparePackageList (2, &mFileExplorerGuid, FEBin, BdsDxeStrings);
+ ASSERT (PackageList != NULL);
+
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ BmmCallbackInfo->FeDriverHandle,
+ &BmmCallbackInfo->FeHiiHandle
+ );
+ FreePool (PackageList);
+
+ //
+ // Allocate space for creation of Buffer
+ //
+ gUpdateData.BufferSize = UPDATE_DATA_SIZE;
+ gUpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);
+ if (gUpdateData.Data == NULL) {
+ FreePool (BmmCallbackInfo->LoadContext);
+ FreePool (BmmCallbackInfo);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ InitializeStringDepository ();
+
+ InitAllMenu (BmmCallbackInfo);
+
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu);
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu);
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu);
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu);
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu);
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu);
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu);
+
+ UpdateBootDelPage (BmmCallbackInfo);
+ UpdateDrvDelPage (BmmCallbackInfo);
+
+ if (TerminalMenu.MenuNumber > 0) {
+ BmmCallbackInfo->CurrentTerminal = 0;
+ UpdateTerminalPage (BmmCallbackInfo);
+ }
+
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
+ if (!EFI_ERROR (Status)) {
+ RefreshUpdateData ();
+
+ //
+ // If LegacyBios Protocol is installed, add 3 tags about legacy boot option
+ // in BootOption form: legacy FD/HD/CD/NET/BEV
+ //
+ CreateGotoOpCode (
+ FORM_SET_FD_ORDER_ID,
+ STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),
+ STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),
+ EFI_IFR_FLAG_CALLBACK,
+ FORM_SET_FD_ORDER_ID,
+ &gUpdateData
+ );
+
+ CreateGotoOpCode (
+ FORM_SET_HD_ORDER_ID,
+ STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),
+ STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),
+ EFI_IFR_FLAG_CALLBACK,
+ FORM_SET_HD_ORDER_ID,
+ &gUpdateData
+ );
+
+ CreateGotoOpCode (
+ FORM_SET_CD_ORDER_ID,
+ STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),
+ STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),
+ EFI_IFR_FLAG_CALLBACK,
+ FORM_SET_CD_ORDER_ID,
+ &gUpdateData
+ );
+
+ CreateGotoOpCode (
+ FORM_SET_NET_ORDER_ID,
+ STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),
+ STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),
+ EFI_IFR_FLAG_CALLBACK,
+ FORM_SET_NET_ORDER_ID,
+ &gUpdateData
+ );
+
+ CreateGotoOpCode (
+ FORM_SET_BEV_ORDER_ID,
+ STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),
+ STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),
+ EFI_IFR_FLAG_CALLBACK,
+ FORM_SET_BEV_ORDER_ID,
+ &gUpdateData
+ );
+
+ IfrLibUpdateForm (
+ BmmCallbackInfo->BmmHiiHandle,
+ &mBootMaintGuid,
+ FORM_MAIN_ID,
+ FORM_BOOT_LEGACY_DEVICE_ID,
+ FALSE,
+ &gUpdateData
+ );
+ }
+
+ //
+ // Dispatch BMM main formset and File Explorer formset.
+ //
+ FormSetDispatcher (BmmCallbackInfo);
+
+ //
+ // Remove our IFR data from HII database
+ //
+ gHiiDatabase->RemovePackageList (gHiiDatabase, BmmCallbackInfo->BmmHiiHandle);
+ gHiiDatabase->RemovePackageList (gHiiDatabase, BmmCallbackInfo->FeHiiHandle);
+
+ CleanUpStringDepository ();
+
+ FreeAllMenu ();
+
+ FreePool (BmmCallbackInfo->LoadContext);
+ FreePool (BmmCallbackInfo);
+ FreePool (gUpdateData.Data);
+ gUpdateData.Data = NULL;
+
+ return Status;
+}
+
+/**
+ 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_GetLegacyOptions ();
+ InitializeListHead (&FsOptionMenu.Head);
+ BOpt_FindDrivers ();
+ InitializeListHead (&DirectoryMenu.Head);
+ InitializeListHead (&ConsoleInpMenu.Head);
+ InitializeListHead (&ConsoleOutMenu.Head);
+ InitializeListHead (&ConsoleErrMenu.Head);
+ InitializeListHead (&TerminalMenu.Head);
+ LocateSerialIo ();
+ GetAllConsoles ();
+}
+
+/**
+ Free up all Menu Option list.
+
+**/
+VOID
+FreeAllMenu (
+ VOID
+ )
+{
+ BOpt_FreeMenu (&DirectoryMenu);
+ BOpt_FreeMenu (&FsOptionMenu);
+ BOpt_FreeMenu (&BootOptionMenu);
+ BOpt_FreeMenu (&DriverOptionMenu);
+ BOpt_FreeMenu (&DriverMenu);
+ BOpt_FreeLegacyOptions ();
+ FreeAllConsoles ();
+}
+
+/**
+ Intialize all the string depositories.
+
+**/
+VOID
+InitializeStringDepository (
+ VOID
+ )
+{
+ STRING_DEPOSITORY *StringDepository;
+ StringDepository = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER);
+ FileOptionStrDepository = StringDepository++;
+ ConsoleOptionStrDepository = StringDepository++;
+ BootOptionStrDepository = StringDepository++;
+ BootOptionHelpStrDepository = StringDepository++;
+ DriverOptionStrDepository = StringDepository++;
+ DriverOptionHelpStrDepository = StringDepository++;
+ TerminalStrDepository = StringDepository;
+}
+
+/**
+ Fetch a usable string node from the string depository and return the string token.
+
+ @param CallbackData The BMM context data.
+ @param StringDepository The string repository.
+
+ @retval EFI_STRING_ID String token.
+
+**/
+EFI_STRING_ID
+GetStringTokenFromDepository (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN STRING_DEPOSITORY *StringDepository
+ )
+{
+ STRING_LIST_NODE *CurrentListNode;
+ STRING_LIST_NODE *NextListNode;
+
+ CurrentListNode = StringDepository->CurrentNode;
+
+ if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) {
+ //
+ // Fetch one reclaimed node from the list.
+ //
+ NextListNode = StringDepository->CurrentNode->Next;
+ } else {
+ //
+ // If there is no usable node in the list, update the list.
+ //
+ NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE));
+ ASSERT (NextListNode != NULL);
+ HiiLibNewString (CallbackData->BmmHiiHandle, &(NextListNode->StringToken), L" ");
+ ASSERT (NextListNode->StringToken != 0);
+
+ StringDepository->TotalNodeNumber++;
+
+ if (NULL == CurrentListNode) {
+ StringDepository->ListHead = NextListNode;
+ } else {
+ CurrentListNode->Next = NextListNode;
+ }
+ }
+
+ StringDepository->CurrentNode = NextListNode;
+
+ return StringDepository->CurrentNode->StringToken;
+}
+
+/**
+ Reclaim string depositories by moving the current node pointer to list head..
+
+**/
+VOID
+ReclaimStringDepository (
+ VOID
+ )
+{
+ UINTN DepositoryIndex;
+ STRING_DEPOSITORY *StringDepository;
+
+ StringDepository = FileOptionStrDepository;
+ for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {
+ StringDepository->CurrentNode = StringDepository->ListHead;
+ StringDepository++;
+ }
+}
+
+/**
+ Release resource for all the string depositories.
+
+**/
+VOID
+CleanUpStringDepository (
+ VOID
+ )
+{
+ UINTN NodeIndex;
+ UINTN DepositoryIndex;
+ STRING_LIST_NODE *CurrentListNode;
+ STRING_LIST_NODE *NextListNode;
+ STRING_DEPOSITORY *StringDepository;
+
+ //
+ // Release string list nodes.
+ //
+ StringDepository = FileOptionStrDepository;
+ for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {
+ CurrentListNode = StringDepository->ListHead;
+ for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) {
+ NextListNode = CurrentListNode->Next;
+ FreePool (CurrentListNode);
+ CurrentListNode = NextListNode;
+ }
+
+ StringDepository++;
+ }
+ //
+ // Release string depository.
+ //
+ FreePool (FileOptionStrDepository);
+}
+
+/**
+ Start boot maintenance manager
+
+ @retval EFI_SUCCESS If BMM is invoked successfully.
+ @return Other value if BMM return unsuccessfully.
+
+**/
+EFI_STATUS
+BdsStartBootMaint (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY BdsBootOptionList;
+
+ InitializeListHead (&BdsBootOptionList);
+
+ //
+ // Connect all prior to entering the platform setup menu.
+ //
+ if (!gConnectAllHappened) {
+ BdsLibConnectAllDriversToAllControllers ();
+ gConnectAllHappened = TRUE;
+ }
+ //
+ // Have chance to enumerate boot device
+ //
+ BdsLibEnumerateAllBootOption (&BdsBootOptionList);
+
+ //
+ // Init the BMM
+ //
+ Status = InitializeBM ();
+
+ return Status;
+}
+
+/**
+ Dispatch BMM formset and FileExplorer formset.
+
+
+ @param CallbackData The BMM context data.
+
+ @retval EFI_SUCCESS If function complete successfully.
+ @return Other value if the Setup Browser process BMM's pages and
+ return unsuccessfully.
+
+**/
+EFI_STATUS
+FormSetDispatcher (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ EFI_STATUS Status;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+
+ while (TRUE) {
+ UpdatePageId (CallbackData, FORM_MAIN_ID);
+
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Status = gFormBrowser2->SendForm (
+ gFormBrowser2,
+ &CallbackData->BmmHiiHandle,
+ 1,
+ NULL,
+ 0,
+ NULL,
+ &ActionRequest
+ );
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
+ EnableResetRequired ();
+ }
+
+ ReclaimStringDepository ();
+
+ //
+ // When this Formset returns, check if we are going to explore files.
+ //
+ if (INACTIVE_STATE != CallbackData->FeCurrentState) {
+ UpdateFileExplorer (CallbackData, 0);
+
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Status = gFormBrowser2->SendForm (
+ gFormBrowser2,
+ &CallbackData->FeHiiHandle,
+ 1,
+ NULL,
+ 0,
+ NULL,
+ &ActionRequest
+ );
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
+ EnableResetRequired ();
+ }
+
+ CallbackData->FeCurrentState = INACTIVE_STATE;
+ CallbackData->FeDisplayContext = UNKNOWN_CONTEXT;
+ ReclaimStringDepository ();
+ } else {
+ break;
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Deletete the Boot Option from EFI Variable. The Boot Order Arrray
+ is also updated.
+
+ @param OptionNumber The number of Boot option want to be deleted.
+ @param BootOrder The Boot Order array.
+ @param BootOrderSize The size of the Boot Order Array.
+
+ @return Other value if the Boot Option specified by OptionNumber is not deleteed succesfully.
+ @retval EFI_SUCCESS If function return successfully.
+
+**/
+EFI_STATUS
+BdsDeleteBootOption (
+ IN UINTN OptionNumber,
+ IN OUT UINT16 *BootOrder,
+ IN OUT UINTN *BootOrderSize
+ )
+{
+ UINT16 BootOption[100];
+ UINTN Index;
+ EFI_STATUS Status;
+ UINTN Index2Del;
+
+ Status = EFI_SUCCESS;
+ Index2Del = 0;
+
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber);
+ Status = EfiLibDeleteVariable (BootOption, &gEfiGlobalVariableGuid);
+
+ //
+ // adjust boot order array
+ //
+ for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) {
+ if (BootOrder[Index] == OptionNumber) {
+ Index2Del = Index;
+ break;
+ }
+ }
+
+ if (Index != *BootOrderSize / sizeof (UINT16)) {
+ for (Index = 0; Index < *BootOrderSize / sizeof (UINT16) - 1; Index++) {
+ if (Index >= Index2Del) {
+ BootOrder[Index] = BootOrder[Index + 1];
+ }
+ }
+
+ *BootOrderSize -= sizeof (UINT16);
+ }
+
+ return Status;
+
+}
+
+
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h
new file mode 100644
index 0000000000..2db13372af
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h
@@ -0,0 +1,1612 @@
+/** @file
+ Header file for boot maintenance module.
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "Bds.h"
+#include "BBSsupport.h"
+#include "FormGuid.h"
+#include "FrontPage.h"
+
+//
+// Constants which are variable names used to access variables
+//
+#define VAR_LEGACY_DEV_ORDER L"LegacyDevOrder"
+
+#define VAR_CON_OUT_MODE L"ConOutMode"
+
+///
+/// Guid of a NV Variable which store the information about the
+/// FD/HD/CD/NET/BEV order
+///
+#define EFI_LEGACY_DEV_ORDER_VARIABLE_GUID \
+ { \
+ 0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52} \
+ }
+
+//
+// String Contant
+//
+#define STR_FLOPPY L"Floppy Drive #%02x"
+#define STR_HARDDISK L"HardDisk Drive #%02x"
+#define STR_CDROM L"ATAPI CDROM Drive #%02x"
+#define STR_NET L"NET Drive #%02x"
+#define STR_BEV L"BEV Drive #%02x"
+#define STR_FLOPPY_HELP L"Select Floppy Drive #%02x"
+#define STR_HARDDISK_HELP L"Select HardDisk Drive #%02x"
+#define STR_CDROM_HELP L"Select ATAPI CDROM Drive #%02x"
+#define STR_NET_HELP L"NET Drive #%02x"
+#define STR_BEV_HELP L"BEV Drive #%02x"
+
+//
+// Variable created with this flag will be "Efi:...."
+//
+#define VAR_FLAG EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE
+
+//
+// Define Maxmim characters that will be accepted
+//
+#define MAX_CHAR 480
+#define MAX_CHAR_SIZE (MAX_CHAR * 2)
+
+extern EFI_GUID mBootMaintGuid;
+extern EFI_GUID mFileExplorerGuid;
+
+//
+// These are the VFR compiler generated data representing our VFR data.
+//
+extern UINT8 BmBin[];
+extern UINT8 FEBin[];
+
+//
+// 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)
+
+#define FE_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, FeConfigAccess, BMM_CALLBACK_DATA_SIGNATURE)
+
+//
+// Enumeration type definition
+//
+typedef UINT8 BBS_TYPE;
+
+typedef enum {
+ PC_ANSI = 0,
+ VT_100,
+ VT_100_PLUS,
+ VT_UTF8
+} TYPE_OF_TERMINAL;
+
+typedef enum {
+ COM1 = 0,
+ COM2,
+ UNKNOW_COM
+} TYPE_OF_COM;
+
+typedef enum {
+ CONIN = 0,
+ CONOUT,
+ CONERR,
+ UNKNOWN_CON
+} TYPE_OF_CON;
+
+typedef enum {
+ BAUDRATE = 0,
+ DATABITS,
+ PARITY,
+ STOPBITS,
+ UNKNOW_ATTR
+} TYPE_OF_ATTRIBUTE;
+
+typedef enum {
+ MANNER_GOTO = 0,
+ MANNER_CHECK,
+ MANNER_ONEOF,
+ MANNER_USER_DEFINE
+} TYPE_OF_UPATE_MANNER;
+
+typedef enum {
+ INACTIVE_STATE = 0,
+ BOOT_FROM_FILE_STATE,
+ ADD_BOOT_OPTION_STATE,
+ ADD_DRIVER_OPTION_STATE,
+ UNKNOWN_STATE
+} FILE_EXPLORER_STATE;
+
+typedef enum {
+ FILE_SYSTEM,
+ DIRECTORY,
+ UNKNOWN_CONTEXT
+} FILE_EXPLORER_DISPLAY_CONTEXT;
+
+//
+// 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
+#define BM_LEGACY_DEV_CONTEXT_SELECT 0x9
+
+//
+// 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 OPTION_ORDER_VAR_OFFSET VAR_OFFSET (OptionOrder)
+#define DRIVER_OPTION_ORDER_VAR_OFFSET VAR_OFFSET (DriverOptionToBeDeleted)
+#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 LEGACY_FD_VAR_OFFSET VAR_OFFSET (LegacyFD)
+#define LEGACY_HD_VAR_OFFSET VAR_OFFSET (LegacyHD)
+#define LEGACY_CD_VAR_OFFSET VAR_OFFSET (LegacyCD)
+#define LEGACY_NET_VAR_OFFSET VAR_OFFSET (LegacyNET)
+#define LEGACY_BEV_VAR_OFFSET VAR_OFFSET (LegacyBEV)
+
+#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 OPTION_ORDER_QUESTION_ID QUESTION_ID (OptionOrder)
+#define DRIVER_OPTION_ORDER_QUESTION_ID QUESTION_ID (DriverOptionToBeDeleted)
+#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 LEGACY_FD_QUESTION_ID QUESTION_ID (LegacyFD)
+#define LEGACY_HD_QUESTION_ID QUESTION_ID (LegacyHD)
+#define LEGACY_CD_QUESTION_ID QUESTION_ID (LegacyCD)
+#define LEGACY_NET_QUESTION_ID QUESTION_ID (LegacyNET)
+#define LEGACY_BEV_QUESTION_ID QUESTION_ID (LegacyBEV)
+
+#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;
+
+#pragma pack(1)
+typedef struct {
+ BBS_TYPE BbsType;
+ ///
+ /// Length = sizeof (UINT16) + SIZEOF (Data)
+ ///
+ UINT16 Length;
+ UINT16 *Data;
+} BM_LEGACY_DEV_ORDER_CONTEXT;
+#pragma pack()
+
+typedef struct {
+ UINT64 BaudRate;
+ UINT8 DataBits;
+ UINT8 Parity;
+ UINT8 StopBits;
+
+ UINT8 BaudRateIndex;
+ UINT8 DataBitsIndex;
+ UINT8 ParityIndex;
+ UINT8 StopBitsIndex;
+
+ 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 {
+ BBS_TABLE *BbsTable;
+ UINTN Index;
+ UINTN BbsCount;
+ UINT16 *Description;
+} BM_LEGACY_DEVICE_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 {
+ //
+ // Shared callback data.
+ //
+ UINTN Signature;
+
+ 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_HII_HANDLE BmmHiiHandle;
+ EFI_HANDLE BmmDriverHandle;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL BmmConfigAccess;
+ EFI_FORM_ID BmmCurrentPageId;
+ EFI_FORM_ID BmmPreviousPageId;
+ BOOLEAN BmmAskSaveOrNot;
+ BMM_FAKE_NV_DATA BmmFakeNvData;
+ BMM_FAKE_NV_DATA BmmOldFakeNVData;
+
+ //
+ // File explorer formset callback data.
+ //
+ EFI_HII_HANDLE FeHiiHandle;
+ EFI_HANDLE FeDriverHandle;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL FeConfigAccess;
+ FILE_EXPLORER_STATE FeCurrentState;
+ FILE_EXPLORER_DISPLAY_CONTEXT FeDisplayContext;
+ FILE_EXPLORER_NV_DATA FeFakeNvData;
+} BMM_CALLBACK_DATA;
+
+typedef struct _STRING_LIST_NODE {
+ EFI_STRING_ID StringToken;
+ struct _STRING_LIST_NODE *Next;
+} STRING_LIST_NODE;
+
+typedef struct _STRING_DEPOSITORY {
+ UINTN TotalNodeNumber;
+ STRING_LIST_NODE *CurrentNode;
+ STRING_LIST_NODE *ListHead;
+} STRING_DEPOSITORY;
+
+//
+// #pragma pack()
+//
+// For initializing File System menu
+//
+
+/**
+ This function build the FsOptionMenu list which records all
+ available file system in the system. They includes all instances
+ of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM
+ and all type of legacy boot device.
+
+ @param CallbackData BMM context data
+
+ @retval EFI_SUCCESS Success find the file system
+ @retval EFI_OUT_OF_RESOURCES Can not create menu entry
+
+**/
+EFI_STATUS
+BOpt_FindFileSystem (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Find files under current directory
+ All files and sub-directories in current directory
+ will be stored in DirectoryMenu for future use.
+
+ @param CallbackData The BMM context data.
+ @param MenuEntry The Menu Entry.
+
+ @retval EFI_SUCCESS Get files from current dir successfully.
+ @return Other value if can't get files from current dir.
+
+**/
+EFI_STATUS
+BOpt_FindFiles (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN BM_MENU_ENTRY *MenuEntry
+ );
+
+/**
+
+ 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
+ );
+
+
+/**
+ Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function.
+
+**/
+EFI_STATUS
+BOpt_GetLegacyOptions (
+ VOID
+ );
+
+/**
+ Free out resouce allocated from Legacy Boot Options.
+
+**/
+VOID
+BOpt_FreeLegacyOptions (
+ VOID
+ );
+
+/**
+ Free resources allocated in Allocate Rountine.
+
+ @param FreeMenu Menu to be freed
+
+**/
+VOID
+BOpt_FreeMenu (
+ BM_MENU_OPTION *FreeMenu
+ );
+
+
+/**
+
+ Append file name to existing file name.
+
+ @param Str1 The existing file name
+ @param Str2 The file name to be appended
+
+ @return Allocate a new string to hold the appended result.
+ Caller is responsible to free the returned string.
+
+**/
+CHAR16*
+BOpt_AppendFileName (
+ IN CHAR16 *Str1,
+ IN CHAR16 *Str2
+ );
+
+/**
+
+ Check whether current FileName point to a valid
+ Efi Image File.
+
+ @param FileName File need to be checked.
+
+ @retval TRUE Is Efi Image
+ @retval FALSE Not a valid Efi Image
+
+**/
+BOOLEAN
+BOpt_IsEfiImageName (
+ IN UINT16 *FileName
+ );
+
+/**
+
+ Check whether current FileName point to a valid Efi Application
+
+ @param Dir Pointer to current Directory
+ @param FileName Pointer to current File name.
+
+ @retval TRUE Is a valid Efi Application
+ @retval FALSE not a valid Efi Application
+
+**/
+BOOLEAN
+BOpt_IsEfiApp (
+ IN EFI_FILE_HANDLE Dir,
+ IN UINT16 *FileName
+ );
+
+/**
+
+ Get the Option Number that has not been allocated for use.
+
+ @return The available Option Number.
+
+**/
+UINT16
+BOpt_GetBootOptionNumber (
+ VOID
+ );
+
+/**
+
+ Get the Option Number that is not in use.
+
+ @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
+ );
+
+//
+// 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.
+ @param NvRamMap The file explorer formset internal state.
+
+ @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,
+ IN FILE_EXPLORER_NV_DATA *NvRamMap
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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 legacy BBS boot option. L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable
+ is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid
+ is also updated.
+
+ @param CallbackData The context data for BMM.
+
+ @return EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND If L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable can not be found.
+
+**/
+EFI_STATUS
+Var_UpdateBBSOption (
+ 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
+//
+/**
+ 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
+ );
+
+/**
+ Create a dynamic page so that Legacy Device boot order
+ can be set for specified device type.
+
+ @param UpdatePageId The form ID. It also spefies the legacy device type.
+ @param CallbackData The BMM context data.
+**/
+VOID
+UpdateSetLegacyDeviceOrderPage (
+ IN UINT16 UpdatePageId,
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+
+/**
+ Function opens and returns a file handle to the root directory of a volume.
+
+ @param DeviceHandle A handle for a device
+ @return A valid file handle or NULL is returned
+**/
+EFI_FILE_HANDLE
+EfiLibOpenRoot (
+ IN EFI_HANDLE DeviceHandle
+ );
+
+/**
+ Function gets the file system information from an open file descriptor,
+ and stores it in a buffer allocated from pool.
+
+ @param FHand The file handle.
+
+ @return A pointer to a buffer with file information.
+ NULL is returned if failed to get Vaolume Label Info.
+**/
+EFI_FILE_SYSTEM_VOLUME_LABEL *
+EfiLibFileSystemVolumeLabelInfo (
+ IN EFI_FILE_HANDLE FHand
+ );
+
+/**
+
+ Function gets the file information from an open file descriptor, and stores it
+ in a buffer allocated from pool.
+
+ @param FHand File Handle.
+
+ @return A pointer to a buffer with file information or NULL is returned
+
+**/
+EFI_FILE_INFO *
+EfiLibFileInfo (
+ IN EFI_FILE_HANDLE FHand
+ );
+
+/**
+ 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 *
+DevicePathToStr (
+ EFI_DEVICE_PATH_PROTOCOL *DevPath
+ );
+
+/**
+ Find the first instance of this Protocol in the system and return it's interface.
+
+ @param ProtocolGuid Provides the protocol to search for
+ @param Interface On return, a pointer to the first interface
+ that matches ProtocolGuid
+
+ @retval EFI_SUCCESS A protocol instance matching ProtocolGuid was found
+ @retval EFI_NOT_FOUND No protocol instances were found that match ProtocolGuid
+
+**/
+EFI_STATUS
+EfiLibLocateProtocol (
+ IN EFI_GUID *ProtocolGuid,
+ OUT VOID **Interface
+ );
+
+/**
+ Adjusts the size of a previously allocated buffer.
+
+ @param OldPool A pointer to the buffer whose size is being adjusted.
+ @param OldSize The size of the current buffer.
+ @param NewSize The size of the new buffer.
+
+ @return The newly allocated buffer. if NULL, allocation failed.
+
+**/
+VOID*
+EfiReallocatePool (
+ IN VOID *OldPool,
+ IN UINTN OldSize,
+ IN UINTN NewSize
+ );
+
+/**
+ Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
+ buffer, and the size of the buffer. If failure return NULL.
+
+ @param Name String part of EFI variable name
+ @param VendorGuid GUID part of EFI variable name
+ @param VarSize Returns the size of the EFI variable that was read
+
+ @return Dynamically allocated memory that contains a copy of the EFI variable.
+ @return Caller is responsible freeing the buffer.
+ @retval NULL Variable was not read
+
+**/
+VOID *
+BdsLibGetVariableAndSize (
+ IN CHAR16 *Name,
+ IN EFI_GUID *VendorGuid,
+ OUT UINTN *VarSize
+ );
+
+/**
+ 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
+ );
+
+/**
+ Duplicate a string.
+
+ @param Src The source.
+
+ @return A new string which is duplicated copy of the source.
+ @retval NULL If there is not enough memory.
+
+**/
+CHAR16 *
+EfiStrDuplicate (
+ IN CHAR16 *Src
+ );
+
+/**
+ 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
+ );
+
+/**
+ Create string tokens for a menu from its help strings and display strings
+
+
+ @param CallbackData The BMM context data.
+ @param HiiHandle Hii Handle of the package to be updated.
+ @param MenuOption The Menu whose string tokens need to be created
+
+ @retval EFI_SUCCESS string tokens created successfully
+ @retval others contain some errors
+
+**/
+EFI_STATUS
+CreateMenuStringToken (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN BM_MENU_OPTION *MenuOption
+ );
+
+/**
+ 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
+ );
+
+/**
+ Initialize the Boot Maintenance Utitliy.
+
+ @retval EFI_SUCCESS utility ended successfully.
+ @retval others contain some errors.
+
+**/
+EFI_STATUS
+InitializeBM (
+ VOID
+ );
+
+/**
+ Start boot maintenance manager
+
+ @retval EFI_SUCCESS If BMM is invoked successfully.
+ @return Other value if BMM return unsuccessfully.
+
+**/
+EFI_STATUS
+BdsStartBootMaint (
+ VOID
+ );
+
+/**
+ Intialize all the string depositories.
+
+**/
+VOID
+InitializeStringDepository (
+ VOID
+ );
+
+/**
+ Fetch a usable string node from the string depository and return the string token.
+
+
+ @param CallbackData The BMM context data.
+ @param StringDepository Pointer of the string depository.
+
+ @retval EFI_STRING_ID String token.
+
+**/
+EFI_STRING_ID
+GetStringTokenFromDepository (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN STRING_DEPOSITORY *StringDepository
+ );
+
+/**
+ Reclaim string depositories by moving the current node pointer to list head..
+**/
+VOID
+ReclaimStringDepository (
+ VOID
+ );
+
+/**
+ Release resource for all the string depositories.
+
+**/
+VOID
+CleanUpStringDepository (
+ VOID
+ );
+
+/**
+ Function handling request to apply changes for BMM pages.
+
+ @param Private Pointer to callback data buffer.
+ @param CurrentFakeNVMap Pointer to buffer holding data of various values used by BMM
+ @param FormId ID of the form which has sent the request to apply change.
+
+ @retval EFI_SUCCESS Change successfully applied.
+ @retval Other Error occurs while trying to apply changes.
+
+**/
+EFI_STATUS
+ApplyChangeHandler (
+ IN BMM_CALLBACK_DATA *Private,
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap,
+ IN EFI_FORM_ID FormId
+ );
+
+/**
+ 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
+ );
+
+/**
+ Boot a file selected by user at File Expoloer of BMM.
+
+ @param FileContext The file context data, which contains the device path
+ of the file to be boot from.
+
+ @retval EFI_SUCCESS The function completed successfull.
+ @return Other value if the boot from the file fails.
+
+**/
+EFI_STATUS
+BootThisFile (
+ IN BM_FILE_CONTEXT *FileContext
+ );
+
+/**
+ Update the file explower page with the refershed file system.
+
+
+ @param CallbackData BMM context data
+ @param KeyValue Key value to identify the type of data to expect.
+
+ @retval TRUE Inform the caller to create a callback packet to exit file explorer.
+ @retval FALSE Indicate that there is no need to exit file explorer.
+
+**/
+BOOLEAN
+UpdateFileExplorer (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN UINT16 KeyValue
+ );
+
+/**
+ This function processes the results of changes in configuration.
+ When user select a interactive opcode, this callback will be triggered.
+ Based on the Question(QuestionId) that triggers the callback, the corresponding
+ actions is performed. It handles:
+
+ 1) the addition of boot option.
+ 2) the addition of driver option.
+ 3) exit from file browser
+ 4) update of file content if a dir is selected.
+ 5) boot the file if a file is selected in "boot from file"
+
+
+ @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.
+
+**/
+EFI_STATUS
+EFIAPI
+FileExplorerCallback (
+ 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
+ );
+
+/**
+ Dispatch BMM formset and FileExplorer formset.
+
+
+ @param CallbackData The BMM context data.
+
+ @retval EFI_SUCCESS If function complete successfully.
+ @return Other value if the Setup Browser process BMM's pages and
+ return unsuccessfully.
+
+**/
+EFI_STATUS
+FormSetDispatcher (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+/**
+ Function returns the value of the specified variable.
+
+ @param Name A Null-terminated Unicode string that is
+ the name of the vendor's variable.
+ @param VendorGuid A unique identifier for the vendor.
+
+ @return The payload of the variable.
+ @retval NULL If the variable can't be read.
+
+**/
+VOID *
+EfiLibGetVariable (
+ IN CHAR16 *Name,
+ IN EFI_GUID *VendorGuid
+ );
+
+//
+// Global variable in this program (defined in data.c)
+//
+extern BM_MENU_OPTION BootOptionMenu;
+extern BM_MENU_OPTION DriverOptionMenu;
+extern BM_MENU_OPTION FsOptionMenu;
+extern BM_MENU_OPTION ConsoleInpMenu;
+extern BM_MENU_OPTION ConsoleOutMenu;
+extern BM_MENU_OPTION ConsoleErrMenu;
+extern BM_MENU_OPTION DirectoryMenu;
+extern BM_MENU_OPTION DriverMenu;
+extern BM_MENU_OPTION TerminalMenu;
+extern BM_MENU_OPTION LegacyFDMenu;
+extern BM_MENU_OPTION LegacyHDMenu;
+extern BM_MENU_OPTION LegacyCDMenu;
+extern BM_MENU_OPTION LegacyNETMenu;
+extern BM_MENU_OPTION LegacyBEVMenu;
+extern UINT16 TerminalType[];
+extern COM_ATTR BaudRateList[19];
+extern COM_ATTR DataBitsList[4];
+extern COM_ATTR ParityList[5];
+extern COM_ATTR StopBitsList[3];
+extern EFI_GUID TerminalTypeGuid[4];
+extern EFI_HII_UPDATE_DATA gUpdateData;
+extern STRING_DEPOSITORY *FileOptionStrDepository;
+extern STRING_DEPOSITORY *ConsoleOptionStrDepository;
+extern STRING_DEPOSITORY *BootOptionStrDepository;
+extern STRING_DEPOSITORY *BootOptionHelpStrDepository;
+extern STRING_DEPOSITORY *DriverOptionStrDepository;
+extern STRING_DEPOSITORY *DriverOptionHelpStrDepository;
+extern STRING_DEPOSITORY *TerminalStrDepository;
+extern EFI_DEVICE_PATH_PROTOCOL EndDevicePath[];
+extern EFI_GUID EfiLegacyDevOrderGuid;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c
new file mode 100644
index 0000000000..e9caf5958a
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c
@@ -0,0 +1,1661 @@
+/** @file
+ Provide boot option support for Application "BootMaint"
+
+ Include file system navigation, system handle selection
+
+ Boot option manipulation
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "BootMaint.h"
+#include "BBSsupport.h"
+
+/**
+ 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;
+
+ case BM_LEGACY_DEV_CONTEXT_SELECT:
+ ContextSize = sizeof (BM_LEGACY_DEVICE_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;
+ BM_LEGACY_DEVICE_CONTEXT *LegacyDevContext;
+
+ //
+ // 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;
+
+ case BM_LEGACY_DEV_CONTEXT_SELECT:
+ LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext;
+ FreePool (LegacyDevContext);
+
+ 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;
+}
+
+/**
+ This function build the FsOptionMenu list which records all
+ available file system in the system. They includes all instances
+ of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM
+ and all type of legacy boot device.
+
+ @param CallbackData BMM context data
+
+ @retval EFI_SUCCESS Success find the file system
+ @retval EFI_OUT_OF_RESOURCES Can not create menu entry
+
+**/
+EFI_STATUS
+BOpt_FindFileSystem (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINTN NoBlkIoHandles;
+ UINTN NoSimpleFsHandles;
+ UINTN NoLoadFileHandles;
+ EFI_HANDLE *BlkIoHandle;
+ EFI_HANDLE *SimpleFsHandle;
+ EFI_HANDLE *LoadFileHandle;
+ UINT16 *VolumeLabel;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ UINTN Index;
+ EFI_STATUS Status;
+ BM_MENU_ENTRY *MenuEntry;
+ BM_FILE_CONTEXT *FileContext;
+ UINT16 *TempStr;
+ UINTN OptionNumber;
+ VOID *Buffer;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINT16 DeviceType;
+ BBS_BBS_DEVICE_PATH BbsDevicePathNode;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ BOOLEAN RemovableMedia;
+
+
+ NoSimpleFsHandles = 0;
+ NoLoadFileHandles = 0;
+ OptionNumber = 0;
+ InitializeListHead (&FsOptionMenu.Head);
+
+ //
+ // Locate Handles that support BlockIo protocol
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ &NoBlkIoHandles,
+ &BlkIoHandle
+ );
+ if (!EFI_ERROR (Status)) {
+
+ for (Index = 0; Index < NoBlkIoHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ BlkIoHandle[Index],
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo
+ );
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media
+ //
+ if (BlkIo->Media->RemovableMedia) {
+ Buffer = AllocateZeroPool (BlkIo->Media->BlockSize);
+ if (NULL == Buffer) {
+ FreePool (BlkIoHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BlkIo->ReadBlocks (
+ BlkIo,
+ BlkIo->Media->MediaId,
+ 0,
+ BlkIo->Media->BlockSize,
+ Buffer
+ );
+ FreePool (Buffer);
+ }
+ }
+ FreePool (BlkIoHandle);
+ }
+
+ //
+ // Locate Handles that support Simple File System protocol
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ &NoSimpleFsHandles,
+ &SimpleFsHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Find all the instances of the File System prototocol
+ //
+ for (Index = 0; Index < NoSimpleFsHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ SimpleFsHandle[Index],
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If no block IO exists assume it's NOT a removable media
+ //
+ RemovableMedia = FALSE;
+ } else {
+ //
+ // If block IO exists check to see if it's remobable media
+ //
+ RemovableMedia = BlkIo->Media->RemovableMedia;
+ }
+
+ //
+ // Allocate pool for this load option
+ //
+ MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
+ if (NULL == MenuEntry) {
+ FreePool (SimpleFsHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
+
+ FileContext->Handle = SimpleFsHandle[Index];
+ MenuEntry->OptionNumber = Index;
+ FileContext->FHandle = EfiLibOpenRoot (FileContext->Handle);
+ if (FileContext->FHandle == NULL) {
+ BOpt_DestroyMenuEntry (MenuEntry);
+ continue;
+ }
+
+ MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle));
+ FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle);
+ FileContext->FileName = EfiStrDuplicate (L"\\");
+ FileContext->DevicePath = FileDevicePath (
+ FileContext->Handle,
+ FileContext->FileName
+ );
+ FileContext->IsDir = TRUE;
+ FileContext->IsRoot = TRUE;
+ FileContext->IsRemovableMedia = RemovableMedia;
+ FileContext->IsLoadFile = FALSE;
+
+ //
+ // Get current file system's Volume Label
+ //
+ if (FileContext->Info == NULL) {
+ VolumeLabel = L"NO FILE SYSTEM INFO";
+ } else {
+ if (FileContext->Info->VolumeLabel == NULL) {
+ VolumeLabel = L"NULL VOLUME LABEL";
+ } else {
+ VolumeLabel = FileContext->Info->VolumeLabel;
+ if (*VolumeLabel == 0x0000) {
+ VolumeLabel = L"NO VOLUME LABEL";
+ }
+ }
+ }
+
+ TempStr = MenuEntry->HelpString;
+ MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);
+ ASSERT (MenuEntry->DisplayString != NULL);
+ UnicodeSPrint (
+ MenuEntry->DisplayString,
+ MAX_CHAR,
+ L"%s, [%s]",
+ VolumeLabel,
+ TempStr
+ );
+ OptionNumber++;
+ InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
+ }
+ }
+
+ if (NoSimpleFsHandles != 0) {
+ FreePool (SimpleFsHandle);
+ }
+ //
+ // Searching for handles that support Load File protocol
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiLoadFileProtocolGuid,
+ NULL,
+ &NoLoadFileHandles,
+ &LoadFileHandle
+ );
+
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < NoLoadFileHandles; Index++) {
+ MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
+ if (NULL == MenuEntry) {
+ FreePool (LoadFileHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
+ FileContext->IsRemovableMedia = FALSE;
+ FileContext->IsLoadFile = TRUE;
+ FileContext->Handle = LoadFileHandle[Index];
+ FileContext->IsRoot = TRUE;
+
+ FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle);
+
+ MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);
+
+ TempStr = MenuEntry->HelpString;
+ MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);
+ ASSERT (MenuEntry->DisplayString != NULL);
+ UnicodeSPrint (
+ MenuEntry->DisplayString,
+ MAX_CHAR,
+ L"Load File [%s]",
+ TempStr
+ );
+
+ MenuEntry->OptionNumber = OptionNumber;
+ OptionNumber++;
+ InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
+ }
+ }
+
+ if (NoLoadFileHandles != 0) {
+ FreePool (LoadFileHandle);
+ }
+
+ //
+ // Add Legacy Boot Option Support Here
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID **) &LegacyBios
+ );
+ if (!EFI_ERROR (Status)) {
+
+ for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) {
+ MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
+ if (NULL == MenuEntry) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
+
+ FileContext->IsRemovableMedia = FALSE;
+ FileContext->IsLoadFile = TRUE;
+ FileContext->IsBootLegacy = TRUE;
+ DeviceType = (UINT16) Index;
+ BbsDevicePathNode.Header.Type = BBS_DEVICE_PATH;
+ BbsDevicePathNode.Header.SubType = BBS_BBS_DP;
+ SetDevicePathNodeLength (
+ &BbsDevicePathNode.Header,
+ sizeof (BBS_BBS_DEVICE_PATH)
+ );
+ BbsDevicePathNode.DeviceType = DeviceType;
+ BbsDevicePathNode.StatusFlag = 0;
+ BbsDevicePathNode.String[0] = 0;
+ DevicePath = AppendDevicePathNode (
+ EndDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode
+ );
+
+ FileContext->DevicePath = DevicePath;
+ MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);
+
+ TempStr = MenuEntry->HelpString;
+ MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);
+ ASSERT (MenuEntry->DisplayString != NULL);
+ UnicodeSPrint (
+ MenuEntry->DisplayString,
+ MAX_CHAR,
+ L"Boot Legacy [%s]",
+ TempStr
+ );
+ MenuEntry->OptionNumber = OptionNumber;
+ OptionNumber++;
+ InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
+ }
+ }
+ //
+ // Remember how many file system options are here
+ //
+ FsOptionMenu.MenuNumber = OptionNumber;
+ return EFI_SUCCESS;
+}
+
+/**
+ 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);
+ }
+}
+
+/**
+ Find files under current directory
+ All files and sub-directories in current directory
+ will be stored in DirectoryMenu for future use.
+
+ @param CallbackData The BMM context data.
+ @param MenuEntry The Menu Entry.
+
+ @retval EFI_SUCCESS Get files from current dir successfully.
+ @return Other value if can't get files from current dir.
+
+**/
+EFI_STATUS
+BOpt_FindFiles (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN BM_MENU_ENTRY *MenuEntry
+ )
+{
+ EFI_FILE_HANDLE NewDir;
+ EFI_FILE_HANDLE Dir;
+ EFI_FILE_INFO *DirInfo;
+ UINTN BufferSize;
+ UINTN DirBufferSize;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_FILE_CONTEXT *FileContext;
+ BM_FILE_CONTEXT *NewFileContext;
+ UINTN Pass;
+ EFI_STATUS Status;
+ UINTN OptionNumber;
+
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
+ Dir = FileContext->FHandle;
+ OptionNumber = 0;
+ //
+ // Open current directory to get files from it
+ //
+ Status = Dir->Open (
+ Dir,
+ &NewDir,
+ FileContext->FileName,
+ EFI_FILE_READ_ONLY,
+ 0
+ );
+ if (!FileContext->IsRoot) {
+ Dir->Close (Dir);
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DirInfo = EfiLibFileInfo (NewDir);
+ if (DirInfo == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (!(DirInfo->Attribute & EFI_FILE_DIRECTORY)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FileContext->DevicePath = FileDevicePath (
+ FileContext->Handle,
+ FileContext->FileName
+ );
+
+ DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;
+ DirInfo = AllocateZeroPool (DirBufferSize);
+ if (DirInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Get all files in current directory
+ // Pass 1 to get Directories
+ // Pass 2 to get files that are EFI images
+ //
+ for (Pass = 1; Pass <= 2; Pass++) {
+ NewDir->SetPosition (NewDir, 0);
+ for (;;) {
+ BufferSize = DirBufferSize;
+ Status = NewDir->Read (NewDir, &BufferSize, DirInfo);
+ if (EFI_ERROR (Status) || BufferSize == 0) {
+ break;
+ }
+
+ if ((DirInfo->Attribute & EFI_FILE_DIRECTORY && Pass == 2) ||
+ (!(DirInfo->Attribute & EFI_FILE_DIRECTORY) && Pass == 1)
+ ) {
+ //
+ // Pass 1 is for Directories
+ // Pass 2 is for file names
+ //
+ continue;
+ }
+
+ if (!(BOpt_IsEfiImageName (DirInfo->FileName) || DirInfo->Attribute & EFI_FILE_DIRECTORY)) {
+ //
+ // Slip file unless it is a directory entry or a .EFI file
+ //
+ continue;
+ }
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;
+ NewFileContext->Handle = FileContext->Handle;
+ NewFileContext->FileName = BOpt_AppendFileName (
+ FileContext->FileName,
+ DirInfo->FileName
+ );
+ NewFileContext->FHandle = NewDir;
+ NewFileContext->DevicePath = FileDevicePath (
+ NewFileContext->Handle,
+ NewFileContext->FileName
+ );
+ NewMenuEntry->HelpString = NULL;
+
+ MenuEntry->DisplayStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ FileOptionStrDepository
+ );
+
+ NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);
+
+ if (NewFileContext->IsDir) {
+ BufferSize = StrLen (DirInfo->FileName) * 2 + 6;
+ NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize);
+
+ UnicodeSPrint (
+ NewMenuEntry->DisplayString,
+ BufferSize,
+ L"<%s>",
+ DirInfo->FileName
+ );
+
+ } else {
+ NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName);
+ }
+
+ NewFileContext->IsRoot = FALSE;
+ NewFileContext->IsLoadFile = FALSE;
+ NewFileContext->IsRemovableMedia = FALSE;
+
+ NewMenuEntry->OptionNumber = OptionNumber;
+ OptionNumber++;
+ InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);
+ }
+ }
+
+ DirectoryMenu.MenuNumber = OptionNumber;
+ FreePool (DirInfo);
+ return EFI_SUCCESS;
+}
+
+/**
+ Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
+
+ @retval EFI_SUCCESS The function complete successfully.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function.
+
+**/
+EFI_STATUS
+BOpt_GetLegacyOptions (
+ VOID
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LEGACY_DEVICE_CONTEXT *NewLegacyDevContext;
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINT16 HddCount;
+ HDD_INFO *HddInfo;
+ UINT16 BbsCount;
+ BBS_TABLE *BbsTable;
+ UINTN Index;
+ CHAR16 DescString[100];
+ UINTN FDNum;
+ UINTN HDNum;
+ UINTN CDNum;
+ UINTN NETNum;
+ UINTN BEVNum;
+
+ NewMenuEntry = NULL;
+ HddInfo = NULL;
+ BbsTable = NULL;
+ BbsCount = 0;
+
+ //
+ // Initialize Bbs Table Context from BBS info data
+ //
+ InitializeListHead (&LegacyFDMenu.Head);
+ InitializeListHead (&LegacyHDMenu.Head);
+ InitializeListHead (&LegacyCDMenu.Head);
+ InitializeListHead (&LegacyNETMenu.Head);
+ InitializeListHead (&LegacyBEVMenu.Head);
+
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID **) &LegacyBios
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = LegacyBios->GetBbsInfo (
+ LegacyBios,
+ &HddCount,
+ &HddInfo,
+ &BbsCount,
+ &BbsTable
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ FDNum = 0;
+ HDNum = 0;
+ CDNum = 0;
+ NETNum = 0;
+ BEVNum = 0;
+
+ for (Index = 0; Index < BbsCount; Index++) {
+ if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) ||
+ (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority)
+ ) {
+ continue;
+ }
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ break;
+ }
+
+ NewLegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLegacyDevContext->BbsTable = &BbsTable[Index];
+ NewLegacyDevContext->Index = Index;
+ NewLegacyDevContext->BbsCount = BbsCount;
+ BdsBuildLegacyDevNameString (
+ &BbsTable[Index],
+ Index,
+ sizeof (DescString),
+ DescString
+ );
+ NewLegacyDevContext->Description = AllocateZeroPool (StrSize (DescString));
+ if (NULL == NewLegacyDevContext->Description) {
+ break;
+ }
+
+ CopyMem (NewLegacyDevContext->Description, DescString, StrSize (DescString));
+ NewMenuEntry->DisplayString = NewLegacyDevContext->Description;
+ NewMenuEntry->HelpString = NULL;
+
+ switch (BbsTable[Index].DeviceType) {
+ case BBS_FLOPPY:
+ InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);
+ FDNum++;
+ break;
+
+ case BBS_HARDDISK:
+ InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);
+ HDNum++;
+ break;
+
+ case BBS_CDROM:
+ InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);
+ CDNum++;
+ break;
+
+ case BBS_EMBED_NETWORK:
+ InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);
+ NETNum++;
+ break;
+
+ case BBS_BEV_DEVICE:
+ InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);
+ BEVNum++;
+ break;
+ }
+ }
+
+ if (Index != BbsCount) {
+ BOpt_FreeLegacyOptions ();
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ LegacyFDMenu.MenuNumber = FDNum;
+ LegacyHDMenu.MenuNumber = HDNum;
+ LegacyCDMenu.MenuNumber = CDNum;
+ LegacyNETMenu.MenuNumber = NETNum;
+ LegacyBEVMenu.MenuNumber = BEVNum;
+ return EFI_SUCCESS;
+}
+
+/**
+ Free out resouce allocated from Legacy Boot Options.
+
+**/
+VOID
+BOpt_FreeLegacyOptions (
+ VOID
+ )
+{
+ BOpt_FreeMenu (&LegacyFDMenu);
+ BOpt_FreeMenu (&LegacyHDMenu);
+ BOpt_FreeMenu (&LegacyCDMenu);
+ BOpt_FreeMenu (&LegacyNETMenu);
+ BOpt_FreeMenu (&LegacyBEVMenu);
+}
+
+/**
+
+ 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;
+
+ MenuCount = 0;
+ BootOrderListSize = 0;
+ BootNextSize = 0;
+ BootOrderList = NULL;
+ BootNext = NULL;
+ LoadOptionFromVar = NULL;
+ BOpt_FreeMenu (&BootOptionMenu);
+ InitializeListHead (&BootOptionMenu.Head);
+
+ //
+ // Get the BootOrder from the Var
+ //
+ BootOrderList = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderListSize
+ );
+ if (BootOrderList == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get the BootNext from the Var
+ //
+ BootNext = BdsLibGetVariableAndSize (
+ L"BootNext",
+ &gEfiGlobalVariableGuid,
+ &BootNextSize
+ );
+
+ if (BootNext != NULL) {
+ if (BootNextSize != sizeof (UINT16)) {
+ FreePool (BootNext);
+ BootNext = NULL;
+ }
+ }
+
+ for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {
+ UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);
+ //
+ // Get all loadoptions from the VAR
+ //
+ LoadOptionFromVar = BdsLibGetVariableAndSize (
+ BootString,
+ &gEfiGlobalVariableGuid,
+ &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;
+ }
+
+ if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) {
+ FreePool (LoadOption);
+ continue;
+ }
+ //
+ // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.
+ // the buffer allocated already should be freed before returning.
+ //
+ 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 + 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 (StringSize);
+ ASSERT (NewLoadContext->Description != NULL);
+ CopyMem (
+ NewLoadContext->Description,
+ (UINT16 *) LoadOptionPtr,
+ StringSize
+ );
+ NewMenuEntry->DisplayString = NewLoadContext->Description;
+
+ LoadOptionPtr += StringSize;
+
+ NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);
+ ASSERT (NewLoadContext->FilePathList != NULL);
+ CopyMem (
+ NewLoadContext->FilePathList,
+ (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,
+ NewLoadContext->FilePathListLength
+ );
+
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ BootOptionStrDepository
+ );
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ BootOptionHelpStrDepository
+ );
+ 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++;
+ }
+
+ if (BootNext != NULL) {
+ FreePool (BootNext);
+ }
+ if (BootOrderList != NULL) {
+ FreePool (BootOrderList);
+ }
+ BootOptionMenu.MenuNumber = MenuCount;
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Append file name to existing file name.
+
+ @param Str1 The existing file name
+ @param Str2 The file name to be appended
+
+ @return Allocate a new string to hold the appended result.
+ Caller is responsible to free the returned string.
+
+**/
+CHAR16 *
+BOpt_AppendFileName (
+ IN CHAR16 *Str1,
+ IN CHAR16 *Str2
+ )
+{
+ UINTN Size1;
+ UINTN Size2;
+ CHAR16 *Str;
+ CHAR16 *TmpStr;
+ CHAR16 *Ptr;
+ CHAR16 *LastSlash;
+
+ Size1 = StrSize (Str1);
+ Size2 = StrSize (Str2);
+ Str = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));
+ ASSERT (Str != NULL);
+
+ TmpStr = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));
+ ASSERT (TmpStr != NULL);
+
+ StrCat (Str, Str1);
+ if (!((*Str == '\\') && (*(Str + 1) == 0))) {
+ StrCat (Str, L"\\");
+ }
+
+ StrCat (Str, Str2);
+
+ Ptr = Str;
+ LastSlash = Str;
+ while (*Ptr != 0) {
+ if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) == L'\\') {
+ //
+ // Convert "\Name\..\" to "\"
+ // DO NOT convert the .. if it is at the end of the string. This will
+ // break the .. behavior in changing directories.
+ //
+
+ //
+ // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings
+ // that overlap.
+ //
+ StrCpy (TmpStr, Ptr + 3);
+ StrCpy (LastSlash, TmpStr);
+ Ptr = LastSlash;
+ } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {
+ //
+ // Convert a "\.\" to a "\"
+ //
+
+ //
+ // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings
+ // that overlap.
+ //
+ StrCpy (TmpStr, Ptr + 2);
+ StrCpy (Ptr, TmpStr);
+ Ptr = LastSlash;
+ } else if (*Ptr == '\\') {
+ LastSlash = Ptr;
+ }
+
+ Ptr++;
+ }
+
+ FreePool (TmpStr);
+
+ return Str;
+}
+
+/**
+
+ Check whether current FileName point to a valid
+ Efi Image File.
+
+ @param FileName File need to be checked.
+
+ @retval TRUE Is Efi Image
+ @retval FALSE Not a valid Efi Image
+
+**/
+BOOLEAN
+BOpt_IsEfiImageName (
+ IN UINT16 *FileName
+ )
+{
+ //
+ // Search for ".efi" extension
+ //
+ while (*FileName != L'\0') {
+ if (FileName[0] == '.') {
+ if (FileName[1] == 'e' || FileName[1] == 'E') {
+ if (FileName[2] == 'f' || FileName[2] == 'F') {
+ if (FileName[3] == 'i' || FileName[3] == 'I') {
+ return TRUE;
+ } else if (FileName[3] == 0x0000) {
+ return FALSE;
+ }
+ } else if (FileName[2] == 0x0000) {
+ return FALSE;
+ }
+ } else if (FileName[1] == 0x0000) {
+ return FALSE;
+ }
+ }
+
+ FileName += 1;
+ }
+
+ return FALSE;
+}
+
+/**
+
+ Check whether current FileName point to a valid Efi Application
+
+ @param Dir Pointer to current Directory
+ @param FileName Pointer to current File name.
+
+ @retval TRUE Is a valid Efi Application
+ @retval FALSE not a valid Efi Application
+
+**/
+BOOLEAN
+BOpt_IsEfiApp (
+ IN EFI_FILE_HANDLE Dir,
+ IN UINT16 *FileName
+ )
+{
+ UINTN BufferSize;
+ EFI_IMAGE_DOS_HEADER DosHdr;
+ UINT16 Subsystem;
+ EFI_FILE_HANDLE File;
+ EFI_STATUS Status;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr;
+
+ Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0);
+
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);
+ File->Read (File, &BufferSize, &DosHdr);
+ if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ File->Close (File);
+ return FALSE;
+ }
+
+ File->SetPosition (File, DosHdr.e_lfanew);
+ BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
+ File->Read (File, &BufferSize, &PeHdr);
+ if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
+ File->Close (File);
+ return FALSE;
+ }
+ //
+ // Determine PE type and read subsytem
+ //
+ if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ Subsystem = PeHdr.Pe32.OptionalHeader.Subsystem;
+ } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ Subsystem = PeHdr.Pe32Plus.OptionalHeader.Subsystem;
+ } else {
+ return FALSE;
+ }
+
+ if (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
+ File->Close (File);
+ return TRUE;
+ } else {
+ File->Close (File);
+ return FALSE;
+ }
+}
+
+/**
+
+ 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 = DevicePathToStr (NewHandleContext->DevicePath);
+ NewMenuEntry->HelpString = NULL;
+ 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.
+
+ @return The available Option Number.
+
+**/
+UINT16
+BOpt_GetBootOptionNumber (
+ VOID
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 *BootOrderList;
+ UINTN BootOrderListSize;
+ UINT16 Number;
+ UINTN Index;
+ UINTN Index2;
+ BOOLEAN Found;
+ CHAR16 StrTemp[100];
+ UINT16 *OptionBuffer;
+ UINTN OptionSize;
+
+ BootOrderListSize = 0;
+ BootOrderList = NULL;
+
+ BootOrderList = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderListSize
+ );
+ if (BootOrderList != NULL) {
+ //
+ // already have Boot####
+ //
+ // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);
+ //
+ for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {
+ Found = TRUE;
+ for (Index2 = 0; Index2 < BootOptionMenu.MenuNumber; Index2++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index2);
+ if (Index == NewMenuEntry->OptionNumber) {
+ Found = FALSE;
+ break;
+ }
+ }
+
+ if (Found) {
+ UnicodeSPrint (StrTemp, 100, L"Boot%04x", Index);
+ DEBUG((DEBUG_ERROR,"INdex= %s\n", StrTemp));
+ OptionBuffer = BdsLibGetVariableAndSize (
+ StrTemp,
+ &gEfiGlobalVariableGuid,
+ &OptionSize
+ );
+ if (NULL == OptionBuffer) {
+ break;
+ }
+ }
+ }
+ //
+ // end for Index
+ //
+ Number = (UINT16) Index;
+ } else {
+ //
+ // No Boot####
+ //
+ Number = 0;
+ }
+
+ return Number;
+}
+
+/**
+
+ Get the Option Number that is not in use.
+
+ @return The unused Option Number.
+
+**/
+UINT16
+BOpt_GetDriverOptionNumber (
+ VOID
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 *DriverOrderList;
+ UINTN DriverOrderListSize;
+ UINT16 Number;
+ UINTN Index;
+ UINTN Index2;
+ BOOLEAN Found;
+
+ DriverOrderListSize = 0;
+ DriverOrderList = NULL;
+
+ DriverOrderList = BdsLibGetVariableAndSize (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ &DriverOrderListSize
+ );
+ if (DriverOrderList != NULL) {
+ //
+ // already have Driver####
+ //
+ // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);
+ //
+ for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {
+ Found = TRUE;
+ for (Index2 = 0; Index2 < DriverOptionMenu.MenuNumber; Index2++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index2);
+ if (Index == NewMenuEntry->OptionNumber) {
+ Found = FALSE;
+ break;
+ }
+ }
+
+ if (Found) {
+ break;
+ }
+ }
+ //
+ // end for Index
+ //
+ Number = (UINT16) Index;
+ } else {
+ //
+ // No Driver####
+ //
+ Number = 0;
+ }
+
+ return Number;
+}
+
+/**
+
+ 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
+ //
+ DriverOrderList = BdsLibGetVariableAndSize (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ &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
+ //
+ LoadOptionFromVar = BdsLibGetVariableAndSize (
+ DriverString,
+ &gEfiGlobalVariableGuid,
+ &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;
+
+ LoadOptionPtr += StringSize;
+
+ NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);
+ ASSERT (NewLoadContext->FilePathList != NULL);
+ CopyMem (
+ NewLoadContext->FilePathList,
+ (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,
+ NewLoadContext->FilePathListLength
+ );
+
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ DriverOptionStrDepository
+ );
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ DriverOptionHelpStrDepository
+ );
+ 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;
+
+}
+
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c
new file mode 100644
index 0000000000..da0a8389fa
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c
@@ -0,0 +1,942 @@
+/** @file
+ handles console redirection from boot manager
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "BootMaint.h"
+
+/**
+ 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;
+ UINT32 Match;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ BM_MENU_ENTRY *NewMenuEntry;
+
+ Match = EISA_PNP_ID (0x0501);
+ Node = DevicePath;
+ Node = NextDevicePathNode (Node);
+ Com = 0;
+ while (!IsDevicePathEnd (Node)) {
+ if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
+ 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;
+ UINT32 Match;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ BM_MENU_ENTRY *NewMenuEntry;
+
+ Match = EISA_PNP_ID (0x0501);
+ Node = DevicePath;
+ Node = NextDevicePathNode (Node);
+ Com = 0;
+ while (!IsDevicePathEnd (Node)) {
+ if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
+ 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
+ )
+{
+ UINT32 Match;
+ UINT8 *Ptr;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ gBS->HandleProtocol (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath
+ );
+ Ptr = (UINT8 *) DevicePath;
+
+ while (*Ptr != END_DEVICE_PATH_TYPE) {
+ Ptr++;
+ }
+
+ Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);
+ Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;
+ Match = EISA_PNP_ID (0x0501);
+
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
+ if (AcpiUid != NULL) {
+ *AcpiUid = Acpi->UID;
+ }
+ 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
+ )
+{
+ UINT8 *Ptr;
+ UINTN Index;
+ UINTN Index2;
+ UINTN NoHandles;
+ EFI_HANDLE *Handles;
+ EFI_STATUS Status;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINT32 Match;
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ 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
+ );
+ Ptr = (UINT8 *) DevicePath;
+ while (*Ptr != END_DEVICE_PATH_TYPE) {
+ Ptr++;
+ }
+
+ Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);
+ Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;
+ Match = EISA_PNP_ID (0x0501);
+
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
+ 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 = DevicePathToStr (DevicePath);
+ }
+
+ NewMenuEntry->HelpString = NULL;
+
+ 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
+ //
+ OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);
+ InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);
+ ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);
+ 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 < 4; 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 = DevicePathToStr (NewDevicePath);
+ // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;
+ //
+ NewMenuEntry->HelpString = NULL;
+
+ if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) {
+ NewTerminalContext->IsConOut = TRUE;
+ NewTerminalContext->TerminalType = (UINT8) Index2;
+ }
+
+ if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) {
+ NewTerminalContext->IsConIn = TRUE;
+ NewTerminalContext->TerminalType = (UINT8) Index2;
+ }
+
+ if (BdsLibMatchDevicePaths (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;
+ UINT32 Match;
+ UINTN TerminalNumber;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ UINTN Index;
+
+ Match = EISA_PNP_ID (0x0501);
+ Node = DevicePath;
+ Node = NextDevicePathNode (Node);
+ TerminalNumber = 0;
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ while (!IsDevicePathEnd (Node)) {
+ if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
+ 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;
+ DevicePath = EfiLibGetVariable (
+ L"ConIn",
+ &gEfiGlobalVariableGuid
+ );
+
+ AllDevicePath = EfiLibGetVariable (
+ L"ConInDev",
+ &gEfiGlobalVariableGuid
+ );
+ break;
+
+ case BM_CONSOLE_OUT_CONTEXT_SELECT:
+ ConsoleMenu = &ConsoleOutMenu;
+ DevicePath = EfiLibGetVariable (
+ L"ConOut",
+ &gEfiGlobalVariableGuid
+ );
+
+ AllDevicePath = EfiLibGetVariable (
+ L"ConOutDev",
+ &gEfiGlobalVariableGuid
+ );
+ break;
+
+ case BM_CONSOLE_ERR_CONTEXT_SELECT:
+ ConsoleMenu = &ConsoleErrMenu;
+ DevicePath = EfiLibGetVariable (
+ L"ErrOut",
+ &gEfiGlobalVariableGuid
+ );
+
+ AllDevicePath = EfiLibGetVariable (
+ L"ErrOutDev",
+ &gEfiGlobalVariableGuid
+ );
+ 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);
+ NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath);
+ if (NULL == NewMenuEntry->DisplayString) {
+ NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath);
+ }
+
+ NewConsoleContext->IsTerminal = IsTerminalDevicePath (
+ NewConsoleContext->DevicePath,
+ &Terminal,
+ &Com
+ );
+
+ NewConsoleContext->IsActive = BdsLibMatchDevicePaths (
+ 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
+ )
+{
+ UINT8 *Ptr;
+ BOOLEAN IsTerminal;
+ VENDOR_DEVICE_PATH *Vendor;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ UINT32 Match;
+ EFI_GUID TempGuid;
+
+ IsTerminal = FALSE;
+
+ //
+ // Parse the Device Path, should be change later!!!
+ //
+ Ptr = (UINT8 *) DevicePath;
+ while (*Ptr != END_DEVICE_PATH_TYPE) {
+ Ptr++;
+ }
+
+ Ptr = Ptr - sizeof (VENDOR_DEVICE_PATH);
+ Vendor = (VENDOR_DEVICE_PATH *) Ptr;
+
+ //
+ // There are four kinds of Terminal types
+ // check to see whether this devicepath
+ // is one of that type
+ //
+ CopyMem (&TempGuid, &Vendor->Guid, sizeof (EFI_GUID));
+
+ if (CompareGuid (&TempGuid, &TerminalTypeGuid[0])) {
+ *Termi = PC_ANSI;
+ IsTerminal = TRUE;
+ } else {
+ if (CompareGuid (&TempGuid, &TerminalTypeGuid[1])) {
+ *Termi = VT_100;
+ IsTerminal = TRUE;
+ } else {
+ if (CompareGuid (&TempGuid, &TerminalTypeGuid[2])) {
+ *Termi = VT_100_PLUS;
+ IsTerminal = TRUE;
+ } else {
+ if (CompareGuid (&TempGuid, &TerminalTypeGuid[3])) {
+ *Termi = VT_UTF8;
+ IsTerminal = TRUE;
+ } else {
+ IsTerminal = FALSE;
+ }
+ }
+ }
+ }
+
+ if (!IsTerminal) {
+ return FALSE;
+ }
+
+ Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);
+ Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;
+ Match = EISA_PNP_ID (0x0501);
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
+ 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;
+ CONSOLE_OUT_MODE *ModeInfo;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
+
+ ConOut = gST->ConOut;
+ MaxMode = (UINTN) (ConOut->Mode->MaxMode);
+ ModeInfo = EfiLibGetVariable (VAR_CON_OUT_MODE, &gEfiGenericPlatformVariableGuid);
+
+ if (ModeInfo != NULL) {
+ CurrentCol = ModeInfo->Column;
+ CurrentRow = ModeInfo->Row;
+ 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;
+ }
+ }
+ }
+ FreePool (ModeInfo);
+ }
+}
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c
new file mode 100644
index 0000000000..5a22e77a9a
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c
@@ -0,0 +1,315 @@
+/** @file
+ Define some data used for Boot Maint
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "BootMaint.h"
+
+EFI_HII_UPDATE_DATA gUpdateData;
+STRING_DEPOSITORY *FileOptionStrDepository;
+STRING_DEPOSITORY *ConsoleOptionStrDepository;
+STRING_DEPOSITORY *BootOptionStrDepository;
+STRING_DEPOSITORY *BootOptionHelpStrDepository;
+STRING_DEPOSITORY *DriverOptionStrDepository;
+STRING_DEPOSITORY *DriverOptionHelpStrDepository;
+STRING_DEPOSITORY *TerminalStrDepository;
+
+///
+/// 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),
+};
+
+///
+/// File system selection menu
+///
+BM_MENU_OPTION FsOptionMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ {NULL},
+ 0
+};
+
+///
+/// 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
+};
+
+///
+/// Legacy FD Info from LegacyBios.GetBbsInfo()
+///
+BM_MENU_OPTION LegacyFDMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ {NULL},
+ 0
+};
+
+///
+/// Legacy HD Info from LegacyBios.GetBbsInfo()
+///
+BM_MENU_OPTION LegacyHDMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ {NULL},
+ 0
+};
+
+///
+/// Legacy CD Info from LegacyBios.GetBbsInfo()
+///
+BM_MENU_OPTION LegacyCDMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ {NULL},
+ 0
+};
+
+///
+/// Legacy NET Info from LegacyBios.GetBbsInfo()
+///
+BM_MENU_OPTION LegacyNETMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ {NULL},
+ 0
+};
+
+///
+/// Legacy NET Info from LegacyBios.GetBbsInfo()
+///
+BM_MENU_OPTION LegacyBEVMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ {NULL},
+ 0
+};
+
+///
+/// Files and sub-directories in current directory menu
+///
+BM_MENU_OPTION DirectoryMenu = {
+ 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[4] = {
+ DEVICE_PATH_MESSAGING_PC_ANSI,
+ DEVICE_PATH_MESSAGING_VT_100,
+ DEVICE_PATH_MESSAGING_VT_100_PLUS,
+ DEVICE_PATH_MESSAGING_VT_UTF8
+};
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr
new file mode 100644
index 0000000000..b89cf114cd
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr
@@ -0,0 +1,126 @@
+///** @file
+//
+// File Explorer Formset
+//
+// Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+// All rights reserved. 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"
+
+#define LABEL_END 0xffff
+
+formset
+ guid = FILE_EXPLORE_FORMSET_GUID,
+ title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ class = 0,
+ subclass = 0,
+
+ varstore FILE_EXPLORER_NV_DATA,
+ varid = VARSTORE_ID_BOOT_MAINT,
+ name = FeData,
+ guid = FILE_EXPLORE_FORMSET_GUID;
+
+ form formid = FORM_FILE_EXPLORER_ID,
+ title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE);
+
+ label FORM_FILE_EXPLORER_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_BOOT_ADD_DESCRIPTION_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_DESC_TITLE);
+
+ label FORM_BOOT_ADD_DESCRIPTION_ID;
+ label LABEL_END;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ string varid = FeData.DescriptionData,
+ prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ minsize = 6,
+ maxsize = 75,
+ endstring;
+
+ string varid = FeData.OptionalData,
+ prompt = STRING_TOKEN(STR_OPTIONAL_DATA),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ 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),
+ text = STRING_TOKEN(STR_NULL_STRING),
+ 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),
+ text = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_NO_SAVE_AND_EXIT_BOOT;
+
+ endform;
+
+ form formid = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);
+
+ label FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;
+ label LABEL_END;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ string varid = FeData.DescriptionData,
+ prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ minsize = 6,
+ maxsize = 75,
+ endstring;
+
+ string varid = FeData.OptionalData,
+ prompt = STRING_TOKEN(STR_OPTIONAL_DATA),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ minsize = 0,
+ maxsize = 120,
+ endstring;
+
+ checkbox varid = FeData.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),
+ text = STRING_TOKEN(STR_NULL_STRING),
+ 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),
+ text = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER;
+
+ endform;
+
+endformset; \ No newline at end of file
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c
new file mode 100644
index 0000000000..8253ded988
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c
@@ -0,0 +1,319 @@
+/** @file
+ File explorer related functions.
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "BootMaint.h"
+
+/**
+ Update the File Explore page.
+
+ @param CallbackData The BMM context data.
+ @param MenuOption Pointer to menu options to display.
+
+**/
+VOID
+UpdateFileExplorePage (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ BM_MENU_OPTION *MenuOption
+ )
+{
+ UINTN Index;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_FILE_CONTEXT *NewFileContext;
+ EFI_FORM_ID FormId;
+
+ NewMenuEntry = NULL;
+ NewFileContext = NULL;
+ FormId = 0;
+
+ RefreshUpdateData ();
+
+ for (Index = 0; Index < MenuOption->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);
+ NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;
+
+ if (NewFileContext->IsBootLegacy) {
+ continue;
+ }
+
+ if ((NewFileContext->IsDir) || (BOOT_FROM_FILE_STATE == CallbackData->FeCurrentState)) {
+ //
+ // Create Text opcode for directory, also create Text opcode for file in BOOT_FROM_FILE_STATE.
+ //
+ CreateActionOpCode (
+ (UINT16) (FILE_OPTION_OFFSET + Index),
+ NewMenuEntry->DisplayStringToken,
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ 0,
+ &gUpdateData
+ );
+ } else {
+ //
+ // Create Goto opcode for file in ADD_BOOT_OPTION_STATE or ADD_DRIVER_OPTION_STATE.
+ //
+ if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {
+ FormId = FORM_BOOT_ADD_DESCRIPTION_ID;
+ } else if (ADD_DRIVER_OPTION_STATE == CallbackData->FeCurrentState) {
+ FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;
+ }
+
+ CreateGotoOpCode (
+ FormId,
+ NewMenuEntry->DisplayStringToken,
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ (UINT16) (FILE_OPTION_OFFSET + Index),
+ &gUpdateData
+ );
+ }
+ }
+
+ IfrLibUpdateForm (
+ CallbackData->FeHiiHandle,
+ &mFileExplorerGuid,
+ FORM_FILE_EXPLORER_ID,
+ FORM_FILE_EXPLORER_ID,
+ FALSE,
+ &gUpdateData
+ );
+}
+
+/**
+ Update the file explower page with the refershed file system.
+
+
+ @param CallbackData BMM context data
+ @param KeyValue Key value to identify the type of data to expect.
+
+ @retval TRUE Inform the caller to create a callback packet to exit file explorer.
+ @retval FALSE Indicate that there is no need to exit file explorer.
+
+**/
+BOOLEAN
+UpdateFileExplorer (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN UINT16 KeyValue
+ )
+{
+ UINT16 FileOptionMask;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_FILE_CONTEXT *NewFileContext;
+ EFI_FORM_ID FormId;
+ BOOLEAN ExitFileExplorer;
+ EFI_STATUS Status;
+
+ NewMenuEntry = NULL;
+ NewFileContext = NULL;
+ ExitFileExplorer = FALSE;
+
+ FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue);
+
+ if (UNKNOWN_CONTEXT == CallbackData->FeDisplayContext) {
+ //
+ // First in, display file system.
+ //
+ BOpt_FreeMenu (&FsOptionMenu);
+ BOpt_FindFileSystem (CallbackData);
+ CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu);
+
+ UpdateFileExplorePage (CallbackData, &FsOptionMenu);
+
+ CallbackData->FeDisplayContext = FILE_SYSTEM;
+ } else {
+ if (FILE_SYSTEM == CallbackData->FeDisplayContext) {
+ NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask);
+ } else if (DIRECTORY == CallbackData->FeDisplayContext) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask);
+ }
+
+ CallbackData->FeDisplayContext = DIRECTORY;
+
+ NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;
+
+ if (NewFileContext->IsDir ) {
+ RemoveEntryList (&NewMenuEntry->Link);
+ BOpt_FreeMenu (&DirectoryMenu);
+ Status = BOpt_FindFiles (CallbackData, NewMenuEntry);
+ if (EFI_ERROR (Status)) {
+ ExitFileExplorer = TRUE;
+ goto exit;
+ }
+ CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &DirectoryMenu);
+ BOpt_DestroyMenuEntry (NewMenuEntry);
+
+ UpdateFileExplorePage (CallbackData, &DirectoryMenu);
+
+ } else {
+ switch (CallbackData->FeCurrentState) {
+ case BOOT_FROM_FILE_STATE:
+ //
+ // Here boot from file
+ //
+ BootThisFile (NewFileContext);
+ ExitFileExplorer = TRUE;
+ break;
+
+ case ADD_BOOT_OPTION_STATE:
+ case ADD_DRIVER_OPTION_STATE:
+ if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {
+ FormId = FORM_BOOT_ADD_DESCRIPTION_ID;
+ } else {
+ FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;
+ }
+
+ CallbackData->MenuEntry = NewMenuEntry;
+ CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath;
+
+ //
+ // Create Subtitle op-code for the display string of the option.
+ //
+ RefreshUpdateData ();
+
+ CreateSubTitleOpCode (
+ NewMenuEntry->DisplayStringToken,
+ 0,
+ 0,
+ 0,
+ &gUpdateData
+ );
+
+ IfrLibUpdateForm (
+ CallbackData->FeHiiHandle,
+ &mFileExplorerGuid,
+ FormId,
+ FormId,
+ FALSE,
+ &gUpdateData
+ );
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ exit:
+ return ExitFileExplorer;
+}
+
+/**
+ This function processes the results of changes in configuration.
+ When user select a interactive opcode, this callback will be triggered.
+ Based on the Question(QuestionId) that triggers the callback, the corresponding
+ actions is performed. It handles:
+
+ 1) the addition of boot option.
+ 2) the addition of driver option.
+ 3) exit from file browser
+ 4) update of file content if a dir is selected.
+ 5) boot the file if a file is selected in "boot from file"
+
+
+ @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 If paramter Value or ActionRequest is NULL.
+**/
+EFI_STATUS
+EFIAPI
+FileExplorerCallback (
+ 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;
+ FILE_EXPLORER_NV_DATA *NvRamMap;
+ EFI_STATUS Status;
+ UINTN BufferSize;
+
+ if ((Value == NULL) || (ActionRequest == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ Private = FE_CALLBACK_DATA_FROM_THIS (This);
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+
+ //
+ // Retrieve uncommitted data from Form Browser
+ //
+ NvRamMap = &Private->FeFakeNvData;
+ BufferSize = sizeof (FILE_EXPLORER_NV_DATA);
+ Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) NvRamMap);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) {
+ //
+ // Apply changes and exit formset
+ //
+ if (ADD_BOOT_OPTION_STATE == Private->FeCurrentState) {
+ Status = Var_UpdateBootOption (Private, NvRamMap);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BOpt_GetBootOptions (Private);
+ CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu);
+ } else if (ADD_DRIVER_OPTION_STATE == Private->FeCurrentState) {
+ Status = Var_UpdateDriverOption (
+ Private,
+ Private->FeHiiHandle,
+ NvRamMap->DescriptionData,
+ NvRamMap->OptionalData,
+ NvRamMap->ForceReconnect
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BOpt_GetDriverOptions (Private);
+ CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu);
+ }
+
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) {
+ //
+ // Discard changes and exit formset
+ //
+ NvRamMap->OptionalData[0] = 0x0000;
+ NvRamMap->DescriptionData[0] = 0x0000;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ } else if (QuestionId < FILE_OPTION_OFFSET) {
+ //
+ // Exit File Explorer formset
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ } else {
+ if (UpdateFileExplorer (Private, QuestionId)) {
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ }
+ }
+
+ return Status;
+}
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h
new file mode 100644
index 0000000000..2523d64c66
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h
@@ -0,0 +1,209 @@
+/** @file
+ Formset guids, form id and VarStore data structure for Boot Maintenance Manager.
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 FILE_EXPLORE_FORMSET_GUID \
+ { \
+ 0x1f2d63e1, 0xfebd, 0x4dc7, {0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c, 0x5b} \
+ }
+
+#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_RESET 0x1013
+#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_SET_FD_ORDER_ID 0x1019
+#define FORM_SET_HD_ORDER_ID 0x101A
+#define FORM_SET_CD_ORDER_ID 0x101B
+#define FORM_SET_NET_ORDER_ID 0x101C
+#define FORM_SET_BEV_ORDER_ID 0x101D
+#define FORM_FILE_EXPLORER_ID 0x101E
+#define FORM_BOOT_ADD_DESCRIPTION_ID 0x101F
+#define FORM_DRIVER_ADD_FILE_DESCRIPTION_ID 0x1020
+#define FORM_CON_MODE_ID 0x1021
+
+#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 MAXIMUM_NORMAL_KEY_VALUE 0x11FF
+
+//
+// Varstore ID defined for Buffer Stoarge
+//
+#define VARSTORE_ID_BOOT_MAINT 0x1000
+#define VARSTORE_ID_FILE_EXPLORER 0x1001
+
+///
+/// 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[100];
+ UINT16 DriverAddHandleOptionalData[100];
+ 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[100];
+
+ //
+ // Boot or Driver Option Order storage
+ //
+ UINT8 OptionOrder[100];
+ UINT8 DriverOptionToBeDeleted[100];
+
+ //
+ // Boot Option Delete storage
+ //
+ UINT8 BootOptionDel[100];
+ UINT8 DriverOptionDel[100];
+
+ //
+ // This is the Terminal Attributes value storage
+ //
+ UINT8 COMBaudRate;
+ UINT8 COMDataRate;
+ UINT8 COMStopBits;
+ UINT8 COMParity;
+ UINT8 COMTerminalType;
+
+ //
+ // Legacy Device Order Selection Storage
+ //
+ UINT8 LegacyFD[100];
+ UINT8 LegacyHD[100];
+ UINT8 LegacyCD[100];
+ UINT8 LegacyNET[100];
+ UINT8 LegacyBEV[100];
+
+ //
+ // 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];
+ //
+} BMM_FAKE_NV_DATA;
+
+//
+// Key used by File Explorer forms
+//
+#define KEY_VALUE_SAVE_AND_EXIT_BOOT 0x1000
+#define KEY_VALUE_NO_SAVE_AND_EXIT_BOOT 0x1001
+#define KEY_VALUE_SAVE_AND_EXIT_DRIVER 0x1002
+#define KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER 0x1003
+
+///
+/// This is the data structure used by File Explorer formset
+///
+typedef struct {
+ UINT16 DescriptionData[75];
+ UINT16 OptionalData[127];
+ UINT8 Active;
+ UINT8 ForceReconnect;
+} FILE_EXPLORER_NV_DATA;
+
+#endif
+
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c
new file mode 100644
index 0000000000..9fa2556cd5
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c
@@ -0,0 +1,1323 @@
+/** @file
+Dynamically update the pages.
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "BootMaint.h"
+
+/**
+ Refresh the global UpdateData structure.
+
+**/
+VOID
+RefreshUpdateData (
+ VOID
+ )
+{
+ gUpdateData.Offset = 0;
+}
+
+/**
+ 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 ();
+
+ 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.
+ //
+ CreateGotoOpCode (
+ FORM_MAIN_ID,
+ STRING_TOKEN (STR_FORM_GOTO_MAIN),
+ STRING_TOKEN (STR_FORM_GOTO_MAIN),
+ 0,
+ FORM_MAIN_ID,
+ &gUpdateData
+ );
+ }
+
+}
+
+/**
+ 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) {
+ CreateSubTitleOpCode (
+ STRING_TOKEN (STR_NULL_STRING),
+ 0,
+ 0,
+ 0,
+ &gUpdateData
+ );
+
+ CreateGotoOpCode (
+ FORM_MAIN_ID,
+ STRING_TOKEN (STR_SAVE_AND_EXIT),
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ KEY_VALUE_SAVE_AND_EXIT,
+ &gUpdateData
+ );
+ }
+
+ //
+ // Ensure user can return to the main page.
+ //
+ CreateGotoOpCode (
+ FORM_MAIN_ID,
+ STRING_TOKEN (STR_NO_SAVE_AND_EXIT),
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ KEY_VALUE_NO_SAVE_AND_EXIT,
+ &gUpdateData
+ );
+
+ IfrLibUpdateForm (
+ CallbackData->BmmHiiHandle,
+ &mBootMaintGuid,
+ CallbackData->BmmCurrentPageId,
+ CallbackData->BmmCurrentPageId,
+ FALSE,
+ &gUpdateData
+ );
+}
+
+/**
+ 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
+ //
+ IfrLibUpdateForm (
+ CallbackData->BmmHiiHandle,
+ &mBootMaintGuid,
+ LabelId,
+ LabelId,
+ FALSE,
+ &gUpdateData
+ );
+}
+
+/**
+ Boot a file selected by user at File Expoloer of BMM.
+
+ @param FileContext The file context data, which contains the device path
+ of the file to be boot from.
+
+ @retval EFI_SUCCESS The function completed successfull.
+ @return Other value if the boot from the file fails.
+
+**/
+EFI_STATUS
+BootThisFile (
+ IN BM_FILE_CONTEXT *FileContext
+ )
+{
+ EFI_STATUS Status;
+ UINTN ExitDataSize;
+ CHAR16 *ExitData;
+ BDS_COMMON_OPTION *Option;
+
+ Option = (BDS_COMMON_OPTION *) AllocatePool (sizeof (BDS_COMMON_OPTION));
+ ASSERT (Option != NULL);
+ Option->Description = FileContext->FileName;
+ Option->DevicePath = FileContext->DevicePath;
+ Option->LoadOptionsSize = 0;
+ Option->LoadOptions = NULL;
+
+ //
+ // Since current no boot from removable media directly is allowed */
+ //
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ ExitDataSize = 0;
+
+ Status = BdsLibBootViaBootOption (Option, Option->DevicePath, &ExitDataSize, &ExitData);
+
+ return Status;
+
+}
+
+/**
+ 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 = FALSE;
+
+ UpdatePageStart (CallbackData);
+
+
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+
+ CreateGotoOpCode (
+ FORM_CON_COM_SETUP_ID,
+ NewMenuEntry->DisplayStringToken,
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ (UINT16) (TERMINAL_OPTION_OFFSET + Index),
+ &gUpdateData
+ );
+ }
+
+ UpdatePageEnd (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
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT16 Index;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);
+
+ 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;
+ CallbackData->BmmFakeNvData.BootOptionDel[Index] = 0x00;
+
+ CreateCheckBoxOpCode (
+ (EFI_QUESTION_ID) (BOOT_OPTION_DEL_QUESTION_ID + Index),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (BOOT_OPTION_DEL_VAR_OFFSET + Index),
+ NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->HelpStringToken,
+ 0,
+ 0,
+ &gUpdateData
+ );
+ }
+
+ 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);
+
+ CreateGotoOpCode (
+ FORM_DRV_ADD_HANDLE_DESC_ID,
+ NewMenuEntry->DisplayStringToken,
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ (UINT16) (HANDLE_OPTION_OFFSET + Index),
+ &gUpdateData
+ );
+ }
+
+ 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);
+
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &DriverOptionMenu);
+
+ 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;
+ CallbackData->BmmFakeNvData.DriverOptionDel[Index] = 0x00;
+
+ CreateCheckBoxOpCode (
+ (EFI_QUESTION_ID) (DRIVER_OPTION_DEL_QUESTION_ID + Index),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (DRIVER_OPTION_DEL_VAR_OFFSET + Index),
+ NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->HelpStringToken,
+ 0,
+ 0,
+ &gUpdateData
+ );
+ }
+
+ 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);
+
+ CreateSubTitleOpCode (
+ NewMenuEntry->DisplayStringToken,
+ 0,
+ 0,
+ 0,
+ &gUpdateData
+ );
+
+ CreateStringOpCode (
+ (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,
+ &gUpdateData
+ );
+
+ CreateCheckBoxOpCode (
+ (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,
+ &gUpdateData
+ );
+
+ CreateStringOpCode (
+ (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,
+ &gUpdateData
+ );
+
+ 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;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ ASSERT (ConsoleMenu->MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.ConsoleCheck) / sizeof (CallbackData->BmmFakeNvData.ConsoleCheck[0])));
+ for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ CheckFlags = 0;
+ if (NewConsoleContext->IsActive) {
+ CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = TRUE;
+ } else {
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = FALSE;
+ }
+
+ CreateCheckBoxOpCode (
+ (EFI_QUESTION_ID) (CON_DEVICE_QUESTION_ID + Index),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (CON_DEVICE_VAR_OFFSET + Index),
+ NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->HelpStringToken,
+ 0,
+ CheckFlags,
+ &gUpdateData
+ );
+ }
+
+ for (Index2 = 0; Index2 < TerminalMenu.MenuNumber; Index2++) {
+ CheckFlags = 0;
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index2);
+ 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))
+ ) {
+ CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = TRUE;
+ } else {
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = FALSE;
+ }
+
+ CreateCheckBoxOpCode (
+ (EFI_QUESTION_ID) (CON_DEVICE_QUESTION_ID + Index),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (CON_DEVICE_VAR_OFFSET + Index),
+ NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->HelpStringToken,
+ 0,
+ CheckFlags,
+ &gUpdateData
+ );
+
+ Index++;
+ }
+
+ 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;
+ IFR_OPTION *IfrOptionList;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);
+
+ ZeroMem (CallbackData->BmmFakeNvData.OptionOrder, 100);
+
+ IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * OptionMenu->MenuNumber);
+ if (IfrOptionList == NULL) {
+ return ;
+ }
+
+ ASSERT (OptionMenu->MenuNumber <= (sizeof (IfrOptionList) / sizeof (IfrOptionList[0])));
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);
+ IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;
+ IfrOptionList[Index].Value.u8 = (UINT8) (NewMenuEntry->OptionNumber + 1);
+ IfrOptionList[Index].Flags = 0;
+ CallbackData->BmmFakeNvData.OptionOrder[Index] = IfrOptionList[Index].Value.u8;
+ }
+
+ if (OptionMenu->MenuNumber > 0) {
+ CreateOrderedListOpCode (
+ (EFI_QUESTION_ID) OPTION_ORDER_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ OPTION_ORDER_VAR_OFFSET,
+ STRING_TOKEN (STR_CHANGE_ORDER),
+ STRING_TOKEN (STR_CHANGE_ORDER),
+ 0,
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 100,
+ IfrOptionList,
+ OptionMenu->MenuNumber,
+ &gUpdateData
+ );
+ }
+
+ FreePool (IfrOptionList);
+
+ UpdatePageEnd (CallbackData);
+
+ CopyMem (
+ CallbackData->BmmOldFakeNVData.OptionOrder,
+ CallbackData->BmmFakeNvData.OptionOrder,
+ 100
+ );
+}
+
+/**
+ 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;
+ IFR_OPTION *IfrOptionList;
+ UINTN NumberOfOptions;
+ UINT16 Index;
+
+ IfrOptionList = NULL;
+ NumberOfOptions = BootOptionMenu.MenuNumber;
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);
+
+ if (NumberOfOptions > 0) {
+ IfrOptionList = AllocateZeroPool ((NumberOfOptions + 1) * sizeof (IFR_OPTION));
+
+ ASSERT (IfrOptionList);
+
+ 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) {
+ IfrOptionList[Index].Flags = EFI_IFR_OPTION_DEFAULT;
+ CallbackData->BmmFakeNvData.BootNext = Index;
+ } else {
+ IfrOptionList[Index].Flags = 0;
+ }
+
+ IfrOptionList[Index].Value.u16 = Index;
+ IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;
+ }
+
+ IfrOptionList[Index].Value.u16 = Index;
+ IfrOptionList[Index].StringToken = STRING_TOKEN (STR_NONE);
+ IfrOptionList[Index].Flags = 0;
+ if (CallbackData->BmmFakeNvData.BootNext == Index) {
+ IfrOptionList[Index].Flags |= EFI_IFR_OPTION_DEFAULT;
+ }
+
+ CreateOneOfOpCode (
+ (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,
+ IfrOptionList,
+ (UINTN) (NumberOfOptions + 1),
+ &gUpdateData
+ );
+
+ FreePool (IfrOptionList);
+ }
+
+ 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
+ )
+{
+ UINT16 BootTimeOut;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ BootTimeOut = BdsLibGetTimeout ();
+
+ CreateNumericOpCode (
+ (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,
+ BootTimeOut,
+ &gUpdateData
+ );
+
+ CallbackData->BmmFakeNvData.BootTimeOut = BootTimeOut;
+
+ 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 RowString[50];
+ CHAR16 ModeString[50];
+ UINTN MaxMode;
+ UINTN ValidMode;
+ EFI_STRING_ID *ModeToken;
+ IFR_OPTION *IfrOptionList;
+ EFI_STATUS Status;
+ 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;
+ }
+
+ IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * ValidMode);
+ ASSERT(IfrOptionList != 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);
+ ASSERT ((StrLen (ModeString) + 1) < (sizeof (ModeString) / sizeof (ModeString[0])));
+ StrCat (ModeString, L" x ");
+ UnicodeValueToString (RowString, 0, Row, 0);
+ ASSERT ((StrLen (ModeString) + StrLen(RowString)) < (sizeof (ModeString) / sizeof (ModeString[0])));
+ StrCat (ModeString, RowString);
+
+ HiiLibNewString (CallbackData->BmmHiiHandle, &ModeToken[Index], ModeString);
+
+ IfrOptionList[Index].StringToken = ModeToken[Index];
+ IfrOptionList[Index].Value.u16 = (UINT16) Mode;
+ if (Mode == CallbackData->BmmFakeNvData.ConsoleOutMode) {
+ IfrOptionList[Index].Flags = EFI_IFR_OPTION_DEFAULT;
+ } else {
+ IfrOptionList[Index].Flags = 0;
+ }
+ Index++;
+ }
+
+ CreateOneOfOpCode (
+ (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,
+ IfrOptionList,
+ ValidMode,
+ &gUpdateData
+ );
+ FreePool (IfrOptionList);
+ 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;
+ IFR_OPTION *IfrOptionList;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ NewMenuEntry = BOpt_GetMenuEntry (
+ &TerminalMenu,
+ CallbackData->CurrentTerminal
+ );
+
+ if (NewMenuEntry == NULL) {
+ return ;
+ }
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+
+ IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 19);
+ if (IfrOptionList == NULL) {
+ return ;
+ }
+
+ for (Index = 0; Index < sizeof (BaudRateList) / sizeof (BaudRateList [0]); Index++) {
+ CheckFlags = 0;
+ if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[Index].Value)) {
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ NewTerminalContext->BaudRateIndex = Index;
+ CallbackData->BmmFakeNvData.COMBaudRate = NewTerminalContext->BaudRateIndex;
+ }
+
+ IfrOptionList[Index].Flags = CheckFlags;
+ IfrOptionList[Index].StringToken = BaudRateList[Index].StringToken;
+ IfrOptionList[Index].Value.u8 = Index;
+ }
+
+ CreateOneOfOpCode (
+ (EFI_QUESTION_ID) COM_BAUD_RATE_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ COM_BAUD_RATE_VAR_OFFSET,
+ STRING_TOKEN (STR_COM_BAUD_RATE),
+ STRING_TOKEN (STR_COM_BAUD_RATE),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ 19,
+ &gUpdateData
+ );
+
+ for (Index = 0; Index < sizeof (DataBitsList) / sizeof (DataBitsList[0]); Index++) {
+ CheckFlags = 0;
+
+ if (NewTerminalContext->DataBits == DataBitsList[Index].Value) {
+ NewTerminalContext->DataBitsIndex = Index;
+ CallbackData->BmmFakeNvData.COMDataRate = NewTerminalContext->DataBitsIndex;
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ }
+
+ IfrOptionList[Index].Flags = CheckFlags;
+ IfrOptionList[Index].StringToken = DataBitsList[Index].StringToken;
+ IfrOptionList[Index].Value.u8 = Index;
+ }
+
+ CreateOneOfOpCode (
+ (EFI_QUESTION_ID) COM_DATA_RATE_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ COM_DATA_RATE_VAR_OFFSET,
+ STRING_TOKEN (STR_COM_DATA_BITS),
+ STRING_TOKEN (STR_COM_DATA_BITS),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ 4,
+ &gUpdateData
+ );
+
+ for (Index = 0; Index < sizeof (ParityList) / sizeof (ParityList[0]); Index++) {
+ CheckFlags = 0;
+ if (NewTerminalContext->Parity == ParityList[Index].Value) {
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ NewTerminalContext->ParityIndex = (UINT8) Index;
+ CallbackData->BmmFakeNvData.COMParity = NewTerminalContext->ParityIndex;
+ }
+
+ IfrOptionList[Index].Flags = CheckFlags;
+ IfrOptionList[Index].StringToken = ParityList[Index].StringToken;
+ IfrOptionList[Index].Value.u8 = Index;
+ }
+
+ CreateOneOfOpCode (
+ (EFI_QUESTION_ID) COM_PARITY_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ COM_PARITY_VAR_OFFSET,
+ STRING_TOKEN (STR_COM_PARITY),
+ STRING_TOKEN (STR_COM_PARITY),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ 5,
+ &gUpdateData
+ );
+
+ for (Index = 0; Index < sizeof (StopBitsList) / sizeof (StopBitsList[0]); Index++) {
+ CheckFlags = 0;
+ if (NewTerminalContext->StopBits == StopBitsList[Index].Value) {
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ NewTerminalContext->StopBitsIndex = (UINT8) Index;
+ CallbackData->BmmFakeNvData.COMStopBits = NewTerminalContext->StopBitsIndex;
+ }
+
+ IfrOptionList[Index].Flags = CheckFlags;
+ IfrOptionList[Index].StringToken = StopBitsList[Index].StringToken;
+ IfrOptionList[Index].Value.u8 = Index;
+ }
+
+ CreateOneOfOpCode (
+ (EFI_QUESTION_ID) COM_STOP_BITS_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ COM_STOP_BITS_VAR_OFFSET,
+ STRING_TOKEN (STR_COM_STOP_BITS),
+ STRING_TOKEN (STR_COM_STOP_BITS),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ 3,
+ &gUpdateData
+ );
+
+ for (Index = 0; Index < 4; Index++) {
+ CheckFlags = 0;
+ if (NewTerminalContext->TerminalType == Index) {
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ CallbackData->BmmFakeNvData.COMTerminalType = NewTerminalContext->TerminalType;
+ }
+
+ IfrOptionList[Index].Flags = CheckFlags;
+ IfrOptionList[Index].StringToken = (EFI_STRING_ID) TerminalType[Index];
+ IfrOptionList[Index].Value.u8 = Index;
+ }
+
+ CreateOneOfOpCode (
+ (EFI_QUESTION_ID) COM_TERMINAL_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ COM_TERMINAL_VAR_OFFSET,
+ STRING_TOKEN (STR_COM_TERMI_TYPE),
+ STRING_TOKEN (STR_COM_TERMI_TYPE),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ 4,
+ &gUpdateData
+ );
+
+ FreePool (IfrOptionList);
+
+ UpdatePageEnd (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
+ )
+{
+ 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;
+ }
+}
+
+/**
+ 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
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ VOID *OptionBuffer;
+ UINTN OrderSize;
+ UINTN Index;
+ UINT16 *OrderBuffer;
+ CHAR16 StrTemp[100];
+ UINT16 FilePathSize;
+ UINT8 *Ptr;
+ UINT8 *OptionalData;
+
+ //
+ // Get Boot Option number from the size of BootOrder
+ //
+ OrderBuffer = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &OrderSize
+ );
+
+ if (OrderBuffer == NULL) {
+ return NULL;
+ }
+
+ for (Index = 0; Index < OrderSize / sizeof (UINT16); Index++) {
+ UnicodeSPrint (StrTemp, 100, L"Boot%04x", OrderBuffer[Index]);
+ OptionBuffer = BdsLibGetVariableAndSize (
+ StrTemp,
+ &gEfiGlobalVariableGuid,
+ OptionSize
+ );
+ if (NULL == OptionBuffer) {
+ continue;
+ }
+
+ Ptr = (UINT8 *) OptionBuffer;
+ Ptr += sizeof (UINT32);
+
+ FilePathSize = *(UINT16 *) Ptr;
+ Ptr += sizeof (UINT16);
+
+ Ptr += StrSize ((CHAR16 *) Ptr);
+
+ //
+ // Now Ptr point to Device Path
+ //
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
+ Ptr += FilePathSize;
+
+ //
+ // Now Ptr point to Optional Data
+ //
+ OptionalData = Ptr;
+
+ if ((DeviceType == ((BBS_TABLE *) OptionalData)->DeviceType) &&
+ (BBS_DEVICE_PATH == DevicePath->Type) &&
+ (BBS_BBS_DP == DevicePath->SubType)
+ ) {
+ *OptionIndex = OrderBuffer[Index];
+ FreePool (OrderBuffer);
+ return OptionBuffer;
+ } else {
+ FreePool (OptionBuffer);
+ }
+ }
+
+ FreePool (OrderBuffer);
+ return NULL;
+}
+
+/**
+ Create a dynamic page so that Legacy Device boot order
+ can be set for specified device type.
+
+ @param UpdatePageId The form ID. It also spefies the legacy device type.
+ @param CallbackData The BMM context data.
+
+
+**/
+VOID
+UpdateSetLegacyDeviceOrderPage (
+ IN UINT16 UpdatePageId,
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;
+ BM_MENU_OPTION *OptionMenu;
+ BM_MENU_ENTRY *NewMenuEntry;
+ IFR_OPTION *IfrOptionList;
+ EFI_STRING_ID StrRef;
+ EFI_STRING_ID StrRefHelp;
+ BBS_TYPE BbsType;
+ UINTN VarSize;
+ UINTN Pos;
+ UINTN Bit;
+ UINT16 Index;
+ UINT16 Key;
+ CHAR16 String[100];
+ CHAR16 *TypeStr;
+ CHAR16 *TypeStrHelp;
+ UINT16 VarDevOrder;
+ UINT8 *VarData;
+ UINT8 *LegacyOrder;
+ UINT8 *OldData;
+ UINT8 *DisMap;
+
+ OptionMenu = NULL;
+ Key = 0;
+ StrRef = 0;
+ StrRefHelp = 0;
+ TypeStr = NULL;
+ TypeStrHelp = NULL;
+ BbsType = BBS_FLOPPY;
+ LegacyOrder = NULL;
+ OldData = NULL;
+ DisMap = NULL;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+ UpdatePageStart (CallbackData);
+
+ DisMap = CallbackData->BmmOldFakeNVData.DisableMap;
+
+ SetMem (DisMap, 32, 0);
+ //
+ // Create oneof option list
+ //
+ switch (UpdatePageId) {
+ case FORM_SET_FD_ORDER_ID:
+ OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;
+ Key = (UINT16) LEGACY_FD_QUESTION_ID;
+ TypeStr = STR_FLOPPY;
+ TypeStrHelp = STR_FLOPPY_HELP;
+ BbsType = BBS_FLOPPY;
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD;
+ OldData = CallbackData->BmmOldFakeNVData.LegacyFD;
+ break;
+
+ case FORM_SET_HD_ORDER_ID:
+ OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;
+ Key = (UINT16) LEGACY_HD_QUESTION_ID;
+ TypeStr = STR_HARDDISK;
+ TypeStrHelp = STR_HARDDISK_HELP;
+ BbsType = BBS_HARDDISK;
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD;
+ OldData = CallbackData->BmmOldFakeNVData.LegacyHD;
+ break;
+
+ case FORM_SET_CD_ORDER_ID:
+ OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;
+ Key = (UINT16) LEGACY_CD_QUESTION_ID;
+ TypeStr = STR_CDROM;
+ TypeStrHelp = STR_CDROM_HELP;
+ BbsType = BBS_CDROM;
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD;
+ OldData = CallbackData->BmmOldFakeNVData.LegacyCD;
+ break;
+
+ case FORM_SET_NET_ORDER_ID:
+ OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;
+ Key = (UINT16) LEGACY_NET_QUESTION_ID;
+ TypeStr = STR_NET;
+ TypeStrHelp = STR_NET_HELP;
+ BbsType = BBS_EMBED_NETWORK;
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET;
+ OldData = CallbackData->BmmOldFakeNVData.LegacyNET;
+ break;
+
+ case FORM_SET_BEV_ORDER_ID:
+ OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;
+ Key = (UINT16) LEGACY_BEV_QUESTION_ID;
+ TypeStr = STR_BEV;
+ TypeStrHelp = STR_BEV_HELP;
+ BbsType = BBS_BEV_DEVICE;
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV;
+ OldData = CallbackData->BmmOldFakeNVData.LegacyBEV;
+ break;
+
+ default:
+ DEBUG ((EFI_D_ERROR, "Invalid command ID for updating page!\n"));
+ return;
+ }
+
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);
+
+ IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * (OptionMenu->MenuNumber + 1));
+ if (NULL == IfrOptionList) {
+ return ;
+ }
+
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);
+ IfrOptionList[Index].Flags = 0;
+ if (0 == Index) {
+ IfrOptionList[Index].Flags |= EFI_IFR_OPTION_DEFAULT;
+ }
+
+ IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;
+ IfrOptionList[Index].Value.u8 = (UINT8) ((BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->Index;
+ }
+ //
+ // for item "Disabled"
+ //
+ IfrOptionList[Index].Flags = 0;
+ IfrOptionList[Index].StringToken = STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE);
+ IfrOptionList[Index].Value.u8 = 0xFF;
+
+ //
+ // Get Device Order from variable
+ //
+ VarData = BdsLibGetVariableAndSize (
+ VAR_LEGACY_DEV_ORDER,
+ &EfiLegacyDevOrderGuid,
+ &VarSize
+ );
+
+ if (NULL != VarData) {
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
+ while (VarData < VarData + VarSize) {
+ if (DevOrder->BbsType == BbsType) {
+ break;
+ }
+
+ VarData += sizeof (BBS_TYPE);
+ VarData += *(UINT16 *) VarData;
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
+ }
+ //
+ // Create oneof tag here for FD/HD/CD #1 #2
+ //
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
+ //
+ // Create the string for oneof tag
+ //
+ UnicodeSPrint (String, sizeof (String), TypeStr, Index);
+ StrRef = 0;
+ HiiLibNewString (CallbackData->BmmHiiHandle, &StrRef, String);
+
+ UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index);
+ StrRefHelp = 0;
+ HiiLibNewString (CallbackData->BmmHiiHandle, &StrRefHelp, String);
+
+ CreateOneOfOpCode (
+ (EFI_QUESTION_ID) (Key + Index),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (Key + Index - CONFIG_OPTION_OFFSET),
+ StrRef,
+ StrRefHelp,
+ EFI_IFR_FLAG_CALLBACK,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ OptionMenu->MenuNumber + 1,
+ &gUpdateData
+ );
+
+ VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16));
+
+ if (0xFF00 == (VarDevOrder & 0xFF00)) {
+ LegacyOrder[Index] = 0xFF;
+ Pos = (VarDevOrder & 0xFF) / 8;
+ Bit = 7 - ((VarDevOrder & 0xFF) % 8);
+ DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
+ } else {
+ LegacyOrder[Index] = (UINT8) (VarDevOrder & 0xFF);
+ }
+ }
+ }
+
+ CopyMem (OldData, LegacyOrder, 100);
+
+ if (IfrOptionList != NULL) {
+ FreePool (IfrOptionList);
+ IfrOptionList = NULL;
+ }
+
+ UpdatePageEnd (CallbackData);
+}
+
+/**
+ 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/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c
new file mode 100644
index 0000000000..5cc7abcb5a
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c
@@ -0,0 +1,1417 @@
+/** @file
+ Variable operation that will be used by bootmaint
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "BootMaint.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
+ //
+ BootOrderList = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &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 EFI_STATUS other 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
+ //
+ DriverOrderList = BdsLibGetVariableAndSize (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ &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;
+
+ OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);
+ InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);
+ ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);
+ 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;
+
+ ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid);
+ 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) {
+ StrCpy (DescriptionData, 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 = DevicePathToStr (NewLoadContext->FilePathList);
+ NewMenuEntry->OptionNumber = Index;
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ DriverOptionStrDepository
+ );
+ HiiLibNewString (HiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);
+
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ DriverOptionHelpStrDepository
+ );
+ HiiLibNewString (HiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);
+
+ 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);
+ DriverOrderList = BdsLibGetVariableAndSize (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ &DriverOrderListSize
+ );
+ NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16));
+ ASSERT (NewDriverOrderList != 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++;
+
+ *DescriptionData = 0x0000;
+ *OptionalData = 0x0000;
+ 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.
+ @param NvRamMap The file explorer formset internal state.
+
+ @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,
+ IN FILE_EXPLORER_NV_DATA *NvRamMap
+ )
+{
+ 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;
+
+ OptionalDataExist = FALSE;
+
+ Index = BOpt_GetBootOptionNumber () ;
+ UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);
+
+ if (NvRamMap->DescriptionData[0] == 0x0000) {
+ StrCpy (NvRamMap->DescriptionData, BootString);
+ }
+
+ BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData);
+ BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+
+ if (NvRamMap->OptionalData[0] != 0x0000) {
+ OptionalDataExist = TRUE;
+ BufferSize += StrSize (NvRamMap->OptionalData);
+ }
+
+ 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->DescriptionData,
+ StrSize (NvRamMap->DescriptionData)
+ );
+
+ NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->DescriptionData));
+ ASSERT (NewLoadContext->Description != NULL);
+
+ NewMenuEntry->DisplayString = NewLoadContext->Description;
+ CopyMem (
+ NewLoadContext->Description,
+ (VOID *) Ptr,
+ StrSize (NvRamMap->DescriptionData)
+ );
+
+ Ptr += StrSize (NvRamMap->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 = DevicePathToStr (NewLoadContext->FilePathList);
+ NewMenuEntry->OptionNumber = Index;
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ BootOptionStrDepository
+ );
+ HiiLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);
+
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ BootOptionHelpStrDepository
+ );
+ HiiLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);
+
+ if (OptionalDataExist) {
+ Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+
+ CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData));
+ }
+
+ Status = gRT->SetVariable (
+ BootString,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BufferSize,
+ Buffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ BootOrderList = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderListSize
+ );
+
+ NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16));
+ ASSERT (NewBootOrderList != NULL);
+ CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);
+ NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;
+
+ if (BootOrderList != NULL) {
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
+ 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++;
+
+ NvRamMap->DescriptionData[0] = 0x0000;
+ NvRamMap->OptionalData[0] = 0x0000;
+ return EFI_SUCCESS;
+}
+
+/**
+ 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"
+ 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 *BootOrderList;
+ UINT16 *NewBootOrderList;
+ UINTN BootOrderListSize;
+
+ BootOrderList = NULL;
+ BootOrderListSize = 0;
+
+ //
+ // First check whether BootOrder is present in current configuration
+ //
+ BootOrderList = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderListSize
+ );
+
+ NewBootOrderList = AllocateZeroPool (BootOrderListSize);
+ if (NewBootOrderList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // If exists, delete it to hold new BootOrder
+ //
+ if (BootOrderList != NULL) {
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
+ FreePool (BootOrderList);
+ }
+
+ ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.OptionOrder) / sizeof (CallbackData->BmmFakeNvData.OptionOrder[0])));
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewBootOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);
+ }
+
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BootOrderListSize,
+ NewBootOrderList
+ );
+ FreePool (NewBootOrderList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BOpt_FreeMenu (&BootOptionMenu);
+ BOpt_GetBootOptions (CallbackData);
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ 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
+ //
+ DriverOrderList = BdsLibGetVariableAndSize (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ &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 (DriverOrderListSize <= (sizeof (CallbackData->BmmFakeNvData.OptionOrder) / sizeof (CallbackData->BmmFakeNvData.OptionOrder[0])));
+ for (Index = 0; Index < DriverOrderListSize; Index++) {
+ NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[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 legacy BBS boot option. L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable
+ is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid
+ is also updated.
+
+ @param CallbackData The context data for BMM.
+
+ @return EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND If L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable can be found.
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource
+**/
+EFI_STATUS
+Var_UpdateBBSOption (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINTN Index;
+ UINTN Index2;
+ VOID *BootOptionVar;
+ CHAR16 VarName[100];
+ UINTN OptionSize;
+ UINT8 *Ptr;
+ EFI_STATUS Status;
+ CHAR16 DescString[100];
+ CHAR8 DescAsciiString[100];
+ UINTN NewOptionSize;
+ UINT8 *NewOptionPtr;
+ UINT8 *TempPtr;
+ UINT32 *Attribute;
+ BM_MENU_OPTION *OptionMenu;
+ BM_LEGACY_DEVICE_CONTEXT *LegacyDeviceContext;
+ UINT8 *LegacyDev;
+ UINT8 *VarData;
+ UINTN VarSize;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;
+ UINT8 *OriginalPtr;
+ UINT8 *DisMap;
+ UINTN Pos;
+ UINTN Bit;
+ UINT16 *NewOrder;
+ UINT16 Tmp;
+
+ LegacyDeviceContext = NULL;
+ DisMap = NULL;
+ NewOrder = NULL;
+
+ if (FORM_SET_FD_ORDER_ID == CallbackData->BmmPreviousPageId) {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyFD;
+ CallbackData->BbsType = BBS_FLOPPY;
+ } else {
+ if (FORM_SET_HD_ORDER_ID == CallbackData->BmmPreviousPageId) {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyHD;
+ CallbackData->BbsType = BBS_HARDDISK;
+ } else {
+ if (FORM_SET_CD_ORDER_ID == CallbackData->BmmPreviousPageId) {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyCD;
+ CallbackData->BbsType = BBS_CDROM;
+ } else {
+ if (FORM_SET_NET_ORDER_ID == CallbackData->BmmPreviousPageId) {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyNET;
+ CallbackData->BbsType = BBS_EMBED_NETWORK;
+ } else {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyBEV;
+ CallbackData->BbsType = BBS_BEV_DEVICE;
+ }
+ }
+ }
+ }
+
+ DisMap = CallbackData->BmmOldFakeNVData.DisableMap;
+ Status = EFI_SUCCESS;
+
+ //
+ // Find the first device's context
+ // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext
+ // because we just use it to fill the desc string, and user can not see the string in UI
+ //
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);
+ LegacyDeviceContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;
+ if (0xFF != LegacyDev[0] && LegacyDev[0] == LegacyDeviceContext->Index) {
+ DEBUG ((DEBUG_ERROR, "DescStr: %s\n", LegacyDeviceContext->Description));
+ break;
+ }
+ }
+ //
+ // Update the Variable "LegacyDevOrder"
+ //
+ VarData = (UINT8 *) BdsLibGetVariableAndSize (
+ VAR_LEGACY_DEV_ORDER,
+ &EfiLegacyDevOrderGuid,
+ &VarSize
+ );
+
+ if (VarData == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ OriginalPtr = VarData;
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
+
+ while (VarData < VarData + VarSize) {
+ if (DevOrder->BbsType == CallbackData->BbsType) {
+ break;
+ }
+
+ VarData += sizeof (BBS_TYPE);
+ VarData += *(UINT16 *) VarData;
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
+ }
+
+ if (VarData >= VarData + VarSize) {
+ FreePool (OriginalPtr);
+ return EFI_NOT_FOUND;
+ }
+
+ NewOrder = (UINT16 *) AllocateZeroPool (DevOrder->Length - sizeof (UINT16));
+ if (NewOrder == NULL) {
+ FreePool (VarData);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
+ if (0xFF == LegacyDev[Index]) {
+ break;
+ }
+
+ NewOrder[Index] = LegacyDev[Index];
+ }
+ //
+ // Only the enable/disable state of each boot device with same device type can be changed,
+ // so we can count on the index information in DevOrder.
+ // DisMap bit array is the only reliable source to check a device's en/dis state,
+ // so we use DisMap to set en/dis state of each item in NewOrder array
+ //
+ for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {
+ Tmp = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index2 * sizeof (UINT16));
+ Tmp &= 0xFF;
+ Pos = Tmp / 8;
+ Bit = 7 - (Tmp % 8);
+ if ((DisMap[Pos] & (1 << Bit)) != 0) {
+ NewOrder[Index] = (UINT16) (0xFF00 | Tmp);
+ Index++;
+ }
+ }
+
+ CopyMem (
+ (UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16),
+ NewOrder,
+ DevOrder->Length - sizeof (UINT16)
+ );
+ FreePool (NewOrder);
+
+ Status = gRT->SetVariable (
+ VAR_LEGACY_DEV_ORDER,
+ &EfiLegacyDevOrderGuid,
+ VAR_FLAG,
+ VarSize,
+ OriginalPtr
+ );
+
+ FreePool (OriginalPtr);
+
+ //
+ // Update Optional Data of Boot####
+ //
+ BootOptionVar = GetLegacyBootOptionVar (CallbackData->BbsType, &Index, &OptionSize);
+
+ if (BootOptionVar != NULL) {
+ CopyMem (
+ DescString,
+ LegacyDeviceContext->Description,
+ StrSize (LegacyDeviceContext->Description)
+ );
+
+ UnicodeStrToAsciiStr((CONST CHAR16*)&DescString, (CHAR8 *)&DescAsciiString);
+
+ NewOptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescString) +
+ sizeof (BBS_BBS_DEVICE_PATH);
+ NewOptionSize += AsciiStrLen (DescAsciiString) +
+ END_DEVICE_PATH_LENGTH + sizeof (BBS_TABLE) + sizeof (UINT16);
+
+ UnicodeSPrint (VarName, 100, L"Boot%04x", Index);
+
+ Ptr = BootOptionVar;
+
+ Attribute = (UINT32 *) Ptr;
+ *Attribute |= LOAD_OPTION_ACTIVE;
+ if (LegacyDev[0] == 0xFF) {
+ //
+ // Disable this legacy boot option
+ //
+ *Attribute &= ~LOAD_OPTION_ACTIVE;
+ }
+
+ Ptr += sizeof (UINT32);
+
+ Ptr += sizeof (UINT16);
+ Ptr += StrSize ((CHAR16 *) Ptr);
+
+ NewOptionPtr = AllocateZeroPool (NewOptionSize);
+ if (NewOptionPtr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ TempPtr = NewOptionPtr;
+
+ //
+ // Attribute
+ //
+ CopyMem (
+ TempPtr,
+ BootOptionVar,
+ sizeof (UINT32)
+ );
+
+ TempPtr += sizeof (UINT32);
+
+ //
+ // BBS device path Length
+ //
+ *((UINT16 *) TempPtr) = (UINT16) (sizeof (BBS_BBS_DEVICE_PATH) +
+ AsciiStrLen (DescAsciiString) +
+ END_DEVICE_PATH_LENGTH);
+
+ TempPtr += sizeof (UINT16);
+
+ //
+ // Description string
+ //
+ CopyMem (
+ TempPtr,
+ DescString,
+ StrSize (DescString)
+ );
+
+ TempPtr += StrSize (DescString);
+
+ //
+ // BBS device path
+ //
+ CopyMem (
+ TempPtr,
+ Ptr,
+ sizeof (BBS_BBS_DEVICE_PATH)
+ );
+
+ CopyMem (
+ ((BBS_BBS_DEVICE_PATH*) TempPtr)->String,
+ DescAsciiString,
+ AsciiStrSize (DescAsciiString)
+ );
+
+ SetDevicePathNodeLength (
+ (EFI_DEVICE_PATH_PROTOCOL *) TempPtr,
+ sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString)
+ );
+
+ TempPtr += sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString);
+
+ //
+ // End node
+ //
+ CopyMem (
+ TempPtr,
+ EndDevicePath,
+ END_DEVICE_PATH_LENGTH
+ );
+ TempPtr += END_DEVICE_PATH_LENGTH;
+
+ //
+ // Now TempPtr point to optional data, i.e. Bbs Table
+ //
+ CopyMem (
+ TempPtr,
+ LegacyDeviceContext->BbsTable,
+ sizeof (BBS_TABLE)
+ );
+
+ //
+ // Now TempPtr point to BBS index
+ //
+ TempPtr += sizeof (BBS_TABLE);
+ *((UINT16 *) TempPtr) = (UINT16) LegacyDeviceContext->Index;
+
+ Status = gRT->SetVariable (
+ VarName,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ NewOptionSize,
+ NewOptionPtr
+ );
+
+ FreePool (NewOptionPtr);
+ FreePool (BootOptionVar);
+ }
+
+ BOpt_GetBootOptions (CallbackData);
+ return Status;
+}
+
+/**
+ 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)) {
+ ModeInfo.Column = 80;
+ ModeInfo.Row = 25;
+ }
+
+ Status = gRT->SetVariable (
+ VAR_CON_OUT_MODE,
+ &gEfiGenericPlatformVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ sizeof (CONSOLE_OUT_MODE),
+ &ModeInfo
+ );
+
+ return Status;
+}
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c
new file mode 100644
index 0000000000..a1612cd1b1
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c
@@ -0,0 +1,299 @@
+/** @file
+ The platform boot manager reference implementation
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "BootManager.h"
+
+UINT16 mKeyInput;
+EFI_GUID mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID;
+LIST_ENTRY *mBootOptionsList;
+BDS_COMMON_OPTION *gOption;
+
+BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = {
+ BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,
+ NULL,
+ NULL,
+ {
+ FakeExtractConfig,
+ FakeRouteConfig,
+ BootManagerCallback
+ }
+};
+
+/**
+ This call back funtion is registered with Boot Manager formset.
+ When user selects a boot option, this call back function will
+ be triggered. The boot option is saved for later processing.
+
+
+ @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_INVALID_PARAMETER The setup browser call this function with invalid parameters.
+
+**/
+EFI_STATUS
+EFIAPI
+BootManagerCallback (
+ 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
+ )
+{
+ BDS_COMMON_OPTION *Option;
+ LIST_ENTRY *Link;
+ UINT16 KeyCount;
+
+ if ((Value == NULL) || (ActionRequest == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Initialize the key count
+ //
+ KeyCount = 0;
+
+ for (Link = mBootOptionsList->ForwardLink; Link != mBootOptionsList; Link = Link->ForwardLink) {
+ Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
+
+ KeyCount++;
+
+ gOption = Option;
+
+ //
+ // Is this device the one chosen?
+ //
+ if (KeyCount == QuestionId) {
+ //
+ // Assigning the returned Key to a global allows the original routine to know what was chosen
+ //
+ mKeyInput = QuestionId;
+
+ //
+ // Request to exit SendForm(), so that we could boot the selected option
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Registers HII packages for the Boot Manger to HII Database.
+ It also registers the browser call back function.
+
+ @return Status of HiiLibCreateHiiDriverHandle() and gHiiDatabase->NewPackageList()
+
+**/
+EFI_STATUS
+InitializeBootManager (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&gBootManagerPrivate.DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install Config Access protocol to driver handle
+ //
+ Status = gBS->InstallProtocolInterface (
+ &gBootManagerPrivate.DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gBootManagerPrivate.ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Publish our HII data
+ //
+ PackageList = HiiLibPreparePackageList (2, &mBootManagerGuid, BootManagerVfrBin, BdsDxeStrings);
+ ASSERT (PackageList != NULL);
+
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ gBootManagerPrivate.DriverHandle,
+ &gBootManagerPrivate.HiiHandle
+ );
+ FreePool (PackageList);
+
+ return Status;
+}
+
+/**
+ This funtion invokees Boot Manager. If all devices have not a chance to be connected,
+ the connect all will be triggered. It then enumerate all boot options. If
+ a boot option from the Boot Manager page is selected, Boot Manager will boot
+ from this boot option.
+
+**/
+VOID
+CallBootManager (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BDS_COMMON_OPTION *Option;
+ LIST_ENTRY *Link;
+ EFI_HII_UPDATE_DATA UpdateData;
+ CHAR16 *ExitData;
+ UINTN ExitDataSize;
+ EFI_STRING_ID Token;
+ EFI_INPUT_KEY Key;
+ LIST_ENTRY BdsBootOptionList;
+ CHAR16 *HelpString;
+ EFI_STRING_ID HelpToken;
+ UINT16 *TempStr;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+ UINTN TempSize;
+
+ gOption = NULL;
+ InitializeListHead (&BdsBootOptionList);
+
+ //
+ // Connect all prior to entering the platform setup menu.
+ //
+ if (!gConnectAllHappened) {
+ BdsLibConnectAllDriversToAllControllers ();
+ gConnectAllHappened = TRUE;
+ }
+ //
+ // BugBug: Here we can not remove the legacy refresh macro, so we need
+ // get the boot order every time from "BootOrder" variable.
+ // Recreate the boot option list base on the BootOrder variable
+ //
+ BdsLibEnumerateAllBootOption (&BdsBootOptionList);
+
+ mBootOptionsList = &BdsBootOptionList;
+
+ HiiHandle = gBootManagerPrivate.HiiHandle;
+
+ //
+ // Allocate space for creation of UpdateData Buffer
+ //
+ UpdateData.BufferSize = 0x1000;
+ UpdateData.Offset = 0;
+ UpdateData.Data = AllocateZeroPool (0x1000);
+ ASSERT (UpdateData.Data != NULL);
+
+ mKeyInput = 0;
+
+ for (Link = BdsBootOptionList.ForwardLink; Link != &BdsBootOptionList; Link = Link->ForwardLink) {
+ Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
+
+ //
+ // At this stage we are creating a menu entry, thus the Keys are reproduceable
+ //
+ mKeyInput++;
+
+ //
+ // Don't display the boot option marked as LOAD_OPTION_HIDDEN
+ //
+ if (Option->Attribute & LOAD_OPTION_HIDDEN) {
+ continue;
+ }
+
+ HiiLibNewString (HiiHandle, &Token, Option->Description);
+
+ TempStr = DevicePathToStr (Option->DevicePath);
+ TempSize = StrSize (TempStr);
+ HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));
+ ASSERT (HelpString != NULL);
+ StrCat (HelpString, L"Device Path : ");
+ StrCat (HelpString, TempStr);
+
+ HiiLibNewString (HiiHandle, &HelpToken, HelpString);
+
+ CreateActionOpCode (
+ mKeyInput,
+ Token,
+ HelpToken,
+ EFI_IFR_FLAG_CALLBACK,
+ 0,
+ &UpdateData
+ );
+ }
+
+ IfrLibUpdateForm (
+ HiiHandle,
+ &mBootManagerGuid,
+ BOOT_MANAGER_FORM_ID,
+ LABEL_BOOT_OPTION,
+ FALSE,
+ &UpdateData
+ );
+ FreePool (UpdateData.Data);
+
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Status = gFormBrowser2->SendForm (
+ gFormBrowser2,
+ &HiiHandle,
+ 1,
+ NULL,
+ 0,
+ NULL,
+ &ActionRequest
+ );
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
+ EnableResetRequired ();
+ }
+
+ if (gOption == NULL) {
+ return ;
+ }
+
+ //
+ //Will leave browser, check any reset required change is applied? if yes, reset system
+ //
+ SetupResetReminder ();
+
+ //
+ // parse the selected option
+ //
+ Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);
+
+ if (!EFI_ERROR (Status)) {
+ gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
+ PlatformBdsBootSuccess (gOption);
+ } else {
+ gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
+ PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))
+ );
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ }
+}
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h
new file mode 100644
index 0000000000..4e460788a7
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h
@@ -0,0 +1,108 @@
+/** @file
+ The platform boot manager reference implement
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 _EFI_BOOT_MANAGER_H_
+#define _EFI_BOOT_MANAGER_H_
+
+#include "Bds.h"
+#include "FrontPage.h"
+
+//
+// These are defined as the same with vfr file
+//
+#define BOOT_MANAGER_FORMSET_GUID \
+ { \
+ 0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b} \
+ }
+
+#define BOOT_MANAGER_FORM_ID 0x1000
+
+#define LABEL_BOOT_OPTION 0x00
+
+//
+// These are the VFR compiler generated data representing our VFR data.
+//
+extern UINT8 BootManagerVfrBin[];
+
+#define BOOT_MANAGER_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('B', 'M', 'C', 'B')
+
+typedef struct {
+ UINTN Signature;
+
+ //
+ // HII relative handles
+ //
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HANDLE DriverHandle;
+
+ //
+ // Produced protocols
+ //
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+} BOOT_MANAGER_CALLBACK_DATA;
+
+/**
+ This call back funtion is registered with Boot Manager formset.
+ When user selects a boot option, this call back function will
+ be triggered. The boot option is saved for later processing.
+
+
+ @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_INVALID_PARAMETER The setup browser call this function with invalid parameters.
+
+**/
+EFI_STATUS
+EFIAPI
+BootManagerCallback (
+ 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
+ );
+
+/**
+
+ Registers HII packages for the Boot Manger to HII Database.
+ It also registers the browser call back function.
+
+ @return Status of HiiLibCreateHiiDriverHandle() and gHiiDatabase->NewPackageList()
+**/
+EFI_STATUS
+InitializeBootManager (
+ VOID
+ );
+
+/**
+ This funtion invokees Boot Manager. If all devices have not a chance to be connected,
+ the connect all will be triggered. It then enumerate all boot options. If
+ a boot option from the Boot Manager page is selected, Boot Manager will boot
+ from this boot option.
+
+**/
+VOID
+CallBootManager (
+ VOID
+ );
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni
new file mode 100644
index 0000000000..5a29d53761
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni
Binary files differ
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr
new file mode 100644
index 0000000000..a70966cf3c
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr
@@ -0,0 +1,51 @@
+///** @file
+//
+// Browser formset.
+//
+// Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+// All rights reserved. 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.
+//
+//**/
+
+#define FORMSET_GUID { 0x847bc3fe, 0xb974, 0x446d, 0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b }
+
+#define BOOT_MANAGER_FORM_ID 0x1000
+
+#define LABEL_BOOT_OPTION 0x00
+#define LABEL_BOOT_OPTION_END 0x01
+
+#define BOOT_MANAGER_CLASS 0x00
+#define BOOT_MANAGER_SUBCLASS 0x00
+
+formset
+ guid = FORMSET_GUID,
+ title = STRING_TOKEN(STR_BM_BANNER),
+ help = STRING_TOKEN(STR_LAST_STRING),
+ class = BOOT_MANAGER_CLASS,
+ subclass = BOOT_MANAGER_SUBCLASS,
+
+ form formid = BOOT_MANAGER_FORM_ID,
+ title = STRING_TOKEN(STR_BM_BANNER);
+
+ subtitle text = STRING_TOKEN(STR_LAST_STRING);
+ subtitle text = STRING_TOKEN(STR_BOOT_OPTION_BANNER);
+ subtitle text = STRING_TOKEN(STR_LAST_STRING);
+
+ //
+ // This is where we will dynamically add choices for the Boot Manager
+ //
+ label LABEL_BOOT_OPTION;
+ label LABEL_BOOT_OPTION_END;
+
+ subtitle text = STRING_TOKEN(STR_LAST_STRING);
+ subtitle text = STRING_TOKEN(STR_HELP_FOOTER);
+
+ endform;
+
+endformset;
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c b/IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c
new file mode 100644
index 0000000000..904a775493
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c
@@ -0,0 +1,257 @@
+/** @file
+ BDS routines to handle capsules.
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "Bds.h"
+
+/**
+ This function locks the block
+
+ @param CpuIo A instance of EFI_CPU_IO_PROTOCOL.
+ @param Base The base address flash region to be locked.
+
+**/
+VOID
+BdsLockFv (
+ IN EFI_CPU_IO_PROTOCOL *CpuIo,
+ IN EFI_PHYSICAL_ADDRESS Base
+ )
+{
+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT8 Data;
+ UINT32 BlockLength;
+ UINTN Index;
+
+ BaseAddress = Base - 0x400000 + 2;
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (Base));
+ BlockMap = &(FvHeader->BlockMap[0]);
+
+ while ((BlockMap->NumBlocks != 0) && (BlockMap->Length != 0)) {
+ BlockLength = BlockMap->Length;
+ for (Index = 0; Index < BlockMap->NumBlocks; Index++) {
+ CpuIo->Mem.Read (
+ CpuIo,
+ EfiCpuIoWidthUint8,
+ BaseAddress,
+ 1,
+ &Data
+ );
+ Data = (UINT8) (Data | 0x3);
+ CpuIo->Mem.Write (
+ CpuIo,
+ EfiCpuIoWidthUint8,
+ BaseAddress,
+ 1,
+ &Data
+ );
+ BaseAddress += BlockLength;
+ }
+
+ BlockMap++;
+ }
+}
+
+/**
+
+ This routine is called to see if there are any capsules we need to process.
+ If the boot mode is not UPDATE, then we do nothing. Otherwise find the
+ capsule HOBS and produce firmware volumes for them via the DXE service.
+ Then call the dispatcher to dispatch drivers from them. Finally, check
+ the status of the updates.
+
+ This function should be called by BDS in case we need to do some
+ sort of processing even if there is no capsule to process. We
+ need to do this if an earlier update went away and we need to
+ clear the capsule variable so on the next reset PEI does not see it and
+ think there is a capsule available.
+
+ @param BootMode the current boot mode
+
+ @retval EFI_INVALID_PARAMETER boot mode is not correct for an update
+ @retval EFI_SUCCESS There is no error when processing capsule
+
+**/
+EFI_STATUS
+ProcessCapsules (
+ EFI_BOOT_MODE BootMode
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS HobPointer;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+ UINT32 Size;
+ UINT32 CapsuleNumber;
+ UINT32 CapsuleTotalNumber;
+ EFI_CAPSULE_TABLE *CapsuleTable;
+ UINT32 Index;
+ UINT32 CacheIndex;
+ UINT32 CacheNumber;
+ VOID **CapsulePtr;
+ VOID **CapsulePtrCache;
+ EFI_GUID *CapsuleGuidCache;
+ CAPSULE_HOB_INFO *CapsuleHobInfo;
+
+ CapsuleNumber = 0;
+ CapsuleTotalNumber = 0;
+ CacheIndex = 0;
+ CacheNumber = 0;
+ CapsulePtr = NULL;
+ CapsulePtrCache = NULL;
+ CapsuleGuidCache = NULL;
+
+ //
+ // We don't do anything else if the boot mode is not flash-update
+ //
+ if (BootMode != BOOT_ON_FLASH_UPDATE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ //
+ // Find all capsule images from hob
+ //
+ HobPointer.Raw = GetHobList ();
+ while ((HobPointer.Raw = GetNextGuidHob (&gEfiCapsuleVendorGuid, HobPointer.Raw)) != NULL) {
+ CapsuleTotalNumber ++;
+
+ HobPointer.Raw = GET_NEXT_HOB (HobPointer);
+ }
+
+ if (CapsuleTotalNumber == 0) {
+ //
+ // We didn't find a hob, so had no errors.
+ //
+ PlatformBdsLockNonUpdatableFlash ();
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Init temp Capsule Data table.
+ //
+ CapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
+ ASSERT (CapsulePtr != NULL);
+ CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
+ ASSERT (CapsulePtrCache != NULL);
+ CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber);
+ ASSERT (CapsuleGuidCache != NULL);
+
+ //
+ // Find all capsule images from hob
+ //
+ HobPointer.Raw = GetHobList ();
+ while ((HobPointer.Raw = GetNextGuidHob (&gEfiCapsuleVendorGuid, HobPointer.Raw)) != NULL) {
+ CapsuleHobInfo = GET_GUID_HOB_DATA (HobPointer.Guid);
+ CapsulePtr [CapsuleNumber++] = (VOID *)(UINTN)(CapsuleHobInfo->BaseAddress);
+
+ HobPointer.Raw = GET_NEXT_HOB (HobPointer);
+ }
+
+ //
+ //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install
+ //capsuleTable to configure table with EFI_CAPSULE_GUID
+ //
+
+ //
+ // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating
+ // System to have information persist across a system reset. EFI System Table must
+ // point to an array of capsules that contains the same CapsuleGuid value. And agents
+ // searching for this type capsule will look in EFI System Table and search for the
+ // capsule's Guid and associated pointer to retrieve the data. Two steps below describes
+ // how to sorting the capsules by the unique guid and install the array to EFI System Table.
+ // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an
+ // array for later sorting capsules by CapsuleGuid.
+ //
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
+ //
+ // For each capsule, we compare it with known CapsuleGuid in the CacheArray.
+ // If already has the Guid, skip it. Whereas, record it in the CacheArray as
+ // an additional one.
+ //
+ CacheIndex = 0;
+ while (CacheIndex < CacheNumber) {
+ if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) {
+ break;
+ }
+ CacheIndex++;
+ }
+ if (CacheIndex == CacheNumber) {
+ CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID));
+ }
+ }
+ }
+
+ //
+ // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules
+ // whose guid is the same as it, and malloc memory for an array which preceding
+ // with UINT32. The array fills with entry point of capsules that have the same
+ // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install
+ // this array into EFI System Table, so that agents searching for this type capsule
+ // will look in EFI System Table and search for the capsule's Guid and associated
+ // pointer to retrieve the data.
+ //
+ CacheIndex = 0;
+ while (CacheIndex < CacheNumber) {
+ CapsuleNumber = 0;
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
+ if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {
+ //
+ // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.
+ //
+ CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;
+ }
+ }
+ }
+ if (CapsuleNumber != 0) {
+ Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*);
+ CapsuleTable = AllocateRuntimePool (Size);
+ ASSERT (CapsuleTable != NULL);
+ CapsuleTable->CapsuleArrayNumber = CapsuleNumber;
+ CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));
+ Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);
+ ASSERT_EFI_ERROR (Status);
+ }
+ CacheIndex++;
+ }
+
+ //
+ // Besides ones with CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag, all capsules left are
+ // recognized by platform with CapsuleGuid. For general platform driver, UpdateFlash
+ // type is commonly supported, so here only deal with encapsuled FVs capsule. Additional
+ // type capsule transaction could be extended. It depends on platform policy.
+ //
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {
+ //
+ // Call capsule library to process capsule image.
+ //
+ ProcessCapsuleImage (CapsuleHeader);
+ }
+ }
+
+ PlatformBdsLockNonUpdatableFlash ();
+
+ //
+ // Free the allocated temp memory space.
+ //
+ FreePool (CapsuleGuidCache);
+ FreePool (CapsulePtrCache);
+ FreePool (CapsulePtr);
+
+ return Status;
+}
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c
new file mode 100644
index 0000000000..715e1013e7
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c
@@ -0,0 +1,409 @@
+/** @file
+ The platform device manager reference implementation
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "DeviceManager.h"
+
+DEVICE_MANAGER_CALLBACK_DATA gDeviceManagerPrivate = {
+ DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE,
+ NULL,
+ NULL,
+ {
+ FakeExtractConfig,
+ FakeRouteConfig,
+ DeviceManagerCallback
+ }
+};
+
+EFI_GUID mDeviceManagerGuid = DEVICE_MANAGER_FORMSET_GUID;
+
+DEVICE_MANAGER_MENU_ITEM mDeviceManagerMenuItemTable[] = {
+ { STRING_TOKEN (STR_DISK_DEVICE), EFI_DISK_DEVICE_CLASS },
+ { STRING_TOKEN (STR_VIDEO_DEVICE), EFI_VIDEO_DEVICE_CLASS },
+ { STRING_TOKEN (STR_NETWORK_DEVICE), EFI_NETWORK_DEVICE_CLASS },
+ { STRING_TOKEN (STR_INPUT_DEVICE), EFI_INPUT_DEVICE_CLASS },
+ { STRING_TOKEN (STR_ON_BOARD_DEVICE), EFI_ON_BOARD_DEVICE_CLASS },
+ { STRING_TOKEN (STR_OTHER_DEVICE), EFI_OTHER_DEVICE_CLASS }
+};
+
+#define MENU_ITEM_NUM \
+ (sizeof (mDeviceManagerMenuItemTable) / sizeof (DEVICE_MANAGER_MENU_ITEM))
+
+/**
+ This function is invoked if user selected a iteractive opcode from Device Manager's
+ Formset. The decision by user is saved to gCallbackKey for later processing. If
+ user set VBIOS, the new value is saved to EFI variable.
+
+ @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_INVALID_PARAMETER The setup browser call this function with invalid parameters.
+
+**/
+EFI_STATUS
+EFIAPI
+DeviceManagerCallback (
+ 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
+ )
+{
+ DEVICE_MANAGER_CALLBACK_DATA *PrivateData;
+
+ if ((Value == NULL) || (ActionRequest == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS (This);
+
+ switch (QuestionId) {
+ case DEVICE_MANAGER_KEY_VBIOS:
+ PrivateData->VideoBios = Value->u8;
+ gRT->SetVariable (
+ L"VBIOS",
+ &gEfiGenericPlatformVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ sizeof (UINT8),
+ &PrivateData->VideoBios
+ );
+
+ //
+ // Tell browser not to ask for confirmation of changes,
+ // since we have already applied.
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
+ break;
+
+ default:
+ //
+ // The key corresponds the Handle Index which was requested to be displayed
+ //
+ gCallbackKey = QuestionId;
+
+ //
+ // Request to exit SendForm(), so as to switch to selected form
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function registers HII packages to HII database.
+
+ @retval EFI_SUCCESS This function complete successfully.
+ @return Other value if failed to register HII packages.
+
+**/
+EFI_STATUS
+InitializeDeviceManager (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&gDeviceManagerPrivate.DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install Config Access protocol to driver handle
+ //
+ Status = gBS->InstallProtocolInterface (
+ &gDeviceManagerPrivate.DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gDeviceManagerPrivate.ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Publish our HII data
+ //
+ PackageList = HiiLibPreparePackageList (2, &mDeviceManagerGuid, DeviceManagerVfrBin, BdsDxeStrings);
+ ASSERT (PackageList != NULL);
+
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ gDeviceManagerPrivate.DriverHandle,
+ &gDeviceManagerPrivate.HiiHandle
+ );
+ FreePool (PackageList);
+
+ return Status;
+}
+
+/**
+ Call the browser and display the device manager to allow user
+ to configure the platform.
+
+ This function create the dynamic content for device manager. It includes
+ section header for all class of devices, one-of opcode to set VBIOS.
+
+ @retval EFI_SUCCESS Operation is successful.
+ @return Other values if failed to clean up the dynamic content from HII
+ database.
+
+**/
+EFI_STATUS
+CallDeviceManager (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Count;
+ UINTN Index;
+ CHAR16 *String;
+ UINTN StringLength;
+ EFI_HII_UPDATE_DATA UpdateData[MENU_ITEM_NUM];
+ EFI_STRING_ID Token;
+ EFI_STRING_ID TokenHelp;
+ IFR_OPTION *IfrOptionList;
+ UINT8 *VideoOption;
+ UINTN VideoOptionSize;
+ EFI_HII_HANDLE *HiiHandles;
+ UINTN HandleBufferLength;
+ UINTN NumberOfHiiHandles;
+ EFI_HII_HANDLE HiiHandle;
+ UINT16 FormSetClass;
+ EFI_STRING_ID FormSetTitle;
+ EFI_STRING_ID FormSetHelp;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+
+ IfrOptionList = NULL;
+ VideoOption = NULL;
+ HiiHandles = NULL;
+ HandleBufferLength = 0;
+
+ Status = EFI_SUCCESS;
+ gCallbackKey = 0;
+
+ //
+ // Connect all prior to entering the platform setup menu.
+ //
+ if (!gConnectAllHappened) {
+ BdsLibConnectAllDriversToAllControllers ();
+ gConnectAllHappened = TRUE;
+ }
+
+ //
+ // Create Subtitle OpCodes
+ //
+ for (Index = 0; Index < MENU_ITEM_NUM; Index++) {
+ //
+ // Allocate space for creation of UpdateData Buffer
+ //
+ UpdateData[Index].BufferSize = 0x1000;
+ UpdateData[Index].Offset = 0;
+ UpdateData[Index].Data = AllocatePool (0x1000);
+ ASSERT (UpdateData[Index].Data != NULL);
+
+ CreateSubTitleOpCode (mDeviceManagerMenuItemTable[Index].StringId, 0, 0, 1, &UpdateData[Index]);
+ }
+
+ //
+ // Get all the Hii handles
+ //
+ Status = HiiLibGetHiiHandles (&HandleBufferLength, &HiiHandles);
+ ASSERT_EFI_ERROR (Status && (HiiHandles != NULL));
+
+ HiiHandle = gDeviceManagerPrivate.HiiHandle;
+
+ StringLength = 0x1000;
+ String = AllocateZeroPool (StringLength);
+ ASSERT (String != NULL);
+
+ //
+ // Search for formset of each class type
+ //
+ NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE);
+ for (Index = 0; Index < NumberOfHiiHandles; Index++) {
+ IfrLibExtractClassFromHiiHandle (HiiHandles[Index], &FormSetClass, &FormSetTitle, &FormSetHelp);
+
+ if (FormSetClass == EFI_NON_DEVICE_CLASS) {
+ continue;
+ }
+
+ Token = 0;
+ *String = 0;
+ StringLength = 0x1000;
+ HiiLibGetString (HiiHandles[Index], FormSetTitle, String, &StringLength);
+ HiiLibNewString (HiiHandle, &Token, String);
+
+ TokenHelp = 0;
+ *String = 0;
+ StringLength = 0x1000;
+ HiiLibGetString (HiiHandles[Index], FormSetHelp, String, &StringLength);
+ HiiLibNewString (HiiHandle, &TokenHelp, String);
+
+ for (Count = 0; Count < MENU_ITEM_NUM; Count++) {
+ if (FormSetClass & mDeviceManagerMenuItemTable[Count].Class) {
+ CreateActionOpCode (
+ (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET),
+ Token,
+ TokenHelp,
+ EFI_IFR_FLAG_CALLBACK,
+ 0,
+ &UpdateData[Count]
+ );
+ }
+ }
+ }
+ FreePool (String);
+
+ for (Index = 0; Index < MENU_ITEM_NUM; Index++) {
+ //
+ // Add End Opcode for Subtitle
+ //
+ CreateEndOpCode (&UpdateData[Index]);
+
+ IfrLibUpdateForm (
+ HiiHandle,
+ &mDeviceManagerGuid,
+ DEVICE_MANAGER_FORM_ID,
+ mDeviceManagerMenuItemTable[Index].Class,
+ FALSE,
+ &UpdateData[Index]
+ );
+ }
+
+ //
+ // Add oneof for video BIOS selection
+ //
+ VideoOption = BdsLibGetVariableAndSize (
+ L"VBIOS",
+ &gEfiGenericPlatformVariableGuid,
+ &VideoOptionSize
+ );
+ if (VideoOption == NULL) {
+ gDeviceManagerPrivate.VideoBios = 0;
+ } else {
+ gDeviceManagerPrivate.VideoBios = VideoOption[0];
+ FreePool (VideoOption);
+ }
+
+ ASSERT (gDeviceManagerPrivate.VideoBios <= 1);
+
+ IfrOptionList = AllocatePool (2 * sizeof (IFR_OPTION));
+ ASSERT (IfrOptionList != NULL);
+ IfrOptionList[0].Flags = 0;
+ IfrOptionList[0].StringToken = STRING_TOKEN (STR_ONE_OF_PCI);
+ IfrOptionList[0].Value.u8 = 0;
+ IfrOptionList[1].Flags = 0;
+ IfrOptionList[1].StringToken = STRING_TOKEN (STR_ONE_OF_AGP);
+ IfrOptionList[1].Value.u8 = 1;
+ IfrOptionList[gDeviceManagerPrivate.VideoBios].Flags |= EFI_IFR_OPTION_DEFAULT;
+
+ UpdateData[0].Offset = 0;
+ CreateOneOfOpCode (
+ DEVICE_MANAGER_KEY_VBIOS,
+ 0,
+ 0,
+ STRING_TOKEN (STR_ONE_OF_VBIOS),
+ STRING_TOKEN (STR_ONE_OF_VBIOS_HELP),
+ EFI_IFR_FLAG_CALLBACK,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ 2,
+ &UpdateData[0]
+ );
+
+ IfrLibUpdateForm (
+ HiiHandle,
+ &mDeviceManagerGuid,
+ DEVICE_MANAGER_FORM_ID,
+ LABEL_VBIOS,
+ FALSE,
+ &UpdateData[0]
+ );
+
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Status = gFormBrowser2->SendForm (
+ gFormBrowser2,
+ &HiiHandle,
+ 1,
+ NULL,
+ 0,
+ NULL,
+ &ActionRequest
+ );
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
+ EnableResetRequired ();
+ }
+
+ //
+ // We will have returned from processing a callback - user either hit ESC to exit, or selected
+ // a target to display
+ //
+ if (gCallbackKey != 0) {
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Status = gFormBrowser2->SendForm (
+ gFormBrowser2,
+ &HiiHandles[gCallbackKey - DEVICE_KEY_OFFSET],
+ 1,
+ NULL,
+ 0,
+ NULL,
+ &ActionRequest
+ );
+
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
+ EnableResetRequired ();
+ }
+
+ //
+ // Force return to Device Manager
+ //
+ gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;
+ }
+
+ //
+ // Cleanup dynamic created strings in HII database by reinstall the packagelist
+ //
+ gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);
+ PackageList = HiiLibPreparePackageList (2, &mDeviceManagerGuid, DeviceManagerVfrBin, BdsDxeStrings);
+ ASSERT (PackageList != NULL);
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ gDeviceManagerPrivate.DriverHandle,
+ &gDeviceManagerPrivate.HiiHandle
+ );
+ FreePool (PackageList);
+
+ for (Index = 0; Index < MENU_ITEM_NUM; Index++) {
+ FreePool (UpdateData[Index].Data);
+ }
+ FreePool (HiiHandles);
+
+ return Status;
+}
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h
new file mode 100644
index 0000000000..23809dd924
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h
@@ -0,0 +1,134 @@
+/** @file
+ The platform device manager reference implement
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 _DEVICE_MANAGER_H_
+#define _DEVICE_MANAGER_H_
+
+#include "Bds.h"
+#include "FrontPage.h"
+
+//
+// These are defined as the same with vfr file
+//
+#define DEVICE_MANAGER_FORMSET_GUID \
+ { \
+ 0x3ebfa8e6, 0x511d, 0x4b5b, {0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27} \
+ }
+
+#define LABEL_VBIOS 0x0040
+
+#define DEVICE_MANAGER_FORM_ID 0x1000
+
+#define DEVICE_KEY_OFFSET 0x1000
+#define DEVICE_MANAGER_KEY_VBIOS 0x2000
+
+//
+// These are the VFR compiler generated data representing our VFR data.
+//
+extern UINT8 DeviceManagerVfrBin[];
+
+#define DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('D', 'M', 'C', 'B')
+
+typedef struct {
+ UINTN Signature;
+
+ ///
+ /// HII relative handles
+ ///
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HANDLE DriverHandle;
+
+ ///
+ /// Produced protocols
+ ///
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+
+ ///
+ /// Configuration data
+ ///
+ UINT8 VideoBios;
+} DEVICE_MANAGER_CALLBACK_DATA;
+
+#define DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS(a) \
+ CR (a, \
+ DEVICE_MANAGER_CALLBACK_DATA, \
+ ConfigAccess, \
+ DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE \
+ )
+typedef struct {
+ EFI_STRING_ID StringId;
+ UINT16 Class;
+} DEVICE_MANAGER_MENU_ITEM;
+
+/**
+ This function is invoked if user selected a iteractive opcode from Device Manager's
+ Formset. The decision by user is saved to gCallbackKey for later processing. If
+ user set VBIOS, the new value is saved to EFI variable.
+
+
+ @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_INVALID_PARAMETER The setup browser call this function with invalid parameters.
+
+**/
+EFI_STATUS
+EFIAPI
+DeviceManagerCallback (
+ 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
+ );
+
+/**
+
+ This function registers HII packages to HII database.
+
+ @retval EFI_SUCCESS This function complete successfully.
+ @return Other value if failed to register HII packages.
+
+**/
+EFI_STATUS
+InitializeDeviceManager (
+ VOID
+ );
+
+/**
+
+ Call the browser and display the device manager to allow user
+ to configure the platform.
+
+ This function create the dynamic content for device manager. It includes
+ section header for all class of devices, one-of opcode to set VBIOS.
+
+ @retval EFI_SUCCESS Operation is successful.
+ @retval Other values if failed to clean up the dynamic content from HII
+ database.
+
+**/
+EFI_STATUS
+CallDeviceManager (
+ VOID
+ );
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni
new file mode 100644
index 0000000000..8cc4db2d7f
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni
Binary files differ
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr
new file mode 100644
index 0000000000..14cafd4761
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr
@@ -0,0 +1,74 @@
+///** @file
+//
+// Device Manager formset.
+//
+// Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+// All rights reserved. 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.
+//
+//**/
+
+#define FORMSET_GUID { 0x3ebfa8e6, 0x511d, 0x4b5b, 0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27 }
+
+#define EFI_DISK_DEVICE_CLASS 0x0001
+#define EFI_VIDEO_DEVICE_CLASS 0x0002
+#define EFI_NETWORK_DEVICE_CLASS 0x0004
+#define EFI_INPUT_DEVICE_CLASS 0x0008
+#define EFI_ON_BOARD_DEVICE_CLASS 0x0010
+#define EFI_OTHER_DEVICE_CLASS 0x0020
+#define LABEL_VBIOS 0x0040
+
+#define LABEL_END 0xffff
+
+#define DEVICE_MANAGER_CLASS 0x0000
+#define FRONT_PAGE_SUBCLASS 0x0003
+
+#define DEVICE_MANAGER_FORM_ID 0x1000
+
+formset
+ guid = FORMSET_GUID,
+ title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE),
+ help = STRING_TOKEN(STR_EMPTY_STRING),
+ class = DEVICE_MANAGER_CLASS,
+ subclass = FRONT_PAGE_SUBCLASS,
+
+ form formid = DEVICE_MANAGER_FORM_ID,
+ title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE);
+
+ //
+ // This is where devices get added to the device manager hierarchy
+ //
+ label EFI_DISK_DEVICE_CLASS;
+// label LABEL_END; // Since next opcode is a label, so this one could be omitted to save code size
+
+ label EFI_VIDEO_DEVICE_CLASS;
+// label LABEL_END;
+
+ label EFI_NETWORK_DEVICE_CLASS;
+// label LABEL_END;
+
+ label EFI_INPUT_DEVICE_CLASS;
+// label LABEL_END;
+
+ label EFI_ON_BOARD_DEVICE_CLASS;
+// label LABEL_END;
+
+ label EFI_OTHER_DEVICE_CLASS;
+ label LABEL_END;
+
+ subtitle text = STRING_TOKEN(STR_EMPTY_STRING);
+
+ label LABEL_VBIOS;
+ label LABEL_END;
+
+ subtitle text = STRING_TOKEN(STR_EMPTY_STRING);
+ subtitle text = STRING_TOKEN(STR_EXIT_STRING);
+
+ endform;
+endformset;
+
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c
new file mode 100644
index 0000000000..44a1e08689
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c
@@ -0,0 +1,976 @@
+/** @file
+ FrontPage routines to handle the callbacks and browser calls
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "Bds.h"
+#include "FrontPage.h"
+
+EFI_GUID mFrontPageGuid = FRONT_PAGE_FORMSET_GUID;
+
+BOOLEAN gConnectAllHappened = FALSE;
+UINTN gCallbackKey;
+
+EFI_HII_DATABASE_PROTOCOL *gHiiDatabase;
+EFI_HII_STRING_PROTOCOL *gHiiString;
+EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2;
+EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting;
+
+FRONT_PAGE_CALLBACK_DATA gFrontPagePrivate = {
+ FRONT_PAGE_CALLBACK_DATA_SIGNATURE,
+ NULL,
+ NULL,
+ NULL,
+ {
+ FakeExtractConfig,
+ FakeRouteConfig,
+ FrontPageCallback
+ }
+};
+
+/**
+ 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
+FakeExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+{
+ return EFI_NOT_FOUND;
+}
+
+/**
+ This function processes the results of changes in configuration.
+
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Configuration A null-terminated Unicode string in <ConfigResp> format.
+ @param Progress A pointer to a string filled in with the offset of 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) or the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The Results is processed successfully.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+FakeRouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+ 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.
+
+**/
+EFI_STATUS
+EFIAPI
+FrontPageCallback (
+ 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
+ )
+{
+ CHAR8 *LanguageString;
+ CHAR8 *LangCode;
+ CHAR8 Lang[RFC_3066_ENTRY_SIZE];
+ CHAR8 OldLang[ISO_639_2_ENTRY_SIZE];
+ UINTN Index;
+ EFI_STATUS Status;
+
+ if ((Value == NULL) || (ActionRequest == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ gCallbackKey = QuestionId;
+
+ //
+ // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
+ // describe to their customers in documentation how to find their setup information (namely
+ // under the device manager and specific buckets)
+ //
+ switch (QuestionId) {
+ case FRONT_PAGE_KEY_CONTINUE:
+ //
+ // This is the continue - clear the screen and return an error to get out of FrontPage loop
+ //
+ break;
+
+ case FRONT_PAGE_KEY_LANGUAGE:
+ //
+ // Collect the languages from what our current Language support is based on our VFR
+ //
+ LanguageString = HiiLibGetSupportedLanguages (gFrontPagePrivate.HiiHandle);
+ ASSERT (LanguageString != NULL);
+
+ Index = 0;
+ LangCode = LanguageString;
+ while (*LangCode != 0) {
+ HiiLibGetNextLanguage (&LangCode, Lang);
+
+ if (Index == Value->u8) {
+ break;
+ }
+
+ Index++;
+ }
+
+ Status = gRT->SetVariable (
+ L"PlatformLang",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ AsciiStrSize (Lang),
+ Lang
+ );
+
+ if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {
+ //
+ // Set UEFI deprecated variable "Lang" for backwards compatibility
+ //
+ Status = ConvertRfc3066LanguageToIso639Language (Lang, OldLang);
+ if (!EFI_ERROR (Status)) {
+ Status = gRT->SetVariable (
+ L"Lang",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ ISO_639_2_ENTRY_SIZE,
+ OldLang
+ );
+ }
+ }
+
+ FreePool (LanguageString);
+ break;
+
+ case FRONT_PAGE_KEY_BOOT_MANAGER:
+ //
+ // Boot Manager
+ //
+ break;
+
+ case FRONT_PAGE_KEY_DEVICE_MANAGER:
+ //
+ // Device Manager
+ //
+ break;
+
+ case FRONT_PAGE_KEY_BOOT_MAINTAIN:
+ //
+ // Boot Maintenance Manager
+ //
+ break;
+
+ default:
+ gCallbackKey = 0;
+ break;
+ }
+
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize HII information for the FrontPage
+
+
+ @param InitializeHiiData TRUE if HII elements need to be initialized.
+
+ @retval EFI_SUCCESS The operation is successful.
+ @retval EFI_DEVICE_ERROR If the dynamic opcode creation failed.
+
+**/
+EFI_STATUS
+InitializeFrontPage (
+ IN BOOLEAN InitializeHiiData
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+ EFI_HII_UPDATE_DATA UpdateData;
+ IFR_OPTION *OptionList;
+ CHAR8 *LanguageString;
+ CHAR8 *LangCode;
+ CHAR8 Lang[RFC_3066_ENTRY_SIZE];
+ CHAR8 CurrentLang[RFC_3066_ENTRY_SIZE];
+ UINTN OptionCount;
+ EFI_STRING_ID Token;
+ CHAR16 *StringBuffer;
+ UINTN BufferSize;
+ UINTN Index;
+ EFI_HII_HANDLE HiiHandle;
+
+ if (InitializeHiiData) {
+ //
+ // Initialize the Device Manager
+ //
+ InitializeDeviceManager ();
+
+ //
+ // Initialize the Device Manager
+ //
+ InitializeBootManager ();
+
+ gCallbackKey = 0;
+
+ //
+ // Locate Hii relative protocols
+ //
+ Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gHiiDatabase);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &gHiiString);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFormBrowser2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &gHiiConfigRouting);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&gFrontPagePrivate.DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install Config Access protocol to driver handle
+ //
+ Status = gBS->InstallProtocolInterface (
+ &gFrontPagePrivate.DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gFrontPagePrivate.ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Publish our HII data
+ //
+ PackageList = HiiLibPreparePackageList (2, &mFrontPageGuid, FrontPageVfrBin, BdsDxeStrings);
+ ASSERT (PackageList != NULL);
+
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ gFrontPagePrivate.DriverHandle,
+ &gFrontPagePrivate.HiiHandle
+ );
+ FreePool (PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Get current language setting
+ //
+ GetCurrentLanguage (CurrentLang);
+
+ //
+ // Allocate space for creation of UpdateData Buffer
+ //
+ UpdateData.BufferSize = 0x1000;
+ UpdateData.Data = AllocateZeroPool (0x1000);
+ ASSERT (UpdateData.Data != NULL);
+
+ OptionList = AllocateZeroPool (0x1000);
+ ASSERT (OptionList != NULL);
+
+ //
+ // Collect the languages from what our current Language support is based on our VFR
+ //
+ HiiHandle = gFrontPagePrivate.HiiHandle;
+ LanguageString = HiiLibGetSupportedLanguages (HiiHandle);
+ ASSERT (LanguageString != NULL);
+
+ OptionCount = 0;
+ LangCode = LanguageString;
+ while (*LangCode != 0) {
+ HiiLibGetNextLanguage (&LangCode, Lang);
+
+ if (gFrontPagePrivate.LanguageToken == NULL) {
+ //
+ // Get Language Name from String Package. The StringId of Printable Language
+ // Name is always 1 which is generated by StringGather Tool.
+ //
+ BufferSize = 0x100;
+ StringBuffer = AllocatePool (BufferSize);
+ Status = gHiiString->GetString (
+ gHiiString,
+ Lang,
+ HiiHandle,
+ PRINTABLE_LANGUAGE_NAME_STRING_ID,
+ StringBuffer,
+ &BufferSize,
+ NULL
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ FreePool (StringBuffer);
+ StringBuffer = AllocatePool (BufferSize);
+ Status = gHiiString->GetString (
+ gHiiString,
+ Lang,
+ HiiHandle,
+ PRINTABLE_LANGUAGE_NAME_STRING_ID,
+ StringBuffer,
+ &BufferSize,
+ NULL
+ );
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ Token = 0;
+ Status = HiiLibNewString (HiiHandle, &Token, StringBuffer);
+ FreePool (StringBuffer);
+ } else {
+ Token = gFrontPagePrivate.LanguageToken[OptionCount];
+ }
+
+ if (AsciiStrCmp (Lang, CurrentLang) == 0) {
+ OptionList[OptionCount].Flags = EFI_IFR_OPTION_DEFAULT;
+ } else {
+ OptionList[OptionCount].Flags = 0;
+ }
+ OptionList[OptionCount].StringToken = Token;
+ OptionList[OptionCount].Value.u8 = (UINT8) OptionCount;
+
+ OptionCount++;
+ }
+
+ FreePool (LanguageString);
+
+ UpdateData.Offset = 0;
+ CreateOneOfOpCode (
+ FRONT_PAGE_KEY_LANGUAGE,
+ 0,
+ 0,
+ STRING_TOKEN (STR_LANGUAGE_SELECT),
+ STRING_TOKEN (STR_LANGUAGE_SELECT_HELP),
+ EFI_IFR_FLAG_CALLBACK,
+ EFI_IFR_NUMERIC_SIZE_1,
+ OptionList,
+ OptionCount,
+ &UpdateData
+ );
+
+ Status = IfrLibUpdateForm (
+ HiiHandle,
+ &mFrontPageGuid,
+ FRONT_PAGE_FORM_ID,
+ LABEL_SELECT_LANGUAGE,
+ FALSE,
+ &UpdateData
+ );
+
+ //
+ // Save the string Id for each language
+ //
+ gFrontPagePrivate.LanguageToken = AllocatePool (OptionCount * sizeof (EFI_STRING_ID));
+ ASSERT (gFrontPagePrivate.LanguageToken != NULL);
+ for (Index = 0; Index < OptionCount; Index++) {
+ gFrontPagePrivate.LanguageToken[Index] = OptionList[Index].StringToken;
+ }
+
+ FreePool (UpdateData.Data);
+ FreePool (OptionList);
+ return Status;
+}
+
+/**
+ Call the browser and display the front page
+
+ @return Status code that will be returned by
+ EFI_FORM_BROWSER2_PROTOCOL.SendForm ().
+
+**/
+EFI_STATUS
+CallFrontPage (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+
+ //
+ // Begin waiting for USER INPUT
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT)
+ );
+
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Status = gFormBrowser2->SendForm (
+ gFormBrowser2,
+ &gFrontPagePrivate.HiiHandle,
+ 1,
+ NULL,
+ 0,
+ NULL,
+ &ActionRequest
+ );
+ //
+ // Check whether user change any option setting which needs a reset to be effective
+ //
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
+ EnableResetRequired ();
+ }
+
+ return Status;
+}
+
+/**
+ Acquire the string associated with the ProducerGuid and return it.
+
+
+ @param ProducerGuid The Guid to search the HII database for
+ @param Token The token value of the string to extract
+ @param String The string that is extracted
+
+ @retval EFI_SUCCESS The function returns EFI_SUCCESS always.
+
+**/
+EFI_STATUS
+GetProducerString (
+ IN EFI_GUID *ProducerGuid,
+ IN EFI_STRING_ID Token,
+ OUT CHAR16 **String
+ )
+{
+ EFI_STATUS Status;
+
+ Status = HiiLibGetStringFromToken (ProducerGuid, Token, String);
+ if (EFI_ERROR (Status)) {
+ *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING));
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Convert Processor Frequency Data to a string
+
+ @param ProcessorFrequency The frequency data to process
+ @param String The string that is created
+
+**/
+VOID
+ConvertProcessorToString (
+ IN EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency,
+ OUT CHAR16 **String
+ )
+{
+ CHAR16 *StringBuffer;
+ UINTN Index;
+ UINT32 FreqMhz;
+
+ if (ProcessorFrequency->Exponent >= 6) {
+ FreqMhz = ProcessorFrequency->Value;
+ for (Index = 0; Index < (UINTN) (ProcessorFrequency->Exponent - 6); Index++) {
+ FreqMhz *= 10;
+ }
+ } else {
+ FreqMhz = 0;
+ }
+
+ StringBuffer = AllocateZeroPool (0x20);
+ ASSERT (StringBuffer != NULL);
+ Index = UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, FreqMhz / 1000, 3);
+ StrCat (StringBuffer, L".");
+ UnicodeValueToString (StringBuffer + Index + 1, PREFIX_ZERO, (FreqMhz % 1000) / 10, 2);
+ StrCat (StringBuffer, L" GHz");
+
+ *String = (CHAR16 *) StringBuffer;
+
+ return ;
+}
+
+/**
+ Convert Memory Size to a string.
+
+ @param MemorySize The size of the memory to process
+ @param String The string that is created
+
+**/
+VOID
+ConvertMemorySizeToString (
+ IN UINT32 MemorySize,
+ OUT CHAR16 **String
+ )
+{
+ CHAR16 *StringBuffer;
+
+ StringBuffer = AllocateZeroPool (0x20);
+ ASSERT (StringBuffer != NULL);
+ UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, MemorySize, 6);
+ StrCat (StringBuffer, L" MB RAM");
+
+ *String = (CHAR16 *) StringBuffer;
+
+ return ;
+}
+
+/**
+ Update the banner information for the Front Page based on DataHub information.
+
+**/
+VOID
+UpdateFrontPageStrings (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING_ID TokenToUpdate;
+ CHAR16 *NewString;
+ UINT64 MonotonicCount;
+ EFI_DATA_HUB_PROTOCOL *DataHub;
+ EFI_DATA_RECORD_HEADER *Record;
+ EFI_SUBCLASS_TYPE1_HEADER *DataHeader;
+ EFI_MISC_BIOS_VENDOR_DATA *BiosVendor;
+ EFI_MISC_SYSTEM_MANUFACTURER_DATA *SystemManufacturer;
+ EFI_PROCESSOR_VERSION_DATA *ProcessorVersion;
+ EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency;
+ EFI_MEMORY_ARRAY_START_ADDRESS_DATA *MemoryArray;
+ BOOLEAN Find[5];
+
+ ZeroMem (Find, sizeof (Find));
+
+ //
+ // Update Front Page strings
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiDataHubProtocolGuid,
+ NULL,
+ (VOID **) &DataHub
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ MonotonicCount = 0;
+ Record = NULL;
+ do {
+ Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record);
+ if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {
+ DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiMiscSubClassGuid) &&
+ (DataHeader->RecordType == EFI_MISC_BIOS_VENDOR_RECORD_NUMBER)
+ ) {
+ BiosVendor = (EFI_MISC_BIOS_VENDOR_DATA *) (DataHeader + 1);
+ GetProducerString (&Record->ProducerName, BiosVendor->BiosVersion, &NewString);
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION);
+ HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);
+ FreePool (NewString);
+ Find[0] = TRUE;
+ }
+
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiMiscSubClassGuid) &&
+ (DataHeader->RecordType == EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER)
+ ) {
+ SystemManufacturer = (EFI_MISC_SYSTEM_MANUFACTURER_DATA *) (DataHeader + 1);
+ GetProducerString (&Record->ProducerName, SystemManufacturer->SystemProductName, &NewString);
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL);
+ HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);
+ FreePool (NewString);
+ Find[1] = TRUE;
+ }
+
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&
+ (DataHeader->RecordType == ProcessorVersionRecordType)
+ ) {
+ ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *) (DataHeader + 1);
+ GetProducerString (&Record->ProducerName, *ProcessorVersion, &NewString);
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL);
+ HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);
+ FreePool (NewString);
+ Find[2] = TRUE;
+ }
+
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&
+ (DataHeader->RecordType == ProcessorCoreFrequencyRecordType)
+ ) {
+ ProcessorFrequency = (EFI_PROCESSOR_CORE_FREQUENCY_DATA *) (DataHeader + 1);
+ ConvertProcessorToString (ProcessorFrequency, &NewString);
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED);
+ HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);
+ FreePool (NewString);
+ Find[3] = TRUE;
+ }
+
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiMemorySubClassGuid) &&
+ (DataHeader->RecordType == EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER)
+ ) {
+ MemoryArray = (EFI_MEMORY_ARRAY_START_ADDRESS_DATA *) (DataHeader + 1);
+ ConvertMemorySizeToString (
+ (UINT32)(RShiftU64((MemoryArray->MemoryArrayEndAddress - MemoryArray->MemoryArrayStartAddress + 1), 20)),
+ &NewString
+ );
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE);
+ HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);
+ FreePool (NewString);
+ Find[4] = TRUE;
+ }
+ }
+ } while (!EFI_ERROR (Status) && (MonotonicCount != 0) && !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4]));
+
+ return ;
+}
+
+/**
+ Function waits for a given event to fire, or for an optional timeout to expire.
+
+ @param Event The event to wait for
+ @param Timeout An optional timeout value in 100 ns units.
+
+ @retval EFI_SUCCESS Event fired before Timeout expired.
+ @retval EFI_TIME_OUT Timout expired before Event fired..
+
+**/
+EFI_STATUS
+WaitForSingleEvent (
+ IN EFI_EVENT Event,
+ IN UINT64 Timeout OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_EVENT TimerEvent;
+ EFI_EVENT WaitList[2];
+
+ if (Timeout != 0) {
+ //
+ // Create a timer event
+ //
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Set the timer event
+ //
+ gBS->SetTimer (
+ TimerEvent,
+ TimerRelative,
+ Timeout
+ );
+
+ //
+ // Wait for the original event or the timer
+ //
+ WaitList[0] = Event;
+ WaitList[1] = TimerEvent;
+ Status = gBS->WaitForEvent (2, WaitList, &Index);
+ gBS->CloseEvent (TimerEvent);
+
+ //
+ // If the timer expired, change the return to timed out
+ //
+ if (!EFI_ERROR (Status) && Index == 1) {
+ Status = EFI_TIMEOUT;
+ }
+ }
+ } else {
+ //
+ // No timeout... just wait on the event
+ //
+ Status = gBS->WaitForEvent (1, &Event, &Index);
+ ASSERT (!EFI_ERROR (Status));
+ ASSERT (Index == 0);
+ }
+
+ return Status;
+}
+
+/**
+ Function show progress bar to wait for user input.
+
+
+ @param TimeoutDefault The fault time out value before the system continue to boot.
+
+ @retval EFI_SUCCESS User pressed some key except "Enter"
+ @retval EFI_TIME_OUT Timout expired or user press "Enter"
+
+**/
+EFI_STATUS
+ShowProgress (
+ IN UINT16 TimeoutDefault
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *TmpStr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+ EFI_INPUT_KEY Key;
+ UINT16 TimeoutRemain;
+
+ if (TimeoutDefault == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it! ...Zzz....\n"));
+
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+
+ //
+ // Clear the progress status bar first
+ //
+ TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION));
+ if (TmpStr != NULL) {
+ PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0);
+ }
+
+ TimeoutRemain = TimeoutDefault;
+ while (TimeoutRemain != 0) {
+ DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain));
+
+ Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);
+ if (Status != EFI_TIMEOUT) {
+ break;
+ }
+ TimeoutRemain--;
+
+ //
+ // Show progress
+ //
+ if (TmpStr != NULL) {
+ PlatformBdsShowProgress (
+ Foreground,
+ Background,
+ TmpStr,
+ Color,
+ ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),
+ 0
+ );
+ }
+ }
+ gBS->FreePool (TmpStr);
+
+ //
+ // Timeout expired
+ //
+ if (TimeoutRemain == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ //
+ // User pressed some key
+ //
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+ //
+ // User pressed enter, equivalent to select "continue"
+ //
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is the main entry of the platform setup entry.
+ The function will present the main menu of the system setup,
+ this is the platform reference part and can be customize.
+
+
+ @param TimeoutDefault The fault time out value before the system
+ continue to boot.
+ @param ConnectAllHappened The indicater to check if the connect all have
+ already happended.
+
+**/
+VOID
+PlatformBdsEnterFrontPage (
+ IN UINT16 TimeoutDefault,
+ IN BOOLEAN ConnectAllHappened
+ )
+{
+ EFI_STATUS Status;
+ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
+
+ PERF_START (0, "BdsTimeOut", "BDS", 0);
+ //
+ // Indicate if we need connect all in the platform setup
+ //
+ if (ConnectAllHappened) {
+ gConnectAllHappened = TRUE;
+ }
+
+ if (TimeoutDefault != 0xffff) {
+ Status = ShowProgress (TimeoutDefault);
+
+ //
+ // Ensure screen is clear when switch Console from Graphics mode to Text mode
+ //
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Timeout or user press enter to continue
+ //
+ goto Exit;
+ }
+ }
+
+ do {
+
+ InitializeFrontPage (FALSE);
+
+ //
+ // Update Front Page strings
+ //
+ UpdateFrontPageStrings ();
+
+ gCallbackKey = 0;
+ Status = CallFrontPage ();
+
+ //
+ // If gCallbackKey is greater than 1 and less or equal to 5,
+ // it will lauch configuration utilities.
+ // 2 = set language
+ // 3 = boot manager
+ // 4 = device manager
+ // 5 = boot maintainenance manager
+ //
+ if (gCallbackKey != 0) {
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP)
+ );
+ }
+ //
+ // Based on the key that was set, we can determine what to do
+ //
+ switch (gCallbackKey) {
+ //
+ // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
+ // describe to their customers in documentation how to find their setup information (namely
+ // under the device manager and specific buckets)
+ //
+ // These entries consist of the Continue, Select language, Boot Manager, and Device Manager
+ //
+ case FRONT_PAGE_KEY_CONTINUE:
+ //
+ // User hit continue
+ //
+ break;
+
+ case FRONT_PAGE_KEY_LANGUAGE:
+ //
+ // User made a language setting change - display front page again
+ //
+ break;
+
+ case FRONT_PAGE_KEY_BOOT_MANAGER:
+ //
+ // User chose to run the Boot Manager
+ //
+ CallBootManager ();
+ break;
+
+ case FRONT_PAGE_KEY_DEVICE_MANAGER:
+ //
+ // Display the Device Manager
+ //
+ do {
+ CallDeviceManager();
+ } while (gCallbackKey == FRONT_PAGE_KEY_DEVICE_MANAGER);
+ break;
+
+ case FRONT_PAGE_KEY_BOOT_MAINTAIN:
+ //
+ // Display the Boot Maintenance Manager
+ //
+ BdsStartBootMaint ();
+ break;
+ }
+
+ } while ((Status == EFI_SUCCESS) && (gCallbackKey != FRONT_PAGE_KEY_CONTINUE));
+
+ //
+ //Will leave browser, check any reset required change is applied? if yes, reset system
+ //
+ SetupResetReminder ();
+
+Exit:
+ //
+ // Automatically load current entry
+ // Note: The following lines of code only execute when Auto boot
+ // takes affect
+ //
+ PERF_END (0, "BdsTimeOut", "BDS", 0);
+ Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
+ ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);
+
+}
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h
new file mode 100644
index 0000000000..d8e3bb49b8
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h
@@ -0,0 +1,240 @@
+/** @file
+ FrontPage routines to handle the callbacks and browser calls
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 _FRONT_PAGE_H_
+#define _FRONT_PAGE_H_
+
+#include "DeviceMngr/DeviceManager.h"
+#include "BootMaint/BootMaint.h"
+#include "BootMngr/BootManager.h"
+#include "String.h"
+
+#define ONE_SECOND 10000000
+
+//
+// This is the VFR compiler generated header file which defines the
+// string identifiers.
+//
+#define PRINTABLE_LANGUAGE_NAME_STRING_ID 0x0001
+
+//
+// These are defined as the same with vfr file
+//
+#define FRONT_PAGE_FORM_ID 0x1000
+
+#define FRONT_PAGE_KEY_CONTINUE 0x1000
+#define FRONT_PAGE_KEY_LANGUAGE 0x1234
+#define FRONT_PAGE_KEY_BOOT_MANAGER 0x1064
+#define FRONT_PAGE_KEY_DEVICE_MANAGER 0x8567
+#define FRONT_PAGE_KEY_BOOT_MAINTAIN 0x9876
+
+#define LABEL_SELECT_LANGUAGE 0x1000
+
+#define FRONT_PAGE_FORMSET_GUID \
+ { \
+ 0x9e0c30bc, 0x3f06, 0x4ba6, {0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe} \
+ }
+
+#define FRONT_PAGE_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('F', 'P', 'C', 'B')
+
+typedef struct {
+ UINTN Signature;
+
+ //
+ // HII relative handles
+ //
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HANDLE DriverHandle;
+ EFI_STRING_ID *LanguageToken;
+
+ //
+ // Produced protocols
+ //
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+} FRONT_PAGE_CALLBACK_DATA;
+
+#define EFI_FP_CALLBACK_DATA_FROM_THIS(a) \
+ CR (a, \
+ FRONT_PAGE_CALLBACK_DATA, \
+ ConfigAccess, \
+ FRONT_PAGE_CALLBACK_DATA_SIGNATURE \
+ )
+
+//
+// These are the VFR compiler generated data representing our VFR data.
+//
+extern UINT8 FrontPageVfrBin[];
+
+extern EFI_HII_DATABASE_PROTOCOL *gHiiDatabase;
+extern EFI_HII_STRING_PROTOCOL *gHiiString;
+extern EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2;
+extern EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting;
+
+extern UINTN gCallbackKey;
+extern BOOLEAN gConnectAllHappened;
+
+/**
+ 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
+FakeExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ );
+
+/**
+ This function processes the results of changes in configuration.
+
+
+ @param This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Configuration - A null-terminated Unicode string in <ConfigResp> format.
+ @param Progress - A pointer to a string filled in with the offset of 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) or the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The Results is processed successfully.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+FakeRouteConfig (
+ 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.
+
+**/
+EFI_STATUS
+EFIAPI
+FrontPageCallback (
+ 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
+ );
+
+/**
+ Initialize HII information for the FrontPage
+
+
+ @param InitializeHiiData TRUE if HII elements need to be initialized.
+
+ @retval EFI_SUCCESS The operation is successful.
+ @retval EFI_DEVICE_ERROR If the dynamic opcode creation failed.
+
+**/
+EFI_STATUS
+InitializeFrontPage (
+ IN BOOLEAN InitializeHiiData
+ );
+
+/**
+ Acquire the string associated with the ProducerGuid and return it.
+
+
+ @param ProducerGuid - The Guid to search the HII database for
+ @param Token - The token value of the string to extract
+ @param String - The string that is extracted
+
+ @retval EFI_SUCCESS The function returns EFI_SUCCESS always.
+
+**/
+EFI_STATUS
+GetProducerString (
+ IN EFI_GUID *ProducerGuid,
+ IN EFI_STRING_ID Token,
+ OUT CHAR16 **String
+ );
+
+/**
+ Compare two EFI_TIME data.
+
+
+ @param FirstTime - A pointer to the first EFI_TIME data.
+ @param SecondTime - A pointer to the second EFI_TIME data.
+
+ @retval TRUE The FirstTime is not later than the SecondTime.
+ @retval FALSE The FirstTime is later than the SecondTime.
+
+**/
+BOOLEAN
+TimeCompare (
+ IN EFI_TIME *FirstTime,
+ IN EFI_TIME *SecondTime
+ );
+
+/**
+ This function is the main entry of the platform setup entry.
+ The function will present the main menu of the system setup,
+ this is the platform reference part and can be customize.
+
+
+ @param TimeoutDefault - The fault time out value before the system
+ continue to boot.
+ @param ConnectAllHappened - The indicater to check if the connect all have
+ already happended.
+
+**/
+VOID
+PlatformBdsEnterFrontPage (
+ IN UINT16 TimeoutDefault,
+ IN BOOLEAN ConnectAllHappened
+ );
+
+#endif // _FRONT_PAGE_H_
+
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni
new file mode 100644
index 0000000000..4d55b2bbe8
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni
Binary files differ
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr
new file mode 100644
index 0000000000..4bf657dc72
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr
@@ -0,0 +1,137 @@
+///** @file
+//
+// Browser formset.
+//
+// Copyright (c) 2007 - 2008, Intel Corporation. <BR>
+// All rights reserved. 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.
+//
+//**/
+
+#define FORMSET_GUID { 0x9e0c30bc, 0x3f06, 0x4ba6, 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe }
+
+#define FRONT_PAGE_CLASS 0x0000
+#define FRONT_PAGE_SUBCLASS 0x0002
+
+#define FRONT_PAGE_FORM_ID 0x1000
+
+#define FRONT_PAGE_ITEM_ONE 0x0001
+#define FRONT_PAGE_ITEM_TWO 0x0002
+#define FRONT_PAGE_ITEM_THREE 0x0003
+#define FRONT_PAGE_ITEM_FOUR 0x0004
+#define FRONT_PAGE_ITEM_FIVE 0x0005
+
+#define FRONT_PAGE_KEY_CONTINUE 0x1000
+#define FRONT_PAGE_KEY_LANGUAGE 0x1234
+#define FRONT_PAGE_KEY_BOOT_MANAGER 0x1064
+#define FRONT_PAGE_KEY_DEVICE_MANAGER 0x8567
+#define FRONT_PAGE_KEY_BOOT_MAINTAIN 0x9876
+
+#define LABEL_SELECT_LANGUAGE 0x1000
+#define LABEL_TIMEOUT 0x2000
+#define LABEL_END 0xffff
+
+formset
+ guid = FORMSET_GUID,
+ title = STRING_TOKEN(STR_FRONT_PAGE_TITLE),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ class = FRONT_PAGE_CLASS,
+ subclass = FRONT_PAGE_SUBCLASS,
+
+ form formid = FRONT_PAGE_FORM_ID,
+ title = STRING_TOKEN(STR_FRONT_PAGE_TITLE);
+
+ banner
+ title = STRING_TOKEN(STR_FRONT_PAGE_COMPUTER_MODEL),
+ line 0,
+ align left;
+
+ banner
+ title = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL),
+ line 1,
+ align left;
+
+ banner
+ title = STRING_TOKEN(STR_FRONT_PAGE_CPU_SPEED),
+ line 1,
+ align right;
+
+ banner
+ title = STRING_TOKEN(STR_FRONT_PAGE_BIOS_VERSION),
+ line 2,
+ align left;
+
+ banner
+ title = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE),
+ line 2,
+ align right;
+
+// banner
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_LEFT),
+// line 0,
+// align left;
+
+// banner
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_RIGHT),
+// line 0,
+// align right;
+
+// banner
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_LEFT),
+// line 1,
+// align left;
+
+// banner
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_RIGHT),
+// line 1,
+// align right;
+
+// banner
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_2_LEFT),
+// line 2,
+// align left;
+
+// banner
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_3_LEFT),
+// line 3,
+// align left;
+
+ goto FRONT_PAGE_ITEM_ONE,
+ prompt = STRING_TOKEN(STR_CONTINUE_PROMPT),
+ help = STRING_TOKEN(STR_CONTINUE_HELP),
+ flags = INTERACTIVE,
+ key = FRONT_PAGE_KEY_CONTINUE;
+
+ label LABEL_SELECT_LANGUAGE;
+ //
+ // This is where we will dynamically add a OneOf type op-code to select
+ // Languages from the currently available choices
+ //
+ label LABEL_END;
+
+ goto FRONT_PAGE_ITEM_THREE,
+ prompt = STRING_TOKEN(STR_BOOT_MANAGER),
+ help = STRING_TOKEN(STR_BOOT_MANAGER_HELP),
+ flags = INTERACTIVE,
+ key = FRONT_PAGE_KEY_BOOT_MANAGER;
+
+ goto FRONT_PAGE_ITEM_FOUR,
+ prompt = STRING_TOKEN(STR_DEVICE_MANAGER),
+ help = STRING_TOKEN(STR_DEVICE_MANAGER_HELP),
+ flags = INTERACTIVE,
+ key = FRONT_PAGE_KEY_DEVICE_MANAGER;
+
+ goto FRONT_PAGE_ITEM_FIVE,
+ prompt = STRING_TOKEN(STR_BOOT_MAINT_MANAGER),
+ help = STRING_TOKEN(STR_BOOT_MAINT_MANAGER_HELP),
+ flags = INTERACTIVE,
+ key = FRONT_PAGE_KEY_BOOT_MAINTAIN;
+
+ endform;
+
+endformset;
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c b/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c
new file mode 100644
index 0000000000..bfad7ce755
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c
@@ -0,0 +1,701 @@
+/** @file
+ Provides a way for 3rd party applications to register themselves for launch by the
+ Boot Manager based on hot key
+
+Copyright (c) 2007 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "Hotkey.h"
+
+
+LIST_ENTRY mHotkeyList = INITIALIZE_LIST_HEAD_VARIABLE (mHotkeyList);
+BOOLEAN mHotkeyCallbackPending = FALSE;
+EFI_EVENT mHotkeyEvent;
+VOID *mHotkeyRegistration;
+
+
+/**
+ Check if the Key Option is valid or not.
+
+ @param KeyOption The Hot Key Option to be checked.
+
+ @retval TRUE The Hot Key Option is valid.
+ @retval FALSE The Hot Key Option is invalid.
+
+**/
+BOOLEAN
+IsKeyOptionValid (
+ IN EFI_KEY_OPTION *KeyOption
+)
+{
+ UINT16 BootOptionName[10];
+ UINT8 *BootOptionVar;
+ UINTN BootOptionSize;
+ UINT32 Crc;
+
+ //
+ // Check whether corresponding Boot Option exist
+ //
+ UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", KeyOption->BootOption);
+ BootOptionVar = BdsLibGetVariableAndSize (
+ BootOptionName,
+ &gEfiGlobalVariableGuid,
+ &BootOptionSize
+ );
+
+ if (BootOptionVar == NULL || BootOptionSize == 0) {
+ return FALSE;
+ }
+
+ //
+ // Check CRC for Boot Option
+ //
+ gBS->CalculateCrc32 (BootOptionVar, BootOptionSize, &Crc);
+ FreePool (BootOptionVar);
+
+ return (BOOLEAN) ((KeyOption->BootOptionCrc == Crc) ? TRUE : FALSE);
+}
+
+/**
+ Create Key#### for the given hotkey.
+
+ @param KeyOption The Hot Key Option to be added.
+ @param KeyOptionNumber The key option number for Key#### (optional).
+
+ @retval EFI_SUCCESS Register hotkey successfully.
+ @retval EFI_INVALID_PARAMETER The hotkey option is invalid.
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.
+
+**/
+EFI_STATUS
+RegisterHotkey (
+ IN EFI_KEY_OPTION *KeyOption,
+ OUT UINT16 *KeyOptionNumber
+)
+{
+ UINT16 KeyOptionName[10];
+ UINT16 *KeyOrder;
+ UINTN KeyOrderSize;
+ UINT16 *NewKeyOrder;
+ UINTN Index;
+ UINT16 MaxOptionNumber;
+ UINT16 RegisterOptionNumber;
+ EFI_KEY_OPTION *TempOption;
+ UINTN TempOptionSize;
+ EFI_STATUS Status;
+ UINTN KeyOptionSize;
+ BOOLEAN UpdateBootOption;
+
+ //
+ // Validate the given key option
+ //
+ if (!IsKeyOptionValid (KeyOption)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ KeyOptionSize = sizeof (EFI_KEY_OPTION) + GET_KEY_CODE_COUNT (KeyOption->KeyData.PackedValue) * sizeof (EFI_INPUT_KEY);
+ UpdateBootOption = FALSE;
+
+ //
+ // check whether HotKey conflict with keys used by Setup Browser
+ //
+ KeyOrder = BdsLibGetVariableAndSize (
+ VAR_KEY_ORDER,
+ &gEfiGlobalVariableGuid,
+ &KeyOrderSize
+ );
+ if (KeyOrder == NULL) {
+ KeyOrderSize = 0;
+ }
+
+ //
+ // Find free key option number
+ //
+ MaxOptionNumber = 0;
+ TempOption = NULL;
+ for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {
+ if (MaxOptionNumber < KeyOrder[Index]) {
+ MaxOptionNumber = KeyOrder[Index];
+ }
+
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);
+ TempOption = BdsLibGetVariableAndSize (
+ KeyOptionName,
+ &gEfiGlobalVariableGuid,
+ &TempOptionSize
+ );
+
+ if (CompareMem (TempOption, KeyOption, TempOptionSize) == 0) {
+ //
+ // Got the option, so just return
+ //
+ FreePool (TempOption);
+ FreePool (KeyOrder);
+ return EFI_SUCCESS;
+ }
+
+ if (KeyOption->KeyData.PackedValue == TempOption->KeyData.PackedValue) {
+ if (GET_KEY_CODE_COUNT (KeyOption->KeyData.PackedValue) == 0 ||
+ CompareMem (
+ ((UINT8 *) TempOption) + sizeof (EFI_KEY_OPTION),
+ ((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION),
+ KeyOptionSize - sizeof (EFI_KEY_OPTION)
+ ) == 0) {
+ //
+ // Hotkey is the same but BootOption changed, need update
+ //
+ UpdateBootOption = TRUE;
+ break;
+ }
+ }
+
+ FreePool (TempOption);
+ }
+
+ if (UpdateBootOption) {
+ RegisterOptionNumber = KeyOrder[Index];
+ FreePool (TempOption);
+ } else {
+ RegisterOptionNumber = (UINT16) (MaxOptionNumber + 1);
+ }
+
+ if (KeyOptionNumber != NULL) {
+ *KeyOptionNumber = RegisterOptionNumber;
+ }
+
+ //
+ // Create variable Key####
+ //
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", RegisterOptionNumber);
+ Status = gRT->SetVariable (
+ KeyOptionName,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ KeyOptionSize,
+ KeyOption
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (KeyOrder);
+ return Status;
+ }
+
+ //
+ // Update the key order variable - "KeyOrder"
+ //
+ if (!UpdateBootOption) {
+ Index = KeyOrderSize / sizeof (UINT16);
+ KeyOrderSize += sizeof (UINT16);
+ }
+
+ NewKeyOrder = AllocatePool (KeyOrderSize);
+ if (NewKeyOrder == NULL) {
+ FreePool (KeyOrder);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (KeyOrder != NULL) {
+ CopyMem (NewKeyOrder, KeyOrder, KeyOrderSize);
+ }
+
+ NewKeyOrder[Index] = RegisterOptionNumber;
+
+ Status = gRT->SetVariable (
+ VAR_KEY_ORDER,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ KeyOrderSize,
+ NewKeyOrder
+ );
+
+ FreePool (KeyOrder);
+ FreePool (NewKeyOrder);
+
+ return Status;
+}
+
+/**
+
+ Delete Key#### for the given Key Option number.
+
+ @param KeyOptionNumber Key option number for Key####
+
+ @retval EFI_SUCCESS Unregister hotkey successfully.
+ @retval EFI_NOT_FOUND No Key#### is found for the given Key Option number.
+
+**/
+EFI_STATUS
+UnregisterHotkey (
+ IN UINT16 KeyOptionNumber
+)
+{
+ UINT16 KeyOption[10];
+ UINTN Index;
+ EFI_STATUS Status;
+ UINTN Index2Del;
+ UINT16 *KeyOrder;
+ UINTN KeyOrderSize;
+
+ //
+ // Delete variable Key####
+ //
+ UnicodeSPrint (KeyOption, sizeof (KeyOption), L"Key%04x", KeyOptionNumber);
+ gRT->SetVariable (
+ KeyOption,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ 0,
+ NULL
+ );
+
+ //
+ // Adjust key order array
+ //
+ KeyOrder = BdsLibGetVariableAndSize (
+ VAR_KEY_ORDER,
+ &gEfiGlobalVariableGuid,
+ &KeyOrderSize
+ );
+ if (KeyOrder == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Index2Del = 0;
+ for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {
+ if (KeyOrder[Index] == KeyOptionNumber) {
+ Index2Del = Index;
+ break;
+ }
+ }
+
+ if (Index != KeyOrderSize / sizeof (UINT16)) {
+ //
+ // KeyOptionNumber found in "KeyOrder", delete it
+ //
+ for (Index = Index2Del; Index < KeyOrderSize / sizeof (UINT16) - 1; Index++) {
+ KeyOrder[Index] = KeyOrder[Index + 1];
+ }
+
+ KeyOrderSize -= sizeof (UINT16);
+ }
+
+ Status = gRT->SetVariable (
+ VAR_KEY_ORDER,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ KeyOrderSize,
+ KeyOrder
+ );
+
+ FreePool (KeyOrder);
+
+ return Status;
+}
+
+/**
+
+ This is the common notification function for HotKeys, it will be registered
+ with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.
+
+ @param KeyData A pointer to a buffer that is filled in with the keystroke
+ information for the key that was pressed.
+
+ @retval EFI_SUCCESS KeyData is successfully processed.
+ @return EFI_NOT_FOUND Fail to find boot option variable.
+**/
+EFI_STATUS
+HotkeyCallback (
+ IN EFI_KEY_DATA *KeyData
+)
+{
+ BOOLEAN HotkeyCatched;
+ LIST_ENTRY BootLists;
+ LIST_ENTRY *Link;
+ BDS_HOTKEY_OPTION *Hotkey;
+ UINT16 Buffer[10];
+ BDS_COMMON_OPTION *BootOption;
+ UINTN ExitDataSize;
+ CHAR16 *ExitData;
+ EFI_STATUS Status;
+ EFI_KEY_DATA *HotkeyData;
+
+ if (mHotkeyCallbackPending) {
+ //
+ // When responsing to a Hotkey, ignore sequential hotkey stroke until
+ // the current Boot#### load option returned
+ //
+ return EFI_SUCCESS;
+ }
+
+ Status = EFI_SUCCESS;
+ Link = GetFirstNode (&mHotkeyList);
+
+ while (!IsNull (&mHotkeyList, Link)) {
+ HotkeyCatched = FALSE;
+ Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);
+
+ //
+ // Is this Key Stroke we are waiting for?
+ //
+ ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));
+ HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];
+ if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&
+ (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&
+ ((HotkeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : 1)) {
+ //
+ // Receive an expecting key stroke
+ //
+ if (Hotkey->CodeCount > 1) {
+ //
+ // For hotkey of key combination, transit to next waiting state
+ //
+ Hotkey->WaitingKey++;
+
+ if (Hotkey->WaitingKey == Hotkey->CodeCount) {
+ //
+ // Received the whole key stroke sequence
+ //
+ HotkeyCatched = TRUE;
+ }
+ } else {
+ //
+ // For hotkey of single key stroke
+ //
+ HotkeyCatched = TRUE;
+ }
+ } else {
+ //
+ // Receive an unexpected key stroke, reset to initial waiting state
+ //
+ Hotkey->WaitingKey = 0;
+ }
+
+ if (HotkeyCatched) {
+ //
+ // Reset to initial waiting state
+ //
+ Hotkey->WaitingKey = 0;
+
+ //
+ // Launch its BootOption
+ //
+ InitializeListHead (&BootLists);
+
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);
+ BootOption = BdsLibVariableToOption (&BootLists, Buffer);
+ if (BootOption == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ BootOption->BootCurrent = Hotkey->BootOptionNumber;
+ BdsLibConnectDevicePath (BootOption->DevicePath);
+
+ //
+ // Clear the screen before launch this BootOption
+ //
+ gST->ConOut->Reset (gST->ConOut, FALSE);
+
+ mHotkeyCallbackPending = TRUE;
+ Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
+ mHotkeyCallbackPending = FALSE;
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Call platform action to indicate the boot fail
+ //
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
+ PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);
+ } else {
+ //
+ // Call platform action to indicate the boot success
+ //
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
+ PlatformBdsBootSuccess (BootOption);
+ }
+ }
+
+ Link = GetNextNode (&mHotkeyList, Link);
+ }
+
+ return Status;
+}
+
+/**
+ Register the common HotKey notify function to given SimpleTextInEx protocol instance.
+
+ @param SimpleTextInEx Simple Text Input Ex protocol instance
+
+ @retval EFI_SUCCESS Register hotkey notification function successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures.
+
+**/
+EFI_STATUS
+HotkeyRegisterNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx
+)
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ BDS_HOTKEY_OPTION *Hotkey;
+
+ //
+ // Register notification function for each hotkey
+ //
+ Link = GetFirstNode (&mHotkeyList);
+
+ while (!IsNull (&mHotkeyList, Link)) {
+ Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);
+
+ Index = 0;
+ do {
+ Status = SimpleTextInEx->RegisterKeyNotify (
+ SimpleTextInEx,
+ &Hotkey->KeyData[Index],
+ HotkeyCallback,
+ &Hotkey->NotifyHandle
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // some of the hotkey registry failed
+ //
+ return Status;
+ }
+ Index ++;
+ } while (Index < Hotkey->CodeCount);
+
+ Link = GetNextNode (&mHotkeyList, Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Callback function for SimpleTextInEx protocol install events
+
+ @param Event the event that is signaled.
+ @param Context not used here.
+
+**/
+VOID
+EFIAPI
+HotkeyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ EFI_HANDLE Handle;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;
+
+ while (TRUE) {
+ BufferSize = sizeof (EFI_HANDLE);
+ Status = gBS->LocateHandle (
+ ByRegisterNotify,
+ NULL,
+ mHotkeyRegistration,
+ &BufferSize,
+ &Handle
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If no more notification events exist
+ //
+ return ;
+ }
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiSimpleTextInputExProtocolGuid,
+ (VOID **) &SimpleTextInEx
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ HotkeyRegisterNotify (SimpleTextInEx);
+ }
+}
+
+/**
+ Insert Key Option to hotkey list.
+
+ @param KeyOption The Hot Key Option to be added to hotkey list.
+
+ @retval EFI_SUCCESS Add to hotkey list success.
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.
+**/
+EFI_STATUS
+HotkeyInsertList (
+ IN EFI_KEY_OPTION *KeyOption
+)
+{
+ BDS_HOTKEY_OPTION *HotkeyLeft;
+ BDS_HOTKEY_OPTION *HotkeyRight;
+ UINTN Index;
+ UINT32 KeyOptions;
+ UINT32 KeyShiftStateLeft;
+ UINT32 KeyShiftStateRight;
+ EFI_INPUT_KEY *InputKey;
+ EFI_KEY_DATA *KeyData;
+
+ HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));
+ if (HotkeyLeft == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;
+ HotkeyLeft->BootOptionNumber = KeyOption->BootOption;
+
+ KeyOptions = KeyOption->KeyData.PackedValue;
+
+ HotkeyLeft->CodeCount = (UINT8) GET_KEY_CODE_COUNT (KeyOptions);
+
+ //
+ // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState
+ //
+ KeyShiftStateRight = (KeyOptions & EFI_KEY_OPTION_SHIFT) |
+ ((KeyOptions & EFI_KEY_OPTION_CONTROL) << 1) |
+ ((KeyOptions & EFI_KEY_OPTION_ALT) << 2) |
+ ((KeyOptions & EFI_KEY_OPTION_LOGO) << 3) |
+ ((KeyOptions & (EFI_KEY_OPTION_MENU | EFI_KEY_OPTION_SYSREQ)) << 4) |
+ EFI_SHIFT_STATE_VALID;
+
+ KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);
+
+ InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));
+
+ Index = 0;
+ KeyData = &HotkeyLeft->KeyData[0];
+ do {
+ //
+ // If Key CodeCount is 0, then only KeyData[0] is used;
+ // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used
+ //
+ KeyData->Key.ScanCode = InputKey[Index].ScanCode;
+ KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;
+ KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;
+
+ Index++;
+ KeyData++;
+ } while (Index < HotkeyLeft->CodeCount);
+ InsertTailList (&mHotkeyList, &HotkeyLeft->Link);
+
+ if (KeyShiftStateLeft != KeyShiftStateRight) {
+ //
+ // Need an extra hotkey for shift key on right
+ //
+ HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);
+ if (HotkeyRight == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Index = 0;
+ KeyData = &HotkeyRight->KeyData[0];
+ do {
+ //
+ // Key.ScanCode and Key.UnicodeChar have already been initialized,
+ // only need to update KeyState.KeyShiftState
+ //
+ KeyData->KeyState.KeyShiftState = KeyShiftStateRight;
+
+ Index++;
+ KeyData++;
+ } while (Index < HotkeyRight->CodeCount);
+ InsertTailList (&mHotkeyList, &HotkeyRight->Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.
+
+ @retval EFI_SUCCESS Hotkey services successfully initialized.
+ @retval EFI_NOT_FOUND Can not find the "KeyOrder" variable
+**/
+EFI_STATUS
+InitializeHotkeyService (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 BootOptionSupport;
+ UINT16 *KeyOrder;
+ UINTN KeyOrderSize;
+ UINTN Index;
+ UINT16 KeyOptionName[8];
+ UINTN KeyOptionSize;
+ EFI_KEY_OPTION *KeyOption;
+
+ //
+ // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP
+ //
+ BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;
+ Status = gRT->SetVariable (
+ L"BootOptionSupport",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ sizeof (UINT32),
+ &BootOptionSupport
+ );
+
+ //
+ // Get valid Key Option List from private EFI variable "KeyOrder"
+ //
+ KeyOrder = BdsLibGetVariableAndSize (
+ VAR_KEY_ORDER,
+ &gEfiGlobalVariableGuid,
+ &KeyOrderSize
+ );
+
+ if (KeyOrder == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);
+ KeyOption = BdsLibGetVariableAndSize (
+ KeyOptionName,
+ &gEfiGlobalVariableGuid,
+ &KeyOptionSize
+ );
+
+ if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {
+ UnregisterHotkey (KeyOrder[Index]);
+ } else {
+ HotkeyInsertList (KeyOption);
+ }
+ }
+
+ //
+ // Register Protocol notify for Hotkey service
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ HotkeyEvent,
+ NULL,
+ &mHotkeyEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for protocol notifications on this event
+ //
+ Status = gBS->RegisterProtocolNotify (
+ &gEfiSimpleTextInputExProtocolGuid,
+ mHotkeyEvent,
+ &mHotkeyRegistration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h b/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h
new file mode 100644
index 0000000000..f2d1c60bf6
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h
@@ -0,0 +1,90 @@
+/** @file
+ Provides a way for 3rd party applications to register themselves for launch by the
+ Boot Manager based on hot key
+
+Copyright (c) 2007 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 _HOTKEY_H_
+#define _HOTKEY_H_
+
+#include "Bds.h"
+#include "String.h"
+
+#define GET_KEY_CODE_COUNT(KeyOptions) (((KeyOptions) & EFI_KEY_CODE_COUNT) >> 8)
+
+#define BDS_HOTKEY_OPTION_SIGNATURE SIGNATURE_32 ('B', 'd', 'K', 'O')
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ EFI_HANDLE NotifyHandle;
+ UINT16 BootOptionNumber;
+ UINT8 CodeCount;
+ UINT8 WaitingKey;
+ EFI_KEY_DATA KeyData[3];
+} BDS_HOTKEY_OPTION;
+
+#define BDS_HOTKEY_OPTION_FROM_LINK(a) CR (a, BDS_HOTKEY_OPTION, Link, BDS_HOTKEY_OPTION_SIGNATURE)
+
+#define VAR_KEY_ORDER L"KeyOrder"
+
+/**
+
+ Create Key#### for the given hotkey.
+
+
+ @param KeyOption - The Hot Key Option to be added.
+ @param KeyOptionNumber - The key option number for Key#### (optional).
+
+ @retval EFI_SUCCESS Register hotkey successfully.
+ @retval EFI_INVALID_PARAMETER The hotkey option is invalid.
+
+**/
+EFI_STATUS
+RegisterHotkey (
+ IN EFI_KEY_OPTION *KeyOption,
+ OUT UINT16 *KeyOptionNumber
+ );
+
+/**
+
+ Delete Key#### for the given Key Option number.
+
+
+ @param KeyOptionNumber - Key option number for Key####
+
+ @retval EFI_SUCCESS Unregister hotkey successfully.
+ @retval EFI_NOT_FOUND No Key#### is found for the given Key Option number.
+
+**/
+EFI_STATUS
+UnregisterHotkey (
+ IN UINT16 KeyOptionNumber
+ );
+
+
+/**
+
+ Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.
+
+
+ @param VOID
+
+ @retval EFI_SUCCESS Hotkey services successfully initialized.
+
+**/
+EFI_STATUS
+InitializeHotkeyService (
+ VOID
+ );
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c b/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c
new file mode 100644
index 0000000000..3b48c370ce
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c
@@ -0,0 +1,49 @@
+/** @file
+ Set the level of support for Hardware Error Record Persistence that is
+ implemented by the platform.
+
+Copyright (c) 2007 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "HwErrRecSupport.h"
+
+/**
+ Set the HwErrRecSupport variable contains a binary UINT16 that supplies the
+ level of support for Hardware Error Record Persistence that is implemented
+ by the platform.
+
+
+ @param HwErrRecSupportLevel
+ zero value: Indicates that the platform implements no support for
+ Hardware Error Record Persistence.
+ non-zero value: Indicates that the platform implements Hardware Error
+ Record Persistence.
+
+**/
+VOID
+InitializeHwErrRecSupport (
+ IN UINT16 HwErrRecSupportLevel
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gRT->SetVariable (
+ L"HwErrRecSupport",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof (UINT16),
+ &HwErrRecSupportLevel
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "HwErrRecSupport: Can not set the variable\n"));
+ }
+
+}
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h b/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h
new file mode 100644
index 0000000000..1926839c6f
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h
@@ -0,0 +1,39 @@
+/** @file
+ Set the level of support for Hardware Error Record Persistence that is
+ implemented by the platform.
+
+Copyright (c) 2007 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 _HW_ERR_REC_SUPPORT_H_
+#define _HW_ERR_REC_SUPPORT_H_
+
+#include "Bds.h"
+
+/**
+ Set the HwErrRecSupport variable contains a binary UINT16 that supplies the
+ level of support for Hardware Error Record Persistence that is implemented
+ by the platform.
+
+
+ @param HwErrRecSupportLevel
+ zero value - Indicates that the platform implements no support for
+ Hardware Error Record Persistence.
+ non-zero value - Indicates that the platform implements Hardware Error
+ Record Persistence.
+
+**/
+VOID
+InitializeHwErrRecSupport (
+ IN UINT16 HwErrRecSupportLevel
+ );
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Language.c b/IntelFrameworkModulePkg/Universal/BdsDxe/Language.c
new file mode 100644
index 0000000000..4e7537c9e4
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/Language.c
@@ -0,0 +1,399 @@
+/** @file
+ Language settings
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "Language.h"
+#include "FrontPage.h"
+
+#define NARROW_GLYPH_NUMBER 8
+#define WIDE_GLYPH_NUMBER 75
+
+EFI_GUID mFontPackageGuid = {
+ 0x78941450, 0x90ab, 0x4fb1, {0xb7, 0x5f, 0x58, 0x92, 0x14, 0xe2, 0x4a, 0xc}
+};
+
+typedef struct {
+ ///
+ /// This 4-bytes total array length is required by HiiLibPreparePackageList()
+ ///
+ UINT32 Length;
+
+ //
+ // This is the Font package definition
+ //
+ EFI_HII_PACKAGE_HEADER Header;
+ UINT16 NumberOfNarrowGlyphs;
+ UINT16 NumberOfWideGlyphs;
+ EFI_NARROW_GLYPH NarrowArray[NARROW_GLYPH_NUMBER];
+ EFI_WIDE_GLYPH WideArray[WIDE_GLYPH_NUMBER];
+} FONT_PACK_BIN;
+
+FONT_PACK_BIN mFontBin = {
+ sizeof (FONT_PACK_BIN),
+ {
+ sizeof (FONT_PACK_BIN) - sizeof (UINT32),
+ EFI_HII_PACKAGE_SIMPLE_FONTS,
+ },
+ NARROW_GLYPH_NUMBER,
+ 0,
+ { // Narrow Glyphs
+ {
+ 0x05d0,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x4E,
+ 0x6E,
+ 0x62,
+ 0x32,
+ 0x32,
+ 0x3C,
+ 0x68,
+ 0x4C,
+ 0x4C,
+ 0x46,
+ 0x76,
+ 0x72,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ },
+ {
+ 0x05d1,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x78,
+ 0x7C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x7E,
+ 0x7E,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ },
+ {
+ 0x05d2,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x78,
+ 0x7C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x1C,
+ 0x3E,
+ 0x66,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ },
+ {
+ 0x05d3,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x7E,
+ 0x7E,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ },
+ {
+ 0x05d4,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x7C,
+ 0x7E,
+ 0x06,
+ 0x06,
+ 0x06,
+ 0x06,
+ 0x66,
+ 0x66,
+ 0x66,
+ 0x66,
+ 0x66,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ },
+ {
+ 0x05d5,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3C,
+ 0x3C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ },
+ {
+ 0x05d6,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x38,
+ 0x38,
+ 0x1E,
+ 0x1E,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ },
+ {
+ 0x0000,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ }
+ }
+};
+
+/**
+ Routine to export glyphs to the HII database. This is in addition to whatever is defined in the Graphics Console driver.
+
+**/
+VOID
+ExportFonts (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+
+ PackageList = HiiLibPreparePackageList (1, &mFontPackageGuid, &mFontBin);
+ ASSERT (PackageList != NULL);
+
+ gHiiDatabase->NewPackageList (gHiiDatabase, PackageList, DriverHandle, &HiiHandle);
+ FreePool (PackageList);
+}
+
+/**
+ Determine the current language that will be used
+ based on language related EFI Variables.
+
+ @param LangCodesSettingRequired - If required to set LangCode variable
+
+**/
+VOID
+InitializeLanguage (
+ BOOLEAN LangCodesSettingRequired
+ )
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ CHAR8 *Lang;
+ CHAR8 LangCode[ISO_639_2_ENTRY_SIZE];
+ CHAR8 *LangCodes;
+ CHAR8 *PlatformLang;
+ CHAR8 *PlatformLangCodes;
+ UINTN Index;
+ BOOLEAN Invalid;
+
+ ExportFonts ();
+
+ LangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLangCodes);
+ if (LangCodesSettingRequired) {
+ if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {
+ //
+ // UEFI 2.1 depricated this variable so we support turning it off
+ //
+ Status = gRT->SetVariable (
+ L"LangCodes",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ AsciiStrLen (LangCodes),
+ LangCodes
+ );
+ }
+
+
+ PlatformLangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes);
+ Status = gRT->SetVariable (
+ L"PlatformLangCodes",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ AsciiStrSize (PlatformLangCodes),
+ PlatformLangCodes
+ );
+ }
+
+ if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {
+ //
+ // UEFI 2.1 depricated this variable so we support turning it off
+ //
+
+ //
+ // Find current LangCode from Lang NV Variable
+ //
+ Size = ISO_639_2_ENTRY_SIZE;
+ Status = gRT->GetVariable (
+ L"Lang",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &Size,
+ &LangCode
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ for (Index = 0; LangCodes[Index] != 0; Index += ISO_639_2_ENTRY_SIZE) {
+ if (CompareMem (&LangCodes[Index], LangCode, ISO_639_2_ENTRY_SIZE) == 0) {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ }
+
+ //
+ // If we cannot get language code from Lang variable,
+ // or LangCode cannot be found from language table,
+ // set the mDefaultLangCode to Lang variable.
+ //
+ if (EFI_ERROR (Status)) {
+ Lang = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLang);
+ Status = gRT->SetVariable (
+ L"Lang",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ ISO_639_2_ENTRY_SIZE,
+ Lang
+ );
+ }
+ }
+
+ Invalid = FALSE;
+ PlatformLang = BdsLibGetVariableAndSize (L"PlatformLang", &gEfiGlobalVariableGuid, &Size);
+ if (PlatformLang != NULL) {
+ //
+ // Check Current PlatformLang value against PlatformLangCode. Need a library that is TBD
+ // Set Invalid based on state of PlatformLang.
+ //
+
+ FreePool (PlatformLang);
+ } else {
+ // No valid variable is set
+ Invalid = TRUE;
+ }
+
+ if (Invalid) {
+ PlatformLang = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLang);
+ Status = gRT->SetVariable (
+ L"PlatformLang",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ AsciiStrSize (PlatformLang),
+ PlatformLang
+ );
+ }
+}
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Language.h b/IntelFrameworkModulePkg/Universal/BdsDxe/Language.h
new file mode 100644
index 0000000000..39dd1eccf9
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/Language.h
@@ -0,0 +1,32 @@
+/** @file
+ Language setting
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 _LANGUAGE_H_
+#define _LANGUAGE_H_
+
+#include "String.h"
+
+/**
+ Determine the current language that will be used
+ based on language related EFI Variables.
+
+ @param LangCodesSettingRequired If required to set LangCode variable
+
+**/
+VOID
+InitializeLanguage (
+ BOOLEAN LangCodesSettingRequired
+ );
+
+#endif // _LANGUAGE_H_
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c b/IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c
new file mode 100644
index 0000000000..fabdf24310
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c
@@ -0,0 +1,425 @@
+/** @file
+ Perform the platform memory test
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "Bds.h"
+#include "String.h"
+
+//
+// BDS Platform Functions
+//
+/**
+
+ Show progress bar with title above it. It only works in Graphics mode.
+
+
+ @param TitleForeground Foreground color for Title.
+ @param TitleBackground Background color for Title.
+ @param Title Title above progress bar.
+ @param ProgressColor Progress bar color.
+ @param Progress Progress (0-100)
+ @param PreviousValue The previous value of the progress.
+
+ @retval EFI_STATUS Success update the progress bar
+
+**/
+EFI_STATUS
+PlatformBdsShowProgress (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,
+ IN CHAR16 *Title,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,
+ IN UINTN Progress,
+ IN UINTN PreviousValue
+ )
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;
+ UINT32 SizeOfX;
+ UINT32 SizeOfY;
+ UINT32 ColorDepth;
+ UINT32 RefreshRate;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+ UINTN BlockHeight;
+ UINTN BlockWidth;
+ UINTN BlockNum;
+ UINTN PosX;
+ UINTN PosY;
+ UINTN Index;
+
+ if (Progress > 100) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UgaDraw = NULL;
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID **) &GraphicsOutput
+ );
+ if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ GraphicsOutput = NULL;
+
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiUgaDrawProtocolGuid,
+ (VOID **) &UgaDraw
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ SizeOfX = 0;
+ SizeOfY = 0;
+ if (GraphicsOutput != NULL) {
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
+ } else if (UgaDraw != NULL) {
+ Status = UgaDraw->GetMode (
+ UgaDraw,
+ &SizeOfX,
+ &SizeOfY,
+ &ColorDepth,
+ &RefreshRate
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ BlockWidth = SizeOfX / 100;
+ BlockHeight = SizeOfY / 50;
+
+ BlockNum = Progress;
+
+ PosX = 0;
+ PosY = SizeOfY * 48 / 50;
+
+ if (BlockNum == 0) {
+ //
+ // Clear progress area
+ //
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ &Color,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ 0,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ SizeOfX,
+ SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
+ SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) &Color,
+ EfiUgaVideoFill,
+ 0,
+ 0,
+ 0,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ SizeOfX,
+ SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
+ SizeOfX * sizeof (EFI_UGA_PIXEL)
+ );
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ //
+ // Show progress by drawing blocks
+ //
+ for (Index = PreviousValue; Index < BlockNum; Index++) {
+ PosX = Index * BlockWidth;
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ &ProgressColor,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ PosX,
+ PosY,
+ BlockWidth - 1,
+ BlockHeight,
+ (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) &ProgressColor,
+ EfiUgaVideoFill,
+ 0,
+ 0,
+ PosX,
+ PosY,
+ BlockWidth - 1,
+ BlockHeight,
+ (BlockWidth) * sizeof (EFI_UGA_PIXEL)
+ );
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ PrintXY (
+ (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ &TitleForeground,
+ &TitleBackground,
+ Title
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Perform the memory test base on the memory test intensive level,
+ and update the memory resource.
+
+
+ @param Level The memory test intensive level.
+
+ @retval EFI_STATUS Success test all the system memory and update
+ the memory resource
+
+**/
+EFI_STATUS
+BdsMemoryTest (
+ IN EXTENDMEM_COVERAGE_LEVEL Level
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS KeyStatus;
+ EFI_STATUS InitStatus;
+ EFI_STATUS ReturnStatus;
+ BOOLEAN RequireSoftECCInit;
+ EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;
+ UINT64 TestedMemorySize;
+ UINT64 TotalMemorySize;
+ UINTN TestPercent;
+ UINT64 PreviousValue;
+ BOOLEAN ErrorOut;
+ BOOLEAN TestAbort;
+ EFI_INPUT_KEY Key;
+ CHAR16 StrPercent[16];
+ CHAR16 *StrTotalMemory;
+ CHAR16 *Pos;
+ CHAR16 *TmpStr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+ UINT8 Value;
+ UINTN DataSize;
+ UINT32 Attributes;
+ UINT32 TempData;
+
+ ReturnStatus = EFI_SUCCESS;
+ ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
+
+ Pos = AllocatePool (128);
+
+ if (Pos == NULL) {
+ return ReturnStatus;
+ }
+
+ StrTotalMemory = Pos;
+
+ TestedMemorySize = 0;
+ TotalMemorySize = 0;
+ PreviousValue = 0;
+ ErrorOut = FALSE;
+ TestAbort = FALSE;
+
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+
+ RequireSoftECCInit = FALSE;
+
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ Status = gBS->LocateProtocol (
+ &gEfiGenericMemTestProtocolGuid,
+ NULL,
+ (VOID **) &GenMemoryTest
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Pos);
+ return EFI_SUCCESS;
+ }
+
+ InitStatus = GenMemoryTest->MemoryTestInit (
+ GenMemoryTest,
+ Level,
+ &RequireSoftECCInit
+ );
+ if (InitStatus == EFI_NO_MEDIA) {
+ //
+ // The PEI codes also have the relevant memory test code to check the memory,
+ // it can select to test some range of the memory or all of them. If PEI code
+ // checks all the memory, this BDS memory test will has no not-test memory to
+ // do the test, and then the status of EFI_NO_MEDIA will be returned by
+ // "MemoryTestInit". So it does not need to test memory again, just return.
+ //
+ FreePool (Pos);
+ return EFI_SUCCESS;
+ }
+
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 2);
+ TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST));
+
+ if (TmpStr != NULL) {
+ gST->ConOut->OutputString (gST->ConOut, TmpStr);
+ FreePool (TmpStr);
+ }
+
+ do {
+ Status = GenMemoryTest->PerformMemoryTest (
+ GenMemoryTest,
+ &TestedMemorySize,
+ &TotalMemorySize,
+ &ErrorOut,
+ TestAbort
+ );
+ if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {
+ TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR));
+ if (TmpStr != NULL) {
+ PrintXY (10, 10, NULL, NULL, TmpStr);
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 4);
+ gST->ConOut->OutputString (gST->ConOut, TmpStr);
+ FreePool (TmpStr);
+ }
+
+ ASSERT (0);
+ }
+
+ TempData = (UINT32) DivU64x32 (TotalMemorySize, 16);
+ TestPercent = (UINTN) DivU64x32 (
+ DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),
+ TempData
+ );
+ if (TestPercent != PreviousValue) {
+ UnicodeValueToString (StrPercent, 0, TestPercent, 0);
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);
+ TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT));
+ if (TmpStr != NULL) {
+ BdsLibOutputStrings (gST->ConOut, StrPercent, TmpStr, NULL);
+ FreePool (TmpStr);
+ }
+
+ TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));
+ if (TmpStr != NULL) {
+ PlatformBdsShowProgress (
+ Foreground,
+ Background,
+ TmpStr,
+ Color,
+ TestPercent,
+ (UINTN) PreviousValue
+ );
+ FreePool (TmpStr);
+ }
+ }
+
+ PreviousValue = TestPercent;
+
+ KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) {
+ if (!RequireSoftECCInit) {
+ TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));
+ if (TmpStr != NULL) {
+ PlatformBdsShowProgress (
+ Foreground,
+ Background,
+ TmpStr,
+ Color,
+ 100,
+ (UINTN) PreviousValue
+ );
+ FreePool (TmpStr);
+ }
+
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);
+ gST->ConOut->OutputString (gST->ConOut, L"100");
+ Status = GenMemoryTest->Finished (GenMemoryTest);
+ goto Done;
+ }
+
+ TestAbort = TRUE;
+ }
+ } while (Status != EFI_NOT_FOUND);
+
+ Status = GenMemoryTest->Finished (GenMemoryTest);
+
+Done:
+ UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0);
+ if (StrTotalMemory[0] == L',') {
+ StrTotalMemory++;
+ }
+
+ TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED));
+ if (TmpStr != NULL) {
+ StrCat (StrTotalMemory, TmpStr);
+ FreePool (TmpStr);
+ }
+
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+ gST->ConOut->OutputString (gST->ConOut, StrTotalMemory);
+ PlatformBdsShowProgress (
+ Foreground,
+ Background,
+ StrTotalMemory,
+ Color,
+ 100,
+ (UINTN) PreviousValue
+ );
+
+ FreePool (Pos);
+
+ DataSize = sizeof (Value);
+ Status = gRT->GetVariable (
+ L"BootState",
+ &gEfiBootStateGuid,
+ &Attributes,
+ &DataSize,
+ &Value
+ );
+
+ if (EFI_ERROR (Status)) {
+ Value = 1;
+ gRT->SetVariable (
+ L"BootState",
+ &gEfiBootStateGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (Value),
+ &Value
+ );
+ }
+
+ return ReturnStatus;
+}
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/String.c b/IntelFrameworkModulePkg/Universal/BdsDxe/String.c
new file mode 100644
index 0000000000..d1c6651977
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/String.c
@@ -0,0 +1,88 @@
+/** @file
+ String support
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 "Bds.h"
+#include "Language.h"
+#include "FrontPage.h"
+
+EFI_HII_HANDLE gStringPackHandle;
+
+EFI_GUID mBdsStringPackGuid = {
+ 0x7bac95d3, 0xddf, 0x42f3, {0x9e, 0x24, 0x7c, 0x64, 0x49, 0x40, 0x37, 0x9a}
+};
+
+/**
+ Initialize HII global accessor for string support
+
+ @retval EFI_SUCCESS String support initialize success.
+
+**/
+EFI_STATUS
+InitializeStringSupport (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+
+ Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gHiiDatabase);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PackageList = HiiLibPreparePackageList (1, &mBdsStringPackGuid, &BdsDxeStrings);
+ ASSERT (PackageList != NULL);
+
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ DriverHandle,
+ &gStringPackHandle
+ );
+
+ FreePool (PackageList);
+ return Status;
+}
+
+/**
+ Get string by string id from HII Interface
+
+
+ @param Id String ID.
+
+ @retval CHAR16 * String from ID.
+ @retval NULL If error occurs.
+
+**/
+CHAR16 *
+GetStringById (
+ IN EFI_STRING_ID Id
+ )
+{
+ CHAR16 *String;
+
+ String = NULL;
+ HiiLibGetStringFromHandle (gStringPackHandle, Id, &String);
+
+ return String;
+}
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/String.h b/IntelFrameworkModulePkg/Universal/BdsDxe/String.h
new file mode 100644
index 0000000000..81a7a6035a
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/String.h
@@ -0,0 +1,75 @@
+/** @file
+ String support
+
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>
+All rights reserved. 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 _STRING_H_
+#define _STRING_H_
+
+#include "Bds.h"
+
+extern EFI_HII_HANDLE gStringPackHandle;
+
+//
+// This is the VFR compiler generated header file which defines the
+// string identifiers.
+//
+
+extern UINT8 BdsDxeStrings[];
+
+//
+// String Definition Guid for BDS Platform
+//
+#define EFI_BDS_PLATFORM_GUID \
+ { \
+ 0x7777E939, 0xD57E, 0x4DCB, 0xA0, 0x8E, 0x64, 0xD7, 0x98, 0x57, 0x1E, 0x0F \
+ }
+
+/**
+ Get string by string id from HII Interface
+
+
+ @param Id String ID.
+
+ @retval CHAR16 * String from ID.
+ @retval NULL If error occurs.
+
+**/
+CHAR16 *
+GetStringById (
+ IN EFI_STRING_ID Id
+ );
+
+/**
+ Initialize HII global accessor for string support
+
+ @retval EFI_SUCCESS String support initialize success.
+
+**/
+EFI_STATUS
+InitializeStringSupport (
+ VOID
+ );
+
+/**
+ Call the browser and display the front page
+
+ @return Status code that will be returned by
+ EFI_FORM_BROWSER2_PROTOCOL.SendForm ().
+
+**/
+EFI_STATUS
+CallFrontPage (
+ VOID
+ );
+
+#endif // _STRING_H_
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni
new file mode 100644
index 0000000000..0d4274a4a9
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni
Binary files differ