]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UEFI HII: Merge UEFI HII support changes from branch.
authorqwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 21 Jan 2008 14:39:56 +0000 (14:39 +0000)
committerqwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 21 Jan 2008 14:39:56 +0000 (14:39 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4599 6f19259b-4bc3-4df7-8a09-765794883524

139 files changed:
MdeModulePkg/Core/Dxe/DxeMain.inf
MdeModulePkg/Include/Library/GenericBdsLib.h [new file with mode: 0644]
MdeModulePkg/Include/Library/PlatformBdsLib.h [new file with mode: 0644]
MdeModulePkg/Include/MdeModuleHii.h [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/BdsBoot.c [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/BdsConnect.c [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/BdsConsole.c [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/BdsMisc.c [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/DevicePath.c [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/Ebc/BmMachine.h [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.msa [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/Ia32/BmMachine.h [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/Ia32/ClearDr.asm [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/InternalBdsLib.h [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/Ipf/BmMachine.h [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/Ipf/ShadowRom.c [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/Performance.c [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/R8Lib.c [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/R8Lib.h [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/x64/BmMachine.h [new file with mode: 0644]
MdeModulePkg/Library/GenericBdsLib/x64/ClearDr.asm [new file with mode: 0644]
MdeModulePkg/Library/GraphicsLib/Graphics.c [new file with mode: 0644]
MdeModulePkg/Library/GraphicsLib/GraphicsLib.inf [new file with mode: 0644]
MdeModulePkg/Library/GraphicsLib/GraphicsLib.msa [new file with mode: 0644]
MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.inf [new file with mode: 0644]
MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.msa [new file with mode: 0644]
MdeModulePkg/Library/IfrSupportLib/R8Lib.c [new file with mode: 0644]
MdeModulePkg/Library/IfrSupportLib/R8Lib.h [new file with mode: 0644]
MdeModulePkg/Library/IfrSupportLib/UefiIfrCommon.c [new file with mode: 0644]
MdeModulePkg/Library/IfrSupportLib/UefiIfrForm.c [new file with mode: 0644]
MdeModulePkg/Library/IfrSupportLib/UefiIfrLibraryInternal.h [new file with mode: 0644]
MdeModulePkg/Library/IfrSupportLib/UefiIfrOpCodeCreation.c [new file with mode: 0644]
MdeModulePkg/Library/IfrSupportLib/UefiIfrString.c [new file with mode: 0644]
MdeModulePkg/Library/PlatformBdsLibNull/BdsPlatform.c [new file with mode: 0644]
MdeModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h [new file with mode: 0644]
MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf [new file with mode: 0644]
MdeModulePkg/Library/PlatformBdsLibNull/PlatformData.c [new file with mode: 0644]
MdeModulePkg/MdeModulePkg.dec
MdeModulePkg/MdeModulePkg.dsc
MdeModulePkg/Universal/BdsDxe/Bds.h [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BdsDxe.inf [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BdsDxe.msa [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BdsEntry.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/BmLib.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/BootOption.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/Data.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/FE.vfr [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMaint/Variable.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.h [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/Capsules.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/FrontPage.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/FrontPage.h [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/FrontPageStrings.uni [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/Hotkey.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/Hotkey.h [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.h [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/Language.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/Language.h [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/MemoryTest.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/String.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/String.h [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/Strings.uni [new file with mode: 0644]
MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h
MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.msa
MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c
MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c
MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c [new file with mode: 0644]
MdeModulePkg/Universal/DriverSampleDxe/DriverSample.h [new file with mode: 0644]
MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf [new file with mode: 0644]
MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.msa [new file with mode: 0644]
MdeModulePkg/Universal/DriverSampleDxe/NVDataStruc.h [new file with mode: 0644]
MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr [new file with mode: 0644]
MdeModulePkg/Universal/DriverSampleDxe/VfrStrings.uni [new file with mode: 0644]
MdeModulePkg/Universal/DriverSampleDxe/inventory.vfr [new file with mode: 0644]
MdeModulePkg/Universal/DriverSampleDxe/inventorystrings.uni [new file with mode: 0644]
MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c [new file with mode: 0644]
MdeModulePkg/Universal/HiiDatabaseDxe/Database.c [new file with mode: 0644]
MdeModulePkg/Universal/HiiDatabaseDxe/Font.c [new file with mode: 0644]
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h [new file with mode: 0644]
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.msa [new file with mode: 0644]
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf [new file with mode: 0644]
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c [new file with mode: 0644]
MdeModulePkg/Universal/HiiDatabaseDxe/Image.c [new file with mode: 0644]
MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.c [new file with mode: 0644]
MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.h [new file with mode: 0644]
MdeModulePkg/Universal/HiiDatabaseDxe/String.c [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/Colors.h [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/Expression.c [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/Print.c [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/Print.h [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/R8Lib.c [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/R8Lib.h [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/Setup.c [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/Setup.h [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowser.msa [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/Ui.c [new file with mode: 0644]
MdeModulePkg/Universal/SetupBrowserDxe/Ui.h [new file with mode: 0644]
MdeModulePkg/Universal/iScsi/IScsi.inf
MdeModulePkg/Universal/iScsi/IScsiCHAP.c
MdeModulePkg/Universal/iScsi/IScsiCHAP.h
MdeModulePkg/Universal/iScsi/IScsiConfig.c
MdeModulePkg/Universal/iScsi/IScsiConfig.h
MdeModulePkg/Universal/iScsi/IScsiConfigDxe.vfr
MdeModulePkg/Universal/iScsi/IScsiConfigNVDataStruc.h
MdeModulePkg/Universal/iScsi/IScsiDhcp.c
MdeModulePkg/Universal/iScsi/IScsiDhcp.h
MdeModulePkg/Universal/iScsi/IScsiIbft.c
MdeModulePkg/Universal/iScsi/IScsiImpl.h
MdeModulePkg/Universal/iScsi/IScsiMisc.c
MdeModulePkg/Universal/iScsi/IScsiProto.c
MdeModulePkg/Universal/iScsi/IScsiProto.h

index 9257fbaed4e97becf5f96a584b08df29cbd93346..a6b6df2b86f5fa44384e38faae3d395e3e9b46eb 100644 (file)
   gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueDxeCoreHandoffToBds | 0x3041001   # EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT\r
   gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueBootServiceExit | 0x3100019       # EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES\r
   gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueDxeDriverBegin | 0x3040002        # EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN\r
-  gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueDxeDriverEnd | 0x3040003          # EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END
\ No newline at end of file
+  gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueDxeDriverEnd | 0x3040003          # EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END\r
+\r
diff --git a/MdeModulePkg/Include/Library/GenericBdsLib.h b/MdeModulePkg/Include/Library/GenericBdsLib.h
new file mode 100644 (file)
index 0000000..9266a86
--- /dev/null
@@ -0,0 +1,565 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  GenericBdsLib.h\r
+\r
+Abstract:\r
+\r
+  Generic BDS library definition, include the file and data structure\r
+\r
+--*/\r
+\r
+#ifndef _GENERIC_BDS_LIB_H_\r
+#define _GENERIC_BDS_LIB_H_\r
+\r
+//\r
+// WQBugBug: These Macro will be handled properly later.\r
+//\r
+//#undef EFI_SPECIFICATION_VERSION\r
+//#define EFI_SPECIFICATION_VERSION 0x0002000A\r
+\r
+#define PI_SPECIFICATION_VERSION 0x00010000\r
+\r
+#include <PiDxe.h>\r
+#include <Protocol/HiiDatabase.h>\r
+#include <IndustryStandard/PeImage.h>\r
+\r
+\r
+extern EFI_HANDLE mBdsImageHandle;\r
+\r
+//\r
+// Constants which are variable names used to access variables\r
+//\r
+#define VarLegacyDevOrder L"LegacyDevOrder"\r
+\r
+//\r
+// Data structures and defines\r
+//\r
+#define FRONT_PAGE_QUESTION_ID  0x0000\r
+#define FRONT_PAGE_DATA_WIDTH   0x01\r
+\r
+//\r
+// ConnectType\r
+//\r
+#define CONSOLE_OUT 0x00000001\r
+#define STD_ERROR   0x00000002\r
+#define CONSOLE_IN  0x00000004\r
+#define CONSOLE_ALL (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)\r
+\r
+//\r
+// Load Option Attributes defined in EFI Specification\r
+//\r
+#define LOAD_OPTION_ACTIVE              0x00000001\r
+#define LOAD_OPTION_FORCE_RECONNECT     0x00000002\r
+\r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+#define LOAD_OPTION_HIDDEN              0x00000008\r
+#define LOAD_OPTION_CATEGORY            0x00001F00\r
+\r
+#define LOAD_OPTION_CATEGORY_BOOT       0x00000000\r
+#define LOAD_OPTION_CATEGORY_APP        0x00000100\r
+\r
+#define EFI_BOOT_OPTION_SUPPORT_KEY     0x00000001\r
+#define EFI_BOOT_OPTION_SUPPORT_APP     0x00000002\r
+#endif\r
+\r
+#define IS_LOAD_OPTION_TYPE(_c, _Mask)  (BOOLEAN) (((_c) & (_Mask)) != 0)\r
+\r
+//\r
+// Define Maxmim characters that will be accepted\r
+//\r
+#define MAX_CHAR            480\r
+#define MAX_CHAR_SIZE       (MAX_CHAR * 2)\r
+\r
+#define MIN_ALIGNMENT_SIZE  4\r
+#define ALIGN_SIZE(a)       ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)\r
+\r
+//\r
+// Define maximum characters for boot option variable "BootXXXX"\r
+//\r
+#define BOOT_OPTION_MAX_CHAR 10\r
+\r
+//\r
+// This data structure is the part of BDS_CONNECT_ENTRY that we can hard code.\r
+//\r
+#define BDS_LOAD_OPTION_SIGNATURE EFI_SIGNATURE_32 ('B', 'd', 'C', 'O')\r
+\r
+typedef struct {\r
+\r
+  UINTN                     Signature;\r
+  LIST_ENTRY                Link;\r
+\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+\r
+  CHAR16                    *OptionName;\r
+  UINTN                     OptionNumber;\r
+  UINT16                    BootCurrent;\r
+  UINT32                    Attribute;\r
+  CHAR16                    *Description;\r
+  VOID                      *LoadOptions;\r
+  UINT32                    LoadOptionsSize;\r
+  CHAR16                    *StatusString;\r
+\r
+} BDS_COMMON_OPTION;\r
+\r
+typedef struct {\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  UINTN                     ConnectType;\r
+} BDS_CONSOLE_CONNECT_ENTRY;\r
+\r
+//\r
+// Lib Functions\r
+//\r
+\r
+//\r
+// Bds boot relate lib functions\r
+//\r
+EFI_STATUS\r
+BdsLibUpdateBootOrderList (\r
+  IN  LIST_ENTRY                 *BdsOptionList,\r
+  IN  CHAR16                         *VariableName\r
+  );\r
+\r
+VOID\r
+BdsLibBootNext (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsLibBootViaBootOption (\r
+  IN  BDS_COMMON_OPTION             * Option,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL      * DevicePath,\r
+  OUT UINTN                         *ExitDataSize,\r
+  OUT CHAR16                        **ExitData OPTIONAL\r
+  );\r
+\r
+EFI_STATUS\r
+BdsLibEnumerateAllBootOption (\r
+  IN OUT LIST_ENTRY    *BdsBootOptionList\r
+  );\r
+\r
+VOID\r
+BdsLibBuildOptionFromHandle (\r
+  IN  EFI_HANDLE          Handle,\r
+  IN  LIST_ENTRY      *BdsBootOptionList,\r
+  IN  CHAR16              *String\r
+  );\r
+\r
+VOID\r
+BdsLibBuildOptionFromShell (\r
+  IN  EFI_HANDLE                     Handle,\r
+  IN  LIST_ENTRY                 *BdsBootOptionList\r
+  );\r
+\r
+//\r
+// Bds misc lib functions\r
+//\r
+UINT16\r
+BdsLibGetTimeout (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsLibGetBootMode (\r
+  OUT EFI_BOOT_MODE       *BootMode\r
+  );\r
+\r
+VOID\r
+BdsLibLoadDrivers (\r
+  IN  LIST_ENTRY              *BdsDriverLists\r
+  );\r
+\r
+EFI_STATUS\r
+BdsLibBuildOptionFromVar (\r
+  IN  LIST_ENTRY              *BdsCommonOptionList,\r
+  IN  CHAR16                      *VariableName\r
+  );\r
+\r
+VOID                      *\r
+BdsLibGetVariableAndSize (\r
+  IN  CHAR16              *Name,\r
+  IN  EFI_GUID            *VendorGuid,\r
+  OUT UINTN               *VariableSize\r
+  );\r
+\r
+EFI_STATUS\r
+BdsLibOutputStrings (\r
+  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *ConOut,\r
+  ...\r
+  );\r
+\r
+BDS_COMMON_OPTION         *\r
+BdsLibVariableToOption (\r
+  IN OUT LIST_ENTRY               *BdsCommonOptionList,\r
+  IN CHAR16                           *VariableName\r
+  );\r
+\r
+EFI_STATUS\r
+BdsLibRegisterNewOption (\r
+  IN  LIST_ENTRY                 *BdsOptionList,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL       *DevicePath,\r
+  IN  CHAR16                         *String,\r
+  IN  CHAR16                         *VariableName\r
+  );\r
+\r
+//\r
+// Bds connect or disconnect driver lib funcion\r
+//\r
+VOID\r
+BdsLibConnectAllDriversToAllControllers (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+BdsLibConnectAll (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsLibConnectDevicePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePathToConnect\r
+  );\r
+\r
+EFI_STATUS\r
+BdsLibConnectAllEfi (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsLibDisconnectAllEfi (\r
+  VOID\r
+  );\r
+\r
+//\r
+// Bds console relate lib functions\r
+//\r
+VOID\r
+BdsLibConnectAllConsoles (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsLibConnectAllDefaultConsoles (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsLibUpdateConsoleVariable (\r
+  IN  CHAR16                    *ConVarName,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *CustomizedConDevicePath,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *ExclusiveDevicePath\r
+  );\r
+\r
+EFI_STATUS\r
+BdsLibConnectConsoleVariable (\r
+  IN  CHAR16                 *ConVarName\r
+  );\r
+\r
+//\r
+// Bds device path relate lib functions\r
+//\r
+EFI_DEVICE_PATH_PROTOCOL  *\r
+BdsLibUnpackDevicePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevPath\r
+  );\r
+\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BdsLibDelPartMatchInstance (\r
+  IN     EFI_DEVICE_PATH_PROTOCOL  *Multi,\r
+  IN     EFI_DEVICE_PATH_PROTOCOL  *Single\r
+  );\r
+\r
+BOOLEAN\r
+BdsLibMatchDevicePaths (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Single\r
+  );\r
+\r
+CHAR16                    *\r
+DevicePathToStr (\r
+  EFI_DEVICE_PATH_PROTOCOL     *DevPath\r
+  );\r
+\r
+VOID                      *\r
+EfiLibGetVariable (\r
+  IN CHAR16               *Name,\r
+  IN EFI_GUID             *VendorGuid\r
+  );\r
+\r
+//\r
+// Internal definitions\r
+//\r
+typedef struct {\r
+  CHAR16  *str;\r
+  UINTN   len;\r
+  UINTN   maxlen;\r
+} POOL_PRINT;\r
+\r
+typedef struct {\r
+  UINT8 Type;\r
+  UINT8 SubType;\r
+  VOID (*Function) (POOL_PRINT *, VOID *);\r
+} DEVICE_PATH_STRING_TABLE;\r
+\r
+extern EFI_GUID mEfiDevicePathMessagingUartFlowControlGuid;\r
+\r
+typedef struct {\r
+  EFI_DEVICE_PATH_PROTOCOL  Header;\r
+  EFI_GUID                  Guid;\r
+  UINT8                     VendorDefinedData[1];\r
+} VENDOR_DEVICE_PATH_WITH_DATA;\r
+\r
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
+\r
+extern EFI_GUID mEfiDevicePathMessagingSASGuid;\r
+\r
+typedef struct {\r
+  EFI_DEVICE_PATH_PROTOCOL  Header;\r
+  UINT16                    NetworkProtocol;\r
+  UINT16                    LoginOption;\r
+  UINT64                    Lun;\r
+  UINT16                    TargetPortalGroupTag;\r
+  CHAR16                    iSCSITargetName[1];\r
+} ISCSI_DEVICE_PATH_WITH_NAME;\r
+\r
+#endif\r
+\r
+//\r
+// Internal functions\r
+//\r
+EFI_STATUS\r
+BdsBootByDiskSignatureAndPartition (\r
+  IN  BDS_COMMON_OPTION          * Option,\r
+  IN  HARDDRIVE_DEVICE_PATH      * HardDriveDevicePath,\r
+  IN  UINT32                     LoadOptionsSize,\r
+  IN  VOID                       *LoadOptions,\r
+  OUT UINTN                      *ExitDataSize,\r
+  OUT CHAR16                     **ExitData OPTIONAL\r
+  );\r
+\r
+//\r
+// Notes: EFI 64 shadow all option rom\r
+//\r
+#if defined (MDE_CPU_IPF)\r
+#define EFI64_SHADOW_ALL_LEGACY_ROM() ShadowAllOptionRom ();\r
+VOID\r
+ShadowAllOptionRom();\r
+#else\r
+#define EFI64_SHADOW_ALL_LEGACY_ROM()\r
+#endif\r
+\r
+//\r
+// BBS support macros and functions\r
+//\r
+\r
+#if defined(MDE_CPU_IA32) || defined(MDE_CPU_X64)\r
+#define REFRESH_LEGACY_BOOT_OPTIONS \\r
+        BdsDeleteAllInvalidLegacyBootOptions ();\\r
+        BdsAddNonExistingLegacyBootOptions (); \\r
+        BdsUpdateLegacyDevOrder ()\r
+#else\r
+#define REFRESH_LEGACY_BOOT_OPTIONS\r
+#endif\r
+\r
+EFI_STATUS\r
+BdsDeleteAllInvalidLegacyBootOptions (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsAddNonExistingLegacyBootOptions (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsUpdateLegacyDevOrder (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsRefreshBbsTableForBoot (\r
+  IN BDS_COMMON_OPTION        *Entry\r
+  );\r
+\r
+EFI_STATUS\r
+BdsDeleteBootOption (\r
+  IN UINTN                       OptionNumber,\r
+  IN OUT UINT16                  *BootOrder,\r
+  IN OUT UINTN                   *BootOrderSize\r
+  );\r
+\r
+//\r
+//The interface functions relate with Setup Browser Reset Reminder feature\r
+//\r
+VOID\r
+EnableResetReminderFeature (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+DisableResetReminderFeature (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+EnableResetRequired (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+DisableResetRequired (\r
+  VOID\r
+  );\r
+\r
+BOOLEAN\r
+IsResetReminderFeatureEnable (\r
+  VOID\r
+  );\r
+\r
+BOOLEAN\r
+IsResetRequired (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+SetupResetReminder (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsLibGetImageHeader (\r
+  IN  EFI_HANDLE                  Device,\r
+  IN  CHAR16                      *FileName,\r
+  OUT EFI_IMAGE_DOS_HEADER        *DosHeader,\r
+  OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+BdsLibGetHiiHandles (\r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+  IN     EFI_HII_DATABASE_PROTOCOL *HiiDatabase,\r
+#else\r
+  IN     EFI_HII_PROTOCOL          *Hii,\r
+#endif\r
+  IN OUT UINT16                    *HandleBufferLength,\r
+  OUT    EFI_HII_HANDLE            **HiiHandleBuffer\r
+  );\r
+  \r
+//\r
+// Define the boot type which to classify the boot option type\r
+// Different boot option type could have different boot behavior\r
+// Use their device path node (Type + SubType) as type value\r
+// The boot type here can be added according to requirement\r
+//\r
+//\r
+// ACPI boot type. For ACPI device, cannot use sub-type to distinguish device, so hardcode their value\r
+//\r
+#define  BDS_EFI_ACPI_FLOPPY_BOOT         0x0201\r
+//\r
+// Message boot type\r
+// If a device path of boot option only point to a message node, the boot option is message boot type\r
+//\r
+#define  BDS_EFI_MESSAGE_ATAPI_BOOT       0x0301 // Type 03; Sub-Type 01\r
+#define  BDS_EFI_MESSAGE_SCSI_BOOT        0x0302 // Type 03; Sub-Type 02\r
+#define  BDS_EFI_MESSAGE_USB_DEVICE_BOOT  0x0305 // Type 03; Sub-Type 05\r
+#define  BDS_EFI_MESSAGE_MISC_BOOT        0x03FF\r
+//\r
+// Media boot type\r
+// If a device path of boot option contain a media node, the boot option is media boot type\r
+//\r
+#define  BDS_EFI_MEDIA_HD_BOOT            0x0401 // Type 04; Sub-Type 01\r
+#define  BDS_EFI_MEDIA_CDROM_BOOT         0x0402 // Type 04; Sub-Type 02\r
+//\r
+// BBS boot type\r
+// If a device path of boot option contain a BBS node, the boot option is BBS boot type\r
+//\r
+#define  BDS_LEGACY_BBS_BOOT              0x0501 //  Type 05; Sub-Type 01\r
+\r
+#define  BDS_EFI_UNSUPPORT                0xFFFF\r
+\r
+//\r
+// USB host controller Programming Interface.\r
+//\r
+#define  PCI_CLASSC_PI_UHCI               0x00\r
+#define  PCI_CLASSC_PI_EHCI               0x20\r
+\r
+BOOLEAN\r
+MatchPartitionDevicePathNode (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL   *BlockIoDevicePath,\r
+  IN  HARDDRIVE_DEVICE_PATH      *HardDriveDevicePath\r
+  );\r
+  \r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BdsExpandPartitionPartialDevicePathToFull (\r
+  IN  HARDDRIVE_DEVICE_PATH      *HardDriveDevicePath\r
+  );\r
+  \r
+EFI_HANDLE\r
+BdsLibGetBootableHandle (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL      *DevicePath\r
+  );\r
+  \r
+BOOLEAN\r
+BdsLibIsValidEFIBootOptDevicePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath,\r
+  IN BOOLEAN                      CheckMedia\r
+  );\r
+  \r
+UINT32\r
+BdsGetBootTypeFromDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
+  );\r
+  \r
+VOID\r
+EFIAPI\r
+BdsLibSaveMemoryTypeInformation (\r
+  VOID \r
+  );\r
+  \r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibUpdateFvFileDevicePath (\r
+  IN  OUT EFI_DEVICE_PATH_PROTOCOL      ** DevicePath,\r
+  IN  EFI_GUID                          *FileGuid\r
+  );\r
+\r
+EFI_STATUS\r
+BdsLibConnectUsbDevByShortFormDP (\r
+  IN CHAR8                      HostControllerPI,\r
+  IN EFI_DEVICE_PATH_PROTOCOL   *RemainingDevicePath\r
+  );\r
+  \r
+EFI_TPL\r
+BdsLibGetCurrentTpl (\r
+  VOID\r
+  );\r
+\r
+//\r
+// The implementation of this function is provided by Platform code.\r
+//\r
+VOID\r
+DevPathVendor (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+;\r
+\r
+CHAR16 *\r
+CatPrint (\r
+  IN OUT POOL_PRINT   *Str,\r
+  IN CHAR16           *fmt,\r
+  ...\r
+  )\r
+;\r
+#endif // _BDS_LIB_H_\r
diff --git a/MdeModulePkg/Include/Library/PlatformBdsLib.h b/MdeModulePkg/Include/Library/PlatformBdsLib.h
new file mode 100644 (file)
index 0000000..cc11824
--- /dev/null
@@ -0,0 +1,98 @@
+/*++\r
+\r
+Copyright (c) 2008, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PlatformBdsLib.h\r
+\r
+Abstract:\r
+\r
+  Platform BDS library definition, include the file and data structure\r
+\r
+--*/\r
+\r
+#ifndef __PLATFORM_BDS_LIB_H_\r
+#define __PLATFORM_BDS_LIB_H_\r
+\r
+#include <PiDxe.h>\r
+#include <Protocol/Bds.h>\r
+#include <Protocol/GenericMemoryTest.h>\r
+\r
+//\r
+// Bds AP Context data\r
+//\r
+#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE  EFI_SIGNATURE_32 ('B', 'd', 's', 'A')\r
+typedef struct _EFI_BDS_ARCH_PROTOCOL_INSTANCE EFI_BDS_ARCH_PROTOCOL_INSTANCE;\r
+\r
+struct _EFI_BDS_ARCH_PROTOCOL_INSTANCE {\r
+  UINTN                     Signature;\r
+  EFI_HANDLE                Handle;\r
+  EFI_BDS_ARCH_PROTOCOL     Bds;\r
+  //\r
+  // Save the current boot mode\r
+  //\r
+  EFI_BOOT_MODE             BootMode;\r
+  //\r
+  // Set true if boot with default settings\r
+  //\r
+  BOOLEAN                   DefaultBoot;\r
+  //\r
+  // The system default timeout for choose the boot option\r
+  //\r
+  UINT16                    TimeoutDefault;\r
+  //\r
+  // Memory Test Level\r
+  //\r
+  EXTENDMEM_COVERAGE_LEVEL  MemoryTestLevel;\r
+};\r
+\r
+//\r
+// Platform BDS Functions\r
+//\r
+VOID\r
+EFIAPI\r
+PlatformBdsInit (\r
+  IN EFI_BDS_ARCH_PROTOCOL_INSTANCE  *PrivateData\r
+  )\r
+;\r
+\r
+VOID\r
+EFIAPI\r
+PlatformBdsPolicyBehavior (\r
+  IN EFI_BDS_ARCH_PROTOCOL_INSTANCE  *PrivateData,\r
+  IN LIST_ENTRY                      *DriverOptionList,\r
+  IN LIST_ENTRY                      *BootOptionList\r
+  )\r
+;\r
+\r
+\r
+VOID\r
+PlatformBdsBootFail (\r
+  IN  BDS_COMMON_OPTION  *Option,\r
+  IN  EFI_STATUS         Status,\r
+  IN  CHAR16             *ExitData,\r
+  IN  UINTN              ExitDataSize\r
+  )\r
+;\r
+\r
+VOID\r
+PlatformBdsBootSuccess (\r
+  IN  BDS_COMMON_OPTION *Option\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PlatformBdsLockNonUpdatableFlash (\r
+  VOID\r
+  )\r
+;\r
+#endif\r
diff --git a/MdeModulePkg/Include/MdeModuleHii.h b/MdeModulePkg/Include/MdeModuleHii.h
new file mode 100644 (file)
index 0000000..7f99ccd
--- /dev/null
@@ -0,0 +1,125 @@
+/* @file\r
+\r
+  EDK II specific HII relative definition.\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _MDEMODULE_HII_H\r
+#define _MDEMODULE_HII_H\r
+\r
+#define NARROW_CHAR         0xFFF0\r
+#define WIDE_CHAR           0xFFF1\r
+#define NON_BREAKING_CHAR   0xFFF2\r
+\r
+#define GLYPH_WIDTH         EFI_GLYPH_WIDTH\r
+#define GLYPH_HEIGHT        EFI_GLYPH_HEIGHT\r
+\r
+//\r
+// State defined for password statemachine \r
+//\r
+#define BROWSER_STATE_VALIDATE_PASSWORD  0\r
+#define BROWSER_STATE_SET_PASSWORD       1\r
+\r
+\r
+//\r
+// Tiano Implementation specific Device Path definition.\r
+//\r
+typedef struct {\r
+  VENDOR_DEVICE_PATH             VendorDevicePath;\r
+  UINT32                         MonotonicCount;\r
+} HII_VENDOR_DEVICE_PATH_NODE;\r
+\r
+typedef struct {\r
+  HII_VENDOR_DEVICE_PATH_NODE    Node;\r
+  EFI_DEVICE_PATH_PROTOCOL       End;\r
+} HII_VENDOR_DEVICE_PATH;\r
+\r
+\r
+//\r
+// References to string tokens must use this macro to enable scanning for\r
+// token usages.\r
+//\r
+#define STRING_TOKEN(t) t\r
+\r
+//\r
+// GUIDed opcodes defined for Tiano\r
+//\r
+#define EFI_IFR_TIANO_GUID \\r
+  { 0xf0b1735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38, 0xaf, 0x48, 0xce} }\r
+\r
+\r
+#pragma pack(1)\r
+\r
+#define EFI_IFR_EXTEND_OP_LABEL       0x0\r
+#define EFI_IFR_EXTEND_OP_BANNER      0x1\r
+#define EFI_IFR_EXTEND_OP_TIMEOUT     0x2\r
+#define EFI_IFR_EXTEND_OP_CLASS       0x3\r
+#define EFI_IFR_EXTEND_OP_SUBCLASS    0x4\r
+\r
+typedef struct _EFI_IFR_GUID_LABEL {\r
+  EFI_IFR_OP_HEADER   Header;\r
+  EFI_GUID            Guid;\r
+  UINT8               ExtendOpCode;\r
+  UINT16              Number;\r
+} EFI_IFR_GUID_LABEL;\r
+\r
+#define EFI_IFR_BANNER_ALIGN_LEFT     0\r
+#define EFI_IFR_BANNER_ALIGN_CENTER   1\r
+#define EFI_IFR_BANNER_ALIGN_RIGHT    2\r
+\r
+typedef struct _EFI_IFR_GUID_BANNER {\r
+  EFI_IFR_OP_HEADER   Header;\r
+  EFI_GUID            Guid;\r
+  UINT8               ExtendOpCode; // Extended opcode is EFI_IFR_EXTEND_OP_BANNER\r
+  EFI_STRING_ID       Title;        // The string token for the banner title\r
+  UINT16              LineNumber;   // 1-based line number\r
+  UINT8               Alignment;    // left, center, or right-aligned\r
+} EFI_IFR_GUID_BANNER;\r
+\r
+typedef struct _EFI_IFR_GUID_TIMEOUT {\r
+  EFI_IFR_OP_HEADER   Header;\r
+  EFI_GUID            Guid;\r
+  UINT8               ExtendOpCode;\r
+  UINT16              TimeOut;\r
+} EFI_IFR_GUID_TIMEOUT;\r
+\r
+#define EFI_NON_DEVICE_CLASS              0x00\r
+#define EFI_DISK_DEVICE_CLASS             0x01\r
+#define EFI_VIDEO_DEVICE_CLASS            0x02\r
+#define EFI_NETWORK_DEVICE_CLASS          0x04\r
+#define EFI_INPUT_DEVICE_CLASS            0x08\r
+#define EFI_ON_BOARD_DEVICE_CLASS         0x10\r
+#define EFI_OTHER_DEVICE_CLASS            0x20\r
+\r
+typedef struct _EFI_IFR_GUID_CLASS {\r
+  EFI_IFR_OP_HEADER   Header;\r
+  EFI_GUID            Guid;\r
+  UINT8               ExtendOpCode;\r
+  UINT16              Class;\r
+} EFI_IFR_GUID_CLASS;\r
+\r
+#define EFI_SETUP_APPLICATION_SUBCLASS    0x00\r
+#define EFI_GENERAL_APPLICATION_SUBCLASS  0x01\r
+#define EFI_FRONT_PAGE_SUBCLASS           0x02\r
+#define EFI_SINGLE_USE_SUBCLASS           0x03\r
+\r
+typedef struct _EFI_IFR_GUID_SUBCLASS {\r
+  EFI_IFR_OP_HEADER   Header;\r
+  EFI_GUID            Guid;\r
+  UINT8               ExtendOpCode;\r
+  UINT16              SubClass;\r
+} EFI_IFR_GUID_SUBCLASS;\r
+\r
+#pragma pack()\r
+\r
+#endif\r
+\r
diff --git a/MdeModulePkg/Library/GenericBdsLib/BdsBoot.c b/MdeModulePkg/Library/GenericBdsLib/BdsBoot.c
new file mode 100644 (file)
index 0000000..5071a67
--- /dev/null
@@ -0,0 +1,1912 @@
+/** @file
+
+Copyright (c) 2004 - 2007, Intel Corporation
+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.
+
+Module Name:
+
+  BdsBoot.c
+
+Abstract:
+
+  BDS Lib functions which relate with create or process the boot
+  option.
+
+
+**/
+
+#include "InternalBdsLib.h"
+
+BOOLEAN mEnumBootDevice = FALSE;
+
+//
+// This GUID is used for an EFI Variable that stores the front device pathes
+// for a partial device path that starts with the HD node.
+//
+EFI_GUID  mHdBootVariablePrivateGuid = { 0xfab7e9e1, 0x39dd, 0x4f2b, { 0x84, 0x8, 0xe2, 0xe, 0x90, 0x6c, 0xb6, 0xde } };
+
+
+
+/**
+  Boot the legacy system with the boot option
+
+  @param  Option                 The legacy boot option which have BBS device path
+
+  @retval EFI_UNSUPPORTED        There is no legacybios protocol, do not support
+                                 legacy boot.
+  @retval EFI_STATUS             Return the status of LegacyBios->LegacyBoot ().
+
+**/
+EFI_STATUS
+BdsLibDoLegacyBoot (
+  IN  BDS_COMMON_OPTION           *Option
+  )
+{
+  EFI_STATUS                Status;
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
+
+  Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+  if (EFI_ERROR (Status)) {
+    //
+    // If no LegacyBios protocol we do not support legacy boot
+    //
+    return EFI_UNSUPPORTED;
+  }
+  //
+  // Notes: if we seperate the int 19, then we don't need to refresh BBS
+  //
+  BdsRefreshBbsTableForBoot (Option);
+
+  //
+  // Write boot to OS performance data to a file
+  //
+  PERF_CODE (
+    WriteBootToOsPerformanceData ();
+  );
+
+  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Legacy Boot: %S\n", Option->Description));
+  return LegacyBios->LegacyBoot (
+                      LegacyBios,
+                      (BBS_BBS_DEVICE_PATH *) Option->DevicePath,
+                      Option->LoadOptionsSize,
+                      Option->LoadOptions
+                      );
+}
+
+
+/**
+  Process the boot option follow the EFI 1.1 specification and
+  special treat the legacy boot option with BBS_DEVICE_PATH.
+
+  @param  Option                 The boot option need to be processed
+  @param  DevicePath             The device path which describe where to load the
+                                 boot image or the legcy BBS device path to boot
+                                 the legacy OS
+  @param  ExitDataSize           Returned directly from gBS->StartImage ()
+  @param  ExitData               Returned directly from gBS->StartImage ()
+
+  @retval EFI_SUCCESS            Status from gBS->StartImage ()
+  @retval EFI_NOT_FOUND          If the Device Path is not found in the system
+
+**/
+EFI_STATUS
+BdsLibBootViaBootOption (
+  IN  BDS_COMMON_OPTION             * Option,
+  IN  EFI_DEVICE_PATH_PROTOCOL      * DevicePath,
+  OUT UINTN                         *ExitDataSize,
+  OUT CHAR16                        **ExitData OPTIONAL
+  )
+{
+  EFI_STATUS                Status;
+  EFI_HANDLE                Handle;
+  EFI_HANDLE                ImageHandle;
+  EFI_DEVICE_PATH_PROTOCOL  *FilePath;
+  EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
+  EFI_DEVICE_PATH_PROTOCOL  *WorkingDevicePath;
+  EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;
+  LIST_ENTRY                TempBootLists;
+
+  //
+  // Record the performance data for End of BDS
+  //
+  PERF_END (0, BDS_TOK, NULL, 0);
+
+  *ExitDataSize = 0;
+  *ExitData     = NULL;
+
+  //
+  // Notes: put EFI64 ROM Shadow Solution
+  //
+  EFI64_SHADOW_ALL_LEGACY_ROM ();
+
+  //
+  // Notes: this code can be remove after the s3 script table
+  // hook on the event EFI_EVENT_SIGNAL_READY_TO_BOOT or
+  // EFI_EVENT_SIGNAL_LEGACY_BOOT
+  //
+  Status = gBS->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid, NULL, (VOID **) &AcpiS3Save);
+  if (!EFI_ERROR (Status)) {
+    AcpiS3Save->S3Save (AcpiS3Save, NULL);
+  }
+  //
+  // If it's Device Path that starts with a hard drive path, append it with the front part to compose a
+  // full device path
+  //
+  WorkingDevicePath = NULL;
+  if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&
+      (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)) {
+    WorkingDevicePath = BdsExpandPartitionPartialDevicePathToFull (
+                          (HARDDRIVE_DEVICE_PATH *)DevicePath
+                          );
+    if (WorkingDevicePath != NULL) {
+      DevicePath = WorkingDevicePath;
+    }
+  }
+  //
+  // Signal the EFI_EVENT_SIGNAL_READY_TO_BOOT event
+  //
+  EfiSignalEventReadyToBoot();
+  
+  
+  //
+  // Set Boot Current
+  //
+  gRT->SetVariable (
+        L"BootCurrent",
+        &gEfiGlobalVariableGuid,
+        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+        sizeof (UINT16),
+        &Option->BootCurrent
+        );
+
+  if ((DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) &&
+      (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP)
+    ) {
+    //
+    // Check to see if we should legacy BOOT. If yes then do the legacy boot
+    //
+    return BdsLibDoLegacyBoot (Option);
+  }
+
+  //
+  // If the boot option point to Internal FV shell, make sure it is valid
+  //
+  Status = BdsLibUpdateFvFileDevicePath (&DevicePath, &gEfiShellFileGuid);
+  if (!EFI_ERROR(Status)) {
+    if (Option->DevicePath != NULL) {
+      SafeFreePool(Option->DevicePath);
+    }
+    Option->DevicePath  = AllocateZeroPool (GetDevicePathSize (DevicePath));
+    CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));
+    //
+    // Update the shell boot option
+    //
+    InitializeListHead (&TempBootLists);
+    BdsLibRegisterNewOption (&TempBootLists, DevicePath, L"EFI Internal Shell", L"BootOrder");
+  }
+
+  //
+  // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION
+  //
+  gBS->RestoreTPL (TPL_APPLICATION);
+
+  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting EFI way %S\n", Option->Description));
+
+  Status = gBS->LoadImage (
+                  TRUE,
+                  mBdsImageHandle,
+                  DevicePath,
+                  NULL,
+                  0,
+                  &ImageHandle
+                  );
+
+  //
+  // If we didn't find an image directly, we need to try as if it is a removable device boot opotion
+  // and load the image according to the default boot behavior for removable device.
+  //
+  if (EFI_ERROR (Status)) {
+    //
+    // check if there is a bootable removable media could be found in this device path ,
+    // and get the bootable media handle
+    //
+    Handle = BdsLibGetBootableHandle(DevicePath);
+    if (Handle == NULL) {
+       goto Done;
+    }
+    //
+    // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media
+    //  machinename is ia32, ia64, x64, ...
+    //
+    FilePath = FileDevicePath (Handle, DEFAULT_REMOVABLE_FILE_NAME);
+    if (FilePath) {
+      Status = gBS->LoadImage (
+                      TRUE,
+                      mBdsImageHandle,
+                      FilePath,
+                      NULL,
+                      0,
+                      &ImageHandle
+                      );
+      if (EFI_ERROR (Status)) {
+        //
+        // The DevicePath failed, and it's not a valid
+        // removable media device.
+        //
+        goto Done;
+      }
+    }
+  }
+
+  if (EFI_ERROR (Status)) {
+    //
+    // It there is any error from the Boot attempt exit now.
+    //
+    goto Done;
+  }
+  //
+  // Provide the image with it's load options
+  //
+  Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
+  ASSERT_EFI_ERROR (Status);
+
+  if (Option->LoadOptionsSize != 0) {
+    ImageInfo->LoadOptionsSize  = Option->LoadOptionsSize;
+    ImageInfo->LoadOptions      = Option->LoadOptions;
+  }
+  //
+  // Before calling the image, enable the Watchdog Timer for
+  // the 5 Minute period
+  //
+  gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
+
+  Status = gBS->StartImage (ImageHandle, ExitDataSize, ExitData);
+  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Image Return Status = %r\n", Status));
+
+  //
+  // Clear the Watchdog Timer after the image returns
+  //
+  gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
+
+Done:
+  //
+  // Clear Boot Current
+  //
+  gRT->SetVariable (
+        L"BootCurrent",
+        &gEfiGlobalVariableGuid,
+        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+        0,
+        &Option->BootCurrent
+        );
+
+  //
+  // Raise the TPL level back to TPL_APPLICATION
+  //
+  gBS->RaiseTPL (TPL_APPLICATION);
+
+  return Status;
+}
+
+
+/**
+  Expand a device path that starts with a hard drive media device path node to be a
+  full device path that includes the full hardware path to the device. We need
+  to do this so it can be booted. As an optimizaiton the front match (the part point
+  to the partition node. E.g. ACPI() /PCI()/ATA()/Partition() ) is saved in a variable
+  so a connect all is not required on every boot. All successful history device path
+  which point to partition node (the front part) will be saved.
+
+  @param  HardDriveDevicePath    EFI Device Path to boot, if it starts with a hard
+                                 drive media device path.
+ A Pointer to the full device path.
+  @retval NULL                   Cannot find a valid Hard Drive devic path
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+BdsExpandPartitionPartialDevicePathToFull (
+  IN  HARDDRIVE_DEVICE_PATH      *HardDriveDevicePath
+  )
+{
+  EFI_STATUS                Status;
+  UINTN                     BlockIoHandleCount;
+  EFI_HANDLE                *BlockIoBuffer;
+  EFI_DEVICE_PATH_PROTOCOL  *FullDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *BlockIoDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  UINTN                     Index;
+  UINTN                     InstanceNum;
+  EFI_DEVICE_PATH_PROTOCOL  *CachedDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;
+  UINTN                     CachedDevicePathSize;
+  BOOLEAN                   DeviceExist;
+  BOOLEAN                   NeedAdjust;
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;
+  UINTN                     Size;
+
+  FullDevicePath = NULL;
+  //
+  // Check if there is prestore 'HDDP' variable.
+  // If exist, search the front path which point to partition node in the variable instants.
+  // If fail to find or 'HDDP' not exist, reconnect all and search in all system
+  //
+  CachedDevicePath = BdsLibGetVariableAndSize (
+                      L"HDDP",
+                      &mHdBootVariablePrivateGuid,
+                      &CachedDevicePathSize
+                      );
+  if (CachedDevicePath != NULL) {
+    TempNewDevicePath = CachedDevicePath;
+    DeviceExist = FALSE;
+    NeedAdjust = FALSE;
+    do {
+      //
+      // Check every instance of the variable
+      // First, check wheather the instance contain the partition node, which is needed for distinguishing  multi
+      // partial partition boot option. Second, check wheather the instance could be connected.
+      //
+      Instance  = GetNextDevicePathInstance (&TempNewDevicePath, &Size);
+      if (MatchPartitionDevicePathNode (Instance, HardDriveDevicePath)) {
+        //
+        // Connect the device path instance, the device path point to hard drive media device path node
+        // e.g. ACPI() /PCI()/ATA()/Partition()
+        //
+        Status = BdsLibConnectDevicePath (Instance);
+        if (!EFI_ERROR (Status)) {
+          DeviceExist = TRUE;
+          break;
+        }
+      }
+      //
+      // Come here means the first instance is not matched
+      //
+      NeedAdjust = TRUE;
+      SafeFreePool(Instance);
+    } while (TempNewDevicePath != NULL);
+
+    if (DeviceExist) {
+      //
+      // Find the matched device path.
+      // Append the file path infomration from the boot option and return the fully expanded device path.
+      //
+      DevicePath    = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);
+      FullDevicePath = AppendDevicePath (Instance, DevicePath);
+
+      //
+      // Adjust the 'HDDP' instances sequense if the matched one is not first one.
+      //
+      if (NeedAdjust) {
+        //
+        // First delete the matched instance.
+        //
+        TempNewDevicePath = CachedDevicePath;
+        CachedDevicePath = BdsLibDelPartMatchInstance ( CachedDevicePath, Instance );
+        SafeFreePool (TempNewDevicePath);
+        //
+        // Second, append the remaining parth after the matched instance
+        //
+        TempNewDevicePath = CachedDevicePath;
+        CachedDevicePath = AppendDevicePathInstance ( Instance, CachedDevicePath );
+        SafeFreePool (TempNewDevicePath);
+        //
+        // Save the matching Device Path so we don't need to do a connect all next time
+        //
+        Status = gRT->SetVariable (
+                        L"HDDP",
+                        &mHdBootVariablePrivateGuid,
+                        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                        GetDevicePathSize (CachedDevicePath),
+                        CachedDevicePath
+                        );
+      }
+      SafeFreePool(Instance);
+      gBS->FreePool (CachedDevicePath);
+      return FullDevicePath;
+    }
+  }
+
+  //
+  // If we get here we fail to find or 'HDDP' not exist, and now we need
+  // to seach all devices in the system for a matched partition
+  //
+  BdsLibConnectAllDriversToAllControllers ();
+  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);
+  if (EFI_ERROR (Status) || BlockIoHandleCount == 0) {
+    //
+    // If there was an error or there are no device handles that support
+    // the BLOCK_IO Protocol, then return.
+    //
+    return NULL;
+  }
+  //
+  // Loop through all the device handles that support the BLOCK_IO Protocol
+  //
+  for (Index = 0; Index < BlockIoHandleCount; Index++) {
+
+    Status = gBS->HandleProtocol (BlockIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &BlockIoDevicePath);
+    if (EFI_ERROR (Status) || BlockIoDevicePath == NULL) {
+      continue;
+    }
+
+    if (MatchPartitionDevicePathNode (BlockIoDevicePath, HardDriveDevicePath)) {
+      //
+      // Find the matched partition device path
+      //
+      DevicePath    = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);
+      FullDevicePath = AppendDevicePath (BlockIoDevicePath, DevicePath);
+
+      //
+      // Save the matched patition device path in 'HDDP' variable
+      //
+      if (CachedDevicePath != NULL) {
+        //
+        // Save the matched patition device path as first instance of 'HDDP' variable
+        //
+        if (BdsLibMatchDevicePaths (CachedDevicePath, BlockIoDevicePath)) {
+          TempNewDevicePath = CachedDevicePath;
+          CachedDevicePath = BdsLibDelPartMatchInstance (CachedDevicePath, BlockIoDevicePath);
+          SafeFreePool(TempNewDevicePath);
+
+          TempNewDevicePath = CachedDevicePath;
+          CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);
+          SafeFreePool(TempNewDevicePath);
+        } else {
+          TempNewDevicePath = CachedDevicePath;
+          CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);
+          SafeFreePool(TempNewDevicePath);
+        }
+        //
+        // Here limit the device path instance number to 12, which is max number for a system support 3 IDE controller
+        // If the user try to boot many OS in different HDs or partitions, in theary, the 'HDDP' variable maybe become larger and larger.
+        //
+        InstanceNum = 0;
+        TempNewDevicePath = CachedDevicePath;
+        while (!IsDevicePathEnd (TempNewDevicePath)) {
+          TempNewDevicePath = NextDevicePathNode (TempNewDevicePath);
+          //
+          // Parse one instance
+          //
+          while (!IsDevicePathEndType (TempNewDevicePath)) {
+            TempNewDevicePath = NextDevicePathNode (TempNewDevicePath);
+          }
+          InstanceNum++;
+          //
+          // If the CachedDevicePath variable contain too much instance, only remain 12 instances.
+          //
+          if (InstanceNum >= 12) {
+            SetDevicePathEndNode (TempNewDevicePath);
+            break;
+          }
+        }
+      } else {
+        CachedDevicePath = DuplicateDevicePath (BlockIoDevicePath);
+      }
+
+      //
+      // Save the matching Device Path so we don't need to do a connect all next time
+      //
+      Status = gRT->SetVariable (
+                      L"HDDP",
+                      &mHdBootVariablePrivateGuid,
+                      EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                      GetDevicePathSize (CachedDevicePath),
+                      CachedDevicePath
+                      );
+
+      break;
+    }
+  }
+  gBS->FreePool (CachedDevicePath);
+  gBS->FreePool (BlockIoBuffer);
+  return FullDevicePath;
+}
+
+
+/**
+  Check whether there is a instance in BlockIoDevicePath, which contain multi device path
+  instances, has the same partition node with HardDriveDevicePath device path
+
+  @param  BlockIoDevicePath      Multi device path instances which need to check
+  @param  HardDriveDevicePath    A device path which starts with a hard drive media
+                                 device path.
+
+  @retval TRUE                   There is a matched device path instance FALSE
+                                 -There is no matched device path instance
+
+**/
+BOOLEAN
+MatchPartitionDevicePathNode (
+  IN  EFI_DEVICE_PATH_PROTOCOL   *BlockIoDevicePath,
+  IN  HARDDRIVE_DEVICE_PATH      *HardDriveDevicePath
+  )
+{
+  HARDDRIVE_DEVICE_PATH     *TmpHdPath;
+  HARDDRIVE_DEVICE_PATH     *TempPath;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  BOOLEAN                   Match;
+  EFI_DEVICE_PATH_PROTOCOL  *BlockIoHdDevicePathNode;
+
+  if ((BlockIoDevicePath == NULL) || (HardDriveDevicePath == NULL)) {
+    return FALSE;
+  }
+  //
+  // Make PreviousDevicePath == the device path node before the end node
+  //
+  DevicePath          = BlockIoDevicePath;
+  BlockIoHdDevicePathNode = NULL;
+
+  //
+  // find the partition device path node
+  //
+  while (!IsDevicePathEnd (DevicePath)) {
+    if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&
+        (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)
+        ) {
+      BlockIoHdDevicePathNode = DevicePath;
+      break;
+    }
+
+    DevicePath = NextDevicePathNode (DevicePath);
+  }
+
+  if (BlockIoHdDevicePathNode == NULL) {
+    return FALSE;
+  }
+  //
+  // See if the harddrive device path in blockio matches the orig Hard Drive Node
+  //
+  TmpHdPath = (HARDDRIVE_DEVICE_PATH *) BlockIoHdDevicePathNode;
+  TempPath  = (HARDDRIVE_DEVICE_PATH *) BdsLibUnpackDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);
+  Match = FALSE;
+  //
+  // Check for the match
+  //
+  if ((TmpHdPath->MBRType == TempPath->MBRType) &&
+      (TmpHdPath->SignatureType == TempPath->SignatureType)) {
+    switch (TmpHdPath->SignatureType) {
+    case SIGNATURE_TYPE_GUID:
+      Match = CompareGuid ((EFI_GUID *)TmpHdPath->Signature, (EFI_GUID *)TempPath->Signature);
+      break;
+    case SIGNATURE_TYPE_MBR:
+      Match = (BOOLEAN)(*((UINT32 *)(&(TmpHdPath->Signature[0]))) == *(UINT32 *)(&(TempPath->Signature[0])));
+      break;
+    default:
+      Match = FALSE;
+      break;
+    }
+  }
+
+  return Match;
+}
+
+
+/**
+  Delete the boot option associated with the handle passed in
+
+  @param  Handle                 The handle which present the device path to create
+                                 boot option
+
+  @retval EFI_SUCCESS            Delete the boot option success
+  @retval EFI_NOT_FOUND          If the Device Path is not found in the system
+  @retval EFI_OUT_OF_RESOURCES   Lack of memory resource
+  @retval Other                  Error return value from SetVariable()
+
+**/
+EFI_STATUS
+BdsLibDeleteOptionFromHandle (
+  IN  EFI_HANDLE                 Handle
+  )
+{
+  UINT16                    *BootOrder;
+  UINT8                     *BootOptionVar;
+  UINTN                     BootOrderSize;
+  UINTN                     BootOptionSize;
+  EFI_STATUS                Status;
+  UINTN                     Index;
+  UINT16                    BootOption[BOOT_OPTION_MAX_CHAR];
+  UINTN                     DevicePathSize;
+  UINTN                     OptionDevicePathSize;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *OptionDevicePath;
+  UINT8                     *TempPtr;
+
+  Status        = EFI_SUCCESS;
+  BootOrder     = NULL;
+  BootOrderSize = 0;
+
+  BootOrder = BdsLibGetVariableAndSize (
+                L"BootOrder",
+                &gEfiGlobalVariableGuid,
+                &BootOrderSize
+                );
+  if (NULL == BootOrder) {
+    return EFI_NOT_FOUND;
+  }
+
+  DevicePath = DevicePathFromHandle (Handle);
+  if (DevicePath == NULL) {
+    return EFI_NOT_FOUND;
+  }
+  DevicePathSize = GetDevicePathSize (DevicePath);
+
+  Index = 0;
+  while (Index < BootOrderSize / sizeof (UINT16)) {
+    UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
+    BootOptionVar = BdsLibGetVariableAndSize (
+                      BootOption,
+                      &gEfiGlobalVariableGuid,
+                      &BootOptionSize
+                      );
+    if (NULL == BootOptionVar) {
+      gBS->FreePool (BootOrder);
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    TempPtr = BootOptionVar;
+    TempPtr += sizeof (UINT32) + sizeof (UINT16);
+    TempPtr += StrSize ((CHAR16 *) TempPtr);
+    OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
+    OptionDevicePathSize = GetDevicePathSize (OptionDevicePath);
+
+    //
+    // Check whether the device path match
+    //
+    if ((OptionDevicePathSize == DevicePathSize) &&
+        (CompareMem (DevicePath, OptionDevicePath, DevicePathSize) == 0)) {
+      BdsDeleteBootOption (BootOrder[Index], BootOrder, &BootOrderSize);
+      gBS->FreePool (BootOptionVar);
+      break;
+    }
+
+    gBS->FreePool (BootOptionVar);
+    Index++;
+  }
+
+  Status = gRT->SetVariable (
+                  L"BootOrder",
+                  &gEfiGlobalVariableGuid,
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                  BootOrderSize,
+                  BootOrder
+                  );
+
+  gBS->FreePool (BootOrder);
+
+  return Status;
+}
+
+
+/**
+  Delete all invalid EFI boot options. The probable invalid boot option could
+  be Removable media or Network boot device.
+
+  VOID
+
+  @retval EFI_SUCCESS            Delete all invalid boot option success
+  @retval EFI_NOT_FOUND          Variable "BootOrder" is not found
+  @retval EFI_OUT_OF_RESOURCES   Lack of memory resource
+  @retval Other                  Error return value from SetVariable()
+
+**/
+EFI_STATUS
+BdsDeleteAllInvalidEfiBootOption (
+  VOID
+  )
+{
+  UINT16                    *BootOrder;
+  UINT8                     *BootOptionVar;
+  UINTN                     BootOrderSize;
+  UINTN                     BootOptionSize;
+  EFI_STATUS                Status;
+  UINTN                     Index;
+  UINTN                     Index2;
+  UINT16                    BootOption[BOOT_OPTION_MAX_CHAR];
+  EFI_DEVICE_PATH_PROTOCOL  *OptionDevicePath;
+  UINT8                     *TempPtr;
+
+  Status        = EFI_SUCCESS;
+  BootOrder     = NULL;
+  BootOrderSize = 0;
+
+  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) {
+      gBS->FreePool (BootOrder);
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    TempPtr = BootOptionVar;
+    TempPtr += sizeof (UINT32) + sizeof (UINT16);
+    TempPtr += StrSize ((CHAR16 *) TempPtr);
+    OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
+
+    //
+    // Skip legacy boot option (BBS boot device)
+    //
+    if ((DevicePathType (OptionDevicePath) == BBS_DEVICE_PATH) &&
+        (DevicePathSubType (OptionDevicePath) == BBS_BBS_DP)) {
+      gBS->FreePool (BootOptionVar);
+      Index++;
+      continue;
+    }
+
+    if (!BdsLibIsValidEFIBootOptDevicePath (OptionDevicePath, FALSE)) {
+      //
+      // Delete this invalid boot option "Boot####"
+      //
+      Status = gRT->SetVariable (
+                      BootOption,
+                      &gEfiGlobalVariableGuid,
+                      EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                      0,
+                      NULL
+                      );
+      //
+      // Mark this boot option in boot order as deleted
+      //
+      BootOrder[Index] = 0xffff;
+    }
+
+    gBS->FreePool (BootOptionVar);
+    Index++;
+  }
+
+  //
+  // Adjust boot order array
+  //
+  Index2 = 0;
+  for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
+    if (BootOrder[Index] != 0xffff) {
+      BootOrder[Index2] = BootOrder[Index];
+      Index2 ++;
+    }
+  }
+  Status = gRT->SetVariable (
+                  L"BootOrder",
+                  &gEfiGlobalVariableGuid,
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                  Index2 * sizeof (UINT16),
+                  BootOrder
+                  );
+
+  gBS->FreePool (BootOrder);
+
+  return Status;
+}
+
+
+/**
+  This function will enumerate all possible boot device in the system,
+  it will only excute once of every boot.
+
+  @param  BdsBootOptionList      The header of the link list which indexed all
+                                 current boot options
+
+  @retval EFI_SUCCESS            Finished all the boot device enumerate and create
+                                 the boot option base on that boot device
+
+**/
+EFI_STATUS
+BdsLibEnumerateAllBootOption (
+  IN OUT LIST_ENTRY          *BdsBootOptionList
+  )
+{
+  EFI_STATUS                    Status;
+  UINT16                        FloppyNumber;
+  UINT16                        CdromNumber;
+  UINT16                        UsbNumber;
+  UINT16                        MiscNumber;
+  UINT16                        NonBlockNumber;
+  UINTN                         NumberBlockIoHandles;
+  EFI_HANDLE                    *BlockIoHandles;
+  EFI_BLOCK_IO_PROTOCOL         *BlkIo;
+  UINTN                         Index;
+  UINTN                         NumberSimpleNetworkHandles;
+  EFI_HANDLE                    *SimpleNetworkHandles;
+  UINTN                         FvHandleCount;
+  EFI_HANDLE                    *FvHandleBuffer;
+  EFI_FV_FILETYPE               Type;
+  UINTN                         Size;
+  EFI_FV_FILE_ATTRIBUTES        Attributes;
+  UINT32                        AuthenticationStatus;
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+  EFI_FIRMWARE_VOLUME_PROTOCOL  *Fv;
+#else
+  EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv;
+#endif
+  EFI_DEVICE_PATH_PROTOCOL     *DevicePath;
+  UINTN                         DevicePathType;
+  CHAR16                        Buffer[40];
+  EFI_HANDLE                    *FileSystemHandles;
+  UINTN                         NumberFileSystemHandles;
+  BOOLEAN                       NeedDelete;
+  EFI_IMAGE_DOS_HEADER          DosHeader;
+  EFI_IMAGE_OPTIONAL_HEADER_UNION       HdrData;
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;
+
+  FloppyNumber = 0;
+  CdromNumber = 0;
+  UsbNumber = 0;
+  MiscNumber = 0;
+  ZeroMem (Buffer, sizeof (Buffer));
+  //
+  // If the boot device enumerate happened, just get the boot
+  // device from the boot order variable
+  //
+  if (mEnumBootDevice) {
+    BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");
+    return EFI_SUCCESS;
+  }
+  //
+  // Notes: this dirty code is to get the legacy boot option from the
+  // BBS table and create to variable as the EFI boot option, it should
+  // be removed after the CSM can provide legacy boot option directly
+  //
+  REFRESH_LEGACY_BOOT_OPTIONS;
+
+  //
+  // Delete invalid boot option
+  //
+  BdsDeleteAllInvalidEfiBootOption ();
+  //
+  // Parse removable media
+  //
+  gBS->LocateHandleBuffer (
+        ByProtocol,
+        &gEfiBlockIoProtocolGuid,
+        NULL,
+        &NumberBlockIoHandles,
+        &BlockIoHandles
+        );
+  for (Index = 0; Index < NumberBlockIoHandles; Index++) {
+    Status = gBS->HandleProtocol (
+                    BlockIoHandles[Index],
+                    &gEfiBlockIoProtocolGuid,
+                    (VOID **) &BlkIo
+                    );
+    if (!EFI_ERROR (Status)) {
+      if (!BlkIo->Media->RemovableMedia) {
+        //
+        // skip the non-removable block devices
+        //
+        continue;
+      }
+    }
+    DevicePath  = DevicePathFromHandle (BlockIoHandles[Index]);
+    DevicePathType = BdsGetBootTypeFromDevicePath (DevicePath);
+
+    switch (DevicePathType) {
+    case BDS_EFI_ACPI_FLOPPY_BOOT:
+      if (FloppyNumber == 0) {
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Floppy");
+      } else {
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Floppy %d", FloppyNumber);
+      }
+      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
+      FloppyNumber++;
+      break;
+
+    case BDS_EFI_MESSAGE_ATAPI_BOOT:
+      if (CdromNumber == 0) {
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI DVD/CDROM");
+      } else {
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI DVD/CDROM %d", CdromNumber);
+      }
+      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
+      CdromNumber++;
+      break;
+
+    case BDS_EFI_MESSAGE_USB_DEVICE_BOOT:
+      if (UsbNumber == 0) {
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI USB Device");
+      } else {
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI USB Device %d", UsbNumber);
+      }
+      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
+      UsbNumber++;
+      break;
+
+    case BDS_EFI_MESSAGE_SCSI_BOOT:
+      if (UsbNumber == 0) {
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI SCSI Device");
+      } else {
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI SCSI Device %d", UsbNumber);
+      }
+      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
+      UsbNumber++;
+      break;
+
+    case BDS_EFI_MESSAGE_MISC_BOOT:
+      if (MiscNumber == 0) {
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Misc Device");
+      } else {
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Misc Device %d", MiscNumber);
+      }
+      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
+      MiscNumber++;
+      break;
+
+    default:
+      break;
+    }
+  }
+
+  if (NumberBlockIoHandles) {
+    gBS->FreePool (BlockIoHandles);
+  }
+
+  //
+  // If there is simple file protocol which does not consume block Io protocol, create a boot option for it here.
+  //
+  NonBlockNumber = 0;
+  gBS->LocateHandleBuffer (
+        ByProtocol,
+        &gEfiSimpleFileSystemProtocolGuid,
+        NULL,
+        &NumberFileSystemHandles,
+        &FileSystemHandles
+        );
+  for (Index = 0; Index < NumberFileSystemHandles; Index++) {
+    Status = gBS->HandleProtocol (
+                    FileSystemHandles[Index],
+                    &gEfiBlockIoProtocolGuid,
+                    (VOID **) &BlkIo
+                    );
+     if (!EFI_ERROR (Status)) {
+      //
+      //  Skip if the file system handle supports a BlkIo protocol,
+      //
+      continue;
+    }
+
+    //
+    // Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI
+    //  machinename is ia32, ia64, x64, ...
+    //
+    Hdr.Union = &HdrData;
+    NeedDelete = TRUE;
+    Status     = BdsLibGetImageHeader (
+                   FileSystemHandles[Index],
+                   DEFAULT_REMOVABLE_FILE_NAME,
+                   &DosHeader,
+                   Hdr
+                   );
+    if (!EFI_ERROR (Status) &&
+        EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&
+        Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
+      NeedDelete = FALSE;
+    }
+
+    if (NeedDelete) {
+      //
+      // No such file or the file is not a EFI application, delete this boot option
+      //
+      BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]);
+    } else {
+      if (NonBlockNumber == 0) {
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Non-Block Boot Device");
+      } else {
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Non-Block Boot Device %d", NonBlockNumber);
+      }
+      BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList, Buffer);
+      NonBlockNumber++;
+    }
+  }
+
+  if (NumberFileSystemHandles) {
+    gBS->FreePool (FileSystemHandles);
+  }
+
+  //
+  // Parse Network Boot Device
+  //
+  gBS->LocateHandleBuffer (
+        ByProtocol,
+        &gEfiSimpleNetworkProtocolGuid,
+        NULL,
+        &NumberSimpleNetworkHandles,
+        &SimpleNetworkHandles
+        );
+  for (Index = 0; Index < NumberSimpleNetworkHandles; Index++) {
+    if (Index == 0) {
+      UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Network");
+    } else {
+      UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Network %d", Index);
+    }
+    BdsLibBuildOptionFromHandle (SimpleNetworkHandles[Index], BdsBootOptionList, Buffer);
+  }
+
+  if (NumberSimpleNetworkHandles) {
+    gBS->FreePool (SimpleNetworkHandles);
+  }
+
+  //
+  // Check if we have on flash shell
+  //
+  gBS->LocateHandleBuffer (
+        ByProtocol,
+     #if (PI_SPECIFICATION_VERSION < 0x00010000)
+        &gEfiFirmwareVolumeProtocolGuid,
+     #else
+        &gEfiFirmwareVolume2ProtocolGuid,
+     #endif
+        NULL,
+        &FvHandleCount,
+        &FvHandleBuffer
+        );
+  for (Index = 0; Index < FvHandleCount; Index++) {
+    gBS->HandleProtocol (
+          FvHandleBuffer[Index],
+       #if (PI_SPECIFICATION_VERSION < 0x00010000)
+          &gEfiFirmwareVolumeProtocolGuid,
+       #else
+          &gEfiFirmwareVolume2ProtocolGuid,
+       #endif
+          (VOID **) &Fv
+          );
+
+    Status = Fv->ReadFile (
+                  Fv,
+                  &gEfiShellFileGuid,
+                  NULL,
+                  &Size,
+                  &Type,
+                  &Attributes,
+                  &AuthenticationStatus
+                  );
+    if (EFI_ERROR (Status)) {
+      //
+      // Skip if no shell file in the FV
+      //
+      continue;
+    }
+    //
+    // Build the shell boot option
+    //
+    BdsLibBuildOptionFromShell (FvHandleBuffer[Index], BdsBootOptionList);
+  }
+
+  if (FvHandleCount) {
+    gBS->FreePool (FvHandleBuffer);
+  }
+  //
+  // Make sure every boot only have one time
+  // boot device enumerate
+  //
+  BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");
+  mEnumBootDevice = TRUE;
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Build the boot option with the handle parsed in
+
+  @param  Handle                 The handle which present the device path to create
+                                 boot option
+  @param  BdsBootOptionList      The header of the link list which indexed all
+                                 current boot options
+
+  @return VOID
+
+**/
+VOID
+BdsLibBuildOptionFromHandle (
+  IN  EFI_HANDLE                 Handle,
+  IN  LIST_ENTRY                 *BdsBootOptionList,
+  IN  CHAR16                     *String
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+
+  DevicePath  = DevicePathFromHandle (Handle);
+
+  //
+  // Create and register new boot option
+  //
+  BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, String, L"BootOrder");
+}
+
+
+/**
+  Build the on flash shell boot option with the handle parsed in
+
+  @param  Handle                 The handle which present the device path to create
+                                 on flash shell boot option
+  @param  BdsBootOptionList      The header of the link list which indexed all
+                                 current boot options
+
+  @return None
+
+**/
+VOID
+BdsLibBuildOptionFromShell (
+  IN EFI_HANDLE                  Handle,
+  IN OUT LIST_ENTRY              *BdsBootOptionList
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ShellNode;
+
+  DevicePath = DevicePathFromHandle (Handle);
+
+  //
+  // Build the shell device path
+  //
+  EfiInitializeFwVolDevicepathNode (&ShellNode, &gEfiShellFileGuid);
+  //
+  //ShellNode.Header.Type     = MEDIA_DEVICE_PATH;
+  //ShellNode.Header.SubType  = MEDIA_FV_FILEPATH_DP;
+  //SetDevicePathNodeLength (&ShellNode.Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));
+  //CopyMem (&ShellNode.NameGuid, &gEfiShellFileGuid, sizeof (EFI_GUID));
+  //
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &ShellNode);
+
+  //
+  // Create and register the shell boot option
+  //
+  BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, L"EFI Internal Shell", L"BootOrder");
+
+}
+
+
+/**
+  Boot from the EFI1.1 spec defined "BootNext" variable
+
+  None
+
+  @return None
+
+**/
+VOID
+BdsLibBootNext (
+  VOID
+  )
+{
+  UINT16            *BootNext;
+  UINTN             BootNextSize;
+  CHAR16            Buffer[20];
+  BDS_COMMON_OPTION *BootOption;
+  LIST_ENTRY        TempList;
+  UINTN             ExitDataSize;
+  CHAR16            *ExitData;
+
+  //
+  // Init the boot option name buffer and temp link list
+  //
+  InitializeListHead (&TempList);
+  ZeroMem (Buffer, sizeof (Buffer));
+
+  BootNext = BdsLibGetVariableAndSize (
+              L"BootNext",
+              &gEfiGlobalVariableGuid,
+              &BootNextSize
+              );
+
+  //
+  // Clear the boot next variable first
+  //
+  if (BootNext != NULL) {
+    gRT->SetVariable (
+          L"BootNext",
+          &gEfiGlobalVariableGuid,
+          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+          0,
+          BootNext
+          );
+
+    //
+    // Start to build the boot option and try to boot
+    //
+    UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *BootNext);
+    BootOption = BdsLibVariableToOption (&TempList, Buffer);
+    BdsLibConnectDevicePath (BootOption->DevicePath);
+    BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
+  }
+
+}
+
+
+
+/**
+  Return the bootable media handle.
+  First, check the device is connected
+  Second, check whether the device path point to a device which support SimpleFileSystemProtocol,
+  Third, detect the the default boot file in the Media, and return the removable Media handle.
+
+  @param  DevicePath             Device Path to a  bootable device
+
+  @retval NULL                   The device path points to an EFI bootable Media
+  @retval NULL                   The media on the DevicePath is not bootable
+
+**/
+EFI_HANDLE
+BdsLibGetBootableHandle (
+  IN  EFI_DEVICE_PATH_PROTOCOL      *DevicePath
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_DEVICE_PATH_PROTOCOL        *UpdatedDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL        *DupDevicePath;
+  EFI_HANDLE                      Handle;
+  EFI_BLOCK_IO_PROTOCOL           *BlockIo;
+  VOID                            *Buffer;
+  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
+  UINTN                           Size;
+  UINTN                           TempSize;
+  EFI_HANDLE                      ReturnHandle;
+  EFI_HANDLE                      *SimpleFileSystemHandles;
+
+  UINTN                           NumberSimpleFileSystemHandles;
+  UINTN                           Index;
+  EFI_IMAGE_DOS_HEADER            DosHeader;
+  EFI_IMAGE_OPTIONAL_HEADER_UNION       HdrData;
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;
+
+  UpdatedDevicePath = DevicePath;
+  //
+  // Check whether the device is connected
+  //
+  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &UpdatedDevicePath, &Handle);
+  if (EFI_ERROR (Status)) {
+    //
+    // Skip the case that the boot option point to a simple file protocol which does not consume block Io protocol,
+    //
+    Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &UpdatedDevicePath, &Handle);
+    if (EFI_ERROR (Status)) {
+      //
+      // Fail to find the proper BlockIo and simple file protocol, maybe because device not present,  we need to connect it firstly
+      //
+      UpdatedDevicePath = DevicePath;
+      Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle);
+      gBS->ConnectController (Handle, NULL, NULL, TRUE);
+    }
+  } else {
+    //
+    // Get BlockIo protocal and check removable attribute
+    //
+    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
+    //
+    // Issue a dummy read to the device to check for media change.
+    // When the removable media is changed, any Block IO read/write will
+    // cause the BlockIo protocol be reinstalled and EFI_MEDIA_CHANGED is
+    // returned. After the Block IO protocol is reinstalled, subsequent
+    // Block IO read/write will success.
+    //
+    Buffer = AllocatePool (BlockIo->Media->BlockSize);
+    if (Buffer != NULL) {
+      BlockIo->ReadBlocks (
+               BlockIo,
+               BlockIo->Media->MediaId,
+               0,
+               BlockIo->Media->BlockSize,
+               Buffer
+               );
+      gBS->FreePool (Buffer);
+    }
+  }
+
+  //
+  // Detect the the default boot file from removable Media
+  //
+
+  //
+  // If fail to get bootable handle specified by a USB boot option, the BDS should try to find other bootable device in the same USB bus
+  // Try to locate the USB node device path first, if fail then use its previour PCI node to search
+  //
+  DupDevicePath = DuplicateDevicePath (DevicePath);
+  UpdatedDevicePath = DupDevicePath;
+  Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle);
+  //
+  // if the resulting device path point to a usb node, and the usb node is a dummy node, should only let device path only point to the previous Pci node
+  // Acpi()/Pci()/Usb() --> Acpi()/Pci()
+  //
+  if ((DevicePathType (UpdatedDevicePath) == MESSAGING_DEVICE_PATH) &&
+      (DevicePathSubType (UpdatedDevicePath) == MSG_USB_DP)) {
+    //
+    // Remove the usb node, let the device path only point to PCI node
+    //
+    SetDevicePathEndNode (UpdatedDevicePath);
+    UpdatedDevicePath = DupDevicePath;
+  } else {
+    UpdatedDevicePath = DevicePath;
+  }
+
+  //
+  // Get the device path size of boot option
+  //
+  Size = GetDevicePathSize(UpdatedDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node
+  ReturnHandle = NULL;
+  gBS->LocateHandleBuffer (
+      ByProtocol,
+      &gEfiSimpleFileSystemProtocolGuid,
+      NULL,
+      &NumberSimpleFileSystemHandles,
+      &SimpleFileSystemHandles
+      );
+  for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {
+    //
+    // Get the device path size of SimpleFileSystem handle
+    //
+    TempDevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);
+    TempSize = GetDevicePathSize (TempDevicePath)- sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node
+    //
+    // Check whether the device path of boot option is part of the  SimpleFileSystem handle's device path
+    //
+    if (Size <= TempSize && CompareMem (TempDevicePath, UpdatedDevicePath, Size)==0) {
+      //
+      // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media
+      //  machinename is ia32, ia64, x64, ...
+      //
+      Hdr.Union = &HdrData;
+      Status = BdsLibGetImageHeader (
+                 SimpleFileSystemHandles[Index],
+                 DEFAULT_REMOVABLE_FILE_NAME,
+                 &DosHeader,
+                 Hdr
+                 );
+      if (!EFI_ERROR (Status) &&
+        EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&
+        Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
+        ReturnHandle = SimpleFileSystemHandles[Index];
+        break;
+      }
+    }
+  }
+
+  if (DupDevicePath != NULL) {
+    SafeFreePool(DupDevicePath);
+  }
+  if (SimpleFileSystemHandles !=NULL ) {
+    gBS->FreePool (SimpleFileSystemHandles);
+  }
+
+  return ReturnHandle;
+}
+
+
+
+
+/**
+  Check to see if the network cable is plugged in. If the DevicePath is not
+  connected it will be connected.
+
+  @param  DevicePath             Device Path to check
+
+  @retval TRUE                   DevicePath points to an Network that is connected
+  @retval FALSE                  DevicePath does not point to a bootable network
+
+**/
+BOOLEAN
+BdsLibNetworkBootWithMediaPresent (
+  IN  EFI_DEVICE_PATH_PROTOCOL      *DevicePath
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_DEVICE_PATH_PROTOCOL        *UpdatedDevicePath;
+  EFI_HANDLE                      Handle;
+  EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;
+  BOOLEAN                         MediaPresent;
+
+  MediaPresent = FALSE;
+
+  UpdatedDevicePath = DevicePath;
+  Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);
+  if (EFI_ERROR (Status)) {
+    //
+    // Device not present so see if we need to connect it
+    //
+    Status = BdsLibConnectDevicePath (DevicePath);
+    if (!EFI_ERROR (Status)) {
+      //
+      // This one should work after we did the connect
+      //
+      Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);
+    }
+  }
+
+  if (!EFI_ERROR (Status)) {
+    Status = gBS->HandleProtocol (Handle, &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);
+    if (!EFI_ERROR (Status)) {
+      if (Snp->Mode->MediaPresentSupported) {
+        if (Snp->Mode->State == EfiSimpleNetworkInitialized) {
+          //
+          // In case some one else is using the SNP check to see if it's connected
+          //
+          MediaPresent = Snp->Mode->MediaPresent;
+        } else {
+          //
+          // No one is using SNP so we need to Start and Initialize so
+          // MediaPresent will be valid.
+          //
+          Status = Snp->Start (Snp);
+          if (!EFI_ERROR (Status)) {
+            Status = Snp->Initialize (Snp, 0, 0);
+            if (!EFI_ERROR (Status)) {
+              MediaPresent = Snp->Mode->MediaPresent;
+              Snp->Shutdown (Snp);
+            }
+            Snp->Stop (Snp);
+          }
+        }
+      } else {
+        MediaPresent = TRUE;
+      }
+    }
+  }
+
+  return MediaPresent;
+}
+
+
+
+/**
+  For a bootable Device path, return its boot type
+
+  @param  DevicePath             The bootable device Path to check
+
+  @return UINT32 Boot type :
+  @return //
+  @return // If the device path contains any media deviec path node, it is media boot type
+  @return // For the floppy node, handle it as media node
+  @return //
+  @return BDS_EFI_MEDIA_HD_BOOT
+  @return BDS_EFI_MEDIA_CDROM_BOOT
+  @return BDS_EFI_ACPI_FLOPPY_BOOT
+  @return //
+  @return // If the device path not contains any media deviec path node,  and
+  @return // its last device path node point to a message device path node, it is
+  @return // a message boot type
+  @return //
+  @return BDS_EFI_MESSAGE_ATAPI_BOOT
+  @return BDS_EFI_MESSAGE_SCSI_BOOT
+  @return BDS_EFI_MESSAGE_USB_DEVICE_BOOT
+  @return BDS_EFI_MESSAGE_MISC_BOOT
+  @return //
+  @return // Legacy boot type
+  @return //
+  @return BDS_LEGACY_BBS_BOOT
+  @return //
+  @return // If a EFI Removable BlockIO device path not point to a media and message devie,
+  @return // it is unsupported
+  @return //
+  @return BDS_EFI_UNSUPPORT
+
+**/
+UINT32
+BdsGetBootTypeFromDevicePath (
+  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
+  )
+{
+  ACPI_HID_DEVICE_PATH          *Acpi;
+  EFI_DEVICE_PATH_PROTOCOL      *TempDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL      *LastDeviceNode;
+
+
+  if (NULL == DevicePath) {
+    return BDS_EFI_UNSUPPORT;
+  }
+
+  TempDevicePath = DevicePath;
+
+  while (!IsDevicePathEndType (TempDevicePath)) {
+    switch (DevicePathType (TempDevicePath)) {
+      case BBS_DEVICE_PATH:
+         return BDS_LEGACY_BBS_BOOT;
+      case MEDIA_DEVICE_PATH:
+        if (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP) {
+          return BDS_EFI_MEDIA_HD_BOOT;
+        } else if (DevicePathSubType (TempDevicePath) == MEDIA_CDROM_DP) {
+          return BDS_EFI_MEDIA_CDROM_BOOT;
+        }
+        break;
+      case ACPI_DEVICE_PATH:
+        Acpi = (ACPI_HID_DEVICE_PATH *) TempDevicePath;
+        if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {
+          return BDS_EFI_ACPI_FLOPPY_BOOT;
+        }
+        break;
+      case MESSAGING_DEVICE_PATH:
+        //
+        // if the device path not only point to driver device, it is not a messaging device path.
+        //
+        LastDeviceNode = NextDevicePathNode (TempDevicePath);
+        if (!IsDevicePathEndType (LastDeviceNode)) {
+          break;
+        }
+
+        if (DevicePathSubType(TempDevicePath) == MSG_ATAPI_DP) {
+          return BDS_EFI_MESSAGE_ATAPI_BOOT;
+        } else if (DevicePathSubType(TempDevicePath) == MSG_USB_DP) {
+          return BDS_EFI_MESSAGE_USB_DEVICE_BOOT;
+        } else if (DevicePathSubType(TempDevicePath) == MSG_SCSI_DP) {
+          return BDS_EFI_MESSAGE_SCSI_BOOT;
+        }
+        return BDS_EFI_MESSAGE_MISC_BOOT;
+      default:
+        break;
+    }
+    TempDevicePath = NextDevicePathNode (TempDevicePath);
+  }
+
+  return BDS_EFI_UNSUPPORT;
+}
+
+
+/**
+  Check whether the Device path in a boot option point to a valide bootable device,
+  And if CheckMedia is true, check the device is ready to boot now.
+
+  DevPath -- the Device path in a boot option
+  CheckMedia -- if true, check the device is ready to boot now.
+
+  @return TRUE      -- the Device path  is valide
+  @return FALSE   -- the Device path  is invalide .
+
+**/
+BOOLEAN
+BdsLibIsValidEFIBootOptDevicePath (
+  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath,
+  IN BOOLEAN                      CheckMedia
+  )
+{
+  EFI_STATUS                Status;
+  EFI_HANDLE                Handle;
+  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *LastDeviceNode;
+  EFI_BLOCK_IO_PROTOCOL     *BlockIo;
+
+  TempDevicePath = DevPath;
+  LastDeviceNode = DevPath;
+  //
+  // Check if it's a valid boot option for network boot device
+  // Only check if there is SimpleNetworkProtocol installed. If yes, that means
+  // there is the network card there.
+  //
+  Status = gBS->LocateDevicePath (
+                  &gEfiSimpleNetworkProtocolGuid,
+                  &TempDevicePath,
+                  &Handle
+                  );
+  if (EFI_ERROR (Status)) {
+    //
+    // Device not present so see if we need to connect it
+    //
+    TempDevicePath = DevPath;
+    BdsLibConnectDevicePath (TempDevicePath);
+    Status = gBS->LocateDevicePath (
+                    &gEfiSimpleNetworkProtocolGuid,
+                    &TempDevicePath,
+                    &Handle
+                    );
+  }
+  if (!EFI_ERROR (Status)) {
+    if (CheckMedia) {
+      //
+      // Test if it is ready to boot now
+      //
+      if (BdsLibNetworkBootWithMediaPresent(DevPath)) {
+        return TRUE;
+      }
+    } else {
+      return TRUE;
+    }
+  }
+
+  //
+  // If the boot option point to a file, it is a valid EFI boot option,
+  // and assume it is ready to boot now
+  //
+  while (!EfiIsDevicePathEnd (TempDevicePath)) {
+     LastDeviceNode = TempDevicePath;
+     TempDevicePath = EfiNextDevicePathNode (TempDevicePath);
+  }
+  if ((DevicePathType (LastDeviceNode) == MEDIA_DEVICE_PATH) &&
+    (DevicePathSubType (LastDeviceNode) == MEDIA_FILEPATH_DP)) {
+    return TRUE;
+  }
+
+  //
+  // If the boot option point to a internal Shell, it is a valid EFI boot option,
+  // and assume it is ready to boot now
+  //
+  if (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode) != NULL) {
+     return TRUE;
+  }
+
+  //
+  // If the boot option point to a blockIO device, no matter whether or not it is a removeable device, it is a valid EFI boot option
+  //
+  TempDevicePath = DevPath;
+  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);
+  if (EFI_ERROR (Status)) {
+    //
+    // Device not present so see if we need to connect it
+    //
+    Status = BdsLibConnectDevicePath (DevPath);
+    if (!EFI_ERROR (Status)) {
+      //
+      // Try again to get the Block Io protocol after we did the connect
+      //
+      TempDevicePath = DevPath;
+      Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);
+    }
+  }
+  if (!EFI_ERROR (Status)) {
+    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
+    if (!EFI_ERROR (Status)) {
+      if (CheckMedia) {
+        //
+        // Test if it is ready to boot now
+        //
+        if (BdsLibGetBootableHandle (DevPath) != NULL) {
+          return TRUE;
+        }
+      } else {
+        return TRUE;
+      }
+    }
+  } else {
+    //
+    // if the boot option point to a simple file protocol which does not consume block Io protocol, it is also a valid EFI boot option,
+    //
+    Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &TempDevicePath, &Handle);
+    if (!EFI_ERROR (Status)) {
+      if (CheckMedia) {
+        //
+        // Test if it is ready to boot now
+        //
+        if (BdsLibGetBootableHandle (DevPath) != NULL) {
+          return TRUE;
+        }
+      } else {
+        return TRUE;
+      }
+    }
+  }
+
+  return FALSE;
+}
+
+
+/**
+  According to a file guild, check a Fv file device path is valid. If it is invalid,
+  try to return the valid device path.
+  FV address maybe changes for memory layout adjust from time to time, use this funciton
+  could promise the Fv file device path is right.
+
+  @param  DevicePath             on input, the Fv file device path need to check on
+                                 output, the updated valid Fv file device path
+  @param  FileGuid               the Fv file guild
+
+  @retval EFI_INVALID_PARAMETER  the input DevicePath or FileGuid is invalid
+                                 parameter
+  @retval EFI_UNSUPPORTED        the input DevicePath does not contain Fv file
+                                 guild at all
+  @retval EFI_ALREADY_STARTED    the input DevicePath has pointed to Fv file, it is
+                                 valid
+  @retval EFI_SUCCESS            has successfully updated the invalid DevicePath,
+                                 and return the updated device path in DevicePath
+
+**/
+EFI_STATUS
+EFIAPI
+BdsLibUpdateFvFileDevicePath (
+  IN  OUT EFI_DEVICE_PATH_PROTOCOL      ** DevicePath,
+  IN  EFI_GUID                          *FileGuid
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL      *TempDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL      *LastDeviceNode;
+  EFI_STATUS                    Status;
+  EFI_GUID                      *GuidPoint;
+  UINTN                         Index;
+  UINTN                         FvHandleCount;
+  EFI_HANDLE                    *FvHandleBuffer;
+  EFI_FV_FILETYPE               Type;
+  UINTN                         Size;
+  EFI_FV_FILE_ATTRIBUTES        Attributes;
+  UINT32                        AuthenticationStatus;
+  BOOLEAN                       FindFvFile;
+  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+  EFI_FIRMWARE_VOLUME_PROTOCOL  *Fv;
+#else
+  EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+#endif
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode;
+  EFI_HANDLE                    FoundFvHandle;
+  EFI_DEVICE_PATH_PROTOCOL      *NewDevicePath;
+
+  if ((DevicePath == NULL) || (*DevicePath == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+  if (FileGuid == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  //
+  // Check whether the device path point to the default the input Fv file
+  //
+  TempDevicePath = *DevicePath;
+  LastDeviceNode = TempDevicePath;
+  while (!EfiIsDevicePathEnd (TempDevicePath)) {
+     LastDeviceNode = TempDevicePath;
+     TempDevicePath = EfiNextDevicePathNode (TempDevicePath);
+  }
+  GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode (
+                (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode
+                );
+  if (GuidPoint == NULL) {
+    //
+    // if this option does not points to a Fv file, just return EFI_UNSUPPORTED
+    //
+    return EFI_UNSUPPORTED;
+  }
+  if (!CompareGuid (GuidPoint, FileGuid)) {
+    //
+    // If the Fv file is not the input file guid, just return EFI_UNSUPPORTED
+    //
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check whether the input Fv file device path is valid
+  //
+  TempDevicePath = *DevicePath;
+  FoundFvHandle = NULL;
+  Status = gBS->LocateDevicePath (
+                #if (PI_SPECIFICATION_VERSION < 0x00010000)
+                  &gEfiFirmwareVolumeProtocolGuid,
+                #else
+                  &gEfiFirmwareVolume2ProtocolGuid,
+                #endif
+                  &TempDevicePath,
+                  &FoundFvHandle
+                  );
+  if (!EFI_ERROR (Status)) {
+    Status = gBS->HandleProtocol (
+                    FoundFvHandle,
+                  #if (PI_SPECIFICATION_VERSION < 0x00010000)
+                    &gEfiFirmwareVolumeProtocolGuid,
+                  #else
+                    &gEfiFirmwareVolume2ProtocolGuid,
+                  #endif
+                    (VOID **) &Fv
+                    );
+    if (!EFI_ERROR (Status)) {
+      //
+      // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there
+      //
+      Status = Fv->ReadFile (
+                    Fv,
+                    FileGuid,
+                    NULL,
+                    &Size,
+                    &Type,
+                    &Attributes,
+                    &AuthenticationStatus
+                    );
+      if (!EFI_ERROR (Status)) {
+        return EFI_ALREADY_STARTED;
+      }
+    }
+  }
+
+  //
+  // Look for the input wanted FV file in current FV
+  // First, try to look for in Bds own FV. Bds and input wanted FV file usually are in the same FV
+  //
+  FindFvFile = FALSE;
+  FoundFvHandle = NULL;
+  Status = gBS->HandleProtocol (
+             mBdsImageHandle,
+             &gEfiLoadedImageProtocolGuid,
+             (VOID **) &LoadedImage
+             );
+  if (!EFI_ERROR (Status)) {
+    Status = gBS->HandleProtocol (
+                    LoadedImage->DeviceHandle,
+                  #if (PI_SPECIFICATION_VERSION < 0x00010000)
+                    &gEfiFirmwareVolumeProtocolGuid,
+                  #else
+                    &gEfiFirmwareVolume2ProtocolGuid,
+                  #endif
+                    (VOID **) &Fv
+                    );
+    if (!EFI_ERROR (Status)) {
+      Status = Fv->ReadFile (
+                    Fv,
+                    FileGuid,
+                    NULL,
+                    &Size,
+                    &Type,
+                    &Attributes,
+                    &AuthenticationStatus
+                    );
+      if (!EFI_ERROR (Status)) {
+        FindFvFile = TRUE;
+        FoundFvHandle = LoadedImage->DeviceHandle;
+      }
+    }
+  }
+  //
+  // Second, if fail to find, try to enumerate all FV
+  //
+  if (!FindFvFile) {
+    gBS->LocateHandleBuffer (
+          ByProtocol,
+       #if (PI_SPECIFICATION_VERSION < 0x00010000)
+          &gEfiFirmwareVolumeProtocolGuid,
+       #else
+          &gEfiFirmwareVolume2ProtocolGuid,
+       #endif
+          NULL,
+          &FvHandleCount,
+          &FvHandleBuffer
+          );
+    for (Index = 0; Index < FvHandleCount; Index++) {
+      gBS->HandleProtocol (
+            FvHandleBuffer[Index],
+         #if (PI_SPECIFICATION_VERSION < 0x00010000)
+            &gEfiFirmwareVolumeProtocolGuid,
+         #else
+            &gEfiFirmwareVolume2ProtocolGuid,
+         #endif
+            (VOID **) &Fv
+            );
+
+      Status = Fv->ReadFile (
+                    Fv,
+                    FileGuid,
+                    NULL,
+                    &Size,
+                    &Type,
+                    &Attributes,
+                    &AuthenticationStatus
+                    );
+      if (EFI_ERROR (Status)) {
+        //
+        // Skip if input Fv file not in the FV
+        //
+        continue;
+      }
+      FindFvFile = TRUE;
+      FoundFvHandle = FvHandleBuffer[Index];
+      break;
+    }
+  }
+
+  if (FindFvFile) {
+    //
+    // Build the shell device path
+    //
+    NewDevicePath = DevicePathFromHandle (FoundFvHandle);
+    EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid);
+    NewDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode);
+    *DevicePath = NewDevicePath;
+    return EFI_SUCCESS;
+  }
+  return EFI_NOT_FOUND;
+}
diff --git a/MdeModulePkg/Library/GenericBdsLib/BdsConnect.c b/MdeModulePkg/Library/GenericBdsLib/BdsConnect.c
new file mode 100644 (file)
index 0000000..6e9068b
--- /dev/null
@@ -0,0 +1,424 @@
+/** @file
+
+Copyright (c) 2004 - 2007, Intel Corporation
+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.
+
+Module Name:
+
+  BdsConnect.c
+
+Abstract:
+
+  BDS Lib functions which relate with connect the device
+
+
+**/
+
+#include "InternalBdsLib.h"
+
+
+/**
+  This function will connect all the system driver to controller
+  first, and then special connect the default console, this make
+  sure all the system controller avialbe and the platform default
+  console connected.
+
+  None
+
+  @return None
+
+**/
+VOID
+BdsLibConnectAll (
+  VOID
+  )
+{
+  //
+  // Connect the platform console first
+  //
+  BdsLibConnectAllDefaultConsoles ();
+
+  //
+  // Generic way to connect all the drivers
+  //
+  BdsLibConnectAllDriversToAllControllers ();
+
+  //
+  // Here we have the assumption that we have already had
+  // platform default console
+  //
+  BdsLibConnectAllDefaultConsoles ();
+}
+
+
+/**
+  This function will connect all the system drivers to all controllers
+  first, and then connect all the console devices the system current
+  have. After this we should get all the device work and console avariable
+  if the system have console device.
+
+  None
+
+  @return None
+
+**/
+VOID
+BdsLibGenericConnectAll (
+  VOID
+  )
+{
+  //
+  // Most generic way to connect all the drivers
+  //
+  BdsLibConnectAllDriversToAllControllers ();
+  BdsLibConnectAllConsoles ();
+}
+
+
+/**
+  This function will create all handles associate with every device
+  path node. If the handle associate with one device path node can not
+  be created success, then still give one chance to do the dispatch,
+  which load the missing drivers if possible.
+
+  @param  DevicePathToConnect   The device path which will be connected, it can be
+                                a multi-instance device path
+
+  @retval EFI_SUCCESS           All handles associate with every device path  node
+                                have been created
+  @retval EFI_OUT_OF_RESOURCES  There is no resource to create new handles
+  @retval EFI_NOT_FOUND         Create the handle associate with one device  path
+                                node failed
+
+**/
+EFI_STATUS
+BdsLibConnectDevicePath (
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePathToConnect
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *CopyOfDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;
+  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *Next;
+  EFI_HANDLE                Handle;
+  EFI_HANDLE                PreviousHandle;
+  UINTN                     Size;
+
+  if (DevicePathToConnect == NULL) {
+    return EFI_SUCCESS;
+  }
+
+  DevicePath        = DuplicateDevicePath (DevicePathToConnect);
+  CopyOfDevicePath  = DevicePath;
+  if (DevicePath == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  do {
+    //
+    // The outer loop handles multi instance device paths.
+    // Only console variables contain multiple instance device paths.
+    //
+    // After this call DevicePath points to the next Instance
+    //
+    Instance  = GetNextDevicePathInstance (&DevicePath, &Size);
+    Next      = Instance;
+    while (!IsDevicePathEndType (Next)) {
+      Next = NextDevicePathNode (Next);
+    }
+
+    SetDevicePathEndNode (Next);
+
+    //
+    // Start the real work of connect with RemainingDevicePath
+    //
+    PreviousHandle = NULL;
+    do {
+      //
+      // Find the handle that best matches the Device Path. If it is only a
+      // partial match the remaining part of the device path is returned in
+      // RemainingDevicePath.
+      //
+      RemainingDevicePath = Instance;
+      Status              = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);
+
+      if (!EFI_ERROR (Status)) {
+        if (Handle == PreviousHandle) {
+          //
+          // If no forward progress is made try invoking the Dispatcher.
+          // A new FV may have been added to the system an new drivers
+          // may now be found.
+          // Status == EFI_SUCCESS means a driver was dispatched
+          // Status == EFI_NOT_FOUND means no new drivers were dispatched
+          //
+          Status = gDS->Dispatch ();
+        }
+
+        if (!EFI_ERROR (Status)) {
+          PreviousHandle = Handle;
+          //
+          // Connect all drivers that apply to Handle and RemainingDevicePath,
+          // the Recursive flag is FALSE so only one level will be expanded.
+          //
+          // Do not check the connect status here, if the connect controller fail,
+          // then still give the chance to do dispatch, because partial
+          // RemainingDevicepath may be in the new FV
+          //
+          // 1. If the connect fail, RemainingDevicepath and handle will not
+          //    change, so next time will do the dispatch, then dispatch's status
+          //    will take effect
+          // 2. If the connect success, the RemainingDevicepath and handle will
+          //    change, then avoid the dispatch, we have chance to continue the
+          //    next connection
+          //
+          gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
+        }
+      }
+      //
+      // Loop until RemainingDevicePath is an empty device path
+      //
+    } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
+
+  } while (DevicePath != NULL);
+
+  if (CopyOfDevicePath != NULL) {
+    gBS->FreePool (CopyOfDevicePath);
+  }
+  //
+  // All handle with DevicePath exists in the handle database
+  //
+  return Status;
+}
+
+
+/**
+  This function will connect all current system handles recursively. The
+  connection will finish until every handle's child handle created if it have.
+
+  None
+
+  @retval EFI_SUCCESS           All handles and it's child handle have been
+                                connected
+  @retval EFI_STATUS            Return the status of gBS->LocateHandleBuffer().
+
+**/
+EFI_STATUS
+BdsLibConnectAllEfi (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       HandleCount;
+  EFI_HANDLE  *HandleBuffer;
+  UINTN       Index;
+
+  Status = gBS->LocateHandleBuffer (
+                  AllHandles,
+                  NULL,
+                  NULL,
+                  &HandleCount,
+                  &HandleBuffer
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  for (Index = 0; Index < HandleCount; Index++) {
+    Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
+  }
+
+  gBS->FreePool (HandleBuffer);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  This function will disconnect all current system handles. The disconnection
+  will finish until every handle have been disconnected.
+
+  None
+
+  @retval EFI_SUCCESS           All handles have been disconnected
+  @retval EFI_STATUS            Return the status of gBS->LocateHandleBuffer().
+
+**/
+EFI_STATUS
+BdsLibDisconnectAllEfi (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       HandleCount;
+  EFI_HANDLE  *HandleBuffer;
+  UINTN       Index;
+
+  //
+  // Disconnect all
+  //
+  Status = gBS->LocateHandleBuffer (
+                  AllHandles,
+                  NULL,
+                  NULL,
+                  &HandleCount,
+                  &HandleBuffer
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  for (Index = 0; Index < HandleCount; Index++) {
+    Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
+  }
+
+  gBS->FreePool (HandleBuffer);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Connects all drivers to all controllers.
+  This function make sure all the current system driver will manage
+  the correspoinding controllers if have. And at the same time, make
+  sure all the system controllers have driver to manage it if have.
+
+  None
+
+  @return None
+
+**/
+VOID
+BdsLibConnectAllDriversToAllControllers (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  do {
+    //
+    // Connect All EFI 1.10 drivers following EFI 1.10 algorithm
+    //
+    BdsLibConnectAllEfi ();
+
+    //
+    // Check to see if it's possible to dispatch an more DXE drivers.
+    // The BdsLibConnectAllEfi () may have made new DXE drivers show up.
+    // If anything is Dispatched Status == EFI_SUCCESS and we will try
+    // the connect again.
+    //
+    Status = gDS->Dispatch ();
+
+  } while (!EFI_ERROR (Status));
+
+}
+
+
+/**
+  Connect the specific Usb device which match the short form device path,
+  and whose bus is determined by Host Controller (Uhci or Ehci)
+
+  @param  HostControllerPI      Uhci (0x00) or Ehci (0x20) or Both uhci and ehci
+                                (0xFF)
+  @param  RemainingDevicePath   a short-form device path that starts with the first
+                                element  being a USB WWID or a USB Class device
+                                path
+
+  @return EFI_INVALID_PARAMETER
+  @return EFI_SUCCESS
+  @return EFI_NOT_FOUND
+
+**/
+EFI_STATUS
+BdsLibConnectUsbDevByShortFormDP(
+  IN CHAR8                      HostControllerPI,
+  IN EFI_DEVICE_PATH_PROTOCOL   *RemainingDevicePath
+  )
+{
+  EFI_STATUS                            Status;
+  EFI_HANDLE                            *HandleArray;
+  UINTN                                 HandleArrayCount;
+  UINTN                                 Index;
+  EFI_PCI_IO_PROTOCOL                   *PciIo;
+  UINT8                                 Class[3];
+  BOOLEAN                               AtLeastOneConnected;
+
+  //
+  // Check the passed in parameters
+  //
+  if (RemainingDevicePath == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((DevicePathType (RemainingDevicePath) != MESSAGING_DEVICE_PATH) ||
+      ((DevicePathSubType (RemainingDevicePath) != MSG_USB_CLASS_DP)
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+      && (DevicePathSubType (RemainingDevicePath) != MSG_USB_WWID_DP)
+#endif
+      )) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (HostControllerPI != 0xFF &&
+      HostControllerPI != 0x00 &&
+      HostControllerPI != 0x20) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Find the usb host controller firstly, then connect with the remaining device path
+  //
+  AtLeastOneConnected = FALSE;
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiPciIoProtocolGuid,
+                  NULL,
+                  &HandleArrayCount,
+                  &HandleArray
+                  );
+  if (!EFI_ERROR (Status)) {
+    for (Index = 0; Index < HandleArrayCount; Index++) {
+      Status = gBS->HandleProtocol (
+                      HandleArray[Index],
+                      &gEfiPciIoProtocolGuid,
+                      (VOID **)&PciIo
+                      );
+      if (!EFI_ERROR (Status)) {
+        //
+        // Check whether the Pci device is the wanted usb host controller
+        //
+        Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
+        if (!EFI_ERROR (Status)) {
+          if ((PCI_CLASS_SERIAL == Class[2]) &&
+              (PCI_CLASS_SERIAL_USB == Class[1])) {
+            if (HostControllerPI == Class[0] || HostControllerPI == 0xFF) {
+              Status = gBS->ConnectController (
+                              HandleArray[Index],
+                              NULL,
+                              RemainingDevicePath,
+                              FALSE
+                              );
+              if (!EFI_ERROR(Status)) {
+                AtLeastOneConnected = TRUE;
+              }
+            }
+          }
+        }
+      }
+    }
+
+    if (AtLeastOneConnected) {
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
diff --git a/MdeModulePkg/Library/GenericBdsLib/BdsConsole.c b/MdeModulePkg/Library/GenericBdsLib/BdsConsole.c
new file mode 100644 (file)
index 0000000..db28b68
--- /dev/null
@@ -0,0 +1,399 @@
+/** @file
+
+Copyright (c) 2004 - 2007, Intel Corporation
+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.
+
+Module Name:
+
+  BdsConsole.c
+
+Abstract:
+
+  BDS Lib functions which contain all the code to connect console device
+
+
+**/
+
+#include "InternalBdsLib.h"
+//@MT:#include "EfiPrintLib.h"
+
+BOOLEAN
+IsNvNeed (
+  IN CHAR16 *ConVarName
+  )
+{
+  CHAR16 *Ptr;
+
+  Ptr = ConVarName;
+
+  //
+  // If the variable includes "Dev" at last, we consider
+  // it does not support NV attribute.
+  //
+  while (*Ptr) {
+    Ptr++;
+  }
+
+  if ((*(Ptr-3) == 'D') && (*(Ptr-2) == 'e') && (*(Ptr-1) == 'v')) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+
+/**
+  This function update console variable based on ConVarName, it can
+  add or remove one specific console device path from the variable
+
+  @param  ConVarName               Console related variable name, ConIn, ConOut,
+                                   ErrOut.
+  @param  CustomizedConDevicePath  The console device path which will be added to
+                                   the console variable ConVarName, this parameter
+                                   can not be multi-instance.
+  @param  ExclusiveDevicePath      The console device path which will be removed
+                                   from the console variable ConVarName, this
+                                   parameter can not be multi-instance.
+
+  @retval EFI_UNSUPPORTED          Add or remove the same device path.
+  @retval EFI_SUCCESS              Success add or remove the device path from  the
+                                   console variable.
+
+**/
+EFI_STATUS
+BdsLibUpdateConsoleVariable (
+  IN  CHAR16                    *ConVarName,
+  IN  EFI_DEVICE_PATH_PROTOCOL  *CustomizedConDevicePath,
+  IN  EFI_DEVICE_PATH_PROTOCOL  *ExclusiveDevicePath
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *VarConsole;
+  UINTN                     DevicePathSize;
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;
+  UINT32                    Attributes;
+
+  VarConsole      = NULL;
+  DevicePathSize  = 0;
+
+  //
+  // Notes: check the device path point, here should check
+  // with compare memory
+  //
+  if (CustomizedConDevicePath == ExclusiveDevicePath) {
+    return EFI_UNSUPPORTED;
+  }
+  //
+  // Delete the ExclusiveDevicePath from current default console
+  //
+  VarConsole = BdsLibGetVariableAndSize (
+                ConVarName,
+                &gEfiGlobalVariableGuid,
+                &DevicePathSize
+                );
+
+  //
+  // Initialize NewDevicePath
+  //
+  NewDevicePath  = VarConsole;
+
+  //
+  // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.
+  // In the end, NewDevicePath is the final device path.
+  //
+  if (ExclusiveDevicePath != NULL && VarConsole != NULL) {
+      NewDevicePath = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath);
+  }
+  //
+  // Try to append customized device path to NewDevicePath.
+  //
+  if (CustomizedConDevicePath != NULL) {
+    if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {
+      //
+      // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.
+      //
+      NewDevicePath = BdsLibDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);
+      //
+      // In the first check, the default console variable will be _ModuleEntryPoint,
+      // just append current customized device path
+      //
+      TempNewDevicePath = NewDevicePath;
+      NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);
+      SafeFreePool(TempNewDevicePath);
+    }
+  }
+
+  //
+  // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.
+  //
+  if (IsNvNeed(ConVarName)) {
+    //
+    // ConVarName has NV attribute.
+    //
+    Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;
+  } else {
+    //
+    // ConVarName does not have NV attribute.
+    //
+    Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
+  }
+
+  //
+  // Finally, Update the variable of the default console by NewDevicePath
+  //
+  gRT->SetVariable (
+        ConVarName,
+        &gEfiGlobalVariableGuid,
+        Attributes,
+        GetDevicePathSize (NewDevicePath),
+        NewDevicePath
+        );
+
+  if (VarConsole == NewDevicePath) {
+    SafeFreePool(VarConsole);
+  } else {
+    SafeFreePool(VarConsole);
+    SafeFreePool(NewDevicePath);
+  }
+
+  return EFI_SUCCESS;
+
+}
+
+
+/**
+  Connect the console device base on the variable ConVarName, if
+  device path of the ConVarName is multi-instance device path, if
+  anyone of the instances is connected success, then this function
+  will return success.
+
+  @param  ConVarName               Console related variable name, ConIn, ConOut,
+                                   ErrOut.
+
+  @retval EFI_NOT_FOUND            There is not any console devices connected
+                                   success
+  @retval EFI_SUCCESS              Success connect any one instance of the console
+                                   device path base on the variable ConVarName.
+
+**/
+EFI_STATUS
+BdsLibConnectConsoleVariable (
+  IN  CHAR16                 *ConVarName
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *StartDevicePath;
+  UINTN                     VariableSize;
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;
+  EFI_DEVICE_PATH_PROTOCOL  *Next;
+  EFI_DEVICE_PATH_PROTOCOL  *CopyOfDevicePath;
+  UINTN                     Size;
+  BOOLEAN                   DeviceExist;
+
+  Status      = EFI_SUCCESS;
+  DeviceExist = FALSE;
+
+  //
+  // Check if the console variable exist
+  //
+  StartDevicePath = BdsLibGetVariableAndSize (
+                      ConVarName,
+                      &gEfiGlobalVariableGuid,
+                      &VariableSize
+                      );
+  if (StartDevicePath == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  CopyOfDevicePath = StartDevicePath;
+  do {
+    //
+    // Check every instance of the console variable
+    //
+    Instance  = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);
+    Next      = Instance;
+    while (!IsDevicePathEndType (Next)) {
+      Next = NextDevicePathNode (Next);
+    }
+
+    SetDevicePathEndNode (Next);
+    //
+    // Check USB1.1 console
+    //
+    if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&
+       ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP)
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+       || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)
+#endif
+       )) {
+      //
+      // Check the Usb console in Usb2.0 bus firstly, then Usb1.1 bus
+      //
+      Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_EHCI, Instance);
+      if (!EFI_ERROR (Status)) {
+        DeviceExist = TRUE;
+      }
+
+      Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_UHCI, Instance);
+      if (!EFI_ERROR (Status)) {
+        DeviceExist = TRUE;
+      }
+    } else {
+      //
+      // Connect the instance device path
+      //
+      Status = BdsLibConnectDevicePath (Instance);
+      if (EFI_ERROR (Status)) {
+        //
+        // Delete the instance from the console varialbe
+        //
+        BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance);
+      } else {
+        DeviceExist = TRUE;
+      }
+    }
+    SafeFreePool(Instance);
+  } while (CopyOfDevicePath != NULL);
+
+  gBS->FreePool (StartDevicePath);
+
+  if (DeviceExist == FALSE) {
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  This function will search every simpletxt devive in current system,
+  and make every simpletxt device as pertantial console device.
+
+  None
+
+  @return None
+
+**/
+VOID
+BdsLibConnectAllConsoles (
+  VOID
+  )
+{
+  UINTN                     Index;
+  EFI_DEVICE_PATH_PROTOCOL  *ConDevicePath;
+  UINTN                     HandleCount;
+  EFI_HANDLE                *HandleBuffer;
+
+  Index         = 0;
+  HandleCount   = 0;
+  HandleBuffer  = NULL;
+  ConDevicePath = NULL;
+
+  //
+  // Update all the console varables
+  //
+  gBS->LocateHandleBuffer (
+          ByProtocol,
+          &gEfiSimpleTextInProtocolGuid,
+          NULL,
+          &HandleCount,
+          &HandleBuffer
+          );
+  
+  for (Index = 0; Index < HandleCount; Index++) {
+    gBS->HandleProtocol (
+            HandleBuffer[Index],
+            &gEfiDevicePathProtocolGuid,
+            (VOID **) &ConDevicePath
+            );
+    BdsLibUpdateConsoleVariable (L"ConIn", ConDevicePath, NULL);
+  }
+
+  SafeFreePool(HandleBuffer);
+
+  gBS->LocateHandleBuffer (
+          ByProtocol,
+          &gEfiSimpleTextOutProtocolGuid,
+          NULL,
+          &HandleCount,
+          &HandleBuffer
+          );
+  for (Index = 0; Index < HandleCount; Index++) {
+    gBS->HandleProtocol (
+            HandleBuffer[Index],
+            &gEfiDevicePathProtocolGuid,
+            (VOID **) &ConDevicePath
+            );
+    BdsLibUpdateConsoleVariable (L"ConOut", ConDevicePath, NULL);
+    BdsLibUpdateConsoleVariable (L"ErrOut", ConDevicePath, NULL);
+  }
+
+  SafeFreePool(HandleBuffer);
+
+  //
+  // Connect all console variables
+  //
+  BdsLibConnectAllDefaultConsoles ();
+
+}
+
+
+/**
+  This function will connect console device base on the console
+  device variable ConIn, ConOut and ErrOut.
+
+  None
+
+  @retval EFI_SUCCESS              At least one of the ConIn and ConOut device have
+                                   been connected success.
+  @retval EFI_STATUS               Return the status of
+                                   BdsLibConnectConsoleVariable ().
+
+**/
+EFI_STATUS
+BdsLibConnectAllDefaultConsoles (
+  VOID
+  )
+{
+  EFI_STATUS                Status;
+
+  //
+  // Connect all default console variables
+  //
+
+  //
+  // It seems impossible not to have any ConOut device on platform,
+  // so we check the status here.
+  //
+  Status = BdsLibConnectConsoleVariable (L"ConOut");
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Insert the performance probe for Console Out
+  //
+  PERF_START (NULL, "ConOut", "BDS", 1);
+  PERF_END (NULL, "ConOut", "BDS", 0);
+
+  //
+  // Because possibly the platform is legacy free, in such case,
+  // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,
+  // so we need not check the status.
+  //
+  BdsLibConnectConsoleVariable (L"ConIn");
+
+  //
+  // The _ModuleEntryPoint err out var is legal.
+  //
+  BdsLibConnectConsoleVariable (L"ErrOut");
+
+  return EFI_SUCCESS;
+
+}
diff --git a/MdeModulePkg/Library/GenericBdsLib/BdsMisc.c b/MdeModulePkg/Library/GenericBdsLib/BdsMisc.c
new file mode 100644 (file)
index 0000000..739913b
--- /dev/null
@@ -0,0 +1,1415 @@
+/** @file
+
+Copyright (c) 2004 - 2007, Intel Corporation
+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.
+
+Module Name:
+
+  BdsMisc.c
+
+Abstract:
+
+  Misc BDS library function
+
+
+**/
+
+#include "InternalBdsLib.h"
+
+
+#define MAX_STRING_LEN        200
+
+static BOOLEAN   mFeaturerSwitch = TRUE;
+static BOOLEAN   mResetRequired = FALSE;
+
+extern UINT16 gPlatformBootTimeOutDefault;
+
+
+/**
+  Return the default value for system Timeout variable.
+
+  None
+
+  @return Timeout value.
+
+**/
+UINT16
+BdsLibGetTimeout (
+  VOID
+  )
+{
+  UINT16      Timeout;
+  UINTN       Size;
+  EFI_STATUS  Status;
+
+  //
+  // Return Timeout variable or 0xffff if no valid
+  // Timeout variable exists.
+  //
+  Size    = sizeof (UINT16);
+  Status  = gRT->GetVariable (L"Timeout", &gEfiGlobalVariableGuid, NULL, &Size, &Timeout);
+  if (!EFI_ERROR (Status)) {
+    return Timeout;
+  }
+  //
+  // To make the current EFI Automatic-Test activity possible, just add
+  // following code to make AutoBoot enabled when this variable is not
+  // present.
+  // This code should be removed later.
+  //
+  Timeout = PcdGet16 (PcdPlatformBootTimeOutDefault);
+
+  //
+  // Notes: Platform should set default variable if non exists on all error cases!!!
+  //
+  Status = gRT->SetVariable (
+                  L"Timeout",
+                  &gEfiGlobalVariableGuid,
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                  sizeof (UINT16),
+                  &Timeout
+                  );
+  return Timeout;
+}
+
+
+/**
+  The function will go through the driver optoin link list, load and start
+  every driver the driver optoin device path point to.
+
+  @param  BdsDriverLists        The header of the current driver option link list
+
+  @return None
+
+**/
+VOID
+BdsLibLoadDrivers (
+  IN LIST_ENTRY                   *BdsDriverLists
+  )
+{
+  EFI_STATUS                Status;
+  LIST_ENTRY                *Link;
+  BDS_COMMON_OPTION         *Option;
+  EFI_HANDLE                ImageHandle;
+  EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
+  UINTN                     ExitDataSize;
+  CHAR16                    *ExitData;
+  BOOLEAN                   ReconnectAll;
+
+  ReconnectAll = FALSE;
+
+  //
+  // Process the driver option
+  //
+  for (Link = BdsDriverLists->ForwardLink; Link != BdsDriverLists; Link = Link->ForwardLink) {
+    Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
+    //
+    // 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 (Option->Attribute, LOAD_OPTION_ACTIVE)) {
+      continue;
+    }
+    //
+    // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,
+    // then all of the EFI drivers in the system will be disconnected and
+    // reconnected after the last driver load option is processed.
+    //
+    if (IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_FORCE_RECONNECT)) {
+      ReconnectAll = TRUE;
+    }
+    //
+    // Make sure the driver path is connected.
+    //
+    BdsLibConnectDevicePath (Option->DevicePath);
+
+    //
+    // Load and start the image that Driver#### describes
+    //
+    Status = gBS->LoadImage (
+                    FALSE,
+                    mBdsImageHandle,
+                    Option->DevicePath,
+                    NULL,
+                    0,
+                    &ImageHandle
+                    );
+
+    if (!EFI_ERROR (Status)) {
+      gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
+
+      //
+      // Verify whether this image is a driver, if not,
+      // exit it and continue to parse next load option
+      //
+      if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {
+        gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);
+        continue;
+      }
+
+      if (Option->LoadOptionsSize != 0) {
+        ImageInfo->LoadOptionsSize  = Option->LoadOptionsSize;
+        ImageInfo->LoadOptions      = Option->LoadOptions;
+      }
+      //
+      // Before calling the image, enable the Watchdog Timer for
+      // the 5 Minute period
+      //
+      gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
+
+      Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);
+      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Driver Return Status = %r\n", Status));
+
+      //
+      // Clear the Watchdog Timer after the image returns
+      //
+      gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
+    }
+  }
+  //
+  // Process the LOAD_OPTION_FORCE_RECONNECT driver option
+  //
+  if (ReconnectAll) {
+    BdsLibDisconnectAllEfi ();
+    BdsLibConnectAll ();
+  }
+
+}
+
+
+/**
+  Get the Option Number that does not used
+  Try to locate the specific option variable one by one untile find a free number
+
+  @param  VariableName          Indicate if the boot#### or driver#### option
+
+  @return The Minimal Free Option Number
+
+**/
+UINT16
+BdsLibGetFreeOptionNumber (
+  IN  CHAR16    *VariableName
+  )
+{
+  UINT16        Number;
+  UINTN         Index;
+  CHAR16        StrTemp[10];
+  UINT16        *OptionBuffer;
+  UINTN         OptionSize;
+
+  //
+  // Try to find the minimum free number from 0, 1, 2, 3....
+  //
+  Index = 0;
+  do {
+    if (*VariableName == 'B') {
+      UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Boot%04x", Index);
+    } else {
+      UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Driver%04x", Index);
+    }
+    //
+    // try if the option number is used
+    //
+    OptionBuffer = BdsLibGetVariableAndSize (
+              StrTemp,
+              &gEfiGlobalVariableGuid,
+              &OptionSize
+              );
+    if (OptionBuffer == NULL) {
+      break;
+    }
+    Index++;
+  } while (1);
+
+  Number = (UINT16) Index;
+  return Number;
+}
+
+
+/**
+  This function will register the new boot#### or driver#### option base on
+  the VariableName. The new registered boot#### or driver#### will be linked
+  to BdsOptionList and also update to the VariableName. After the boot#### or
+  driver#### updated, the BootOrder or DriverOrder will also be updated.
+
+  @param  BdsOptionList         The header of the boot#### or driver#### link list
+  @param  DevicePath            The device path which the boot#### or driver####
+                                option present
+  @param  String                The description of the boot#### or driver####
+  @param  VariableName          Indicate if the boot#### or driver#### option
+
+  @retval EFI_SUCCESS           The boot#### or driver#### have been success
+                                registered
+  @retval EFI_STATUS            Return the status of gRT->SetVariable ().
+
+**/
+EFI_STATUS
+BdsLibRegisterNewOption (
+  IN  LIST_ENTRY                     *BdsOptionList,
+  IN  EFI_DEVICE_PATH_PROTOCOL       *DevicePath,
+  IN  CHAR16                         *String,
+  IN  CHAR16                         *VariableName
+  )
+{
+  EFI_STATUS                Status;
+  UINTN                     Index;
+  UINT16                    RegisterOptionNumber;
+  UINT16                    *TempOptionPtr;
+  UINTN                     TempOptionSize;
+  UINT16                    *OptionOrderPtr;
+  VOID                      *OptionPtr;
+  UINTN                     OptionSize;
+  UINT8                     *TempPtr;
+  EFI_DEVICE_PATH_PROTOCOL  *OptionDevicePath;
+  CHAR16                    *Description;
+  CHAR16                    OptionName[10];
+  BOOLEAN                   UpdateBootDevicePath;
+  UINT16                    BootOrderEntry;
+  UINTN                     OrderItemNum;
+
+
+  OptionPtr             = NULL;
+  OptionSize            = 0;
+  TempPtr               = NULL;
+  OptionDevicePath      = NULL;
+  Description           = NULL;
+  OptionOrderPtr        = NULL;
+  UpdateBootDevicePath  = FALSE;
+  ZeroMem (OptionName, sizeof (OptionName));
+
+  TempOptionSize = 0;
+  TempOptionPtr = BdsLibGetVariableAndSize (
+                    VariableName,
+                    &gEfiGlobalVariableGuid,
+                    &TempOptionSize
+                    );
+
+  //
+  // Compare with current option variable
+  //
+  for (Index = 0; Index < TempOptionSize / sizeof (UINT16); Index++) {
+
+    if (*VariableName == 'B') {
+      UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", TempOptionPtr[Index]);
+    } else {
+      UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", TempOptionPtr[Index]);
+    }
+
+    OptionPtr = BdsLibGetVariableAndSize (
+                  OptionName,
+                  &gEfiGlobalVariableGuid,
+                  &OptionSize
+                  );
+    if (OptionPtr == NULL) {
+      continue;
+    }
+    TempPtr = OptionPtr;
+    TempPtr += sizeof (UINT32) + sizeof (UINT16);
+    Description = (CHAR16 *) TempPtr;
+    TempPtr += StrSize ((CHAR16 *) TempPtr);
+    OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
+
+    //
+    // Notes: the description may will change base on the GetStringToken
+    //
+    if (CompareMem (Description, String, StrSize (Description)) == 0) {
+      if (CompareMem (OptionDevicePath, DevicePath, GetDevicePathSize (OptionDevicePath)) == 0) {
+        //
+        // Got the option, so just return
+        //
+        gBS->FreePool (OptionPtr);
+        gBS->FreePool (TempOptionPtr);
+        return EFI_SUCCESS;
+      } else {
+        //
+        // Boot device path changed, need update.
+        //
+        UpdateBootDevicePath = TRUE;
+        break;
+      }
+    }
+
+    gBS->FreePool (OptionPtr);
+  }
+
+  OptionSize          = sizeof (UINT32) + sizeof (UINT16) + StrSize (String);
+  OptionSize += GetDevicePathSize (DevicePath);
+  OptionPtr           = AllocateZeroPool (OptionSize);
+  TempPtr             = OptionPtr;
+  *(UINT32 *) TempPtr = LOAD_OPTION_ACTIVE;
+  TempPtr += sizeof (UINT32);
+  *(UINT16 *) TempPtr = (UINT16) GetDevicePathSize (DevicePath);
+  TempPtr += sizeof (UINT16);
+  CopyMem (TempPtr, String, StrSize (String));
+  TempPtr += StrSize (String);
+  CopyMem (TempPtr, DevicePath, GetDevicePathSize (DevicePath));
+
+  if (UpdateBootDevicePath) {
+    //
+    // The number in option#### to be updated
+    //
+    RegisterOptionNumber = TempOptionPtr[Index];
+  } else {
+    //
+    // The new option#### number
+    //
+    RegisterOptionNumber = BdsLibGetFreeOptionNumber(VariableName);
+  }
+
+  if (*VariableName == 'B') {
+    UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", RegisterOptionNumber);
+  } else {
+    UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", RegisterOptionNumber);
+  }
+
+  Status = gRT->SetVariable (
+                  OptionName,
+                  &gEfiGlobalVariableGuid,
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                  OptionSize,
+                  OptionPtr
+                  );
+  if (EFI_ERROR (Status) || UpdateBootDevicePath) {
+    gBS->FreePool (OptionPtr);
+    gBS->FreePool (TempOptionPtr);
+    return Status;
+  }
+
+  gBS->FreePool (OptionPtr);
+
+  //
+  // Update the option order variable
+  //
+
+  //
+  // If no BootOrder
+  //
+  if (TempOptionSize == 0) {
+    BootOrderEntry = 0;
+    Status = gRT->SetVariable (
+                    VariableName,
+                    &gEfiGlobalVariableGuid,
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                    sizeof (UINT16),
+                    &BootOrderEntry
+                    );
+    if (EFI_ERROR (Status)) {
+      gBS->FreePool (TempOptionPtr);
+      return Status;
+    }
+    return EFI_SUCCESS;
+  }
+
+  if (UpdateBootDevicePath) {
+    //
+    // If just update a old option, the new optionorder size not change
+    //
+    OrderItemNum = (TempOptionSize / sizeof (UINT16)) ;
+    OptionOrderPtr = AllocateZeroPool ( OrderItemNum * sizeof (UINT16));
+    CopyMem (OptionOrderPtr, TempOptionPtr, OrderItemNum * sizeof (UINT16));
+  } else {
+    OrderItemNum = (TempOptionSize / sizeof (UINT16)) + 1 ;
+    OptionOrderPtr = AllocateZeroPool ( OrderItemNum * sizeof (UINT16));
+    CopyMem (OptionOrderPtr, TempOptionPtr, (OrderItemNum - 1) * sizeof (UINT16));
+  }
+
+  OptionOrderPtr[Index] = RegisterOptionNumber;
+
+  Status = gRT->SetVariable (
+                  VariableName,
+                  &gEfiGlobalVariableGuid,
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                  OrderItemNum * sizeof (UINT16),
+                  OptionOrderPtr
+                  );
+  if (EFI_ERROR (Status)) {
+    gBS->FreePool (TempOptionPtr);
+    gBS->FreePool (OptionOrderPtr);
+    return Status;
+  }
+
+  gBS->FreePool (TempOptionPtr);
+  gBS->FreePool (OptionOrderPtr);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Build the boot#### or driver#### option from the VariableName, the
+  build boot#### or driver#### will also be linked to BdsCommonOptionList
+
+  @param  BdsCommonOptionList   The header of the boot#### or driver#### option
+                                link list
+  @param  VariableName          EFI Variable name indicate if it is boot#### or
+                                driver####
+
+  @retval BDS_COMMON_OPTION     Get the option just been created
+  @retval NULL                  Failed to get the new option
+
+**/
+BDS_COMMON_OPTION *
+BdsLibVariableToOption (
+  IN OUT LIST_ENTRY                   *BdsCommonOptionList,
+  IN  CHAR16                          *VariableName
+  )
+{
+  UINT32                    Attribute;
+  UINT16                    FilePathSize;
+  UINT8                     *Variable;
+  UINT8                     *TempPtr;
+  UINTN                     VariableSize;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  BDS_COMMON_OPTION         *Option;
+  VOID                      *LoadOptions;
+  UINT32                    LoadOptionsSize;
+  CHAR16                    *Description;
+  UINT8                     NumOff;
+  //
+  // Read the variable. We will never free this data.
+  //
+  Variable = BdsLibGetVariableAndSize (
+              VariableName,
+              &gEfiGlobalVariableGuid,
+              &VariableSize
+              );
+  if (Variable == NULL) {
+    return NULL;
+  }
+  //
+  // Notes: careful defined the variable of Boot#### or
+  // Driver####, consider use some macro to abstract the code
+  //
+  //
+  // Get the option attribute
+  //
+  TempPtr   = Variable;
+  Attribute = *(UINT32 *) Variable;
+  TempPtr += sizeof (UINT32);
+
+  //
+  // Get the option's device path size
+  //
+  FilePathSize = *(UINT16 *) TempPtr;
+  TempPtr += sizeof (UINT16);
+
+  //
+  // Get the option's description string
+  //
+  Description = (CHAR16 *) TempPtr;
+
+  //
+  // Get the option's description string size
+  //
+  TempPtr += StrSize ((CHAR16 *) TempPtr);
+
+  //
+  // Get the option's device path
+  //
+  DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
+  TempPtr += FilePathSize;
+
+  LoadOptions     = TempPtr;
+  LoadOptionsSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable));
+
+  //
+  // The Console variables may have multiple device paths, so make
+  // an Entry for each one.
+  //
+  Option = AllocateZeroPool (sizeof (BDS_COMMON_OPTION));
+  if (Option == NULL) {
+    return NULL;
+  }
+
+  Option->Signature   = BDS_LOAD_OPTION_SIGNATURE;
+  Option->DevicePath  = AllocateZeroPool (GetDevicePathSize (DevicePath));
+  CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));
+  Option->Attribute   = Attribute;
+  Option->Description = AllocateZeroPool (StrSize (Description));
+  CopyMem (Option->Description, Description, StrSize (Description));
+  Option->LoadOptions = AllocateZeroPool (LoadOptionsSize);
+  CopyMem (Option->LoadOptions, LoadOptions, LoadOptionsSize);
+  Option->LoadOptionsSize = LoadOptionsSize;
+
+  //
+  // Get the value from VariableName Unicode string
+  // since the ISO standard assumes ASCII equivalent abbreviations, we can be safe in converting this
+  // Unicode stream to ASCII without any loss in meaning.
+  //
+  if (*VariableName == 'B') {
+    NumOff = sizeof (L"Boot")/sizeof(CHAR16) -1 ;
+    Option->BootCurrent = (UINT16) ((VariableName[NumOff]  -'0') * 0x1000);
+    Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+1]-'0') * 0x100));
+    Option->BootCurrent = (UINT16) (Option->BootCurrent +  ((VariableName[NumOff+2]-'0') * 0x10));
+    Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+3]-'0')));
+  }
+  //
+  // Insert active entry to BdsDeviceList
+  //
+  if ((Option->Attribute & LOAD_OPTION_ACTIVE) == LOAD_OPTION_ACTIVE) {
+    InsertTailList (BdsCommonOptionList, &Option->Link);
+    gBS->FreePool (Variable);
+    return Option;
+  }
+
+  gBS->FreePool (Variable);
+  gBS->FreePool (Option);
+  return NULL;
+
+}
+
+
+/**
+  Process BootOrder, or DriverOrder variables, by calling
+  BdsLibVariableToOption () for each UINT16 in the variables.
+
+  @param  BdsCommonOptionList   The header of the option list base on variable
+                                VariableName
+  @param  VariableName          EFI Variable name indicate the BootOrder or
+                                DriverOrder
+
+  @retval EFI_SUCCESS           Success create the boot option or driver option
+                                list
+  @retval EFI_OUT_OF_RESOURCES  Failed to get the boot option or driver option list
+
+**/
+EFI_STATUS
+BdsLibBuildOptionFromVar (
+  IN  LIST_ENTRY                      *BdsCommonOptionList,
+  IN  CHAR16                          *VariableName
+  )
+{
+  UINT16            *OptionOrder;
+  UINTN             OptionOrderSize;
+  UINTN             Index;
+  BDS_COMMON_OPTION *Option;
+  CHAR16            OptionName[20];
+
+  //
+  // Zero Buffer in order to get all BOOT#### variables
+  //
+  ZeroMem (OptionName, sizeof (OptionName));
+
+  //
+  // Read the BootOrder, or DriverOrder variable.
+  //
+  OptionOrder = BdsLibGetVariableAndSize (
+                  VariableName,
+                  &gEfiGlobalVariableGuid,
+                  &OptionOrderSize
+                  );
+  if (OptionOrder == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
+    if (*VariableName == 'B') {
+      UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionOrder[Index]);
+    } else {
+      UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionOrder[Index]);
+    }
+
+    Option              = BdsLibVariableToOption (BdsCommonOptionList, OptionName);
+    Option->BootCurrent = OptionOrder[Index];
+
+  }
+
+  gBS->FreePool (OptionOrder);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Get boot mode by looking up configuration table and parsing HOB list
+
+  @param  BootMode              Boot mode from PEI handoff HOB.
+
+  @retval EFI_SUCCESS           Successfully get boot mode
+  @retval EFI_NOT_FOUND         Can not find the current system boot mode
+
+**/
+EFI_STATUS
+BdsLibGetBootMode (
+  OUT EFI_BOOT_MODE       *BootMode
+  )
+{
+  VOID        *HobList;
+  EFI_STATUS  Status;
+
+  //
+  // Get Hob list
+  //
+  Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Hob list not found\n"));
+    *BootMode = 0;
+    return EFI_NOT_FOUND;
+  }
+
+  Status = R8_GetHobBootMode (HobList, BootMode);
+  if (EFI_ERROR (Status)) {
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  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  VariableSize          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               *VariableSize
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       BufferSize;
+  VOID        *Buffer;
+
+  Buffer = NULL;
+
+  //
+  // Pass in a zero size buffer to find the required buffer size.
+  //
+  BufferSize  = 0;
+  Status      = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    //
+    // Allocate the buffer to return
+    //
+    Buffer = AllocateZeroPool (BufferSize);
+    if (Buffer == NULL) {
+      return NULL;
+    }
+    //
+    // Read variable into the allocated buffer.
+    //
+    Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
+    if (EFI_ERROR (Status)) {
+      BufferSize = 0;
+    }
+  }
+
+  *VariableSize = BufferSize;
+  return Buffer;
+}
+
+
+/**
+  Delete the instance in Multi which matches partly with Single instance
+
+  @param  Multi                 A pointer to a multi-instance device path data
+                                structure.
+  @param  Single                A pointer to a single-instance device path data
+                                structure.
+
+  @return This function will remove the device path instances in Multi which partly
+  @return match with the Single, and return the result device path. If there is no
+  @return remaining device path as a result, this function will return NULL.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+BdsLibDelPartMatchInstance (
+  IN     EFI_DEVICE_PATH_PROTOCOL  *Multi,
+  IN     EFI_DEVICE_PATH_PROTOCOL  *Single
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;
+  UINTN                     InstanceSize;
+  UINTN                     SingleDpSize;
+  UINTN                     Size;
+
+  NewDevicePath     = NULL;
+  TempNewDevicePath = NULL;
+
+  if (Multi == NULL || Single == NULL) {
+    return Multi;
+  }
+
+  Instance        =  GetNextDevicePathInstance (&Multi, &InstanceSize);
+  SingleDpSize    =  GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;
+  InstanceSize    -= END_DEVICE_PATH_LENGTH;
+
+  while (Instance != NULL) {
+
+    Size = (SingleDpSize < InstanceSize) ? SingleDpSize : InstanceSize;
+
+    if ((CompareMem (Instance, Single, Size) != 0)) {
+      //
+      // Append the device path instance which does not match with Single
+      //
+      TempNewDevicePath = NewDevicePath;
+      NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);
+      SafeFreePool(TempNewDevicePath);
+    }
+    SafeFreePool(Instance);
+    Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);
+    InstanceSize  -= END_DEVICE_PATH_LENGTH;
+  }
+
+  return NewDevicePath;
+}
+
+
+/**
+  Function compares a device path data structure to that of all the nodes of a
+  second device path instance.
+
+  @param  Multi                 A pointer to a multi-instance device path data
+                                structure.
+  @param  Single                A pointer to a single-instance device path data
+                                structure.
+
+  @retval TRUE                  If the Single is contained within Multi
+  @retval FALSE                 The Single is not match within Multi
+
+**/
+BOOLEAN
+BdsLibMatchDevicePaths (
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Single
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;
+  UINTN                     Size;
+
+  if (!Multi || !Single) {
+    return FALSE;
+  }
+
+  DevicePath      = Multi;
+  DevicePathInst  = GetNextDevicePathInstance (&DevicePath, &Size);
+
+  //
+  // Search for the match of 'Single' in 'Multi'
+  //
+  while (DevicePathInst != NULL) {
+    //
+    // If the single device path is found in multiple device paths,
+    // return success
+    //
+    if (CompareMem (Single, DevicePathInst, Size) == 0) {
+      gBS->FreePool (DevicePathInst);
+      return TRUE;
+    }
+
+    gBS->FreePool (DevicePathInst);
+    DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
+  }
+
+  return FALSE;
+}
+
+
+/**
+  This function prints a series of strings.
+
+  @param  ConOut                Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
+  @param  ...                   A variable argument list containing series of
+                                strings, the last string must be NULL.
+
+  @retval EFI_SUCCESS           Success print out the string using ConOut.
+  @retval EFI_STATUS            Return the status of the ConOut->OutputString ().
+
+**/
+EFI_STATUS
+BdsLibOutputStrings (
+  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *ConOut,
+  ...
+  )
+{
+  VA_LIST     args;
+  EFI_STATUS  Status;
+  CHAR16      *String;
+
+  Status = EFI_SUCCESS;
+  VA_START (args, ConOut);
+
+  while (!EFI_ERROR (Status)) {
+    //
+    // If String is NULL, then it's the end of the list
+    //
+    String = VA_ARG (args, CHAR16 *);
+    if (!String) {
+      break;
+    }
+
+    Status = ConOut->OutputString (ConOut, String);
+
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+  }
+
+  return Status;
+}
+
+//
+//  Following are BDS Lib functions which  contain all the code about setup browser reset reminder feature.
+//  Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser  if
+//  user change any option setting which needs a reset to be effective, and  the reset will be applied according to  the user selection.
+//
+
+
+/**
+  Enable the setup browser reset reminder feature.
+  This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it.
+
+  VOID
+
+  @return VOID
+
+**/
+VOID
+EnableResetReminderFeature (
+  VOID
+  )
+{
+  mFeaturerSwitch = TRUE;
+}
+
+
+/**
+  Disable the setup browser reset reminder feature.
+  This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it.
+
+  VOID
+
+  @return VOID
+
+**/
+VOID
+DisableResetReminderFeature (
+  VOID
+  )
+{
+  mFeaturerSwitch = FALSE;
+}
+
+
+/**
+  Record the info that  a reset is required.
+  A  module boolean variable is used to record whether a reset is required.
+
+  VOID
+
+  @return VOID
+
+**/
+VOID
+EnableResetRequired (
+  VOID
+  )
+{
+  mResetRequired = TRUE;
+}
+
+
+/**
+  Record the info that  no reset is required.
+  A  module boolean variable is used to record whether a reset is required.
+
+  VOID
+
+  @return VOID
+
+**/
+VOID
+DisableResetRequired (
+  VOID
+  )
+{
+  mResetRequired = FALSE;
+}
+
+
+/**
+  Check whether platform policy enable the reset reminder feature. The default is enabled.
+
+  VOID
+
+  @return VOID
+
+**/
+BOOLEAN
+IsResetReminderFeatureEnable (
+  VOID
+  )
+{
+  return mFeaturerSwitch;
+}
+
+
+/**
+  Check if  user changed any option setting which needs a system reset to be effective.
+
+  VOID
+
+  @return VOID
+
+**/
+BOOLEAN
+IsResetRequired (
+  VOID
+  )
+{
+  return mResetRequired;
+}
+
+
+/**
+  Check whether a reset is needed, and finish the reset reminder feature.
+  If a reset is needed, Popup a menu to notice user, and finish the feature
+  according to the user selection.
+
+  VOID
+
+  @return VOID
+
+**/
+VOID
+SetupResetReminder (
+  VOID
+  )
+{
+#if (EFI_SPECIFICATION_VERSION < 0x0002000A)
+  EFI_STATUS                    Status;
+  EFI_FORM_BROWSER_PROTOCOL     *Browser;
+#endif
+  EFI_INPUT_KEY                 Key;
+  CHAR16                        *StringBuffer1;
+  CHAR16                        *StringBuffer2;
+
+
+  //
+  //check any reset required change is applied? if yes, reset system
+  //
+  if (IsResetReminderFeatureEnable ()) {
+    if (IsResetRequired ()) {
+
+#if (EFI_SPECIFICATION_VERSION < 0x0002000A)
+      Status = gBS->LocateProtocol (
+                      &gEfiFormBrowserProtocolGuid,
+                      NULL,
+                      &Browser
+                      );
+#endif
+
+      StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));
+      ASSERT (StringBuffer1 != NULL);
+      StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));
+      ASSERT (StringBuffer2 != NULL);
+      StrCpy (StringBuffer1, L"Configuration changed. Reset to apply it Now ? ");
+      StrCpy (StringBuffer2, L"Enter (YES)  /   Esc (NO)");
+      //
+      // Popup a menu to notice user
+      //
+      do {
+#if (EFI_SPECIFICATION_VERSION < 0x0002000A)
+        Browser->CreatePopUp (2, TRUE, 0, NULL, &Key, StringBuffer1, StringBuffer2);
+#else
+        IfrLibCreatePopUp (2, &Key, StringBuffer1, StringBuffer2);
+#endif
+      } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
+
+      gBS->FreePool (StringBuffer1);
+      gBS->FreePool (StringBuffer2);
+      //
+      // If the user hits the YES Response key, reset
+      //
+      if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {
+        gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+      }
+      gST->ConOut->ClearScreen (gST->ConOut);
+    }
+  }
+}
+
+
+/**
+  Get the headers (dos, image, optional header) from an image
+
+  @param  Device                SimpleFileSystem device handle
+  @param  FileName              File name for the image
+  @param  DosHeader             Pointer to dos header
+  @param  ImageHeader           Pointer to image header
+  @param  OptionalHeader        Pointer to optional header
+
+  @retval EFI_SUCCESS           Successfully get the machine type.
+  @retval EFI_NOT_FOUND         The file is not found.
+  @retval EFI_LOAD_ERROR        File is not a valid image file.
+
+**/
+EFI_STATUS
+BdsLibGetImageHeader (
+  IN  EFI_HANDLE                  Device,
+  IN  CHAR16                      *FileName,
+  OUT EFI_IMAGE_DOS_HEADER        *DosHeader,
+  OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Volume;
+  EFI_FILE_HANDLE                  Root;
+  EFI_FILE_HANDLE                  ThisFile;
+  UINTN                            BufferSize;
+  UINT64                           FileSize;
+  EFI_FILE_INFO                    *Info;
+
+  Root     = NULL;
+  ThisFile = NULL;
+  //
+  // Handle the file system interface to the device
+  //
+  Status = gBS->HandleProtocol (
+                  Device,
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  (VOID *) &Volume
+                  );
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  Status = Volume->OpenVolume (
+                     Volume,
+                     &Root
+                     );
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0);
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  //
+  // Get file size
+  //
+  BufferSize  = SIZE_OF_EFI_FILE_INFO + 200;
+  do {
+    Info   = NULL;
+    Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info);
+    if (EFI_ERROR (Status)) {
+      goto Done;
+    }
+    Status = ThisFile->GetInfo (
+                         ThisFile,
+                         &gEfiFileInfoGuid,
+                         &BufferSize,
+                         Info
+                         );
+    if (!EFI_ERROR (Status)) {
+      break;
+    }
+    if (Status != EFI_BUFFER_TOO_SMALL) {
+      goto Done;
+    }
+    gBS->FreePool (Info);
+  } while (TRUE);
+
+  FileSize = Info->FileSize;
+  gBS->FreePool (Info);
+
+  //
+  // Read dos header
+  //
+  BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);
+  Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader);
+  if (EFI_ERROR (Status) ||
+      BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) ||
+      FileSize <= DosHeader->e_lfanew ||
+      DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+    Status = EFI_LOAD_ERROR;
+    goto Done;
+  }
+
+  //
+  // Move to PE signature
+  //
+  Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew);
+  if (EFI_ERROR (Status)) {
+    Status = EFI_LOAD_ERROR;
+    goto Done;
+  }
+
+  //
+  // Read and check PE signature
+  //
+  BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
+  Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32);
+  if (EFI_ERROR (Status) ||
+      BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) ||
+      Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
+    Status = EFI_LOAD_ERROR;
+    goto Done;
+  }
+
+  //
+  // Check PE32 or PE32+ magic
+  //
+  if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
+      Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+    Status = EFI_LOAD_ERROR;
+    goto Done;
+  }
+
+ Done:
+  if (ThisFile != NULL) {
+    ThisFile->Close (ThisFile);
+  }
+  if (Root != NULL) {
+    Root->Close (Root);
+  }
+  return Status;
+}
+
+#if (EFI_SPECIFICATION_VERSION < 0x0002000A)
+EFI_STATUS
+BdsLibGetHiiHandles (
+  IN     EFI_HII_PROTOCOL *Hii,
+  IN OUT UINT16           *HandleBufferLength,
+  OUT    EFI_HII_HANDLE   **HiiHandleBuffer
+  )
+/*++
+
+Routine Description:
+
+  Determines the handles that are currently active in the database.
+  It's the caller's responsibility to free handle buffer.
+
+Arguments:
+
+  This                  - A pointer to the EFI_HII_PROTOCOL instance.
+  HandleBufferLength    - On input, a pointer to the length of the handle buffer. On output,
+                          the length of the handle buffer that is required for the handles found.
+  HiiHandleBuffer       - Pointer to an array of EFI_HII_PROTOCOL instances returned.
+
+Returns:
+
+  EFI_SUCCESS           - Get an array of EFI_HII_PROTOCOL instances successfully.
+  EFI_INVALID_PARAMETER - Hii is NULL.
+  EFI_NOT_FOUND         - Database not found.
+
+--*/
+{
+  UINT16      TempBufferLength;
+  EFI_STATUS  Status;
+
+  TempBufferLength = 0;
+
+  //
+  // Try to find the actual buffer size for HiiHandle Buffer.
+  //
+  Status = Hii->FindHandles (Hii, &TempBufferLength, *HiiHandleBuffer);
+
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+      *HiiHandleBuffer = AllocateZeroPool (TempBufferLength);
+      Status = Hii->FindHandles (Hii, &TempBufferLength, *HiiHandleBuffer);
+      //
+      // we should not fail here.
+      //
+      ASSERT_EFI_ERROR (Status);
+  }
+
+  *HandleBufferLength = TempBufferLength;
+
+  return Status;
+
+}
+#endif
+
+VOID
+EFIAPI
+BdsSetMemoryTypeInformationVariable (
+  EFI_EVENT  Event,
+  VOID       *Context
+  )
+/*++
+
+Routine Description:
+
+  This routine is a notification function for legayc boot or exit boot
+  service event. It will adjust the memory information for different
+  memory type and save them into the variables for next boot
+
+Arguments:
+
+  Event    - The event that triggered this notification function
+  Context  - Pointer to the notification functions context
+
+Returns:
+
+  None.
+
+--*/
+{
+  EFI_STATUS                   Status;
+  EFI_MEMORY_TYPE_INFORMATION  *PreviousMemoryTypeInformation;
+  EFI_MEMORY_TYPE_INFORMATION  *CurrentMemoryTypeInformation;
+  UINTN                        VariableSize;
+  BOOLEAN                      UpdateRequired;
+  UINTN                        Index;
+  UINTN                        Index1;
+  UINT32                       Previous;
+  UINT32                       Current;
+  UINT32                       Next;
+  VOID                         *HobList;
+
+  UpdateRequired = FALSE;
+
+  //
+  // Retrieve the current memory usage statistics.  If they are not found, then
+  // no adjustments can be made to the Memory Type Information variable.
+  //
+  Status = EfiGetSystemConfigurationTable (
+             &gEfiMemoryTypeInformationGuid,
+             (VOID **) &CurrentMemoryTypeInformation
+             );
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  //
+  // Get the Memory Type Information settings from Hob if they exist,
+  // PEI is responsible for getting them from variable and build a Hob to save them.
+  // If the previous Memory Type Information is not available, then set defaults
+  //
+  EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
+  Status = R8_GetNextGuidHob (&HobList, &gEfiMemoryTypeInformationGuid, (VOID **) &PreviousMemoryTypeInformation, &VariableSize);
+  if (EFI_ERROR (Status) || PreviousMemoryTypeInformation == NULL) {
+    //
+    // If Platform has not built Memory Type Info into the Hob, just return.
+    //
+    return;
+  }
+
+  //
+  // Use a heuristic to adjust the Memory Type Information for the next boot
+  //
+  for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
+
+    Current = 0;
+    for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {
+      if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {
+        Current = CurrentMemoryTypeInformation[Index1].NumberOfPages;
+        break;
+      }
+    }
+
+    if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {
+      continue;
+    }
+
+    Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;
+
+    //
+    // Write next varible to 125% * current and Inconsistent Memory Reserved across bootings may lead to S4 fail
+    //
+    if (Current > Previous) {
+      Next = Current + (Current >> 2);
+    } else {
+      Next = Previous;
+    }
+    if (Next > 0 && Next < 4) {
+      Next = 4;
+    }
+
+    if (Next != Previous) {
+      PreviousMemoryTypeInformation[Index].NumberOfPages = Next;
+      UpdateRequired = TRUE;
+    }
+
+  }
+
+  //
+  // If any changes were made to the Memory Type Information settings, then set the new variable value
+  //
+  if (UpdateRequired) {
+    Status = gRT->SetVariable (
+          EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
+          &gEfiMemoryTypeInformationGuid,
+          EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+          VariableSize,
+          PreviousMemoryTypeInformation
+          );
+  }
+
+  return;
+}
+
+
+/**
+  This routine register a function to adjust the different type memory page number just before booting
+  and save the updated info into the variable for next boot to use
+
+  None
+
+  @return None.
+
+**/
+VOID
+EFIAPI
+BdsLibSaveMemoryTypeInformation (
+  VOID
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_EVENT                    ReadyToBootEvent;
+
+  Status = EfiCreateEventReadyToBootEx (
+           TPL_CALLBACK,
+           BdsSetMemoryTypeInformationVariable,
+           NULL,
+           &ReadyToBootEvent
+           );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR,"Bds Set Memory Type Informationa Variable Fails\n"));
+  }
+
+}
+
+
+/**
+  return the current TPL, copied from the EDKII glue lib.
+
+  VOID
+
+  @return Current TPL
+
+**/
+EFI_TPL
+BdsLibGetCurrentTpl (
+  VOID
+  )
+{
+  EFI_TPL                 Tpl;
+
+  Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+  gBS->RestoreTPL (Tpl);
+
+  return Tpl;
+}
diff --git a/MdeModulePkg/Library/GenericBdsLib/DevicePath.c b/MdeModulePkg/Library/GenericBdsLib/DevicePath.c
new file mode 100644 (file)
index 0000000..96a3c5d
--- /dev/null
@@ -0,0 +1,1321 @@
+/** @file
+
+Copyright (c) 2004 - 2007, Intel Corporation
+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.
+
+Module Name:
+
+  DevicePath.c
+
+Abstract:
+
+  BDS internal function define the default device path string, it can be
+  replaced by platform device path.
+
+
+**/
+
+#include "InternalBdsLib.h"
+
+//
+// Platform Code should implement the Vendor specific Device Path display routine.
+//
+extern
+VOID
+DevPathVendor (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+;
+
+EFI_GUID  mEfiDevicePathMessagingUartFlowControlGuid = DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL;
+
+EFI_GUID mEfiDevicePathMessagingSASGuid = DEVICE_PATH_MESSAGING_SAS;
+
+
+VOID *
+ReallocatePool (
+  IN VOID                 *OldPool,
+  IN UINTN                OldSize,
+  IN UINTN                NewSize
+  )
+/*++
+
+Routine Description:
+
+  Adjusts the size of a previously allocated buffer.
+
+Arguments:
+
+  OldPool               - A pointer to the buffer whose size is being adjusted.
+
+  OldSize               - The size of the current buffer.
+
+  NewSize               - The size of the new buffer.
+
+Returns:
+
+  EFI_SUCEESS           - The requested number of bytes were allocated.
+
+  EFI_OUT_OF_RESOURCES  - The pool requested could not be allocated.
+
+  EFI_INVALID_PARAMETER - The buffer was invalid.
+
+--*/
+{
+  VOID  *NewPool;
+
+  NewPool = NULL;
+  if (NewSize) {
+    NewPool = AllocateZeroPool (NewSize);
+  }
+
+  if (OldPool) {
+    if (NewPool) {
+      CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);
+    }
+
+    gBS->FreePool (OldPool);
+  }
+
+  return NewPool;
+}
+
+
+/**
+  Concatenates a formatted unicode string to allocated pool.
+  The caller must free the resulting buffer.
+
+  @param  Str      Tracks the allocated pool, size in use, and  amount of pool
+                   allocated.
+  @param  fmt      The format string
+
+  @return Allocated buffer with the formatted string printed in it.
+  @return The caller must free the allocated buffer.   The buffer
+  @return allocation is not packed.
+
+**/
+CHAR16 *
+CatPrint (
+  IN OUT POOL_PRINT   *Str,
+  IN CHAR16           *fmt,
+  ...
+  )
+{
+  UINT16  *AppendStr;
+  VA_LIST args;
+  UINTN   strsize;
+
+  AppendStr = AllocateZeroPool (0x1000);
+  if (AppendStr == NULL) {
+    return Str->str;
+  }
+
+  VA_START (args, fmt);
+  UnicodeVSPrint (AppendStr, 0x1000, fmt, args);
+  VA_END (args);
+  if (NULL == Str->str) {
+    strsize   = StrSize (AppendStr);
+    Str->str  = AllocateZeroPool (strsize);
+    ASSERT (Str->str != NULL);
+  } else {
+    strsize = StrSize (AppendStr);
+    strsize += (StrSize (Str->str) - sizeof (UINT16));
+
+    Str->str = ReallocatePool (
+                Str->str,
+                StrSize (Str->str),
+                strsize
+                );
+    ASSERT (Str->str != NULL);
+  }
+
+  Str->maxlen = MAX_CHAR * sizeof (UINT16);
+  if (strsize < Str->maxlen) {
+    StrCat (Str->str, AppendStr);
+    Str->len = strsize - sizeof (UINT16);
+  }
+
+  gBS->FreePool (AppendStr);
+  return Str->str;
+}
+
+
+/**
+  Function unpacks a device path data structure so that all the nodes
+  of a device path are naturally aligned.
+
+  @param  DevPath  A pointer to a device path data structure
+
+  @return If the memory for the device path is successfully allocated, then a
+  @return pointer to the new device path is returned.  Otherwise, NULL is returned.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+BdsLibUnpackDevicePath (
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevPath
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *Src;
+  EFI_DEVICE_PATH_PROTOCOL  *Dest;
+  EFI_DEVICE_PATH_PROTOCOL  *NewPath;
+  UINTN                     Size;
+
+  //
+  // Walk device path and round sizes to valid boundries
+  //
+  Src   = DevPath;
+  Size  = 0;
+  for (;;) {
+    Size += DevicePathNodeLength (Src);
+    Size += ALIGN_SIZE (Size);
+
+    if (IsDevicePathEnd (Src)) {
+      break;
+    }
+
+    Src = NextDevicePathNode (Src);
+  }
+  //
+  // Allocate space for the unpacked path
+  //
+  NewPath = AllocateZeroPool (Size);
+  if (NewPath) {
+
+    ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0);
+
+    //
+    // Copy each node
+    //
+    Src   = DevPath;
+    Dest  = NewPath;
+    for (;;) {
+      Size = DevicePathNodeLength (Src);
+      CopyMem (Dest, Src, Size);
+      Size += ALIGN_SIZE (Size);
+      SetDevicePathNodeLength (Dest, Size);
+      Dest->Type |= EFI_DP_TYPE_UNPACKED;
+      Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size);
+
+      if (IsDevicePathEnd (Src)) {
+        break;
+      }
+
+      Src = NextDevicePathNode (Src);
+    }
+  }
+
+  return NewPath;
+}
+
+VOID
+DevPathPci (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  PCI_DEVICE_PATH *Pci;
+
+  Pci = DevPath;
+  CatPrint (Str, L"Pci(%x|%x)", (UINTN) Pci->Device, (UINTN) Pci->Function);
+}
+
+VOID
+DevPathPccard (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  PCCARD_DEVICE_PATH  *Pccard;
+
+  Pccard = DevPath;
+  CatPrint (Str, L"Pcmcia(Function%x)", (UINTN) Pccard->FunctionNumber);
+}
+
+VOID
+DevPathMemMap (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  MEMMAP_DEVICE_PATH  *MemMap;
+
+  MemMap = DevPath;
+  CatPrint (
+    Str,
+    L"MemMap(%d:%lx-%lx)",
+    MemMap->MemoryType,
+    MemMap->StartingAddress,
+    MemMap->EndingAddress
+    );
+}
+
+VOID
+DevPathController (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  CONTROLLER_DEVICE_PATH  *Controller;
+
+  Controller = DevPath;
+  CatPrint (Str, L"Ctrl(%d)", (UINTN) Controller->ControllerNumber);
+}
+
+
+/**
+  Convert Vendor device path to device name
+
+  @param  Str      The buffer store device name
+  @param  DevPath  Pointer to vendor device path
+
+  @return When it return, the device name have been stored in *Str.
+
+**/
+VOID
+DevPathVendor (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  VENDOR_DEVICE_PATH  *Vendor;
+  CHAR16              *Type;
+  UINTN               DataLength;
+  UINTN               Index;
+  UINT32              FlowControlMap;
+
+  UINT16              Info;
+
+  Vendor  = DevPath;
+
+  switch (DevicePathType (&Vendor->Header)) {
+  case HARDWARE_DEVICE_PATH:
+    Type = L"Hw";
+// bugbug: nt 32 specific definition
+#if 0
+    //
+    // If the device is a winntbus device, we will give it a readable device name.
+    //
+    if (CompareGuid (&Vendor->Guid, &mEfiWinNtThunkProtocolGuid)) {
+      CatPrint (Str, L"%s", L"WinNtBus");
+      return ;
+    } else if (CompareGuid (&Vendor->Guid, &mEfiWinNtGopGuid)) {
+      CatPrint (Str, L"%s", L"GOP");
+      return ;
+    } else if (CompareGuid (&Vendor->Guid, &mEfiWinNtSerialPortGuid)) {
+      CatPrint (Str, L"%s", L"Serial");
+      return ;
+    }
+#endif
+    break;
+
+  case MESSAGING_DEVICE_PATH:
+    Type = L"Msg";
+    if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) {
+      CatPrint (Str, L"VenPcAnsi()");
+      return ;
+    } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) {
+      CatPrint (Str, L"VenVt100()");
+      return ;
+    } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) {
+      CatPrint (Str, L"VenVt100Plus()");
+      return ;
+    } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) {
+      CatPrint (Str, L"VenUft8()");
+      return ;
+    } else if (CompareGuid (&Vendor->Guid, &mEfiDevicePathMessagingUartFlowControlGuid)) {
+      FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap);
+      switch (FlowControlMap & 0x00000003) {
+      case 0:
+        CatPrint (Str, L"UartFlowCtrl(%s)", L"None");
+        break;
+
+      case 1:
+        CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware");
+        break;
+
+      case 2:
+        CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff");
+        break;
+
+      default:
+        break;
+      }
+
+      return ;
+
+    } else if (CompareGuid (&Vendor->Guid, &mEfiDevicePathMessagingSASGuid)) {
+      CatPrint (
+        Str,
+        L"SAS(%lx,%lx,%x,",
+        ((SAS_DEVICE_PATH *) Vendor)->SasAddress,
+        ((SAS_DEVICE_PATH *) Vendor)->Lun,
+        ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort
+        );
+      Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology);
+      if ((Info & 0x0f) == 0) {
+        CatPrint (Str, L"NoTopology,0,0,0,");
+      } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) {
+        CatPrint (
+          Str,
+          L"%s,%s,%s,",
+          (Info & (0x1 << 4)) ? L"SATA" : L"SAS",
+          (Info & (0x1 << 5)) ? L"External" : L"Internal",
+          (Info & (0x1 << 6)) ? L"Expanded" : L"Direct"
+          );
+        if ((Info & 0x0f) == 1) {
+          CatPrint (Str, L"0,");
+        } else {
+          CatPrint (Str, L"%x,", (UINTN) ((Info >> 8) & 0xff));
+        }
+      } else {
+        CatPrint (Str, L"0,0,0,0,");
+      }
+
+      CatPrint (Str, L"%x)", (UINTN) ((SAS_DEVICE_PATH *) Vendor)->Reserved);
+      return ;
+
+    } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) {
+      CatPrint (Str, L"DebugPort()");
+      return ;
+    }
+    break;
+
+  case MEDIA_DEVICE_PATH:
+    Type = L"Media";
+    break;
+
+  default:
+    Type = L"?";
+    break;
+  }
+
+  CatPrint (Str, L"Ven%s(%g", Type, &Vendor->Guid);
+  DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH);
+  if (DataLength > 0) {
+    CatPrint (Str, L",");
+    for (Index = 0; Index < DataLength; Index++) {
+      CatPrint (Str, L"%02x", (UINTN) ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]);
+    }
+  }
+  CatPrint (Str, L")");
+}
+
+
+VOID
+DevPathAcpi (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  ACPI_HID_DEVICE_PATH  *Acpi;
+
+  Acpi = DevPath;
+  if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+    CatPrint (Str, L"Acpi(PNP%04x,%x)", (UINTN)  EISA_ID_TO_NUM (Acpi->HID), (UINTN) Acpi->UID);
+  } else {
+    CatPrint (Str, L"Acpi(%08x,%x)", (UINTN) Acpi->HID, (UINTN) Acpi->UID);
+  }
+}
+
+VOID
+DevPathExtendedAcpi (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  ACPI_EXTENDED_HID_DEVICE_PATH   *ExtendedAcpi;
+  //
+  // Index for HID, UID and CID strings, 0 for non-exist
+  //
+  UINT16                          HIDSTRIdx;
+  UINT16                          UIDSTRIdx;
+  UINT16                          CIDSTRIdx;
+  UINT16                          Index;
+  UINT16                          Length;
+  UINT16                          Anchor;
+  CHAR8                           *AsChar8Array;
+
+  ASSERT (Str != NULL);
+  ASSERT (DevPath != NULL);
+
+  HIDSTRIdx    = 0;
+  UIDSTRIdx    = 0;
+  CIDSTRIdx    = 0;
+  ExtendedAcpi = DevPath;
+  Length       = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) ExtendedAcpi);
+
+  ASSERT (Length >= 19);
+  AsChar8Array = (CHAR8 *) ExtendedAcpi;
+
+  //
+  // find HIDSTR
+  //
+  Anchor = 16;
+  for (Index = Anchor; Index < Length && AsChar8Array[Index]; Index++) {
+    ;
+  }
+  if (Index > Anchor) {
+    HIDSTRIdx = Anchor;
+  }
+  //
+  // find UIDSTR
+  //
+  Anchor = (UINT16) (Index + 1);
+  for (Index = Anchor; Index < Length && AsChar8Array[Index]; Index++) {
+    ;
+  }
+  if (Index > Anchor) {
+    UIDSTRIdx = Anchor;
+  }
+  //
+  // find CIDSTR
+  //
+  Anchor = (UINT16) (Index + 1);
+  for (Index = Anchor; Index < Length && AsChar8Array[Index]; Index++) {
+    ;
+  }
+  if (Index > Anchor) {
+    CIDSTRIdx = Anchor;
+  }
+
+  if (HIDSTRIdx == 0 && CIDSTRIdx == 0 && ExtendedAcpi->UID == 0) {
+    CatPrint (Str, L"AcpiExp(");
+    if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+      CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID));
+    } else {
+      CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);
+    }
+    if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+      CatPrint (Str, L"PNP%04x,", (UINTN)  EISA_ID_TO_NUM (ExtendedAcpi->CID));
+    } else {
+      CatPrint (Str, L"%08x,", (UINTN)  ExtendedAcpi->CID);
+    }
+    if (UIDSTRIdx != 0) {
+      CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);
+    } else {
+      CatPrint (Str, L"\"\")");
+    }
+  } else {
+    CatPrint (Str, L"AcpiEx(");
+    if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+      CatPrint (Str, L"PNP%04x,", (UINTN)  EISA_ID_TO_NUM (ExtendedAcpi->HID));
+    } else {
+      CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);
+    }
+    if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+      CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID));
+    } else {
+      CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID);
+    }
+    CatPrint (Str, L"%x,", (UINTN) ExtendedAcpi->UID);
+
+    if (HIDSTRIdx != 0) {
+      CatPrint (Str, L"%a,", AsChar8Array + HIDSTRIdx);
+    } else {
+      CatPrint (Str, L"\"\",");
+    }
+    if (CIDSTRIdx != 0) {
+      CatPrint (Str, L"%a,", AsChar8Array + CIDSTRIdx);
+    } else {
+      CatPrint (Str, L"\"\",");
+    }
+    if (UIDSTRIdx != 0) {
+      CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);
+    } else {
+      CatPrint (Str, L"\"\")");
+    }
+  }
+
+}
+
+VOID
+DevPathAdrAcpi (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  ACPI_ADR_DEVICE_PATH    *AcpiAdr;
+  UINT16                  Index;
+  UINT16                  Length;
+  UINT16                  AdditionalAdrCount;
+
+  AcpiAdr            = DevPath;
+  Length             = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr);
+  AdditionalAdrCount = (UINT16) ((Length - 8) / 4);
+
+  CatPrint (Str, L"AcpiAdr(%x", (UINTN) AcpiAdr->ADR);
+  for (Index = 0; Index < AdditionalAdrCount; Index++) {
+    CatPrint (Str, L",%x", (UINTN) *(UINT32 *) ((UINT8 *) AcpiAdr + 8 + Index * 4));
+  }
+  CatPrint (Str, L")");
+}
+
+VOID
+DevPathAtapi (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  ATAPI_DEVICE_PATH *Atapi;
+
+  Atapi = DevPath;
+  CatPrint (
+    Str,
+    L"Ata(%s,%s)",
+    Atapi->PrimarySecondary ? L"Secondary" : L"Primary",
+    Atapi->SlaveMaster ? L"Slave" : L"Master"
+    );
+}
+
+VOID
+DevPathScsi (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  SCSI_DEVICE_PATH  *Scsi;
+
+  Scsi = DevPath;
+  CatPrint (Str, L"Scsi(Pun%x,Lun%x)", (UINTN) Scsi->Pun, (UINTN) Scsi->Lun);
+}
+
+VOID
+DevPathFibre (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  FIBRECHANNEL_DEVICE_PATH  *Fibre;
+
+  Fibre = DevPath;
+  CatPrint (Str, L"Fibre(Wwn%lx,Lun%x)", Fibre->WWN, Fibre->Lun);
+}
+
+VOID
+DevPath1394 (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  F1394_DEVICE_PATH *F1394;
+
+  F1394 = DevPath;
+  CatPrint (Str, L"1394(%g)", &F1394->Guid);
+}
+
+VOID
+DevPathUsb (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  USB_DEVICE_PATH *Usb;
+
+  Usb = DevPath;
+  CatPrint (Str, L"Usb(%x,%x)", (UINTN) Usb->ParentPortNumber, (UINTN) Usb->InterfaceNumber);
+}
+
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+VOID
+DevPathUsbWWID (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  USB_WWID_DEVICE_PATH  *UsbWWId;
+
+  UsbWWId = DevPath;
+  CatPrint (
+    Str,
+    L"UsbWwid(%x,%x,%x,\"WWID\")",
+    (UINTN) UsbWWId->VendorId,
+    (UINTN) UsbWWId->ProductId,
+    (UINTN) UsbWWId->InterfaceNumber
+    );
+}
+
+VOID
+DevPathLogicalUnit (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;
+
+  LogicalUnit = DevPath;
+  CatPrint (Str, L"Unit(%x)", (UINTN) LogicalUnit->Lun);
+}
+#endif
+
+VOID
+DevPathUsbClass (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  USB_CLASS_DEVICE_PATH *UsbClass;
+
+  UsbClass = DevPath;
+  CatPrint (
+    Str,
+    L"Usb Class(%x,%x,%x,%x,%x)",
+    (UINTN) UsbClass->VendorId,
+    (UINTN) UsbClass->ProductId,
+    (UINTN) UsbClass->DeviceClass,
+    (UINTN) UsbClass->DeviceSubClass,
+    (UINTN) UsbClass->DeviceProtocol
+    );
+}
+
+VOID
+DevPathSata (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  SATA_DEVICE_PATH *Sata;
+
+  Sata = DevPath;
+  CatPrint (
+    Str,
+    L"Sata(%x,%x,%x)",
+    (UINTN) Sata->HBAPortNumber,
+    (UINTN) Sata->PortMultiplierPortNumber,
+    (UINTN) Sata->Lun
+    );
+}
+
+VOID
+DevPathI2O (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  I2O_DEVICE_PATH *I2O;
+
+  I2O = DevPath;
+  CatPrint (Str, L"I2O(%x)", (UINTN) I2O->Tid);
+}
+
+VOID
+DevPathMacAddr (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  MAC_ADDR_DEVICE_PATH  *MAC;
+  UINTN                 HwAddressSize;
+  UINTN                 Index;
+
+  MAC           = DevPath;
+
+  HwAddressSize = sizeof (EFI_MAC_ADDRESS);
+  if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
+    HwAddressSize = 6;
+  }
+
+  CatPrint (Str, L"Mac(");
+
+  for (Index = 0; Index < HwAddressSize; Index++) {
+    CatPrint (Str, L"%02x", (UINTN) MAC->MacAddress.Addr[Index]);
+  }
+
+  CatPrint (Str, L")");
+}
+
+VOID
+DevPathIPv4 (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  IPv4_DEVICE_PATH  *IP;
+
+  IP = DevPath;
+  CatPrint (
+    Str,
+    L"IPv4(%d.%d.%d.%d:%d)",
+    (UINTN) IP->RemoteIpAddress.Addr[0],
+    (UINTN) IP->RemoteIpAddress.Addr[1],
+    (UINTN) IP->RemoteIpAddress.Addr[2],
+    (UINTN) IP->RemoteIpAddress.Addr[3],
+    (UINTN) IP->RemotePort
+    );
+}
+
+VOID
+DevPathIPv6 (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  IPv6_DEVICE_PATH  *IP;
+
+  IP = DevPath;
+  CatPrint (
+    Str,
+    L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)",
+    (UINTN) IP->RemoteIpAddress.Addr[0],
+    (UINTN) IP->RemoteIpAddress.Addr[1],
+    (UINTN) IP->RemoteIpAddress.Addr[2],
+    (UINTN) IP->RemoteIpAddress.Addr[3],
+    (UINTN) IP->RemoteIpAddress.Addr[4],
+    (UINTN) IP->RemoteIpAddress.Addr[5],
+    (UINTN) IP->RemoteIpAddress.Addr[6],
+    (UINTN) IP->RemoteIpAddress.Addr[7],
+    (UINTN) IP->RemoteIpAddress.Addr[8],
+    (UINTN) IP->RemoteIpAddress.Addr[9],
+    (UINTN) IP->RemoteIpAddress.Addr[10],
+    (UINTN) IP->RemoteIpAddress.Addr[11],
+    (UINTN) IP->RemoteIpAddress.Addr[12],
+    (UINTN) IP->RemoteIpAddress.Addr[13],
+    (UINTN) IP->RemoteIpAddress.Addr[14],
+    (UINTN) IP->RemoteIpAddress.Addr[15]
+    );
+}
+
+VOID
+DevPathInfiniBand (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  INFINIBAND_DEVICE_PATH  *InfiniBand;
+
+  InfiniBand = DevPath;
+  CatPrint (
+    Str,
+    L"Infiniband(%x,%g,%lx,%lx,%lx)",
+    (UINTN) InfiniBand->ResourceFlags,
+    InfiniBand->PortGid,
+    InfiniBand->ServiceId,
+    InfiniBand->TargetPortId,
+    InfiniBand->DeviceId
+    );
+}
+
+VOID
+DevPathUart (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  UART_DEVICE_PATH  *Uart;
+  CHAR8             Parity;
+
+  Uart = DevPath;
+  switch (Uart->Parity) {
+  case 0:
+    Parity = 'D';
+    break;
+
+  case 1:
+    Parity = 'N';
+    break;
+
+  case 2:
+    Parity = 'E';
+    break;
+
+  case 3:
+    Parity = 'O';
+    break;
+
+  case 4:
+    Parity = 'M';
+    break;
+
+  case 5:
+    Parity = 'S';
+    break;
+
+  default:
+    Parity = 'x';
+    break;
+  }
+
+  if (Uart->BaudRate == 0) {
+    CatPrint (Str, L"Uart(DEFAULT,%c,", Parity);
+  } else {
+    CatPrint (Str, L"Uart(%d,%c,", Uart->BaudRate, Parity);
+  }
+
+  if (Uart->DataBits == 0) {
+    CatPrint (Str, L"D,");
+  } else {
+    CatPrint (Str, L"%d,", (UINTN) Uart->DataBits);
+  }
+
+  switch (Uart->StopBits) {
+  case 0:
+    CatPrint (Str, L"D)");
+    break;
+
+  case 1:
+    CatPrint (Str, L"1)");
+    break;
+
+  case 2:
+    CatPrint (Str, L"1.5)");
+    break;
+
+  case 3:
+    CatPrint (Str, L"2)");
+    break;
+
+  default:
+    CatPrint (Str, L"x)");
+    break;
+  }
+}
+
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+VOID
+DevPathiSCSI (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  ISCSI_DEVICE_PATH_WITH_NAME *iSCSI;
+  UINT16                      Options;
+
+  ASSERT (Str != NULL);
+  ASSERT (DevPath != NULL);
+
+  iSCSI = DevPath;
+  CatPrint (
+    Str,
+    L"iSCSI(%s,%x,%lx,",
+    iSCSI->iSCSITargetName,
+    iSCSI->TargetPortalGroupTag,
+    iSCSI->Lun
+    );
+
+  Options = iSCSI->LoginOption;
+  CatPrint (Str, L"%s,", ((Options >> 1) & 0x0001) ? L"CRC32C" : L"None");
+  CatPrint (Str, L"%s,", ((Options >> 3) & 0x0001) ? L"CRC32C" : L"None");
+  if ((Options >> 11) & 0x0001) {
+    CatPrint (Str, L"%s,", L"None");
+  } else if ((Options >> 12) & 0x0001) {
+    CatPrint (Str, L"%s,", L"CHAP_UNI");
+  } else {
+    CatPrint (Str, L"%s,", L"CHAP_BI");
+
+  }
+
+  CatPrint (Str, L"%s)", (iSCSI->NetworkProtocol == 0) ? L"TCP" : L"reserved");
+}
+#endif
+
+VOID
+DevPathHardDrive (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  HARDDRIVE_DEVICE_PATH *Hd;
+
+  Hd = DevPath;
+  switch (Hd->SignatureType) {
+  case SIGNATURE_TYPE_MBR:
+    CatPrint (
+      Str,
+      L"HD(Part%d,Sig%08x)",
+      (UINTN) Hd->PartitionNumber,
+      (UINTN) *((UINT32 *) (&(Hd->Signature[0])))
+      );
+    break;
+
+  case SIGNATURE_TYPE_GUID:
+    CatPrint (
+      Str,
+      L"HD(Part%d,Sig%g)",
+      (UINTN) Hd->PartitionNumber,
+      (EFI_GUID *) &(Hd->Signature[0])
+      );
+    break;
+
+  default:
+    CatPrint (
+      Str,
+      L"HD(Part%d,MBRType=%02x,SigType=%02x)",
+      (UINTN) Hd->PartitionNumber,
+      (UINTN) Hd->MBRType,
+      (UINTN) Hd->SignatureType
+      );
+    break;
+  }
+}
+
+VOID
+DevPathCDROM (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  CDROM_DEVICE_PATH *Cd;
+
+  Cd = DevPath;
+  CatPrint (Str, L"CDROM(Entry%x)", (UINTN) Cd->BootEntry);
+}
+
+VOID
+DevPathFilePath (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  FILEPATH_DEVICE_PATH  *Fp;
+
+  Fp = DevPath;
+  CatPrint (Str, L"%s", Fp->PathName);
+}
+
+VOID
+DevPathMediaProtocol (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;
+
+  MediaProt = DevPath;
+  CatPrint (Str, L"Media(%g)", &MediaProt->Protocol);
+}
+
+VOID
+DevPathFvFilePath (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;
+
+  FvFilePath = DevPath;
+  CatPrint (Str, L"%g", &FvFilePath->FvFileName);
+}
+
+VOID
+DevPathBssBss (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  BBS_BBS_DEVICE_PATH *Bbs;
+  CHAR16              *Type;
+
+  Bbs = DevPath;
+  switch (Bbs->DeviceType) {
+  case BBS_TYPE_FLOPPY:
+    Type = L"Floppy";
+    break;
+
+  case BBS_TYPE_HARDDRIVE:
+    Type = L"Harddrive";
+    break;
+
+  case BBS_TYPE_CDROM:
+    Type = L"CDROM";
+    break;
+
+  case BBS_TYPE_PCMCIA:
+    Type = L"PCMCIA";
+    break;
+
+  case BBS_TYPE_USB:
+    Type = L"Usb";
+    break;
+
+  case BBS_TYPE_EMBEDDED_NETWORK:
+    Type = L"Net";
+    break;
+
+  case BBS_TYPE_BEV:
+    Type = L"BEV";
+    break;
+
+  default:
+    Type = L"?";
+    break;
+  }
+  CatPrint (Str, L"Legacy-%s", Type);
+}
+
+VOID
+DevPathEndInstance (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  CatPrint (Str, L",");
+}
+
+VOID
+DevPathNodeUnknown (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath
+  )
+{
+  CatPrint (Str, L"?");
+}
+
+DEVICE_PATH_STRING_TABLE  DevPathTable[] = {
+  HARDWARE_DEVICE_PATH,
+  HW_PCI_DP,
+  DevPathPci,
+  HARDWARE_DEVICE_PATH,
+  HW_PCCARD_DP,
+  DevPathPccard,
+  HARDWARE_DEVICE_PATH,
+  HW_MEMMAP_DP,
+  DevPathMemMap,
+  HARDWARE_DEVICE_PATH,
+  HW_VENDOR_DP,
+  DevPathVendor,
+  HARDWARE_DEVICE_PATH,
+  HW_CONTROLLER_DP,
+  DevPathController,
+  ACPI_DEVICE_PATH,
+  ACPI_DP,
+  DevPathAcpi,
+  ACPI_DEVICE_PATH,
+  ACPI_EXTENDED_DP,
+  DevPathExtendedAcpi,
+  ACPI_DEVICE_PATH,
+  ACPI_ADR_DP,
+  DevPathAdrAcpi,
+  MESSAGING_DEVICE_PATH,
+  MSG_ATAPI_DP,
+  DevPathAtapi,
+  MESSAGING_DEVICE_PATH,
+  MSG_SCSI_DP,
+  DevPathScsi,
+  MESSAGING_DEVICE_PATH,
+  MSG_FIBRECHANNEL_DP,
+  DevPathFibre,
+  MESSAGING_DEVICE_PATH,
+  MSG_1394_DP,
+  DevPath1394,
+  MESSAGING_DEVICE_PATH,
+  MSG_USB_DP,
+  DevPathUsb,
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+  MESSAGING_DEVICE_PATH,
+  MSG_USB_WWID_DP,
+  DevPathUsbWWID,
+  MESSAGING_DEVICE_PATH,
+  MSG_DEVICE_LOGICAL_UNIT_DP,
+  DevPathLogicalUnit,
+#endif
+  MESSAGING_DEVICE_PATH,
+  MSG_USB_CLASS_DP,
+  DevPathUsbClass,
+  MESSAGING_DEVICE_PATH,
+  MSG_SATA_DP,
+  DevPathSata,
+  MESSAGING_DEVICE_PATH,
+  MSG_I2O_DP,
+  DevPathI2O,
+  MESSAGING_DEVICE_PATH,
+  MSG_MAC_ADDR_DP,
+  DevPathMacAddr,
+  MESSAGING_DEVICE_PATH,
+  MSG_IPv4_DP,
+  DevPathIPv4,
+  MESSAGING_DEVICE_PATH,
+  MSG_IPv6_DP,
+  DevPathIPv6,
+  MESSAGING_DEVICE_PATH,
+  MSG_INFINIBAND_DP,
+  DevPathInfiniBand,
+  MESSAGING_DEVICE_PATH,
+  MSG_UART_DP,
+  DevPathUart,
+  MESSAGING_DEVICE_PATH,
+  MSG_VENDOR_DP,
+  DevPathVendor,
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+  MESSAGING_DEVICE_PATH,
+  MSG_ISCSI_DP,
+  DevPathiSCSI,
+#endif
+  MEDIA_DEVICE_PATH,
+  MEDIA_HARDDRIVE_DP,
+  DevPathHardDrive,
+  MEDIA_DEVICE_PATH,
+  MEDIA_CDROM_DP,
+  DevPathCDROM,
+  MEDIA_DEVICE_PATH,
+  MEDIA_VENDOR_DP,
+  DevPathVendor,
+  MEDIA_DEVICE_PATH,
+  MEDIA_FILEPATH_DP,
+  DevPathFilePath,
+  MEDIA_DEVICE_PATH,
+  MEDIA_PROTOCOL_DP,
+  DevPathMediaProtocol,
+#if (EFI_SPECIFICATION_VERSION != 0x00020000)
+  MEDIA_DEVICE_PATH,
+  MEDIA_PIWG_FW_FILE_DP,
+  DevPathFvFilePath,
+#endif
+  BBS_DEVICE_PATH,
+  BBS_BBS_DP,
+  DevPathBssBss,
+  END_DEVICE_PATH_TYPE,
+  END_INSTANCE_DEVICE_PATH_SUBTYPE,
+  DevPathEndInstance,
+  0,
+  0,
+  NULL
+};
+
+
+/**
+
+**/
+CHAR16 *
+DevicePathToStr (
+  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
+  )
+{
+  POOL_PRINT                Str;
+  EFI_DEVICE_PATH_PROTOCOL  *DevPathNode;
+  VOID (*DumpNode) (POOL_PRINT *, VOID *);
+
+  UINTN Index;
+  UINTN NewSize;
+
+  EFI_STATUS                       Status;
+  CHAR16                           *ToText;
+  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
+
+  ZeroMem (&Str, sizeof (Str));
+
+  if (DevPath == NULL) {
+    goto Done;
+  }
+
+  Status = gBS->LocateProtocol (
+                  &gEfiDevicePathToTextProtocolGuid,
+                  NULL,
+                  (VOID **) &DevPathToText
+                  );
+  if (!EFI_ERROR (Status)) {
+    ToText = DevPathToText->ConvertDevicePathToText (
+                              DevPath,
+                              FALSE,
+                              TRUE
+                              );
+    ASSERT (ToText != NULL);
+    return ToText;
+  }
+
+  //
+  // Unpacked the device path
+  //
+  DevPath = BdsLibUnpackDevicePath (DevPath);
+  ASSERT (DevPath);
+
+  //
+  // Process each device path node
+  //
+  DevPathNode = DevPath;
+  while (!IsDevicePathEnd (DevPathNode)) {
+    //
+    // Find the handler to dump this device path node
+    //
+    DumpNode = NULL;
+    for (Index = 0; DevPathTable[Index].Function; Index += 1) {
+
+      if (DevicePathType (DevPathNode) == DevPathTable[Index].Type &&
+          DevicePathSubType (DevPathNode) == DevPathTable[Index].SubType
+          ) {
+        DumpNode = DevPathTable[Index].Function;
+        break;
+      }
+    }
+    //
+    // If not found, use a generic function
+    //
+    if (!DumpNode) {
+      DumpNode = DevPathNodeUnknown;
+    }
+    //
+    //  Put a path seperator in if needed
+    //
+    if (Str.len && DumpNode != DevPathEndInstance) {
+      CatPrint (&Str, L"/");
+    }
+    //
+    // Print this node of the device path
+    //
+    DumpNode (&Str, DevPathNode);
+
+    //
+    // Next device path node
+    //
+    DevPathNode = NextDevicePathNode (DevPathNode);
+  }
+  //
+  // Shrink pool used for string allocation
+  //
+  gBS->FreePool (DevPath);
+
+Done:
+  NewSize = (Str.len + 1) * sizeof (CHAR16);
+  Str.str = ReallocatePool (Str.str, NewSize, NewSize);
+  ASSERT (Str.str != NULL);
+  Str.str[Str.len] = 0;
+  return Str.str;
+}
+
+
+/**
+  Function creates a device path data structure that identically matches the
+  device path passed in.
+
+  @param  DevPath  A pointer to a device path data structure.
+
+  @return The new copy of DevPath is created to identically match the input.
+  @return Otherwise, NULL is returned.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+LibDuplicateDevicePathInstance (
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevPath
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevPath;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;
+  EFI_DEVICE_PATH_PROTOCOL  *Temp;
+  UINTN                     Size;
+
+  //
+  // get the size of an instance from the input
+  //
+  Temp            = DevPath;
+  DevicePathInst  = GetNextDevicePathInstance (&Temp, &Size);
+
+  //
+  // Make a copy
+  //
+  NewDevPath = NULL;
+  if (Size) {
+    NewDevPath = AllocateZeroPool (Size);
+    ASSERT (NewDevPath != NULL);
+  }
+
+  if (NewDevPath) {
+    CopyMem (NewDevPath, DevicePathInst, Size);
+  }
+
+  return NewDevPath;
+}
diff --git a/MdeModulePkg/Library/GenericBdsLib/Ebc/BmMachine.h b/MdeModulePkg/Library/GenericBdsLib/Ebc/BmMachine.h
new file mode 100644 (file)
index 0000000..dc4d728
--- /dev/null
@@ -0,0 +1,35 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+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.
+
+Module Name:
+
+  BmMachine.h
+
+Abstract:
+
+  Boot Manager Machine type
+
+
+
+Revision History
+
+
+**/
+
+#ifndef _BM_MACHINE_H
+#define _BM_MACHINE_H
+
+//
+// NOTE: This is not defined in UEFI spec.
+//
+#define DEFAULT_REMOVABLE_FILE_NAME L"\\EFI\\BOOT\\BOOTEBC.EFI"
+
+#endif
diff --git a/MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf b/MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf
new file mode 100644 (file)
index 0000000..ebaed91
--- /dev/null
@@ -0,0 +1,119 @@
+#/** @file\r
+# Component name for module GenericBdsLib\r
+#\r
+# FIX ME!\r
+# Copyright (c) 2007, Intel Corporation. All rights reserved.\r
+#\r
+#  All rights reserved. This program and the accompanying materials       \r
+#  are licensed and made available under the terms and conditions of the BSD License   \r
+#  which accompanies this distribution. The full text of the license may be found at  \r
+#  http://opensource.org/licenses/bsd-license.php           \r
+#  \r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,      \r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = GenericBdsLib\r
+  FILE_GUID                      = e405ec31-ccaa-4dd4-83e8-0aec01703f7e\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = GenericBdsLib|DXE_DRIVER   \r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x0002000A\r
+\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+  DevicePath.c\r
+  Performance.c\r
+  BdsConnect.c\r
+  BdsMisc.c\r
+  R8Lib.c\r
+  BdsConsole.c\r
+  BdsBoot.c\r
+  InternalBdsLib.h\r
+  R8Lib.h\r
+\r
+[Sources.Ia32]\r
+  Ia32\ClearDr.asm\r
+  Ia32\BmMachine.h\r
+\r
+[Sources.X64]\r
+  x64\ClearDr.asm\r
+  x64\BmMachine.h\r
+\r
+[Sources.IPF]\r
+  Ipf\ShadowRom.c\r
+  Ipf\BmMachine.h\r
+\r
+[Sources.EBC]\r
+  Ebc\BmMachine.h\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  #\r
+  #This dependency is because of gEfiLegacyBiosProtocolGuid. It may be removed if a Library class is created to\r
+  #abstract away definition in Framework specification or PI spec incorporates the Legacy Booting Protocols.\r
+  #\r
+  IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+  DevicePathLib\r
+  PeCoffGetEntryPointLib\r
+  BaseLib\r
+  HobLib\r
+  UefiRuntimeServicesTableLib\r
+  DxeServicesTableLib\r
+  MemoryAllocationLib\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  PrintLib\r
+  PcdLib\r
+  PerformanceLib\r
+  TimerLib\r
+\r
+\r
+[Guids]\r
+  gEfiVT100PlusGuid                             # ALWAYS_CONSUMED\r
+  gEfiMemoryTypeInformationGuid                 # ALWAYS_CONSUMED\r
+  gEfiVTUTF8Guid                                # ALWAYS_CONSUMED\r
+  gEfiHobListGuid                               # ALWAYS_CONSUMED\r
+  gEfiShellFileGuid                             # ALWAYS_CONSUMED\r
+  gEfiGlobalVariableGuid                        # ALWAYS_CONSUMED\r
+  gEfiVT100Guid                                 # ALWAYS_CONSUMED\r
+  gEfiFileInfoGuid                              # ALWAYS_CONSUMED\r
+  gEfiPcAnsiGuid                                # ALWAYS_CONSUMED\r
+  gEfiGenericPlatformVariableGuid               # ALWAYS_CONSUMED\r
+\r
+\r
+[Protocols]\r
+  gEfiSimpleFileSystemProtocolGuid              # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSimpleTextOutProtocolGuid                 # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiPciIoProtocolGuid                         # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiLoadedImageProtocolGuid                   # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiDevicePathToTextProtocolGuid              # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSimpleNetworkProtocolGuid                 # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiDebugPortProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSimpleTextInProtocolGuid                  # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiBlockIoProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiFirmwareVolume2ProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiLegacyBiosProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiCpuArchProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiDevicePathProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
+\r
+[Pcd]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault
\ No newline at end of file
diff --git a/MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.msa b/MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.msa
new file mode 100644 (file)
index 0000000..076d7b9
--- /dev/null
@@ -0,0 +1,159 @@
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+  <MsaHeader>\r
+    <ModuleName>GenericBdsLib</ModuleName>\r
+    <ModuleType>DXE_DRIVER</ModuleType>\r
+    <GuidValue>e405ec31-ccaa-4dd4-83e8-0aec01703f7e</GuidValue>\r
+    <Version>1.0</Version>\r
+    <Abstract>Component name for module GenericBdsLib</Abstract>\r
+    <Description>FIX ME!</Description>\r
+    <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>\r
+    <License>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.</License>\r
+    <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION   0x00000052</Specification>\r
+  </MsaHeader>\r
+  <ModuleDefinitions>\r
+    <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+    <BinaryModule>false</BinaryModule>\r
+    <OutputFileBasename>GenericBdsLib</OutputFileBasename>\r
+  </ModuleDefinitions>\r
+  <LibraryClassDefinitions>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>PrintLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DebugLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseMemoryLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiBootServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>MemoryAllocationLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DxeServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiRuntimeServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>HobLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DevicePathLib</Keyword>\r
+    </LibraryClass>\r
+  </LibraryClassDefinitions>\r
+  <SourceFiles>\r
+    <Filename SupArchList="IPF">Ipf\BmMachine.h</Filename>\r
+    <Filename>R8Lib.h</Filename>\r
+    <Filename SupArchList="X64">x64\BmMachine.h</Filename>\r
+    <Filename>BdsLib.h</Filename>\r
+    <Filename>BdsBoot.c</Filename>\r
+    <Filename SupArchList="IA32">Ia32\BmMachine.h</Filename>\r
+    <Filename SupArchList="X64">x64\ClearDr.asm</Filename>\r
+    <Filename SupArchList="EBC">Ebc\BmMachine.h</Filename>\r
+    <Filename>BdsConsole.c</Filename>\r
+    <Filename>R8Lib.c</Filename>\r
+    <Filename SupArchList="IA32">Ia32\ClearDr.asm</Filename>\r
+    <Filename>BdsMisc.c</Filename>\r
+    <Filename>BdsConnect.c</Filename>\r
+    <Filename>Performance.c</Filename>\r
+    <Filename>DevicePath.c</Filename>\r
+    <Filename SupArchList="IPF">Ipf\ShadowRom.c</Filename>\r
+    <Filename>Performance.h</Filename>\r
+  </SourceFiles>\r
+  <PackageDependencies>\r
+    <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+    <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+  </PackageDependencies>\r
+  <Protocols>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiCpuArchProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiLegacyBiosProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiFirmwareVolumeProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiBlockIoProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiSimpleTextInProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiDebugPortProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiSimpleNetworkProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiFormBrowserProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiDevicePathToTextProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiLoadedImageProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiPciIoProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiSimpleTextOutProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiSimpleFileSystemProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+  </Protocols>\r
+  <Guids>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiPcAnsiGuid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiFileInfoGuid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiVT100Guid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiGlobalVariableGuid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiShellFileGuid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiHobListGuid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiVTUTF8Guid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiMemoryTypeInformationGuid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiVT100PlusGuid</GuidCName>\r
+    </GuidCNames>\r
+  </Guids>\r
+  <Externs>\r
+    <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+    <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+  </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
diff --git a/MdeModulePkg/Library/GenericBdsLib/Ia32/BmMachine.h b/MdeModulePkg/Library/GenericBdsLib/Ia32/BmMachine.h
new file mode 100644 (file)
index 0000000..e0b1fca
--- /dev/null
@@ -0,0 +1,34 @@
+/** @file
+
+Copyright (c) 2004 - 2006, Intel Corporation
+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.
+
+Module Name:
+
+  BmMachine.h
+
+Abstract:
+
+  Boot Manager Machine type
+
+
+
+Revision History
+
+
+**/
+
+#ifndef _BM_MACHINE_H
+#define _BM_MACHINE_H
+
+//@MT:#include "CpuIA32.h"
+
+#define DEFAULT_REMOVABLE_FILE_NAME L"\\EFI\\BOOT\\BOOTIA32.EFI"
+
+#endif
diff --git a/MdeModulePkg/Library/GenericBdsLib/Ia32/ClearDr.asm b/MdeModulePkg/Library/GenericBdsLib/Ia32/ClearDr.asm
new file mode 100644 (file)
index 0000000..c4c1665
--- /dev/null
@@ -0,0 +1,43 @@
+  title   ClearDr.asm
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2004, Intel Corporation                                                         
+; 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.             
+; 
+; Module Name:
+;
+;   ClearDr.asm
+; 
+; Abstract:
+; 
+;   Clear dr0 dr1 register
+;
+;------------------------------------------------------------------------------
+
+  .686
+  .MODEL FLAT,C
+  .CODE
+
+;------------------------------------------------------------------------------
+;  VOID
+;  ClearDebugRegisters (
+;    VOID
+;    )
+;------------------------------------------------------------------------------
+ClearDebugRegisters PROC    PUBLIC
+    push   eax
+    xor    eax, eax
+    mov    dr0, eax
+    mov    dr1, eax
+    pop    eax
+    ret
+ClearDebugRegisters ENDP
+
+END
+
diff --git a/MdeModulePkg/Library/GenericBdsLib/InternalBdsLib.h b/MdeModulePkg/Library/GenericBdsLib/InternalBdsLib.h
new file mode 100644 (file)
index 0000000..cae57b9
--- /dev/null
@@ -0,0 +1,102 @@
+/** @file
+
+Copyright (c) 2004 - 2007, Intel Corporation
+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.
+
+Module Name:
+
+  InternalBdsLib.h
+
+Abstract:
+
+  BDS library definition, include the file and data structure
+
+
+**/
+
+#ifndef _INTERNAL_BDS_LIB_H_
+#define _INTERNAL_BDS_LIB_H_
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci22.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/Cpu.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/DebugPort.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/LegacyBios.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/AcpiS3Save.h>
+#include <Protocol/Performance.h>
+
+#include <Guid/MemoryTypeInformation.h>
+#include <Guid/FileInfo.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/PcAnsi.h>
+#include <Guid/ShellFile.h>
+#include <Guid/HobList.h>
+#include <Guid/GenericPlatformVariable.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/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IfrSupportLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/GenericBdsLib.h>
+#include <Library/TimerLib.h>
+
+#include "BmMachine.h"
+
+#include "R8Lib.h"
+
+#define PERFORMANCE_SIGNATURE   EFI_SIGNATURE_32 ('P', 'e', 'r', 'f')
+#define PERF_TOKEN_SIZE         28
+#define PERF_TOKEN_LENGTH       (PERF_TOKEN_SIZE - 1)
+#define PERF_PEI_ENTRY_MAX_NUM  50
+
+typedef struct {
+  CHAR8   Token[PERF_TOKEN_SIZE];
+  UINT32  Duration;
+} PERF_DATA;
+
+typedef struct {
+  UINT64        BootToOs;
+  UINT64        S3Resume;
+  UINT32        S3EntryNum;
+  PERF_DATA     S3Entry[PERF_PEI_ENTRY_MAX_NUM];
+  UINT64        CpuFreq;
+  UINT64        BDSRaw;
+  UINT32        Count;
+  UINT32        Signiture;
+} PERF_HEADER;
+
+VOID
+WriteBootToOsPerformanceData (
+  VOID
+  );
+
+#endif // _BDS_LIB_H_
diff --git a/MdeModulePkg/Library/GenericBdsLib/Ipf/BmMachine.h b/MdeModulePkg/Library/GenericBdsLib/Ipf/BmMachine.h
new file mode 100644 (file)
index 0000000..e9afc8a
--- /dev/null
@@ -0,0 +1,34 @@
+/** @file
+
+Copyright (c) 2004 - 2006, Intel Corporation
+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.
+
+Module Name:
+
+  BmMachine.h
+
+Abstract:
+
+  Boot Manager Machine type
+
+
+
+Revision History
+
+
+**/
+
+#ifndef _BM_MACHINE_H
+#define _BM_MACHINE_H
+
+//@MT:#include "CpuIA64.h"
+
+#define DEFAULT_REMOVABLE_FILE_NAME L"\\EFI\\BOOT\\BOOTIA64.EFI"
+
+#endif
diff --git a/MdeModulePkg/Library/GenericBdsLib/Ipf/ShadowRom.c b/MdeModulePkg/Library/GenericBdsLib/Ipf/ShadowRom.c
new file mode 100644 (file)
index 0000000..b1bec9d
--- /dev/null
@@ -0,0 +1,56 @@
+/** @file
+
+Copyright (c) 2004, Intel Corporation
+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.
+
+Module Name:
+
+  ShadowRom.c
+
+Abstract:
+
+  Shadow all option rom
+
+Revision History
+
+
+**/
+
+//@MT:#include "Tiano.h"
+//@MT:#include "EfiDriverLib.h"
+
+//@MT:#include EFI_PROTOCOL_DEFINITION (LegacyBios)
+
+#include "InternalBdsLib.h"
+
+UINT8 mShadowRomFlag = 0;
+
+VOID
+ShadowAllOptionRom()
+{
+  EFI_STATUS                Status;
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
+  //
+  // Rom shadow only do once.
+  //
+  if (mShadowRomFlag == 0) {
+    Status = gBS->LocateProtocol (
+                    &gEfiLegacyBiosProtocolGuid,
+                    NULL,
+                    (VOID **) &LegacyBios
+                    );
+    if (!EFI_ERROR (Status)) {
+      LegacyBios->PrepareToBootEfi (LegacyBios, NULL, NULL);
+    }
+
+    mShadowRomFlag = 1;
+  }
+
+  return ;
+}
diff --git a/MdeModulePkg/Library/GenericBdsLib/Performance.c b/MdeModulePkg/Library/GenericBdsLib/Performance.c
new file mode 100644 (file)
index 0000000..0a42428
--- /dev/null
@@ -0,0 +1,326 @@
+/** @file
+
+Copyright (c) 2004 - 2007, Intel Corporation
+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.
+
+Module Name:
+
+  Performance.c
+
+Abstract:
+
+  This file include the file which can help to get the system
+  performance, all the function will only include if the performance
+  switch is set.
+
+
+**/
+
+#include "InternalBdsLib.h"
+
+STATIC PERF_HEADER               mPerfHeader;
+STATIC PERF_DATA                 mPerfData;
+
+STATIC
+VOID
+GetShortPdbFileName (
+  CHAR8  *PdbFileName,
+  CHAR8  *GaugeString
+  )
+/*++
+
+Routine Description:
+  
+Arguments:
+
+Returns:
+
+--*/
+{
+  UINTN Index;
+  UINTN Index1;
+  UINTN StartIndex;
+  UINTN EndIndex;
+
+  if (PdbFileName == NULL) {
+    AsciiStrCpy (GaugeString, " ");
+  } else {
+    StartIndex = 0;
+    for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
+      ;
+
+    for (Index = 0; PdbFileName[Index] != 0; Index++) {
+      if (PdbFileName[Index] == '\\') {
+        StartIndex = Index + 1;
+      }
+
+      if (PdbFileName[Index] == '.') {
+        EndIndex = Index;
+      }
+    }
+
+    Index1 = 0;
+    for (Index = StartIndex; Index < EndIndex; Index++) {
+      GaugeString[Index1] = PdbFileName[Index];
+      Index1++;
+      if (Index1 == PERF_TOKEN_LENGTH - 1) {
+        break;
+      }
+    }
+
+    GaugeString[Index1] = 0;
+  }
+
+  return ;
+}
+
+STATIC
+VOID
+GetNameFromHandle (
+  IN  EFI_HANDLE     Handle,
+  OUT CHAR8          *GaugeString
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_LOADED_IMAGE_PROTOCOL   *Image;
+  CHAR8                       *PdbFileName;
+  EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+
+  AsciiStrCpy (GaugeString, " ");
+
+  //
+  // Get handle name from image protocol
+  //
+  Status = gBS->HandleProtocol (
+                  Handle,
+                  &gEfiLoadedImageProtocolGuid,
+                  (VOID **) &Image
+                  );
+
+  if (EFI_ERROR (Status)) {
+    Status = gBS->OpenProtocol (
+                    Handle,
+                    &gEfiDriverBindingProtocolGuid,
+                    (VOID **) &DriverBinding,
+                    NULL,
+                    NULL,
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                    );
+    if (EFI_ERROR (Status)) {
+      return ;
+    }
+    //
+    // Get handle name from image protocol
+    //
+    Status = gBS->HandleProtocol (
+                    DriverBinding->ImageHandle,
+                    &gEfiLoadedImageProtocolGuid,
+                    (VOID **) &Image
+                    );
+  }
+
+  PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
+
+  if (PdbFileName != NULL) {
+    GetShortPdbFileName (PdbFileName, GaugeString);
+  }
+
+  return ;
+}
+
+VOID
+WriteBootToOsPerformanceData (
+  VOID
+  )
+/*++
+
+Routine Description:
+  
+  Allocates a block of memory and writes performance data of booting to OS into it.
+
+Arguments:
+  
+  None
+  
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS                Status;
+  EFI_PHYSICAL_ADDRESS      AcpiLowMemoryBase;
+  UINT32                    AcpiLowMemoryLength;
+  UINT32                    LimitCount;
+  EFI_HANDLE                *Handles;
+  UINTN                     NoHandles;
+  CHAR8                     GaugeString[PERF_TOKEN_LENGTH];
+  UINT8                     *Ptr;
+  UINT32                    Index;
+  UINT64                    Ticker;
+  UINT64                    Freq;
+  UINT32                    Duration;
+  UINTN                     LogEntryKey;
+  CONST VOID                *Handle;
+  CONST CHAR8               *Token;
+  CONST CHAR8               *Module;
+  UINT64                    StartTicker;
+  UINT64                    EndTicker;
+  UINT64                    StartValue;
+  UINT64                    EndValue;
+  BOOLEAN                   CountUp;
+
+  //
+  // Retrive time stamp count as early as possilbe
+  //
+  Ticker  = GetPerformanceCounter ();
+
+  Freq    = GetPerformanceCounterProperties (&StartValue, &EndValue);
+  
+  Freq    = DivU64x32 (Freq, 1000);
+
+  mPerfHeader.CpuFreq = Freq;
+
+  //
+  // Record BDS raw performance data
+  //
+  if (EndValue >= StartValue) {
+    mPerfHeader.BDSRaw = Ticker - StartValue;
+    CountUp            = TRUE;
+  } else {
+    mPerfHeader.BDSRaw = StartValue - Ticker;
+    CountUp            = FALSE;
+  }
+
+  AcpiLowMemoryLength   = 0x2000;
+
+  //
+  // Allocate a block of memory that contain performance data to OS
+  //
+  Status = gBS->AllocatePages (
+                  AllocateAnyPages,
+                  EfiACPIReclaimMemory,
+                  EFI_SIZE_TO_PAGES (AcpiLowMemoryLength),
+                  &AcpiLowMemoryBase
+                  );
+  if (EFI_ERROR (Status)) {
+    return ;
+  }
+
+
+  Ptr                   = (UINT8 *) ((UINT32) AcpiLowMemoryBase + sizeof (PERF_HEADER));
+  LimitCount            = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
+
+  //
+  // Put Detailed performance data into memory
+  //
+  Handles = NULL;
+  Status = gBS->LocateHandleBuffer (
+                  AllHandles,
+                  NULL,
+                  NULL,
+                  &NoHandles,
+                  &Handles
+                  );
+  if (EFI_ERROR (Status)) {
+    gBS->FreePages (AcpiLowMemoryBase, 1);
+    return ;
+  }
+  //
+  // Get DXE drivers performance
+  //
+  for (Index = 0; Index < NoHandles; Index++) {
+    Ticker = 0;
+    LogEntryKey = 0;
+    while ((LogEntryKey = GetPerformanceMeasurement (
+                            LogEntryKey,
+                            &Handle,
+                            &Token,
+                            &Module,
+                            &StartTicker,
+                            &EndTicker)) != 0) {
+      if ((Handle == Handles[Index]) && (EndTicker != 0)) {
+        Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
+      }
+    }
+
+    Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
+
+    if (Duration > 0) {
+
+      GetNameFromHandle (Handles[Index], GaugeString);
+
+      AsciiStrCpy (mPerfData.Token, GaugeString);
+      mPerfData.Duration = Duration;
+
+      CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
+      Ptr += sizeof (PERF_DATA);
+
+      mPerfHeader.Count++;
+      if (mPerfHeader.Count == LimitCount) {
+        goto Done;
+      }
+    }
+  }
+
+  FreePool (Handles);
+
+  //
+  // Get inserted performance data
+  //
+  LogEntryKey = 0;
+  while ((LogEntryKey = GetPerformanceMeasurement (
+                          LogEntryKey,
+                          &Handle,
+                          &Token,
+                          &Module,
+                          &StartTicker,
+                          &EndTicker)) != 0) {
+    if (Handle == NULL && EndTicker != 0) {
+
+      ZeroMem (&mPerfData, sizeof (PERF_DATA));
+
+      AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);
+      Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
+
+      mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
+
+      CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
+      Ptr += sizeof (PERF_DATA);
+
+      mPerfHeader.Count++;
+      if (mPerfHeader.Count == LimitCount) {
+        goto Done;
+      }
+    }
+  }
+
+Done:
+
+  mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;
+
+  //
+  // Put performance data to memory
+  //
+  CopyMem (
+    (UINTN *) (UINTN) AcpiLowMemoryBase,
+    &mPerfHeader,
+    sizeof (PERF_HEADER)
+    );
+
+  gRT->SetVariable (
+        L"PerfDataMemAddr",
+        &gEfiGenericPlatformVariableGuid,
+        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+        sizeof (EFI_PHYSICAL_ADDRESS),
+        &AcpiLowMemoryBase
+        );
+
+  return ;
+}
diff --git a/MdeModulePkg/Library/GenericBdsLib/R8Lib.c b/MdeModulePkg/Library/GenericBdsLib/R8Lib.c
new file mode 100644 (file)
index 0000000..537dc12
--- /dev/null
@@ -0,0 +1,114 @@
+/**@file
+  Copyright (c) 2007, Intel Corporation
+
+  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 "InternalBdsLib.h"
+
+/**
+  Get current boot mode.
+
+  @param  HobStart               Start pointer of hob list
+  @param  BootMode               Current boot mode recorded in PHIT hob
+
+  @retval EFI_NOT_FOUND          Invalid hob header
+  @retval EFI_SUCCESS            Boot mode found
+
+**/
+EFI_STATUS
+R8_GetHobBootMode (
+  IN  VOID           *HobStart,
+  OUT EFI_BOOT_MODE  *BootMode
+  )
+{
+  //
+  // Porting Guide:
+  // This library interface is simply obsolete.
+  // Include the source code to user code.
+  // In fact, since EFI_HANDOFF_HOB must be the first Hob,
+  // the following code can retrieve boot mode.
+  //
+  // EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
+  //
+  // HandOffHob = GetHobList ();
+  // ASSERT (HandOffHob->Header.HobType == EFI_HOB_TYPE_HANDOFF);
+  //
+  // BootMode = HandOffHob->BootMode;
+  //
+  EFI_PEI_HOB_POINTERS  Hob;
+
+  Hob.Raw = HobStart;
+  if (Hob.Header->HobType != EFI_HOB_TYPE_HANDOFF) {
+    return EFI_NOT_FOUND;
+  }
+
+  *BootMode = Hob.HandoffInformationTable->BootMode;
+  return EFI_SUCCESS;
+}
+
+
+
+
+/**
+  Get the next guid hob.
+
+  @param  HobStart               A pointer to the start hob.
+  @param  Guid                   A pointer to a guid.
+  @param  Buffer                 A pointer to the buffer.
+  @param  BufferSize             Buffer size.
+
+  @retval EFI_NOT_FOUND          Next Guid hob not found
+  @retval EFI_SUCCESS            Next Guid hob found and data for this Guid got
+  @retval EFI_INVALID_PARAMETER  invalid parameter
+
+**/
+EFI_STATUS
+R8_GetNextGuidHob (
+  IN OUT VOID      **HobStart,
+  IN     EFI_GUID  * Guid,
+  OUT    VOID      **Buffer,
+  OUT    UINTN     *BufferSize OPTIONAL
+  )
+{
+  //
+  // Porting Guide:
+  // This library interface is changed substantially with R9 counerpart GetNextGuidHob ().
+  // 1. R9 GetNextGuidHob has two parameters and returns the matched GUID HOB from the StartHob.
+  // 2. R9 GetNextGuidHob does not strip the HOB header, so caller is required to apply
+  //    GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () to extract the data section and its
+  //    size info respectively.
+  // 3. this function does not skip the starting HOB pointer unconditionally:
+  //    it returns HobStart back if HobStart itself meets the requirement;
+  //    caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
+  //
+  EFI_PEI_HOB_POINTERS  GuidHob;
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  GuidHob.Raw = GetNextGuidHob (Guid, *HobStart);
+  if (GuidHob.Raw == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  *Buffer = GET_GUID_HOB_DATA (GuidHob.Guid);
+  if (BufferSize != NULL) {
+    *BufferSize = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);
+  }
+
+  *HobStart = GET_NEXT_HOB (GuidHob);
+
+  return EFI_SUCCESS;
+}
+
+
diff --git a/MdeModulePkg/Library/GenericBdsLib/R8Lib.h b/MdeModulePkg/Library/GenericBdsLib/R8Lib.h
new file mode 100644 (file)
index 0000000..f62de99
--- /dev/null
@@ -0,0 +1,59 @@
+/**@file
+  Copyright (c) 2007, Intel Corporation
+
+  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.
+
+
+**/
+
+
+
+/**
+  Get current boot mode.
+
+  @param  HobStart               Start pointer of hob list
+  @param  BootMode               Current boot mode recorded in PHIT hob
+
+  @retval EFI_NOT_FOUND          Invalid hob header
+  @retval EFI_SUCCESS            Boot mode found
+
+**/
+EFI_STATUS
+R8_GetHobBootMode (
+  IN  VOID           *HobStart,
+  OUT EFI_BOOT_MODE  *BootMode
+  )
+;
+
+
+
+
+/**
+  Get the next guid hob.
+
+  @param  HobStart               A pointer to the start hob.
+  @param  Guid                   A pointer to a guid.
+  @param  Buffer                 A pointer to the buffer.
+  @param  BufferSize             Buffer size.
+
+  @retval EFI_NOT_FOUND          Next Guid hob not found
+  @retval EFI_SUCCESS            Next Guid hob found and data for this Guid got
+  @retval EFI_INVALID_PARAMETER  invalid parameter
+
+**/
+EFI_STATUS
+R8_GetNextGuidHob (
+  IN OUT VOID      **HobStart,
+  IN     EFI_GUID  * Guid,
+  OUT    VOID      **Buffer,
+  OUT    UINTN     *BufferSize OPTIONAL
+  )
+;
+
+
diff --git a/MdeModulePkg/Library/GenericBdsLib/x64/BmMachine.h b/MdeModulePkg/Library/GenericBdsLib/x64/BmMachine.h
new file mode 100644 (file)
index 0000000..a646371
--- /dev/null
@@ -0,0 +1,34 @@
+/** @file
+
+Copyright (c) 2005 - 2006, Intel Corporation
+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.
+
+Module Name:
+
+  BmMachine.h
+
+Abstract:
+
+  Boot Manager Machine type
+
+
+
+Revision History
+
+
+**/
+
+#ifndef _BM_MACHINE_H
+#define _BM_MACHINE_H
+
+//@MT:#include "CpuIA32.h"
+
+#define DEFAULT_REMOVABLE_FILE_NAME L"\\EFI\\BOOT\\BOOTX64.EFI"
+
+#endif
diff --git a/MdeModulePkg/Library/GenericBdsLib/x64/ClearDr.asm b/MdeModulePkg/Library/GenericBdsLib/x64/ClearDr.asm
new file mode 100644 (file)
index 0000000..83d198d
--- /dev/null
@@ -0,0 +1,41 @@
+  title   ClearDr.asm
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2005, Intel Corporation                                                         
+; 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.             
+; 
+; Module Name:
+;
+;   ClearDr.asm
+; 
+; Abstract:
+; 
+;   Clear dr0 dr1 register
+;
+;------------------------------------------------------------------------------
+
+text SEGMENT
+
+;------------------------------------------------------------------------------
+;  VOID
+;  ClearDebugRegisters (
+;    VOID
+;    )
+;------------------------------------------------------------------------------
+ClearDebugRegisters PROC    PUBLIC
+    push   rax
+    xor    rax, rax
+    mov    dr0, rax
+    mov    dr1, rax
+    pop    rax
+    ret
+ClearDebugRegisters ENDP
+
+END
+
diff --git a/MdeModulePkg/Library/GraphicsLib/Graphics.c b/MdeModulePkg/Library/GraphicsLib/Graphics.c
new file mode 100644 (file)
index 0000000..10b144c
--- /dev/null
@@ -0,0 +1,892 @@
+/**@file\r
+  Support for Basic Graphics operations.\r
+\r
+  BugBug: Currently *.BMP files are supported. This will be replaced\r
+          when Tiano graphics format is supported.\r
+\r
+\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/SimpleTextOut.h>\r
+#include <Protocol/OEMBadging.h>\r
+#include <Protocol/ConsoleControl.h>\r
+#include <Protocol/GraphicsOutput.h>\r
+#include <Protocol/FirmwareVolume2.h>\r
+#include <Protocol/UgaDraw.h>\r
+#include <Protocol/HiiFont.h>\r
+#include <Protocol/HiiImage.h>\r
+\r
+#include <Guid/Bmp.h>\r
+\r
+#include <Library/GraphicsLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DxePiLib.h>\r
+\r
+STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors[16] = {\r
+  { 0x00, 0x00, 0x00, 0x00 },\r
+  { 0x98, 0x00, 0x00, 0x00 },\r
+  { 0x00, 0x98, 0x00, 0x00 },\r
+  { 0x98, 0x98, 0x00, 0x00 },\r
+  { 0x00, 0x00, 0x98, 0x00 },\r
+  { 0x98, 0x00, 0x98, 0x00 },\r
+  { 0x00, 0x98, 0x98, 0x00 },\r
+  { 0x98, 0x98, 0x98, 0x00 },\r
+  { 0x10, 0x10, 0x10, 0x00 },\r
+  { 0xff, 0x10, 0x10, 0x00 },\r
+  { 0x10, 0xff, 0x10, 0x00 },\r
+  { 0xff, 0xff, 0x10, 0x00 },\r
+  { 0x10, 0x10, 0xff, 0x00 },\r
+  { 0xf0, 0x10, 0xff, 0x00 },\r
+  { 0x10, 0xff, 0xff, 0x00 },\r
+  { 0xff, 0xff, 0xff, 0x00 }\r
+};\r
+\r
+\r
+EFI_STATUS\r
+GetGraphicsBitMapFromFV (\r
+  IN  EFI_GUID      *FileNameGuid,\r
+  OUT VOID          **Image,\r
+  OUT UINTN         *ImageSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Return the graphics image file named FileNameGuid into Image and return it's\r
+  size in ImageSize. All Firmware Volumes (FV) in the system are searched for the\r
+  file name.\r
+\r
+Arguments:\r
+\r
+  FileNameGuid  - File Name of graphics file in the FV(s).\r
+\r
+  Image         - Pointer to pointer to return graphics image.  If NULL, a\r
+                  buffer will be allocated.\r
+\r
+  ImageSize     - Size of the graphics Image in bytes. Zero if no image found.\r
+\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS          - Image and ImageSize are valid.\r
+  EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size\r
+  EFI_NOT_FOUND        - FileNameGuid not found\r
+\r
+--*/\r
+{\r
+  return GetGraphicsBitMapFromFVEx (NULL, FileNameGuid, Image, ImageSize);\r
+}\r
+\r
+EFI_STATUS\r
+GetGraphicsBitMapFromFVEx (\r
+  IN  EFI_HANDLE    ImageHandle,\r
+  IN  EFI_GUID      *FileNameGuid,\r
+  OUT VOID          **Image,\r
+  OUT UINTN         *ImageSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Return the graphics image file named FileNameGuid into Image and return it's\r
+  size in ImageSize. All Firmware Volumes (FV) in the system are searched for the\r
+  file name.\r
+\r
+Arguments:\r
+\r
+  ImageHandle   - The driver image handle of the caller. The parameter is used to\r
+                  optimize the loading of the image file so that the FV from which\r
+                  the driver image is loaded will be tried first. \r
+\r
+  FileNameGuid  - File Name of graphics file in the FV(s).\r
+\r
+  Image         - Pointer to pointer to return graphics image.  If NULL, a \r
+                  buffer will be allocated.\r
+\r
+  ImageSize     - Size of the graphics Image in bytes. Zero if no image found.\r
+\r
+\r
+Returns: \r
+\r
+  EFI_SUCCESS          - Image and ImageSize are valid. \r
+  EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size\r
+  EFI_NOT_FOUND        - FileNameGuid not found\r
+\r
+--*/\r
+{\r
+  return PiLibGetSectionFromCurrentFv (\r
+           FileNameGuid,\r
+           EFI_SECTION_RAW,\r
+           0,\r
+           Image,\r
+           ImageSize\r
+           );\r
+}\r
+\r
+\r
+EFI_STATUS\r
+ConvertBmpToGopBlt (\r
+  IN  VOID      *BmpImage,\r
+  IN  UINTN     BmpImageSize,\r
+  IN OUT VOID   **GopBlt,\r
+  IN OUT UINTN  *GopBltSize,\r
+  OUT UINTN     *PixelHeight,\r
+  OUT UINTN     *PixelWidth\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Convert a *.BMP graphics image to a GOP/UGA blt buffer. If a NULL Blt buffer\r
+  is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt\r
+  buffer is passed in it will be used if it is big enough.\r
+\r
+Arguments:\r
+\r
+  BmpImage      - Pointer to BMP file\r
+\r
+  BmpImageSize  - Number of bytes in BmpImage\r
+\r
+  GopBlt        - Buffer containing GOP version of BmpImage.\r
+\r
+  GopBltSize    - Size of GopBlt in bytes.\r
+\r
+  PixelHeight   - Height of GopBlt/BmpImage in pixels\r
+\r
+  PixelWidth    - Width of GopBlt/BmpImage in pixels\r
+\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS           - GopBlt and GopBltSize are returned.\r
+  EFI_UNSUPPORTED       - BmpImage is not a valid *.BMP image\r
+  EFI_BUFFER_TOO_SMALL  - The passed in GopBlt buffer is not big enough.\r
+                          GopBltSize will contain the required size.\r
+  EFI_OUT_OF_RESOURCES  - No enough buffer to allocate\r
+\r
+--*/\r
+{\r
+  UINT8             *Image;\r
+  UINT8             *ImageHeader;\r
+  BMP_IMAGE_HEADER  *BmpHeader;\r
+  BMP_COLOR_MAP     *BmpColorMap;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
+  UINTN             BltBufferSize;\r
+  UINTN             Index;\r
+  UINTN             Height;\r
+  UINTN             Width;\r
+  UINTN             ImageIndex;\r
+  BOOLEAN           IsAllocated;\r
+\r
+  BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;\r
+  if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (BmpHeader->CompressionType != 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Calculate Color Map offset in the image.\r
+  //\r
+  Image       = BmpImage;\r
+  BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));\r
+\r
+  //\r
+  // Calculate graphics image data address in the image\r
+  //\r
+  Image         = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;\r
+  ImageHeader   = Image;\r
+\r
+  BltBufferSize = BmpHeader->PixelWidth * BmpHeader->PixelHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+  IsAllocated   = FALSE;\r
+  if (*GopBlt == NULL) {\r
+    *GopBltSize = BltBufferSize;\r
+    *GopBlt     = AllocatePool (*GopBltSize);\r
+    IsAllocated = TRUE;\r
+    if (*GopBlt == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  } else {\r
+    if (*GopBltSize < BltBufferSize) {\r
+      *GopBltSize = BltBufferSize;\r
+      return EFI_BUFFER_TOO_SMALL;\r
+    }\r
+  }\r
+\r
+  *PixelWidth   = BmpHeader->PixelWidth;\r
+  *PixelHeight  = BmpHeader->PixelHeight;\r
+\r
+  //\r
+  // Convert image from BMP to Blt buffer format\r
+  //\r
+  BltBuffer = *GopBlt;\r
+  for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {\r
+    Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];\r
+    for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {\r
+      switch (BmpHeader->BitPerPixel) {\r
+      case 1:\r
+        //\r
+        // Convert 1bit BMP to 24-bit color\r
+        //\r
+        for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {\r
+          Blt->Red    = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;\r
+          Blt->Green  = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;\r
+          Blt->Blue   = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;\r
+          Blt++;\r
+          Width++;\r
+        }\r
+\r
+        Blt --;\r
+        Width --;\r
+        break;\r
+\r
+      case 4:\r
+        //\r
+        // Convert BMP Palette to 24-bit color\r
+        //\r
+        Index       = (*Image) >> 4;\r
+        Blt->Red    = BmpColorMap[Index].Red;\r
+        Blt->Green  = BmpColorMap[Index].Green;\r
+        Blt->Blue   = BmpColorMap[Index].Blue;\r
+        if (Width < (BmpHeader->PixelWidth - 1)) {\r
+          Blt++;\r
+          Width++;\r
+          Index       = (*Image) & 0x0f;\r
+          Blt->Red    = BmpColorMap[Index].Red;\r
+          Blt->Green  = BmpColorMap[Index].Green;\r
+          Blt->Blue   = BmpColorMap[Index].Blue;\r
+        }\r
+        break;\r
+\r
+      case 8:\r
+        //\r
+        // Convert BMP Palette to 24-bit color\r
+        //\r
+        Blt->Red    = BmpColorMap[*Image].Red;\r
+        Blt->Green  = BmpColorMap[*Image].Green;\r
+        Blt->Blue   = BmpColorMap[*Image].Blue;\r
+        break;\r
+\r
+      case 24:\r
+        Blt->Blue   = *Image++;\r
+        Blt->Green  = *Image++;\r
+        Blt->Red    = *Image;\r
+        break;\r
+\r
+      default:\r
+        if (IsAllocated) {\r
+          gBS->FreePool (*GopBlt);\r
+          *GopBlt = NULL;\r
+        }\r
+        return EFI_UNSUPPORTED;\r
+        break;\r
+      };\r
+\r
+    }\r
+\r
+    ImageIndex = (UINTN) (Image - ImageHeader);\r
+    if ((ImageIndex % 4) != 0) {\r
+      //\r
+      // Bmp Image starts each row on a 32-bit boundary!\r
+      //\r
+      Image = Image + (4 - (ImageIndex % 4));\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+LockKeyboards (\r
+  IN  CHAR16    *Password\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Use Console Control Protocol to lock the Console In Spliter virtual handle.\r
+  This is the ConInHandle and ConIn handle in the EFI system table. All key\r
+  presses will be ignored until the Password is typed in. The only way to\r
+  disable the password is to type it in to a ConIn device.\r
+\r
+Arguments:\r
+  Password - Password used to lock ConIn device\r
+\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS     - ConsoleControl has been flipped to graphics and logo\r
+                          displayed.\r
+  EFI_UNSUPPORTED - Logo not found\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = ConsoleControl->LockStdIn (ConsoleControl, Password);\r
+  return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EnableQuietBoot (\r
+  IN  EFI_GUID  *LogoFile\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Use Console Control to turn off UGA based Simple Text Out consoles from going\r
+  to the UGA device. Put up LogoFile on every UGA device that is a console\r
+\r
+Arguments:\r
+\r
+  LogoFile - File name of logo to display on the center of the screen.\r
+\r
+\r
+Returns: \r
+\r
+  EFI_SUCCESS           - ConsoleControl has been flipped to graphics and logo\r
+                          displayed.\r
+  EFI_UNSUPPORTED       - Logo not found\r
+\r
+--*/\r
+{\r
+  return EnableQuietBootEx (LogoFile, NULL);\r
+}\r
+\r
+EFI_STATUS\r
+EnableQuietBootEx (\r
+  IN  EFI_GUID    *LogoFile,\r
+  IN  EFI_HANDLE  ImageHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Use Console Control to turn off GOP/UGA based Simple Text Out consoles from going\r
+  to the GOP/UGA device. Put up LogoFile on every GOP/UGA device that is a console\r
+\r
+Arguments:\r
+\r
+  LogoFile    - File name of logo to display on the center of the screen.\r
+  ImageHandle - The driver image handle of the caller. The parameter is used to\r
+                optimize the loading of the logo file so that the FV from which\r
+                the driver image is loaded will be tried first.\r
+\r
+\r
+Returns: \r
+\r
+  EFI_SUCCESS           - ConsoleControl has been flipped to graphics and logo\r
+                          displayed.\r
+  EFI_UNSUPPORTED       - Logo not found\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;\r
+  EFI_OEM_BADGING_PROTOCOL      *Badging;\r
+  UINT32                        SizeOfX;\r
+  UINT32                        SizeOfY;\r
+  INTN                          DestX;\r
+  INTN                          DestY;\r
+  UINT8                         *ImageData;\r
+  UINTN                         ImageSize;\r
+  UINTN                         BltSize;\r
+  UINT32                        Instance;\r
+  EFI_BADGING_FORMAT            Format;\r
+  EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;\r
+  UINTN                         CoordinateX;\r
+  UINTN                         CoordinateY;\r
+  UINTN                         Height;\r
+  UINTN                         Width;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
+  EFI_UGA_DRAW_PROTOCOL         *UgaDraw;\r
+  UINT32                        ColorDepth;\r
+  UINT32                        RefreshRate;\r
+  EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID**)&ConsoleControl);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  UgaDraw = NULL;\r
+  //\r
+  // Try to open GOP first\r
+  //\r
+  Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID**)&GraphicsOutput);\r
+  if (EFI_ERROR (Status)) {\r
+    GraphicsOutput = NULL;\r
+    //\r
+    // Open GOP failed, try to open UGA\r
+    //\r
+    Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID**)&UgaDraw);\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  Badging = NULL;\r
+  Status  = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID**)&Badging);\r
+\r
+  ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);\r
+\r
+  if (GraphicsOutput != NULL) {\r
+    SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+    SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
+  } else {\r
+    Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  Instance = 0;\r
+  while (1) {\r
+    ImageData = NULL;\r
+    ImageSize = 0;\r
+\r
+    if (Badging != NULL) {\r
+      Status = Badging->GetImage (\r
+                          Badging,\r
+                          &Instance,\r
+                          &Format,\r
+                          &ImageData,\r
+                          &ImageSize,\r
+                          &Attribute,\r
+                          &CoordinateX,\r
+                          &CoordinateY\r
+                          );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Currently only support BMP format\r
+      //\r
+      if (Format != EfiBadgingFormatBMP) {\r
+        gBS->FreePool (ImageData);\r
+        continue;\r
+      }\r
+    } else {\r
+      Status = GetGraphicsBitMapFromFVEx (ImageHandle, LogoFile, (VOID **) &ImageData, &ImageSize);\r
+      if (EFI_ERROR (Status)) {\r
+        return EFI_UNSUPPORTED;\r
+      }\r
+\r
+      CoordinateX = 0;\r
+      CoordinateY = 0;\r
+      Attribute   = EfiBadgingDisplayAttributeCenter;\r
+    }\r
+\r
+    Blt = NULL;\r
+    Status = ConvertBmpToGopBlt (\r
+              ImageData,\r
+              ImageSize,\r
+              (VOID**)&Blt,\r
+              &BltSize,\r
+              &Height,\r
+              &Width\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      gBS->FreePool (ImageData);\r
+      if (Badging == NULL) {\r
+        return Status;\r
+      } else {\r
+        continue;\r
+      }\r
+    }\r
+\r
+    switch (Attribute) {\r
+    case EfiBadgingDisplayAttributeLeftTop:\r
+      DestX = CoordinateX;\r
+      DestY = CoordinateY;\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeCenterTop:\r
+      DestX = (SizeOfX - Width) / 2;\r
+      DestY = CoordinateY;\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeRightTop:\r
+      DestX = (SizeOfX - Width - CoordinateX);\r
+      DestY = CoordinateY;;\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeCenterRight:\r
+      DestX = (SizeOfX - Width - CoordinateX);\r
+      DestY = (SizeOfY - Height) / 2;\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeRightBottom:\r
+      DestX = (SizeOfX - Width - CoordinateX);\r
+      DestY = (SizeOfY - Height - CoordinateY);\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeCenterBottom:\r
+      DestX = (SizeOfX - Width) / 2;\r
+      DestY = (SizeOfY - Height - CoordinateY);\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeLeftBottom:\r
+      DestX = CoordinateX;\r
+      DestY = (SizeOfY - Height - CoordinateY);\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeCenterLeft:\r
+      DestX = CoordinateX;\r
+      DestY = (SizeOfY - Height) / 2;\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeCenter:\r
+      DestX = (SizeOfX - Width) / 2;\r
+      DestY = (SizeOfY - Height) / 2;\r
+      break;\r
+\r
+    default:\r
+      DestX = CoordinateX;\r
+      DestY = CoordinateY;\r
+      break;\r
+    }\r
+\r
+    if ((DestX >= 0) && (DestY >= 0)) {\r
+      if (GraphicsOutput != NULL) {\r
+        Status = GraphicsOutput->Blt (\r
+                            GraphicsOutput,\r
+                            Blt,\r
+                            EfiBltBufferToVideo,\r
+                            0,\r
+                            0,\r
+                            (UINTN) DestX,\r
+                            (UINTN) DestY,\r
+                            Width,\r
+                            Height,\r
+                            Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+                            );\r
+      } else {\r
+        Status = UgaDraw->Blt (\r
+                            UgaDraw,\r
+                            (EFI_UGA_PIXEL *) Blt,\r
+                            EfiUgaBltBufferToVideo,\r
+                            0,\r
+                            0,\r
+                            (UINTN) DestX,\r
+                            (UINTN) DestY,\r
+                            Width,\r
+                            Height,\r
+                            Width * sizeof (EFI_UGA_PIXEL)\r
+                            );\r
+      }\r
+    }\r
+\r
+    gBS->FreePool (ImageData);\r
+    gBS->FreePool (Blt);\r
+\r
+    if (Badging == NULL) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+DisableQuietBoot (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA\r
+  Simple Text Out screens will now be synced up with all non GOP/UGA output devices\r
+\r
+Arguments:\r
+\r
+  NONE\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS           - GOP/UGA devices are back in text mode and synced up.\r
+  EFI_UNSUPPORTED       - Logo not found\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);\r
+}\r
+\r
+UINTN\r
+_IPrint (\r
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL     *GraphicsOutput,\r
+  IN EFI_UGA_DRAW_PROTOCOL            *UgaDraw,\r
+  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL     *Sto,\r
+  IN UINTN                            X,\r
+  IN UINTN                            Y,\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL    *Foreground,\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL    *Background,\r
+  IN CHAR16                           *fmt,\r
+  IN VA_LIST                          args\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Display string worker for: Print, PrintAt, IPrint, IPrintAt\r
+\r
+Arguments:\r
+\r
+  GraphicsOutput  - Graphics output protocol interface\r
+\r
+  UgaDraw         - UGA draw protocol interface\r
+  \r
+  Sto             - Simple text out protocol interface\r
+  \r
+  X               - X coordinate to start printing\r
+  \r
+  Y               - Y coordinate to start printing\r
+  \r
+  Foreground      - Foreground color\r
+  \r
+  Background      - Background color\r
+  \r
+  fmt             - Format string\r
+  \r
+  args            - Print arguments\r
+\r
+Returns: \r
+\r
+  EFI_SUCCESS             -  success\r
+  EFI_OUT_OF_RESOURCES    -  out of resources\r
+\r
+--*/\r
+{\r
+  VOID                           *Buffer;\r
+  EFI_STATUS                     Status;\r
+  UINTN                          Index;\r
+  CHAR16                         *UnicodeWeight;\r
+  UINT32                         HorizontalResolution;\r
+  UINT32                         VerticalResolution;\r
+  UINT32                         ColorDepth;\r
+  UINT32                         RefreshRate;\r
+  UINTN                          BufferLen;\r
+  UINTN                          LineBufferLen;\r
+  EFI_HII_FONT_PROTOCOL          *HiiFont;\r
+  EFI_IMAGE_OUTPUT               *Blt;\r
+  EFI_FONT_DISPLAY_INFO          *FontInfo;  \r
+\r
+  //\r
+  // For now, allocate an arbitrarily long buffer\r
+  //\r
+  Buffer = AllocateZeroPool (0x10000);\r
+  if (Buffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (GraphicsOutput != NULL) {\r
+    HorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+    VerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;\r
+  } else {\r
+    UgaDraw->GetMode (UgaDraw, &HorizontalResolution, &VerticalResolution, &ColorDepth, &RefreshRate);\r
+  }\r
+  ASSERT ((HorizontalResolution != 0) && (VerticalResolution !=0)); \r
+\r
+  Blt      = NULL;\r
+  FontInfo = NULL;\r
+  ASSERT (GraphicsOutput != NULL);\r
+  Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, (VOID **) &HiiFont);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Error;\r
+  }  \r
+\r
+  UnicodeVSPrint (Buffer, 0x10000, fmt, args);\r
+  \r
+  UnicodeWeight = (CHAR16 *) Buffer;\r
+\r
+  for (Index = 0; UnicodeWeight[Index] != 0; Index++) {\r
+    if (UnicodeWeight[Index] == CHAR_BACKSPACE ||\r
+        UnicodeWeight[Index] == CHAR_LINEFEED  ||\r
+        UnicodeWeight[Index] == CHAR_CARRIAGE_RETURN) {\r
+      UnicodeWeight[Index] = 0;\r
+    }\r
+  }\r
+\r
+  BufferLen = StrLen (Buffer);\r
\r
+\r
+  LineBufferLen = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * HorizontalResolution * EFI_GLYPH_HEIGHT;\r
+  if (EFI_GLYPH_WIDTH * EFI_GLYPH_HEIGHT * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * BufferLen > LineBufferLen) {\r
+     Status = EFI_INVALID_PARAMETER;\r
+     goto Error;\r
+  }\r
+\r
+  Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
+  if (Blt == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+\r
+  Blt->Width        = (UINT16) (HorizontalResolution);\r
+  Blt->Height       = (UINT16) (VerticalResolution);\r
+  Blt->Image.Screen = GraphicsOutput;\r
+   \r
+  FontInfo = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));\r
+  if (FontInfo == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+  if (Foreground != NULL) {\r
+    CopyMem (&FontInfo->ForegroundColor, Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+  } else {\r
+    CopyMem (\r
+      &FontInfo->ForegroundColor, \r
+      &mEfiColors[Sto->Mode->Attribute & 0x0f], \r
+      sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+      );\r
+  }\r
+  if (Background != NULL) {\r
+    CopyMem (&FontInfo->BackgroundColor, Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+  } else {\r
+    CopyMem (\r
+      &FontInfo->BackgroundColor, \r
+      &mEfiColors[Sto->Mode->Attribute >> 4], \r
+      sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+      );\r
+  }\r
+\r
+  Status = HiiFont->StringToImage (\r
+                       HiiFont,\r
+                       EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN,\r
+                       Buffer,\r
+                       FontInfo,\r
+                       &Blt,\r
+                       X,\r
+                       Y,\r
+                       NULL,\r
+                       NULL,\r
+                       NULL\r
+                       );\r
+  \r
+\r
+Error:\r
+  SafeFreePool (Blt);\r
+  SafeFreePool (FontInfo);\r
+  gBS->FreePool (Buffer);\r
+  return Status;\r
+}\r
+\r
+UINTN\r
+PrintXY (\r
+  IN UINTN                            X,\r
+  IN UINTN                            Y,\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL    *ForeGround, OPTIONAL\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL    *BackGround, OPTIONAL\r
+  IN CHAR16                           *Fmt,\r
+  ...\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Prints a formatted unicode string to the default console\r
+\r
+Arguments:\r
+\r
+    X           - X coordinate to start printing\r
+    \r
+    Y           - Y coordinate to start printing\r
+    \r
+    ForeGround  - Foreground color\r
+    \r
+    BackGround  - Background color\r
+\r
+    Fmt         - Format string\r
+\r
+    ...         - Print arguments\r
+\r
+Returns:\r
+\r
+    Length of string printed to the console\r
+\r
+--*/\r
+{\r
+  EFI_HANDLE                    Handle;\r
+  EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;\r
+  EFI_UGA_DRAW_PROTOCOL         *UgaDraw;\r
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *Sto;\r
+  EFI_STATUS                    Status;\r
+  VA_LIST                       Args;\r
+\r
+  VA_START (Args, Fmt);\r
+\r
+  Handle = gST->ConsoleOutHandle;\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiGraphicsOutputProtocolGuid,\r
+                  (VOID**)&GraphicsOutput\r
+                  );\r
+\r
+  UgaDraw = NULL;\r
+  if (EFI_ERROR (Status)) {\r
+    GraphicsOutput = NULL;\r
+\r
+    Status = gBS->HandleProtocol (\r
+                    Handle,\r
+                    &gEfiUgaDrawProtocolGuid,\r
+                    (VOID**)&UgaDraw\r
+                    );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiSimpleTextOutProtocolGuid,\r
+                  (VOID**)&Sto\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return _IPrint (GraphicsOutput, UgaDraw, Sto, X, Y, ForeGround, BackGround, Fmt, Args);\r
+}\r
+\r
diff --git a/MdeModulePkg/Library/GraphicsLib/GraphicsLib.inf b/MdeModulePkg/Library/GraphicsLib/GraphicsLib.inf
new file mode 100644 (file)
index 0000000..c7cb0af
--- /dev/null
@@ -0,0 +1,57 @@
+#/** @file\r
+# Graphics Library for UEFI drivers\r
+#\r
+# This library provides supports for basic graphic functions.\r
+# Copyright (c) 2006 - 2007, Intel Corporation.\r
+#\r
+#  All rights reserved. This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = EdkGraphicsLib\r
+  FILE_GUID                      = 08c1a0e4-1208-47f8-a2c5-f42eabee653a\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = GraphicsLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER\r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x00020000\r
+\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+  Graphics.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiBootServicesTableLib\r
+  MemoryAllocationLib\r
+  BaseLib\r
+  PrintLib\r
+  DebugLib\r
+  DxePiLib\r
+  BaseMemoryLib\r
+\r
+[Protocols]\r
+  gEfiSimpleTextOutProtocolGuid                 # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiGraphicsOutputProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiUgaDrawProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiConsoleControlProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiFirmwareVolume2ProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiOEMBadgingProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiHiiFontProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED   
\ No newline at end of file
diff --git a/MdeModulePkg/Library/GraphicsLib/GraphicsLib.msa b/MdeModulePkg/Library/GraphicsLib/GraphicsLib.msa
new file mode 100644 (file)
index 0000000..2007ba0
--- /dev/null
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+  <MsaHeader>\r
+    <ModuleName>EdkGraphicsLib</ModuleName>\r
+    <ModuleType>DXE_DRIVER</ModuleType>\r
+    <GuidValue>08c1a0e4-1208-47f8-a2c5-f42eabee653a</GuidValue>\r
+    <Version>1.0</Version>\r
+    <Abstract>Graphics Library for UEFI drivers</Abstract>\r
+    <Description>This library provides supports for basic graphic functions.</Description>\r
+    <Copyright>Copyright (c) 2006 - 2007, Intel Corporation.</Copyright>\r
+    <License>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.</License>\r
+    <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION   0x00000052</Specification>\r
+  </MsaHeader>\r
+  <ModuleDefinitions>\r
+    <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+    <BinaryModule>false</BinaryModule>\r
+    <OutputFileBasename>EdkGraphicsLib</OutputFileBasename>\r
+  </ModuleDefinitions>\r
+  <LibraryClassDefinitions>\r
+    <LibraryClass Usage="ALWAYS_PRODUCED" SupModuleList="DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER">\r
+      <Keyword>EdkGraphicsLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>PrintLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>MemoryAllocationLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiBootServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+  </LibraryClassDefinitions>\r
+  <SourceFiles>\r
+    <Filename>Graphics.c</Filename>\r
+  </SourceFiles>\r
+  <PackageDependencies>\r
+    <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+    <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+  </PackageDependencies>\r
+  <Protocols>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiOEMBadgingProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiFirmwareVolumeProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiConsoleControlProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiUgaDrawProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiGraphicsOutputProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiSimpleTextOutProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+  </Protocols>\r
+  <Externs>\r
+    <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+    <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+  </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
diff --git a/MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.inf b/MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.inf
new file mode 100644 (file)
index 0000000..74b7c10
--- /dev/null
@@ -0,0 +1,71 @@
+#/** @file\r
+# Component name for module UefiEfiIfrSupportLib\r
+#\r
+# FIX ME!\r
+# Copyright (c) 2007, Intel Corporation. All rights reserved.\r
+#\r
+#  All rights reserved. This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  \r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = IfrSupportLib\r
+  FILE_GUID                      = bf38668e-e231-4baa-99e4-8c0e4c35dca6\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = IfrSupportLib\r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x00020000\r
+\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+  UefiIfrCommon.c\r
+  UefiIfrForm.c\r
+  UefiIfrLibraryInternal.h\r
+  UefiIfrOpCodeCreation.c\r
+  UefiIfrString.c\r
+  R8Lib.h\r
+  R8Lib.c\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+  MemoryAllocationLib\r
+  DevicePathLib\r
+  BaseLib\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeServicesTableLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  PcdLib\r
+\r
+[Guids]\r
+  gEfiGlobalVariableGuid                        # ALWAYS_CONSUMED\r
+\r
+[Protocols]\r
+  gEfiDevicePathProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiHiiDatabaseProtocolGuid\r
+  gEfiHiiStringProtocolGuid\r
+  gEfiHiiConfigRoutingProtocolGuid\r
+  gEfiFormBrowser2ProtocolGuid   \r
+\r
+[Pcd]\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang
\ No newline at end of file
diff --git a/MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.msa b/MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.msa
new file mode 100644 (file)
index 0000000..dc9d665
--- /dev/null
@@ -0,0 +1,74 @@
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+  <MsaHeader>\r
+    <ModuleName>UefiEfiIfrSupportLib</ModuleName>\r
+    <ModuleType>DXE_DRIVER</ModuleType>\r
+    <GuidValue>bf38668e-e231-4baa-99e4-8c0e4c35dca6</GuidValue>\r
+    <Version>1.0</Version>\r
+    <Abstract>Component name for module UefiEfiIfrSupportLib</Abstract>\r
+    <Description>FIX ME!</Description>\r
+    <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>\r
+    <License>All rights reserved. This program and the accompanying materials\r
+      are licensed and made available under the terms and conditions of the BSD License\r
+      which accompanies this distribution.  The full text of the license may be found at\r
+      http://opensource.org/licenses/bsd-license.php\r
+      \r
+      THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+      WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>\r
+    <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION   0x00000052</Specification>\r
+  </MsaHeader>\r
+  <ModuleDefinitions>\r
+    <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+    <BinaryModule>false</BinaryModule>\r
+    <OutputFileBasename>UefiEfiIfrSupportLib</OutputFileBasename>\r
+  </ModuleDefinitions>\r
+  <LibraryClassDefinitions>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DebugLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseMemoryLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiRuntimeServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiBootServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DevicePathLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>MemoryAllocationLib</Keyword>\r
+    </LibraryClass>\r
+  </LibraryClassDefinitions>\r
+  <SourceFiles>\r
+    <Filename>R8Lib.c</Filename>\r
+    <Filename>R8Lib.h</Filename>\r
+    <Filename>UefiIfrString.c</Filename>\r
+    <Filename>UefiIfrOpCodeCreation.c</Filename>\r
+    <Filename>UefiIfrLibraryInternal.h</Filename>\r
+    <Filename>UefiIfrForm.c</Filename>\r
+    <Filename>UefiIfrCommon.c</Filename>\r
+  </SourceFiles>\r
+  <PackageDependencies>\r
+    <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+    <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+  </PackageDependencies>\r
+  <Protocols>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+  </Protocols>\r
+  <Guids>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiGlobalVariableGuid</GuidCName>\r
+    </GuidCNames>\r
+  </Guids>\r
+  <Externs>\r
+    <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+    <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+  </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
diff --git a/MdeModulePkg/Library/IfrSupportLib/R8Lib.c b/MdeModulePkg/Library/IfrSupportLib/R8Lib.c
new file mode 100644 (file)
index 0000000..634bdb6
--- /dev/null
@@ -0,0 +1,241 @@
+/**@file
+  Copyright (c) 2007, Intel Corporation
+
+  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 "UefiIfrLibraryInternal.h"
+
+
+CHAR16
+InternalNibbleToHexChar (
+  IN UINT8      Nibble
+  )
+/*++
+
+  Routine Description:
+    Converts the low nibble of a byte  to hex unicode character.
+
+  Arguments:
+    Nibble - lower nibble of a byte.
+
+  Returns:
+    Hex unicode character.
+
+--*/
+{
+  Nibble &= 0x0F;
+  if (Nibble <= 0x9) {
+    return (CHAR16)(Nibble + L'0');
+  }
+
+  return (CHAR16)(Nibble - 0xA + L'A');
+}
+
+
+/**
+  Converts binary buffer to Unicode string.
+  At a minimum, any blob of data could be represented as a hex string.
+
+  @param  Str                    Pointer to the string.
+  @param  HexStringBufferLength  Length in bytes of buffer to hold the hex string.
+                                 Includes tailing '\0' character. If routine return
+                                 with EFI_SUCCESS, containing length of hex string
+                                 buffer. If routine return with
+                                 EFI_BUFFER_TOO_SMALL, containg length of hex
+                                 string buffer desired.
+  @param  Buf                    Buffer to be converted from.
+  @param  Len                    Length in bytes of the buffer to be converted.
+
+  @retval EFI_SUCCESS            Routine success.
+  @retval EFI_BUFFER_TOO_SMALL   The hex string buffer is too small.
+
+**/
+EFI_STATUS
+R8_BufToHexString (
+  IN OUT CHAR16                    *Str,
+  IN OUT UINTN                     *HexStringBufferLength,
+  IN     UINT8                     *Buf,
+  IN     UINTN                      Len
+  )
+{
+  //
+  // Porting Guide:
+  // This library interface is simply obsolete.
+  // Include the source code to user code.
+  //
+  UINTN       Idx;
+  UINT8       Byte;
+  UINTN       StrLen;
+
+  //
+  // Make sure string is either passed or allocate enough.
+  // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.
+  // Plus the Unicode termination character.
+  //
+  StrLen = Len * 2;
+  if (StrLen > ((*HexStringBufferLength) - 1)) {
+    *HexStringBufferLength = StrLen + 1;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  *HexStringBufferLength = StrLen + 1;
+  //
+  // Ends the string.
+  //
+  Str[StrLen] = L'\0';
+
+  for (Idx = 0; Idx < Len; Idx++) {
+
+    Byte = Buf[Idx];
+    Str[StrLen - 1 - Idx * 2] = InternalNibbleToHexChar (Byte);
+    Str[StrLen - 2 - Idx * 2] = InternalNibbleToHexChar ((UINT8)(Byte >> 4));
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+
+
+/**
+  Converts Unicode string to binary buffer.
+  The conversion may be partial.
+  The first character in the string that is not hex digit stops the conversion.
+  At a minimum, any blob of data could be represented as a hex string.
+
+  @param  Buf                    Pointer to buffer that receives the data.
+  @param  Len                    Length in bytes of the buffer to hold converted
+                                 data. If routine return with EFI_SUCCESS,
+                                 containing length of converted data. If routine
+                                 return with EFI_BUFFER_TOO_SMALL, containg length
+                                 of buffer desired.
+  @param  Str                    String to be converted from.
+  @param  ConvertedStrLen        Length of the Hex String consumed.
+
+  @retval EFI_SUCCESS            Routine Success.
+  @retval EFI_BUFFER_TOO_SMALL   The buffer is too small to hold converted data.
+
+**/
+EFI_STATUS
+R8_HexStringToBuf (
+  IN OUT UINT8                     *Buf,
+  IN OUT UINTN                    *Len,
+  IN     CHAR16                    *Str,
+  OUT    UINTN                     *ConvertedStrLen  OPTIONAL
+  )
+{
+  //
+  // Porting Guide:
+  // This library interface is simply obsolete.
+  // Include the source code to user code.
+  //
+
+  UINTN       HexCnt;
+  UINTN       Idx;
+  UINTN       BufferLength;
+  UINT8       Digit;
+  UINT8       Byte;
+
+  //
+  // Find out how many hex characters the string has.
+  //
+  for (Idx = 0, HexCnt = 0; R8_IsHexDigit (&Digit, Str[Idx]); Idx++, HexCnt++);
+
+  if (HexCnt == 0) {
+    *Len = 0;
+    return EFI_SUCCESS;
+  }
+  //
+  // Two Unicode characters make up 1 buffer byte. Round up.
+  //
+  BufferLength = (HexCnt + 1) / 2;
+
+  //
+  // Test if  buffer is passed enough.
+  //
+  if (BufferLength > (*Len)) {
+    *Len = BufferLength;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  *Len = BufferLength;
+
+  for (Idx = 0; Idx < HexCnt; Idx++) {
+
+    R8_IsHexDigit (&Digit, Str[HexCnt - 1 - Idx]);
+
+    //
+    // For odd charaters, write the lower nibble for each buffer byte,
+    // and for even characters, the upper nibble.
+    //
+    if ((Idx & 1) == 0) {
+      Byte = Digit;
+    } else {
+      Byte = Buf[Idx / 2];
+      Byte &= 0x0F;
+      Byte = (UINT8) (Byte | Digit << 4);
+    }
+
+    Buf[Idx / 2] = Byte;
+  }
+
+  if (ConvertedStrLen != NULL) {
+    *ConvertedStrLen = HexCnt;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Determines if a Unicode character is a hexadecimal digit.
+  The test is case insensitive.
+
+  @param  Digit                  Pointer to byte that receives the value of the hex
+                                 character.
+  @param  Char                   Unicode character to test.
+
+  @retval TRUE                   If the character is a hexadecimal digit.
+  @retval FALSE                  Otherwise.
+
+**/
+BOOLEAN
+R8_IsHexDigit (
+  OUT UINT8      *Digit,
+  IN  CHAR16      Char
+  )
+{
+  //
+  // Porting Guide:
+  // This library interface is simply obsolete.
+  // Include the source code to user code.
+  //
+
+  if ((Char >= L'0') && (Char <= L'9')) {
+    *Digit = (UINT8) (Char - L'0');
+    return TRUE;
+  }
+
+  if ((Char >= L'A') && (Char <= L'F')) {
+    *Digit = (UINT8) (Char - L'A' + 0x0A);
+    return TRUE;
+  }
+
+  if ((Char >= L'a') && (Char <= L'f')) {
+    *Digit = (UINT8) (Char - L'a' + 0x0A);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+
diff --git a/MdeModulePkg/Library/IfrSupportLib/R8Lib.h b/MdeModulePkg/Library/IfrSupportLib/R8Lib.h
new file mode 100644 (file)
index 0000000..ca9b939
--- /dev/null
@@ -0,0 +1,93 @@
+/**@file
+  Copyright (c) 2007, Intel Corporation
+
+  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.
+
+
+**/
+
+
+
+/**
+  Converts binary buffer to Unicode string.
+  At a minimum, any blob of data could be represented as a hex string.
+
+  @param  Str                    Pointer to the string.
+  @param  HexStringBufferLength  Length in bytes of buffer to hold the hex string.
+                                 Includes tailing '\0' character. If routine return
+                                 with EFI_SUCCESS, containing length of hex string
+                                 buffer. If routine return with
+                                 EFI_BUFFER_TOO_SMALL, containg length of hex
+                                 string buffer desired.
+  @param  Buf                    Buffer to be converted from.
+  @param  Len                    Length in bytes of the buffer to be converted.
+
+  @retval EFI_SUCCESS            Routine success.
+  @retval EFI_BUFFER_TOO_SMALL   The hex string buffer is too small.
+
+**/
+EFI_STATUS
+R8_BufToHexString (
+  IN OUT CHAR16                    *Str,
+  IN OUT UINTN                     *HexStringBufferLength,
+  IN     UINT8                     *Buf,
+  IN     UINTN                      Len
+  )
+;
+
+
+
+
+/**
+  Converts Unicode string to binary buffer.
+  The conversion may be partial.
+  The first character in the string that is not hex digit stops the conversion.
+  At a minimum, any blob of data could be represented as a hex string.
+
+  @param  Buf                    Pointer to buffer that receives the data.
+  @param  Len                    Length in bytes of the buffer to hold converted
+                                 data. If routine return with EFI_SUCCESS,
+                                 containing length of converted data. If routine
+                                 return with EFI_BUFFER_TOO_SMALL, containg length
+                                 of buffer desired.
+  @param  Str                    String to be converted from.
+  @param  ConvertedStrLen        Length of the Hex String consumed.
+
+  @retval EFI_SUCCESS            Routine Success.
+  @retval EFI_BUFFER_TOO_SMALL   The buffer is too small to hold converted data.
+
+**/
+EFI_STATUS
+R8_HexStringToBuf (
+  IN OUT UINT8                     *Buf,
+  IN OUT UINTN                    *Len,
+  IN     CHAR16                    *Str,
+  OUT    UINTN                     *ConvertedStrLen  OPTIONAL
+  )
+;
+
+/**
+  Determines if a Unicode character is a hexadecimal digit.
+  The test is case insensitive.
+
+  @param  Digit                  Pointer to byte that receives the value of the hex
+                                 character.
+  @param  Char                   Unicode character to test.
+
+  @retval TRUE                   If the character is a hexadecimal digit.
+  @retval FALSE                  Otherwise.
+
+**/
+BOOLEAN
+R8_IsHexDigit (
+  OUT UINT8      *Digit,
+  IN  CHAR16      Char
+  )
+;
+
diff --git a/MdeModulePkg/Library/IfrSupportLib/UefiIfrCommon.c b/MdeModulePkg/Library/IfrSupportLib/UefiIfrCommon.c
new file mode 100644 (file)
index 0000000..b2b92d1
--- /dev/null
@@ -0,0 +1,369 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+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.
+
+Module Name:
+
+  UefiIfrCommon.c
+
+Abstract:
+
+  Common Library Routines to assist handle HII elements.
+
+
+**/
+
+#include "UefiIfrLibraryInternal.h"
+
+//
+// Hii relative protocols
+//
+BOOLEAN  mHiiProtocolsInitialized = FALSE;
+
+EFI_HII_DATABASE_PROTOCOL *gIfrLibHiiDatabase;
+EFI_HII_STRING_PROTOCOL   *gIfrLibHiiString;
+
+
+/**
+  This function locate Hii relative protocols for later usage.
+
+  None.
+
+  @return None.
+
+**/
+VOID
+LocateHiiProtocols (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  if (mHiiProtocolsInitialized) {
+    return;
+  }
+
+  Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gIfrLibHiiDatabase);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &gIfrLibHiiString);
+  ASSERT_EFI_ERROR (Status);
+
+  mHiiProtocolsInitialized = TRUE;
+}
+
+
+/**
+  Assemble EFI_HII_PACKAGE_LIST according to the passed in packages.
+
+  @param  NumberOfPackages       Number of packages.
+  @param  GuidId                 Package GUID.
+
+  @return Pointer of EFI_HII_PACKAGE_LIST_HEADER.
+
+**/
+EFI_HII_PACKAGE_LIST_HEADER *
+PreparePackageList (
+  IN UINTN                    NumberOfPackages,
+  IN EFI_GUID                 *GuidId,
+  ...
+  )
+{
+  VA_LIST                     Marker;
+  EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
+  UINT8                       *PackageListData;
+  UINT32                      PackageListLength;
+  UINT32                      PackageLength;
+  EFI_HII_PACKAGE_HEADER      PackageHeader;
+  UINT8                       *PackageArray;
+  UINTN                       Index;
+
+  PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+
+  VA_START (Marker, GuidId);
+  for (Index = 0; Index < NumberOfPackages; Index++) {
+    CopyMem (&PackageLength, VA_ARG (Marker, VOID *), sizeof (UINT32));
+    PackageListLength += (PackageLength - sizeof (UINT32));
+  }
+  VA_END (Marker);
+
+  //
+  // Include the lenght of EFI_HII_PACKAGE_END
+  //
+  PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);
+  PackageListHeader = AllocateZeroPool (PackageListLength);
+  ASSERT (PackageListHeader != NULL);
+  CopyMem (&PackageListHeader->PackageListGuid, GuidId, sizeof (EFI_GUID));
+  PackageListHeader->PackageLength = PackageListLength;
+
+  PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+
+  VA_START (Marker, GuidId);
+  for (Index = 0; Index < NumberOfPackages; Index++) {
+    PackageArray = (UINT8 *) VA_ARG (Marker, VOID *);
+    CopyMem (&PackageLength, PackageArray, sizeof (UINT32));
+    PackageLength  -= sizeof (UINT32);
+    PackageArray += sizeof (UINT32);
+    CopyMem (PackageListData, PackageArray, PackageLength);
+    PackageListData += PackageLength;
+  }
+  VA_END (Marker);
+
+  //
+  // Append EFI_HII_PACKAGE_END
+  //
+  PackageHeader.Type = EFI_HII_PACKAGE_END;
+  PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);
+  CopyMem (PackageListData, &PackageHeader, PackageHeader.Length);
+
+  return PackageListHeader;
+}
+
+
+/**
+  Find HII Handle associated with given Device Path.
+
+  @param  HiiDatabase            Point to EFI_HII_DATABASE_PROTOCOL instance.
+  @param  DevicePath             Device Path associated with the HII package list
+                                 handle.
+
+  @retval Handle                 HII package list Handle associated with the Device
+                                 Path.
+  @retval NULL                   Hii Package list handle is not found.
+
+**/
+EFI_HII_HANDLE
+DevicePathToHiiHandle (
+  IN EFI_HII_DATABASE_PROTOCOL  *HiiDatabase,
+  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_DEVICE_PATH_PROTOCOL    *TmpDevicePath;
+  UINTN                       BufferSize;
+  UINTN                       HandleCount;
+  UINTN                       Index;
+  EFI_HANDLE                  *Handles;
+  EFI_HANDLE                  Handle;
+  UINTN                       Size;
+  EFI_HANDLE                  DriverHandle;
+  EFI_HII_HANDLE              *HiiHandles;
+  EFI_HII_HANDLE              HiiHandle;
+
+  //
+  // Locate Device Path Protocol handle buffer
+  //
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiDevicePathProtocolGuid,
+                  NULL,
+                  &HandleCount,
+                  &Handles
+                  );
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  //
+  // Search Driver Handle by Device Path
+  //
+  DriverHandle = NULL;
+  BufferSize = GetDevicePathSize (DevicePath);
+  for(Index = 0; Index < HandleCount; Index++) {
+    Handle = Handles[Index];
+    gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **) &TmpDevicePath);
+
+    //
+    // Check whether DevicePath match
+    //
+    Size = GetDevicePathSize (TmpDevicePath);
+    if ((Size == BufferSize) && CompareMem (DevicePath, TmpDevicePath, Size) == 0) {
+      DriverHandle = Handle;
+      break;
+    }
+  }
+  gBS->FreePool (Handles);
+
+  if (DriverHandle == NULL) {
+    return NULL;
+  }
+
+  //
+  // Retrieve all Hii Handles from HII database
+  //
+  BufferSize = 0x1000;
+  HiiHandles = AllocatePool (BufferSize);
+  ASSERT (HiiHandles != NULL);
+  Status = HiiDatabase->ListPackageLists (
+                          HiiDatabase,
+                          EFI_HII_PACKAGE_TYPE_ALL,
+                          NULL,
+                          &BufferSize,
+                          HiiHandles
+                          );
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    gBS->FreePool (HiiHandles);
+    HiiHandles = AllocatePool (BufferSize);
+    ASSERT (HiiHandles != NULL);
+
+    Status = HiiDatabase->ListPackageLists (
+                            HiiDatabase,
+                            EFI_HII_PACKAGE_TYPE_ALL,
+                            NULL,
+                            &BufferSize,
+                            HiiHandles
+                            );
+  }
+
+  if (EFI_ERROR (Status)) {
+    gBS->FreePool (HiiHandles);
+    return NULL;
+  }
+
+  //
+  // Search Hii Handle by Driver Handle
+  //
+  HiiHandle = NULL;
+  HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);
+  for (Index = 0; Index < HandleCount; Index++) {
+    Status = HiiDatabase->GetPackageListHandle (
+                            HiiDatabase,
+                            HiiHandles[Index],
+                            &Handle
+                            );
+    if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {
+      HiiHandle = HiiHandles[Index];
+      break;
+    }
+  }
+
+  gBS->FreePool (HiiHandles);
+  return HiiHandle;
+}
+
+
+/**
+  Determines the handles that are currently active in the database.
+  It's the caller's responsibility to free handle buffer.
+
+  @param  HiiDatabase            A pointer to the EFI_HII_DATABASE_PROTOCOL
+                                 instance.
+  @param  HandleBufferLength     On input, a pointer to the length of the handle
+                                 buffer. On output, the length of the handle buffer
+                                 that is required for the handles found.
+  @param  HiiHandleBuffer        Pointer to an array of Hii Handles returned.
+
+  @retval EFI_SUCCESS            Get an array of Hii Handles successfully.
+  @retval EFI_INVALID_PARAMETER  Hii is NULL.
+  @retval EFI_NOT_FOUND          Database not found.
+
+**/
+EFI_STATUS
+GetHiiHandles (
+  IN OUT UINTN                     *HandleBufferLength,
+  OUT    EFI_HII_HANDLE            **HiiHandleBuffer
+  )
+{
+  UINTN       BufferLength;
+  EFI_STATUS  Status;
+
+  BufferLength = 0;
+
+  LocateHiiProtocols ();
+
+  //
+  // Try to find the actual buffer size for HiiHandle Buffer.
+  //
+  Status = gIfrLibHiiDatabase->ListPackageLists (
+                                 gIfrLibHiiDatabase,
+                                 EFI_HII_PACKAGE_TYPE_ALL,
+                                 NULL,
+                                 &BufferLength,
+                                 *HiiHandleBuffer
+                                 );
+
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+      *HiiHandleBuffer = AllocateZeroPool (BufferLength);
+      Status = gIfrLibHiiDatabase->ListPackageLists (
+                                     gIfrLibHiiDatabase,
+                                     EFI_HII_PACKAGE_TYPE_ALL,
+                                     NULL,
+                                     &BufferLength,
+                                     *HiiHandleBuffer
+                                     );
+      //
+      // we should not fail here.
+      //
+      ASSERT_EFI_ERROR (Status);
+  }
+
+  *HandleBufferLength = BufferLength;
+
+  return Status;
+}
+
+
+/**
+  Extract Hii package list GUID for given HII handle.
+
+  @param  HiiHandle              Hii handle
+  @param  Guid                   Package list GUID
+
+  @retval EFI_SUCCESS            Successfully extract GUID from Hii database.
+
+**/
+EFI_STATUS
+ExtractGuidFromHiiHandle (
+  IN      EFI_HII_HANDLE      Handle,
+  OUT     EFI_GUID            *Guid
+  )
+{
+  EFI_STATUS                   Status;
+  UINTN                        BufferSize;
+  EFI_HII_DATABASE_PROTOCOL    *HiiDatabase;
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
+
+  //
+  // Locate HII Database protocol
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiHiiDatabaseProtocolGuid,
+                  NULL,
+                  (VOID **) &HiiDatabase
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Get HII PackageList
+  //
+  BufferSize = 0;
+  HiiPackageList = NULL;
+  Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    HiiPackageList = AllocatePool (BufferSize);
+    ASSERT (HiiPackageList != NULL);
+
+    Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
+  }
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Extract GUID
+  //
+  CopyMem (Guid, &HiiPackageList->PackageListGuid, sizeof (EFI_GUID));
+
+  gBS->FreePool (HiiPackageList);
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/IfrSupportLib/UefiIfrForm.c b/MdeModulePkg/Library/IfrSupportLib/UefiIfrForm.c
new file mode 100644 (file)
index 0000000..362978a
--- /dev/null
@@ -0,0 +1,1121 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+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.
+
+Module Name:
+
+  UefiIfrForm.c
+
+Abstract:
+
+  Common Library Routines to assist handle HII elements.
+
+
+**/
+
+#include "UefiIfrLibraryInternal.h"
+
+//
+// Fake <ConfigHdr>
+//
+UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";
+
+STATIC
+EFI_STATUS
+GetPackageDataFromPackageList (
+  IN  EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,
+  IN  UINT32                      PackageIndex,
+  OUT UINT32                      *BufferLen,
+  OUT EFI_HII_PACKAGE_HEADER      **Buffer
+  )
+{
+  UINT32                        Index;
+  EFI_HII_PACKAGE_HEADER        *Package;
+  UINT32                        Offset;
+  UINT32                        PackageListLength;
+  EFI_HII_PACKAGE_HEADER        PackageHeader = {0, 0};
+
+  ASSERT(HiiPackageList != NULL);
+
+  if ((BufferLen == NULL) || (Buffer == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Package = NULL;
+  Index   = 0;
+  Offset  = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+  CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
+  while (Offset < PackageListLength) {
+    Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
+    CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+    if (Index == PackageIndex) {
+      break;
+    }
+    Offset += PackageHeader.Length;
+    Index++;
+  }
+  if (Offset >= PackageListLength) {
+    //
+    // no package found in this Package List
+    //
+    return EFI_NOT_FOUND;
+  }
+
+  *BufferLen = PackageHeader.Length;
+  *Buffer    = Package;
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+UpdateFormPackageData (
+  IN  EFI_GUID               *FormSetGuid,
+  IN  EFI_FORM_ID            FormId,
+  IN  EFI_HII_PACKAGE_HEADER *Package,
+  IN  UINT32                 PackageLength,
+  IN  UINT16                 Label,
+  IN  BOOLEAN                Insert,
+  IN  EFI_HII_UPDATE_DATA    *Data,
+  OUT UINT8                  **TempBuffer,
+  OUT UINT32                 *TempBufferSize
+  )
+{
+  UINTN                     AddSize;
+  UINT8                     *BufferPos;
+  EFI_HII_PACKAGE_HEADER    PackageHeader;
+  UINTN                     Offset;
+  EFI_IFR_OP_HEADER         *IfrOpHdr;
+  BOOLEAN                   GetFormSet;
+  BOOLEAN                   GetForm;
+  UINT8                     ExtendOpCode;
+  UINT16                    LabelNumber;
+  BOOLEAN                   Updated;
+  EFI_IFR_OP_HEADER         *AddOpCode;
+
+  if ((TempBuffer == NULL) || (TempBufferSize == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *TempBufferSize = PackageLength;
+  if (Data != NULL) {
+    *TempBufferSize += Data->Offset;
+  }
+  *TempBuffer = AllocateZeroPool (*TempBufferSize);
+  if (*TempBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  CopyMem (*TempBuffer, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+  *TempBufferSize = sizeof (EFI_HII_PACKAGE_HEADER);
+  BufferPos = *TempBuffer + sizeof (EFI_HII_PACKAGE_HEADER);
+
+  CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+  IfrOpHdr   = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));
+  Offset     = sizeof (EFI_HII_PACKAGE_HEADER);
+  GetFormSet = (BOOLEAN) ((FormSetGuid == NULL) ? TRUE : FALSE);
+  GetForm    = FALSE;
+  Updated    = FALSE;
+
+  while (Offset < PackageHeader.Length) {
+    CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
+    BufferPos += IfrOpHdr->Length;
+    *TempBufferSize += IfrOpHdr->Length;
+
+    switch (IfrOpHdr->OpCode) {
+    case EFI_IFR_FORM_SET_OP :
+      if (FormSetGuid != NULL) {
+        if (CompareMem (&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid, sizeof (EFI_GUID)) == 0) {
+          GetFormSet = TRUE;
+        }
+      }
+      break;
+
+    case EFI_IFR_FORM_OP:
+      if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {
+        GetForm = TRUE;
+      }
+      break;
+
+    case EFI_IFR_GUID_OP :
+      if (!GetFormSet || !GetForm || Updated) {
+        //
+        // Go to the next Op-Code
+        //
+        Offset   += IfrOpHdr->Length;
+        IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
+        continue;
+      }
+
+      ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;
+      CopyMem (&LabelNumber, &((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Number, sizeof (UINT16));
+      if ((ExtendOpCode != EFI_IFR_EXTEND_OP_LABEL) || (LabelNumber != Label)) {
+        //
+        // Go to the next Op-Code
+        //
+        Offset   += IfrOpHdr->Length;
+        IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
+        continue;
+      }
+
+      if (Insert && (Data != NULL)) {
+        //
+        // insert the DataCount amount of opcodes to TempBuffer if Data is NULL remove
+        // DataCount amount of opcodes unless runing into a label.
+        //
+        AddOpCode = (EFI_IFR_OP_HEADER *)Data->Data;
+        AddSize   = 0;
+        while (AddSize < Data->Offset) {
+          CopyMem (BufferPos, AddOpCode, AddOpCode->Length);
+          BufferPos += AddOpCode->Length;
+          *TempBufferSize += AddOpCode->Length;
+
+          AddSize += AddOpCode->Length;
+          AddOpCode = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (AddOpCode) + AddOpCode->Length);
+        }
+      } else {
+        //
+        // Search the next Label.
+        //
+        while (TRUE) {
+          Offset   += IfrOpHdr->Length;
+          //
+          // Search the next label and Fail if not label found.
+          //
+          if (Offset >= PackageHeader.Length) {
+            goto Fail;
+          }
+          IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
+          if (IfrOpHdr->OpCode == EFI_IFR_GUID_OP) {
+            ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;
+            if (ExtendOpCode == EFI_IFR_EXTEND_OP_LABEL) {
+              break;
+            }
+          }
+        }
+
+        if (Data != NULL) {
+          AddOpCode = (EFI_IFR_OP_HEADER *)Data->Data;
+          AddSize   = 0;
+          while (AddSize < Data->Offset) {
+            CopyMem (BufferPos, AddOpCode, AddOpCode->Length);
+            BufferPos += AddOpCode->Length;
+            *TempBufferSize += AddOpCode->Length;
+
+            AddSize   += AddOpCode->Length;
+            AddOpCode = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (AddOpCode) + AddOpCode->Length);
+          }
+        }
+
+        //
+        // copy the next label
+        //
+        CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
+        BufferPos += IfrOpHdr->Length;
+        *TempBufferSize += IfrOpHdr->Length;
+      }
+
+      Updated = TRUE;
+      break;
+    default :
+      break;
+    }
+
+    //
+    // Go to the next Op-Code
+    //
+    Offset   += IfrOpHdr->Length;
+    IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
+  }
+
+  //
+  // Update the package length.
+  //
+  PackageHeader.Length = *TempBufferSize;
+  CopyMem (*TempBuffer, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
+
+Fail:
+  if (!Updated) {
+    gBS->FreePool (*TempBuffer);
+    *TempBufferSize = 0;
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  This function allows the caller to update a form that has
+  previously been registered with the EFI HII database.
+
+  @param  Handle                 Hii Handle
+  @param  FormSetGuid            The formset should be updated.
+  @param  FormId                 The form should be updated.
+  @param  Label                  Update information starting immediately after this
+                                 label in the IFR
+  @param  Insert                 If TRUE and Data is not NULL, insert data after
+                                 Label. If FALSE, replace opcodes between two
+                                 labels with Data
+  @param  Data                   The adding data; If NULL, remove opcodes between
+                                 two Label.
+
+  @retval EFI_SUCCESS            Update success.
+  @retval Other                  Update fail.
+
+**/
+EFI_STATUS
+IfrLibUpdateForm (
+  IN EFI_HII_HANDLE            Handle,
+  IN EFI_GUID                  *FormSetGuid, OPTIONAL
+  IN EFI_FORM_ID               FormId,
+  IN UINT16                    Label,
+  IN BOOLEAN                   Insert,
+  IN EFI_HII_UPDATE_DATA       *Data
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_HII_DATABASE_PROTOCOL    *HiiDatabase;
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
+  UINT32                       Index;
+  EFI_HII_PACKAGE_LIST_HEADER  *UpdateBuffer;
+  UINTN                        BufferSize;
+  UINT8                        *UpdateBufferPos;
+  EFI_HII_PACKAGE_HEADER       PackageHeader;
+  EFI_HII_PACKAGE_HEADER       *Package;
+  UINT32                       PackageLength;
+  EFI_HII_PACKAGE_HEADER       *TempBuffer;
+  UINT32                       TempBufferSize;
+  BOOLEAN                      Updated;
+
+  if (Data == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  LocateHiiProtocols ();
+  HiiDatabase = gIfrLibHiiDatabase;
+
+  //
+  // Get the orginal package list
+  //
+  BufferSize = 0;
+  HiiPackageList   = NULL;
+  Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    HiiPackageList = AllocatePool (BufferSize);
+    ASSERT (HiiPackageList != NULL);
+
+    Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
+    if (EFI_ERROR (Status)) {
+      gBS->FreePool (HiiPackageList);
+      return Status;
+    }
+  }
+
+  //
+  // Calculate and allocate space for retrieval of IFR data
+  //
+  BufferSize += Data->Offset;
+  UpdateBuffer = AllocateZeroPool (BufferSize);
+  if (UpdateBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  UpdateBufferPos = (UINT8 *) UpdateBuffer;
+
+  //
+  // copy the package list header
+  //
+  CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));
+  UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+
+  Updated = FALSE;
+  for (Index = 0; ; Index++) {
+    Status = GetPackageDataFromPackageList (HiiPackageList, Index, &PackageLength, &Package);
+    if (Status == EFI_SUCCESS) {
+      CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+      if ((PackageHeader.Type == EFI_HII_PACKAGE_FORM) && !Updated) {
+        Status = UpdateFormPackageData (FormSetGuid, FormId, Package, PackageLength, Label, Insert, Data, (UINT8 **)&TempBuffer, &TempBufferSize);
+        if (!EFI_ERROR(Status)) {
+          if (FormSetGuid == NULL) {
+            Updated = TRUE;
+          }
+          CopyMem (UpdateBufferPos, TempBuffer, TempBufferSize);
+          UpdateBufferPos += TempBufferSize;
+          gBS->FreePool (TempBuffer);
+          continue;
+        }
+      }
+
+      CopyMem (UpdateBufferPos, Package, PackageLength);
+      UpdateBufferPos += PackageLength;
+    } else if (Status == EFI_NOT_FOUND) {
+      break;
+    } else {
+      gBS->FreePool (HiiPackageList);
+      return Status;
+    }
+  }
+
+  //
+  // Update package list length
+  //
+  BufferSize = UpdateBufferPos - (UINT8 *) UpdateBuffer;
+  CopyMem (&UpdateBuffer->PackageLength, &BufferSize, sizeof (UINT32));
+
+  gBS->FreePool (HiiPackageList);
+
+  return HiiDatabase->UpdatePackageList (HiiDatabase, Handle, UpdateBuffer);
+}
+
+
+/**
+  Draw a dialog and return the selected key.
+
+  @param  NumberOfLines          The number of lines for the dialog box
+  @param  KeyValue               The EFI_KEY value returned if HotKey is TRUE..
+  @param  String                 Pointer to the first string in the list
+  @param  ...                    A series of (quantity == NumberOfLines) text
+                                 strings which will be used to construct the dialog
+                                 box
+
+  @retval EFI_SUCCESS            Displayed dialog and received user interaction
+  @retval EFI_INVALID_PARAMETER  One of the parameters was invalid.
+
+**/
+EFI_STATUS
+IfrLibCreatePopUp (
+  IN  UINTN                       NumberOfLines,
+  OUT EFI_INPUT_KEY               *KeyValue,
+  IN  CHAR16                      *String,
+  ...
+  )
+{
+  UINTN                         Index;
+  UINTN                         Count;
+  UINTN                         Start;
+  UINTN                         Top;
+  CHAR16                        *StringPtr;
+  UINTN                         LeftColumn;
+  UINTN                         RightColumn;
+  UINTN                         TopRow;
+  UINTN                         BottomRow;
+  UINTN                         DimensionsWidth;
+  UINTN                         DimensionsHeight;
+  VA_LIST                       Marker;
+  EFI_INPUT_KEY                 Key;
+  UINTN                         LargestString;
+  CHAR16                        *StackString;
+  EFI_STATUS                    Status;
+  UINTN                         StringLen;
+  CHAR16                        *LineBuffer;
+  CHAR16                        **StringArray;
+  EFI_EVENT                     TimerEvent;
+  EFI_EVENT                     WaitList[2];
+  UINTN                         CurrentAttribute;
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *ConOut;
+
+  if ((KeyValue == NULL) || (String == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TopRow      = 0;
+  BottomRow   = 0;
+  LeftColumn  = 0;
+  RightColumn = 0;
+
+  ConOut = gST->ConOut;
+  ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &RightColumn, &BottomRow);
+
+  DimensionsWidth  = RightColumn - LeftColumn;
+  DimensionsHeight = BottomRow - TopRow;
+
+  CurrentAttribute = ConOut->Mode->Attribute;
+
+  LineBuffer = AllocateZeroPool (DimensionsWidth * sizeof (CHAR16));
+  ASSERT (LineBuffer != NULL);
+
+  //
+  // Determine the largest string in the dialog box
+  // Notice we are starting with 1 since String is the first string
+  //
+  StringArray = AllocateZeroPool (NumberOfLines * sizeof (CHAR16 *));
+  LargestString = StrLen (String);
+  StringArray[0] = String;
+
+  VA_START (Marker, String);
+  for (Index = 1; Index < NumberOfLines; Index++) {
+    StackString = VA_ARG (Marker, CHAR16 *);
+
+    if (StackString == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    StringArray[Index] = StackString;
+    StringLen = StrLen (StackString);
+    if (StringLen > LargestString) {
+      LargestString = StringLen;
+    }
+  }
+
+  if ((LargestString + 2) > DimensionsWidth) {
+    LargestString = DimensionsWidth - 2;
+  }
+
+  //
+  // Subtract the PopUp width from total Columns, allow for one space extra on
+  // each end plus a border.
+  //
+  Start     = (DimensionsWidth - LargestString - 2) / 2 + LeftColumn + 1;
+
+  Top       = ((DimensionsHeight - NumberOfLines - 2) / 2) + TopRow - 1;
+
+  //
+  // Disable cursor
+  //
+  ConOut->EnableCursor (ConOut, FALSE);
+  ConOut->SetAttribute (ConOut, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
+
+  StringPtr = &LineBuffer[0];
+  *StringPtr++ = BOXDRAW_DOWN_RIGHT;
+  for (Index = 0; Index < LargestString; Index++) {
+    *StringPtr++ = BOXDRAW_HORIZONTAL;
+  }
+  *StringPtr++ = BOXDRAW_DOWN_LEFT;
+  *StringPtr = L'\0';
+
+  ConOut->SetCursorPosition (ConOut, Start, Top);
+  ConOut->OutputString (ConOut, LineBuffer);
+
+  for (Index = 0; Index < NumberOfLines; Index++) {
+    StringPtr = &LineBuffer[0];
+    *StringPtr++ = BOXDRAW_VERTICAL;
+
+    for (Count = 0; Count < LargestString; Count++) {
+      StringPtr[Count] = L' ';
+    }
+
+    StringLen = StrLen (StringArray[Index]);
+    if (StringLen > LargestString) {
+      StringLen = LargestString;
+    }
+    CopyMem (
+      StringPtr + ((LargestString - StringLen) / 2),
+      StringArray[Index],
+      StringLen * sizeof (CHAR16)
+      );
+    StringPtr += LargestString;
+
+    *StringPtr++ = BOXDRAW_VERTICAL;
+    *StringPtr = L'\0';
+
+    ConOut->SetCursorPosition (ConOut, Start, Top + 1 + Index);
+    ConOut->OutputString (ConOut, LineBuffer);
+  }
+
+  StringPtr = &LineBuffer[0];
+  *StringPtr++ = BOXDRAW_UP_RIGHT;
+  for (Index = 0; Index < LargestString; Index++) {
+    *StringPtr++ = BOXDRAW_HORIZONTAL;
+  }
+  *StringPtr++ = BOXDRAW_UP_LEFT;
+  *StringPtr = L'\0';
+
+  ConOut->SetCursorPosition (ConOut, Start, Top + NumberOfLines + 1);
+  ConOut->OutputString (ConOut, LineBuffer);
+
+  do {
+    Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
+
+    //
+    // Set a timer event of 1 second expiration
+    //
+    gBS->SetTimer (
+          TimerEvent,
+          TimerRelative,
+          10000000
+          );
+
+    //
+    // Wait for the keystroke event or the timer
+    //
+    WaitList[0] = gST->ConIn->WaitForKey;
+    WaitList[1] = TimerEvent;
+    Status      = gBS->WaitForEvent (2, WaitList, &Index);
+
+    //
+    // Check for the timer expiration
+    //
+    if (!EFI_ERROR (Status) && Index == 1) {
+      Status = EFI_TIMEOUT;
+    }
+
+    gBS->CloseEvent (TimerEvent);
+  } while (Status == EFI_TIMEOUT);
+
+  Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+  CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));
+
+  ConOut->SetAttribute (ConOut, CurrentAttribute);
+  ConOut->EnableCursor (ConOut, TRUE);
+
+  return Status;
+}
+
+
+/**
+  Configure the buffer accrording to ConfigBody strings.
+
+  @param  DefaultId              the ID of default.
+  @param  Buffer                 the start address of buffer.
+  @param  BufferSize             the size of buffer.
+  @param  Number                 the number of the strings.
+
+  @retval EFI_BUFFER_TOO_SMALL   the BufferSize is too small to operate.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL or BufferSize is 0.
+  @retval EFI_SUCCESS            Operation successful.
+
+**/
+EFI_STATUS
+ExtractDefault(
+  IN VOID                         *Buffer,
+  IN UINTN                        *BufferSize,
+  UINTN                           Number,
+  ...
+  )
+{
+  VA_LIST                         Args;
+  UINTN                           Index;
+  UINT32                          TotalLen;
+  UINT8                           *BufCfgArray;
+  UINT8                           *BufferPos;
+  UINT16                          Offset;
+  UINT16                          Width;
+  UINT8                           *Value;
+
+  if ((Buffer == NULL) || (BufferSize == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Offset = 0;
+  Width  = 0;
+  Value  = NULL;
+
+  VA_START (Args, Number);
+  for (Index = 0; Index < Number; Index++) {
+    BufCfgArray = (UINT8 *) VA_ARG (Args, VOID *);
+    CopyMem (&TotalLen, BufCfgArray, sizeof (UINT32));
+    BufferPos = BufCfgArray + sizeof (UINT32);
+
+    while ((UINT32)(BufferPos - BufCfgArray) < TotalLen) {
+      CopyMem (&Offset, BufferPos, sizeof (UINT16));
+      BufferPos += sizeof (UINT16);
+      CopyMem (&Width, BufferPos, sizeof (UINT16));
+      BufferPos += sizeof (UINT16);
+      Value = BufferPos;
+      BufferPos += Width;
+
+      if ((UINTN)(Offset + Width) > *BufferSize) {
+        return EFI_BUFFER_TOO_SMALL;
+      }
+
+      CopyMem ((UINT8 *)Buffer + Offset, Value, Width);
+    }
+  }
+  VA_END (Args);
+
+  *BufferSize = (UINTN)Offset;
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Swap bytes in the buffer.
+
+  @param  Buffer                 Binary buffer.
+  @param  BufferSize             Size of the buffer in bytes.
+
+  @return None.
+
+**/
+STATIC
+VOID
+SwapBuffer (
+  IN OUT UINT8     *Buffer,
+  IN UINTN         BufferSize
+  )
+{
+  UINTN  Index;
+  UINT8  Temp;
+  UINTN  SwapCount;
+
+  SwapCount = (BufferSize - 1) / 2;
+  for (Index = 0; Index < SwapCount; Index++) {
+    Temp = Buffer[Index];
+    Buffer[Index] = Buffer[BufferSize - 1 - Index];
+    Buffer[BufferSize - 1 - Index] = Temp;
+  }
+}
+
+
+/**
+  Converts binary buffer to Unicode string in reversed byte order from R8_BufToHexString().
+
+  @param  Str                    String for output
+  @param  Buffer                 Binary buffer.
+  @param  BufferSize             Size of the buffer in bytes.
+
+  @retval EFI_SUCCESS            The function completed successfully.
+
+**/
+EFI_STATUS
+BufferToHexString (
+  IN OUT CHAR16    *Str,
+  IN UINT8         *Buffer,
+  IN UINTN         BufferSize
+  )
+{
+  EFI_STATUS  Status;
+  UINT8       *NewBuffer;
+  UINTN       StrBufferLen;
+
+  NewBuffer = AllocateCopyPool (BufferSize, Buffer);
+  SwapBuffer (NewBuffer, BufferSize);
+
+  StrBufferLen = (BufferSize + 1) * sizeof (CHAR16);
+  Status = R8_BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize);
+
+  gBS->FreePool (NewBuffer);
+
+  return Status;
+}
+
+
+/**
+  Converts Hex String to binary buffer in reversed byte order from R8_HexStringToBuf().
+
+  @param  Buffer                 Pointer to buffer that receives the data.
+  @param  BufferSize             Length in bytes of the buffer to hold converted
+                                 data. If routine return with EFI_SUCCESS,
+                                 containing length of converted data. If routine
+                                 return with EFI_BUFFER_TOO_SMALL, containg length
+                                 of buffer desired.
+  @param  Str                    String to be converted from.
+
+  @retval EFI_SUCCESS            The function completed successfully.
+
+**/
+EFI_STATUS
+HexStringToBuffer (
+  IN OUT UINT8         *Buffer,
+  IN OUT UINTN         *BufferSize,
+  IN CHAR16            *Str
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       ConvertedStrLen;
+
+  ConvertedStrLen = 0;
+  Status = R8_HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);
+  if (!EFI_ERROR (Status)) {
+    SwapBuffer (Buffer, ConvertedStrLen);
+  }
+
+  return Status;
+}
+
+
+/**
+  Construct <ConfigHdr> using routing information GUID/NAME/PATH.
+
+  @param  ConfigHdr              Pointer to the ConfigHdr string.
+  @param  StrBufferLen           On input: Length in bytes of buffer to hold the
+                                 ConfigHdr string. Includes tailing '\0' character.
+                                 On output: If return EFI_SUCCESS, containing
+                                 length of ConfigHdr string buffer. If return
+                                 EFI_BUFFER_TOO_SMALL, containg length of string
+                                 buffer desired.
+  @param  Guid                   Routing information: GUID.
+  @param  Name                   Routing information: NAME.
+  @param  DriverHandle           Driver handle which contains the routing
+                                 information: PATH.
+
+  @retval EFI_SUCCESS            Routine success.
+  @retval EFI_BUFFER_TOO_SMALL   The ConfigHdr string buffer is too small.
+
+**/
+EFI_STATUS
+ConstructConfigHdr (
+  IN OUT CHAR16                *ConfigHdr,
+  IN OUT UINTN                 *StrBufferLen,
+  IN EFI_GUID                  *Guid,
+  IN CHAR16                    *Name, OPTIONAL
+  IN EFI_HANDLE                *DriverHandle
+  )
+{
+  EFI_STATUS                Status;
+  UINTN                     NameStrLen;
+  UINTN                     DevicePathSize;
+  UINTN                     BufferSize;
+  CHAR16                    *StrPtr;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+
+  if (Name == NULL) {
+    //
+    // There will be no "NAME" in <ConfigHdr> for  Name/Value storage
+    //
+    NameStrLen = 0;
+  } else {
+    //
+    // For buffer storage
+    //
+    NameStrLen = StrLen (Name);
+  }
+
+  //
+  // Retrieve DevicePath Protocol associated with this HiiPackageList
+  //
+  Status = gBS->HandleProtocol (
+                  DriverHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &DevicePath
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  DevicePathSize = GetDevicePathSize (DevicePath);
+
+  //
+  // GUID=<HexCh>32&NAME=<Alpha>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
+  // | 5  |   32   |  6  |   NameStrLen   |  6  |    DevicePathStrLen   |
+  //
+  BufferSize = (5 + 32 + 6 + NameStrLen + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);
+  if (*StrBufferLen < BufferSize) {
+    *StrBufferLen = BufferSize;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  *StrBufferLen = BufferSize;
+
+  StrPtr = ConfigHdr;
+
+  StrCpy (StrPtr, L"GUID=");
+  StrPtr += 5;
+  BufferToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));
+  StrPtr += 32;
+
+  StrCpy (StrPtr, L"&NAME=");
+  StrPtr += 6;
+  if (Name != NULL) {
+    StrCpy (StrPtr, Name);
+    StrPtr += NameStrLen;
+  }
+
+  StrCpy (StrPtr, L"&PATH=");
+  StrPtr += 6;
+  BufferToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
+
+  @param  String                 The string to be searched in.
+  @param  Offset                 Offset in BlockName.
+  @param  Width                  Width in BlockName.
+
+  @retval TRUE                   Block name found.
+  @retval FALSE                  Block name not found.
+
+**/
+BOOLEAN
+FindBlockName (
+  IN OUT CHAR16                *String,
+  UINTN                        Offset,
+  UINTN                        Width
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       Data;
+  UINTN       BufferSize;
+  UINTN       ConvertedStrLen;
+
+  while ((String = StrStr (String, L"&OFFSET=")) != NULL) {
+    //
+    // Skip '&OFFSET='
+    //
+    String = String + 8;
+
+    Data = 0;
+    BufferSize = sizeof (UINTN);
+    Status = R8_HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
+    if (EFI_ERROR (Status)) {
+      return FALSE;
+    }
+    String = String + ConvertedStrLen;
+
+    if (Data != Offset) {
+      continue;
+    }
+
+    if (StrnCmp (String, L"&WIDTH=", 7) != 0) {
+      return FALSE;
+    }
+    String = String + 7;
+
+    Data = 0;
+    BufferSize = sizeof (UINTN);
+    Status = R8_HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
+    if (EFI_ERROR (Status)) {
+      return FALSE;
+    }
+    if (Data == Width) {
+      return TRUE;
+    }
+
+    String = String + ConvertedStrLen;
+  }
+
+  return FALSE;
+}
+
+
+/**
+  This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
+
+  @param  VariableGuid           An optional field to indicate the target variable
+                                 GUID name to use.
+  @param  VariableName           An optional field to indicate the target
+                                 human-readable variable name.
+  @param  BufferSize             On input: Length in bytes of buffer to hold
+                                 retrived data. On output: If return
+                                 EFI_BUFFER_TOO_SMALL, containg length of buffer
+                                 desired.
+  @param  Buffer                 Buffer to hold retrived data.
+
+  @retval EFI_SUCCESS            Routine success.
+  @retval EFI_BUFFER_TOO_SMALL   The intput buffer is too small.
+
+**/
+EFI_STATUS
+GetBrowserData (
+  EFI_GUID                   *VariableGuid, OPTIONAL
+  CHAR16                     *VariableName, OPTIONAL
+  UINTN                      *BufferSize,
+  UINT8                      *Buffer
+  )
+{
+  EFI_STATUS                      Status;
+  CHAR16                          *ConfigHdr;
+  CHAR16                          *ConfigResp;
+  CHAR16                          *StringPtr;
+  UINTN                           HeaderLen;
+  UINTN                           BufferLen;
+  CHAR16                          *Progress;
+  EFI_FORM_BROWSER2_PROTOCOL      *FormBrowser2;
+  EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+  //
+  // Locate protocols for use
+  //
+  Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Retrive formset storage data from Form Browser
+  //
+  ConfigHdr = mFakeConfigHdr;
+  HeaderLen = StrLen (ConfigHdr);
+
+  BufferLen = 0x4000;
+  ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
+
+  StringPtr = ConfigResp + HeaderLen;
+  *StringPtr = L'&';
+  StringPtr++;
+
+  Status = FormBrowser2->BrowserCallback (
+                           FormBrowser2,
+                           &BufferLen,
+                           StringPtr,
+                           TRUE,
+                           VariableGuid,
+                           VariableName
+                           );
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    gBS->FreePool (ConfigResp);
+    ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
+
+    StringPtr = ConfigResp + HeaderLen;
+    *StringPtr = L'&';
+    StringPtr++;
+
+    Status = FormBrowser2->BrowserCallback (
+                             FormBrowser2,
+                             &BufferLen,
+                             StringPtr,
+                             TRUE,
+                             VariableGuid,
+                             VariableName
+                             );
+  }
+  if (EFI_ERROR (Status)) {
+    gBS->FreePool (ConfigResp);
+    return Status;
+  }
+  CopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16));
+
+  //
+  // Convert <ConfigResp> to buffer data
+  //
+  Status = HiiConfigRouting->ConfigToBlock (
+                               HiiConfigRouting,
+                               ConfigResp,
+                               Buffer,
+                               BufferSize,
+                               &Progress
+                               );
+  gBS->FreePool (ConfigResp);
+
+  return Status;
+}
+
+
+/**
+  This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
+
+  @param  VariableGuid           An optional field to indicate the target variable
+                                 GUID name to use.
+  @param  VariableName           An optional field to indicate the target
+                                 human-readable variable name.
+  @param  BufferSize             Length in bytes of buffer to hold retrived data.
+  @param  Buffer                 Buffer to hold retrived data.
+  @param  RequestElement         An optional field to specify which part of the
+                                 buffer data will be send back to Browser. If NULL,
+                                 the whole buffer of data will be committed to
+                                 Browser. <RequestElement> ::=
+                                 &OFFSET=<Number>&WIDTH=<Number>*
+
+  @retval EFI_SUCCESS            Routine success.
+  @retval Other                  Updating Browser uncommitted data failed.
+
+**/
+EFI_STATUS
+SetBrowserData (
+  EFI_GUID                   *VariableGuid, OPTIONAL
+  CHAR16                     *VariableName, OPTIONAL
+  UINTN                      BufferSize,
+  UINT8                      *Buffer,
+  CHAR16                     *RequestElement  OPTIONAL
+  )
+{
+  EFI_STATUS                      Status;
+  CHAR16                          *ConfigHdr;
+  CHAR16                          *ConfigResp;
+  CHAR16                          *StringPtr;
+  UINTN                           HeaderLen;
+  UINTN                           BufferLen;
+  CHAR16                          *Progress;
+  EFI_FORM_BROWSER2_PROTOCOL      *FormBrowser2;
+  EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+  CHAR16                          BlockName[33];
+  CHAR16                          *ConfigRequest;
+  CHAR16                          *Request;
+
+  //
+  // Locate protocols for use
+  //
+  Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Prepare <ConfigRequest>
+  //
+  ConfigHdr = mFakeConfigHdr;
+  HeaderLen = StrLen (ConfigHdr);
+
+  if (RequestElement == NULL) {
+    //
+    // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
+    //
+    BlockName[0] = L'\0';
+    StrCpy (BlockName, L"&OFFSET=0&WIDTH=");
+
+    //
+    // String lenghth of L"&OFFSET=0&WIDTH=" is 16
+    //
+    StringPtr = BlockName + 16;
+    BufferLen = sizeof (BlockName) - (16 * sizeof (CHAR16));
+    R8_BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN));
+
+    Request = BlockName;
+  } else {
+    Request = RequestElement;
+  }
+
+  BufferLen = HeaderLen * sizeof (CHAR16) + StrSize (Request);
+  ConfigRequest = AllocateZeroPool (BufferLen);
+
+  CopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16));
+  StringPtr = ConfigRequest + HeaderLen;
+  StrCpy (StringPtr, Request);
+
+  //
+  // Convert buffer to <ConfigResp>
+  //
+  Status = HiiConfigRouting->BlockToConfig (
+                                HiiConfigRouting,
+                                ConfigRequest,
+                                Buffer,
+                                BufferSize,
+                                &ConfigResp,
+                                &Progress
+                                );
+  if (EFI_ERROR (Status)) {
+    gBS->FreePool (ConfigResp);
+    return Status;
+  }
+
+  //
+  // Skip <ConfigHdr> and '&'
+  //
+  StringPtr = ConfigResp + HeaderLen + 1;
+
+  //
+  // Change uncommitted data in Browser
+  //
+  Status = FormBrowser2->BrowserCallback (
+                           FormBrowser2,
+                           &BufferSize,
+                           StringPtr,
+                           FALSE,
+                           NULL,
+                           NULL
+                           );
+  gBS->FreePool (ConfigResp);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/IfrSupportLib/UefiIfrLibraryInternal.h b/MdeModulePkg/Library/IfrSupportLib/UefiIfrLibraryInternal.h
new file mode 100644 (file)
index 0000000..1b5a79f
--- /dev/null
@@ -0,0 +1,64 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+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.
+
+Module Name:
+
+  UefiIfrLibraryInternal
+
+Abstract:
+
+  The file contain all library function for Ifr Operations.
+
+
+**/
+
+#ifndef _IFRLIBRARY_INTERNAL_H
+#define _IFRLIBRARY_INTERNAL_H
+
+
+#include <PiDxe.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Protocol/DevicePath.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/IfrSupportLib.h>
+#include <Library/PcdLib.h>
+
+#include <MdeModuleHii.h>
+
+#include "R8Lib.h"
+
+VOID
+LocateHiiProtocols (
+  VOID
+  )
+/*++
+
+Routine Description:
+  This function locate Hii relative protocols for later usage.
+
+Arguments:
+  None.
+
+Returns:
+  None.
+
+--*/
+;
+
+#endif
diff --git a/MdeModulePkg/Library/IfrSupportLib/UefiIfrOpCodeCreation.c b/MdeModulePkg/Library/IfrSupportLib/UefiIfrOpCodeCreation.c
new file mode 100644 (file)
index 0000000..240f020
--- /dev/null
@@ -0,0 +1,639 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+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.
+
+Module Name:
+
+  UefiIfrOpCodeCreation.c
+
+Abstract:
+
+  Library Routines to create IFR independent of string data - assume tokens already exist
+  Primarily to be used for exporting op-codes at a label in pre-defined forms.
+
+Revision History:
+
+
+**/
+
+#include "UefiIfrLibraryInternal.h"
+
+STATIC EFI_GUID mIfrVendorGuid = EFI_IFR_TIANO_GUID;
+
+STATIC
+BOOLEAN
+IsValidQuestionFlags (
+  IN UINT8                   Flags
+  )
+{
+  return (BOOLEAN) ((Flags & (~QUESTION_FLAGS)) ? FALSE : TRUE);
+}
+
+STATIC
+BOOLEAN
+IsValidValueType (
+  IN UINT8                   Type
+  )
+{
+  return (BOOLEAN) ((Type <= EFI_IFR_TYPE_OTHER) ? TRUE : FALSE);
+}
+
+STATIC
+BOOLEAN
+IsValidNumricFlags (
+  IN UINT8                   Flags
+  )
+{
+  if (Flags & ~(EFI_IFR_NUMERIC_SIZE | EFI_IFR_DISPLAY)) {
+    return FALSE;
+  }
+
+  if ((Flags & EFI_IFR_DISPLAY) > EFI_IFR_DISPLAY_UINT_HEX) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+STATIC
+BOOLEAN
+IsValidCheckboxFlags (
+  IN UINT8                   Flags
+  )
+{
+  return (BOOLEAN) ((Flags <= EFI_IFR_CHECKBOX_DEFAULT_MFG) ? TRUE : FALSE);
+}
+
+EFI_STATUS
+CreateEndOpCode (
+  IN OUT EFI_HII_UPDATE_DATA *Data
+  )
+{
+  EFI_IFR_END                 End;
+  UINT8                       *LocalBuffer;
+
+  ASSERT (Data != NULL && Data->Data != NULL);
+
+  if (Data->Offset + sizeof (EFI_IFR_END) > Data->BufferSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  End.Header.Length  = sizeof (EFI_IFR_END);
+  End.Header.OpCode  = EFI_IFR_END_OP;
+  End.Header.Scope   = 0;
+
+  LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
+  CopyMem (LocalBuffer, &End, sizeof (EFI_IFR_END));
+  Data->Offset += sizeof (EFI_IFR_END);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateDefaultOpCode (
+  IN     EFI_IFR_TYPE_VALUE  *Value,
+  IN     UINT8               Type,
+  IN OUT EFI_HII_UPDATE_DATA *Data
+  )
+{
+  EFI_IFR_DEFAULT            Default;
+  UINT8                      *LocalBuffer;
+
+  ASSERT (Data != NULL && Data->Data != NULL);
+
+  if ((Value == NULL) || !IsValidValueType (Type)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Data->Offset + sizeof (EFI_IFR_DEFAULT) > Data->BufferSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  Default.Header.OpCode = EFI_IFR_DEFAULT_OP;
+  Default.Header.Length = sizeof (EFI_IFR_DEFAULT);
+  Default.Header.Scope  = 0;
+  Default.Type          = Type;
+  Default.DefaultId     = EFI_HII_DEFAULT_CLASS_STANDARD;
+  CopyMem (&Default.Value, Value, sizeof(EFI_IFR_TYPE_VALUE));
+
+  LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
+  CopyMem (LocalBuffer, &Default, sizeof (EFI_IFR_DEFAULT));
+  Data->Offset += sizeof (EFI_IFR_DEFAULT);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateActionOpCode (
+  IN     EFI_QUESTION_ID      QuestionId,
+  IN     EFI_STRING_ID        Prompt,
+  IN     EFI_STRING_ID        Help,
+  IN     UINT8                QuestionFlags,
+  IN     EFI_STRING_ID        QuestionConfig,
+  IN OUT EFI_HII_UPDATE_DATA  *Data
+  )
+{
+  EFI_IFR_ACTION              Action;
+  UINT8                       *LocalBuffer;
+
+  ASSERT (Data != NULL && Data->Data != NULL);
+
+  if (!IsValidQuestionFlags (QuestionFlags)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Data->Offset + sizeof (EFI_IFR_ACTION) > Data->BufferSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  Action.Header.OpCode          = EFI_IFR_ACTION_OP;
+  Action.Header.Length          = sizeof (EFI_IFR_ACTION);
+  Action.Header.Scope           = 0;
+  Action.Question.QuestionId    = QuestionId;
+  Action.Question.Header.Prompt = Prompt;
+  Action.Question.Header.Help   = Help;
+  Action.Question.VarStoreId    = INVALID_VARSTORE_ID;
+  Action.Question.Flags         = QuestionFlags;
+  Action.QuestionConfig         = QuestionConfig;
+
+  LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
+  CopyMem (LocalBuffer, &Action, sizeof (EFI_IFR_ACTION));
+  Data->Offset += sizeof (EFI_IFR_ACTION);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateSubTitleOpCode (
+  IN      EFI_STRING_ID       Prompt,
+  IN      EFI_STRING_ID       Help,
+  IN      UINT8               Flags,
+  IN      UINT8               Scope,
+  IN OUT EFI_HII_UPDATE_DATA  *Data
+  )
+{
+  EFI_IFR_SUBTITLE            Subtitle;
+  UINT8                       *LocalBuffer;
+
+  ASSERT (Data != NULL && Data->Data != NULL);
+
+  if (Data->Offset + sizeof (EFI_IFR_SUBTITLE) > Data->BufferSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  Subtitle.Header.OpCode    = EFI_IFR_SUBTITLE_OP;
+  Subtitle.Header.Length    = sizeof (EFI_IFR_SUBTITLE);
+  Subtitle.Header.Scope     = Scope;
+  Subtitle.Statement.Prompt = Prompt;
+  Subtitle.Statement.Help   = Help;
+  Subtitle.Flags            = Flags;
+
+  LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
+  CopyMem (LocalBuffer, &Subtitle, sizeof (EFI_IFR_SUBTITLE));
+  Data->Offset += sizeof (EFI_IFR_SUBTITLE);
+
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateTextOpCode (
+  IN     EFI_STRING_ID        Prompt,
+  IN     EFI_STRING_ID        Help,
+  IN     EFI_STRING_ID        TextTwo,
+  IN OUT EFI_HII_UPDATE_DATA  *Data
+  )
+{
+  EFI_IFR_TEXT                Text;
+  UINT8                       *LocalBuffer;
+
+  ASSERT (Data != NULL && Data->Data != NULL);
+
+  if (Data->Offset + sizeof (EFI_IFR_TEXT) > Data->BufferSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  Text.Header.OpCode    = EFI_IFR_TEXT_OP;
+  Text.Header.Length    = sizeof (EFI_IFR_TEXT);
+  Text.Header.Scope     = 0;
+  Text.Statement.Prompt = Prompt;
+  Text.Statement.Help   = Help;
+  Text.TextTwo          = TextTwo;
+
+  LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
+  CopyMem (LocalBuffer, &Text, sizeof (EFI_IFR_TEXT));
+  Data->Offset += sizeof (EFI_IFR_TEXT);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateGotoOpCode (
+  IN     EFI_FORM_ID          FormId,
+  IN     EFI_STRING_ID        Prompt,
+  IN     EFI_STRING_ID        Help,
+  IN     UINT8                QuestionFlags,
+  IN     EFI_QUESTION_ID      QuestionId,
+  IN OUT EFI_HII_UPDATE_DATA  *Data
+  )
+{
+  EFI_IFR_REF                 Goto;
+  UINT8                       *LocalBuffer;
+
+  ASSERT (Data != NULL && Data->Data != NULL);
+
+  if (!IsValidQuestionFlags (QuestionFlags)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Data->Offset + sizeof (EFI_IFR_REF) > Data->BufferSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  Goto.Header.OpCode          = EFI_IFR_REF_OP;
+  Goto.Header.Length          = sizeof (EFI_IFR_REF);
+  Goto.Header.Scope           = 0;
+  Goto.Question.Header.Prompt = Prompt;
+  Goto.Question.Header.Help   = Help;
+  Goto.Question.VarStoreId    = INVALID_VARSTORE_ID;
+  Goto.Question.QuestionId    = QuestionId;
+  Goto.Question.Flags         = QuestionFlags;
+  Goto.FormId                 = FormId;
+
+  LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
+  CopyMem (LocalBuffer, &Goto, sizeof (EFI_IFR_REF));
+  Data->Offset += sizeof (EFI_IFR_REF);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateOneOfOptionOpCode (
+  IN     UINTN                OptionCount,
+  IN     IFR_OPTION           *OptionsList,
+  IN     UINT8                Type,
+  IN OUT EFI_HII_UPDATE_DATA  *Data
+  )
+{
+  UINTN                       Index;
+  UINT8                       *LocalBuffer;
+  EFI_IFR_ONE_OF_OPTION       OneOfOption;
+
+  ASSERT (Data != NULL && Data->Data != NULL);
+
+  if ((OptionCount != 0) && (OptionsList == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Data->Offset + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) > Data->BufferSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  for (Index = 0; Index < OptionCount; Index++) {
+    OneOfOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;
+    OneOfOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION);
+    OneOfOption.Header.Scope  = 0;
+
+    OneOfOption.Option        = OptionsList[Index].StringToken;
+    OneOfOption.Value         = OptionsList[Index].Value;
+    OneOfOption.Flags         = (UINT8) (OptionsList[Index].Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));
+    OneOfOption.Type          = Type;
+
+    LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
+    CopyMem (LocalBuffer, &OneOfOption, sizeof (EFI_IFR_ONE_OF_OPTION));
+    Data->Offset += sizeof (EFI_IFR_ONE_OF_OPTION);
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateOneOfOpCode (
+  IN     EFI_QUESTION_ID      QuestionId,
+  IN     EFI_VARSTORE_ID      VarStoreId,
+  IN     UINT16               VarOffset,
+  IN     EFI_STRING_ID        Prompt,
+  IN     EFI_STRING_ID        Help,
+  IN     UINT8                QuestionFlags,
+  IN     UINT8                OneOfFlags,
+  IN     IFR_OPTION           *OptionsList,
+  IN     UINTN                OptionCount,
+  IN OUT EFI_HII_UPDATE_DATA  *Data
+  )
+{
+  UINTN                       Length;
+  EFI_IFR_ONE_OF              OneOf;
+  UINT8                       *LocalBuffer;
+
+  ASSERT (Data != NULL && Data->Data != NULL);
+
+  if (!IsValidNumricFlags (OneOfFlags) ||
+      !IsValidQuestionFlags (QuestionFlags) ||
+      ((OptionCount != 0) && (OptionsList == NULL))) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Length = sizeof (EFI_IFR_ONE_OF) + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) + sizeof (EFI_IFR_END);
+  if (Data->Offset + Length > Data->BufferSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  OneOf.Header.OpCode                   = EFI_IFR_ONE_OF_OP;
+  OneOf.Header.Length                   = sizeof (EFI_IFR_ONE_OF);
+  OneOf.Header.Scope                    = 1;
+  OneOf.Question.Header.Prompt          = Prompt;
+  OneOf.Question.Header.Help            = Help;
+  OneOf.Question.QuestionId             = QuestionId;
+  OneOf.Question.VarStoreId             = VarStoreId;
+  OneOf.Question.VarStoreInfo.VarOffset = VarOffset;
+  OneOf.Question.Flags                  = QuestionFlags;
+  OneOf.Flags                           = OneOfFlags;
+  ZeroMem ((VOID *) &OneOf.data, sizeof (MINMAXSTEP_DATA));
+
+  LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
+  CopyMem (LocalBuffer, &OneOf, sizeof (EFI_IFR_ONE_OF));
+  Data->Offset += sizeof (EFI_IFR_ONE_OF);
+
+  CreateOneOfOptionOpCode (OptionCount, OptionsList, (UINT8) (OneOfFlags & EFI_IFR_NUMERIC_SIZE), Data);
+
+  CreateEndOpCode (Data);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateOrderedListOpCode (
+  IN      EFI_QUESTION_ID     QuestionId,
+  IN      EFI_VARSTORE_ID     VarStoreId,
+  IN      UINT16              VarOffset,
+  IN      EFI_STRING_ID       Prompt,
+  IN      EFI_STRING_ID       Help,
+  IN      UINT8               QuestionFlags,
+  IN      UINT8               OrderedListFlags,
+  IN      UINT8               DataType,
+  IN      UINT8               MaxContainers,
+  IN      IFR_OPTION          *OptionsList,
+  IN     UINTN                OptionCount,
+  IN OUT EFI_HII_UPDATE_DATA  *Data
+  )
+{
+  UINTN                       Length;
+  EFI_IFR_ORDERED_LIST        OrderedList;
+  UINT8                       *LocalBuffer;
+
+  ASSERT (Data != NULL && Data->Data != NULL);
+
+  if (!IsValidQuestionFlags (QuestionFlags) ||
+      ((OptionCount != 0) && (OptionsList == NULL))) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((OrderedListFlags != 0) &&
+      (OrderedListFlags != EFI_IFR_UNIQUE_SET) &&
+      (OrderedListFlags != EFI_IFR_NO_EMPTY_SET)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Length = sizeof (EFI_IFR_ORDERED_LIST) + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) + sizeof (EFI_IFR_END);
+  if (Data->Offset + Length > Data->BufferSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  OrderedList.Header.OpCode                   = EFI_IFR_ORDERED_LIST_OP;
+  OrderedList.Header.Length                   = sizeof (EFI_IFR_ORDERED_LIST);
+  OrderedList.Header.Scope                    = 1;
+  OrderedList.Question.Header.Prompt          = Prompt;
+  OrderedList.Question.Header.Help            = Help;
+  OrderedList.Question.QuestionId             = QuestionId;
+  OrderedList.Question.VarStoreId             = VarStoreId;
+  OrderedList.Question.VarStoreInfo.VarOffset = VarOffset;
+  OrderedList.Question.Flags                  = QuestionFlags;
+  OrderedList.MaxContainers                   = MaxContainers;
+  OrderedList.Flags                           = OrderedListFlags;
+
+  LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
+  CopyMem (LocalBuffer, &OrderedList, sizeof (EFI_IFR_ORDERED_LIST));
+  Data->Offset += sizeof (EFI_IFR_ORDERED_LIST);
+
+  CreateOneOfOptionOpCode (OptionCount, OptionsList, DataType, Data);
+
+  CreateEndOpCode (Data);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateCheckBoxOpCode (
+  IN      EFI_QUESTION_ID     QuestionId,
+  IN      EFI_VARSTORE_ID     VarStoreId,
+  IN      UINT16              VarOffset,
+  IN      EFI_STRING_ID       Prompt,
+  IN      EFI_STRING_ID       Help,
+  IN      UINT8               QuestionFlags,
+  IN      UINT8               CheckBoxFlags,
+  IN OUT EFI_HII_UPDATE_DATA  *Data
+  )
+{
+  EFI_IFR_CHECKBOX            CheckBox;
+  UINT8                       *LocalBuffer;
+
+  ASSERT (Data != NULL && Data->Data != NULL);
+
+  if (!IsValidQuestionFlags (QuestionFlags) || !IsValidCheckboxFlags (CheckBoxFlags)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Data->Offset + sizeof (EFI_IFR_CHECKBOX) > Data->BufferSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  CheckBox.Header.OpCode                   = EFI_IFR_CHECKBOX_OP;
+  CheckBox.Header.Length                   = sizeof (EFI_IFR_CHECKBOX);
+  CheckBox.Header.Scope                    = 0;
+  CheckBox.Question.QuestionId             = QuestionId;
+  CheckBox.Question.VarStoreId             = VarStoreId;
+  CheckBox.Question.VarStoreInfo.VarOffset = VarOffset;
+  CheckBox.Question.Header.Prompt          = Prompt;
+  CheckBox.Question.Header.Help            = Help;
+  CheckBox.Question.Flags                  = QuestionFlags;
+  CheckBox.Flags                           = CheckBoxFlags;
+
+  LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
+  CopyMem (LocalBuffer, &CheckBox, sizeof (EFI_IFR_CHECKBOX));
+  Data->Offset += sizeof (EFI_IFR_CHECKBOX);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateNumericOpCode (
+  IN     EFI_QUESTION_ID     QuestionId,
+  IN     EFI_VARSTORE_ID     VarStoreId,
+  IN     UINT16              VarOffset,
+  IN     EFI_STRING_ID       Prompt,
+  IN     EFI_STRING_ID       Help,
+  IN     UINT8               QuestionFlags,
+  IN     UINT8               NumericFlags,
+  IN     UINT64              Minimum,
+  IN     UINT64              Maximum,
+  IN     UINT64              Step,
+  IN     UINT64              Default,
+  IN OUT EFI_HII_UPDATE_DATA *Data
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_IFR_NUMERIC             Numeric;
+  MINMAXSTEP_DATA             MinMaxStep;
+  EFI_IFR_TYPE_VALUE          DefaultValue;
+  UINT8                       *LocalBuffer;
+
+  ASSERT (Data != NULL && Data->Data != NULL);
+
+  if (!IsValidQuestionFlags (QuestionFlags) || !IsValidNumricFlags (NumericFlags)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Data->Offset + sizeof (EFI_IFR_CHECKBOX) > Data->BufferSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  Numeric.Header.OpCode                   = EFI_IFR_NUMERIC_OP;
+  Numeric.Header.Length                   = sizeof (EFI_IFR_NUMERIC);
+  Numeric.Header.Scope                    = 1;
+  Numeric.Question.QuestionId             = QuestionId;
+  Numeric.Question.VarStoreId             = VarStoreId;
+  Numeric.Question.VarStoreInfo.VarOffset = VarOffset;
+  Numeric.Question.Header.Prompt          = Prompt;
+  Numeric.Question.Header.Help            = Help;
+  Numeric.Question.Flags                  = QuestionFlags;
+  Numeric.Flags                           = NumericFlags;
+
+  switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {
+  case EFI_IFR_NUMERIC_SIZE_1:
+    MinMaxStep.u8.MinValue = (UINT8) Minimum;
+    MinMaxStep.u8.MaxValue = (UINT8) Maximum;
+    MinMaxStep.u8.Step     = (UINT8) Step;
+    break;
+
+  case EFI_IFR_NUMERIC_SIZE_2:
+    MinMaxStep.u16.MinValue = (UINT16) Minimum;
+    MinMaxStep.u16.MaxValue = (UINT16) Maximum;
+    MinMaxStep.u16.Step     = (UINT16) Step;
+    break;
+
+  case EFI_IFR_NUMERIC_SIZE_4:
+    MinMaxStep.u32.MinValue = (UINT32) Minimum;
+    MinMaxStep.u32.MaxValue = (UINT32) Maximum;
+    MinMaxStep.u32.Step     = (UINT32) Step;
+    break;
+
+  case EFI_IFR_NUMERIC_SIZE_8:
+    MinMaxStep.u64.MinValue = Minimum;
+    MinMaxStep.u64.MaxValue = Maximum;
+    MinMaxStep.u64.Step     = Step;
+    break;
+  }
+
+  CopyMem (&Numeric.data, &MinMaxStep, sizeof (MINMAXSTEP_DATA));
+
+  LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
+  CopyMem (LocalBuffer, &Numeric, sizeof (EFI_IFR_NUMERIC));
+  Data->Offset += sizeof (EFI_IFR_NUMERIC);
+
+  DefaultValue.u64 = Default;
+  Status = CreateDefaultOpCode (&DefaultValue, (UINT8) (NumericFlags & EFI_IFR_NUMERIC_SIZE), Data);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  CreateEndOpCode (Data);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateStringOpCode (
+  IN      EFI_QUESTION_ID     QuestionId,
+  IN      EFI_VARSTORE_ID     VarStoreId,
+  IN      UINT16              VarOffset,
+  IN      EFI_STRING_ID       Prompt,
+  IN      EFI_STRING_ID       Help,
+  IN      UINT8               QuestionFlags,
+  IN      UINT8               StringFlags,
+  IN      UINT8               MinSize,
+  IN      UINT8               MaxSize,
+  IN OUT EFI_HII_UPDATE_DATA  *Data
+  )
+{
+  EFI_IFR_STRING              String;
+  UINT8                       *LocalBuffer;
+
+  ASSERT (Data != NULL && Data->Data != NULL);
+
+  if (!IsValidQuestionFlags (QuestionFlags) || (StringFlags & (~EFI_IFR_STRING_MULTI_LINE))) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Data->Offset + sizeof (EFI_IFR_STRING) > Data->BufferSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  String.Header.OpCode                   = EFI_IFR_STRING_OP;
+  String.Header.Length                   = sizeof (EFI_IFR_STRING);
+  String.Header.Scope                    = 0;
+  String.Question.Header.Prompt          = Prompt;
+  String.Question.Header.Help            = Help;
+  String.Question.QuestionId             = QuestionId;
+  String.Question.VarStoreId             = VarStoreId;
+  String.Question.VarStoreInfo.VarOffset = VarOffset;
+  String.Question.Flags                  = QuestionFlags;
+  String.MinSize                         = MinSize;
+  String.MaxSize                         = MaxSize;
+  String.Flags                           = StringFlags;
+
+  LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
+  CopyMem (LocalBuffer, &String, sizeof (EFI_IFR_STRING));
+  Data->Offset += sizeof (EFI_IFR_STRING);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateBannerOpCode (
+  IN      EFI_STRING_ID       Title,
+  IN      UINT16              LineNumber,
+  IN      UINT8               Alignment,
+  IN OUT EFI_HII_UPDATE_DATA  *Data
+  )
+{
+  EFI_IFR_GUID_BANNER         Banner;
+  UINT8                       *LocalBuffer;
+
+  ASSERT (Data != NULL && Data->Data != NULL);
+
+  if (Data->Offset + sizeof (EFI_IFR_GUID_BANNER) > Data->BufferSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  Banner.Header.OpCode  = EFI_IFR_GUID_OP;
+  Banner.Header.Length  = sizeof (EFI_IFR_GUID_BANNER);
+  Banner.Header.Scope   = 0;
+  CopyMem (&Banner.Guid, &mIfrVendorGuid, sizeof (EFI_IFR_GUID));
+  Banner.ExtendOpCode   = EFI_IFR_EXTEND_OP_BANNER;
+  Banner.Title          = Title;
+  Banner.LineNumber     = LineNumber;
+  Banner.Alignment      = Alignment;
+
+  LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
+  CopyMem (LocalBuffer, &Banner, sizeof (EFI_IFR_GUID_BANNER));
+  Data->Offset += sizeof (EFI_IFR_GUID_BANNER);
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/IfrSupportLib/UefiIfrString.c b/MdeModulePkg/Library/IfrSupportLib/UefiIfrString.c
new file mode 100644 (file)
index 0000000..2536940
--- /dev/null
@@ -0,0 +1,681 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+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.
+
+Module Name:
+
+  UefiIfrString.c
+
+Abstract:
+
+  Common Library Routines to assist to handle String and Language.
+
+
+**/
+
+#include "UefiIfrLibraryInternal.h"
+
+//
+// Lookup table of ISO639-2 3 character language codes to ISO 639-1 2 character language codes
+// Each entry is 5 CHAR8 values long.  The first 3 CHAR8 values are the ISO 639-2 code.
+// The last 2 CHAR8 values are the ISO 639-1 code.
+//
+CHAR8 Iso639ToRfc3066ConversionTable[] =
+"\
+aaraa\
+abkab\
+afraf\
+amham\
+araar\
+asmas\
+aymay\
+azeaz\
+bakba\
+belbe\
+benbn\
+bihbh\
+bisbi\
+bodbo\
+brebr\
+bulbg\
+catca\
+cescs\
+corkw\
+cosco\
+cymcy\
+danda\
+deude\
+dzodz\
+ellel\
+engen\
+epoeo\
+estet\
+euseu\
+faofo\
+fasfa\
+fijfj\
+finfi\
+frafr\
+fryfy\
+gaiga\
+gdhgd\
+glggl\
+grngn\
+gujgu\
+hauha\
+hebhe\
+hinhi\
+hrvhr\
+hunhu\
+hyehy\
+ikuiu\
+ileie\
+inaia\
+indid\
+ipkik\
+islis\
+itait\
+jawjw\
+jpnja\
+kalkl\
+kankn\
+kasks\
+katka\
+kazkk\
+khmkm\
+kinrw\
+kirky\
+korko\
+kurku\
+laolo\
+latla\
+lavlv\
+linln\
+litlt\
+ltzlb\
+malml\
+marmr\
+mkdmk\
+mlgmg\
+mltmt\
+molmo\
+monmn\
+mrimi\
+msams\
+myamy\
+nauna\
+nepne\
+nldnl\
+norno\
+ocioc\
+ormom\
+panpa\
+polpl\
+porpt\
+pusps\
+quequ\
+rohrm\
+ronro\
+runrn\
+rusru\
+sagsg\
+sansa\
+sinsi\
+slksk\
+slvsl\
+smise\
+smosm\
+snasn\
+sndsd\
+somso\
+sotst\
+spaes\
+sqisq\
+srpsr\
+sswss\
+sunsu\
+swasw\
+swesv\
+tamta\
+tattt\
+telte\
+tgktg\
+tgltl\
+thath\
+tsnts\
+tuktk\
+twitw\
+uigug\
+ukruk\
+urdur\
+uzbuz\
+vievi\
+volvo\
+wolwo\
+xhoxh\
+yidyi\
+zhaza\
+zhozh\
+zulzu\
+";
+
+
+/**
+  Convert language code from RFC3066 to ISO639-2.
+
+  @param  LanguageRfc3066        RFC3066 language code.
+  @param  LanguageIso639         ISO639-2 language code.
+
+  @retval EFI_SUCCESS            Language code converted.
+  @retval EFI_NOT_FOUND          Language code not found.
+
+**/
+EFI_STATUS
+ConvertRfc3066LanguageToIso639Language (
+  CHAR8   *LanguageRfc3066,
+  CHAR8   *LanguageIso639
+  )
+{
+  UINTN  Index;
+
+  if ((LanguageRfc3066[2] != '-') && (LanguageRfc3066[2] != 0)) {
+    CopyMem (LanguageIso639, LanguageRfc3066, 3);
+    return EFI_SUCCESS;
+  }
+
+  for (Index = 0; Iso639ToRfc3066ConversionTable[Index] != 0; Index += 5) {
+    if (CompareMem (LanguageRfc3066, &Iso639ToRfc3066ConversionTable[Index + 3], 2) == 0) {
+      CopyMem (LanguageIso639, &Iso639ToRfc3066ConversionTable[Index], 3);
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+
+/**
+  Convert language code list from RFC3066 to ISO639-2, e.g. "en-US;fr-FR" will
+  be converted to "engfra".
+
+  @param  SupportedLanguages     The RFC3066 language list.
+
+  @return The ISO639-2 language list.
+
+**/
+CHAR8 *
+Rfc3066ToIso639 (
+  CHAR8  *SupportedLanguages
+  )
+{
+  CHAR8       *Languages;
+  CHAR8       *ReturnValue;
+  CHAR8       *LangCodes;
+  CHAR8       LangRfc3066[RFC_3066_ENTRY_SIZE];
+  CHAR8       LangIso639[ISO_639_2_ENTRY_SIZE];
+  EFI_STATUS  Status;
+
+  ReturnValue = AllocateZeroPool (AsciiStrSize (SupportedLanguages));
+  if (ReturnValue == NULL) {
+    return ReturnValue;
+  }
+
+  Languages = ReturnValue;
+  LangCodes = SupportedLanguages;
+  while (*LangCodes != 0) {
+    GetNextLanguage (&LangCodes, LangRfc3066);
+
+    Status = ConvertRfc3066LanguageToIso639Language (LangRfc3066, LangIso639);
+    if (!EFI_ERROR (Status)) {
+      CopyMem (Languages, LangIso639, 3);
+      Languages = Languages + 3;
+    }
+  }
+
+  return ReturnValue;
+}
+
+
+/**
+  Determine what is the current language setting
+
+  @param  Lang                   Pointer of system language
+
+  @return Status code
+
+**/
+EFI_STATUS
+GetCurrentLanguage (
+  OUT     CHAR8               *Lang
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       Size;
+
+  //
+  // Get current language setting
+  //
+  Size = RFC_3066_ENTRY_SIZE;
+  Status = gRT->GetVariable (
+                  L"PlatformLang",
+                  &gEfiGlobalVariableGuid,
+                  NULL,
+                  &Size,
+                  Lang
+                  );
+
+  if (EFI_ERROR (Status)) {
+    AsciiStrCpy (Lang, (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang));
+  }
+
+  return Status;
+}
+
+
+/**
+  Get next language from language code list (with separator ';').
+
+  @param  LangCode               On input: point to first language in the list. On
+                                 output: point to next language in the list, or
+                                 NULL if no more language in the list.
+  @param  Lang                   The first language in the list.
+
+  @return None.
+
+**/
+VOID
+GetNextLanguage (
+  IN OUT CHAR8      **LangCode,
+  OUT CHAR8         *Lang
+  )
+{
+  UINTN  Index;
+  CHAR8  *StringPtr;
+
+  if (LangCode == NULL || *LangCode == NULL) {
+    *Lang = 0;
+    return;
+  }
+
+  Index = 0;
+  StringPtr = *LangCode;
+  while (StringPtr[Index] != 0 && StringPtr[Index] != ';') {
+    Index++;
+  }
+
+  CopyMem (Lang, StringPtr, Index);
+  Lang[Index] = 0;
+
+  if (StringPtr[Index] == ';') {
+    Index++;
+  }
+  *LangCode = StringPtr + Index;
+}
+
+
+/**
+  This function returns the list of supported languages, in the format specified
+  in UEFI specification Appendix M.
+
+  @param  HiiHandle              The HII package list handle.
+
+  @return The supported languages.
+
+**/
+CHAR8 *
+GetSupportedLanguages (
+  IN EFI_HII_HANDLE           HiiHandle
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       BufferSize;
+  CHAR8       *LanguageString;
+
+  LocateHiiProtocols ();
+
+  //
+  // Collect current supported Languages for given HII handle
+  //
+  BufferSize = 0x1000;
+  LanguageString = AllocatePool (BufferSize);
+  Status = gIfrLibHiiString->GetLanguages (gIfrLibHiiString, HiiHandle, LanguageString, &BufferSize);
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    gBS->FreePool (LanguageString);
+    LanguageString = AllocatePool (BufferSize);
+    Status = gIfrLibHiiString->GetLanguages (gIfrLibHiiString, HiiHandle, LanguageString, &BufferSize);
+  }
+
+  if (EFI_ERROR (Status)) {
+    LanguageString = NULL;
+  }
+
+  return LanguageString;
+}
+
+
+/**
+  This function returns the number of supported languages
+
+  @param  HiiHandle              The HII package list handle.
+
+  @return The  number of supported languages.
+
+**/
+UINT16
+GetSupportedLanguageNumber (
+  IN EFI_HII_HANDLE           HiiHandle
+  )
+{
+  CHAR8   *Languages;
+  CHAR8   *LanguageString;
+  UINT16  LangNumber;
+  CHAR8   Lang[RFC_3066_ENTRY_SIZE];
+
+  Languages = GetSupportedLanguages (HiiHandle);
+  if (Languages == NULL) {
+    return 0;
+  }
+
+  LangNumber = 0;
+  LanguageString = Languages;
+  while (*LanguageString != 0) {
+    GetNextLanguage (&LanguageString, Lang);
+    LangNumber++;
+  }
+  gBS->FreePool (Languages);
+
+  return LangNumber;
+}
+
+
+/**
+  Get string specified by StringId form the HiiHandle.
+
+  @param  HiiHandle              The HII handle of package list.
+  @param  StringId               The String ID.
+  @param  String                 The output string.
+
+  @retval EFI_NOT_FOUND          String is not found.
+  @retval EFI_SUCCESS            Operation is successful.
+  @retval EFI_OUT_OF_RESOURCES   There is not enought memory in the system.
+  @retval EFI_INVALID_PARAMETER  The String is NULL.
+
+**/
+EFI_STATUS
+GetStringFromHandle (
+  IN  EFI_HII_HANDLE                  HiiHandle,
+  IN  EFI_STRING_ID                   StringId,
+  OUT EFI_STRING                      *String
+  )
+{
+  EFI_STATUS                          Status;
+  UINTN                               StringSize;
+
+  if (String == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  StringSize = IFR_LIB_DEFAULT_STRING_SIZE;
+  *String    = AllocateZeroPool (StringSize);
+  if (*String == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = IfrLibGetString (HiiHandle, StringId, *String, &StringSize);
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    gBS->FreePool (*String);
+    *String = AllocateZeroPool (StringSize);
+    if (*String == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    Status = IfrLibGetString (HiiHandle, StringId, *String, &StringSize);
+  }
+
+  return Status;
+}
+
+
+/**
+  Get the string given the StringId and String package Producer's Guid.
+
+  @param  ProducerGuid           The Guid of String package list.
+  @param  StringId               The String ID.
+  @param  String                 The output string.
+
+  @retval EFI_NOT_FOUND          String is not found.
+  @retval EFI_SUCCESS            Operation is successful.
+  @retval EFI_OUT_OF_RESOURCES   There is not enought memory in the system.
+
+**/
+EFI_STATUS
+GetStringFromToken (
+  IN  EFI_GUID                        *ProducerGuid,
+  IN  EFI_STRING_ID                   StringId,
+  OUT EFI_STRING                      *String
+  )
+{
+  EFI_STATUS      Status;
+  UINTN           Index;
+  UINTN           HandleBufferLen;
+  EFI_HII_HANDLE  *HiiHandleBuffer;
+  EFI_GUID        Guid;
+
+  Status = GetHiiHandles (&HandleBufferLen, &HiiHandleBuffer);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+  for (Index = 0; Index < (HandleBufferLen / sizeof (EFI_HII_HANDLE)); Index++) {
+    Status = ExtractGuidFromHiiHandle (HiiHandleBuffer[Index], &Guid);
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+    if (CompareGuid (&Guid, ProducerGuid) == TRUE) {
+      break;
+    }
+  }
+
+  if (Index >= (HandleBufferLen / sizeof (EFI_HII_HANDLE))) {
+    Status = EFI_NOT_FOUND;
+    goto Out;
+  }
+
+  Status = GetStringFromHandle (HiiHandleBuffer[Index], StringId, String);
+
+Out:
+  if (HiiHandleBuffer != NULL) {
+    gBS->FreePool (HiiHandleBuffer);
+  }
+  return Status;
+}
+
+
+/**
+  This function adds the string into String Package of each language.
+
+  @param  PackageList            Handle of the package list where this string will
+                                 be added.
+  @param  StringId               On return, contains the new strings id, which is
+                                 unique within PackageList.
+  @param  String                 Points to the new null-terminated string.
+
+  @retval EFI_SUCCESS            The new string was added successfully.
+  @retval EFI_NOT_FOUND          The specified PackageList could not be found in
+                                 database.
+  @retval EFI_OUT_OF_RESOURCES   Could not add the string due to lack of resources.
+  @retval EFI_INVALID_PARAMETER  String is NULL or StringId is NULL is NULL.
+
+**/
+EFI_STATUS
+IfrLibNewString (
+  IN  EFI_HII_HANDLE                  PackageList,
+  OUT EFI_STRING_ID                   *StringId,
+  IN  CONST EFI_STRING                String
+  )
+{
+  EFI_STATUS  Status;
+  CHAR8       *Languages;
+  CHAR8       *LangStrings;
+  CHAR8       Lang[RFC_3066_ENTRY_SIZE];
+
+  Status = EFI_SUCCESS;
+
+  LocateHiiProtocols ();
+
+  Languages = GetSupportedLanguages (PackageList);
+
+  LangStrings = Languages;
+  while (*LangStrings != 0) {
+    GetNextLanguage (&LangStrings, Lang);
+
+    Status = gIfrLibHiiString->NewString (
+                                 gIfrLibHiiString,
+                                 PackageList,
+                                 StringId,
+                                 Lang,
+                                 NULL,
+                                 String,
+                                 NULL
+                                 );
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+  }
+
+  gBS->FreePool (Languages);
+
+  return Status;
+}
+
+
+/**
+  This function try to retrieve string from String package of current language.
+  If fail, it try to retrieve string from String package of first language it support.
+
+  @param  PackageList            The package list in the HII database to search for
+                                 the specified string.
+  @param  StringId               The string's id, which is unique within
+                                 PackageList.
+  @param  String                 Points to the new null-terminated string.
+  @param  StringSize             On entry, points to the size of the buffer pointed
+                                 to by String, in bytes. On return, points to the
+                                 length of the string, in bytes.
+
+  @retval EFI_SUCCESS            The string was returned successfully.
+  @retval EFI_NOT_FOUND          The string specified by StringId is not available.
+  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by StringLength is too small
+                                 to hold the string.
+  @retval EFI_INVALID_PARAMETER  The String or StringSize was NULL.
+
+**/
+EFI_STATUS
+IfrLibGetString (
+  IN  EFI_HII_HANDLE                  PackageList,
+  IN  EFI_STRING_ID                   StringId,
+  OUT EFI_STRING                      String,
+  IN  OUT UINTN                       *StringSize
+  )
+{
+  EFI_STATUS  Status;
+  CHAR8       *Languages;
+  CHAR8       *LangStrings;
+  CHAR8       Lang[RFC_3066_ENTRY_SIZE];
+  CHAR8       CurrentLang[RFC_3066_ENTRY_SIZE];
+
+  LocateHiiProtocols ();
+
+  GetCurrentLanguage (CurrentLang);
+
+  Status = gIfrLibHiiString->GetString (
+                               gIfrLibHiiString,
+                               CurrentLang,
+                               PackageList,
+                               StringId,
+                               String,
+                               StringSize,
+                               NULL
+                               );
+
+  if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
+    Languages = GetSupportedLanguages (PackageList);
+    LangStrings = Languages;
+    GetNextLanguage (&LangStrings, Lang);
+    gBS->FreePool (Languages);
+
+    Status = gIfrLibHiiString->GetString (
+                                 gIfrLibHiiString,
+                                 Lang,
+                                 PackageList,
+                                 StringId,
+                                 String,
+                                 StringSize,
+                                 NULL
+                                 );
+  }
+
+  return Status;
+}
+
+
+/**
+  This function updates the string in String package of each language.
+
+  @param  PackageList            The package list containing the strings.
+  @param  StringId               The string's id, which is unique within
+                                 PackageList.
+  @param  String                 Points to the new null-terminated string.
+
+  @retval EFI_SUCCESS            The string was updated successfully.
+  @retval EFI_NOT_FOUND          The string specified by StringId is not in the
+                                 database.
+  @retval EFI_INVALID_PARAMETER  The String was NULL.
+  @retval EFI_OUT_OF_RESOURCES   The system is out of resources to accomplish the
+                                 task.
+
+**/
+EFI_STATUS
+IfrLibSetString (
+  IN EFI_HII_HANDLE                   PackageList,
+  IN EFI_STRING_ID                    StringId,
+  IN CONST EFI_STRING                 String
+  )
+{
+  EFI_STATUS  Status;
+  CHAR8       *Languages;
+  CHAR8       *LangStrings;
+  CHAR8       Lang[RFC_3066_ENTRY_SIZE];
+
+  Status = EFI_SUCCESS;
+
+  LocateHiiProtocols ();
+
+  Languages = GetSupportedLanguages (PackageList);
+
+  LangStrings = Languages;
+  while (*LangStrings != 0) {
+    GetNextLanguage (&LangStrings, Lang);
+
+    Status = gIfrLibHiiString->SetString (
+                                 gIfrLibHiiString,
+                                 PackageList,
+                                 StringId,
+                                 Lang,
+                                 String,
+                                 NULL
+                                 );
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+  }
+
+  gBS->FreePool (Languages);
+
+  return Status;
+}
+
diff --git a/MdeModulePkg/Library/PlatformBdsLibNull/BdsPlatform.c b/MdeModulePkg/Library/PlatformBdsLibNull/BdsPlatform.c
new file mode 100644 (file)
index 0000000..85633a9
--- /dev/null
@@ -0,0 +1,276 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  BdsPlatform.c\r
+\r
+Abstract:\r
+\r
+  This file include all platform action which can be customized\r
+  by IBV/OEM.\r
+\r
+--*/\r
+\r
+#include "BdsPlatform.h"\r
+\r
+//\r
+// BDS Platform Functions\r
+//\r
+VOID\r
+PlatformBdsInit (\r
+  IN EFI_BDS_ARCH_PROTOCOL_INSTANCE  *PrivateData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Platform Bds init. Incude the platform firmware vendor, revision\r
+  and so crc check.\r
+\r
+Arguments:\r
+\r
+  PrivateData  - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+{\r
+  return;\r
+}\r
+\r
+EFI_STATUS\r
+PlatformBdsConnectConsole (\r
+  IN BDS_CONSOLE_CONNECT_ENTRY   *PlatformConsole\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Connect the predefined platform default console device. Always try to find\r
+  and enable the vga device if have.\r
+\r
+Arguments:\r
+\r
+  PlatformConsole         - Predfined platform default console device array.\r
\r
+Returns:\r
+\r
+  EFI_SUCCESS             - Success connect at least one ConIn and ConOut \r
+                            device, there must have one ConOut device is \r
+                            active vga device.\r
+  \r
+  EFI_STATUS              - Return the status of \r
+                            BdsLibConnectAllDefaultConsoles ()\r
+\r
+--*/\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+PlatformBdsConnectSequence (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Connect with predeined platform connect sequence, \r
+  the OEM/IBV can customize with their own connect sequence.\r
+  \r
+Arguments:\r
+\r
+  None.\r
\r
+Returns:\r
+\r
+  None.\r
+  \r
+--*/\r
+{\r
+  return;\r
+}\r
+\r
+VOID\r
+PlatformBdsGetDriverOption (\r
+  IN OUT LIST_ENTRY              *BdsDriverLists\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Load the predefined driver option, OEM/IBV can customize this\r
+  to load their own drivers\r
+  \r
+Arguments:\r
+\r
+  BdsDriverLists  - The header of the driver option link list.\r
\r
+Returns:\r
+\r
+  None.\r
+  \r
+--*/\r
+{\r
+  return;\r
+}\r
+\r
+VOID\r
+PlatformBdsDiagnostics (\r
+  IN EXTENDMEM_COVERAGE_LEVEL    MemoryTestLevel,\r
+  IN BOOLEAN                     QuietBoot\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Perform the platform diagnostic, such like test memory. OEM/IBV also\r
+  can customize this fuction to support specific platform diagnostic.\r
+  \r
+Arguments:\r
+\r
+  MemoryTestLevel  - The memory test intensive level\r
+  \r
+  QuietBoot        - Indicate if need to enable the quiet boot\r
\r
+Returns:\r
+\r
+  None.\r
+  \r
+--*/\r
+{\r
+  return;\r
+}\r
+\r
+VOID\r
+PlatformBdsPolicyBehavior (\r
+  IN EFI_BDS_ARCH_PROTOCOL_INSTANCE  *PrivateData,\r
+  IN OUT LIST_ENTRY                  *DriverOptionList,\r
+  IN OUT LIST_ENTRY                  *BootOptionList\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  The function will excute with as the platform policy, current policy\r
+  is driven by boot mode. IBV/OEM can customize this code for their specific\r
+  policy action.\r
+  \r
+Arguments:\r
+\r
+  PrivateData      - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance\r
+  \r
+  DriverOptionList - The header of the driver option link list\r
+  \r
+  BootOptionList   - The header of the boot option link list\r
\r
+Returns:\r
+\r
+  None.\r
+  \r
+--*/\r
+{\r
+  return ;\r
+}\r
+\r
+VOID\r
+PlatformBdsBootSuccess (\r
+  IN  BDS_COMMON_OPTION   *Option\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Hook point after a boot attempt succeeds. We don't expect a boot option to\r
+  return, so the EFI 1.0 specification defines that you will default to an\r
+  interactive mode and stop processing the BootOrder list in this case. This\r
+  is alos a platform implementation and can be customized by IBV/OEM.\r
+\r
+Arguments:\r
+\r
+  Option - Pointer to Boot Option that succeeded to boot.\r
+\r
+Returns:\r
+  \r
+  None.\r
+\r
+--*/\r
+{\r
+  return;\r
+}\r
+\r
+VOID\r
+PlatformBdsBootFail (\r
+  IN  BDS_COMMON_OPTION  *Option,\r
+  IN  EFI_STATUS         Status,\r
+  IN  CHAR16             *ExitData,\r
+  IN  UINTN              ExitDataSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Hook point after a boot attempt fails.\r
+\r
+Arguments:\r
+  \r
+  Option - Pointer to Boot Option that failed to boot.\r
+\r
+  Status - Status returned from failed boot.\r
+\r
+  ExitData - Exit data returned from failed boot.\r
+\r
+  ExitDataSize - Exit data size returned from failed boot.\r
+\r
+Returns:\r
+  \r
+  None.\r
+\r
+--*/\r
+{\r
+  return;\r
+}\r
+\r
+EFI_STATUS\r
+PlatformBdsNoConsoleAction (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  This function is remained for IBV/OEM to do some platform action,\r
+  if there no console device can be connected.\r
+\r
+Arguments:\r
+  \r
+  None.\r
+  \r
+Returns:\r
+  \r
+  EFI_SUCCESS      - Direct return success now.\r
+\r
+--*/\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PlatformBdsLockNonUpdatableFlash (\r
+  VOID\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/MdeModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h b/MdeModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h
new file mode 100644 (file)
index 0000000..8332f6c
--- /dev/null
@@ -0,0 +1,37 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name: \r
+\r
+  BdsPlatform.h\r
+\r
+Abstract:\r
+\r
+  Head file for BDS Platform specific code\r
+\r
+--*/\r
+\r
+#ifndef _BDS_PLATFORM_H\r
+#define _BDS_PLATFORM_H\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/GenericBdsLib.h>\r
+#include <Library/PlatformBdsLib.h>\r
+#include <Library/GraphicsLib.h>\r
+\r
+#endif // _BDS_PLATFORM_H\r
diff --git a/MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf b/MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf
new file mode 100644 (file)
index 0000000..ce8535f
--- /dev/null
@@ -0,0 +1,55 @@
+#/** @file\r
+# Component name for module GenericBdsLib\r
+#\r
+# FIX ME!\r
+# Copyright (c) 2007, Intel Corporation. All rights reserved.\r
+#\r
+#  All rights reserved. This program and the accompanying materials       \r
+#  are licensed and made available under the terms and conditions of the BSD License   \r
+#  which accompanies this distribution. The full text of the license may be found at  \r
+#  http://opensource.org/licenses/bsd-license.php           \r
+#  \r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,      \r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = PlatformBdsLib\r
+  FILE_GUID                      = 143B5044-7C1B-4904-9778-EA16F1F3D554\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = PlatformBdsLib|DXE_DRIVER   \r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x0002000A\r
+\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+  BdsPlatform.c\r
+  PlatformData.c\r
+  BdsPlatform.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  MemoryAllocationLib\r
+  UefiBootServicesTableLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  PcdLib\r
+  GraphicsLib\r
+  GenericBdsLib\r
+\r
+[Guids]\r
+  gEfiDefaultBmpLogoGuid\r
diff --git a/MdeModulePkg/Library/PlatformBdsLibNull/PlatformData.c b/MdeModulePkg/Library/PlatformBdsLibNull/PlatformData.c
new file mode 100644 (file)
index 0000000..0b19277
--- /dev/null
@@ -0,0 +1,52 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name: \r
+\r
+  PlatformData.c\r
+\r
+Abstract:\r
+  \r
+  Defined the platform specific device path which will be used by\r
+  platform Bbd to perform the platform policy connect.\r
+\r
+--*/\r
+\r
+#include "BdsPlatform.h"\r
+\r
+//\r
+// Predefined platform default time out value\r
+//\r
+UINT16                      gPlatformBootTimeOutDefault = 10;\r
+\r
+//\r
+// Platform specific keyboard device path\r
+//\r
+\r
+//\r
+// Predefined platform default console device path\r
+//\r
+BDS_CONSOLE_CONNECT_ENTRY   gPlatformConsole[] = {\r
+  {\r
+    NULL,\r
+    0\r
+  }\r
+};\r
+\r
+//\r
+// Predefined platform specific driver option\r
+//\r
+EFI_DEVICE_PATH_PROTOCOL    *gPlatformDriverOption[] = { NULL };\r
+\r
+//\r
+// Predefined platform connect sequence\r
+//\r
+EFI_DEVICE_PATH_PROTOCOL    *gPlatformConnectSequence[] = { NULL };\r
index f182323a451f3e768af0c075c472ca000290ce3e..907a06d3f498ba32a373149fe5a1183de19a5a1e 100644 (file)
@@ -33,6 +33,7 @@
   UdpIoLib|Include/Library/UdpIoLib.h\r
   S3Lib|Include/Library/S3Lib.h\r
   RecoveryLib|Include/Library/RecoveryLib.h\r
+  GenericBdsLib.h|Include/Library/GenericBdsLib.h\r
   PlatDriOverLib|Include/Library/PlatDriOverLib.h\r
 \r
 [Guids.common]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE|BOOLEAN|0x00010042\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|TRUE|BOOLEAN|0x00010043\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst|TRUE|BOOLEAN|0x00010044\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHardwareErrorRecord|FALSE|BOOLEAN|0x00010044\r
 \r
 [PcdsFixedAtBuild.common]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPcdCallBackNumberPerPcdEntry|0x08|UINT32|0x0001000f\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x0|UINT32|0x30000014\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0x0|UINT32|0x30000010\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x0|UINT32|0x30000011\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault|10|UINT16|0x40000001\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|1|UINT16|0x40000002\r
 \r
 [PcdsDynamic.common]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0x0|UINT32|0x30000001\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x0|UINT32|0x30000014\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0x0|UINT32|0x30000010\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x0|UINT32|0x30000011\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault|10|UINT16|0x40000001\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|1|UINT16|0x40000002\r
 \r
 [PcdsPatchableInModule.common]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|40|UINT8|0x0001002f\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x0|UINT32|0x30000014\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0x0|UINT32|0x30000010\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x0|UINT32|0x30000011\r
-\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault|10|UINT16|0x40000001\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|1|UINT16|0x40000002\r
 \r
 [PcdsFeatureFlag.IA32]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|TRUE|BOOLEAN|0x0001003b\r
index 637cdfbe80b7e85b9a80ddd641e8bc2146067667..34854f5e1a9d241713a34ad819c0b70a5f9ea363 100644 (file)
@@ -35,8 +35,6 @@
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf\r
   PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf\r
   PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf\r
-  FrameworkIfrSupportLib|IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.inf\r
-\r
   PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf\r
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf\r
   PostCodeLib|MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf\r
   UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf\r
   FvbServiceLib|MdeModulePkg/Library/EdkFvbServiceLib/EdkFvbServiceLib.inf\r
   ScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf\r
-  FrameworkHiiLib|IntelFrameworkPkg/Library/FrameworkHiiLib/HiiLib.inf\r
+  HiiLib|MdePkg/Library/HiiLib/HiiLib.inf\r
   UsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf\r
   NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf\r
   IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf\r
   UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf\r
   DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf\r
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf\r
+  GraphicsLib|MdeModulepkg/Library/GraphicsLib/GraphicsLib.inf\r
+  IfrSupportLib|MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.inf\r
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf\r
+  DxePiLib|MdePkg/Library/DxePiLib/DxePiLib.inf\r
+  PlatformBdsLib|MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf\r
+  GenericBdsLib|MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf  \r
+  GraphicsLib|MdeModulepkg/Library/GraphicsLib/GraphicsLib.inf\r
+  IfrSupportLib|MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.inf\r
+  DxePiLib|MdePkg/Library/DxePiLib/DxePiLib.inf\r
+  PlatformBdsLib|MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf\r
+  GenericBdsLib|MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf  \r
   PlatDriOverLib|MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.inf\r
 \r
 [LibraryClasses.IA32]\r
   MdeModulePkg/Library/PeiS3LibNull/PeiS3LibNull.inf\r
   MdeModulePkg/Library/PeiRecoveryLibNull/PeiRecoveryLibNull.inf\r
 \r
+  MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.inf\r
+  MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf\r
+  MdeModulepkg/Library/GraphicsLib/GraphicsLib.inf\r
+\r
+  MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf\r
+\r
   MdeModulePkg/Universal/iScsi/IScsi.inf\r
 \r
   MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf\r
+  MdeModulePkg/Universal/BdsDxe/BdsDxe.inf \r
   MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf\r
   MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf\r
   MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf\r
   MdeModulePkg/Universal/Variable/Pei/VariablePei.inf\r
   MdeModulePkg/Universal/Variable/Application/VariableInfo.inf\r
 \r
+  MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
+  MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
+  MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf\r
+\r
 [Components.IA32]\r
   MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf\r
   MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf\r
   MdeModulePkg/Universal/DebugSupportDxe/DebugSupportDxe.inf\r
   MdeModulePkg/Universal/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf\r
   MdeModulePkg/Bus/Pci/UndiRuntimeDxe/UndiRuntimeDxe.inf\r
+  MdeModulepkg/Library/GraphicsLib/GraphicsLib.inf\r
 \r
 [Components.X64]\r
   MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf\r
diff --git a/MdeModulePkg/Universal/BdsDxe/Bds.h b/MdeModulePkg/Universal/BdsDxe/Bds.h
new file mode 100644 (file)
index 0000000..fbfa965
--- /dev/null
@@ -0,0 +1,117 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  Bds.h\r
+\r
+Abstract:\r
+\r
+  Head file for BDS Architectural Protocol implementation\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _BDS_MODULE_H_\r
+#define _BDS_MODULE_H_\r
+\r
+#undef EFI_SPECIFICATION_VERSION\r
+#define EFI_SPECIFICATION_VERSION 0x0002000A\r
+#include <PiDxe.h>\r
+#include <MdeModuleHii.h>\r
+\r
+#include <Guid/FileSystemVolumeLabelInfo.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Guid/BootState.h>\r
+#include <Guid/DataHubRecords.h>\r
+#include <Protocol/LoadFile.h>\r
+#include <Protocol/CpuIo.h>\r
+#include <Guid/HobList.h>\r
+#include <Guid/FileInfo.h>\r
+#include <Protocol/HiiConfigRouting.h>\r
+#include <Protocol/Bds.h>\r
+#include <Protocol/DataHub.h>\r
+#include <Protocol/UgaDraw.h>\r
+#include <Protocol/BlockIo.h>\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/GenericPlatformVariable.h>\r
+#include <Guid/CapsuleVendor.h>\r
+#include <Protocol/ConsoleControl.h>\r
+#include <Protocol/GenericMemoryTest.h>\r
+#include <Protocol/FormBrowser2.h>\r
+#include <Protocol/HiiConfigAccess.h>\r
+#include <Protocol/GraphicsOutput.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/HiiDatabase.h>\r
+#include <Protocol/HiiString.h>\r
+#include <Protocol/SerialIo.h>\r
+#include <Protocol/LegacyBios.h>\r
+#include <Protocol/SimpleTextInEx.h>\r
+#include <Protocol/Performance.h>\r
+\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/GraphicsLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/IfrSupportLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/CapsuleLib.h>\r
+#include <Library/HiiLib.h>\r
+\r
+#include <Library/GenericBdsLib.h>\r
+#include <Library/PlatformBdsLib.h>\r
+\r
+#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS(_this) \\r
+  CR (_this, \\r
+      EFI_BDS_ARCH_PROTOCOL_INSTANCE, \\r
+      Bds, \\r
+      EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE \\r
+      )\r
+\r
+EFI_STATUS\r
+PlatformBdsShowProgress (\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
+  IN CHAR16                        *Title,\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
+  IN UINTN                         Progress,\r
+  IN UINTN                         PreviousValue\r
+  );\r
+\r
+//\r
+// Prototypes\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+BdsInitialize (\r
+  IN EFI_HANDLE                     ImageHandle,\r
+  IN EFI_SYSTEM_TABLE               *SystemTable\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+BdsEntry (\r
+  IN  EFI_BDS_ARCH_PROTOCOL *This\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf b/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
new file mode 100644 (file)
index 0000000..c4c6b7f
--- /dev/null
@@ -0,0 +1,154 @@
+#/** @file\r
+# Component discription file for Bds module\r
+#\r
+# N/A\r
+# Copyright (c) 2008, Intel Corporation\r
+#\r
+#  All rights reserved. This program and the accompanying materials       \r
+#  are licensed and made available under the terms and conditions of the BSD License   \r
+#  which accompanies this distribution. The full text of the license may be found at  \r
+#  http://opensource.org/licenses/bsd-license.php           \r
+#  \r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,      \r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = Bds\r
+  FILE_GUID                      = FC5C7020-1A48-4198-9BE2-EAD5ABC8CF2F\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x00020000\r
+\r
+  ENTRY_POINT                    = BdsInitialize\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+  FrontPage.h\r
+  Language.h\r
+  Bds.h\r
+  Hotkey.h\r
+  BootMaint/BBSsupport.h\r
+  BootMngr/BootManager.h\r
+  BootMaint/BootMaint.h\r
+  String.h\r
+  BootMaint/FormGuid.h\r
+  HwErrRecSupport.c\r
+  HwErrRecSupport.h\r
+\r
+  DeviceMngr/DeviceManager.h\r
+  DeviceMngr/DeviceManagerVfr.Vfr\r
+  DeviceMngr/DeviceManagerStrings.uni\r
+  DeviceMngr/DeviceManager.c\r
+  BootMngr/BootManagerVfr.Vfr\r
+  BootMngr/BootManagerStrings.uni\r
+  BootMngr/BootManager.c\r
+  BootMaint/FE.vfr\r
+  BootMaint/FileExplorer.c\r
+  BootMaint/BootMaint.c\r
+  BootMaint/BBSsupport.c\r
+  BootMaint/UpdatePage.c\r
+  BootMaint/Variable.c\r
+  BootMaint/Data.c\r
+  BootMaint/ConsoleOption.c\r
+  BootMaint/BootOption.c\r
+  BootMaint/BmLib.c\r
+  BootMaint/Bm.vfr\r
+  BootMaint/Bmstring.uni\r
+  Hotkey.c\r
+  MemoryTest.c\r
+  Capsules.c\r
+  Strings.uni\r
+  String.c\r
+  Language.c\r
+  FrontPageVfr.Vfr\r
+  FrontPageStrings.uni\r
+  FrontPage.c\r
+  BdsEntry.c\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+  DevicePathLib\r
+  BaseLib\r
+  HobLib\r
+  UefiRuntimeServicesTableLib\r
+  IfrSupportLib\r
+  GenericBdsLib\r
+  ReportStatusCodeLib\r
+  PerformanceLib\r
+  DxeServicesTableLib\r
+  MemoryAllocationLib\r
+  GraphicsLib\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  PrintLib\r
+  HiiLib\r
+  UefiDriverEntryPoint\r
+  PlatformBdsLib\r
+  CapsuleLib\r
+\r
+[Guids]\r
+  gEfiGlobalVariableGuid                        # ALWAYS_CONSUMED\r
+  gEfiHobListGuid                               # ALWAYS_CONSUMED\r
+  gEfiBootStateGuid                             # ALWAYS_CONSUMED\r
+  gEfiFileSystemVolumeLabelInfoIdGuid           # ALWAYS_CONSUMED\r
+  gEfiFileInfoGuid                              # ALWAYS_CONSUMED\r
+  gEfiGenericPlatformVariableGuid\r
+  gEfiMiscSubClassGuid\r
+  gEfiMemorySubClassGuid\r
+  gEfiProcessorSubClassGuid\r
+  gEfiCapsuleVendorGuid\r
+  \r
+[Protocols]\r
+  gEfiHiiStringProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSimpleFileSystemProtocolGuid              # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiLoadFileProtocolGuid                      # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiCpuIoProtocolGuid                         # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiBdsArchProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiDataHubProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiGenericMemTestProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiLegacyBiosProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiConsoleControlProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiHiiDatabaseProtocolGuid                   # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiUgaDrawProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiBlockIoProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiGraphicsOutputProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSimpleTextInputExProtocolGuid             # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiHiiConfigRoutingProtocolGuid              # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiHiiConfigAccessProtocolGuid               # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiFormBrowser2ProtocolGuid                  # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSerialIoProtocolGuid                      # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiDevicePathProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiAcpiS3SaveProtocolGuid\r
+  \r
+[FeaturePcd.common]\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDepricate\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHardwareErrorRecord\r
+\r
+[Pcd.common]\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLang\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel\r
+\r
+[Depex]\r
+  gEfiHiiDatabaseProtocolGuid\r
+\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BdsDxe.msa b/MdeModulePkg/Universal/BdsDxe/BdsDxe.msa
new file mode 100644 (file)
index 0000000..2554755
--- /dev/null
@@ -0,0 +1,238 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+  <MsaHeader>\r
+    <ModuleName>BdsDxe</ModuleName>\r
+    <ModuleType>DXE_DRIVER</ModuleType>\r
+    <GuidValue>FC5C7020-1A48-4198-9BE2-EAD5ABC8CF2F</GuidValue>\r
+    <Version>1.0</Version>\r
+    <Abstract>Component discription file for Bds module</Abstract>\r
+    <Description>N/A</Description>\r
+    <Copyright>Copyright (c) 2008, Intel Corporation</Copyright>\r
+    <License>All rights reserved. This program and the accompanying materials                          \r
+      are licensed and made available under the terms and conditions of the BSD License         \r
+      which accompanies this distribution.  The full text of the license may be found at        \r
+      http://opensource.org/licenses/bsd-license.php                                            \r
+      \r
+      THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+      WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>\r
+    <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION   0x00000052</Specification>\r
+  </MsaHeader>\r
+  <ModuleDefinitions>\r
+    <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+    <BinaryModule>false</BinaryModule>\r
+    <OutputFileBasename>Bds</OutputFileBasename>\r
+  </ModuleDefinitions>\r
+  <LibraryClassDefinitions>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiDriverEntryPoint</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>PrintLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DebugLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseMemoryLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>EfiShellLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>EdkGenericPlatformBdsLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiBootServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>EdkGraphicsLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>MemoryAllocationLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DxeServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>PerformanceLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>ReportStatusCodeLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>EdkGenericBdsLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>EdkIfrSupportLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiRuntimeServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>HobLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DevicePathLib</Keyword>\r
+    </LibraryClass>\r
+  </LibraryClassDefinitions>\r
+  <SourceFiles>\r
+    <Filename>BdsEntry.c</Filename>\r
+    <Filename>FrontPage.c</Filename>\r
+    <Filename>FrontPageStrings.uni</Filename>\r
+    <Filename>FrontPageVfr.Vfr</Filename>\r
+    <Filename>Language.c</Filename>\r
+    <Filename>String.c</Filename>\r
+    <Filename>Strings.uni</Filename>\r
+    <Filename>Capsules.c</Filename>\r
+    <Filename>MemoryTest.c</Filename>\r
+    <Filename>Hotkey.c</Filename>\r
+    <Filename>BootMaint/Bmstring.uni</Filename>\r
+    <Filename>BootMaint/Bm.vfr</Filename>\r
+    <Filename>BootMaint/BmLib.c</Filename>\r
+    <Filename>BootMaint/BootOption.c</Filename>\r
+    <Filename>BootMaint/ConsoleOption.c</Filename>\r
+    <Filename>BootMaint/Data.c</Filename>\r
+    <Filename>BootMaint/Variable.c</Filename>\r
+    <Filename>BootMaint/UpdatePage.c</Filename>\r
+    <Filename>BootMaint/BBSsupport.c</Filename>\r
+    <Filename>BootMaint/BootMaint.c</Filename>\r
+    <Filename>BootMaint/FileExplorer.c</Filename>\r
+    <Filename>BootMaint/FE.vfr</Filename>\r
+    <Filename>BootMngr/BootManager.c</Filename>\r
+    <Filename>BootMngr/BootManagerStrings.uni</Filename>\r
+    <Filename>BootMngr/BootManagerVfr.Vfr</Filename>\r
+    <Filename>DeviceMngr/DeviceManager.c</Filename>\r
+    <Filename>DeviceMngr/DeviceManagerStrings.uni</Filename>\r
+    <Filename>DeviceMngr/DeviceManagerVfr.Vfr</Filename>\r
+    <Filename>Bds.dxs</Filename>\r
+    <Filename>DeviceMngr/DeviceManager.h</Filename>\r
+    <Filename>BootMaint/FormGuid.h</Filename>\r
+    <Filename>String.h</Filename>\r
+    <Filename>BootMaint/BootMaint.h</Filename>\r
+    <Filename>BootMngr/BootManager.h</Filename>\r
+    <Filename>BootMaint/BBSsupport.h</Filename>\r
+    <Filename>Hotkey.h</Filename>\r
+    <Filename>Bds.h</Filename>\r
+    <Filename>Language.h</Filename>\r
+    <Filename>FrontPage.h</Filename>\r
+    <Filename>EdkILib.c</Filename>\r
+  </SourceFiles>\r
+  <NonProcessedFiles>\r
+    <Filename>DeviceMngr/PlatOverMngr/PlatOverMngr.c</Filename>\r
+    <Filename>DeviceMngr/PlatOverMngr/PlatOverMngr.dxs</Filename>\r
+    <Filename>DeviceMngr/PlatOverMngr/PlatOverMngr.h</Filename>\r
+    <Filename>DeviceMngr/PlatOverMngr/Vfr.vfr</Filename>\r
+    <Filename>DeviceMngr/PlatOverMngr/VfrStrings.uni</Filename>\r
+    <Filename>DeviceMngr/SetOptions/GetInfo.c</Filename>\r
+    <Filename>DeviceMngr/SetOptions/GetInfo.h</Filename>\r
+    <Filename>DeviceMngr/SetOptions/SetOptions.c</Filename>\r
+    <Filename>DeviceMngr/SetOptions/SetOptions.h</Filename>\r
+    <Filename>DeviceMngr/SetOptions/Vfr.vfr</Filename>\r
+    <Filename>DeviceMngr/SetOptions/VfrStrings.uni</Filename>\r
+    <Filename>HwErrRecSupport.c</Filename>\r
+    <Filename>HwErrRecSupport.h</Filename>\r
+  </NonProcessedFiles>\r
+  <PackageDependencies>\r
+    <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+    <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+    <Package PackageGuid="3bd11b88-bf8b-4d90-9e04-77c97e58bbdd"/>\r
+  </PackageDependencies>\r
+  <Protocols>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiSerialIoProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiFormBrowser2ProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiHiiConfigAccessProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiHiiConfigRoutingProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiSimpleTextInputExProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiGraphicsOutputProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiBlockIoProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiUgaDrawProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiHiiDatabaseProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiConsoleControlProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiLegacyBiosProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiGenericMemTestProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiDataHubProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiBdsArchProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiCpuIoProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiLoadFileProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiSimpleFileSystemProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiHiiStringProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+  </Protocols>\r
+  <Guids>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiFlashMapHobGuid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gTerminalDriverGuid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiFileInfoGuid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiFileSystemVolumeLabelInfoIdGuid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiBootStateGuid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiHobListGuid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiGenericVariableGuid</GuidCName>\r
+    </GuidCNames>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiGlobalVariableGuid</GuidCName>\r
+    </GuidCNames>\r
+  </Guids>\r
+  <Externs>\r
+    <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+    <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+    <Extern>\r
+      <ModuleEntryPoint>BdsInitialize</ModuleEntryPoint>\r
+    </Extern>\r
+  </Externs>\r
+</ModuleSurfaceArea>\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c
new file mode 100644 (file)
index 0000000..b40e0ee
--- /dev/null
@@ -0,0 +1,375 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  BdsEntry.c\r
+\r
+Abstract:\r
+\r
+  The entry of the bds\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "Language.h"\r
+#include "FrontPage.h"\r
+#include "Hotkey.h"\r
+#include "HwErrRecSupport.h"\r
+\r
+\r
+EFI_BDS_ARCH_PROTOCOL_INSTANCE  gBdsInstanceTemplate = {\r
+  EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE,\r
+  NULL,\r
+  {BdsEntry},\r
+  0xFFFF,\r
+  TRUE,\r
+  EXTENSIVE\r
+};\r
+\r
+UINT16                          *mBootNext = NULL;\r
+\r
+EFI_HANDLE                      mBdsImageHandle;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BdsInitialize (\r
+  IN EFI_HANDLE                            ImageHandle,\r
+  IN EFI_SYSTEM_TABLE                      *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Install Boot Device Selection Protocol\r
+\r
+Arguments:\r
+\r
+  (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
+\r
+Returns:\r
+\r
+  EFI_SUCEESS - BDS has finished initializing.\r
+                Rerun the\r
+                dispatcher and recall BDS.Entry\r
+\r
+  Other       - Return value from AllocatePool()\r
+                or gBS->InstallProtocolInterface\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  mBdsImageHandle = ImageHandle;\r
+\r
+  //\r
+  // Install protocol interface\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &gBdsInstanceTemplate.Handle,\r
+                  &gEfiBdsArchProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &gBdsInstanceTemplate.Bds\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
+\r
+VOID\r
+BdsBootDeviceSelect (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  In the loop of attempt to boot for the boot order\r
+\r
+Arguments:\r
+\r
+  None.\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS        Status;\r
+  LIST_ENTRY        *Link;\r
+  BDS_COMMON_OPTION *BootOption;\r
+  UINTN             ExitDataSize;\r
+  CHAR16            *ExitData;\r
+  UINT16            Timeout;\r
+  LIST_ENTRY        BootLists;\r
+  CHAR16            Buffer[20];\r
+  BOOLEAN           BootNextExist;\r
+  LIST_ENTRY        *LinkBootNext;\r
+\r
+  //\r
+  // Got the latest boot option\r
+  //\r
+  BootNextExist = FALSE;\r
+  LinkBootNext  = NULL;\r
+  InitializeListHead (&BootLists);\r
+\r
+  //\r
+  // First check the boot next option\r
+  //\r
+  ZeroMem (Buffer, sizeof (Buffer));\r
+\r
+  if (mBootNext != NULL) {\r
+    //\r
+    // Indicate we have the boot next variable, so this time\r
+    // boot will always have this boot option\r
+    //\r
+    BootNextExist = TRUE;\r
+\r
+    //\r
+    // Clear the this variable so it's only exist in this time boot\r
+    //\r
+    gRT->SetVariable (\r
+          L"BootNext",\r
+          &gEfiGlobalVariableGuid,\r
+          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+          0,\r
+          mBootNext\r
+          );\r
+\r
+    //\r
+    // Add the boot next boot option\r
+    //\r
+    UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);\r
+    BootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
+    BootOption->BootCurrent = *mBootNext;\r
+  }\r
+  //\r
+  // Parse the boot order to get boot option\r
+  //\r
+  BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+  Link = BootLists.ForwardLink;\r
+\r
+  //\r
+  // Parameter check, make sure the loop will be valid\r
+  //\r
+  if (Link == NULL) {\r
+    return ;\r
+  }\r
+  //\r
+  // Here we make the boot in a loop, every boot success will\r
+  // return to the front page\r
+  //\r
+  for (;;) {\r
+    //\r
+    // Check the boot option list first\r
+    //\r
+    if (Link == &BootLists) {\r
+      //\r
+      // There are two ways to enter here:\r
+      // 1. There is no active boot option, give user chance to\r
+      //    add new boot option\r
+      // 2. All the active boot option processed, and there is no\r
+      //    one is success to boot, then we back here to allow user\r
+      //    add new active boot option\r
+      //\r
+      Timeout = 0xffff;\r
+      PlatformBdsEnterFrontPage (Timeout, FALSE);\r
+      InitializeListHead (&BootLists);\r
+      BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+      Link = BootLists.ForwardLink;\r
+      continue;\r
+    }\r
+    //\r
+    // Get the boot option from the link list\r
+    //\r
+    BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+    //\r
+    // According to EFI Specification, if a load option is not marked\r
+    // as LOAD_OPTION_ACTIVE, the boot manager will not automatically\r
+    // load the option.\r
+    //\r
+    if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {\r
+      //\r
+      // skip the header of the link list, becuase it has no boot option\r
+      //\r
+      Link = Link->ForwardLink;\r
+      continue;\r
+    }\r
+    //\r
+    // Make sure the boot option device path connected,\r
+    // but ignore the BBS device path\r
+    //\r
+    if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {\r
+      //\r
+      // Notes: the internal shell can not been connected with device path\r
+      // so we do not check the status here\r
+      //\r
+      BdsLibConnectDevicePath (BootOption->DevicePath);\r
+    }\r
+    //\r
+    // All the driver options should have been processed since\r
+    // now boot will be performed.\r
+    //\r
+    Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Call platform action to indicate the boot fail\r
+      //\r
+      BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
+      PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);\r
+\r
+      //\r
+      // Check the next boot option\r
+      //\r
+      Link = Link->ForwardLink;\r
+\r
+    } else {\r
+      //\r
+      // Call platform action to indicate the boot success\r
+      //\r
+      BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); \r
+      PlatformBdsBootSuccess (BootOption);\r
+\r
+      //\r
+      // Boot success, then stop process the boot order, and\r
+      // present the boot manager menu, front page\r
+      //\r
+      Timeout = 0xffff;\r
+      PlatformBdsEnterFrontPage (Timeout, FALSE);\r
+\r
+      //\r
+      // Rescan the boot option list, avoid pertential risk of the boot\r
+      // option change in front page\r
+      //\r
+      if (BootNextExist) {\r
+        LinkBootNext = BootLists.ForwardLink;\r
+      }\r
+\r
+      InitializeListHead (&BootLists);\r
+      if (LinkBootNext != NULL) {\r
+        //\r
+        // Reserve the boot next option\r
+        //\r
+        InsertTailList (&BootLists, LinkBootNext);\r
+      }\r
+\r
+      BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+      Link = BootLists.ForwardLink;\r
+    }\r
+  }\r
+\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+BdsEntry (\r
+  IN EFI_BDS_ARCH_PROTOCOL  *This\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Service routine for BdsInstance->Entry(). Devices are connected, the\r
+  consoles are initialized, and the boot options are tried.\r
+\r
+Arguments:\r
+\r
+  This - Protocol Instance structure.\r
+\r
+Returns:\r
+\r
+  EFI_SUCEESS - BDS->Entry has finished executing.\r
+\r
+--*/\r
+{\r
+  EFI_BDS_ARCH_PROTOCOL_INSTANCE  *PrivateData;\r
+  LIST_ENTRY                      DriverOptionList;\r
+  LIST_ENTRY                      BootOptionList;\r
+  UINTN                           BootNextSize;\r
+\r
+  //\r
+  // Insert the performance probe\r
+  //\r
+  PERF_END (0, DXE_TOK, NULL, 0);\r
+  PERF_START (0, BDS_TOK, NULL, 0);\r
+\r
+  //\r
+  // Initialize the global system boot option and driver option\r
+  //\r
+  InitializeListHead (&DriverOptionList);\r
+  InitializeListHead (&BootOptionList);\r
+\r
+  //\r
+  // Initialize hotkey service\r
+  //\r
+  InitializeHotkeyService ();\r
+\r
+  //\r
+  // Get the BDS private data\r
+  //\r
+  PrivateData = EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This);\r
+\r
+  //\r
+  // Do the platform init, can be customized by OEM/IBV\r
+  //\r
+  PERF_START (0, "PlatformBds", "BDS", 0);\r
+  PlatformBdsInit (PrivateData);\r
+\r
+  if (FeaturePcdGet (PcdSupportHardwareErrorRecord)) {\r
+    InitializeHwErrRecSupport (PcdGet16 (PcdHardwareErrorRecordLevel));\r
+  }\r
+  //\r
+  // bugbug: platform specific code\r
+  // Initialize the platform specific string and language\r
+  //\r
+  InitializeStringSupport ();\r
+  InitializeLanguage (TRUE);\r
+  InitializeFrontPage (FALSE);\r
+\r
+  //\r
+  // Set up the device list based on EFI 1.1 variables\r
+  // process Driver#### and Load the driver's in the\r
+  // driver option list\r
+  //\r
+  BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder");\r
+  if (!IsListEmpty (&DriverOptionList)) {\r
+    BdsLibLoadDrivers (&DriverOptionList);\r
+  }\r
+  //\r
+  // Check if we have the boot next option\r
+  //\r
+  mBootNext = BdsLibGetVariableAndSize (\r
+                L"BootNext",\r
+                &gEfiGlobalVariableGuid,\r
+                &BootNextSize\r
+                );\r
+\r
+  //\r
+  // Setup some platform policy here\r
+  //\r
+  PlatformBdsPolicyBehavior (PrivateData, &DriverOptionList, &BootOptionList);\r
+  PERF_END (0, "PlatformBds", "BDS", 0);\r
+\r
+  //\r
+  // BDS select the boot device to load OS\r
+  //\r
+  BdsBootDeviceSelect ();\r
+\r
+  //\r
+  // Only assert here since this is the right behavior, we should never\r
+  // return back to DxeCore.\r
+  //\r
+  ASSERT (FALSE);\r
+\r
+  return ;\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c
new file mode 100644 (file)
index 0000000..2f0d5d9
--- /dev/null
@@ -0,0 +1,1664 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  BBSsupport.c\r
+\r
+Abstract:\r
+\r
+  This function deal with the legacy boot option, it create, delete\r
+  and manage the legacy boot option, all legacy boot option is getting from\r
+  the legacy BBS table.\r
+\r
+--*/\r
+\r
+#include "BBSsupport.h"\r
+\r
+EFI_DEVICE_PATH_PROTOCOL  EndDevicePath[] = {\r
+  END_DEVICE_PATH_TYPE,\r
+  END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+  END_DEVICE_PATH_LENGTH,\r
+  0\r
+};\r
+\r
+VOID\r
+AsciiToUnicodeSize (\r
+  IN UINT8              *a,\r
+  IN UINTN              Size,\r
+  OUT UINT16            *u\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+\r
+    Translate the first n characters of an Ascii string to\r
+    Unicode characters. The count n is indicated by parameter\r
+    Size. If Size is greater than the length of string, then\r
+    the entire string is translated.\r
+\r
+  Arguments:\r
+\r
+    a         - Pointer to input Ascii string.\r
+    Size      - The number of characters to translate.\r
+    u         - Pointer to output Unicode string buffer.\r
+\r
+  Returns:\r
+\r
+    None\r
+\r
+--*/\r
+{\r
+  UINTN i;\r
+\r
+  i = 0;\r
+  while (a[i] != 0) {\r
+    u[i] = (CHAR16) a[i];\r
+    if (i == Size) {\r
+      break;\r
+    }\r
+\r
+    i++;\r
+  }\r
+  u[i] = 0;\r
+}\r
+\r
+UINTN\r
+UnicodeToAscii (\r
+  IN  CHAR16  *UStr,\r
+  IN  UINTN   Length,\r
+  OUT CHAR8   *AStr\r
+  )\r
+/*++\r
+Routine Description:\r
+\r
+  change a Unicode string t ASCII string\r
+\r
+Arguments:\r
+\r
+  UStr   - Unicode string\r
+  Lenght - most possible length of AStr\r
+  AStr   - ASCII string to pass out\r
+\r
+Returns:\r
+\r
+  Actuall length\r
+\r
+--*/\r
+{\r
+  UINTN Index;\r
+\r
+  //\r
+  // just buffer copy, not character copy\r
+  //\r
+  for (Index = 0; Index < Length; Index++) {\r
+    *AStr++ = (CHAR8) *UStr++;\r
+  }\r
+\r
+  return Index;\r
+}\r
+\r
+VOID\r
+BdsBuildLegacyDevNameString (\r
+  IN BBS_TABLE                 *CurBBSEntry,\r
+  IN UINTN                     Index,\r
+  IN UINTN                     BufSize,\r
+  OUT CHAR16                   *BootString\r
+  )\r
+{\r
+  CHAR16  *Fmt;\r
+  CHAR16  *Type;\r
+  UINT8   *StringDesc;\r
+  CHAR16  temp[80];\r
+\r
+  switch (Index) {\r
+  //\r
+  // Primary Master\r
+  //\r
+  case 1:\r
+    Fmt = L"Primary Master %s";\r
+    break;\r
+\r
+ //\r
+ // Primary Slave\r
+ //\r
+  case 2:\r
+    Fmt = L"Primary Slave %s";\r
+    break;\r
+\r
+  //\r
+  // Secondary Master\r
+  //\r
+  case 3:\r
+    Fmt = L"Secondary Master %s";\r
+    break;\r
+\r
+  //\r
+  // Secondary Slave\r
+  //\r
+  case 4:\r
+    Fmt = L"Secondary Slave %s";\r
+    break;\r
+\r
+  default:\r
+    Fmt = L"%s";\r
+    break;\r
+  }\r
+\r
+  switch (CurBBSEntry->DeviceType) {\r
+  case BBS_FLOPPY:\r
+    Type = L"Floppy";\r
+    break;\r
+\r
+  case BBS_HARDDISK:\r
+    Type = L"Harddisk";\r
+    break;\r
+\r
+  case BBS_CDROM:\r
+    Type = L"CDROM";\r
+    break;\r
+\r
+  case BBS_PCMCIA:\r
+    Type = L"PCMCIAe";\r
+    break;\r
+\r
+  case BBS_USB:\r
+    Type = L"USB";\r
+    break;\r
+\r
+  case BBS_EMBED_NETWORK:\r
+    Type = L"Network";\r
+    break;\r
+\r
+  case BBS_BEV_DEVICE:\r
+    Type = L"BEVe";\r
+    break;\r
+\r
+  case BBS_UNKNOWN:\r
+  default:\r
+    Type = L"Unknown";\r
+    break;\r
+  }\r
+  //\r
+  // If current BBS entry has its description then use it.\r
+  //\r
+  StringDesc = (UINT8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset);\r
+  if (NULL != StringDesc) {\r
+    //\r
+    // Only get fisrt 32 characters, this is suggested by BBS spec\r
+    //\r
+    AsciiToUnicodeSize (StringDesc, 32, temp);\r
+    Fmt   = L"%s";\r
+    Type  = temp;\r
+  }\r
+\r
+  //\r
+  // BbsTable 16 entries are for onboard IDE.\r
+  // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11\r
+  //\r
+  if (Index >= 5 && Index <= 16 && CurBBSEntry->DeviceType == BBS_HARDDISK) {\r
+    Fmt = L"%s %d";\r
+    UnicodeSPrint (BootString, BufSize, Fmt, Type, Index - 5);\r
+  } else {\r
+    UnicodeSPrint (BootString, BufSize, Fmt, Type);\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+BdsCreateLegacyBootOption (\r
+  IN BBS_TABLE                        *CurrentBbsEntry,\r
+  IN EFI_DEVICE_PATH_PROTOCOL         *CurrentBbsDevPath,\r
+  IN UINTN                            Index,\r
+  IN OUT UINT16                       **BootOrderList,\r
+  IN OUT UINTN                        *BootOrderListSize\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+\r
+    Create a legacy boot option for the specified entry of\r
+    BBS table, save it as variable, and append it to the boot\r
+    order list.\r
+\r
+  Arguments:\r
+\r
+    CurrentBbsEntry        - Pointer to current BBS table.\r
+    CurrentBbsDevPath      - Pointer to the Device Path Protocol instance of BBS\r
+    Index                  - Index of the specified entry in BBS table.\r
+    BootOrderList          - On input, the original boot order list.\r
+                             On output, the new boot order list attached with the\r
+                             created node.\r
+    BootOrderListSize      - On input, the original size of boot order list.\r
+                           - On output, the size of new boot order list.\r
+\r
+  Returns:\r
+\r
+    EFI_SUCCESS            - Boot Option successfully created.\r
+    EFI_OUT_OF_RESOURCES   - Fail to allocate necessary memory.\r
+    Other                  - Error occurs while setting variable.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS           Status;\r
+  UINT16               CurrentBootOptionNo;\r
+  UINT16               BootString[10];\r
+  UINT16               BootDesc[100];\r
+  CHAR8                HelpString[100];\r
+  UINT16               *NewBootOrderList;\r
+  UINTN                BufferSize;\r
+  UINTN                StringLen;\r
+  VOID                 *Buffer;\r
+  UINT8                *Ptr;\r
+  UINT16               CurrentBbsDevPathSize;\r
+  UINTN                BootOrderIndex;\r
+  UINTN                BootOrderLastIndex;\r
+  UINTN                ArrayIndex;\r
+  BOOLEAN              IndexNotFound;\r
+  BBS_BBS_DEVICE_PATH  *NewBbsDevPathNode;\r
+\r
+  if (NULL == (*BootOrderList)) {\r
+    CurrentBootOptionNo = 0;\r
+  } else {\r
+    for (ArrayIndex = 0; ArrayIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); ArrayIndex++) {\r
+      IndexNotFound = TRUE;\r
+      for (BootOrderIndex = 0; BootOrderIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); BootOrderIndex++) {\r
+        if ((*BootOrderList)[BootOrderIndex] == ArrayIndex) {\r
+          IndexNotFound = FALSE;\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (!IndexNotFound) {\r
+        continue;\r
+      } else {\r
+        break;\r
+      }\r
+    }\r
+\r
+    CurrentBootOptionNo = (UINT16) ArrayIndex;\r
+  }\r
+\r
+  UnicodeSPrint (\r
+    BootString,\r
+    sizeof (BootString),\r
+    L"Boot%04x",\r
+    CurrentBootOptionNo\r
+    );\r
+\r
+  BdsBuildLegacyDevNameString (CurrentBbsEntry, Index, sizeof (BootDesc), BootDesc);\r
+\r
+  //\r
+  // Create new BBS device path node with description string\r
+  //\r
+  UnicodeToAscii (BootDesc, StrSize (BootDesc), HelpString);\r
+  StringLen = AsciiStrLen (HelpString);\r
+  NewBbsDevPathNode = EfiAllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen);\r
+  if (NewBbsDevPathNode == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  CopyMem (NewBbsDevPathNode, CurrentBbsDevPath, sizeof (BBS_BBS_DEVICE_PATH));\r
+  CopyMem (NewBbsDevPathNode->String, HelpString, StringLen + 1);\r
+  SetDevicePathNodeLength (&(NewBbsDevPathNode->Header), sizeof (BBS_BBS_DEVICE_PATH) + StringLen);\r
+\r
+  //\r
+  // Create entire new CurrentBbsDevPath with end node\r
+  //\r
+  CurrentBbsDevPath = AppendDevicePathNode (\r
+                        EndDevicePath,\r
+                        (EFI_DEVICE_PATH_PROTOCOL *) NewBbsDevPathNode\r
+                        );\r
+   if (CurrentBbsDevPath == NULL) {\r
+    FreePool (NewBbsDevPathNode);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  CurrentBbsDevPathSize = (UINT16) (GetDevicePathSize (CurrentBbsDevPath));\r
+\r
+  BufferSize = sizeof (UINT32) +\r
+    sizeof (UINT16) +\r
+    StrSize (BootDesc) +\r
+    CurrentBbsDevPathSize +\r
+    sizeof (BBS_TABLE) +\r
+    sizeof (UINT16);\r
+\r
+  Buffer = EfiAllocateZeroPool (BufferSize);\r
+  if (Buffer == NULL) {\r
+    FreePool (NewBbsDevPathNode);\r
+    FreePool (CurrentBbsDevPath);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Ptr               = (UINT8 *) Buffer;\r
+\r
+  *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
+  Ptr += sizeof (UINT32);\r
+\r
+  *((UINT16 *) Ptr) = CurrentBbsDevPathSize;\r
+  Ptr += sizeof (UINT16);\r
+\r
+  CopyMem (\r
+    Ptr,\r
+    BootDesc,\r
+    StrSize (BootDesc)\r
+    );\r
+  Ptr += StrSize (BootDesc);\r
+\r
+  CopyMem (\r
+    Ptr,\r
+    CurrentBbsDevPath,\r
+    CurrentBbsDevPathSize\r
+    );\r
+  Ptr += CurrentBbsDevPathSize;\r
+\r
+  CopyMem (\r
+    Ptr,\r
+    CurrentBbsEntry,\r
+    sizeof (BBS_TABLE)\r
+    );\r
+\r
+  Ptr += sizeof (BBS_TABLE);\r
+  *((UINT16 *) Ptr) = (UINT16) Index;\r
+\r
+  Status = gRT->SetVariable (\r
+                  BootString,\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BufferSize,\r
+                  Buffer\r
+                  );\r
+\r
+  SafeFreePool (Buffer);\r
+  Buffer = NULL;\r
+\r
+  NewBootOrderList = EfiAllocateZeroPool (*BootOrderListSize + sizeof (UINT16));\r
+  if (NULL == NewBootOrderList) {\r
+    FreePool (NewBbsDevPathNode);\r
+    FreePool (CurrentBbsDevPath);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (NULL != *BootOrderList) {\r
+    CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize);\r
+  }\r
+\r
+  SafeFreePool (*BootOrderList);\r
+\r
+  BootOrderLastIndex                    = (UINTN) (*BootOrderListSize / sizeof (UINT16));\r
+  NewBootOrderList[BootOrderLastIndex]  = CurrentBootOptionNo;\r
+  *BootOrderListSize += sizeof (UINT16);\r
+  *BootOrderList = NewBootOrderList;\r
+\r
+  FreePool (NewBbsDevPathNode);\r
+  FreePool (CurrentBbsDevPath);\r
+  return Status;\r
+}\r
+\r
+BOOLEAN\r
+BdsIsLegacyBootOption (\r
+  IN UINT8                 *BootOptionVar,\r
+  OUT BBS_TABLE            **BbsEntry,\r
+  OUT UINT16               *BbsIndex\r
+  )\r
+{\r
+  UINT8                     *Ptr;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  BOOLEAN                   Ret;\r
+  UINT16                    DevPathLen;\r
+\r
+  Ptr = BootOptionVar;\r
+  Ptr += sizeof (UINT32);\r
+  DevPathLen = *(UINT16 *) Ptr;\r
+  Ptr += sizeof (UINT16);\r
+  Ptr += StrSize ((UINT16 *) Ptr);\r
+  DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+  if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {\r
+    Ptr += DevPathLen;\r
+    *BbsEntry = (BBS_TABLE *) Ptr;\r
+    Ptr += sizeof (BBS_TABLE);\r
+    *BbsIndex = *(UINT16 *) Ptr;\r
+    Ret       = TRUE;\r
+  } else {\r
+    *BbsEntry = NULL;\r
+    Ret       = FALSE;\r
+  }\r
+\r
+  return Ret;\r
+}\r
+\r
+EFI_STATUS\r
+BdsDeleteBootOption (\r
+  IN UINTN                       OptionNumber,\r
+  IN OUT UINT16                  *BootOrder,\r
+  IN OUT UINTN                   *BootOrderSize\r
+  )\r
+{\r
+  UINT16      BootOption[100];\r
+  UINTN       Index;\r
+  EFI_STATUS  Status;\r
+  UINTN       Index2Del;\r
+\r
+  Status    = EFI_SUCCESS;\r
+  Index2Del = 0;\r
+\r
+  UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber);\r
+  Status = EfiLibDeleteVariable (BootOption, &gEfiGlobalVariableGuid);\r
+  //\r
+  // adjust boot order array\r
+  //\r
+  for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) {\r
+    if (BootOrder[Index] == OptionNumber) {\r
+      Index2Del = Index;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index != *BootOrderSize / sizeof (UINT16)) {\r
+    for (Index = 0; Index < *BootOrderSize / sizeof (UINT16) - 1; Index++) {\r
+      if (Index >= Index2Del) {\r
+        BootOrder[Index] = BootOrder[Index + 1];\r
+      }\r
+    }\r
+\r
+    *BootOrderSize -= sizeof (UINT16);\r
+  }\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+BdsDeleteAllInvalidLegacyBootOptions (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+\r
+    Delete all the invalid legacy boot options.\r
+\r
+  Arguments:\r
+\r
+    None.\r
+\r
+  Returns:\r
+\r
+    EFI_SUCCESS            - All invalide legacy boot options are deleted.\r
+    EFI_OUT_OF_RESOURCES   - Fail to allocate necessary memory.\r
+    EFI_NOT_FOUND          - Fail to retrive variable of boot order.\r
+    Other                  - Error occurs while setting variable or locating\r
+                             protocol.\r
+\r
+--*/\r
+{\r
+  UINT16                    *BootOrder;\r
+  UINT8                     *BootOptionVar;\r
+  UINTN                     BootOrderSize;\r
+  UINTN                     BootOptionSize;\r
+  EFI_STATUS                Status;\r
+  UINT16                    HddCount;\r
+  UINT16                    BbsCount;\r
+  HDD_INFO                  *LocalHddInfo;\r
+  BBS_TABLE                 *LocalBbsTable;\r
+  BBS_TABLE                 *BbsEntry;\r
+  UINT16                    BbsIndex;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINTN                     Index;\r
+  UINT16                    BootOption[10];\r
+  UINT16                    BootDesc[100];\r
+  BOOLEAN                   DescStringMatch;\r
+\r
+  Status        = EFI_SUCCESS;\r
+  BootOrder     = NULL;\r
+  BootOrderSize = 0;\r
+  HddCount      = 0;\r
+  BbsCount      = 0;\r
+  LocalHddInfo  = NULL;\r
+  LocalBbsTable = NULL;\r
+  BbsEntry      = NULL;\r
+\r
+  Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  LegacyBios->GetBbsInfo (\r
+                LegacyBios,\r
+                &HddCount,\r
+                &LocalHddInfo,\r
+                &BbsCount,\r
+                &LocalBbsTable\r
+                );\r
+\r
+  BootOrder = BdsLibGetVariableAndSize (\r
+                L"BootOrder",\r
+                &gEfiGlobalVariableGuid,\r
+                &BootOrderSize\r
+                );\r
+  if (NULL == BootOrder) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Index = 0;\r
+  while (Index < BootOrderSize / sizeof (UINT16)) {\r
+    UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+    BootOptionVar = BdsLibGetVariableAndSize (\r
+                      BootOption,\r
+                      &gEfiGlobalVariableGuid,\r
+                      &BootOptionSize\r
+                      );\r
+    if (NULL == BootOptionVar) {\r
+      SafeFreePool (BootOrder);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {\r
+      SafeFreePool (BootOptionVar);\r
+      Index++;\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Check if BBS Description String is changed\r
+    //\r
+    DescStringMatch = FALSE;\r
+\r
+    BdsBuildLegacyDevNameString (\r
+      &LocalBbsTable[BbsIndex],\r
+      BbsIndex,\r
+      sizeof(BootDesc),\r
+      BootDesc\r
+      );\r
+\r
+    if (StrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) {\r
+      DescStringMatch = TRUE;\r
+    }\r
+\r
+    if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) ||\r
+          (LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM)) &&\r
+        (LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) &&\r
+        DescStringMatch) {\r
+      Index++;\r
+      continue;\r
+    }\r
+\r
+    SafeFreePool (BootOptionVar);\r
+    //\r
+    // should delete\r
+    //\r
+    BdsDeleteBootOption (\r
+      BootOrder[Index],\r
+      BootOrder,\r
+      &BootOrderSize\r
+      );\r
+  }\r
+\r
+  if (BootOrderSize) {\r
+    Status = gRT->SetVariable (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    BootOrderSize,\r
+                    BootOrder\r
+                    );\r
+  } else {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  SafeFreePool (BootOrder);\r
+\r
+  return Status;\r
+}\r
+\r
+BOOLEAN\r
+BdsFindLegacyBootOptionByDevType (\r
+  IN UINT16                 *BootOrder,\r
+  IN UINTN                  BootOptionNum,\r
+  IN UINT16                 DevType,\r
+  OUT UINT32                *Attribute,\r
+  OUT UINT16                *BbsIndex,\r
+  OUT UINTN                 *OptionNumber\r
+  )\r
+{\r
+  UINTN     Index;\r
+  UINTN     BootOrderIndex;\r
+  UINT16    BootOption[100];\r
+  UINTN     BootOptionSize;\r
+  UINT8     *BootOptionVar;\r
+  BBS_TABLE *BbsEntry;\r
+  BOOLEAN   Found;\r
+\r
+  BbsEntry  = NULL;\r
+  Found     = FALSE;\r
+\r
+  if (NULL == BootOrder) {\r
+    return Found;\r
+  }\r
+\r
+  for (BootOrderIndex = 0; BootOrderIndex < BootOptionNum; BootOrderIndex++) {\r
+    Index = (UINTN) BootOrder[BootOrderIndex];\r
+    UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", Index);\r
+    BootOptionVar = BdsLibGetVariableAndSize (\r
+                      BootOption,\r
+                      &gEfiGlobalVariableGuid,\r
+                      &BootOptionSize\r
+                      );\r
+    if (NULL == BootOptionVar) {\r
+      continue;\r
+    }\r
+\r
+    if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {\r
+      SafeFreePool (BootOptionVar);\r
+      continue;\r
+    }\r
+\r
+    if (BbsEntry->DeviceType != DevType) {\r
+      SafeFreePool (BootOptionVar);\r
+      continue;\r
+    }\r
+\r
+    *Attribute    = *(UINT32 *) BootOptionVar;\r
+    *OptionNumber = Index;\r
+    Found         = TRUE;\r
+    SafeFreePool (BootOptionVar);\r
+    break;\r
+  }\r
+\r
+  return Found;\r
+}\r
+\r
+EFI_STATUS\r
+BdsCreateOneLegacyBootOption (\r
+  IN BBS_TABLE              *BbsItem,\r
+  IN UINTN                  Index,\r
+  IN OUT UINT16             **BootOrderList,\r
+  IN OUT UINTN              *BootOrderListSize\r
+  )\r
+{\r
+  BBS_BBS_DEVICE_PATH       BbsDevPathNode;\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
+\r
+  DevPath                       = NULL;\r
+\r
+  BbsDevPathNode.Header.Type    = BBS_DEVICE_PATH;\r
+  BbsDevPathNode.Header.SubType = BBS_BBS_DP;\r
+  SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));\r
+  BbsDevPathNode.DeviceType = BbsItem->DeviceType;\r
+  CopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16));\r
+\r
+  DevPath = AppendDevicePathNode (\r
+              EndDevicePath,\r
+              (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode\r
+              );\r
+  if (NULL == DevPath) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = BdsCreateLegacyBootOption (\r
+            BbsItem,\r
+            DevPath,\r
+            Index,\r
+            BootOrderList,\r
+            BootOrderListSize\r
+            );\r
+  BbsItem->BootPriority = 0x00;\r
+\r
+  FreePool (DevPath);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+BdsAddNonExistingLegacyBootOptions (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Add the legacy boot options from BBS table if they do not exist.\r
+\r
+Arguments:\r
+\r
+  None.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS       - The boot options are added successfully or they are already in boot options.\r
+  others            - An error occurred when creating legacy boot options.\r
+\r
+--*/\r
+{\r
+  UINT16                    *BootOrder;\r
+  UINTN                     BootOrderSize;\r
+  EFI_STATUS                Status;\r
+  UINT16                    HddCount;\r
+  UINT16                    BbsCount;\r
+  HDD_INFO                  *LocalHddInfo;\r
+  BBS_TABLE                 *LocalBbsTable;\r
+  UINT16                    BbsIndex;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINTN                     Index;\r
+  UINT32                    Attribute;\r
+  UINTN                     OptionNumber;\r
+  BOOLEAN                   Ret;\r
+\r
+  BootOrder     = NULL;\r
+  HddCount      = 0;\r
+  BbsCount      = 0;\r
+  LocalHddInfo  = NULL;\r
+  LocalBbsTable = NULL;\r
+\r
+  Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  LegacyBios->GetBbsInfo (\r
+                LegacyBios,\r
+                &HddCount,\r
+                &LocalHddInfo,\r
+                &BbsCount,\r
+                &LocalBbsTable\r
+                );\r
+\r
+  BootOrder = BdsLibGetVariableAndSize (\r
+                L"BootOrder",\r
+                &gEfiGlobalVariableGuid,\r
+                &BootOrderSize\r
+                );\r
+  if (NULL == BootOrder) {\r
+    BootOrderSize = 0;\r
+  }\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+        (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    Ret = BdsFindLegacyBootOptionByDevType (\r
+            BootOrder,\r
+            BootOrderSize / sizeof (UINT16),\r
+            LocalBbsTable[Index].DeviceType,\r
+            &Attribute,\r
+            &BbsIndex,\r
+            &OptionNumber\r
+            );\r
+    if (Ret) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Not found such type of legacy device in boot options or we found but it's disabled\r
+    // so we have to create one and put it to the tail of boot order list\r
+    //\r
+    Status = BdsCreateOneLegacyBootOption (\r
+              &LocalBbsTable[Index],\r
+              Index,\r
+              &BootOrder,\r
+              &BootOrderSize\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (BootOrderSize > 0) {\r
+    Status = gRT->SetVariable (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    BootOrderSize,\r
+                    BootOrder\r
+                    );\r
+  } else {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  if (BootOrder != NULL) {\r
+    SafeFreePool (BootOrder);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+UINT16 *\r
+BdsFillDevOrderBuf (\r
+  IN BBS_TABLE                    *BbsTable,\r
+  IN BBS_TYPE                     BbsType,\r
+  IN UINTN                        BbsCount,\r
+  IN UINT16                       *Buf\r
+  )\r
+{\r
+  UINTN Index;\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
+      continue;\r
+    }\r
+\r
+    if (BbsTable[Index].DeviceType != BbsType) {\r
+      continue;\r
+    }\r
+\r
+    *Buf = (UINT16) (Index & 0xFF);\r
+    Buf++;\r
+  }\r
+\r
+  return Buf;\r
+}\r
+\r
+EFI_STATUS\r
+BdsCreateDevOrder (\r
+  IN BBS_TABLE                  *BbsTable,\r
+  IN UINT16                     BbsCount\r
+  )\r
+{\r
+  UINTN       Index;\r
+  UINTN       FDCount;\r
+  UINTN       HDCount;\r
+  UINTN       CDCount;\r
+  UINTN       NETCount;\r
+  UINTN       BEVCount;\r
+  UINTN       TotalSize;\r
+  UINTN       HeaderSize;\r
+  UINT8       *DevOrder;\r
+  UINT8       *Ptr;\r
+  EFI_STATUS  Status;\r
+\r
+  FDCount     = 0;\r
+  HDCount     = 0;\r
+  CDCount     = 0;\r
+  NETCount    = 0;\r
+  BEVCount    = 0;\r
+  TotalSize   = 0;\r
+  HeaderSize  = sizeof (BBS_TYPE) + sizeof (UINT16);\r
+  DevOrder    = NULL;\r
+  Ptr         = NULL;\r
+  Status      = EFI_SUCCESS;\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
+      continue;\r
+    }\r
+\r
+    switch (BbsTable[Index].DeviceType) {\r
+    case BBS_FLOPPY:\r
+      FDCount++;\r
+      break;\r
+\r
+    case BBS_HARDDISK:\r
+      HDCount++;\r
+      break;\r
+\r
+    case BBS_CDROM:\r
+      CDCount++;\r
+      break;\r
+\r
+    case BBS_EMBED_NETWORK:\r
+      NETCount++;\r
+      break;\r
+\r
+    case BBS_BEV_DEVICE:\r
+      BEVCount++;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);\r
+\r
+  DevOrder = EfiAllocateZeroPool (TotalSize);\r
+  if (NULL == DevOrder) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Ptr                 = DevOrder;\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_FLOPPY;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (FDCount) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_HARDDISK;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (HDCount) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_CDROM;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (CDCount) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_EMBED_NETWORK;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (NETCount) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_BEV_DEVICE;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (BEVCount) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  VarLegacyDevOrder,\r
+                  &EfiLegacyDevOrderGuid,\r
+                  VAR_FLAG,\r
+                  TotalSize,\r
+                  DevOrder\r
+                  );\r
+  SafeFreePool (DevOrder);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+BdsUpdateLegacyDevOrder (\r
+  VOID\r
+  )\r
+/*++\r
+Format of LegacyDevOrder variable:\r
+|-----------------------------------------------------------------------------------------------------------------\r
+| BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ...\r
+|-----------------------------------------------------------------------------------------------------------------\r
+\r
+Length is a 16 bit integer, it indicates how many Indexes follows, including the size of itself.\r
+Index# is a 16 bit integer, the low byte of it stands for the index in BBS table\r
+           the high byte of it only have two value 0 and 0xFF, 0xFF means this device has been\r
+           disabled by user.\r
+--*/\r
+{\r
+  UINT8                     *DevOrder;\r
+  UINT8                     *NewDevOrder;\r
+  UINTN                     DevOrderSize;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  EFI_STATUS                Status;\r
+  UINT16                    HddCount;\r
+  UINT16                    BbsCount;\r
+  HDD_INFO                  *LocalHddInfo;\r
+  BBS_TABLE                 *LocalBbsTable;\r
+  UINTN                     Index;\r
+  UINTN                     Index2;\r
+  UINTN                     *Idx;\r
+  UINTN                     FDCount;\r
+  UINTN                     HDCount;\r
+  UINTN                     CDCount;\r
+  UINTN                     NETCount;\r
+  UINTN                     BEVCount;\r
+  UINTN                     TotalSize;\r
+  UINTN                     HeaderSize;\r
+  UINT8                     *Ptr;\r
+  UINT8                     *NewPtr;\r
+  UINT16                    *NewFDPtr;\r
+  UINT16                    *NewHDPtr;\r
+  UINT16                    *NewCDPtr;\r
+  UINT16                    *NewNETPtr;\r
+  UINT16                    *NewBEVPtr;\r
+  UINT16                    *NewDevPtr;\r
+  UINT16                    Length;\r
+  UINT16                    tmp;\r
+  UINTN                     FDIndex;\r
+  UINTN                     HDIndex;\r
+  UINTN                     CDIndex;\r
+  UINTN                     NETIndex;\r
+  UINTN                     BEVIndex;\r
+\r
+  LocalHddInfo  = NULL;\r
+  LocalBbsTable = NULL;\r
+  Idx           = NULL;\r
+  FDCount       = 0;\r
+  HDCount       = 0;\r
+  CDCount       = 0;\r
+  NETCount      = 0;\r
+  BEVCount      = 0;\r
+  TotalSize     = 0;\r
+  HeaderSize    = sizeof (BBS_TYPE) + sizeof (UINT16);\r
+  FDIndex       = 0;\r
+  HDIndex       = 0;\r
+  CDIndex       = 0;\r
+  NETIndex      = 0;\r
+  BEVIndex      = 0;\r
+  NewDevPtr     = NULL;\r
+\r
+  Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  LegacyBios->GetBbsInfo (\r
+                LegacyBios,\r
+                &HddCount,\r
+                &LocalHddInfo,\r
+                &BbsCount,\r
+                &LocalBbsTable\r
+                );\r
+\r
+  DevOrder = (UINT8 *) BdsLibGetVariableAndSize (\r
+                        VarLegacyDevOrder,\r
+                        &EfiLegacyDevOrderGuid,\r
+                        &DevOrderSize\r
+                        );\r
+  if (NULL == DevOrder) {\r
+    return BdsCreateDevOrder (LocalBbsTable, BbsCount);\r
+  }\r
+  //\r
+  // First we figure out how many boot devices with same device type respectively\r
+  //\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+        (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    switch (LocalBbsTable[Index].DeviceType) {\r
+    case BBS_FLOPPY:\r
+      FDCount++;\r
+      break;\r
+\r
+    case BBS_HARDDISK:\r
+      HDCount++;\r
+      break;\r
+\r
+    case BBS_CDROM:\r
+      CDCount++;\r
+      break;\r
+\r
+    case BBS_EMBED_NETWORK:\r
+      NETCount++;\r
+      break;\r
+\r
+    case BBS_BEV_DEVICE:\r
+      BEVCount++;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+\r
+  TotalSize += (HeaderSize + FDCount * sizeof (UINT16));\r
+  TotalSize += (HeaderSize + HDCount * sizeof (UINT16));\r
+  TotalSize += (HeaderSize + CDCount * sizeof (UINT16));\r
+  TotalSize += (HeaderSize + NETCount * sizeof (UINT16));\r
+  TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));\r
+\r
+  NewDevOrder = EfiAllocateZeroPool (TotalSize);\r
+  if (NULL == NewDevOrder) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewFDPtr  = (UINT16 *) (NewDevOrder + HeaderSize);\r
+  NewHDPtr  = (UINT16 *) ((UINT8 *) NewFDPtr + FDCount * sizeof (UINT16) + HeaderSize);\r
+  NewCDPtr  = (UINT16 *) ((UINT8 *) NewHDPtr + HDCount * sizeof (UINT16) + HeaderSize);\r
+  NewNETPtr = (UINT16 *) ((UINT8 *) NewCDPtr + CDCount * sizeof (UINT16) + HeaderSize);\r
+  NewBEVPtr = (UINT16 *) ((UINT8 *) NewNETPtr + NETCount * sizeof (UINT16) + HeaderSize);\r
+\r
+  //\r
+  // copy FD\r
+  //\r
+  Ptr                     = DevOrder;\r
+  NewPtr                  = NewDevOrder;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_FLOPPY\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewFDPtr[FDIndex] = *(UINT16 *) Ptr;\r
+    FDIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+  //\r
+  // copy HD\r
+  //\r
+  NewPtr                  = (UINT8 *) NewHDPtr - HeaderSize;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_HARDDISK\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewHDPtr[HDIndex] = *(UINT16 *) Ptr;\r
+    HDIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+  //\r
+  // copy CD\r
+  //\r
+  NewPtr                  = (UINT8 *) NewCDPtr - HeaderSize;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_CDROM\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewCDPtr[CDIndex] = *(UINT16 *) Ptr;\r
+    CDIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+  //\r
+  // copy NET\r
+  //\r
+  NewPtr                  = (UINT8 *) NewNETPtr - HeaderSize;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_EMBED_NETWORK\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewNETPtr[NETIndex] = *(UINT16 *) Ptr;\r
+    NETIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+  //\r
+  // copy BEV\r
+  //\r
+  NewPtr                  = (UINT8 *) NewBEVPtr - HeaderSize;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_BEV_DEVICE\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewBEVPtr[BEVIndex] = *(UINT16 *) Ptr;\r
+    BEVIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+        (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    switch (LocalBbsTable[Index].DeviceType) {\r
+    case BBS_FLOPPY:\r
+      Idx       = &FDIndex;\r
+      NewDevPtr = NewFDPtr;\r
+      break;\r
+\r
+    case BBS_HARDDISK:\r
+      Idx       = &HDIndex;\r
+      NewDevPtr = NewHDPtr;\r
+      break;\r
+\r
+    case BBS_CDROM:\r
+      Idx       = &CDIndex;\r
+      NewDevPtr = NewCDPtr;\r
+      break;\r
+\r
+    case BBS_EMBED_NETWORK:\r
+      Idx       = &NETIndex;\r
+      NewDevPtr = NewNETPtr;\r
+      break;\r
+\r
+    case BBS_BEV_DEVICE:\r
+      Idx       = &BEVIndex;\r
+      NewDevPtr = NewBEVPtr;\r
+      break;\r
+\r
+    default:\r
+      Idx = NULL;\r
+      break;\r
+    }\r
+    //\r
+    // at this point we have copied those valid indexes to new buffer\r
+    // and we should check if there is any new appeared boot device\r
+    //\r
+    if (Idx) {\r
+      for (Index2 = 0; Index2 < *Idx; Index2++) {\r
+        if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (Index2 == *Idx) {\r
+        //\r
+        // Index2 == *Idx means we didn't find Index\r
+        // so Index is a new appeared device's index in BBS table\r
+        // save it.\r
+        //\r
+        NewDevPtr[*Idx] = (UINT16) (Index & 0xFF);\r
+        (*Idx)++;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (FDCount) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < FDIndex - 1; Index++) {\r
+      if (0xFF00 != (NewFDPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < FDIndex; Index2++) {\r
+        if (0 == (NewFDPtr[Index2] & 0xFF00)) {\r
+          tmp               = NewFDPtr[Index];\r
+          NewFDPtr[Index]   = NewFDPtr[Index2];\r
+          NewFDPtr[Index2]  = tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (HDCount) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < HDIndex - 1; Index++) {\r
+      if (0xFF00 != (NewHDPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < HDIndex; Index2++) {\r
+        if (0 == (NewHDPtr[Index2] & 0xFF00)) {\r
+          tmp               = NewHDPtr[Index];\r
+          NewHDPtr[Index]   = NewHDPtr[Index2];\r
+          NewHDPtr[Index2]  = tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (CDCount) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < CDIndex - 1; Index++) {\r
+      if (0xFF00 != (NewCDPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < CDIndex; Index2++) {\r
+        if (0 == (NewCDPtr[Index2] & 0xFF00)) {\r
+          tmp               = NewCDPtr[Index];\r
+          NewCDPtr[Index]   = NewCDPtr[Index2];\r
+          NewCDPtr[Index2]  = tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (NETCount) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < NETIndex - 1; Index++) {\r
+      if (0xFF00 != (NewNETPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < NETIndex; Index2++) {\r
+        if (0 == (NewNETPtr[Index2] & 0xFF00)) {\r
+          tmp               = NewNETPtr[Index];\r
+          NewNETPtr[Index]  = NewNETPtr[Index2];\r
+          NewNETPtr[Index2] = tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (BEVCount) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < BEVIndex - 1; Index++) {\r
+      if (0xFF00 != (NewBEVPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < BEVIndex; Index2++) {\r
+        if (0 == (NewBEVPtr[Index2] & 0xFF00)) {\r
+          tmp               = NewBEVPtr[Index];\r
+          NewBEVPtr[Index]  = NewBEVPtr[Index2];\r
+          NewBEVPtr[Index2] = tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  SafeFreePool (DevOrder);\r
+\r
+  Status = gRT->SetVariable (\r
+                  VarLegacyDevOrder,\r
+                  &EfiLegacyDevOrderGuid,\r
+                  VAR_FLAG,\r
+                  TotalSize,\r
+                  NewDevOrder\r
+                  );\r
+  SafeFreePool (NewDevOrder);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+BdsSetBootPriority4SameTypeDev (\r
+  IN UINT16                                              DeviceType,\r
+  IN OUT BBS_TABLE                                       *LocalBbsTable,\r
+  IN OUT UINT16                                          *Priority\r
+  )\r
+/*++\r
+DeviceType           - BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM and so on\r
+LocalBbsTable       - BBS table instance\r
+Priority                 - As input arg, it is the start point of boot priority, as output arg, it is the start point of boot\r
+                              priority can be used next time.\r
+--*/\r
+{\r
+  UINT8   *DevOrder;\r
+\r
+  UINT8   *OrigBuffer;\r
+  UINT16  *DevIndex;\r
+  UINTN   DevOrderSize;\r
+  UINTN   DevCount;\r
+  UINTN   Index;\r
+\r
+  DevOrder = BdsLibGetVariableAndSize (\r
+              VarLegacyDevOrder,\r
+              &EfiLegacyDevOrderGuid,\r
+              &DevOrderSize\r
+              );\r
+  if (NULL == DevOrder) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  OrigBuffer = DevOrder;\r
+  while (DevOrder < OrigBuffer + DevOrderSize) {\r
+    if (DeviceType == * (BBS_TYPE *) DevOrder) {\r
+      break;\r
+    }\r
+\r
+    DevOrder += sizeof (BBS_TYPE);\r
+    DevOrder += *(UINT16 *) DevOrder;\r
+  }\r
+\r
+  if (DevOrder >= OrigBuffer + DevOrderSize) {\r
+    SafeFreePool (OrigBuffer);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  DevOrder += sizeof (BBS_TYPE);\r
+  DevCount  = (*((UINT16 *) DevOrder) - sizeof (UINT16)) / sizeof (UINT16);\r
+  DevIndex  = (UINT16 *) (DevOrder + sizeof (UINT16));\r
+  //\r
+  // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.\r
+  //\r
+  for (Index = 0; Index < DevCount; Index++) {\r
+    if ((DevIndex[Index] & 0xFF00) == 0xFF00) {\r
+      //\r
+      // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;\r
+      //\r
+    } else {\r
+      LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = *Priority;\r
+      (*Priority)++;\r
+    }\r
+  }\r
+\r
+  SafeFreePool (OrigBuffer);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+PrintBbsTable (\r
+  IN BBS_TABLE                      *LocalBbsTable\r
+  )\r
+{\r
+  UINT16  Idx;\r
+\r
+  DEBUG ((DEBUG_ERROR, "\n"));\r
+  DEBUG ((DEBUG_ERROR, " NO  Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));\r
+  DEBUG ((DEBUG_ERROR, "=============================================\n"));\r
+  for (Idx = 0; Idx < MAX_BBS_ENTRIES; Idx++) {\r
+    if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) ||\r
+        (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) ||\r
+        (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    DEBUG (\r
+      (DEBUG_ERROR,\r
+      " %02x: %04x %02x/%02x/%02x %02x/02%x %04x %04x %04x:%04x\n",\r
+      (UINTN) Idx,\r
+      (UINTN) LocalBbsTable[Idx].BootPriority,\r
+      (UINTN) LocalBbsTable[Idx].Bus,\r
+      (UINTN) LocalBbsTable[Idx].Device,\r
+      (UINTN) LocalBbsTable[Idx].Function,\r
+      (UINTN) LocalBbsTable[Idx].Class,\r
+      (UINTN) LocalBbsTable[Idx].SubClass,\r
+      (UINTN) LocalBbsTable[Idx].DeviceType,\r
+      (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags,\r
+      (UINTN) LocalBbsTable[Idx].BootHandlerSegment,\r
+      (UINTN) LocalBbsTable[Idx].BootHandlerOffset,\r
+      (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset),\r
+      (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset))\r
+      );\r
+  }\r
+\r
+  DEBUG ((DEBUG_ERROR, "\n"));\r
+}\r
+\r
+EFI_STATUS\r
+BdsRefreshBbsTableForBoot (\r
+  IN BDS_COMMON_OPTION        *Entry\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINT16                    HddCount;\r
+  UINT16                    BbsCount;\r
+  HDD_INFO                  *LocalHddInfo;\r
+  BBS_TABLE                 *LocalBbsTable;\r
+  UINT16                    DevType;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINTN                     Index;\r
+  UINT16                    Priority;\r
+  UINT16                    *BootOrder;\r
+  UINTN                     BootOrderSize;\r
+  UINT8                     *BootOptionVar;\r
+  UINTN                     BootOptionSize;\r
+  UINT16                    BootOption[100];\r
+  UINT8                     *Ptr;\r
+  UINT16                    DevPathLen;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
+\r
+  HddCount      = 0;\r
+  BbsCount      = 0;\r
+  LocalHddInfo  = NULL;\r
+  LocalBbsTable = NULL;\r
+  DevType       = BBS_UNKNOWN;\r
+\r
+  Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  LegacyBios->GetBbsInfo (\r
+                LegacyBios,\r
+                &HddCount,\r
+                &LocalHddInfo,\r
+                &BbsCount,\r
+                &LocalBbsTable\r
+                );\r
+  //\r
+  // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY\r
+  // We will set them according to the settings setup by user\r
+  //\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) ||\r
+        (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) ||\r
+         (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) {\r
+      LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
+    }\r
+  }\r
+  //\r
+  // boot priority always starts at 0\r
+  //\r
+  Priority = 0;\r
+  if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) {\r
+    //\r
+    // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.\r
+    //\r
+    DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType;\r
+    Status = BdsSetBootPriority4SameTypeDev (\r
+              DevType,\r
+              LocalBbsTable,\r
+              &Priority\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+  //\r
+  // we have to set the boot priority for other BBS entries with different device types\r
+  //\r
+  BootOrder = (UINT16 *) BdsLibGetVariableAndSize (\r
+                          L"BootOrder",\r
+                          &gEfiGlobalVariableGuid,\r
+                          &BootOrderSize\r
+                          );\r
+  for (Index = 0; BootOrder && Index < BootOrderSize / sizeof (UINT16); Index++) {\r
+    UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+    BootOptionVar = BdsLibGetVariableAndSize (\r
+                      BootOption,\r
+                      &gEfiGlobalVariableGuid,\r
+                      &BootOptionSize\r
+                      );\r
+    if (NULL == BootOptionVar) {\r
+      continue;\r
+    }\r
+\r
+    Ptr = BootOptionVar;\r
+\r
+    Ptr += sizeof (UINT32);\r
+    DevPathLen = *(UINT16 *) Ptr;\r
+    Ptr += sizeof (UINT16);\r
+    Ptr += StrSize ((UINT16 *) Ptr);\r
+    DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+    if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) {\r
+      SafeFreePool (BootOptionVar);\r
+      continue;\r
+    }\r
+\r
+    Ptr += DevPathLen;\r
+    if (DevType == ((BBS_TABLE *) Ptr)->DeviceType) {\r
+      //\r
+      // We don't want to process twice for a device type\r
+      //\r
+      SafeFreePool (BootOptionVar);\r
+      continue;\r
+    }\r
+\r
+    Status = BdsSetBootPriority4SameTypeDev (\r
+              ((BBS_TABLE *) Ptr)->DeviceType,\r
+              LocalBbsTable,\r
+              &Priority\r
+              );\r
+    SafeFreePool (BootOptionVar);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (BootOrder) {\r
+    SafeFreePool (BootOrder);\r
+  }\r
+  //\r
+  // For debug\r
+  //\r
+  PrintBbsTable (LocalBbsTable);\r
+\r
+  return Status;\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h b/MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h
new file mode 100644 (file)
index 0000000..532223f
--- /dev/null
@@ -0,0 +1,78 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  BBSsupport.h\r
+\r
+Abstract:\r
+\r
+  declares interface functions\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_BDS_BBS_SUPPORT_H\r
+#define _EFI_BDS_BBS_SUPPORT_H\r
+\r
+#include "BootMaint.h"\r
+//\r
+// Bugbug: Candidate for a PCD entries\r
+//\r
+#define MAX_BBS_ENTRIES 0x100\r
+\r
+VOID\r
+BdsBuildLegacyDevNameString (\r
+  IN BBS_TABLE                     *CurBBSEntry,\r
+  IN UINTN                         Index,\r
+  IN UINTN                         BufSize,\r
+  OUT CHAR16                       *BootString\r
+  );\r
+\r
+EFI_STATUS\r
+BdsDeleteAllInvalidLegacyBootOptions (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsAddNonExistingLegacyBootOptions (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Add the legacy boot options from BBS table if they do not exist.\r
+\r
+Arguments:\r
+\r
+  None.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS       - The boot options are added successfully or they are already in boot options.\r
+  others            - An error occurred when creating legacy boot options.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+BdsUpdateLegacyDevOrder (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsRefreshBbsTableForBoot (\r
+  IN BDS_COMMON_OPTION        *Entry\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr b/MdeModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr
new file mode 100644 (file)
index 0000000..93cbbea
--- /dev/null
@@ -0,0 +1,391 @@
+// *++\r
+//\r
+// Copyright (c) 2004 - 2007, Intel Corporation\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution.  The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// Module Name:\r
+//\r
+//   bm.vfr\r
+//\r
+// Abstract:\r
+//\r
+//   Boot Maintenance Utility Formset\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+\r
+#include "FormGuid.h"\r
+\r
+#define LABEL_END   0xffff\r
+\r
+formset\r
+  guid = BOOT_MAINT_FORMSET_GUID,\r
+  title = STRING_TOKEN(STR_FORM_MAIN_TITLE),\r
+  help = STRING_TOKEN(STR_NULL_STRING),\r
+  class = 0,\r
+  subclass = 0,\r
+\r
+  varstore BMM_FAKE_NV_DATA,\r
+    varid = VARSTORE_ID_BOOT_MAINT,\r
+    name = BmmData,\r
+    guid = BOOT_MAINT_FORMSET_GUID;\r
+\r
+  form formid = FORM_MAIN_ID,\r
+       title = STRING_TOKEN(STR_FORM_MAIN_TITLE);\r
+\r
+    goto FORM_BOOT_SETUP_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_BOOT_SETUP_HELP),\r
+         flags = INTERACTIVE,\r
+         key = FORM_BOOT_SETUP_ID;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+    goto FORM_DRIVER_SETUP_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_DRIVER_SETUP_HELP),\r
+         flags = INTERACTIVE,\r
+         key = FORM_DRIVER_SETUP_ID;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+    goto FORM_CON_MAIN_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_CON_MAIN_HELP),\r
+         flags = INTERACTIVE,\r
+         key = FORM_CON_MAIN_ID;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+    text\r
+         help   = STRING_TOKEN(STR_BOOT_FROM_FILE_HELP),\r
+         text   = STRING_TOKEN(STR_BOOT_FROM_FILE),\r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_VALUE_BOOT_FROM_FILE;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+//    label FORM_MAIN_ID;\r
+\r
+    goto FORM_BOOT_NEXT_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_BOOT_NEXT_HELP),\r
+         flags = INTERACTIVE,\r
+         key = FORM_BOOT_NEXT_ID;\r
+\r
+    goto FORM_TIME_OUT_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_TIME_OUT_HELP),\r
+         flags = INTERACTIVE,\r
+         key = FORM_TIME_OUT_ID;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+    goto FORM_MAIN_ID,\r
+         prompt = STRING_TOKEN(STR_RESET),\r
+         help = STRING_TOKEN(STR_RESET),\r
+         flags = INTERACTIVE,\r
+         key = FORM_RESET;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_BOOT_SETUP_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE);\r
+\r
+       goto FORM_MAIN_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+            help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+            //flags = INTERACTIVE,\r
+            //key = FORM_MAIN_ID;\r
+\r
+       goto FORM_BOOT_ADD_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_BOOT_ADD_HELP),\r
+            flags = INTERACTIVE,\r
+            key = FORM_BOOT_ADD_ID;\r
+\r
+       goto FORM_BOOT_DEL_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+            flags = INTERACTIVE,\r
+            key = FORM_BOOT_DEL_ID;\r
+\r
+       goto FORM_BOOT_CHG_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+            flags = INTERACTIVE,\r
+            key = FORM_BOOT_CHG_ID;\r
+\r
+       subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+           //\r
+          // We will add "Select Legacy Boot Floppy Drive" and "Select Legacy Boot Hard Drive"\r
+          // here dynamically\r
+          //\r
+       label FORM_BOOT_LEGACY_DEVICE_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_DRIVER_SETUP_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE);\r
+\r
+       goto FORM_MAIN_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+            help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+            //help = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+            //flags = INTERACTIVE,\r
+            //key = FORM_MAIN_ID;\r
+\r
+       goto FORM_DRV_ADD_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_DRV_ADD_HELP),\r
+            flags = INTERACTIVE,\r
+            key = FORM_DRV_ADD_ID;\r
+\r
+       goto FORM_DRV_DEL_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+            flags = INTERACTIVE,\r
+            key = FORM_DRV_DEL_ID;\r
+\r
+       goto FORM_DRV_CHG_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+            flags = INTERACTIVE,\r
+            key = FORM_DRV_CHG_ID;\r
+  endform;\r
+\r
+  form formid = FORM_BOOT_ADD_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+       label FORM_BOOT_ADD_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_BOOT_DEL_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE);\r
+\r
+       label FORM_BOOT_DEL_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_BOOT_CHG_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE);\r
+\r
+       label FORM_BOOT_CHG_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_BOOT_NEXT_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE);\r
+\r
+       label FORM_BOOT_NEXT_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_TIME_OUT_ID,\r
+       title = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE);\r
+\r
+       label FORM_TIME_OUT_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_DRV_ADD_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE);\r
+\r
+       goto FORM_MAIN_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+            help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+            //flags = INTERACTIVE,\r
+            //key = FORM_MAIN_ID;\r
+\r
+       goto FORM_DRV_ADD_FILE_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE),\r
+            flags = INTERACTIVE,\r
+            key = FORM_DRV_ADD_FILE_ID;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_DRV_DEL_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE);\r
+\r
+       label FORM_DRV_DEL_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_DRV_CHG_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE);\r
+\r
+       label FORM_DRV_CHG_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_CON_MAIN_ID,\r
+       title = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE);\r
+\r
+       goto FORM_MAIN_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+       help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+       //flags = INTERACTIVE,\r
+       //key = FORM_MAIN_ID;\r
+\r
+       goto FORM_CON_IN_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_CON_IN_TITLE),\r
+       help = STRING_TOKEN(STR_FORM_CON_IN_HELP),\r
+       flags = INTERACTIVE,\r
+       key = FORM_CON_IN_ID;\r
+\r
+       goto FORM_CON_OUT_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_CON_OUT_TITLE),\r
+       help = STRING_TOKEN(STR_FORM_CON_OUT_HELP),\r
+       flags = INTERACTIVE,\r
+       key = FORM_CON_OUT_ID;\r
+\r
+       goto FORM_CON_ERR_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_STD_ERR_TITLE),\r
+       help = STRING_TOKEN(STR_FORM_STD_ERR_HELP),\r
+       flags = INTERACTIVE,\r
+       key = FORM_CON_ERR_ID;\r
+\r
+       goto FORM_CON_MODE_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_MODE_TITLE),\r
+       help = STRING_TOKEN(STR_FORM_MODE_HELP),\r
+       flags = INTERACTIVE,\r
+       key = FORM_CON_MODE_ID;\r
+\r
+       goto FORM_CON_COM_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_COM_TITLE),\r
+       help = STRING_TOKEN(STR_FORM_COM_HELP),\r
+       flags = INTERACTIVE,\r
+       key = FORM_CON_COM_ID;\r
+  endform;\r
+\r
+  form formid = FORM_CON_MODE_ID,\r
+       title = STRING_TOKEN(STR_FORM_MODE_TITLE);\r
+\r
+       label FORM_CON_MODE_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_CON_COM_ID,\r
+       title = STRING_TOKEN(STR_FORM_COM_TITLE);\r
+\r
+       label FORM_CON_COM_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_CON_COM_SETUP_ID,\r
+       title = STRING_TOKEN(STR_CON_COM_SETUP);\r
+\r
+       label FORM_CON_COM_SETUP_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_FILE_SEEK_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+       label FORM_FILE_SEEK_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_FILE_NEW_SEEK_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+       label FORM_FILE_NEW_SEEK_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_DRV_ADD_FILE_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE);\r
+\r
+       label FORM_DRV_ADD_FILE_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_DRV_ADD_HANDLE_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_HANDLE_TITLE);\r
+\r
+       label FORM_DRV_ADD_HANDLE_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_DRV_ADD_HANDLE_DESC_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);\r
+\r
+       label FORM_DRV_ADD_HANDLE_DESC_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_CON_IN_ID,\r
+       title = STRING_TOKEN(STR_FORM_CON_IN_TITLE);\r
+\r
+       label FORM_CON_IN_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_CON_OUT_ID,\r
+       title = STRING_TOKEN(STR_FORM_CON_OUT_TITLE);\r
+\r
+       label FORM_CON_OUT_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_CON_ERR_ID,\r
+       title = STRING_TOKEN(STR_FORM_STD_ERR_TITLE);\r
+\r
+       label FORM_CON_ERR_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_SET_FD_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_FD_ORDER_TITLE);\r
+\r
+       label FORM_SET_FD_ORDER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_SET_HD_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_HD_ORDER_TITLE);\r
+\r
+       label FORM_SET_HD_ORDER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_SET_CD_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_CD_ORDER_TITLE);\r
+\r
+       label FORM_SET_CD_ORDER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_SET_NET_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_NET_ORDER_TITLE);\r
+\r
+       label FORM_SET_NET_ORDER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_SET_BEV_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_BEV_ORDER_TITLE);\r
+\r
+       label FORM_SET_BEV_ORDER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+endformset;\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/BmLib.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/BmLib.c
new file mode 100644 (file)
index 0000000..e9a7409
--- /dev/null
@@ -0,0 +1,563 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  bmlib.c\r
+\r
+AgBStract:\r
+\r
+  Boot Maintainence Helper functions\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+VOID *\r
+EfiAllocateZeroPool (\r
+  IN UINTN            Size\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Wrap original AllocatePool gBS call\r
+  and ZeroMem gBS call into a single\r
+  function in order to decrease code length\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  Valid pointer to the allocated buffer\r
+  Null for failure\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  VOID        *Ptr;\r
+  Status = gBS->AllocatePool (EfiBootServicesData, Size, &Ptr);\r
+  if (EFI_ERROR (Status)) {\r
+    Ptr = NULL;\r
+    return Ptr;\r
+  }\r
+\r
+  ZeroMem (Ptr, Size);\r
+  return Ptr;\r
+}\r
+\r
+EFI_STATUS\r
+EfiLibLocateProtocol (\r
+  IN  EFI_GUID    *ProtocolGuid,\r
+  OUT VOID        **Interface\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Find the first instance of this Protocol\r
+  in the system and return it's interface\r
+\r
+Arguments:\r
+\r
+  ProtocolGuid    - Provides the protocol to search for\r
+  Interface       - On return, a pointer to the first interface\r
+                    that matches ProtocolGuid\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS     - A protocol instance matching ProtocolGuid was found\r
+\r
+  EFI_NOT_FOUND   - No protocol instances were found that match ProtocolGuid\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  ProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) Interface\r
+                  );\r
+  return Status;\r
+}\r
+\r
+EFI_FILE_HANDLE\r
+EfiLibOpenRoot (\r
+  IN EFI_HANDLE                   DeviceHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Function opens and returns a file handle to the root directory of a volume.\r
+\r
+Arguments:\r
+\r
+  DeviceHandle         - A handle for a device\r
+\r
+Returns:\r
+\r
+  A valid file handle or NULL is returned\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
+  EFI_FILE_HANDLE                 File;\r
+\r
+  File = NULL;\r
+\r
+  //\r
+  // File the file system interface to the device\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  DeviceHandle,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  (VOID *) &Volume\r
+                  );\r
+\r
+  //\r
+  // Open the root directory of the volume\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = Volume->OpenVolume (\r
+                      Volume,\r
+                      &File\r
+                      );\r
+  }\r
+  //\r
+  // Done\r
+  //\r
+  return EFI_ERROR (Status) ? NULL : File;\r
+}\r
+\r
+BOOLEAN\r
+EfiGrowBuffer (\r
+  IN OUT EFI_STATUS   *Status,\r
+  IN OUT VOID         **Buffer,\r
+  IN UINTN            BufferSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Helper function called as part of the code needed\r
+    to allocate the proper sized buffer for various\r
+    EFI interfaces.\r
+\r
+Arguments:\r
+\r
+    Status      - Current status\r
+\r
+    Buffer      - Current allocated buffer, or NULL\r
+\r
+    BufferSize  - Current buffer size needed\r
+\r
+Returns:\r
+\r
+    TRUE - if the buffer was reallocated and the caller\r
+    should try the API again.\r
+\r
+--*/\r
+{\r
+  BOOLEAN TryAgain;\r
+\r
+  //\r
+  // If this is an initial request, buffer will be null with a new buffer size\r
+  //\r
+  if (!*Buffer && BufferSize) {\r
+    *Status = EFI_BUFFER_TOO_SMALL;\r
+  }\r
+  //\r
+  // If the status code is "buffer too small", resize the buffer\r
+  //\r
+  TryAgain = FALSE;\r
+  if (*Status == EFI_BUFFER_TOO_SMALL) {\r
+\r
+    SafeFreePool (*Buffer);\r
+\r
+    *Buffer = EfiAllocateZeroPool (BufferSize);\r
+\r
+    if (*Buffer) {\r
+      TryAgain = TRUE;\r
+    } else {\r
+      *Status = EFI_OUT_OF_RESOURCES;\r
+    }\r
+  }\r
+  //\r
+  // If there's an error, free the buffer\r
+  //\r
+  if (!TryAgain && EFI_ERROR (*Status) && *Buffer) {\r
+    SafeFreePool (*Buffer);\r
+    *Buffer = NULL;\r
+  }\r
+\r
+  return TryAgain;\r
+}\r
+\r
+VOID *\r
+EfiLibGetVariable (\r
+  IN CHAR16               *Name,\r
+  IN EFI_GUID             *VendorGuid\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Function returns the value of the specified variable.\r
+\r
+Arguments:\r
+  Name                - A Null-terminated Unicode string that is\r
+                        the name of the vendor's variable.\r
+\r
+  VendorGuid          - A unique identifier for the vendor.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINTN VarSize;\r
+\r
+  return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize);\r
+}\r
+\r
+EFI_STATUS\r
+EfiLibDeleteVariable (\r
+  IN CHAR16   *VarName,\r
+  IN EFI_GUID *VarGuid\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Function deletes the variable specified by VarName and VarGuid.\r
+\r
+Arguments:\r
+  VarName              - A Null-terminated Unicode string that is\r
+                         the name of the vendor's variable.\r
+\r
+  VendorGuid           - A unique identifier for the vendor.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS          - The variable was found and removed\r
+\r
+  EFI_UNSUPPORTED      - The variable store was inaccessible\r
+\r
+  EFI_OUT_OF_RESOURCES - The temporary buffer was not available\r
+\r
+  EFI_NOT_FOUND        - The variable was not found\r
+\r
+--*/\r
+{\r
+  VOID        *VarBuf;\r
+  EFI_STATUS  Status;\r
+\r
+  VarBuf  = EfiLibGetVariable (VarName, VarGuid);\r
+  Status  = EFI_NOT_FOUND;\r
+\r
+  if (VarBuf) {\r
+    //\r
+    // Delete variable from Storage\r
+    //\r
+    Status = gRT->SetVariable (VarName, VarGuid, VAR_FLAG, 0, NULL);\r
+    ASSERT (!EFI_ERROR (Status));\r
+    SafeFreePool (VarBuf);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *\r
+EfiLibFileSystemVolumeLabelInfo (\r
+  IN EFI_FILE_HANDLE      FHand\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Function gets the file system information from an open file descriptor,\r
+  and stores it in a buffer allocated from pool.\r
+\r
+Arguments:\r
+\r
+  Fhand         - A file handle\r
+\r
+Returns:\r
+\r
+  A pointer to a buffer with file information or NULL is returned\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;\r
+  UINTN                             BufferSize;\r
+  //\r
+  // Initialize for GrowBuffer loop\r
+  //\r
+  Buffer      = NULL;\r
+  BufferSize  = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;\r
+\r
+  //\r
+  // Call the real function\r
+  //\r
+  while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
+    Status = FHand->GetInfo (\r
+                      FHand,\r
+                      &gEfiFileSystemVolumeLabelInfoIdGuid,\r
+                      &BufferSize,\r
+                      Buffer\r
+                      );\r
+  }\r
+\r
+  return Buffer;\r
+}\r
+\r
+CHAR16 *\r
+EfiStrDuplicate (\r
+  IN CHAR16   *Src\r
+  )\r
+{\r
+  CHAR16  *Dest;\r
+  UINTN   Size;\r
+\r
+  Size  = StrSize (Src);\r
+  Dest  = EfiAllocateZeroPool (Size);\r
+  ASSERT (Dest != NULL);\r
+  if (Dest) {\r
+    CopyMem (Dest, Src, Size);\r
+  }\r
+\r
+  return Dest;\r
+}\r
+\r
+EFI_FILE_INFO *\r
+EfiLibFileInfo (\r
+  IN EFI_FILE_HANDLE      FHand\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Function gets the file information from an open file descriptor, and stores it\r
+  in a buffer allocated from pool.\r
+\r
+Arguments:\r
+\r
+  Fhand         - A file handle\r
+\r
+Returns:\r
+\r
+  A pointer to a buffer with file information or NULL is returned\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  EFI_FILE_INFO *Buffer;\r
+  UINTN         BufferSize;\r
+\r
+  //\r
+  // Initialize for GrowBuffer loop\r
+  //\r
+  Buffer      = NULL;\r
+  BufferSize  = SIZE_OF_EFI_FILE_INFO + 200;\r
+\r
+  //\r
+  // Call the real function\r
+  //\r
+  while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
+    Status = FHand->GetInfo (\r
+                      FHand,\r
+                      &gEfiFileInfoGuid,\r
+                      &BufferSize,\r
+                      Buffer\r
+                      );\r
+  }\r
+\r
+  return Buffer;\r
+}\r
+\r
+UINTN\r
+EfiDevicePathInstanceCount (\r
+  IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Function is used to determine the number of device path instances\r
+  that exist in a device path.\r
+\r
+Arguments:\r
+  DevicePath           - A pointer to a device path data structure.\r
+\r
+Returns:\r
+\r
+  This function counts and returns the number of device path instances\r
+  in DevicePath.\r
+\r
+--*/\r
+{\r
+  UINTN Count;\r
+  UINTN Size;\r
+\r
+  Count = 0;\r
+  while (GetNextDevicePathInstance (&DevicePath, &Size)) {\r
+    Count += 1;\r
+  }\r
+\r
+  return Count;\r
+}\r
+\r
+VOID *\r
+EfiReallocatePool (\r
+  IN VOID                 *OldPool,\r
+  IN UINTN                OldSize,\r
+  IN UINTN                NewSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Adjusts the size of a previously allocated buffer.\r
+\r
+Arguments:\r
+  OldPool               - A pointer to the buffer whose size is being adjusted.\r
+  OldSize               - The size of the current buffer.\r
+  NewSize               - The size of the new buffer.\r
+\r
+Returns:\r
+\r
+  EFI_SUCEESS           - The requested number of bytes were allocated.\r
+\r
+  EFI_OUT_OF_RESOURCES  - The pool requested could not be allocated.\r
+\r
+  EFI_INVALID_PARAMETER - The buffer was invalid.\r
+\r
+--*/\r
+{\r
+  VOID  *NewPool;\r
+\r
+  NewPool = NULL;\r
+  if (NewSize) {\r
+    NewPool = EfiAllocateZeroPool (NewSize);\r
+  }\r
+\r
+  if (OldPool) {\r
+    if (NewPool) {\r
+      CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
+    }\r
+\r
+    SafeFreePool (OldPool);\r
+  }\r
+\r
+  return NewPool;\r
+}\r
+\r
+BOOLEAN\r
+TimeCompare (\r
+  IN EFI_TIME               *FirstTime,\r
+  IN EFI_TIME               *SecondTime\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Compare two EFI_TIME data.\r
+\r
+Arguments:\r
+\r
+  FirstTime         - A pointer to the first EFI_TIME data.\r
+  SecondTime        - A pointer to the second EFI_TIME data.\r
+\r
+Returns:\r
+  TRUE              The FirstTime is not later than the SecondTime.\r
+  FALSE             The FirstTime is later than the SecondTime.\r
+\r
+--*/\r
+{\r
+  if (FirstTime->Year != SecondTime->Year) {\r
+    return (BOOLEAN) (FirstTime->Year < SecondTime->Year);\r
+  } else if (FirstTime->Month != SecondTime->Month) {\r
+    return (BOOLEAN) (FirstTime->Month < SecondTime->Month);\r
+  } else if (FirstTime->Day != SecondTime->Day) {\r
+    return (BOOLEAN) (FirstTime->Day < SecondTime->Day);\r
+  } else if (FirstTime->Hour != SecondTime->Hour) {\r
+    return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);\r
+  } else if (FirstTime->Minute != SecondTime->Minute) {\r
+    return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute);\r
+  } else if (FirstTime->Second != SecondTime->Second) {\r
+    return (BOOLEAN) (FirstTime->Second < SecondTime->Second);\r
+  }\r
+\r
+  return (BOOLEAN) (FirstTime->Nanosecond <= SecondTime->Nanosecond);\r
+}\r
+\r
+UINT16 *\r
+EfiLibStrFromDatahub (\r
+  IN EFI_DEVICE_PATH_PROTOCOL                 *DevPath\r
+  )\r
+{\r
+  EFI_STATUS                                  Status;\r
+  UINT16                                      *Desc;\r
+  EFI_DATA_HUB_PROTOCOL                       *Datahub;\r
+  UINT64                                      Count;\r
+  EFI_DATA_RECORD_HEADER                      *Record;\r
+  EFI_SUBCLASS_TYPE1_HEADER                   *DataHdr;\r
+  EFI_GUID                                    MiscGuid = EFI_MISC_SUBCLASS_GUID;\r
+  EFI_MISC_ONBOARD_DEVICE_DATA                *ob;\r
+  EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *Port;\r
+  EFI_TIME                                    CurTime;\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiDataHubProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &Datahub\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  Status = gRT->GetTime (&CurTime, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  Count = 0;\r
+  do {\r
+    Status = Datahub->GetNextRecord (Datahub, &Count, NULL, &Record);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA && CompareGuid (&Record->DataRecordGuid, &MiscGuid)) {\r
+      //\r
+      // This record is what we need\r
+      //\r
+      DataHdr = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
+      if (EFI_MISC_ONBOARD_DEVICE_RECORD_NUMBER == DataHdr->RecordType) {\r
+        ob = (EFI_MISC_ONBOARD_DEVICE_DATA *) (DataHdr + 1);\r
+        if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &ob->OnBoardDevicePath, DevPath)) {\r
+          GetProducerString (&Record->ProducerName, ob->OnBoardDeviceDescription, &Desc);\r
+          return Desc;\r
+        }\r
+      }\r
+\r
+      if (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER == DataHdr->RecordType) {\r
+        Port = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) (DataHdr + 1);\r
+        if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Port->PortPath, DevPath)) {\r
+          GetProducerString (&Record->ProducerName, Port->PortExternalConnectorDesignator, &Desc);\r
+          return Desc;\r
+        }\r
+      }\r
+    }\r
+\r
+  } while (TimeCompare (&Record->LogTime, &CurTime) && Count != 0);\r
+\r
+  return NULL;\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni b/MdeModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni
new file mode 100644 (file)
index 0000000..a332fb6
Binary files /dev/null and b/MdeModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni differ
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c
new file mode 100644 (file)
index 0000000..9cf2a9d
--- /dev/null
@@ -0,0 +1,1331 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  BootMaint.c\r
+\r
+Abstract:\r
+\r
+  Boot Maintainence Main File\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+#include "FormGuid.h"\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+EFI_GUID EfiLegacyDevOrderGuid = EFI_LEGACY_DEV_ORDER_VARIABLE_GUID;\r
+EFI_GUID mBootMaintGuid = BOOT_MAINT_FORMSET_GUID;\r
+EFI_GUID mFileExplorerGuid = FILE_EXPLORE_FORMSET_GUID;\r
+\r
+CHAR16  mBootMaintStorageName[] = L"BmData";\r
+CHAR16  mFileExplorerStorageName[] = L"FeData";\r
+\r
+VOID\r
+InitAllMenu (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  );\r
+\r
+VOID\r
+FreeAllMenu (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+CreateMenuStringToken (\r
+  IN BMM_CALLBACK_DATA                *CallbackData,\r
+  IN EFI_HII_HANDLE                   HiiHandle,\r
+  IN BM_MENU_OPTION                   *MenuOption\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Create string tokens for a menu from its help strings and display strings\r
+\r
+Arguments:\r
+  HiiHandle       - Hii Handle of the package to be updated.\r
+  MenuOption      - The Menu whose string tokens need to be created\r
+\r
+Returns:\r
+  EFI_SUCCESS     - string tokens created successfully\r
+  others          - contain some errors\r
+\r
+--*/\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINTN         Index;\r
+\r
+  for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);\r
+\r
+    IfrLibNewString (\r
+      HiiHandle,\r
+      &NewMenuEntry->DisplayStringToken,\r
+      NewMenuEntry->DisplayString\r
+      );\r
+\r
+    if (NULL == NewMenuEntry->HelpString) {\r
+      NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;\r
+    } else {\r
+      IfrLibNewString (\r
+        HiiHandle,\r
+        &NewMenuEntry->HelpStringToken,\r
+        NewMenuEntry->HelpString\r
+        );\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BootMaintExtractConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Request,\r
+  OUT EFI_STRING                             *Progress,\r
+  OUT EFI_STRING                             *Results\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    This function allows a caller to extract the current configuration for one\r
+    or more named elements from the target driver.\r
+\r
+  Arguments:\r
+    This       - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+    Request    - A null-terminated Unicode string in <ConfigRequest> format.\r
+    Progress   - On return, points to a character in the Request string.\r
+                 Points to the string's null terminator if request was successful.\r
+                 Points to the most recent '&' before the first failing name/value\r
+                 pair (or the beginning of the string if the failure is in the\r
+                 first name/value pair) if the request was not successful.\r
+    Results    - A null-terminated Unicode string in <ConfigAltResp> format which\r
+                 has all values filled in for the names in the Request string.\r
+                 String to be allocated by the called function.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The Results is filled with the requested values.\r
+    EFI_OUT_OF_RESOURCES  - Not enough memory to store the results.\r
+    EFI_INVALID_PARAMETER - Request is NULL, illegal syntax, or unknown name.\r
+    EFI_NOT_FOUND         - Routing data doesn't match any storage in this driver.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS         Status;\r
+  UINTN              BufferSize;\r
+  BMM_CALLBACK_DATA  *Private;\r
+\r
+  Private = BMM_CALLBACK_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
+  //\r
+  BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
+  Status = gHiiConfigRouting->BlockToConfig (\r
+                                gHiiConfigRouting,\r
+                                Request,\r
+                                (UINT8 *) &Private->BmmFakeNvData,\r
+                                BufferSize,\r
+                                Results,\r
+                                Progress\r
+                                );\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BootMaintCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    This function processes the results of changes in configuration.\r
+\r
+  Arguments:\r
+    This          - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+    Action        - Specifies the type of action taken by the browser.\r
+    QuestionId    - A unique value which is sent to the original exporting driver\r
+                    so that it can identify the type of data to expect.\r
+    Type          - The type of value for the question.\r
+    Value         - A pointer to the data being sent to the original exporting driver.\r
+    ActionRequest - On return, points to the action requested by the callback function.\r
+\r
+  Returns:\r
+    EFI_SUCCESS          - The callback successfully handled the action.\r
+    EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.\r
+    EFI_DEVICE_ERROR     - The variable could not be saved.\r
+    EFI_UNSUPPORTED      - The specified Action is not supported by the callback.\r
+\r
+--*/\r
+{\r
+  BMM_CALLBACK_DATA *Private;\r
+  BM_MENU_ENTRY     *NewMenuEntry;\r
+  BMM_FAKE_NV_DATA  *CurrentFakeNVMap;\r
+  EFI_STATUS        Status;\r
+  UINTN             OldValue;\r
+  UINTN             NewValue;\r
+  UINTN             Number;\r
+  UINTN             Pos;\r
+  UINTN             Bit;\r
+  UINT16            NewValuePos;\r
+  UINT16            Index2;\r
+  UINT16            Index;\r
+  UINT8             *OldLegacyDev;\r
+  UINT8             *NewLegacyDev;\r
+  UINT8             *DisMap;\r
+  EFI_FORM_ID       FormId;\r
+  UINTN             BufferSize;\r
+\r
+  if ((Value == NULL) || (ActionRequest == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  OldValue       = 0;\r
+  NewValue       = 0;\r
+  Number         = 0;\r
+  OldLegacyDev   = NULL;\r
+  NewLegacyDev   = NULL;\r
+  NewValuePos    = 0;\r
+  DisMap         = NULL;\r
+  *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+  Private        = BMM_CALLBACK_DATA_FROM_THIS (This);\r
+  UpdatePageId (Private, QuestionId);\r
+\r
+  //\r
+  // Retrive uncommitted data from Form Browser\r
+  //\r
+  CurrentFakeNVMap = &Private->BmmFakeNvData;\r
+  BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
+  Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) CurrentFakeNVMap);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // need to be subtituded.\r
+  //\r
+  // Update Select FD/HD/CD/NET/BEV Order Form\r
+  //\r
+  if (FORM_SET_FD_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_HD_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_CD_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_NET_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_BEV_ORDER_ID == Private->BmmPreviousPageId ||\r
+      ((FORM_BOOT_SETUP_ID == Private->BmmPreviousPageId) &&\r
+      (QuestionId >= LEGACY_FD_QUESTION_ID) &&\r
+       (QuestionId < (LEGACY_BEV_QUESTION_ID + 100)) )\r
+      ) {\r
+\r
+    DisMap  = Private->BmmOldFakeNVData.DisableMap;\r
+\r
+    FormId  = Private->BmmPreviousPageId;\r
+    if (FormId == FORM_BOOT_SETUP_ID) {\r
+      FormId = Private->BmmCurrentPageId;\r
+    }\r
+\r
+    switch (FormId) {\r
+    case FORM_SET_FD_ORDER_ID:\r
+      Number        = (UINT16) LegacyFDMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyFD;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyFD;\r
+      break;\r
+\r
+    case FORM_SET_HD_ORDER_ID:\r
+      Number        = (UINT16) LegacyHDMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyHD;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyHD;\r
+      break;\r
+\r
+    case FORM_SET_CD_ORDER_ID:\r
+      Number        = (UINT16) LegacyCDMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyCD;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyCD;\r
+      break;\r
+\r
+    case FORM_SET_NET_ORDER_ID:\r
+      Number        = (UINT16) LegacyNETMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyNET;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyNET;\r
+      break;\r
+\r
+    case FORM_SET_BEV_ORDER_ID:\r
+      Number        = (UINT16) LegacyBEVMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyBEV;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyBEV;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+    //\r
+    //  First, find the different position\r
+    //  if there is change, it should be only one\r
+    //\r
+    for (Index = 0; Index < Number; Index++) {\r
+      if (OldLegacyDev[Index] != NewLegacyDev[Index]) {\r
+        OldValue  = OldLegacyDev[Index];\r
+        NewValue  = NewLegacyDev[Index];\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (Index != Number) {\r
+      //\r
+      // there is change, now process\r
+      //\r
+      if (0xFF == NewValue) {\r
+        //\r
+        // This item will be disable\r
+        // Just move the items behind this forward to overlap it\r
+        //\r
+        Pos = OldValue / 8;\r
+        Bit = 7 - (OldValue % 8);\r
+        DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
+        for (Index2 = Index; Index2 < Number - 1; Index2++) {\r
+          NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1];\r
+        }\r
+\r
+        NewLegacyDev[Index2] = 0xFF;\r
+      } else {\r
+        for (Index2 = 0; Index2 < Number; Index2++) {\r
+          if (Index2 == Index) {\r
+            continue;\r
+          }\r
+\r
+          if (OldLegacyDev[Index2] == NewValue) {\r
+            //\r
+            // If NewValue is in OldLegacyDev array\r
+            // remember its old position\r
+            //\r
+            NewValuePos = Index2;\r
+            break;\r
+          }\r
+        }\r
+\r
+        if (Index2 != Number) {\r
+          //\r
+          // We will change current item to an existing item\r
+          // (It's hard to describe here, please read code, it's like a cycle-moving)\r
+          //\r
+          for (Index2 = NewValuePos; Index2 != Index;) {\r
+            if (NewValuePos < Index) {\r
+              NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1];\r
+              Index2++;\r
+            } else {\r
+              NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1];\r
+              Index2--;\r
+            }\r
+          }\r
+        } else {\r
+          //\r
+          // If NewValue is not in OldlegacyDev array, we are changing to a disabled item\r
+          // so we should modify DisMap to reflect the change\r
+          //\r
+          Pos = NewValue / 8;\r
+          Bit = 7 - (NewValue % 8);\r
+          DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit)));\r
+          if (0xFF != OldValue) {\r
+            //\r
+            // Because NewValue is a item that was disabled before\r
+            // so after changing the OldValue should be disabled\r
+            // actually we are doing a swap of enable-disable states of two items\r
+            //\r
+            Pos = OldValue / 8;\r
+            Bit = 7 - (OldValue % 8);\r
+            DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
+          }\r
+        }\r
+      }\r
+      //\r
+      // To prevent DISABLE appears in the middle of the list\r
+      // we should perform a re-ordering\r
+      //\r
+      Index = 0;\r
+      while (Index < Number) {\r
+        if (0xFF != NewLegacyDev[Index]) {\r
+          Index++;\r
+          continue;\r
+        }\r
+\r
+        Index2 = Index;\r
+        Index2++;\r
+        while (Index2 < Number) {\r
+          if (0xFF != NewLegacyDev[Index2]) {\r
+            break;\r
+          }\r
+\r
+          Index2++;\r
+        }\r
+\r
+        if (Index2 < Number) {\r
+          NewLegacyDev[Index]   = NewLegacyDev[Index2];\r
+          NewLegacyDev[Index2]  = 0xFF;\r
+        }\r
+\r
+        Index++;\r
+      }\r
+\r
+      CopyMem (\r
+        OldLegacyDev,\r
+        NewLegacyDev,\r
+        Number\r
+        );\r
+    }\r
+  }\r
+\r
+  if (QuestionId < FILE_OPTION_OFFSET) {\r
+    if (QuestionId < CONFIG_OPTION_OFFSET) {\r
+      switch (QuestionId) {\r
+      case KEY_VALUE_BOOT_FROM_FILE:\r
+        Private->FeCurrentState = BOOT_FROM_FILE_STATE;\r
+\r
+        //\r
+        // Exit Bmm main formset to send File Explorer formset.\r
+        //\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+        break;\r
+\r
+      case FORM_BOOT_ADD_ID:\r
+        Private->FeCurrentState = ADD_BOOT_OPTION_STATE;\r
+\r
+        //\r
+        // Exit Bmm main formset to send File Explorer formset.\r
+        //\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+        break;\r
+\r
+      case FORM_DRV_ADD_FILE_ID:\r
+        Private->FeCurrentState = ADD_DRIVER_OPTION_STATE;\r
+\r
+        //\r
+        // Exit Bmm main formset to send File Explorer formset.\r
+        //\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+        break;\r
+\r
+      case FORM_DRV_ADD_HANDLE_ID:\r
+        CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private);\r
+        UpdateDrvAddHandlePage (Private);\r
+        break;\r
+\r
+      case FORM_BOOT_DEL_ID:\r
+        CleanUpPage (FORM_BOOT_DEL_ID, Private);\r
+        UpdateBootDelPage (Private);\r
+        break;\r
+\r
+      case FORM_BOOT_CHG_ID:\r
+      case FORM_DRV_CHG_ID:\r
+        UpdatePageBody (QuestionId, Private);\r
+        break;\r
+\r
+      case FORM_DRV_DEL_ID:\r
+        CleanUpPage (FORM_DRV_DEL_ID, Private);\r
+        UpdateDrvDelPage (Private);\r
+        break;\r
+\r
+      case FORM_BOOT_NEXT_ID:\r
+        CleanUpPage (FORM_BOOT_NEXT_ID, Private);\r
+        UpdateBootNextPage (Private);\r
+        break;\r
+\r
+      case FORM_TIME_OUT_ID:\r
+        CleanUpPage (FORM_TIME_OUT_ID, Private);\r
+        UpdateTimeOutPage (Private);\r
+        break;\r
+\r
+      case FORM_RESET:\r
+        gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
+        return EFI_UNSUPPORTED;\r
+\r
+      case FORM_CON_IN_ID:\r
+      case FORM_CON_OUT_ID:\r
+      case FORM_CON_ERR_ID:\r
+        UpdatePageBody (QuestionId, Private);\r
+        break;\r
+\r
+      case FORM_CON_MODE_ID:\r
+        CleanUpPage (FORM_CON_MODE_ID, Private);\r
+        UpdateConModePage (Private);\r
+        break;\r
+\r
+      case FORM_CON_COM_ID:\r
+        CleanUpPage (FORM_CON_COM_ID, Private);\r
+        UpdateConCOMPage (Private);\r
+        break;\r
+\r
+      case FORM_SET_FD_ORDER_ID:\r
+      case FORM_SET_HD_ORDER_ID:\r
+      case FORM_SET_CD_ORDER_ID:\r
+      case FORM_SET_NET_ORDER_ID:\r
+      case FORM_SET_BEV_ORDER_ID:\r
+        CleanUpPage (QuestionId, Private);\r
+        UpdateSetLegacyDeviceOrderPage (QuestionId, Private);\r
+        break;\r
+\r
+      case KEY_VALUE_SAVE_AND_EXIT:\r
+      case KEY_VALUE_NO_SAVE_AND_EXIT:\r
+\r
+        if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) {\r
+          Status = ApplyChangeHandler (Private, CurrentFakeNVMap, Private->BmmPreviousPageId);\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+        } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) {\r
+          DiscardChangeHandler (Private, CurrentFakeNVMap);\r
+        }\r
+\r
+        //\r
+        // Tell browser not to ask for confirmation of changes,\r
+        // since we have already applied or discarded.\r
+        //\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+    } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) {\r
+      Index2                    = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET);\r
+      Private->CurrentTerminal  = Index2;\r
+\r
+      CleanUpPage (FORM_CON_COM_SETUP_ID, Private);\r
+      UpdateTerminalPage (Private);\r
+\r
+    } else if (QuestionId >= HANDLE_OPTION_OFFSET) {\r
+      Index2                  = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET);\r
+\r
+      NewMenuEntry            = BOpt_GetMenuEntry (&DriverMenu, Index2);\r
+      ASSERT (NewMenuEntry != NULL);\r
+      Private->HandleContext  = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+      CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private);\r
+\r
+      Private->MenuEntry                  = NewMenuEntry;\r
+      Private->LoadContext->FilePathList  = Private->HandleContext->DevicePath;\r
+\r
+      UpdateDriverAddHandleDescPage (Private);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Pass changed uncommitted data back to Form Browser\r
+  //\r
+  BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
+  Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) CurrentFakeNVMap, NULL);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+ApplyChangeHandler (\r
+  IN  BMM_CALLBACK_DATA               *Private,\r
+  IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap,\r
+  IN  EFI_FORM_ID                     FormId\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Function handling request to apply changes for BMM pages.\r
+\r
+Arguments:\r
+  Private          - Pointer to callback data buffer.\r
+  CurrentFakeNVMap - Pointer to buffer holding data of various values used by BMM\r
+  FormId           - ID of the form which has sent the request to apply change.\r
+\r
+Returns:\r
+  EFI_SUCCESS      - Change successfully applied.\r
+  Other            - Error occurs while trying to apply changes.\r
+\r
+--*/\r
+{\r
+  BM_CONSOLE_CONTEXT  *NewConsoleContext;\r
+  BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+  BM_LOAD_CONTEXT     *NewLoadContext;\r
+  BM_MENU_ENTRY       *NewMenuEntry;\r
+  EFI_STATUS          Status;\r
+  UINT16              Index;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  switch (FormId) {\r
+  case FORM_SET_FD_ORDER_ID:\r
+  case FORM_SET_HD_ORDER_ID:\r
+  case FORM_SET_CD_ORDER_ID:\r
+  case FORM_SET_NET_ORDER_ID:\r
+  case FORM_SET_BEV_ORDER_ID:\r
+    Var_UpdateBBSOption (Private);\r
+    break;\r
+\r
+  case FORM_BOOT_DEL_ID:\r
+    for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+      NewMenuEntry            = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+      NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewLoadContext->Deleted = CurrentFakeNVMap->BootOptionDel[Index];\r
+    }\r
+\r
+    Var_DelBootOption ();\r
+    break;\r
+\r
+  case FORM_DRV_DEL_ID:\r
+    for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+      NewMenuEntry            = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+      NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewLoadContext->Deleted = CurrentFakeNVMap->DriverOptionDel[Index];\r
+    }\r
+\r
+    Var_DelDriverOption ();\r
+    break;\r
+\r
+  case FORM_BOOT_CHG_ID:\r
+    Status = Var_UpdateBootOrder (Private);\r
+    break;\r
+\r
+  case FORM_DRV_CHG_ID:\r
+    Status = Var_UpdateDriverOrder (Private);\r
+    break;\r
+\r
+  case FORM_TIME_OUT_ID:\r
+    Status = gRT->SetVariable (\r
+                    L"Timeout",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    sizeof (UINT16),\r
+                    &(CurrentFakeNVMap->BootTimeOut)\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+\r
+    Private->BmmOldFakeNVData.BootTimeOut = CurrentFakeNVMap->BootTimeOut;\r
+    break;\r
+\r
+  case FORM_BOOT_NEXT_ID:\r
+    Status = Var_UpdateBootNext (Private);\r
+    break;\r
+\r
+  case FORM_CON_MODE_ID:\r
+    Status = Var_UpdateConMode (Private);\r
+    break;\r
+\r
+  case FORM_CON_COM_SETUP_ID:\r
+    NewMenuEntry                      = BOpt_GetMenuEntry (&TerminalMenu, Private->CurrentTerminal);\r
+\r
+    ASSERT (NewMenuEntry != NULL);\r
+\r
+    NewTerminalContext                = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    NewTerminalContext->BaudRateIndex = CurrentFakeNVMap->COMBaudRate;\r
+    NewTerminalContext->BaudRate      = BaudRateList[CurrentFakeNVMap->COMBaudRate].Value;\r
+    NewTerminalContext->DataBitsIndex = CurrentFakeNVMap->COMDataRate;\r
+    NewTerminalContext->DataBits      = (UINT8) DataBitsList[CurrentFakeNVMap->COMDataRate].Value;\r
+    NewTerminalContext->StopBitsIndex = CurrentFakeNVMap->COMStopBits;\r
+    NewTerminalContext->StopBits      = (UINT8) StopBitsList[CurrentFakeNVMap->COMStopBits].Value;\r
+    NewTerminalContext->ParityIndex   = CurrentFakeNVMap->COMParity;\r
+    NewTerminalContext->Parity        = (UINT8) ParityList[CurrentFakeNVMap->COMParity].Value;\r
+    NewTerminalContext->TerminalType  = CurrentFakeNVMap->COMTerminalType;\r
+\r
+    ChangeTerminalDevicePath (\r
+      NewTerminalContext->DevicePath,\r
+      FALSE\r
+      );\r
+\r
+    Var_UpdateConsoleInpOption ();\r
+    Var_UpdateConsoleOutOption ();\r
+    Var_UpdateErrorOutOption ();\r
+    break;\r
+\r
+  case FORM_CON_IN_ID:\r
+    for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+    }\r
+\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext          = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewTerminalContext->IsConIn = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleInpMenu.MenuNumber];\r
+    }\r
+\r
+    Var_UpdateConsoleInpOption ();\r
+    break;\r
+\r
+  case FORM_CON_OUT_ID:\r
+    for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+    }\r
+\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                  = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext            = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewTerminalContext->IsConOut  = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleOutMenu.MenuNumber];\r
+    }\r
+\r
+    Var_UpdateConsoleOutOption ();\r
+    break;\r
+\r
+  case FORM_CON_ERR_ID:\r
+    for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+    }\r
+\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                  = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext            = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewTerminalContext->IsStdErr  = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleErrMenu.MenuNumber];\r
+    }\r
+\r
+    Var_UpdateErrorOutOption ();\r
+    break;\r
+\r
+  case FORM_DRV_ADD_HANDLE_DESC_ID:\r
+    Status = Var_UpdateDriverOption (\r
+               Private,\r
+               Private->BmmHiiHandle,\r
+               CurrentFakeNVMap->DriverAddHandleDesc,\r
+               CurrentFakeNVMap->DriverAddHandleOptionalData,\r
+               CurrentFakeNVMap->DriverAddForceReconnect\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+\r
+    BOpt_GetDriverOptions (Private);\r
+    CreateMenuStringToken (Private, Private->BmmHiiHandle, &DriverOptionMenu);\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+Error:\r
+  return Status;\r
+}\r
+\r
+VOID\r
+DiscardChangeHandler (\r
+  IN  BMM_CALLBACK_DATA               *Private,\r
+  IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap\r
+  )\r
+{\r
+  UINT16  Index;\r
+\r
+  switch (Private->BmmPreviousPageId) {\r
+  case FORM_BOOT_CHG_ID:\r
+  case FORM_DRV_CHG_ID:\r
+    CopyMem (CurrentFakeNVMap->OptionOrder, Private->BmmOldFakeNVData.OptionOrder, 100);\r
+    break;\r
+\r
+  case FORM_BOOT_DEL_ID:\r
+    for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+      CurrentFakeNVMap->BootOptionDel[Index] = 0x00;\r
+    }\r
+    break;\r
+\r
+  case FORM_DRV_DEL_ID:\r
+    for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+      CurrentFakeNVMap->DriverOptionDel[Index] = 0x00;\r
+    }\r
+    break;\r
+\r
+  case FORM_BOOT_NEXT_ID:\r
+    CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext;\r
+    break;\r
+\r
+  case FORM_TIME_OUT_ID:\r
+    CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut;\r
+    break;\r
+\r
+  case FORM_DRV_ADD_HANDLE_DESC_ID:\r
+  case FORM_DRV_ADD_FILE_ID:\r
+  case FORM_DRV_ADD_HANDLE_ID:\r
+    CurrentFakeNVMap->DriverAddHandleDesc[0]          = 0x0000;\r
+    CurrentFakeNVMap->DriverAddHandleOptionalData[0]  = 0x0000;\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+InitializeBM (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Initialize the Boot Maintenance Utitliy\r
+\r
+Arguments:\r
+  ImageHandle     - caller provided handle\r
+  SystemTable     - caller provided system tables\r
+\r
+Returns:\r
+  EFI_SUCCESS     - utility ended successfully\r
+  others          - contain some errors\r
+\r
+--*/\r
+{\r
+  EFI_LEGACY_BIOS_PROTOCOL    *LegacyBios;\r
+  EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+  BMM_CALLBACK_DATA           *BmmCallbackInfo;\r
+  EFI_STATUS                  Status;\r
+  UINT8                       *Ptr;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // Create CallbackData structures for Driver Callback\r
+  //\r
+  BmmCallbackInfo = EfiAllocateZeroPool (sizeof (BMM_CALLBACK_DATA));\r
+  if (BmmCallbackInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Create LoadOption in BmmCallbackInfo for Driver Callback\r
+  //\r
+  Ptr = EfiAllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY));\r
+  if (!Ptr) {\r
+    SafeFreePool (BmmCallbackInfo);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Initialize Bmm callback data.\r
+  //\r
+  BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;\r
+  Ptr += sizeof (BM_LOAD_CONTEXT);\r
+\r
+  BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;\r
+  Ptr += sizeof (BM_FILE_CONTEXT);\r
+\r
+  BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;\r
+  Ptr += sizeof (BM_HANDLE_CONTEXT);\r
+\r
+  BmmCallbackInfo->MenuEntry      = (BM_MENU_ENTRY *) Ptr;\r
+\r
+  BmmCallbackInfo->Signature                     = BMM_CALLBACK_DATA_SIGNATURE;\r
+  BmmCallbackInfo->BmmConfigAccess.ExtractConfig = BootMaintExtractConfig;\r
+  BmmCallbackInfo->BmmConfigAccess.RouteConfig   = FakeRouteConfig;\r
+  BmmCallbackInfo->BmmConfigAccess.Callback      = BootMaintCallback;\r
+  BmmCallbackInfo->BmmPreviousPageId             = FORM_MAIN_ID;\r
+  BmmCallbackInfo->BmmCurrentPageId              = FORM_MAIN_ID;\r
+  BmmCallbackInfo->FeConfigAccess.ExtractConfig  = FakeExtractConfig;\r
+  BmmCallbackInfo->FeConfigAccess.RouteConfig    = FakeRouteConfig;\r
+  BmmCallbackInfo->FeConfigAccess.Callback       = FileExplorerCallback;\r
+  BmmCallbackInfo->FeCurrentState                = INACTIVE_STATE;\r
+  BmmCallbackInfo->FeDisplayContext              = UNKNOWN_CONTEXT;\r
+\r
+  //\r
+  // Create driver handle used by HII database\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&BmmCallbackInfo->BmmDriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Install Config Access protocol to driver handle\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &BmmCallbackInfo->BmmDriverHandle,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &BmmCallbackInfo->BmmConfigAccess\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Create driver handle used by HII database\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&BmmCallbackInfo->FeDriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Install Config Access protocol to driver handle\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &BmmCallbackInfo->FeDriverHandle,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &BmmCallbackInfo->FeConfigAccess\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Post our Boot Maint VFR binnary to the HII database.\r
+  //\r
+  PackageList = PreparePackageList (2, &mBootMaintGuid, BmBin, BdsStrings);\r
+  ASSERT (PackageList != NULL);\r
+\r
+  Status = gHiiDatabase->NewPackageList (\r
+                           gHiiDatabase,\r
+                           PackageList,\r
+                           BmmCallbackInfo->BmmDriverHandle,\r
+                           &BmmCallbackInfo->BmmHiiHandle\r
+                           );\r
+  FreePool (PackageList);\r
+\r
+  //\r
+  // Post our File Explorer VFR binary to the HII database.\r
+  //\r
+  PackageList = PreparePackageList (2, &mFileExplorerGuid, FEBin, BdsStrings);\r
+  ASSERT (PackageList != NULL);\r
+\r
+  Status = gHiiDatabase->NewPackageList (\r
+                           gHiiDatabase,\r
+                           PackageList,\r
+                           BmmCallbackInfo->FeDriverHandle,\r
+                           &BmmCallbackInfo->FeHiiHandle\r
+                           );\r
+  FreePool (PackageList);\r
+\r
+  //\r
+  // Allocate space for creation of Buffer\r
+  //\r
+  gUpdateData.BufferSize = UPDATE_DATA_SIZE;\r
+  gUpdateData.Data = EfiAllocateZeroPool (UPDATE_DATA_SIZE);\r
+  if (gUpdateData.Data == NULL) {\r
+    SafeFreePool (BmmCallbackInfo->LoadContext);\r
+    SafeFreePool (BmmCallbackInfo);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  InitializeStringDepository ();\r
+\r
+  InitAllMenu (BmmCallbackInfo);\r
+\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu);\r
+\r
+  UpdateBootDelPage (BmmCallbackInfo);\r
+  UpdateDrvDelPage (BmmCallbackInfo);\r
+\r
+  if (TerminalMenu.MenuNumber > 0) {\r
+    BmmCallbackInfo->CurrentTerminal = 0;\r
+    UpdateTerminalPage (BmmCallbackInfo);\r
+  }\r
+\r
+  Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+  if (!EFI_ERROR (Status)) {\r
+    RefreshUpdateData ();\r
+\r
+    //\r
+    // If LegacyBios Protocol is installed, add 3 tags about legacy boot option\r
+    // in BootOption form: legacy FD/HD/CD/NET/BEV\r
+    //\r
+    CreateGotoOpCode (\r
+      FORM_SET_FD_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      FORM_SET_FD_ORDER_ID,\r
+      &gUpdateData\r
+      );\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_HD_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      FORM_SET_HD_ORDER_ID,\r
+      &gUpdateData\r
+      );\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_CD_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      FORM_SET_CD_ORDER_ID,\r
+      &gUpdateData\r
+      );\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_NET_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      FORM_SET_NET_ORDER_ID,\r
+      &gUpdateData\r
+      );\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_BEV_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      FORM_SET_BEV_ORDER_ID,\r
+      &gUpdateData\r
+      );\r
+\r
+    IfrLibUpdateForm (\r
+      BmmCallbackInfo->BmmHiiHandle,\r
+      &mBootMaintGuid,\r
+      FORM_MAIN_ID,\r
+      FORM_BOOT_LEGACY_DEVICE_ID,\r
+      FALSE,\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  //\r
+  // Dispatch BMM main formset and File Explorer formset.\r
+  //\r
+  FormSetDispatcher (BmmCallbackInfo);\r
+\r
+  //\r
+  // Remove our IFR data from HII database\r
+  //\r
+  gHiiDatabase->RemovePackageList (gHiiDatabase, BmmCallbackInfo->BmmHiiHandle);\r
+  gHiiDatabase->RemovePackageList (gHiiDatabase, BmmCallbackInfo->FeHiiHandle);\r
+\r
+  CleanUpStringDepository ();\r
+\r
+  FreeAllMenu ();\r
+\r
+  SafeFreePool (BmmCallbackInfo->LoadContext);\r
+  SafeFreePool (BmmCallbackInfo);\r
+  SafeFreePool (gUpdateData.Data);\r
+  gUpdateData.Data = NULL;\r
+\r
+  return Status;\r
+}\r
+\r
+VOID\r
+InitAllMenu (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  )\r
+{\r
+  InitializeListHead (&BootOptionMenu.Head);\r
+  InitializeListHead (&DriverOptionMenu.Head);\r
+  BOpt_GetBootOptions (CallbackData);\r
+  BOpt_GetDriverOptions (CallbackData);\r
+  BOpt_GetLegacyOptions ();\r
+  InitializeListHead (&FsOptionMenu.Head);\r
+  BOpt_FindDrivers ();\r
+  InitializeListHead (&DirectoryMenu.Head);\r
+  InitializeListHead (&ConsoleInpMenu.Head);\r
+  InitializeListHead (&ConsoleOutMenu.Head);\r
+  InitializeListHead (&ConsoleErrMenu.Head);\r
+  InitializeListHead (&TerminalMenu.Head);\r
+  LocateSerialIo ();\r
+  GetAllConsoles ();\r
+}\r
+\r
+VOID\r
+FreeAllMenu (\r
+  VOID\r
+  )\r
+{\r
+  BOpt_FreeMenu (&DirectoryMenu);\r
+  BOpt_FreeMenu (&FsOptionMenu);\r
+  BOpt_FreeMenu (&BootOptionMenu);\r
+  BOpt_FreeMenu (&DriverOptionMenu);\r
+  BOpt_FreeMenu (&DriverMenu);\r
+  BOpt_FreeLegacyOptions ();\r
+  FreeAllConsoles ();\r
+}\r
+\r
+VOID\r
+InitializeStringDepository (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Intialize all the string depositories.\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  None.\r
+\r
+--*/\r
+{\r
+  STRING_DEPOSITORY *StringDepository;\r
+  StringDepository              = EfiAllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER);\r
+  FileOptionStrDepository       = StringDepository++;\r
+  ConsoleOptionStrDepository    = StringDepository++;\r
+  BootOptionStrDepository       = StringDepository++;\r
+  BootOptionHelpStrDepository   = StringDepository++;\r
+  DriverOptionStrDepository     = StringDepository++;\r
+  DriverOptionHelpStrDepository = StringDepository++;\r
+  TerminalStrDepository         = StringDepository;\r
+}\r
+\r
+EFI_STRING_ID\r
+GetStringTokenFromDepository (\r
+  IN   BMM_CALLBACK_DATA     *CallbackData,\r
+  IN   STRING_DEPOSITORY     *StringDepository\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Fetch a usable string node from the string depository and return the string token.\r
+\r
+Arguments:\r
+  StringDepository       - Pointer of the string depository.\r
+\r
+Returns:\r
+  EFI_STRING_ID          - String token.\r
+\r
+--*/\r
+{\r
+  STRING_LIST_NODE  *CurrentListNode;\r
+  STRING_LIST_NODE  *NextListNode;\r
+\r
+  CurrentListNode = StringDepository->CurrentNode;\r
+\r
+  if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) {\r
+    //\r
+    // Fetch one reclaimed node from the list.\r
+    //\r
+    NextListNode = StringDepository->CurrentNode->Next;\r
+  } else {\r
+    //\r
+    // If there is no usable node in the list, update the list.\r
+    //\r
+    NextListNode = EfiAllocateZeroPool (sizeof (STRING_LIST_NODE));\r
+\r
+    IfrLibNewString (CallbackData->BmmHiiHandle, &(NextListNode->StringToken), L" ");\r
+    ASSERT (NextListNode->StringToken != 0);\r
+\r
+    StringDepository->TotalNodeNumber++;\r
+\r
+    if (NULL == CurrentListNode) {\r
+      StringDepository->ListHead = NextListNode;\r
+    } else {\r
+      CurrentListNode->Next = NextListNode;\r
+    }\r
+  }\r
+\r
+  StringDepository->CurrentNode = NextListNode;\r
+\r
+  return StringDepository->CurrentNode->StringToken;\r
+}\r
+\r
+VOID\r
+ReclaimStringDepository (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Reclaim string depositories by moving the current node pointer to list head..\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  None.\r
+\r
+--*/\r
+{\r
+  UINTN             DepositoryIndex;\r
+  STRING_DEPOSITORY *StringDepository;\r
+\r
+  StringDepository = FileOptionStrDepository;\r
+  for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {\r
+    StringDepository->CurrentNode = StringDepository->ListHead;\r
+    StringDepository++;\r
+  }\r
+}\r
+\r
+VOID\r
+CleanUpStringDepository (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Release resource for all the string depositories.\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  None.\r
+\r
+--*/\r
+{\r
+  UINTN             NodeIndex;\r
+  UINTN             DepositoryIndex;\r
+  STRING_LIST_NODE  *CurrentListNode;\r
+  STRING_LIST_NODE  *NextListNode;\r
+  STRING_DEPOSITORY *StringDepository;\r
+\r
+  //\r
+  // Release string list nodes.\r
+  //\r
+  StringDepository = FileOptionStrDepository;\r
+  for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {\r
+    CurrentListNode = StringDepository->ListHead;\r
+    for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) {\r
+      NextListNode = CurrentListNode->Next;\r
+      SafeFreePool (CurrentListNode);\r
+      CurrentListNode = NextListNode;\r
+    }\r
+\r
+    StringDepository++;\r
+  }\r
+  //\r
+  // Release string depository.\r
+  //\r
+  SafeFreePool (FileOptionStrDepository);\r
+}\r
+\r
+EFI_STATUS\r
+BdsStartBootMaint (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Start boot maintenance manager\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS      Status;\r
+  LIST_ENTRY      BdsBootOptionList;\r
+\r
+  InitializeListHead (&BdsBootOptionList);\r
+\r
+  //\r
+  // Connect all prior to entering the platform setup menu.\r
+  //\r
+  if (!gConnectAllHappened) {\r
+    BdsLibConnectAllDriversToAllControllers ();\r
+    gConnectAllHappened = TRUE;\r
+  }\r
+  //\r
+  // Have chance to enumerate boot device\r
+  //\r
+  BdsLibEnumerateAllBootOption (&BdsBootOptionList);\r
+\r
+  //\r
+  // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION\r
+  //\r
+  gBS->RestoreTPL (TPL_APPLICATION);\r
+\r
+  //\r
+  // Init the BMM\r
+  //\r
+  Status = InitializeBM ();\r
+\r
+  //\r
+  // Raise the TPL level back to TPL_APPLICATION\r
+  //\r
+  gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+FormSetDispatcher (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Dispatch BMM formset and FileExplorer formset.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+\r
+  while (TRUE) {\r
+    UpdatePageId (CallbackData, FORM_MAIN_ID);\r
+\r
+    ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+    Status = gFormBrowser2->SendForm (\r
+                             gFormBrowser2,\r
+                             &CallbackData->BmmHiiHandle,\r
+                             1,\r
+                             NULL,\r
+                             0,\r
+                             NULL,\r
+                             &ActionRequest\r
+                             );\r
+    if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+      EnableResetRequired ();\r
+    }\r
+\r
+    ReclaimStringDepository ();\r
+\r
+    //\r
+    // When this Formset returns, check if we are going to explore files.\r
+    //\r
+    if (INACTIVE_STATE != CallbackData->FeCurrentState) {\r
+      UpdateFileExplorer (CallbackData, 0);\r
+\r
+      ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+      Status = gFormBrowser2->SendForm (\r
+                               gFormBrowser2,\r
+                               &CallbackData->FeHiiHandle,\r
+                               1,\r
+                               NULL,\r
+                               0,\r
+                               NULL,\r
+                               &ActionRequest\r
+                               );\r
+      if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+        EnableResetRequired ();\r
+      }\r
+\r
+      CallbackData->FeCurrentState    = INACTIVE_STATE;\r
+      CallbackData->FeDisplayContext  = UNKNOWN_CONTEXT;\r
+      ReclaimStringDepository ();\r
+    } else {\r
+      break;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h b/MdeModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h
new file mode 100644 (file)
index 0000000..0de7b05
--- /dev/null
@@ -0,0 +1,1087 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  BootMaint.h\r
+\r
+Abstract:\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _BOOT_MAINT_H\r
+#define _BOOT_MAINT_H\r
+\r
+#include "Bds.h"\r
+#include "BBSsupport.h"\r
+#include "FormGuid.h"\r
+#include "FrontPage.h"\r
+\r
+//\r
+// Constants which are variable names used to access variables\r
+//\r
+#define VarLegacyDevOrder L"LegacyDevOrder"\r
+\r
+#define VarConOutMode L"ConOutMode"\r
+\r
+//\r
+// Guid of a NV Variable which store the information about the\r
+// FD/HD/CD/NET/BEV order\r
+//\r
+#define EFI_LEGACY_DEV_ORDER_VARIABLE_GUID \\r
+  { \\r
+  0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52} \\r
+  }\r
+\r
+//\r
+// String Contant\r
+//\r
+#define StrFloppy       L"Floppy Drive #%02x"\r
+#define StrHardDisk     L"HardDisk Drive #%02x"\r
+#define StrCDROM        L"ATAPI CDROM Drive #%02x"\r
+#define StrNET          L"NET Drive #%02x"\r
+#define StrBEV          L"BEV Drive #%02x"\r
+#define StrFloppyHelp   L"Select Floppy Drive #%02x"\r
+#define StrHardDiskHelp L"Select HardDisk Drive #%02x"\r
+#define StrCDROMHelp    L"Select ATAPI CDROM Drive #%02x"\r
+#define StrNETHelp      L"NET Drive #%02x"\r
+#define StrBEVHelp      L"BEV Drive #%02x"\r
+\r
+//\r
+// Variable created with this flag will be "Efi:...."\r
+//\r
+#define VAR_FLAG  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE\r
+\r
+//\r
+// Define Maxmim characters that will be accepted\r
+//\r
+#define MAX_CHAR      480\r
+#define MAX_CHAR_SIZE (MAX_CHAR * 2)\r
+\r
+//\r
+// Check to see if current build support option active feature of\r
+// some driver option\r
+//\r
+#ifndef LOAD_OPTION_ACTIVE\r
+#define LOAD_OPTION_ACTIVE  0x00000001\r
+#endif\r
+\r
+//\r
+// Check to see if current build support force reconnect feature of\r
+// some driver option\r
+//\r
+#ifndef LOAD_OPTION_FORCE_RECONNECT\r
+#define LOAD_OPTION_FORCE_RECONNECT 0x00000002\r
+#endif\r
+\r
+extern EFI_GUID mBootMaintGuid;\r
+extern EFI_GUID mFileExplorerGuid;\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8    BmBin[];\r
+extern UINT8    FEBin[];\r
+\r
+//\r
+// Below are the number of options in Baudrate, Databits,\r
+// Parity and Stopbits selection for serial ports.\r
+//\r
+#define BM_COM_ATTR_BUADRATE  19\r
+#define BM_COM_ATTR_DATABITS  4\r
+#define BM_COM_ATTR_PARITY    5\r
+#define BM_COM_ATTR_STOPBITS  3\r
+\r
+//\r
+// Callback function helper\r
+//\r
+#define BMM_CALLBACK_DATA_SIGNATURE     EFI_SIGNATURE_32 ('C', 'b', 'c', 'k')\r
+#define BMM_CALLBACK_DATA_FROM_THIS(a)  CR (a, BMM_CALLBACK_DATA, BmmConfigAccess, BMM_CALLBACK_DATA_SIGNATURE)\r
+\r
+#define FE_CALLBACK_DATA_FROM_THIS(a)   CR (a, BMM_CALLBACK_DATA, FeConfigAccess, BMM_CALLBACK_DATA_SIGNATURE)\r
+\r
+//\r
+// Enumeration type definition\r
+//\r
+typedef UINT8 BBS_TYPE;\r
+\r
+typedef enum {\r
+  PC_ANSI                             = 0,\r
+  VT_100,\r
+  VT_100_PLUS,\r
+  VT_UTF8\r
+} TYPE_OF_TERMINAL;\r
+\r
+typedef enum {\r
+  COM1                                = 0,\r
+  COM2,\r
+  UNKNOW_COM\r
+} TYPE_OF_COM;\r
+\r
+typedef enum {\r
+  CONIN                               = 0,\r
+  CONOUT,\r
+  CONERR,\r
+  UNKNOWN_CON\r
+} TYPE_OF_CON;\r
+\r
+typedef enum {\r
+  BAUDRATE                            = 0,\r
+  DATABITS,\r
+  PARITY,\r
+  STOPBITS,\r
+  UNKNOW_ATTR\r
+} TYPE_OF_ATTRIBUTE;\r
+\r
+typedef enum {\r
+  MANNER_GOTO                         = 0,\r
+  MANNER_CHECK,\r
+  MANNER_ONEOF,\r
+  MANNER_USER_DEFINE\r
+} TYPE_OF_UPATE_MANNER;\r
+\r
+typedef enum {\r
+  INACTIVE_STATE                      = 0,\r
+  BOOT_FROM_FILE_STATE,\r
+  ADD_BOOT_OPTION_STATE,\r
+  ADD_DRIVER_OPTION_STATE,\r
+  UNKNOWN_STATE\r
+} FILE_EXPLORER_STATE;\r
+\r
+typedef enum {\r
+  FILE_SYSTEM,\r
+  DIRECTORY,\r
+  UNKNOWN_CONTEXT\r
+} FILE_EXPLORER_DISPLAY_CONTEXT;\r
+\r
+//\r
+// All of the signatures that will be used in list structure\r
+//\r
+#define BM_MENU_OPTION_SIGNATURE      'menu'\r
+#define BM_LOAD_OPTION_SIGNATURE      'load'\r
+#define BM_CONSOLE_OPTION_SIGNATURE   'cnsl'\r
+#define BM_FILE_OPTION_SIGNATURE      'file'\r
+#define BM_HANDLE_OPTION_SIGNATURE    'hndl'\r
+#define BM_TERMINAL_OPTION_SIGNATURE  'trml'\r
+#define BM_MENU_ENTRY_SIGNATURE       'entr'\r
+\r
+#define BM_LOAD_CONTEXT_SELECT        0x0\r
+#define BM_CONSOLE_CONTEXT_SELECT     0x1\r
+#define BM_FILE_CONTEXT_SELECT        0x2\r
+#define BM_HANDLE_CONTEXT_SELECT      0x3\r
+#define BM_TERMINAL_CONTEXT_SELECT    0x5\r
+\r
+#define BM_CONSOLE_IN_CONTEXT_SELECT  0x6\r
+#define BM_CONSOLE_OUT_CONTEXT_SELECT 0x7\r
+#define BM_CONSOLE_ERR_CONTEXT_SELECT 0x8\r
+#define BM_LEGACY_DEV_CONTEXT_SELECT  0x9\r
+\r
+//\r
+// Buffer size for update data\r
+//\r
+#define UPDATE_DATA_SIZE        0x100000\r
+\r
+//\r
+// Namespace of callback keys used in display and file system navigation\r
+//\r
+#define MAX_BBS_OFFSET          0xE000\r
+#define NET_OPTION_OFFSET       0xD800\r
+#define BEV_OPTION_OFFSET       0xD000\r
+#define FD_OPTION_OFFSET        0xC000\r
+#define HD_OPTION_OFFSET        0xB000\r
+#define CD_OPTION_OFFSET        0xA000\r
+#define FILE_OPTION_OFFSET      0x8000\r
+#define FILE_OPTION_MASK        0x7FFF\r
+#define HANDLE_OPTION_OFFSET    0x7000\r
+#define CONSOLE_OPTION_OFFSET   0x6000\r
+#define TERMINAL_OPTION_OFFSET  0x5000\r
+#define CONFIG_OPTION_OFFSET    0x1200\r
+#define KEY_VALUE_OFFSET        0x1100\r
+#define FORM_ID_OFFSET          0x1000\r
+\r
+//\r
+// VarOffset that will be used to create question\r
+// all these values are computed from the structure\r
+// defined below\r
+//\r
+#define VAR_OFFSET(Field)              ((UINT16) ((UINTN) &(((BMM_FAKE_NV_DATA *) 0)->Field)))\r
+\r
+//\r
+// Question Id of Zero is invalid, so add an offset to it\r
+//\r
+#define QUESTION_ID(Field)             (VAR_OFFSET (Field) + CONFIG_OPTION_OFFSET)\r
+\r
+#define BOOT_TIME_OUT_VAR_OFFSET        VAR_OFFSET (BootTimeOut)\r
+#define BOOT_NEXT_VAR_OFFSET            VAR_OFFSET (BootNext)\r
+#define COM1_BAUD_RATE_VAR_OFFSET       VAR_OFFSET (COM1BaudRate)\r
+#define COM1_DATA_RATE_VAR_OFFSET       VAR_OFFSET (COM1DataRate)\r
+#define COM1_STOP_BITS_VAR_OFFSET       VAR_OFFSET (COM1StopBits)\r
+#define COM1_PARITY_VAR_OFFSET          VAR_OFFSET (COM1Parity)\r
+#define COM1_TERMINAL_VAR_OFFSET        VAR_OFFSET (COM2TerminalType)\r
+#define COM2_BAUD_RATE_VAR_OFFSET       VAR_OFFSET (COM2BaudRate)\r
+#define COM2_DATA_RATE_VAR_OFFSET       VAR_OFFSET (COM2DataRate)\r
+#define COM2_STOP_BITS_VAR_OFFSET       VAR_OFFSET (COM2StopBits)\r
+#define COM2_PARITY_VAR_OFFSET          VAR_OFFSET (COM2Parity)\r
+#define COM2_TERMINAL_VAR_OFFSET        VAR_OFFSET (COM2TerminalType)\r
+#define DRV_ADD_HANDLE_DESC_VAR_OFFSET  VAR_OFFSET (DriverAddHandleDesc)\r
+#define DRV_ADD_ACTIVE_VAR_OFFSET       VAR_OFFSET (DriverAddActive)\r
+#define DRV_ADD_RECON_VAR_OFFSET        VAR_OFFSET (DriverAddForceReconnect)\r
+#define CON_IN_COM1_VAR_OFFSET          VAR_OFFSET (ConsoleInputCOM1)\r
+#define CON_IN_COM2_VAR_OFFSET          VAR_OFFSET (ConsoleInputCOM2)\r
+#define CON_OUT_COM1_VAR_OFFSET         VAR_OFFSET (ConsoleOutputCOM1)\r
+#define CON_OUT_COM2_VAR_OFFSET         VAR_OFFSET (ConsoleOutputCOM2)\r
+#define CON_ERR_COM1_VAR_OFFSET         VAR_OFFSET (ConsoleErrorCOM1)\r
+#define CON_ERR_COM2_VAR_OFFSET         VAR_OFFSET (ConsoleErrorCOM2)\r
+#define CON_MODE_VAR_OFFSET             VAR_OFFSET (ConsoleOutMode)\r
+#define CON_DEVICE_VAR_OFFSET           VAR_OFFSET (ConsoleCheck)\r
+#define OPTION_ORDER_VAR_OFFSET         VAR_OFFSET (OptionOrder)\r
+#define DRIVER_OPTION_ORDER_VAR_OFFSET  VAR_OFFSET (DriverOptionToBeDeleted)\r
+#define BOOT_OPTION_DEL_VAR_OFFSET      VAR_OFFSET (BootOptionDel)\r
+#define DRIVER_OPTION_DEL_VAR_OFFSET    VAR_OFFSET (DriverOptionDel)\r
+#define DRIVER_ADD_OPTION_VAR_OFFSET    VAR_OFFSET (DriverAddHandleOptionalData)\r
+#define COM_BAUD_RATE_VAR_OFFSET        VAR_OFFSET (COMBaudRate)\r
+#define COM_DATA_RATE_VAR_OFFSET        VAR_OFFSET (COMDataRate)\r
+#define COM_STOP_BITS_VAR_OFFSET        VAR_OFFSET (COMStopBits)\r
+#define COM_PARITY_VAR_OFFSET           VAR_OFFSET (COMParity)\r
+#define COM_TERMINAL_VAR_OFFSET         VAR_OFFSET (COMTerminalType)\r
+#define LEGACY_FD_VAR_OFFSET            VAR_OFFSET (LegacyFD)\r
+#define LEGACY_HD_VAR_OFFSET            VAR_OFFSET (LegacyHD)\r
+#define LEGACY_CD_VAR_OFFSET            VAR_OFFSET (LegacyCD)\r
+#define LEGACY_NET_VAR_OFFSET           VAR_OFFSET (LegacyNET)\r
+#define LEGACY_BEV_VAR_OFFSET           VAR_OFFSET (LegacyBEV)\r
+\r
+#define BOOT_TIME_OUT_QUESTION_ID       QUESTION_ID (BootTimeOut)\r
+#define BOOT_NEXT_QUESTION_ID           QUESTION_ID (BootNext)\r
+#define COM1_BAUD_RATE_QUESTION_ID      QUESTION_ID (COM1BaudRate)\r
+#define COM1_DATA_RATE_QUESTION_ID      QUESTION_ID (COM1DataRate)\r
+#define COM1_STOP_BITS_QUESTION_ID      QUESTION_ID (COM1StopBits)\r
+#define COM1_PARITY_QUESTION_ID         QUESTION_ID (COM1Parity)\r
+#define COM1_TERMINAL_QUESTION_ID       QUESTION_ID (COM2TerminalType)\r
+#define COM2_BAUD_RATE_QUESTION_ID      QUESTION_ID (COM2BaudRate)\r
+#define COM2_DATA_RATE_QUESTION_ID      QUESTION_ID (COM2DataRate)\r
+#define COM2_STOP_BITS_QUESTION_ID      QUESTION_ID (COM2StopBits)\r
+#define COM2_PARITY_QUESTION_ID         QUESTION_ID (COM2Parity)\r
+#define COM2_TERMINAL_QUESTION_ID       QUESTION_ID (COM2TerminalType)\r
+#define DRV_ADD_HANDLE_DESC_QUESTION_ID QUESTION_ID (DriverAddHandleDesc)\r
+#define DRV_ADD_ACTIVE_QUESTION_ID      QUESTION_ID (DriverAddActive)\r
+#define DRV_ADD_RECON_QUESTION_ID       QUESTION_ID (DriverAddForceReconnect)\r
+#define CON_IN_COM1_QUESTION_ID         QUESTION_ID (ConsoleInputCOM1)\r
+#define CON_IN_COM2_QUESTION_ID         QUESTION_ID (ConsoleInputCOM2)\r
+#define CON_OUT_COM1_QUESTION_ID        QUESTION_ID (ConsoleOutputCOM1)\r
+#define CON_OUT_COM2_QUESTION_ID        QUESTION_ID (ConsoleOutputCOM2)\r
+#define CON_ERR_COM1_QUESTION_ID        QUESTION_ID (ConsoleErrorCOM1)\r
+#define CON_ERR_COM2_QUESTION_ID        QUESTION_ID (ConsoleErrorCOM2)\r
+#define CON_MODE_QUESTION_ID            QUESTION_ID (ConsoleOutMode)\r
+#define CON_DEVICE_QUESTION_ID          QUESTION_ID (ConsoleCheck)\r
+#define OPTION_ORDER_QUESTION_ID        QUESTION_ID (OptionOrder)\r
+#define DRIVER_OPTION_ORDER_QUESTION_ID QUESTION_ID (DriverOptionToBeDeleted)\r
+#define BOOT_OPTION_DEL_QUESTION_ID     QUESTION_ID (BootOptionDel)\r
+#define DRIVER_OPTION_DEL_QUESTION_ID   QUESTION_ID (DriverOptionDel)\r
+#define DRIVER_ADD_OPTION_QUESTION_ID   QUESTION_ID (DriverAddHandleOptionalData)\r
+#define COM_BAUD_RATE_QUESTION_ID       QUESTION_ID (COMBaudRate)\r
+#define COM_DATA_RATE_QUESTION_ID       QUESTION_ID (COMDataRate)\r
+#define COM_STOP_BITS_QUESTION_ID       QUESTION_ID (COMStopBits)\r
+#define COM_PARITY_QUESTION_ID          QUESTION_ID (COMParity)\r
+#define COM_TERMINAL_QUESTION_ID        QUESTION_ID (COMTerminalType)\r
+#define LEGACY_FD_QUESTION_ID           QUESTION_ID (LegacyFD)\r
+#define LEGACY_HD_QUESTION_ID           QUESTION_ID (LegacyHD)\r
+#define LEGACY_CD_QUESTION_ID           QUESTION_ID (LegacyCD)\r
+#define LEGACY_NET_QUESTION_ID          QUESTION_ID (LegacyNET)\r
+#define LEGACY_BEV_QUESTION_ID          QUESTION_ID (LegacyBEV)\r
+\r
+#define STRING_DEPOSITORY_NUMBER        8\r
+\r
+//\r
+// #pragma pack(1)\r
+//\r
+// Serial Ports attributes, first one is the value for\r
+// return from callback function, stringtoken is used to\r
+// display the value properly\r
+//\r
+typedef struct {\r
+  UINTN   Value;\r
+  UINT16  StringToken;\r
+} COM_ATTR;\r
+\r
+typedef struct {\r
+  BBS_TYPE  BbsType;\r
+  //\r
+  // Length = sizeof (UINT16) + SIZEOF (Data)\r
+  //\r
+  UINT16    Length;\r
+  UINT16    *Data;\r
+} BM_LEGACY_DEV_ORDER_CONTEXT;\r
+\r
+typedef struct {\r
+  UINT64                    BaudRate;\r
+  UINT8                     DataBits;\r
+  UINT8                     Parity;\r
+  UINT8                     StopBits;\r
+\r
+  UINT8                     BaudRateIndex;\r
+  UINT8                     DataBitsIndex;\r
+  UINT8                     ParityIndex;\r
+  UINT8                     StopBitsIndex;\r
+\r
+  UINT8                     IsConIn;\r
+  UINT8                     IsConOut;\r
+  UINT8                     IsStdErr;\r
+  UINT8                     TerminalType;\r
+\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+} BM_TERMINAL_CONTEXT;\r
+\r
+typedef struct {\r
+  BOOLEAN                   IsBootNext;\r
+  BOOLEAN                   LoadOptionModified;\r
+  BOOLEAN                   Deleted;\r
+\r
+  BOOLEAN                   IsLegacy;\r
+  BOOLEAN                   IsActive;\r
+  BOOLEAN                   ForceReconnect;\r
+  UINTN                     OptionalDataSize;\r
+\r
+  UINTN                     LoadOptionSize;\r
+  UINT8                     *LoadOption;\r
+\r
+  UINT32                    Attributes;\r
+  UINT16                    FilePathListLength;\r
+  UINT16                    *Description;\r
+  EFI_DEVICE_PATH_PROTOCOL  *FilePathList;\r
+  UINT8                     *OptionalData;\r
+\r
+  UINT16                    BbsIndex;\r
+} BM_LOAD_CONTEXT;\r
+\r
+typedef struct {\r
+  BBS_TABLE *BbsTable;\r
+  UINTN     Index;\r
+  UINTN     BbsCount;\r
+  UINT16    *Description;\r
+} BM_LEGACY_DEVICE_CONTEXT;\r
+\r
+typedef struct {\r
+\r
+  BOOLEAN                   IsActive;\r
+\r
+  BOOLEAN                   IsTerminal;\r
+\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+} BM_CONSOLE_CONTEXT;\r
+\r
+typedef struct {\r
+  UINTN   Column;\r
+  UINTN   Row;\r
+} CONSOLE_OUT_MODE;\r
+\r
+typedef struct {\r
+  EFI_HANDLE                        Handle;\r
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;\r
+  EFI_FILE_HANDLE                   FHandle;\r
+  UINT16                            *FileName;\r
+  EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Info;\r
+\r
+  BOOLEAN                           IsRoot;\r
+  BOOLEAN                           IsDir;\r
+  BOOLEAN                           IsRemovableMedia;\r
+  BOOLEAN                           IsLoadFile;\r
+  BOOLEAN                           IsBootLegacy;\r
+} BM_FILE_CONTEXT;\r
+\r
+typedef struct {\r
+  EFI_HANDLE                Handle;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+} BM_HANDLE_CONTEXT;\r
+\r
+typedef struct {\r
+  UINTN           Signature;\r
+  LIST_ENTRY      Head;\r
+  UINTN           MenuNumber;\r
+} BM_MENU_OPTION;\r
+\r
+typedef struct {\r
+  UINTN           Signature;\r
+  LIST_ENTRY      Link;\r
+  UINTN           OptionNumber;\r
+  UINT16          *DisplayString;\r
+  UINT16          *HelpString;\r
+  EFI_STRING_ID   DisplayStringToken;\r
+  EFI_STRING_ID   HelpStringToken;\r
+  UINTN           ContextSelection;\r
+  VOID            *VariableContext;\r
+} BM_MENU_ENTRY;\r
+\r
+typedef struct {\r
+  //\r
+  // Shared callback data.\r
+  //\r
+  UINTN                          Signature;\r
+\r
+  BM_MENU_ENTRY                  *MenuEntry;\r
+  BM_HANDLE_CONTEXT              *HandleContext;\r
+  BM_FILE_CONTEXT                *FileContext;\r
+  BM_LOAD_CONTEXT                *LoadContext;\r
+  BM_TERMINAL_CONTEXT            *TerminalContext;\r
+  UINTN                          CurrentTerminal;\r
+  UINT8                          BbsType;\r
+\r
+  //\r
+  // BMM main formset callback data.\r
+  //\r
+  EFI_HII_HANDLE                 BmmHiiHandle;\r
+  EFI_HANDLE                     BmmDriverHandle;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL BmmConfigAccess;\r
+  EFI_FORM_ID                    BmmCurrentPageId;\r
+  EFI_FORM_ID                    BmmPreviousPageId;\r
+  BOOLEAN                        BmmAskSaveOrNot;\r
+  BMM_FAKE_NV_DATA               BmmFakeNvData;\r
+  BMM_FAKE_NV_DATA               BmmOldFakeNVData;\r
+\r
+  //\r
+  // File explorer formset callback data.\r
+  //\r
+  EFI_HII_HANDLE                 FeHiiHandle;\r
+  EFI_HANDLE                     FeDriverHandle;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL FeConfigAccess;\r
+  FILE_EXPLORER_STATE            FeCurrentState;\r
+  FILE_EXPLORER_DISPLAY_CONTEXT  FeDisplayContext;\r
+  FILE_EXPLORER_NV_DATA          FeFakeNvData;\r
+} BMM_CALLBACK_DATA;\r
+\r
+typedef struct _STRING_LIST_NODE {\r
+  EFI_STRING_ID             StringToken;\r
+  struct _STRING_LIST_NODE  *Next;\r
+} STRING_LIST_NODE;\r
+\r
+typedef struct _STRING_DEPOSITORY {\r
+  UINTN             TotalNodeNumber;\r
+  STRING_LIST_NODE  *CurrentNode;\r
+  STRING_LIST_NODE  *ListHead;\r
+} STRING_DEPOSITORY;\r
+\r
+//\r
+// #pragma pack()\r
+//\r
+// For initializing File System menu\r
+//\r
+EFI_STATUS\r
+BOpt_FindFileSystem (\r
+  IN BMM_CALLBACK_DATA          *CallbackData\r
+  )\r
+;\r
+\r
+//\r
+// For cleaning up File System menu\r
+//\r
+VOID\r
+BOpt_FreeFileSystem (\r
+  VOID\r
+  )\r
+;\r
+\r
+//\r
+// For initializing File Navigation menu\r
+//\r
+EFI_STATUS\r
+BOpt_FindFiles (\r
+  IN BMM_CALLBACK_DATA          *CallbackData,\r
+  IN BM_MENU_ENTRY              *MenuEntry\r
+  )\r
+;\r
+\r
+//\r
+// For cleaning up File Navigation menu\r
+//\r
+VOID\r
+BOpt_FreeFiles (\r
+  VOID\r
+  )\r
+;\r
+\r
+//\r
+// For Initializing handle navigation menu\r
+//\r
+EFI_STATUS\r
+BOpt_FindDrivers (\r
+  VOID\r
+  )\r
+;\r
+\r
+//\r
+// For Cleaning up handle navigation menu\r
+//\r
+VOID\r
+BOpt_FreeDrivers(VOID);\r
+\r
+//\r
+// For initializing Boot Option menu\r
+//\r
+EFI_STATUS\r
+BOpt_GetBootOptions (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData\r
+  );\r
+\r
+//\r
+// For Initializing Driver option menu\r
+//\r
+EFI_STATUS\r
+BOpt_GetDriverOptions (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData\r
+  );\r
+\r
+//\r
+// For Cleaning up boot option menu\r
+//\r
+VOID\r
+BOpt_FreeBootOptions (VOID);\r
+\r
+//\r
+// For cleaning up driver option menu\r
+//\r
+VOID\r
+BOpt_FreeDriverOptions(VOID);\r
+\r
+//\r
+// For Initializing HD/FD/CD/NET/BEV option menu\r
+//\r
+EFI_STATUS\r
+BOpt_GetLegacyOptions(VOID);\r
+\r
+//\r
+// For cleaning up driver option menu\r
+//\r
+VOID\r
+BOpt_FreeLegacyOptions(VOID);\r
+\r
+//\r
+// this function is used to take place of all other free menu actions\r
+//\r
+VOID\r
+BOpt_FreeMenu (\r
+  BM_MENU_OPTION        *FreeMenu\r
+  );\r
+\r
+\r
+//\r
+// Following are the helper functions used\r
+//\r
+CHAR16                            *\r
+BOpt_AppendFileName (\r
+  IN  CHAR16  *Str1,\r
+  IN  CHAR16  *Str2\r
+  );\r
+\r
+BOOLEAN\r
+BOpt_IsEfiImageName (\r
+  IN UINT16  *FileName\r
+  );\r
+\r
+BOOLEAN\r
+BOpt_IsEfiApp (\r
+  IN EFI_FILE_HANDLE Dir,\r
+  IN UINT16          *FileName\r
+  );\r
+\r
+//\r
+// Get current unused boot option number\r
+//\r
+UINT16\r
+BOpt_GetBootOptionNumber (VOID);\r
+\r
+//\r
+// Get current unused driver option number\r
+//\r
+UINT16\r
+BOpt_GetDriverOptionNumber (VOID);\r
+\r
+BM_MENU_ENTRY                     *\r
+BOpt_CreateMenuEntry (\r
+  UINTN           MenuType\r
+  );\r
+\r
+VOID\r
+BOpt_DestroyMenuEntry (\r
+  BM_MENU_ENTRY         *MenuEntry\r
+  );\r
+\r
+BM_MENU_ENTRY                     *\r
+BOpt_GetMenuEntry (\r
+  BM_MENU_OPTION      *MenuOption,\r
+  UINTN               MenuNumber\r
+  );\r
+\r
+//\r
+// a helper function used to free pool type memory\r
+//\r
+VOID\r
+SafeFreePool (\r
+  IN VOID *Buffer\r
+  );\r
+\r
+//\r
+// Locate all serial io devices for console\r
+//\r
+EFI_STATUS\r
+LocateSerialIo (VOID);\r
+\r
+//\r
+// Initializing Console menu\r
+//\r
+EFI_STATUS\r
+GetAllConsoles(VOID);\r
+\r
+//\r
+// Get current mode information\r
+//\r
+VOID\r
+GetConsoleOutMode (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  );\r
+\r
+//\r
+// Cleaning up console menu\r
+//\r
+EFI_STATUS\r
+FreeAllConsoles(VOID);\r
+\r
+VOID\r
+ChangeVariableDevicePath (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+);\r
+\r
+EFI_STATUS\r
+ChangeTerminalDevicePath (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
+  BOOLEAN                   ChangeTerminal\r
+);\r
+//\r
+// Variable operation by menu selection\r
+//\r
+EFI_STATUS\r
+Var_UpdateBootOption (\r
+  IN  BMM_CALLBACK_DATA                   *CallbackData,\r
+  IN  FILE_EXPLORER_NV_DATA               *NvRamMap\r
+  );\r
+\r
+EFI_STATUS\r
+Var_DelBootOption (VOID);\r
+\r
+EFI_STATUS\r
+Var_ChangeBootOrder (VOID);\r
+\r
+EFI_STATUS\r
+Var_UpdateDriverOption (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData,\r
+  IN  EFI_HII_HANDLE            HiiHandle,\r
+  IN  UINT16                    *DescriptionData,\r
+  IN  UINT16                    *OptionalData,\r
+  IN  UINT8                     ForceReconnect\r
+  );\r
+\r
+EFI_STATUS\r
+Var_DelDriverOption (VOID);\r
+\r
+EFI_STATUS\r
+Var_ChangeDriverOrder (VOID);\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleInpOption (VOID);\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleOutOption (VOID);\r
+\r
+EFI_STATUS\r
+Var_UpdateErrorOutOption (VOID);\r
+\r
+VOID\r
+Var_UpdateAllConsoleOption (VOID);\r
+\r
+EFI_STATUS\r
+Var_UpdateBootNext (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  );\r
+\r
+EFI_STATUS\r
+Var_UpdateBootOrder (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  );\r
+\r
+EFI_STATUS\r
+Var_UpdateDriverOrder (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  );\r
+\r
+EFI_STATUS\r
+Var_UpdateBBSOption (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  );\r
+\r
+EFI_STATUS\r
+Var_UpdateConMode (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  );\r
+\r
+//\r
+// Following are page create and refresh functions\r
+//\r
+VOID\r
+RefreshUpdateData (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+CleanUpPage (\r
+  IN UINT16                           LabelId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+EFI_STATUS\r
+UpdatePage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData,\r
+  IN BM_MENU_OPTION                   *UpdatingMenu,\r
+  IN UINT16                           UpdatingPage,\r
+  IN UINT16                           UpdatingManner,\r
+  IN UINT16                           QuestionIdStart,\r
+  IN UINT16                           GotoForm,\r
+  IN UINT16                           GotoAlternateForm,\r
+  IN EFI_STRING_ID                    DisplayTokenStart,\r
+  IN EFI_STRING_ID                    HelpTokenStart,\r
+  IN UINT16                           KeyValueStart\r
+  );\r
+\r
+VOID\r
+UpdateBootAddPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateBootDelPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateDrvAddFilePage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateDrvAddHandlePage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateDrvDelPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateDriverAddHandleDescPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateBootTimeOut (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateConInPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateConOutPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateStdErrPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdatePageBody (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateCOM1Page (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateCOM2Page (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateBootOrderPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateDriverOrderPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateBootNextPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateTimeOutPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateTerminalPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateConModePage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateConCOMPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateSetLegacyDeviceOrderPage (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+);\r
+\r
+EFI_STATUS\r
+BootLegacy (\r
+  IN  UINT16  BbsType,\r
+  IN  UINT16  BbsFlag\r
+);\r
+\r
+BM_MENU_ENTRY                     *\r
+GetCurrentTerminal (\r
+  UINTN       TerminalNumber\r
+);\r
+\r
+EFI_FILE_HANDLE\r
+EfiLibOpenRoot (\r
+  IN EFI_HANDLE       DeviceHandle\r
+  );\r
+\r
+EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *\r
+EfiLibFileSystemVolumeLabelInfo (\r
+  IN EFI_FILE_HANDLE      FHand\r
+  );\r
+\r
+EFI_FILE_INFO                     *\r
+EfiLibFileInfo (\r
+  IN EFI_FILE_HANDLE      FHand\r
+  );\r
+\r
+UINTN\r
+UnicodeToAscii (\r
+  IN  CHAR16  *UStr,\r
+  IN  UINTN   Length,\r
+  OUT CHAR8   *AStr\r
+  );\r
+\r
+CHAR16                            *\r
+DevicePathToStr (\r
+  EFI_DEVICE_PATH_PROTOCOL     *DevPath\r
+  );\r
+\r
+VOID                              *\r
+EfiAllocateZeroPool (\r
+  IN UINTN            Size\r
+  );\r
+\r
+EFI_STATUS\r
+EfiLibLocateProtocol (\r
+  IN  EFI_GUID        *ProtocolGuid,\r
+  OUT VOID            **Interface\r
+  );\r
+\r
+VOID                              *\r
+EfiReallocatePool (\r
+  IN VOID                 *OldPool,\r
+  IN UINTN                OldSize,\r
+  IN UINTN                NewSize\r
+  );\r
+\r
+CHAR16                            *\r
+DevicePathToStr (\r
+  EFI_DEVICE_PATH_PROTOCOL     *DevPath\r
+  );\r
+\r
+VOID                              *\r
+BdsLibGetVariableAndSize (\r
+  IN CHAR16               *Name,\r
+  IN EFI_GUID             *VendorGuid,\r
+  OUT UINTN               *VarSize\r
+  );\r
+\r
+EFI_STATUS\r
+EfiLibDeleteVariable (\r
+  IN CHAR16   *VarName,\r
+  IN EFI_GUID *VarGuid\r
+  );\r
+\r
+CHAR16                            *\r
+EfiStrDuplicate (\r
+  IN CHAR16   *Src\r
+  );\r
+\r
+BOOLEAN\r
+EfiLibMatchDevicePaths (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *Multi,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *Single\r
+  );\r
+\r
+UINTN\r
+EfiDevicePathInstanceCount (\r
+  IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath\r
+  );\r
+\r
+EFI_STATUS\r
+CreateMenuStringToken (\r
+  IN BMM_CALLBACK_DATA                *CallbackData,\r
+  IN EFI_HII_HANDLE                   HiiHandle,\r
+  IN BM_MENU_OPTION                   *MenuOption\r
+  );\r
+\r
+UINT16                            *\r
+EfiLibStrFromDatahub (\r
+  IN EFI_DEVICE_PATH_PROTOCOL                 *DevPath\r
+  );\r
+\r
+VOID                              *\r
+GetLegacyBootOptionVar (\r
+  IN  UINTN                            DeviceType,\r
+  OUT UINTN                            *OptionIndex,\r
+  OUT UINTN                            *OptionSize\r
+ );\r
+\r
+EFI_STATUS\r
+InitializeBM (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsStartBootMaint (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+InitializeStringDepository (VOID);\r
+\r
+EFI_STRING_ID\r
+GetStringTokenFromDepository (\r
+  IN   BMM_CALLBACK_DATA     *CallbackData,\r
+  IN   STRING_DEPOSITORY     *StringDepository\r
+  );\r
+\r
+VOID\r
+ReclaimStringDepository (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+CleanUpStringDepository (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+ApplyChangeHandler (\r
+  IN  BMM_CALLBACK_DATA               *Private,\r
+  IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap,\r
+  IN  EFI_FORM_ID                     FormId\r
+  );\r
+\r
+VOID\r
+DiscardChangeHandler (\r
+  IN  BMM_CALLBACK_DATA               *Private,\r
+  IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap\r
+  );\r
+\r
+VOID\r
+UpdatePageId (\r
+  BMM_CALLBACK_DATA              *Private,\r
+  UINT16                         NewPageId\r
+  );\r
+\r
+EFI_STATUS\r
+BootThisFile (\r
+  IN BM_FILE_CONTEXT                   *FileContext\r
+  );\r
+\r
+BOOLEAN\r
+UpdateFileExplorer (\r
+  IN BMM_CALLBACK_DATA            *CallbackData,\r
+  IN UINT16                       KeyValue\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FileExplorerCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  );\r
+\r
+EFI_STATUS\r
+FormSetDispatcher (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  );\r
+\r
+//\r
+// Global variable in this program (defined in data.c)\r
+//\r
+extern BM_MENU_OPTION             BootOptionMenu;\r
+extern BM_MENU_OPTION             DriverOptionMenu;\r
+extern BM_MENU_OPTION             FsOptionMenu;\r
+extern BM_MENU_OPTION             ConsoleInpMenu;\r
+extern BM_MENU_OPTION             ConsoleOutMenu;\r
+extern BM_MENU_OPTION             ConsoleErrMenu;\r
+extern BM_MENU_OPTION             DirectoryMenu;\r
+extern BM_MENU_OPTION             DriverMenu;\r
+extern BM_MENU_OPTION             TerminalMenu;\r
+extern BM_MENU_OPTION             LegacyFDMenu;\r
+extern BM_MENU_OPTION             LegacyHDMenu;\r
+extern BM_MENU_OPTION             LegacyCDMenu;\r
+extern BM_MENU_OPTION             LegacyNETMenu;\r
+extern BM_MENU_OPTION             LegacyBEVMenu;\r
+extern UINT16                     TerminalType[];\r
+extern COM_ATTR                   BaudRateList[19];\r
+extern COM_ATTR                   DataBitsList[4];\r
+extern COM_ATTR                   ParityList[5];\r
+extern COM_ATTR                   StopBitsList[3];\r
+extern EFI_GUID                   Guid[4];\r
+extern EFI_HII_UPDATE_DATA        gUpdateData;\r
+extern STRING_DEPOSITORY          *FileOptionStrDepository;\r
+extern STRING_DEPOSITORY          *ConsoleOptionStrDepository;\r
+extern STRING_DEPOSITORY          *BootOptionStrDepository;\r
+extern STRING_DEPOSITORY          *BootOptionHelpStrDepository;\r
+extern STRING_DEPOSITORY          *DriverOptionStrDepository;\r
+extern STRING_DEPOSITORY          *DriverOptionHelpStrDepository;\r
+extern STRING_DEPOSITORY          *TerminalStrDepository;\r
+extern EFI_DEVICE_PATH_PROTOCOL   EndDevicePath[];\r
+extern EFI_GUID                   EfiLegacyDevOrderGuid;\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/BootOption.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/BootOption.c
new file mode 100644 (file)
index 0000000..9a2273c
--- /dev/null
@@ -0,0 +1,1697 @@
+/*++\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  bootoption.c\r
+\r
+Abstract:\r
+\r
+  Provide boot option support for Application "BootMaint"\r
+\r
+  Include file system navigation, system handle selection\r
+\r
+  Boot option manipulation\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+#include "BBSsupport.h"\r
+\r
+BM_MENU_ENTRY *\r
+BOpt_CreateMenuEntry (\r
+  UINTN           MenuType\r
+  )\r
+/*++\r
+\r
+Routine Description\r
+  Create Menu Entry for future use, make all types together\r
+  in order to reduce code size\r
+\r
+Arguments:\r
+  MenuType            Use this parameter to identify current\r
+                      Menu type\r
+\r
+Returns:\r
+  NULL                Cannot allocate memory for current menu\r
+                      entry\r
+  Others              A valid pointer pointing to the allocated\r
+                      memory pool for current menu entry\r
+\r
+--*/\r
+{\r
+  BM_MENU_ENTRY *MenuEntry;\r
+  UINTN         ContextSize;\r
+\r
+  switch (MenuType) {\r
+  case BM_LOAD_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_LOAD_CONTEXT);\r
+    break;\r
+\r
+  case BM_FILE_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_FILE_CONTEXT);\r
+    break;\r
+\r
+  case BM_CONSOLE_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_CONSOLE_CONTEXT);\r
+    break;\r
+\r
+  case BM_TERMINAL_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_TERMINAL_CONTEXT);\r
+    break;\r
+\r
+  case BM_HANDLE_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_HANDLE_CONTEXT);\r
+    break;\r
+\r
+  case BM_LEGACY_DEV_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_LEGACY_DEVICE_CONTEXT);\r
+    break;\r
+\r
+  default:\r
+    ContextSize = 0;\r
+    break;\r
+\r
+  }\r
+\r
+  if (0 == ContextSize) {\r
+    return NULL;\r
+  }\r
+\r
+  MenuEntry = EfiAllocateZeroPool (sizeof (BM_MENU_ENTRY));\r
+  if (NULL == MenuEntry) {\r
+    return MenuEntry;\r
+  }\r
+\r
+  MenuEntry->VariableContext = EfiAllocateZeroPool (ContextSize);\r
+  if (NULL == MenuEntry->VariableContext) {\r
+    SafeFreePool (MenuEntry);\r
+    MenuEntry = NULL;\r
+    return MenuEntry;\r
+  }\r
+\r
+  MenuEntry->Signature        = BM_MENU_ENTRY_SIGNATURE;\r
+  MenuEntry->ContextSelection = MenuType;\r
+  return MenuEntry;\r
+}\r
+\r
+VOID\r
+BOpt_DestroyMenuEntry (\r
+  BM_MENU_ENTRY         *MenuEntry\r
+  )\r
+/*++\r
+  Routine Description :\r
+    Destroy the menu entry passed in\r
+\r
+  Arguments :\r
+    The menu entry need to be destroyed\r
+\r
+  Returns :\r
+    None\r
+\r
+--*/\r
+{\r
+  BM_LOAD_CONTEXT           *LoadContext;\r
+  BM_FILE_CONTEXT           *FileContext;\r
+  BM_CONSOLE_CONTEXT        *ConsoleContext;\r
+  BM_TERMINAL_CONTEXT       *TerminalContext;\r
+  BM_HANDLE_CONTEXT         *HandleContext;\r
+  BM_LEGACY_DEVICE_CONTEXT  *LegacyDevContext;\r
+\r
+  //\r
+  //  Select by the type in Menu entry for current context type\r
+  //\r
+  switch (MenuEntry->ContextSelection) {\r
+  case BM_LOAD_CONTEXT_SELECT:\r
+    LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext;\r
+    SafeFreePool (LoadContext->FilePathList);\r
+    SafeFreePool (LoadContext->LoadOption);\r
+    SafeFreePool (LoadContext->OptionalData);\r
+    SafeFreePool (LoadContext);\r
+    break;\r
+\r
+  case BM_FILE_CONTEXT_SELECT:\r
+    FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+\r
+    if (!FileContext->IsRoot) {\r
+      SafeFreePool (FileContext->DevicePath);\r
+    } else {\r
+      if (FileContext->FHandle != NULL) {\r
+        FileContext->FHandle->Close (FileContext->FHandle);\r
+      }\r
+    }\r
+\r
+    SafeFreePool (FileContext->FileName);\r
+    SafeFreePool (FileContext->Info);\r
+    SafeFreePool (FileContext);\r
+    break;\r
+\r
+  case BM_CONSOLE_CONTEXT_SELECT:\r
+    ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext;\r
+    SafeFreePool (ConsoleContext->DevicePath);\r
+    SafeFreePool (ConsoleContext);\r
+    break;\r
+\r
+  case BM_TERMINAL_CONTEXT_SELECT:\r
+    TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext;\r
+    SafeFreePool (TerminalContext->DevicePath);\r
+    SafeFreePool (TerminalContext);\r
+    break;\r
+\r
+  case BM_HANDLE_CONTEXT_SELECT:\r
+    HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext;\r
+    SafeFreePool (HandleContext);\r
+    break;\r
+\r
+  case BM_LEGACY_DEV_CONTEXT_SELECT:\r
+    LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext;\r
+    SafeFreePool (LegacyDevContext);\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  SafeFreePool (MenuEntry->DisplayString);\r
+  if (NULL != MenuEntry->HelpString) {\r
+    SafeFreePool (MenuEntry->HelpString);\r
+  }\r
+\r
+  SafeFreePool (MenuEntry);\r
+}\r
+\r
+BM_MENU_ENTRY *\r
+BOpt_GetMenuEntry (\r
+  BM_MENU_OPTION      *MenuOption,\r
+  UINTN               MenuNumber\r
+  )\r
+/*++\r
+  Rountine Description :\r
+    Use this routine to get one particular menu entry in specified\r
+    menu\r
+\r
+  Arguments :\r
+    MenuOption        The menu that we will search\r
+\r
+    MenuNumber        The menunubmer that we want\r
+\r
+  Returns :\r
+    The desired menu entry\r
+\r
+--*/\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  UINTN           Index;\r
+  LIST_ENTRY      *List;\r
+\r
+  if (MenuNumber >= MenuOption->MenuNumber) {\r
+    return NULL;\r
+  }\r
+\r
+  List = MenuOption->Head.ForwardLink;\r
+  for (Index = 0; Index < MenuNumber; Index++) {\r
+    List = List->ForwardLink;\r
+  }\r
+\r
+  NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE);\r
+\r
+  return NewMenuEntry;\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_FindFileSystem (\r
+  IN BMM_CALLBACK_DATA          *CallbackData\r
+  )\r
+/*++\r
+\r
+Routine Description\r
+  Find file systems for current Extensible Firmware\r
+  Including Handles that support Simple File System\r
+  protocol, Load File protocol.\r
+\r
+  Building up the FileSystem Menu for user selection\r
+  All file system will be stored in FsOptionMenu\r
+  for future use.\r
+\r
+Arguments:\r
+  CallbackData           -   BMM context data\r
+\r
+Returns:\r
+  EFI_SUCCESS            -   Success find the file system\r
+  EFI_OUT_OF_RESOURCES   -   Can not create menu entry\r
+\r
+--*/\r
+{\r
+  UINTN                     NoBlkIoHandles;\r
+  UINTN                     NoSimpleFsHandles;\r
+  UINTN                     NoLoadFileHandles;\r
+  EFI_HANDLE                *BlkIoHandle;\r
+  EFI_HANDLE                *SimpleFsHandle;\r
+  EFI_HANDLE                *LoadFileHandle;\r
+  UINT16                    *VolumeLabel;\r
+  EFI_BLOCK_IO_PROTOCOL     *BlkIo;\r
+  UINTN                     Index;\r
+  EFI_STATUS                Status;\r
+  BM_MENU_ENTRY             *MenuEntry;\r
+  BM_FILE_CONTEXT           *FileContext;\r
+  UINT16                    *TempStr;\r
+  UINTN                     OptionNumber;\r
+  VOID                      *Buffer;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINT16                    DeviceType;\r
+  BBS_BBS_DEVICE_PATH       BbsDevicePathNode;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  BOOLEAN                   RemovableMedia;\r
+\r
+\r
+  NoSimpleFsHandles = 0;\r
+  NoLoadFileHandles = 0;\r
+  OptionNumber      = 0;\r
+  InitializeListHead (&FsOptionMenu.Head);\r
+\r
+  //\r
+  // Locate Handles that support BlockIo protocol\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiBlockIoProtocolGuid,\r
+                  NULL,\r
+                  &NoBlkIoHandles,\r
+                  &BlkIoHandle\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+\r
+    for (Index = 0; Index < NoBlkIoHandles; Index++) {\r
+      Status = gBS->HandleProtocol (\r
+                      BlkIoHandle[Index],\r
+                      &gEfiBlockIoProtocolGuid,\r
+                      (VOID **) &BlkIo\r
+                      );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media\r
+      //\r
+      if (BlkIo->Media->RemovableMedia) {\r
+        Buffer = EfiAllocateZeroPool (BlkIo->Media->BlockSize);\r
+        if (NULL == Buffer) {\r
+          SafeFreePool (BlkIoHandle);\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        BlkIo->ReadBlocks (\r
+                BlkIo,\r
+                BlkIo->Media->MediaId,\r
+                0,\r
+                BlkIo->Media->BlockSize,\r
+                Buffer\r
+                );\r
+        SafeFreePool (Buffer);\r
+      }\r
+    }\r
+    SafeFreePool (BlkIoHandle);\r
+  }\r
+\r
+  //\r
+  // Locate Handles that support Simple File System protocol\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  NULL,\r
+                  &NoSimpleFsHandles,\r
+                  &SimpleFsHandle\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Find all the instances of the File System prototocol\r
+    //\r
+    for (Index = 0; Index < NoSimpleFsHandles; Index++) {\r
+      Status = gBS->HandleProtocol (\r
+                      SimpleFsHandle[Index],\r
+                      &gEfiBlockIoProtocolGuid,\r
+                      (VOID **) &BlkIo\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // If no block IO exists assume it's NOT a removable media\r
+        //\r
+        RemovableMedia = FALSE;\r
+      } else {\r
+        //\r
+        // If block IO exists check to see if it's remobable media\r
+        //\r
+        RemovableMedia = BlkIo->Media->RemovableMedia;\r
+      }\r
+\r
+      //\r
+      // Allocate pool for this load option\r
+      //\r
+      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+      if (NULL == MenuEntry) {\r
+        SafeFreePool (SimpleFsHandle);\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+\r
+      FileContext->Handle     = SimpleFsHandle[Index];\r
+      MenuEntry->OptionNumber = Index;\r
+      FileContext->FHandle    = EfiLibOpenRoot (FileContext->Handle);\r
+      if (!FileContext->FHandle) {\r
+        BOpt_DestroyMenuEntry (MenuEntry);\r
+        continue;\r
+      }\r
+\r
+      MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle));\r
+      FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle);\r
+      FileContext->FileName = EfiStrDuplicate (L"\\");\r
+      FileContext->DevicePath = FileDevicePath (\r
+                                  FileContext->Handle,\r
+                                  FileContext->FileName\r
+                                  );\r
+      FileContext->IsDir            = TRUE;\r
+      FileContext->IsRoot           = TRUE;\r
+      FileContext->IsRemovableMedia = RemovableMedia;\r
+      FileContext->IsLoadFile       = FALSE;\r
+\r
+      //\r
+      // Get current file system's Volume Label\r
+      //\r
+      if (FileContext->Info == NULL) {\r
+        VolumeLabel = L"NO FILE SYSTEM INFO";\r
+      } else {\r
+        if (FileContext->Info->VolumeLabel == NULL) {\r
+          VolumeLabel = L"NULL VOLUME LABEL";\r
+        } else {\r
+          VolumeLabel = FileContext->Info->VolumeLabel;\r
+          if (*VolumeLabel == 0x0000) {\r
+            VolumeLabel = L"NO VOLUME LABEL";\r
+          }\r
+        }\r
+      }\r
+\r
+      TempStr                   = MenuEntry->HelpString;\r
+      MenuEntry->DisplayString  = EfiAllocateZeroPool (MAX_CHAR);\r
+      ASSERT (MenuEntry->DisplayString != NULL);\r
+      UnicodeSPrint (\r
+        MenuEntry->DisplayString,\r
+        MAX_CHAR,\r
+        L"%s, [%s]",\r
+        VolumeLabel,\r
+        TempStr\r
+        );\r
+      OptionNumber++;\r
+      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+    }\r
+  }\r
+\r
+  if (NoSimpleFsHandles != 0) {\r
+    SafeFreePool (SimpleFsHandle);\r
+  }\r
+  //\r
+  // Searching for handles that support Load File protocol\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiLoadFileProtocolGuid,\r
+                  NULL,\r
+                  &NoLoadFileHandles,\r
+                  &LoadFileHandle\r
+                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    for (Index = 0; Index < NoLoadFileHandles; Index++) {\r
+      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+      if (NULL == MenuEntry) {\r
+        SafeFreePool (LoadFileHandle);\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      FileContext                   = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+      FileContext->IsRemovableMedia = FALSE;\r
+      FileContext->IsLoadFile       = TRUE;\r
+      FileContext->Handle           = LoadFileHandle[Index];\r
+      FileContext->IsRoot           = TRUE;\r
+\r
+      FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle);\r
+\r
+      MenuEntry->HelpString     = DevicePathToStr (FileContext->DevicePath);\r
+\r
+      TempStr                   = MenuEntry->HelpString;\r
+      MenuEntry->DisplayString  = EfiAllocateZeroPool (MAX_CHAR);\r
+      ASSERT (MenuEntry->DisplayString != NULL);\r
+      UnicodeSPrint (\r
+        MenuEntry->DisplayString,\r
+        MAX_CHAR,\r
+        L"Load File [%s]",\r
+        TempStr\r
+        );\r
+\r
+      MenuEntry->OptionNumber = OptionNumber;\r
+      OptionNumber++;\r
+      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+    }\r
+  }\r
+\r
+  if (NoLoadFileHandles != 0) {\r
+    SafeFreePool (LoadFileHandle);\r
+  }\r
+\r
+  //\r
+  // Add Legacy Boot Option Support Here\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiLegacyBiosProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &LegacyBios\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+\r
+    for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) {\r
+      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+      if (NULL == MenuEntry) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      FileContext                       = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+\r
+      FileContext->IsRemovableMedia     = FALSE;\r
+      FileContext->IsLoadFile           = TRUE;\r
+      FileContext->IsBootLegacy         = TRUE;\r
+      DeviceType                        = (UINT16) Index;\r
+      BbsDevicePathNode.Header.Type     = BBS_DEVICE_PATH;\r
+      BbsDevicePathNode.Header.SubType  = BBS_BBS_DP;\r
+      SetDevicePathNodeLength (\r
+        &BbsDevicePathNode.Header,\r
+        sizeof (BBS_BBS_DEVICE_PATH)\r
+        );\r
+      BbsDevicePathNode.DeviceType  = DeviceType;\r
+      BbsDevicePathNode.StatusFlag  = 0;\r
+      BbsDevicePathNode.String[0]   = 0;\r
+      DevicePath = AppendDevicePathNode (\r
+                    EndDevicePath,\r
+                    (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode\r
+                    );\r
+\r
+      FileContext->DevicePath   = DevicePath;\r
+      MenuEntry->HelpString     = DevicePathToStr (FileContext->DevicePath);\r
+\r
+      TempStr                   = MenuEntry->HelpString;\r
+      MenuEntry->DisplayString  = EfiAllocateZeroPool (MAX_CHAR);\r
+      ASSERT (MenuEntry->DisplayString != NULL);\r
+      UnicodeSPrint (\r
+        MenuEntry->DisplayString,\r
+        MAX_CHAR,\r
+        L"Boot Legacy [%s]",\r
+        TempStr\r
+        );\r
+      MenuEntry->OptionNumber = OptionNumber;\r
+      OptionNumber++;\r
+      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+    }\r
+  }\r
+  //\r
+  // Remember how many file system options are here\r
+  //\r
+  FsOptionMenu.MenuNumber = OptionNumber;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+BOpt_FreeMenu (\r
+  BM_MENU_OPTION        *FreeMenu\r
+  )\r
+/*++\r
+\r
+Routine Description\r
+  Free resources allocated in Allocate Rountine\r
+\r
+Arguments:\r
+  FreeMenu        Menu to be freed\r
+\r
+Returns:\r
+  VOID\r
+\r
+--*/\r
+{\r
+  BM_MENU_ENTRY *MenuEntry;\r
+  while (!IsListEmpty (&FreeMenu->Head)) {\r
+    MenuEntry = CR (\r
+                  FreeMenu->Head.ForwardLink,\r
+                  BM_MENU_ENTRY,\r
+                  Link,\r
+                  BM_MENU_ENTRY_SIGNATURE\r
+                  );\r
+    RemoveEntryList (&MenuEntry->Link);\r
+    BOpt_DestroyMenuEntry (MenuEntry);\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_FindFiles (\r
+  IN BMM_CALLBACK_DATA          *CallbackData,\r
+  IN BM_MENU_ENTRY              *MenuEntry\r
+  )\r
+/*++\r
+\r
+Routine Description\r
+  Find files under current directory\r
+  All files and sub-directories in current directory\r
+  will be stored in DirectoryMenu for future use.\r
+\r
+Arguments:\r
+  FileOption   -- Pointer for Dir to explore\r
+\r
+Returns:\r
+  TRUE         -- Get files from current dir successfully\r
+  FALSE        -- Can't get files from current dir\r
+\r
+--*/\r
+{\r
+  EFI_FILE_HANDLE NewDir;\r
+  EFI_FILE_HANDLE Dir;\r
+  EFI_FILE_INFO   *DirInfo;\r
+  UINTN           BufferSize;\r
+  UINTN           DirBufferSize;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_FILE_CONTEXT *FileContext;\r
+  BM_FILE_CONTEXT *NewFileContext;\r
+  UINTN           Pass;\r
+  EFI_STATUS      Status;\r
+  UINTN           OptionNumber;\r
+\r
+  FileContext   = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+  Dir           = FileContext->FHandle;\r
+  OptionNumber  = 0;\r
+  //\r
+  // Open current directory to get files from it\r
+  //\r
+  Status = Dir->Open (\r
+                  Dir,\r
+                  &NewDir,\r
+                  FileContext->FileName,\r
+                  EFI_FILE_READ_ONLY,\r
+                  0\r
+                  );\r
+  if (!FileContext->IsRoot) {\r
+    Dir->Close (Dir);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  DirInfo = EfiLibFileInfo (NewDir);\r
+  if (!DirInfo) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (!(DirInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  FileContext->DevicePath = FileDevicePath (\r
+                              FileContext->Handle,\r
+                              FileContext->FileName\r
+                              );\r
+\r
+  DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;\r
+  DirInfo       = EfiAllocateZeroPool (DirBufferSize);\r
+  if (!DirInfo) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Get all files in current directory\r
+  // Pass 1 to get Directories\r
+  // Pass 2 to get files that are EFI images\r
+  //\r
+  for (Pass = 1; Pass <= 2; Pass++) {\r
+    NewDir->SetPosition (NewDir, 0);\r
+    for (;;) {\r
+      BufferSize  = DirBufferSize;\r
+      Status      = NewDir->Read (NewDir, &BufferSize, DirInfo);\r
+      if (EFI_ERROR (Status) || BufferSize == 0) {\r
+        break;\r
+      }\r
+\r
+      if ((DirInfo->Attribute & EFI_FILE_DIRECTORY && Pass == 2) ||\r
+          (!(DirInfo->Attribute & EFI_FILE_DIRECTORY) && Pass == 1)\r
+          ) {\r
+        //\r
+        // Pass 1 is for Directories\r
+        // Pass 2 is for file names\r
+        //\r
+        continue;\r
+      }\r
+\r
+      if (!(BOpt_IsEfiImageName (DirInfo->FileName) || DirInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
+        //\r
+        // Slip file unless it is a directory entry or a .EFI file\r
+        //\r
+        continue;\r
+      }\r
+\r
+      NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+      if (NULL == NewMenuEntry) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      NewFileContext          = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewFileContext->Handle  = FileContext->Handle;\r
+      NewFileContext->FileName = BOpt_AppendFileName (\r
+                                  FileContext->FileName,\r
+                                  DirInfo->FileName\r
+                                  );\r
+      NewFileContext->FHandle = NewDir;\r
+      NewFileContext->DevicePath = FileDevicePath (\r
+                                    NewFileContext->Handle,\r
+                                    NewFileContext->FileName\r
+                                    );\r
+      NewMenuEntry->HelpString = NULL;\r
+\r
+      MenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                        CallbackData,\r
+                                        FileOptionStrDepository\r
+                                        );\r
+\r
+      NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);\r
+\r
+      if (NewFileContext->IsDir) {\r
+        BufferSize                  = StrLen (DirInfo->FileName) * 2 + 6;\r
+        NewMenuEntry->DisplayString = EfiAllocateZeroPool (BufferSize);\r
+\r
+        UnicodeSPrint (\r
+          NewMenuEntry->DisplayString,\r
+          BufferSize,\r
+          L"<%s>",\r
+          DirInfo->FileName\r
+          );\r
+\r
+      } else {\r
+        NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName);\r
+      }\r
+\r
+      NewFileContext->IsRoot            = FALSE;\r
+      NewFileContext->IsLoadFile        = FALSE;\r
+      NewFileContext->IsRemovableMedia  = FALSE;\r
+\r
+      NewMenuEntry->OptionNumber        = OptionNumber;\r
+      OptionNumber++;\r
+      InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);\r
+    }\r
+  }\r
+\r
+  DirectoryMenu.MenuNumber = OptionNumber;\r
+  SafeFreePool (DirInfo);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_GetLegacyOptions (\r
+  VOID\r
+  )\r
+/*++\r
+Routine Description:\r
+\r
+  Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+  The device info of legacy device.\r
+\r
+--*/\r
+{\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_LEGACY_DEVICE_CONTEXT  *NewLegacyDevContext;\r
+  EFI_STATUS                Status;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINT16                    HddCount;\r
+  HDD_INFO                  *HddInfo;\r
+  UINT16                    BbsCount;\r
+  BBS_TABLE                 *BbsTable;\r
+  UINTN                     Index;\r
+  CHAR16                    DescString[100];\r
+  UINTN                     FDNum;\r
+  UINTN                     HDNum;\r
+  UINTN                     CDNum;\r
+  UINTN                     NETNum;\r
+  UINTN                     BEVNum;\r
+\r
+  NewMenuEntry  = NULL;\r
+  HddInfo       = NULL;\r
+  BbsTable      = NULL;\r
+  BbsCount      = 0;\r
+\r
+  //\r
+  // Initialize Bbs Table Context from BBS info data\r
+  //\r
+  InitializeListHead (&LegacyFDMenu.Head);\r
+  InitializeListHead (&LegacyHDMenu.Head);\r
+  InitializeListHead (&LegacyCDMenu.Head);\r
+  InitializeListHead (&LegacyNETMenu.Head);\r
+  InitializeListHead (&LegacyBEVMenu.Head);\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiLegacyBiosProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &LegacyBios\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = LegacyBios->GetBbsInfo (\r
+                          LegacyBios,\r
+                          &HddCount,\r
+                          &HddInfo,\r
+                          &BbsCount,\r
+                          &BbsTable\r
+                          );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  FDNum   = 0;\r
+  HDNum   = 0;\r
+  CDNum   = 0;\r
+  NETNum  = 0;\r
+  BEVNum  = 0;\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) ||\r
+        (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      break;\r
+    }\r
+\r
+    NewLegacyDevContext           = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewLegacyDevContext->BbsTable = &BbsTable[Index];\r
+    NewLegacyDevContext->Index    = Index;\r
+    NewLegacyDevContext->BbsCount = BbsCount;\r
+    BdsBuildLegacyDevNameString (\r
+      &BbsTable[Index],\r
+      Index,\r
+      sizeof (DescString),\r
+      DescString\r
+      );\r
+    NewLegacyDevContext->Description = EfiAllocateZeroPool (StrSize (DescString));\r
+    if (NULL == NewLegacyDevContext->Description) {\r
+      break;\r
+    }\r
+\r
+    CopyMem (NewLegacyDevContext->Description, DescString, StrSize (DescString));\r
+    NewMenuEntry->DisplayString = NewLegacyDevContext->Description;\r
+    NewMenuEntry->HelpString    = NULL;\r
+\r
+    switch (BbsTable[Index].DeviceType) {\r
+    case BBS_FLOPPY:\r
+      InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);\r
+      FDNum++;\r
+      break;\r
+\r
+    case BBS_HARDDISK:\r
+      InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);\r
+      HDNum++;\r
+      break;\r
+\r
+    case BBS_CDROM:\r
+      InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);\r
+      CDNum++;\r
+      break;\r
+\r
+    case BBS_EMBED_NETWORK:\r
+      InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);\r
+      NETNum++;\r
+      break;\r
+\r
+    case BBS_BEV_DEVICE:\r
+      InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);\r
+      BEVNum++;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index != BbsCount) {\r
+    BOpt_FreeLegacyOptions ();\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  LegacyFDMenu.MenuNumber   = FDNum;\r
+  LegacyHDMenu.MenuNumber   = HDNum;\r
+  LegacyCDMenu.MenuNumber   = CDNum;\r
+  LegacyNETMenu.MenuNumber  = NETNum;\r
+  LegacyBEVMenu.MenuNumber  = BEVNum;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+BOpt_FreeLegacyOptions (\r
+  VOID\r
+  )\r
+{\r
+  BOpt_FreeMenu (&LegacyFDMenu);\r
+  BOpt_FreeMenu (&LegacyHDMenu);\r
+  BOpt_FreeMenu (&LegacyCDMenu);\r
+  BOpt_FreeMenu (&LegacyNETMenu);\r
+  BOpt_FreeMenu (&LegacyBEVMenu);\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_GetBootOptions (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Build the BootOptionMenu according to BootOrder Variable.\r
+  This Routine will access the Boot#### to get EFI_LOAD_OPTION\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+  The number of the Var Boot####\r
+\r
+--*/\r
+{\r
+  UINTN                     Index;\r
+  UINT16                    BootString[10];\r
+  UINT8                     *LoadOptionFromVar;\r
+  UINT8                     *LoadOption;\r
+  UINTN                     BootOptionSize;\r
+  BOOLEAN                   BootNextFlag;\r
+  UINT16                    *BootOrderList;\r
+  UINTN                     BootOrderListSize;\r
+  UINT16                    *BootNext;\r
+  UINTN                     BootNextSize;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_LOAD_CONTEXT           *NewLoadContext;\r
+  UINT8                     *LoadOptionPtr;\r
+  UINTN                     StringSize;\r
+  UINTN                     OptionalDataSize;\r
+  UINT8                     *LoadOptionEnd;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  UINTN                     MenuCount;\r
+  UINT8                     *Ptr;\r
+\r
+  MenuCount         = 0;\r
+  BootOrderListSize = 0;\r
+  BootNextSize      = 0;\r
+  BootOrderList     = NULL;\r
+  BootNext          = NULL;\r
+  LoadOptionFromVar = NULL;\r
+  BOpt_FreeMenu (&BootOptionMenu);\r
+  InitializeListHead (&BootOptionMenu.Head);\r
+\r
+  //\r
+  // Get the BootOrder from the Var\r
+  //\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+\r
+  //\r
+  // Get the BootNext from the Var\r
+  //\r
+  BootNext = BdsLibGetVariableAndSize (\r
+              L"BootNext",\r
+              &gEfiGlobalVariableGuid,\r
+              &BootNextSize\r
+              );\r
+\r
+  if (BootNext) {\r
+    if (BootNextSize != sizeof (UINT16)) {\r
+      SafeFreePool (BootNext);\r
+      BootNext = NULL;\r
+    }\r
+  }\r
+\r
+  for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
+    UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);\r
+    //\r
+    //  Get all loadoptions from the VAR\r
+    //\r
+    LoadOptionFromVar = BdsLibGetVariableAndSize (\r
+                          BootString,\r
+                          &gEfiGlobalVariableGuid,\r
+                          &BootOptionSize\r
+                          );\r
+    if (!LoadOptionFromVar) {\r
+      continue;\r
+    }\r
+\r
+    LoadOption = EfiAllocateZeroPool (BootOptionSize);\r
+    if (!LoadOption) {\r
+      continue;\r
+    }\r
+\r
+    CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize);\r
+    SafeFreePool (LoadOptionFromVar);\r
+\r
+    if (BootNext) {\r
+      BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]);\r
+    } else {\r
+      BootNextFlag = FALSE;\r
+    }\r
+\r
+    if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) {\r
+      SafeFreePool (LoadOption);\r
+      continue;\r
+    }\r
+    //\r
+    // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.\r
+    // the buffer allocated already should be freed before returning.\r
+    //\r
+    NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    NewLoadContext                      = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    LoadOptionPtr                       = LoadOption;\r
+    LoadOptionEnd                       = LoadOption + BootOptionSize;\r
+\r
+    NewMenuEntry->OptionNumber          = BootOrderList[Index];\r
+    NewLoadContext->LoadOptionModified  = FALSE;\r
+    NewLoadContext->Deleted             = FALSE;\r
+    NewLoadContext->IsBootNext          = BootNextFlag;\r
+\r
+    //\r
+    // Is a Legacy Device?\r
+    //\r
+    Ptr = (UINT8 *) LoadOption;\r
+\r
+    //\r
+    // Attribute = *(UINT32 *)Ptr;\r
+    //\r
+    Ptr += sizeof (UINT32);\r
+\r
+    //\r
+    // FilePathSize = *(UINT16 *)Ptr;\r
+    //\r
+    Ptr += sizeof (UINT16);\r
+\r
+    //\r
+    // Description = (CHAR16 *)Ptr;\r
+    //\r
+    Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+    //\r
+    // Now Ptr point to Device Path\r
+    //\r
+    DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+    if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {\r
+      NewLoadContext->IsLegacy = TRUE;\r
+    } else {\r
+      NewLoadContext->IsLegacy = FALSE;\r
+    }\r
+    //\r
+    // LoadOption is a pointer type of UINT8\r
+    // for easy use with following LOAD_OPTION\r
+    // embedded in this struct\r
+    //\r
+    NewLoadContext->LoadOption      = LoadOption;\r
+    NewLoadContext->LoadOptionSize  = BootOptionSize;\r
+\r
+    NewLoadContext->Attributes      = *(UINT32 *) LoadOptionPtr;\r
+    NewLoadContext->IsActive        = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
+\r
+    NewLoadContext->ForceReconnect  = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+    LoadOptionPtr += sizeof (UINT32);\r
+\r
+    NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
+    LoadOptionPtr += sizeof (UINT16);\r
+\r
+    StringSize                  = StrSize ((UINT16 *) LoadOptionPtr);\r
+    NewLoadContext->Description = EfiAllocateZeroPool (StringSize);\r
+    ASSERT (NewLoadContext->Description != NULL);\r
+    CopyMem (\r
+      NewLoadContext->Description,\r
+      (UINT16 *) LoadOptionPtr,\r
+      StringSize\r
+      );\r
+    NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+\r
+    LoadOptionPtr += StringSize;\r
+\r
+    NewLoadContext->FilePathList = EfiAllocateZeroPool (NewLoadContext->FilePathListLength);\r
+    ASSERT (NewLoadContext->FilePathList != NULL);\r
+    CopyMem (\r
+      NewLoadContext->FilePathList,\r
+      (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
+      NewLoadContext->FilePathListLength\r
+      );\r
+\r
+    NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
+    NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                        CallbackData,\r
+                                        BootOptionStrDepository\r
+                                        );\r
+    NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+                                      CallbackData,\r
+                                      BootOptionHelpStrDepository\r
+                                      );\r
+    LoadOptionPtr += NewLoadContext->FilePathListLength;\r
+\r
+    if (LoadOptionPtr < LoadOptionEnd) {\r
+      OptionalDataSize = BootOptionSize -\r
+        sizeof (UINT32) -\r
+        sizeof (UINT16) -\r
+        StringSize -\r
+        NewLoadContext->FilePathListLength;\r
+\r
+      NewLoadContext->OptionalData = EfiAllocateZeroPool (OptionalDataSize);\r
+      ASSERT (NewLoadContext->OptionalData != NULL);\r
+      CopyMem (\r
+        NewLoadContext->OptionalData,\r
+        LoadOptionPtr,\r
+        OptionalDataSize\r
+        );\r
+\r
+      NewLoadContext->OptionalDataSize = OptionalDataSize;\r
+    }\r
+\r
+    InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
+    MenuCount++;\r
+  }\r
+\r
+  SafeFreePool (BootNext);\r
+  SafeFreePool (BootOrderList);\r
+  BootOptionMenu.MenuNumber = MenuCount;\r
+  return MenuCount;\r
+}\r
+\r
+CHAR16 *\r
+BOpt_AppendFileName (\r
+  IN  CHAR16  *Str1,\r
+  IN  CHAR16  *Str2\r
+  )\r
+/*++\r
+\r
+Routine Description\r
+  Append file name to existing file name.\r
+\r
+Arguments:\r
+  Str1  -   existing file name\r
+  Str2  -   file name to be appended\r
+\r
+Returns:\r
+  Allocate a new string to hold the appended result.\r
+  Caller is responsible to free the returned string.\r
+\r
+--*/\r
+{\r
+  UINTN   Size1;\r
+  UINTN   Size2;\r
+  CHAR16  *Str;\r
+  CHAR16  *Ptr;\r
+  CHAR16  *LastSlash;\r
+\r
+  Size1 = StrSize (Str1);\r
+  Size2 = StrSize (Str2);\r
+  Str   = EfiAllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));\r
+  ASSERT (Str != NULL);\r
+\r
+  StrCat (Str, Str1);\r
+  if (!((*Str == '\\') && (*(Str + 1) == 0))) {\r
+    StrCat (Str, L"\\");\r
+  }\r
+\r
+  StrCat (Str, Str2);\r
+\r
+  Ptr       = Str;\r
+  LastSlash = Str;\r
+  while (*Ptr != 0) {\r
+    if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) != 0) {\r
+      //\r
+      // Convert \Name\..\ to \\r
+      // DO NOT convert the .. if it is at the end of the string. This will\r
+      // break the .. behavior in changing directories.\r
+      //\r
+      StrCpy (LastSlash, Ptr + 3);\r
+      Ptr = LastSlash;\r
+    } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {\r
+      //\r
+      // Convert a \.\ to a \\r
+      //\r
+      StrCpy (Ptr, Ptr + 2);\r
+      Ptr = LastSlash;\r
+    } else if (*Ptr == '\\') {\r
+      LastSlash = Ptr;\r
+    }\r
+\r
+    Ptr++;\r
+  }\r
+\r
+  return Str;\r
+}\r
+\r
+BOOLEAN\r
+BOpt_IsEfiImageName (\r
+  IN UINT16  *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description\r
+  Check whether current FileName point to a valid\r
+  Efi Image File.\r
+\r
+Arguments:\r
+  FileName  -   File need to be checked.\r
+\r
+Returns:\r
+  TRUE  -   Is Efi Image\r
+  FALSE -   Not a valid Efi Image\r
+\r
+--*/\r
+{\r
+  //\r
+  // Search for ".efi" extension\r
+  //\r
+  while (*FileName) {\r
+    if (FileName[0] == '.') {\r
+      if (FileName[1] == 'e' || FileName[1] == 'E') {\r
+        if (FileName[2] == 'f' || FileName[2] == 'F') {\r
+          if (FileName[3] == 'i' || FileName[3] == 'I') {\r
+            return TRUE;\r
+          } else if (FileName[3] == 0x0000) {\r
+            return FALSE;\r
+          }\r
+        } else if (FileName[2] == 0x0000) {\r
+          return FALSE;\r
+        }\r
+      } else if (FileName[1] == 0x0000) {\r
+        return FALSE;\r
+      }\r
+    }\r
+\r
+    FileName += 1;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+BOpt_IsEfiApp (\r
+  IN EFI_FILE_HANDLE Dir,\r
+  IN UINT16          *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Check whether current FileName point to a valid Efi Application\r
+\r
+Arguments:\r
+  Dir       -   Pointer to current Directory\r
+  FileName  -   Pointer to current File name.\r
+\r
+Returns:\r
+  TRUE      -   Is a valid Efi Application\r
+  FALSE     -   not a valid Efi Application\r
+\r
+--*/\r
+{\r
+  UINTN                       BufferSize;\r
+  EFI_IMAGE_DOS_HEADER        DosHdr;\r
+  EFI_IMAGE_NT_HEADERS        PeHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER32 *PeOpt32;\r
+  EFI_IMAGE_OPTIONAL_HEADER64 *PeOpt64;\r
+  UINT16                      Subsystem;\r
+  EFI_FILE_HANDLE             File;\r
+  EFI_STATUS                  Status;\r
+\r
+  Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);\r
+  File->Read (File, &BufferSize, &DosHdr);\r
+  if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+    File->Close (File);\r
+    return FALSE;\r
+  }\r
+\r
+  File->SetPosition (File, DosHdr.e_lfanew);\r
+  BufferSize = sizeof (EFI_IMAGE_NT_HEADERS);\r
+  File->Read (File, &BufferSize, &PeHdr);\r
+  if (PeHdr.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+    File->Close (File);\r
+    return FALSE;\r
+  }\r
+  //\r
+  // Determine PE type and read subsytem\r
+  // BugBug : We should be using EFI_IMAGE_MACHINE_TYPE_SUPPORTED (machine)\r
+  // macro to detect the machine type.\r
+  // We should not be using  EFI_IMAGE_OPTIONAL_HEADER32 and\r
+  // EFI_IMAGE_OPTIONAL_HEADER64\r
+  //\r
+  if (PeHdr.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    PeOpt32   = (EFI_IMAGE_OPTIONAL_HEADER32 *) &(PeHdr.OptionalHeader);\r
+    Subsystem = PeOpt32->Subsystem;\r
+  } else if (PeHdr.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+    PeOpt64   = (EFI_IMAGE_OPTIONAL_HEADER64 *) &(PeHdr.OptionalHeader);\r
+    Subsystem = PeOpt64->Subsystem;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+\r
+  if (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
+    File->Close (File);\r
+    return TRUE;\r
+  } else {\r
+    File->Close (File);\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_FindDrivers (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description\r
+  Find drivers that will be added as Driver#### variables from handles\r
+  in current system environment\r
+  All valid handles in the system except those consume SimpleFs, LoadFile\r
+  are stored in DriverMenu for future use.\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+  EFI_SUCCESS\r
+  Others\r
+\r
+--*/\r
+{\r
+  UINTN                           NoDevicePathHandles;\r
+  EFI_HANDLE                      *DevicePathHandle;\r
+  UINTN                           Index;\r
+  EFI_STATUS                      Status;\r
+  BM_MENU_ENTRY                   *NewMenuEntry;\r
+  BM_HANDLE_CONTEXT               *NewHandleContext;\r
+  EFI_HANDLE                      CurHandle;\r
+  UINTN                           OptionNumber;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;\r
+  EFI_LOAD_FILE_PROTOCOL          *LoadFile;\r
+\r
+  SimpleFs  = NULL;\r
+  LoadFile  = NULL;\r
+\r
+  InitializeListHead (&DriverMenu.Head);\r
+\r
+  //\r
+  // At first, get all handles that support Device Path\r
+  // protocol which is the basic requirement for\r
+  // Driver####\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  NULL,\r
+                  &NoDevicePathHandles,\r
+                  &DevicePathHandle\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  OptionNumber = 0;\r
+  for (Index = 0; Index < NoDevicePathHandles; Index++) {\r
+    CurHandle = DevicePathHandle[Index];\r
+\r
+    //\r
+    //  Check whether this handle support\r
+    //  driver binding\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    CurHandle,\r
+                    &gEfiSimpleFileSystemProtocolGuid,\r
+                    (VOID **) &SimpleFs\r
+                    );\r
+    if (Status == EFI_SUCCESS) {\r
+      continue;\r
+    }\r
+\r
+    Status = gBS->HandleProtocol (\r
+                    CurHandle,\r
+                    &gEfiLoadFileProtocolGuid,\r
+                    (VOID **) &LoadFile\r
+                    );\r
+    if (Status == EFI_SUCCESS) {\r
+      continue;\r
+    }\r
+\r
+    NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      SafeFreePool (DevicePathHandle);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    NewHandleContext              = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewHandleContext->Handle      = CurHandle;\r
+    NewHandleContext->DevicePath  = DevicePathFromHandle (CurHandle);\r
+    NewMenuEntry->DisplayString = DevicePathToStr (NewHandleContext->DevicePath);\r
+    NewMenuEntry->HelpString    = NULL;\r
+    NewMenuEntry->OptionNumber  = OptionNumber;\r
+    OptionNumber++;\r
+    InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link);\r
+\r
+  }\r
+  SafeFreePool (DevicePathHandle);\r
+\r
+  DriverMenu.MenuNumber = OptionNumber;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+UINT16\r
+BOpt_GetBootOptionNumber (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Get the Option Number that does not used\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  The Option Number\r
+\r
+--*/\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        *BootOrderList;\r
+  UINTN         BootOrderListSize;\r
+  UINT16        Number;\r
+  UINTN         Index;\r
+  UINTN         Index2;\r
+  BOOLEAN       Found;\r
+  CHAR16        StrTemp[100];\r
+  UINT16        *OptionBuffer;\r
+  UINTN         OptionSize;\r
+\r
+  BootOrderListSize = 0;\r
+  BootOrderList     = NULL;\r
+\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+  if (BootOrderList) {\r
+    //\r
+    // already have Boot####\r
+    //\r
+    // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);\r
+    //\r
+    for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
+      Found = TRUE;\r
+      for (Index2 = 0; Index2 < BootOptionMenu.MenuNumber; Index2++) {\r
+        NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index2);\r
+        if (Index == NewMenuEntry->OptionNumber) {\r
+          Found = FALSE;\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (Found) {\r
+     UnicodeSPrint (StrTemp, 100, L"Boot%04x", Index);\r
+     DEBUG((DEBUG_ERROR,"INdex= %s\n", StrTemp));\r
+          OptionBuffer = BdsLibGetVariableAndSize (\r
+                    StrTemp,\r
+                    &gEfiGlobalVariableGuid,\r
+                    &OptionSize\r
+                    );\r
+         if (NULL == OptionBuffer)\r
+            break;\r
+      }\r
+    }\r
+    //\r
+    // end for Index\r
+    //\r
+    Number = (UINT16) Index;\r
+  } else {\r
+    //\r
+    // No Boot####\r
+    //\r
+    Number = 0;\r
+  }\r
+\r
+  return Number;\r
+}\r
+\r
+UINT16\r
+BOpt_GetDriverOptionNumber (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Get the Option Number that does not used\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  The Option Number\r
+\r
+--*/\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        *DriverOrderList;\r
+  UINTN         DriverOrderListSize;\r
+  UINT16        Number;\r
+  UINTN         Index;\r
+  UINTN         Index2;\r
+  BOOLEAN       Found;\r
+\r
+  DriverOrderListSize = 0;\r
+  DriverOrderList     = NULL;\r
+\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+  if (DriverOrderList) {\r
+    //\r
+    // already have Driver####\r
+    //\r
+    // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);\r
+    //\r
+    for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {\r
+      Found = TRUE;\r
+      for (Index2 = 0; Index2 < DriverOptionMenu.MenuNumber; Index2++) {\r
+        NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index2);\r
+        if (Index == NewMenuEntry->OptionNumber) {\r
+          Found = FALSE;\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (Found) {\r
+        break;\r
+      }\r
+    }\r
+    //\r
+    // end for Index\r
+    //\r
+    Number = (UINT16) Index;\r
+  } else {\r
+    //\r
+    // No Driver####\r
+    //\r
+    Number = 0;\r
+  }\r
+\r
+  return Number;\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_GetDriverOptions (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Build up all DriverOptionMenu\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  The Option Number\r
+\r
+--*/\r
+{\r
+  UINTN           Index;\r
+  UINT16          DriverString[12];\r
+  UINT8           *LoadOptionFromVar;\r
+  UINT8           *LoadOption;\r
+  UINTN           DriverOptionSize;\r
+\r
+  UINT16          *DriverOrderList;\r
+  UINTN           DriverOrderListSize;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  UINT8           *LoadOptionPtr;\r
+  UINTN           StringSize;\r
+  UINTN           OptionalDataSize;\r
+  UINT8           *LoadOptionEnd;\r
+\r
+  DriverOrderListSize = 0;\r
+  DriverOrderList     = NULL;\r
+  DriverOptionSize    = 0;\r
+  LoadOptionFromVar   = NULL;\r
+  BOpt_FreeMenu (&DriverOptionMenu);\r
+  InitializeListHead (&DriverOptionMenu.Head);\r
+  //\r
+  // Get the DriverOrder from the Var\r
+  //\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+\r
+  for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {\r
+    UnicodeSPrint (\r
+      DriverString,\r
+      sizeof (DriverString),\r
+      L"Driver%04x",\r
+      DriverOrderList[Index]\r
+      );\r
+    //\r
+    //  Get all loadoptions from the VAR\r
+    //\r
+    LoadOptionFromVar = BdsLibGetVariableAndSize (\r
+                          DriverString,\r
+                          &gEfiGlobalVariableGuid,\r
+                          &DriverOptionSize\r
+                          );\r
+    if (!LoadOptionFromVar) {\r
+      continue;\r
+    }\r
+\r
+    LoadOption = EfiAllocateZeroPool (DriverOptionSize);\r
+    if (!LoadOption) {\r
+      continue;\r
+    }\r
+\r
+    CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize);\r
+    SafeFreePool (LoadOptionFromVar);\r
+\r
+    NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    NewLoadContext                      = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    LoadOptionPtr                       = LoadOption;\r
+    LoadOptionEnd                       = LoadOption + DriverOptionSize;\r
+    NewMenuEntry->OptionNumber          = DriverOrderList[Index];\r
+    NewLoadContext->LoadOptionModified  = FALSE;\r
+    NewLoadContext->Deleted             = FALSE;\r
+    NewLoadContext->IsLegacy            = FALSE;\r
+\r
+    //\r
+    // LoadOption is a pointer type of UINT8\r
+    // for easy use with following LOAD_OPTION\r
+    // embedded in this struct\r
+    //\r
+    NewLoadContext->LoadOption      = LoadOption;\r
+    NewLoadContext->LoadOptionSize  = DriverOptionSize;\r
+\r
+    NewLoadContext->Attributes      = *(UINT32 *) LoadOptionPtr;\r
+    NewLoadContext->IsActive        = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
+\r
+    NewLoadContext->ForceReconnect  = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+    LoadOptionPtr += sizeof (UINT32);\r
+\r
+    NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
+    LoadOptionPtr += sizeof (UINT16);\r
+\r
+    StringSize                  = StrSize ((UINT16 *) LoadOptionPtr);\r
+    NewLoadContext->Description = EfiAllocateZeroPool (StringSize);\r
+    ASSERT (NewLoadContext->Description != NULL);\r
+    CopyMem (\r
+      NewLoadContext->Description,\r
+      (UINT16 *) LoadOptionPtr,\r
+      StringSize\r
+      );\r
+    NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+\r
+    LoadOptionPtr += StringSize;\r
+\r
+    NewLoadContext->FilePathList = EfiAllocateZeroPool (NewLoadContext->FilePathListLength);\r
+    ASSERT (NewLoadContext->FilePathList != NULL);\r
+    CopyMem (\r
+      NewLoadContext->FilePathList,\r
+      (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
+      NewLoadContext->FilePathListLength\r
+      );\r
+\r
+    NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
+    NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                        CallbackData,\r
+                                        DriverOptionStrDepository\r
+                                        );\r
+    NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+                                      CallbackData,\r
+                                      DriverOptionHelpStrDepository\r
+                                      );\r
+    LoadOptionPtr += NewLoadContext->FilePathListLength;\r
+\r
+    if (LoadOptionPtr < LoadOptionEnd) {\r
+      OptionalDataSize = DriverOptionSize -\r
+        sizeof (UINT32) -\r
+        sizeof (UINT16) -\r
+        StringSize -\r
+        NewLoadContext->FilePathListLength;\r
+\r
+      NewLoadContext->OptionalData = EfiAllocateZeroPool (OptionalDataSize);\r
+      ASSERT (NewLoadContext->OptionalData != NULL);\r
+      CopyMem (\r
+        NewLoadContext->OptionalData,\r
+        LoadOptionPtr,\r
+        OptionalDataSize\r
+        );\r
+\r
+      NewLoadContext->OptionalDataSize = OptionalDataSize;\r
+    }\r
+\r
+    InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
+\r
+  }\r
+\r
+  SafeFreePool (DriverOrderList);\r
+  DriverOptionMenu.MenuNumber = Index;\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c
new file mode 100644 (file)
index 0000000..7239e6f
--- /dev/null
@@ -0,0 +1,992 @@
+/*++\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+    consoleoption.c\r
+\r
+Abstract:\r
+\r
+    handles console redirection from boot manager\r
+\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+EFI_DEVICE_PATH_PROTOCOL  *\r
+DevicePathInstanceDup (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevPath\r
+  );\r
+\r
+EFI_STATUS\r
+UpdateComAttributeFromVariable (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  );\r
+\r
+EFI_STATUS\r
+ChangeTerminalDevicePath (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
+  BOOLEAN                   ChangeTerminal\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node1;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  UART_DEVICE_PATH          *Uart;\r
+  UART_DEVICE_PATH          *Uart1;\r
+  UINTN                     Com;\r
+  UINT32                    Match;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+\r
+  Match = EISA_PNP_ID (0x0501);\r
+  Node  = DevicePath;\r
+  Node  = NextDevicePathNode (Node);\r
+  Com   = 0;\r
+  while (!IsDevicePathEnd (Node)) {\r
+    if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+      Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+      if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+        CopyMem (&Com, &Acpi->UID, sizeof (UINT32));\r
+      }\r
+    }\r
+\r
+    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+      Uart = (UART_DEVICE_PATH *) Node;\r
+      CopyMem (\r
+        &Uart->BaudRate,\r
+        &NewTerminalContext->BaudRate,\r
+        sizeof (UINT64)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->DataBits,\r
+        &NewTerminalContext->DataBits,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->Parity,\r
+        &NewTerminalContext->Parity,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->StopBits,\r
+        &NewTerminalContext->StopBits,\r
+        sizeof (UINT8)\r
+        );\r
+      //\r
+      // Change the device path in the ComPort\r
+      //\r
+      if (ChangeTerminal) {\r
+        Node1 = NewTerminalContext->DevicePath;\r
+        Node1 = NextDevicePathNode (Node1);\r
+        while (!IsDevicePathEnd (Node1)) {\r
+          if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) {\r
+            Uart1 = (UART_DEVICE_PATH *) Node1;\r
+            CopyMem (\r
+              &Uart1->BaudRate,\r
+              &NewTerminalContext->BaudRate,\r
+              sizeof (UINT64)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->DataBits,\r
+              &NewTerminalContext->DataBits,\r
+              sizeof (UINT8)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->Parity,\r
+              &NewTerminalContext->Parity,\r
+              sizeof (UINT8)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->StopBits,\r
+              &NewTerminalContext->StopBits,\r
+              sizeof (UINT8)\r
+              );\r
+            break;\r
+          }\r
+          //\r
+          // end if\r
+          //\r
+          Node1 = NextDevicePathNode (Node1);\r
+        }\r
+        //\r
+        // end while\r
+        //\r
+        break;\r
+      }\r
+    }\r
+\r
+    Node = NextDevicePathNode (Node);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+VOID\r
+ChangeVariableDevicePath (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  UART_DEVICE_PATH          *Uart;\r
+  UINTN                     Com;\r
+  UINT32                    Match;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+\r
+  Match = EISA_PNP_ID (0x0501);\r
+  Node  = DevicePath;\r
+  Node  = NextDevicePathNode (Node);\r
+  Com   = 0;\r
+  while (!IsDevicePathEnd (Node)) {\r
+    if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+      Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+      if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+        CopyMem (&Com, &Acpi->UID, sizeof (UINT32));\r
+      }\r
+    }\r
+\r
+    if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+      NewMenuEntry = BOpt_GetMenuEntry (\r
+                      &TerminalMenu,\r
+                      Com\r
+                      );\r
+      ASSERT (NewMenuEntry != NULL);\r
+      NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      Uart                = (UART_DEVICE_PATH *) Node;\r
+      CopyMem (\r
+        &Uart->BaudRate,\r
+        &NewTerminalContext->BaudRate,\r
+        sizeof (UINT64)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->DataBits,\r
+        &NewTerminalContext->DataBits,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->Parity,\r
+        &NewTerminalContext->Parity,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->StopBits,\r
+        &NewTerminalContext->StopBits,\r
+        sizeof (UINT8)\r
+        );\r
+    }\r
+\r
+    Node = NextDevicePathNode (Node);\r
+  }\r
+\r
+  return ;\r
+}\r
+\r
+BOOLEAN\r
+RetrieveUartUid (\r
+  IN EFI_HANDLE   Handle,\r
+  IN OUT UINT32   *AcpiUid\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Retrieve ACPI UID of UART from device path\r
+\r
+Arguments:\r
+  Handles   -   EFI_SERIAL_IO_PROTOCOL handle\r
+\r
+Returns:\r
+  TRUE  - Find valid UID from device path\r
+  FALSE - Can't find\r
+\r
+--*/\r
+{\r
+  UINT32                    Match;\r
+  UINT8                     *Ptr;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+\r
+  gBS->HandleProtocol (\r
+        Handle,\r
+        &gEfiDevicePathProtocolGuid,\r
+        (VOID **) &DevicePath\r
+        );\r
+  Ptr = (UINT8 *) DevicePath;\r
+\r
+  while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+    Ptr++;\r
+  }\r
+\r
+  Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+  Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+  Match = EISA_PNP_ID (0x0501);\r
+\r
+  if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+    if (AcpiUid != NULL) {\r
+      *AcpiUid = Acpi->UID;\r
+    }\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+VOID\r
+SortedUartHandle (\r
+  IN  EFI_HANDLE *Handles,\r
+  IN  UINTN      NoHandles\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Sort Uart handles array with Acpi->UID from low to high\r
+\r
+Arguments:\r
+  Handles   -   EFI_SERIAL_IO_PROTOCOL handle buffer\r
+  NoHandles -   EFI_SERIAL_IO_PROTOCOL handle count\r
+\r
+Returns:\r
+  None\r
+\r
+--*/\r
+{\r
+  UINTN       Index1;\r
+  UINTN       Index2;\r
+  UINTN       Position;\r
+  UINT32      AcpiUid1;\r
+  UINT32      AcpiUid2;\r
+  UINT32      TempAcpiUid;\r
+  EFI_HANDLE  TempHandle;\r
+\r
+  for (Index1 = 0; Index1 < NoHandles-1; Index1++) {\r
+    if (!RetrieveUartUid (Handles[Index1], &AcpiUid1)) {\r
+      continue;\r
+    }\r
+    TempHandle  = Handles[Index1];\r
+    Position    = Index1;\r
+    TempAcpiUid = AcpiUid1;\r
+\r
+    for (Index2 = Index1+1; Index2 < NoHandles; Index2++) {\r
+      if (!RetrieveUartUid (Handles[Index2], &AcpiUid2)) {\r
+        continue;\r
+      }\r
+      if (AcpiUid2 < TempAcpiUid) {\r
+        TempAcpiUid = AcpiUid2;\r
+        TempHandle  = Handles[Index2];\r
+        Position    = Index2;\r
+      }\r
+    }\r
+    Handles[Position] = Handles[Index1];\r
+    Handles[Index1]   = TempHandle;\r
+  }\r
+}\r
+\r
+BOOLEAN\r
+IsTerminalDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+  OUT TYPE_OF_TERMINAL         *Termi,\r
+  OUT UINTN                    *Com\r
+  );\r
+\r
+EFI_STATUS\r
+LocateSerialIo (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Build a list containing all serial devices\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  UINT8                     *Ptr;\r
+  UINTN                     Index;\r
+  UINTN                     Index2;\r
+  UINTN                     NoHandles;\r
+  EFI_HANDLE                *Handles;\r
+  EFI_STATUS                Status;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  UINT32                    Match;\r
+  EFI_SERIAL_IO_PROTOCOL    *SerialIo;\r
+  EFI_DEVICE_PATH_PROTOCOL  *OutDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *InpDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ErrDevicePath;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;\r
+  VENDOR_DEVICE_PATH        Vendor;\r
+  //\r
+  // Get all handles that have SerialIo protocol installed\r
+  //\r
+  InitializeListHead (&TerminalMenu.Head);\r
+  TerminalMenu.MenuNumber = 0;\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiSerialIoProtocolGuid,\r
+                  NULL,\r
+                  &NoHandles,\r
+                  &Handles\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // No serial ports present\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Sort Uart handles array with Acpi->UID from low to high\r
+  // then Terminal menu can be built from low Acpi->UID to high Acpi->UID\r
+  //\r
+  SortedUartHandle (Handles, NoHandles);\r
+\r
+  for (Index = 0; Index < NoHandles; Index++) {\r
+    //\r
+    // Check to see whether the handle has DevicePath Protocol installed\r
+    //\r
+    gBS->HandleProtocol (\r
+          Handles[Index],\r
+          &gEfiDevicePathProtocolGuid,\r
+          (VOID **) &DevicePath\r
+          );\r
+    Ptr = (UINT8 *) DevicePath;\r
+    while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+      Ptr++;\r
+    }\r
+\r
+    Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+    Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+    Match = EISA_PNP_ID (0x0501);\r
+\r
+    if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+      NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT);\r
+      if (!NewMenuEntry) {\r
+        SafeFreePool (Handles);\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32));\r
+      NewTerminalContext->DevicePath = DevicePathInstanceDup (DevicePath);\r
+      //\r
+      // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!\r
+      // coz' the misc data for each platform is not correct, actually it's the device path stored in\r
+      // datahub which is not completed, so a searching for end of device path will enter a\r
+      // dead-loop.\r
+      //\r
+      NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath);\r
+      if (NULL == NewMenuEntry->DisplayString) {\r
+        NewMenuEntry->DisplayString = DevicePathToStr (DevicePath);\r
+      }\r
+\r
+      NewMenuEntry->HelpString = NULL;\r
+\r
+      gBS->HandleProtocol (\r
+            Handles[Index],\r
+            &gEfiSerialIoProtocolGuid,\r
+            (VOID **) &SerialIo\r
+            );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->BaudRate,\r
+        &SerialIo->Mode->BaudRate,\r
+        sizeof (UINT64)\r
+        );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->DataBits,\r
+        &SerialIo->Mode->DataBits,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->Parity,\r
+        &SerialIo->Mode->Parity,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->StopBits,\r
+        &SerialIo->Mode->StopBits,\r
+        sizeof (UINT8)\r
+        );\r
+      InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link);\r
+      TerminalMenu.MenuNumber++;\r
+    }\r
+  }\r
+  SafeFreePool (Handles);\r
+\r
+  //\r
+  // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var\r
+  //\r
+  OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);\r
+  InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);\r
+  ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);\r
+  if (OutDevicePath) {\r
+    UpdateComAttributeFromVariable (OutDevicePath);\r
+  }\r
+\r
+  if (InpDevicePath) {\r
+    UpdateComAttributeFromVariable (InpDevicePath);\r
+  }\r
+\r
+  if (ErrDevicePath) {\r
+    UpdateComAttributeFromVariable (ErrDevicePath);\r
+  }\r
+\r
+  for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewTerminalContext                = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    NewTerminalContext->TerminalType  = 0;\r
+    NewTerminalContext->IsConIn       = FALSE;\r
+    NewTerminalContext->IsConOut      = FALSE;\r
+    NewTerminalContext->IsStdErr      = FALSE;\r
+\r
+    Vendor.Header.Type                = MESSAGING_DEVICE_PATH;\r
+    Vendor.Header.SubType             = MSG_VENDOR_DP;\r
+\r
+    for (Index2 = 0; Index2 < 4; Index2++) {\r
+      CopyMem (&Vendor.Guid, &Guid[Index2], sizeof (EFI_GUID));\r
+      SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));\r
+      NewDevicePath = AppendDevicePathNode (\r
+                        NewTerminalContext->DevicePath,\r
+                        (EFI_DEVICE_PATH_PROTOCOL *) &Vendor\r
+                        );\r
+      SafeFreePool (NewMenuEntry->HelpString);\r
+      //\r
+      // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath);\r
+      // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;\r
+      //\r
+      NewMenuEntry->HelpString = NULL;\r
+\r
+      if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) {\r
+        NewTerminalContext->IsConOut      = TRUE;\r
+        NewTerminalContext->TerminalType  = (UINT8) Index2;\r
+      }\r
+\r
+      if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) {\r
+        NewTerminalContext->IsConIn       = TRUE;\r
+        NewTerminalContext->TerminalType  = (UINT8) Index2;\r
+      }\r
+\r
+      if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) {\r
+        NewTerminalContext->IsStdErr      = TRUE;\r
+        NewTerminalContext->TerminalType  = (UINT8) Index2;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+UpdateComAttributeFromVariable (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Update Com Ports attributes from DevicePath\r
+\r
+Arguments:\r
+  DevicePath  -   DevicePath that contains Com ports\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
+  EFI_DEVICE_PATH_PROTOCOL  *SerialNode;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  UART_DEVICE_PATH          *Uart;\r
+  UART_DEVICE_PATH          *Uart1;\r
+  UINT32                    Match;\r
+  UINTN                     TerminalNumber;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  UINTN                     Index;\r
+\r
+  Match           = EISA_PNP_ID (0x0501);\r
+  Node            = DevicePath;\r
+  Node            = NextDevicePathNode (Node);\r
+  TerminalNumber  = 0;\r
+  for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+    while (!IsDevicePathEnd (Node)) {\r
+      if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+        Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+        if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+          CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32));\r
+        }\r
+      }\r
+\r
+      if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+        Uart          = (UART_DEVICE_PATH *) Node;\r
+        NewMenuEntry  = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber);\r
+        if (NULL == NewMenuEntry) {\r
+          return EFI_NOT_FOUND;\r
+        }\r
+\r
+        NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+        CopyMem (\r
+          &NewTerminalContext->BaudRate,\r
+          &Uart->BaudRate,\r
+          sizeof (UINT64)\r
+          );\r
+\r
+        CopyMem (\r
+          &NewTerminalContext->DataBits,\r
+          &Uart->DataBits,\r
+          sizeof (UINT8)\r
+          );\r
+\r
+        CopyMem (\r
+          &NewTerminalContext->Parity,\r
+          &Uart->Parity,\r
+          sizeof (UINT8)\r
+          );\r
+\r
+        CopyMem (\r
+          &NewTerminalContext->StopBits,\r
+          &Uart->StopBits,\r
+          sizeof (UINT8)\r
+          );\r
+\r
+        SerialNode  = NewTerminalContext->DevicePath;\r
+        SerialNode  = NextDevicePathNode (SerialNode);\r
+        while (!IsDevicePathEnd (SerialNode)) {\r
+          if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) {\r
+            //\r
+            // Update following device paths according to\r
+            // previous acquired uart attributes\r
+            //\r
+            Uart1 = (UART_DEVICE_PATH *) SerialNode;\r
+            CopyMem (\r
+              &Uart1->BaudRate,\r
+              &NewTerminalContext->BaudRate,\r
+              sizeof (UINT64)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->DataBits,\r
+              &NewTerminalContext->DataBits,\r
+              sizeof (UINT8)\r
+              );\r
+            CopyMem (\r
+              &Uart1->Parity,\r
+              &NewTerminalContext->Parity,\r
+              sizeof (UINT8)\r
+              );\r
+            CopyMem (\r
+              &Uart1->StopBits,\r
+              &NewTerminalContext->StopBits,\r
+              sizeof (UINT8)\r
+              );\r
+\r
+            break;\r
+          }\r
+\r
+          SerialNode = NextDevicePathNode (SerialNode);\r
+        }\r
+        //\r
+        // end while\r
+        //\r
+      }\r
+\r
+      Node = NextDevicePathNode (Node);\r
+    }\r
+    //\r
+    // end while\r
+    //\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+DevicePathInstanceDup (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevPath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Function creates a device path data structure that identically matches the\r
+  device path passed in.\r
+\r
+Arguments:\r
+  DevPath      - A pointer to a device path data structure.\r
+\r
+Returns:\r
+\r
+  The new copy of DevPath is created to identically match the input.\r
+  Otherwise, NULL is returned.\r
+\r
+--*/\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevPath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Temp;\r
+  UINT8                     *Ptr;\r
+  UINTN                     Size;\r
+\r
+  //\r
+  // get the size of an instance from the input\r
+  //\r
+  Temp            = DevPath;\r
+  DevicePathInst  = GetNextDevicePathInstance (&Temp, &Size);\r
+\r
+  //\r
+  // Make a copy and set proper end type\r
+  //\r
+  NewDevPath = NULL;\r
+  if (Size) {\r
+    NewDevPath = EfiAllocateZeroPool (Size);\r
+    ASSERT (NewDevPath != NULL);\r
+  }\r
+\r
+  if (NewDevPath) {\r
+    CopyMem (NewDevPath, DevicePathInst, Size);\r
+    Ptr = (UINT8 *) NewDevPath;\r
+    Ptr += Size - sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
+    Temp = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+    SetDevicePathEndNode (Temp);\r
+  }\r
+\r
+  return NewDevPath;\r
+}\r
+\r
+EFI_STATUS\r
+GetConsoleMenu (\r
+  IN UINTN              ConsoleMenuType\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *AllDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *MultiDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
+  UINTN                     Size;\r
+  UINTN                     AllCount;\r
+  UINTN                     Index;\r
+  UINTN                     Index2;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_CONSOLE_CONTEXT        *NewConsoleContext;\r
+  TYPE_OF_TERMINAL          Terminal;\r
+  UINTN                     Com;\r
+  BM_MENU_OPTION            *ConsoleMenu;\r
+\r
+  DevicePath    = NULL;\r
+  AllDevicePath = NULL;\r
+  AllCount      = 0;\r
+  switch (ConsoleMenuType) {\r
+  case BM_CONSOLE_IN_CONTEXT_SELECT:\r
+    ConsoleMenu = &ConsoleInpMenu;\r
+    DevicePath = EfiLibGetVariable (\r
+                  L"ConIn",\r
+                  &gEfiGlobalVariableGuid\r
+                  );\r
+\r
+    AllDevicePath = EfiLibGetVariable (\r
+                      L"ConInDev",\r
+                      &gEfiGlobalVariableGuid\r
+                      );\r
+    break;\r
+\r
+  case BM_CONSOLE_OUT_CONTEXT_SELECT:\r
+    ConsoleMenu = &ConsoleOutMenu;\r
+    DevicePath = EfiLibGetVariable (\r
+                  L"ConOut",\r
+                  &gEfiGlobalVariableGuid\r
+                  );\r
+\r
+    AllDevicePath = EfiLibGetVariable (\r
+                      L"ConOutDev",\r
+                      &gEfiGlobalVariableGuid\r
+                      );\r
+    break;\r
+\r
+  case BM_CONSOLE_ERR_CONTEXT_SELECT:\r
+    ConsoleMenu = &ConsoleErrMenu;\r
+    DevicePath = EfiLibGetVariable (\r
+                  L"ErrOut",\r
+                  &gEfiGlobalVariableGuid\r
+                  );\r
+\r
+    AllDevicePath = EfiLibGetVariable (\r
+                      L"ErrOutDev",\r
+                      &gEfiGlobalVariableGuid\r
+                      );\r
+    break;\r
+\r
+  default:\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (NULL == AllDevicePath) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  InitializeListHead (&ConsoleMenu->Head);\r
+\r
+  AllCount                = EfiDevicePathInstanceCount (AllDevicePath);\r
+  ConsoleMenu->MenuNumber = 0;\r
+  //\r
+  // Following is menu building up for Console Out Devices\r
+  //\r
+  MultiDevicePath = AllDevicePath;\r
+  Index2          = 0;\r
+  for (Index = 0; Index < AllCount; Index++) {\r
+    DevicePathInst  = GetNextDevicePathInstance (&MultiDevicePath, &Size);\r
+\r
+    NewMenuEntry    = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    NewConsoleContext             = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewMenuEntry->OptionNumber    = Index2;\r
+\r
+    NewConsoleContext->DevicePath = DevicePathInstanceDup (DevicePathInst);\r
+    NewMenuEntry->DisplayString   = EfiLibStrFromDatahub (NewConsoleContext->DevicePath);\r
+    if (NULL == NewMenuEntry->DisplayString) {\r
+      NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath);\r
+    }\r
+\r
+    NewConsoleContext->IsTerminal = IsTerminalDevicePath (\r
+                                      NewConsoleContext->DevicePath,\r
+                                      &Terminal,\r
+                                      &Com\r
+                                      );\r
+\r
+    NewConsoleContext->IsActive = BdsLibMatchDevicePaths (\r
+                                    DevicePath,\r
+                                    NewConsoleContext->DevicePath\r
+                                    );\r
+\r
+    if (NewConsoleContext->IsTerminal) {\r
+      BOpt_DestroyMenuEntry (NewMenuEntry);\r
+    } else {\r
+      Index2++;\r
+      ConsoleMenu->MenuNumber++;\r
+      InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetAllConsoles (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  EFI_SUCCESS\r
+  Others\r
+\r
+--*/\r
+{\r
+  GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT);\r
+  GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT);\r
+  GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+FreeAllConsoles (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  EFI_SUCCESS\r
+  Others\r
+\r
+--*/\r
+{\r
+  BOpt_FreeMenu (&ConsoleOutMenu);\r
+  BOpt_FreeMenu (&ConsoleInpMenu);\r
+  BOpt_FreeMenu (&ConsoleErrMenu);\r
+  BOpt_FreeMenu (&TerminalMenu);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+IsTerminalDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+  OUT TYPE_OF_TERMINAL         *Termi,\r
+  OUT UINTN                    *Com\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Test whether DevicePath is a valid Terminal\r
+\r
+Arguments:\r
+  DevicePath  -   DevicePath to be checked\r
+  Termi       -   If is terminal, give its type\r
+  Com         -   If is Com Port, give its type\r
+\r
+Returns:\r
+  TRUE        -   If DevicePath point to a Terminal\r
+  FALSE\r
+\r
+--*/\r
+{\r
+  UINT8                 *Ptr;\r
+  BOOLEAN               IsTerminal;\r
+  VENDOR_DEVICE_PATH    *Vendor;\r
+  ACPI_HID_DEVICE_PATH  *Acpi;\r
+  UINT32                Match;\r
+  EFI_GUID              TempGuid;\r
+\r
+  IsTerminal = FALSE;\r
+\r
+  //\r
+  // Parse the Device Path, should be change later!!!\r
+  //\r
+  Ptr = (UINT8 *) DevicePath;\r
+  while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+    Ptr++;\r
+  }\r
+\r
+  Ptr     = Ptr - sizeof (VENDOR_DEVICE_PATH);\r
+  Vendor  = (VENDOR_DEVICE_PATH *) Ptr;\r
+\r
+  //\r
+  // There are four kinds of Terminal types\r
+  // check to see whether this devicepath\r
+  // is one of that type\r
+  //\r
+  CopyMem (&TempGuid, &Vendor->Guid, sizeof (EFI_GUID));\r
+\r
+  if (CompareGuid (&TempGuid, &Guid[0])) {\r
+    *Termi      = PC_ANSI;\r
+    IsTerminal  = TRUE;\r
+  } else {\r
+    if (CompareGuid (&TempGuid, &Guid[1])) {\r
+      *Termi      = VT_100;\r
+      IsTerminal  = TRUE;\r
+    } else {\r
+      if (CompareGuid (&TempGuid, &Guid[2])) {\r
+        *Termi      = VT_100_PLUS;\r
+        IsTerminal  = TRUE;\r
+      } else {\r
+        if (CompareGuid (&TempGuid, &Guid[3])) {\r
+          *Termi      = VT_UTF8;\r
+          IsTerminal  = TRUE;\r
+        } else {\r
+          IsTerminal = FALSE;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (!IsTerminal) {\r
+    return FALSE;\r
+  }\r
+\r
+  Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+  Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+  Match = EISA_PNP_ID (0x0501);\r
+  if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+    CopyMem (Com, &Acpi->UID, sizeof (UINT32));\r
+  } else {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+VOID\r
+GetConsoleOutMode (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Get mode number according to column and row\r
+\r
+Arguments:\r
+  CallbackData  -  BMM_CALLBACK_DATA\r
+\r
+Returns:\r
+  None.\r
+\r
+--*/\r
+{\r
+  UINTN                         Col;\r
+  UINTN                         Row;\r
+  UINTN                         CurrentCol;\r
+  UINTN                         CurrentRow;\r
+  UINTN                         Mode;\r
+  UINTN                         MaxMode;\r
+  EFI_STATUS                    Status;\r
+  CONSOLE_OUT_MODE              *ModeInfo;\r
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *ConOut;\r
+\r
+  ConOut   = gST->ConOut;\r
+  MaxMode  = (UINTN) (ConOut->Mode->MaxMode);\r
+  ModeInfo = EfiLibGetVariable (VarConOutMode, &gEfiGenericPlatformVariableGuid);\r
+\r
+  if (ModeInfo != NULL) {\r
+    CurrentCol = ModeInfo->Column;\r
+    CurrentRow = ModeInfo->Row;\r
+    for (Mode = 0; Mode < MaxMode; Mode++) {\r
+      Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);\r
+      if (!EFI_ERROR(Status)) {\r
+        if (CurrentCol == Col && CurrentRow == Row) {\r
+          CallbackData->BmmFakeNvData.ConsoleOutMode = (UINT16) Mode;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  SafeFreePool (ModeInfo);\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/Data.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/Data.c
new file mode 100644 (file)
index 0000000..598d3c1
--- /dev/null
@@ -0,0 +1,324 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  Data.c\r
+\r
+Abstract:\r
+\r
+  Define some data used for Boot Maint\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+EFI_HII_UPDATE_DATA gUpdateData;\r
+STRING_DEPOSITORY   *FileOptionStrDepository;\r
+STRING_DEPOSITORY   *ConsoleOptionStrDepository;\r
+STRING_DEPOSITORY   *BootOptionStrDepository;\r
+STRING_DEPOSITORY   *BootOptionHelpStrDepository;\r
+STRING_DEPOSITORY   *DriverOptionStrDepository;\r
+STRING_DEPOSITORY   *DriverOptionHelpStrDepository;\r
+STRING_DEPOSITORY   *TerminalStrDepository;\r
+\r
+//\r
+// Terminal type string token storage\r
+//\r
+UINT16              TerminalType[] = {\r
+  STRING_TOKEN(STR_COM_TYPE_0),\r
+  STRING_TOKEN(STR_COM_TYPE_1),\r
+  STRING_TOKEN(STR_COM_TYPE_2),\r
+  STRING_TOKEN(STR_COM_TYPE_3),\r
+};\r
+\r
+//\r
+// File system selection menu\r
+//\r
+BM_MENU_OPTION      FsOptionMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  NULL,\r
+  0\r
+};\r
+\r
+//\r
+// Console Input Device Selection Menu\r
+//\r
+BM_MENU_OPTION      ConsoleInpMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  NULL,\r
+  0\r
+};\r
+\r
+//\r
+// Console Output Device Selection Menu\r
+//\r
+BM_MENU_OPTION      ConsoleOutMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  NULL,\r
+  0\r
+};\r
+\r
+//\r
+// Error Output Device Selection Menu\r
+//\r
+BM_MENU_OPTION      ConsoleErrMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  NULL,\r
+  0\r
+};\r
+\r
+//\r
+// Boot Option from variable Menu\r
+//\r
+BM_MENU_OPTION      BootOptionMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  NULL,\r
+  0\r
+};\r
+\r
+//\r
+// Driver Option from variable menu\r
+//\r
+BM_MENU_OPTION      DriverOptionMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  NULL,\r
+  0\r
+};\r
+\r
+//\r
+// Legacy FD Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION      LegacyFDMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  NULL,\r
+  0\r
+};\r
+\r
+//\r
+// Legacy HD Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION      LegacyHDMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  NULL,\r
+  0\r
+};\r
+\r
+//\r
+// Legacy CD Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION      LegacyCDMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  NULL,\r
+  0\r
+};\r
+\r
+//\r
+// Legacy NET Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION      LegacyNETMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  NULL,\r
+  0\r
+};\r
+\r
+//\r
+// Legacy NET Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION      LegacyBEVMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  NULL,\r
+  0\r
+};\r
+\r
+//\r
+// Files and sub-directories in current directory menu\r
+//\r
+BM_MENU_OPTION      DirectoryMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  NULL,\r
+  0\r
+};\r
+\r
+//\r
+// Handles in current system selection menu\r
+//\r
+BM_MENU_OPTION      DriverMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  NULL,\r
+  0\r
+};\r
+\r
+BM_MENU_OPTION      TerminalMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  NULL,\r
+  0\r
+};\r
+\r
+//\r
+// Value and string token correspondency for BaudRate\r
+//\r
+COM_ATTR            BaudRateList[19] = {\r
+  {\r
+    115200,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_0)\r
+  },\r
+  {\r
+    57600,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_1)\r
+  },\r
+  {\r
+    38400,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_2)\r
+  },\r
+  {\r
+    19200,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_3)\r
+  },\r
+  {\r
+    9600,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_4)\r
+  },\r
+  {\r
+    7200,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_5)\r
+  },\r
+  {\r
+    4800,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_6)\r
+  },\r
+  {\r
+    3600,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_7)\r
+  },\r
+  {\r
+    2400,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_8)\r
+  },\r
+  {\r
+    2000,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_9)\r
+  },\r
+  {\r
+    1800,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_10)\r
+  },\r
+  {\r
+    1200,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_11)\r
+  },\r
+  {\r
+    600,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_12)\r
+  },\r
+  {\r
+    300,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_13)\r
+  },\r
+  {\r
+    150,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_14)\r
+  },\r
+  {\r
+    134,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_15)\r
+  },\r
+  {\r
+    110,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_16)\r
+  },\r
+  {\r
+    75,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_17)\r
+  },\r
+  {\r
+    50,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_18)\r
+  }\r
+};\r
+\r
+//\r
+// Value and string token correspondency for DataBits\r
+//\r
+COM_ATTR            DataBitsList[4] = {\r
+  {\r
+    5,\r
+    STRING_TOKEN(STR_COM_DATA_BITS_0)\r
+  },\r
+  {\r
+    6,\r
+    STRING_TOKEN(STR_COM_DATA_BITS_1)\r
+  },\r
+  {\r
+    7,\r
+    STRING_TOKEN(STR_COM_DATA_BITS_2)\r
+  },\r
+  {\r
+    8,\r
+    STRING_TOKEN(STR_COM_DATA_BITS_3)\r
+  }\r
+};\r
+\r
+//\r
+// Value and string token correspondency for Parity\r
+//\r
+COM_ATTR            ParityList[5] = {\r
+  {\r
+    NoParity,\r
+    STRING_TOKEN(STR_COM_PAR_0)\r
+  },\r
+  {\r
+    EvenParity,\r
+    STRING_TOKEN(STR_COM_PAR_1)\r
+  },\r
+  {\r
+    OddParity,\r
+    STRING_TOKEN(STR_COM_PAR_2)\r
+  },\r
+  {\r
+    MarkParity,\r
+    STRING_TOKEN(STR_COM_PAR_3)\r
+  },\r
+  {\r
+    SpaceParity,\r
+    STRING_TOKEN(STR_COM_PAR_4)\r
+  }\r
+};\r
+\r
+//\r
+// Value and string token correspondency for Baudreate\r
+//\r
+COM_ATTR            StopBitsList[3] = {\r
+  {\r
+    OneStopBit,\r
+    STRING_TOKEN(STR_COM_STOP_BITS_0)\r
+  },\r
+  {\r
+    OneFiveStopBits,\r
+    STRING_TOKEN(STR_COM_STOP_BITS_1)\r
+  },\r
+  {\r
+    TwoStopBits,\r
+    STRING_TOKEN(STR_COM_STOP_BITS_2)\r
+  }\r
+};\r
+\r
+//\r
+// Guid for messaging path, used in Serial port setting.\r
+//\r
+EFI_GUID            Guid[4] = {\r
+  DEVICE_PATH_MESSAGING_PC_ANSI,\r
+  DEVICE_PATH_MESSAGING_VT_100,\r
+  DEVICE_PATH_MESSAGING_VT_100_PLUS,\r
+  DEVICE_PATH_MESSAGING_VT_UTF8\r
+};\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/FE.vfr b/MdeModulePkg/Universal/BdsDxe/BootMaint/FE.vfr
new file mode 100644 (file)
index 0000000..97d4321
--- /dev/null
@@ -0,0 +1,134 @@
+// *++\r
+//\r
+// Copyright (c) 2004 - 2007, Intel Corporation\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution.  The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// Module Name:\r
+//\r
+//   FE.vfr\r
+//\r
+// Abstract:\r
+//\r
+//   File Explorer Formset\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+\r
+#include "FormGuid.h"\r
+\r
+#define LABEL_END   0xffff\r
+\r
+formset\r
+  guid = FILE_EXPLORE_FORMSET_GUID,\r
+  title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE),\r
+  help = STRING_TOKEN(STR_NULL_STRING),\r
+  class = 0,\r
+  subclass = 0,\r
+\r
+  varstore FILE_EXPLORER_NV_DATA,\r
+    varid = VARSTORE_ID_BOOT_MAINT,\r
+    name = FeData,\r
+    guid = FILE_EXPLORE_FORMSET_GUID;\r
+\r
+  form formid = FORM_FILE_EXPLORER_ID,\r
+       title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE);\r
+\r
+       label FORM_FILE_EXPLORER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_BOOT_ADD_DESCRIPTION_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_ADD_DESC_TITLE);\r
+\r
+       label FORM_BOOT_ADD_DESCRIPTION_ID;\r
+       label LABEL_END;\r
+\r
+       subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+       string    varid    = FeData.DescriptionData,\r
+                 prompt   = STRING_TOKEN(STR_LOAD_OPTION_DESC),\r
+                 help     = STRING_TOKEN(STR_NULL_STRING),\r
+                 minsize  = 6,\r
+                 maxsize  = 75,\r
+       endstring;\r
+\r
+       string    varid    = FeData.OptionalData,\r
+                       prompt   = STRING_TOKEN(STR_OPTIONAL_DATA),\r
+                       help     = STRING_TOKEN(STR_NULL_STRING),\r
+                       minsize  = 0,\r
+                       maxsize  = 120,\r
+       endstring;\r
+\r
+       subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+       text\r
+         help   = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_VALUE_SAVE_AND_EXIT_BOOT;\r
+\r
+       text\r
+         help   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_VALUE_NO_SAVE_AND_EXIT_BOOT;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);\r
+\r
+       label FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+       label LABEL_END;\r
+\r
+       subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+       string    varid    = FeData.DescriptionData,\r
+                 prompt   = STRING_TOKEN(STR_LOAD_OPTION_DESC),\r
+                 help     = STRING_TOKEN(STR_NULL_STRING),\r
+                 minsize  = 6,\r
+                 maxsize  = 75,\r
+       endstring;\r
+\r
+       string    varid    = FeData.OptionalData,\r
+                 prompt   = STRING_TOKEN(STR_OPTIONAL_DATA),\r
+                 help     = STRING_TOKEN(STR_NULL_STRING),\r
+                 minsize  = 0,\r
+                 maxsize  = 120,\r
+       endstring;\r
+\r
+       checkbox varid    = FeData.ForceReconnect,\r
+               prompt   = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON),\r
+               help     = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON),\r
+               flags    = CHECKBOX_DEFAULT,\r
+               key      = 0,\r
+       endcheckbox;\r
+\r
+       subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+       text\r
+         help   = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_VALUE_SAVE_AND_EXIT_DRIVER;  //BUGBUB: allow duplicate key in one formset???\r
+\r
+       text\r
+         help   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER;\r
+\r
+  endform;\r
+\r
+endformset;
\ No newline at end of file
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c
new file mode 100644 (file)
index 0000000..811702f
--- /dev/null
@@ -0,0 +1,327 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  FileExplorer.c\r
+\r
+Abstract:\r
+\r
+  File explorer related functions.\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+VOID\r
+UpdateFileExplorePage (\r
+  IN BMM_CALLBACK_DATA            *CallbackData,\r
+  BM_MENU_OPTION                  *MenuOption\r
+  )\r
+/*++\r
+Routine Description:\r
+  Update the File Explore page.\r
+\r
+Arguments:\r
+  MenuOption      - Pointer to menu options to display.\r
+\r
+Returns:\r
+  None.\r
+\r
+--*/\r
+{\r
+  UINTN           Index;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_FILE_CONTEXT *NewFileContext;\r
+  EFI_FORM_ID     FormId;\r
+\r
+  NewMenuEntry    = NULL;\r
+  NewFileContext  = NULL;\r
+  FormId          = 0;\r
+\r
+  RefreshUpdateData ();\r
+\r
+  for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
+    NewMenuEntry    = BOpt_GetMenuEntry (MenuOption, Index);\r
+    NewFileContext  = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    if (NewFileContext->IsBootLegacy) {\r
+      continue;\r
+    }\r
+\r
+    if ((NewFileContext->IsDir) || (BOOT_FROM_FILE_STATE == CallbackData->FeCurrentState)) {\r
+      //\r
+      // Create Text opcode for directory, also create Text opcode for file in BOOT_FROM_FILE_STATE.\r
+      //\r
+      CreateActionOpCode (\r
+        (UINT16) (FILE_OPTION_OFFSET + Index),\r
+        NewMenuEntry->DisplayStringToken,\r
+        STRING_TOKEN (STR_NULL_STRING),\r
+        EFI_IFR_FLAG_CALLBACK,\r
+        0,\r
+        &gUpdateData\r
+        );\r
+    } else {\r
+      //\r
+      // Create Goto opcode for file in ADD_BOOT_OPTION_STATE or ADD_DRIVER_OPTION_STATE.\r
+      //\r
+      if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {\r
+        FormId = FORM_BOOT_ADD_DESCRIPTION_ID;\r
+      } else if (ADD_DRIVER_OPTION_STATE == CallbackData->FeCurrentState) {\r
+        FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+      }\r
+\r
+      CreateGotoOpCode (\r
+        FormId,\r
+        NewMenuEntry->DisplayStringToken,\r
+        STRING_TOKEN (STR_NULL_STRING),\r
+        EFI_IFR_FLAG_CALLBACK,\r
+        (UINT16) (FILE_OPTION_OFFSET + Index),\r
+        &gUpdateData\r
+        );\r
+    }\r
+  }\r
+\r
+  IfrLibUpdateForm (\r
+    CallbackData->FeHiiHandle,\r
+    &mFileExplorerGuid,\r
+    FORM_FILE_EXPLORER_ID,\r
+    FORM_FILE_EXPLORER_ID,\r
+    FALSE,\r
+    &gUpdateData\r
+    );\r
+}\r
+\r
+BOOLEAN\r
+UpdateFileExplorer (\r
+  IN BMM_CALLBACK_DATA            *CallbackData,\r
+  IN UINT16                       KeyValue\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Update the file explower page with the refershed file system.\r
+\r
+Arguments:\r
+  CallbackData  -   BMM context data\r
+  KeyValue        - Key value to identify the type of data to expect.\r
+\r
+Returns:\r
+  TRUE          - Inform the caller to create a callback packet to exit file explorer.\r
+  FALSE         - Indicate that there is no need to exit file explorer.\r
+\r
+--*/\r
+{\r
+  UINT16          FileOptionMask;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_FILE_CONTEXT *NewFileContext;\r
+  EFI_FORM_ID     FormId;\r
+  BOOLEAN         ExitFileExplorer;\r
+  EFI_STATUS      Status;\r
+\r
+  NewMenuEntry      = NULL;\r
+  NewFileContext    = NULL;\r
+  ExitFileExplorer  = FALSE;\r
+\r
+  FileOptionMask    = (UINT16) (FILE_OPTION_MASK & KeyValue);\r
+\r
+  if (UNKNOWN_CONTEXT == CallbackData->FeDisplayContext) {\r
+    //\r
+    // First in, display file system.\r
+    //\r
+    BOpt_FreeMenu (&FsOptionMenu);\r
+    BOpt_FindFileSystem (CallbackData);\r
+    CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu);\r
+\r
+    UpdateFileExplorePage (CallbackData, &FsOptionMenu);\r
+\r
+    CallbackData->FeDisplayContext = FILE_SYSTEM;\r
+  } else {\r
+    if (FILE_SYSTEM == CallbackData->FeDisplayContext) {\r
+      NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask);\r
+    } else if (DIRECTORY == CallbackData->FeDisplayContext) {\r
+      NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask);\r
+    }\r
+\r
+    CallbackData->FeDisplayContext  = DIRECTORY;\r
+\r
+    NewFileContext                  = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    if (NewFileContext->IsDir ) {\r
+      RemoveEntryList (&NewMenuEntry->Link);\r
+      BOpt_FreeMenu (&DirectoryMenu);\r
+      Status = BOpt_FindFiles (CallbackData, NewMenuEntry);\r
+       if (EFI_ERROR (Status)) {\r
+         ExitFileExplorer = TRUE;\r
+         goto exit;\r
+       }\r
+      CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &DirectoryMenu);\r
+      BOpt_DestroyMenuEntry (NewMenuEntry);\r
+\r
+      UpdateFileExplorePage (CallbackData, &DirectoryMenu);\r
+\r
+    } else {\r
+      switch (CallbackData->FeCurrentState) {\r
+      case BOOT_FROM_FILE_STATE:\r
+        //\r
+        // Here boot from file\r
+        //\r
+        BootThisFile (NewFileContext);\r
+        ExitFileExplorer = TRUE;\r
+        break;\r
+\r
+      case ADD_BOOT_OPTION_STATE:\r
+      case ADD_DRIVER_OPTION_STATE:\r
+        if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {\r
+          FormId = FORM_BOOT_ADD_DESCRIPTION_ID;\r
+        } else {\r
+          FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+        }\r
+\r
+        CallbackData->MenuEntry = NewMenuEntry;\r
+        CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath;\r
+\r
+        //\r
+        // Create Subtitle op-code for the display string of the option.\r
+        //\r
+        RefreshUpdateData ();\r
+\r
+        CreateSubTitleOpCode (\r
+          NewMenuEntry->DisplayStringToken,\r
+          0,\r
+          0,\r
+          0,\r
+          &gUpdateData\r
+          );\r
+\r
+        IfrLibUpdateForm (\r
+          CallbackData->FeHiiHandle,\r
+          &mFileExplorerGuid,\r
+          FormId,\r
+          FormId,\r
+          FALSE,\r
+          &gUpdateData\r
+          );\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  exit:\r
+  return ExitFileExplorer;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FileExplorerCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    This function processes the results of changes in configuration.\r
+\r
+  Arguments:\r
+    This          - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+    Action        - Specifies the type of action taken by the browser.\r
+    QuestionId    - A unique value which is sent to the original exporting driver\r
+                    so that it can identify the type of data to expect.\r
+    Type          - The type of value for the question.\r
+    Value         - A pointer to the data being sent to the original exporting driver.\r
+    ActionRequest - On return, points to the action requested by the callback function.\r
+\r
+  Returns:\r
+    EFI_SUCCESS          - The callback successfully handled the action.\r
+    EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.\r
+    EFI_DEVICE_ERROR     - The variable could not be saved.\r
+    EFI_UNSUPPORTED      - The specified Action is not supported by the callback.\r
+\r
+--*/\r
+{\r
+  BMM_CALLBACK_DATA     *Private;\r
+  FILE_EXPLORER_NV_DATA *NvRamMap;\r
+  EFI_STATUS            Status;\r
+  UINTN                 BufferSize;\r
+\r
+  if ((Value == NULL) || (ActionRequest == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status         = EFI_SUCCESS;\r
+  Private        = FE_CALLBACK_DATA_FROM_THIS (This);\r
+  *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+  //\r
+  // Retrive uncommitted data from Form Browser\r
+  //\r
+  NvRamMap = &Private->FeFakeNvData;\r
+  BufferSize = sizeof (FILE_EXPLORER_NV_DATA);\r
+  Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) NvRamMap);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) {\r
+    //\r
+    // Apply changes and exit formset\r
+    //\r
+    if (ADD_BOOT_OPTION_STATE == Private->FeCurrentState) {\r
+      Status = Var_UpdateBootOption (Private, NvRamMap);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      BOpt_GetBootOptions (Private);\r
+      CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu);\r
+    } else if (ADD_DRIVER_OPTION_STATE == Private->FeCurrentState) {\r
+      Status = Var_UpdateDriverOption (\r
+                Private,\r
+                Private->FeHiiHandle,\r
+                NvRamMap->DescriptionData,\r
+                NvRamMap->OptionalData,\r
+                NvRamMap->ForceReconnect\r
+                );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      BOpt_GetDriverOptions (Private);\r
+      CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu);\r
+    }\r
+\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+  } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) {\r
+    //\r
+    // Discard changes and exit formset\r
+    //\r
+    NvRamMap->OptionalData[0]     = 0x0000;\r
+    NvRamMap->DescriptionData[0]  = 0x0000;\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+  } else if (QuestionId < FILE_OPTION_OFFSET) {\r
+    //\r
+    // Exit File Explorer formset\r
+    //\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+  } else {\r
+    if (UpdateFileExplorer (Private, QuestionId)) {\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h b/MdeModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h
new file mode 100644 (file)
index 0000000..9c0adf2
--- /dev/null
@@ -0,0 +1,216 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  FormGuid.h\r
+\r
+Abstract:\r
+\r
+  Formset guids, form id and VarStore data structure for Boot Maintenance Manager.\r
+\r
+--*/\r
+#ifndef _FORM_GUID_H\r
+#define _FORM_GUID_H\r
+\r
+#define BOOT_MAINT_FORMSET_GUID \\r
+  { \\r
+  0x642237c7, 0x35d4, 0x472d, {0x83, 0x65, 0x12, 0xe0, 0xcc, 0xf2, 0x7a, 0x22} \\r
+  }\r
+\r
+#define FILE_EXPLORE_FORMSET_GUID \\r
+  { \\r
+  0x1f2d63e1, 0xfebd, 0x4dc7, {0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c, 0x5b} \\r
+  }\r
+\r
+#define FORM_MAIN_ID                         0x1001\r
+#define FORM_BOOT_ADD_ID                     0x1002\r
+#define FORM_BOOT_DEL_ID                     0x1003\r
+#define FORM_BOOT_CHG_ID                     0x1004\r
+#define FORM_DRV_ADD_ID                      0x1005\r
+#define FORM_DRV_DEL_ID                      0x1006\r
+#define FORM_DRV_CHG_ID                      0x1007\r
+#define FORM_CON_MAIN_ID                     0x1008\r
+#define FORM_CON_IN_ID                       0x1009\r
+#define FORM_CON_OUT_ID                      0x100A\r
+#define FORM_CON_ERR_ID                      0x100B\r
+#define FORM_FILE_SEEK_ID                    0x100C\r
+#define FORM_FILE_NEW_SEEK_ID                0x100D\r
+#define FORM_DRV_ADD_FILE_ID                 0x100E\r
+#define FORM_DRV_ADD_HANDLE_ID               0x100F\r
+#define FORM_DRV_ADD_HANDLE_DESC_ID          0x1010\r
+#define FORM_BOOT_NEXT_ID                    0x1011\r
+#define FORM_TIME_OUT_ID                     0x1012\r
+#define FORM_RESET                           0x1013\r
+#define FORM_BOOT_SETUP_ID                   0x1014\r
+#define FORM_DRIVER_SETUP_ID                 0x1015\r
+#define FORM_BOOT_LEGACY_DEVICE_ID           0x1016\r
+#define FORM_CON_COM_ID                      0x1017\r
+#define FORM_CON_COM_SETUP_ID                0x1018\r
+#define FORM_SET_FD_ORDER_ID                 0x1019\r
+#define FORM_SET_HD_ORDER_ID                 0x101A\r
+#define FORM_SET_CD_ORDER_ID                 0x101B\r
+#define FORM_SET_NET_ORDER_ID                0x101C\r
+#define FORM_SET_BEV_ORDER_ID                0x101D\r
+#define FORM_FILE_EXPLORER_ID                0x101E\r
+#define FORM_BOOT_ADD_DESCRIPTION_ID         0x101F\r
+#define FORM_DRIVER_ADD_FILE_DESCRIPTION_ID  0x1020\r
+#define FORM_CON_MODE_ID                     0x1021\r
+\r
+#define MAXIMUM_FORM_ID                      0x10FF\r
+\r
+#define KEY_VALUE_COM_SET_BAUD_RATE          0x1101\r
+#define KEY_VALUE_COM_SET_DATA_BITS          0x1102\r
+#define KEY_VALUE_COM_SET_STOP_BITS          0x1103\r
+#define KEY_VALUE_COM_SET_PARITY             0x1104\r
+#define KEY_VALUE_COM_SET_TERMI_TYPE         0x1105\r
+#define KEY_VALUE_MAIN_BOOT_NEXT             0x1106\r
+#define KEY_VALUE_BOOT_ADD_DESC_DATA         0x1107\r
+#define KEY_VALUE_BOOT_ADD_OPT_DATA          0x1108\r
+#define KEY_VALUE_DRIVER_ADD_DESC_DATA       0x1109\r
+#define KEY_VALUE_DRIVER_ADD_OPT_DATA        0x110A\r
+#define KEY_VALUE_SAVE_AND_EXIT              0x110B\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT           0x110C\r
+#define KEY_VALUE_BOOT_FROM_FILE             0x110D\r
+\r
+#define MAXIMUM_NORMAL_KEY_VALUE             0x11FF\r
+\r
+//\r
+// Varstore ID defined for Buffer Stoarge\r
+//\r
+#define VARSTORE_ID_BOOT_MAINT               0x1000\r
+#define VARSTORE_ID_FILE_EXPLORER            0x1001\r
+\r
+//\r
+// This is the structure that will be used to store the\r
+// question's current value. Use it at initialize time to\r
+// set default value for each question. When using at run\r
+// time, this map is returned by the callback function,\r
+// so dynamically changing the question's value will be\r
+// possible through this mechanism\r
+//\r
+typedef struct {\r
+  //\r
+  // Three questions displayed at the main page\r
+  // for Timeout, BootNext Variables respectively\r
+  //\r
+  UINT16  BootTimeOut;\r
+  UINT16  BootNext;\r
+\r
+  //\r
+  // This is the COM1 Attributes value storage\r
+  //\r
+  UINT8   COM1BaudRate;\r
+  UINT8   COM1DataRate;\r
+  UINT8   COM1StopBits;\r
+  UINT8   COM1Parity;\r
+  UINT8   COM1TerminalType;\r
+\r
+  //\r
+  // This is the COM2 Attributes value storage\r
+  //\r
+  UINT8   COM2BaudRate;\r
+  UINT8   COM2DataRate;\r
+  UINT8   COM2StopBits;\r
+  UINT8   COM2Parity;\r
+  UINT8   COM2TerminalType;\r
+\r
+  //\r
+  // Driver Option Add Handle page storage\r
+  //\r
+  UINT16  DriverAddHandleDesc[100];\r
+  UINT16  DriverAddHandleOptionalData[100];\r
+  UINT8   DriverAddActive;\r
+  UINT8   DriverAddForceReconnect;\r
+\r
+  //\r
+  // Console Input/Output/Errorout using COM port check storage\r
+  //\r
+  UINT8   ConsoleInputCOM1;\r
+  UINT8   ConsoleInputCOM2;\r
+  UINT8   ConsoleOutputCOM1;\r
+  UINT8   ConsoleOutputCOM2;\r
+  UINT8   ConsoleErrorCOM1;\r
+  UINT8   ConsoleErrorCOM2;\r
+\r
+  //\r
+  // At most 100 input/output/errorout device for console storage\r
+  //\r
+  UINT8   ConsoleCheck[100];\r
+\r
+  //\r
+  // Boot or Driver Option Order storage\r
+  //\r
+  UINT8   OptionOrder[100];\r
+  UINT8   DriverOptionToBeDeleted[100];\r
+\r
+  //\r
+  // Boot Option Delete storage\r
+  //\r
+  UINT8   BootOptionDel[100];\r
+  UINT8   DriverOptionDel[100];\r
+\r
+  //\r
+  // This is the Terminal Attributes value storage\r
+  //\r
+  UINT8   COMBaudRate;\r
+  UINT8   COMDataRate;\r
+  UINT8   COMStopBits;\r
+  UINT8   COMParity;\r
+  UINT8   COMTerminalType;\r
+\r
+  //\r
+  // Legacy Device Order Selection Storage\r
+  //\r
+  UINT8   LegacyFD[100];\r
+  UINT8   LegacyHD[100];\r
+  UINT8   LegacyCD[100];\r
+  UINT8   LegacyNET[100];\r
+  UINT8   LegacyBEV[100];\r
+\r
+  //\r
+  // We use DisableMap array to record the enable/disable state of each boot device\r
+  // It should be taken as a bit array, from left to right there are totally 256 bits\r
+  // the most left one stands for BBS table item 0, and the most right one stands for item 256\r
+  // If the bit is 1, it means the boot device has been disabled.\r
+  //\r
+  UINT8   DisableMap[32];\r
+\r
+  //\r
+  // Console Output Text Mode\r
+  //\r
+  UINT16  ConsoleOutMode;\r
+\r
+  //\r
+  //  UINT16                    PadArea[10];\r
+  //\r
+} BMM_FAKE_NV_DATA;\r
+\r
+//\r
+// Key used by File Explorer forms\r
+//\r
+#define KEY_VALUE_SAVE_AND_EXIT_BOOT           0x1000\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT_BOOT        0x1001\r
+#define KEY_VALUE_SAVE_AND_EXIT_DRIVER         0x1002\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER      0x1003\r
+\r
+//\r
+// This is the data structure used by File Explorer formset\r
+//\r
+typedef struct {\r
+  UINT16  DescriptionData[75];\r
+  UINT16  OptionalData[127];\r
+  UINT8   Active;\r
+  UINT8   ForceReconnect;\r
+} FILE_EXPLORER_NV_DATA;\r
+\r
+#endif\r
+\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c
new file mode 100644 (file)
index 0000000..d1608bf
--- /dev/null
@@ -0,0 +1,1211 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  UpdatePage.c\r
+\r
+Abstract:\r
+\r
+  Dynamically Update the pages\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+EFI_GUID gTerminalDriverGuid = {\r
+  0x10634d8e, 0x1c05, 0x46cb, {0xbb, 0xc, 0x5a, 0xfd, 0xc8, 0x29, 0xa8, 0xc8}\r
+};\r
+\r
+VOID\r
+RefreshUpdateData (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Refresh the global UpdateData structure.\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  None.\r
+\r
+--*/\r
+{\r
+  gUpdateData.Offset = 0;\r
+}\r
+\r
+VOID\r
+UpdatePageStart (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  RefreshUpdateData ();\r
+\r
+  if (!(CallbackData->BmmAskSaveOrNot)) {\r
+    //\r
+    // Add a "Go back to main page" tag in front of the form when there are no\r
+    // "Apply changes" and "Discard changes" tags in the end of the form.\r
+    //\r
+    CreateGotoOpCode (\r
+      FORM_MAIN_ID,\r
+      STRING_TOKEN (STR_FORM_GOTO_MAIN),\r
+      STRING_TOKEN (STR_FORM_GOTO_MAIN),\r
+      0,\r
+      FORM_MAIN_ID,\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+}\r
+\r
+VOID\r
+UpdatePageEnd (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  //\r
+  // Create the "Apply changes" and "Discard changes" tags.\r
+  //\r
+  if (CallbackData->BmmAskSaveOrNot) {\r
+    CreateSubTitleOpCode (\r
+      STRING_TOKEN (STR_NULL_STRING),\r
+      0,\r
+      0,\r
+      0,\r
+      &gUpdateData\r
+      );\r
+\r
+    CreateGotoOpCode (\r
+      FORM_MAIN_ID,\r
+      STRING_TOKEN (STR_SAVE_AND_EXIT),\r
+      STRING_TOKEN (STR_NULL_STRING),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      KEY_VALUE_SAVE_AND_EXIT,\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  //\r
+  // Ensure user can return to the main page.\r
+  //\r
+  CreateGotoOpCode (\r
+    FORM_MAIN_ID,\r
+    STRING_TOKEN (STR_NO_SAVE_AND_EXIT),\r
+    STRING_TOKEN (STR_NULL_STRING),\r
+    EFI_IFR_FLAG_CALLBACK,\r
+    KEY_VALUE_NO_SAVE_AND_EXIT,\r
+    &gUpdateData\r
+    );\r
+\r
+  IfrLibUpdateForm (\r
+    CallbackData->BmmHiiHandle,\r
+    &mBootMaintGuid,\r
+    CallbackData->BmmCurrentPageId,\r
+    CallbackData->BmmCurrentPageId,\r
+    FALSE,\r
+    &gUpdateData\r
+    );\r
+}\r
+\r
+VOID\r
+CleanUpPage (\r
+  IN UINT16                           LabelId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  RefreshUpdateData ();\r
+\r
+  //\r
+  // Remove all op-codes from dynamic page\r
+  //\r
+  IfrLibUpdateForm (\r
+    CallbackData->BmmHiiHandle,\r
+    &mBootMaintGuid,\r
+    LabelId,\r
+    LabelId,\r
+    FALSE,\r
+    &gUpdateData\r
+    );\r
+}\r
+\r
+EFI_STATUS\r
+BootThisFile (\r
+  IN BM_FILE_CONTEXT                   *FileContext\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  UINTN             ExitDataSize;\r
+  CHAR16            *ExitData;\r
+  BDS_COMMON_OPTION *Option;\r
+\r
+  Status                  = gBS->AllocatePool (EfiBootServicesData, sizeof (BDS_COMMON_OPTION), (VOID **) &Option);\r
+  Option->Description     = FileContext->FileName;\r
+  Option->DevicePath      = FileContext->DevicePath;\r
+  Option->LoadOptionsSize = 0;\r
+  Option->LoadOptions     = NULL;\r
+\r
+  //\r
+  // Since current no boot from removable media directly is allowed */\r
+  //\r
+  gST->ConOut->ClearScreen (gST->ConOut);\r
+\r
+  gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+  ExitDataSize  = 0;\r
+\r
+  Status        = BdsLibBootViaBootOption (Option, Option->DevicePath, &ExitDataSize, &ExitData);\r
+\r
+  gBS->RestoreTPL (TPL_APPLICATION);\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+VOID\r
+UpdateConCOMPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        Index;\r
+  EFI_STATUS    Status;\r
+  VOID          *Interface;\r
+\r
+  CallbackData->BmmAskSaveOrNot = FALSE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  Status = EfiLibLocateProtocol (&gTerminalDriverGuid, (VOID **) &Interface);\r
+  if (!EFI_ERROR (Status)) {\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+\r
+      CreateGotoOpCode (\r
+        FORM_CON_COM_SETUP_ID,\r
+        NewMenuEntry->DisplayStringToken,\r
+        STRING_TOKEN (STR_NULL_STRING),\r
+        EFI_IFR_FLAG_CALLBACK,\r
+        (UINT16) (TERMINAL_OPTION_OFFSET + Index),\r
+        &gUpdateData\r
+        );\r
+    }\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateBootDelPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  UINT16          Index;\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);\r
+\r
+  for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+    NewLoadContext  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (NewLoadContext->IsLegacy) {\r
+      continue;\r
+    }\r
+\r
+    NewLoadContext->Deleted = FALSE;\r
+    CallbackData->BmmFakeNvData.BootOptionDel[Index] = 0x00;\r
+\r
+    CreateCheckBoxOpCode (\r
+      (EFI_QUESTION_ID) (BOOT_OPTION_DEL_QUESTION_ID + Index),\r
+      VARSTORE_ID_BOOT_MAINT,\r
+      (UINT16) (BOOT_OPTION_DEL_VAR_OFFSET + Index),\r
+      NewMenuEntry->DisplayStringToken,\r
+      NewMenuEntry->HelpStringToken,\r
+      0,\r
+      0,\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateDrvAddHandlePage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        Index;\r
+\r
+  CallbackData->BmmAskSaveOrNot = FALSE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  for (Index = 0; Index < DriverMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index);\r
+\r
+    CreateGotoOpCode (\r
+      FORM_DRV_ADD_HANDLE_DESC_ID,\r
+      NewMenuEntry->DisplayStringToken,\r
+      STRING_TOKEN (STR_NULL_STRING),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      (UINT16) (HANDLE_OPTION_OFFSET + Index),\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateDrvDelPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  UINT16          Index;\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &DriverOptionMenu);\r
+\r
+  for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry            = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+\r
+    NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewLoadContext->Deleted = FALSE;\r
+    CallbackData->BmmFakeNvData.DriverOptionDel[Index] = 0x00;\r
+\r
+    CreateCheckBoxOpCode (\r
+      (EFI_QUESTION_ID) (DRIVER_OPTION_DEL_QUESTION_ID + Index),\r
+      VARSTORE_ID_BOOT_MAINT,\r
+      (UINT16) (DRIVER_OPTION_DEL_VAR_OFFSET + Index),\r
+      NewMenuEntry->DisplayStringToken,\r
+      NewMenuEntry->HelpStringToken,\r
+      0,\r
+      0,\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateDriverAddHandleDescPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+\r
+  CallbackData->BmmFakeNvData.DriverAddActive          = 0x01;\r
+  CallbackData->BmmFakeNvData.DriverAddForceReconnect  = 0x00;\r
+  CallbackData->BmmAskSaveOrNot                        = TRUE;\r
+  NewMenuEntry = CallbackData->MenuEntry;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  CreateSubTitleOpCode (\r
+    NewMenuEntry->DisplayStringToken,\r
+    0,\r
+    0,\r
+    0,\r
+    &gUpdateData\r
+    );\r
+\r
+  CreateStringOpCode (\r
+    (EFI_QUESTION_ID) DRV_ADD_HANDLE_DESC_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    DRV_ADD_HANDLE_DESC_VAR_OFFSET,\r
+    STRING_TOKEN (STR_LOAD_OPTION_DESC),\r
+    STRING_TOKEN (STR_NULL_STRING),\r
+    0,\r
+    0,\r
+    6,\r
+    75,\r
+    &gUpdateData\r
+    );\r
+\r
+  CreateCheckBoxOpCode (\r
+    (EFI_QUESTION_ID) DRV_ADD_RECON_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    DRV_ADD_RECON_VAR_OFFSET,\r
+    STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),\r
+    STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),\r
+    0,\r
+    0,\r
+    &gUpdateData\r
+    );\r
+\r
+  CreateStringOpCode (\r
+    (EFI_QUESTION_ID) DRIVER_ADD_OPTION_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    DRIVER_ADD_OPTION_VAR_OFFSET,\r
+    STRING_TOKEN (STR_OPTIONAL_DATA),\r
+    STRING_TOKEN (STR_NULL_STRING),\r
+    0,\r
+    0,\r
+    6,\r
+    75,\r
+    &gUpdateData\r
+    );\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateConsolePage (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BM_MENU_OPTION                   *ConsoleMenu,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY       *NewMenuEntry;\r
+  BM_CONSOLE_CONTEXT  *NewConsoleContext;\r
+  BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+  UINT16              Index;\r
+  UINT16              Index2;\r
+  UINT8               CheckFlags;\r
+  EFI_STATUS          Status;\r
+  VOID                *Interface;\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {\r
+    NewMenuEntry      = BOpt_GetMenuEntry (ConsoleMenu, Index);\r
+    NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    CheckFlags        = 0;\r
+    if (NewConsoleContext->IsActive) {\r
+      CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;\r
+      CallbackData->BmmFakeNvData.ConsoleCheck[Index] = TRUE;\r
+    } else {\r
+      CallbackData->BmmFakeNvData.ConsoleCheck[Index] = FALSE;\r
+    }\r
+\r
+    CreateCheckBoxOpCode (\r
+      (EFI_QUESTION_ID) (CON_DEVICE_QUESTION_ID + Index),\r
+      VARSTORE_ID_BOOT_MAINT,\r
+      (UINT16) (CON_DEVICE_VAR_OFFSET + Index),\r
+      NewMenuEntry->DisplayStringToken,\r
+      NewMenuEntry->HelpStringToken,\r
+      0,\r
+      CheckFlags,\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  Status = EfiLibLocateProtocol (&gTerminalDriverGuid, (VOID **) &Interface);\r
+  if (!EFI_ERROR (Status)) {\r
+    for (Index2 = 0; Index2 < TerminalMenu.MenuNumber; Index2++) {\r
+      CheckFlags          = 0;\r
+      NewMenuEntry        = BOpt_GetMenuEntry (&TerminalMenu, Index2);\r
+      NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+      if ((NewTerminalContext->IsConIn && (UpdatePageId == FORM_CON_IN_ID)) ||\r
+          (NewTerminalContext->IsConOut && (UpdatePageId == FORM_CON_OUT_ID)) ||\r
+          (NewTerminalContext->IsStdErr && (UpdatePageId == FORM_CON_ERR_ID))\r
+          ) {\r
+        CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;\r
+        CallbackData->BmmFakeNvData.ConsoleCheck[Index] = TRUE;\r
+      } else {\r
+        CallbackData->BmmFakeNvData.ConsoleCheck[Index] = FALSE;\r
+      }\r
+\r
+      CreateCheckBoxOpCode (\r
+        (EFI_QUESTION_ID) (CON_DEVICE_QUESTION_ID + Index),\r
+        VARSTORE_ID_BOOT_MAINT,\r
+        (UINT16) (CON_DEVICE_VAR_OFFSET + Index),\r
+        NewMenuEntry->DisplayStringToken,\r
+        NewMenuEntry->HelpStringToken,\r
+        0,\r
+        CheckFlags,\r
+        &gUpdateData\r
+        );\r
+\r
+      Index++;\r
+    }\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateOrderPage (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BM_MENU_OPTION                   *OptionMenu,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        Index;\r
+  IFR_OPTION    *IfrOptionList;\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);\r
+\r
+  ZeroMem (CallbackData->BmmFakeNvData.OptionOrder, 100);\r
+\r
+  IfrOptionList = EfiAllocateZeroPool (sizeof (IFR_OPTION) * OptionMenu->MenuNumber);\r
+  if (NULL == IfrOptionList) {\r
+    return ;\r
+  }\r
+\r
+  for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);\r
+    IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;\r
+    IfrOptionList[Index].Value.u8 = (UINT8) (NewMenuEntry->OptionNumber + 1);\r
+    IfrOptionList[Index].Flags = 0;\r
+    CallbackData->BmmFakeNvData.OptionOrder[Index] = IfrOptionList[Index].Value.u8;\r
+  }\r
+\r
+  if (OptionMenu->MenuNumber > 0) {\r
+    CreateOrderedListOpCode (\r
+      (EFI_QUESTION_ID) OPTION_ORDER_QUESTION_ID,\r
+      VARSTORE_ID_BOOT_MAINT,\r
+      OPTION_ORDER_VAR_OFFSET,\r
+      STRING_TOKEN (STR_CHANGE_ORDER),\r
+      STRING_TOKEN (STR_CHANGE_ORDER),\r
+      0,\r
+      0,\r
+      EFI_IFR_NUMERIC_SIZE_1,\r
+      100,\r
+      IfrOptionList,\r
+      OptionMenu->MenuNumber,\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  SafeFreePool (IfrOptionList);\r
+\r
+  UpdatePageEnd (CallbackData);\r
+\r
+  CopyMem (\r
+    CallbackData->BmmOldFakeNVData.OptionOrder,\r
+    CallbackData->BmmFakeNvData.OptionOrder,\r
+    100\r
+    );\r
+}\r
+\r
+VOID\r
+UpdateBootNextPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  IFR_OPTION      *IfrOptionList;\r
+  UINTN           NumberOfOptions;\r
+  UINT16          Index;\r
+\r
+  IfrOptionList                 = NULL;\r
+  NumberOfOptions               = BootOptionMenu.MenuNumber;\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);\r
+\r
+  if (NumberOfOptions > 0) {\r
+    IfrOptionList = EfiAllocateZeroPool ((NumberOfOptions + 1) * sizeof (IFR_OPTION));\r
+\r
+    ASSERT (IfrOptionList);\r
+\r
+    CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber);\r
+\r
+    for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+      NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+      NewLoadContext  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+      if (NewLoadContext->IsBootNext) {\r
+        IfrOptionList[Index].Flags            = EFI_IFR_OPTION_DEFAULT;\r
+        CallbackData->BmmFakeNvData.BootNext = Index;\r
+      } else {\r
+        IfrOptionList[Index].Flags = 0;\r
+      }\r
+\r
+      IfrOptionList[Index].Value.u16    = Index;\r
+      IfrOptionList[Index].StringToken  = NewMenuEntry->DisplayStringToken;\r
+    }\r
+\r
+    IfrOptionList[Index].Value.u16        = Index;\r
+    IfrOptionList[Index].StringToken  = STRING_TOKEN (STR_NONE);\r
+    IfrOptionList[Index].Flags        = 0;\r
+    if (CallbackData->BmmFakeNvData.BootNext == Index) {\r
+      IfrOptionList[Index].Flags |= EFI_IFR_OPTION_DEFAULT;\r
+    }\r
+\r
+    CreateOneOfOpCode (\r
+      (EFI_QUESTION_ID) BOOT_NEXT_QUESTION_ID,\r
+      VARSTORE_ID_BOOT_MAINT,\r
+      BOOT_NEXT_VAR_OFFSET,\r
+      STRING_TOKEN (STR_BOOT_NEXT),\r
+      STRING_TOKEN (STR_BOOT_NEXT_HELP),\r
+      0,\r
+      EFI_IFR_NUMERIC_SIZE_2,\r
+      IfrOptionList,\r
+      (UINTN) (NumberOfOptions + 1),\r
+      &gUpdateData\r
+      );\r
+\r
+    SafeFreePool (IfrOptionList);\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateTimeOutPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  UINT16  BootTimeOut;\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  BootTimeOut = BdsLibGetTimeout ();\r
+\r
+  CreateNumericOpCode (\r
+    (EFI_QUESTION_ID) BOOT_TIME_OUT_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    BOOT_TIME_OUT_VAR_OFFSET,\r
+    STRING_TOKEN (STR_NUM_AUTO_BOOT),\r
+    STRING_TOKEN (STR_HLP_AUTO_BOOT),\r
+    0,\r
+    EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC,\r
+    0,\r
+    65535,\r
+    0,\r
+    BootTimeOut,\r
+    &gUpdateData\r
+    );\r
+\r
+  CallbackData->BmmFakeNvData.BootTimeOut = BootTimeOut;\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateConModePage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Refresh the text mode page\r
+\r
+Arguments:\r
+  CallbackData      - BMM_CALLBACK_DATA\r
+\r
+Returns:\r
+  None.\r
+\r
+--*/\r
+{\r
+  UINTN                         Mode;\r
+  UINTN                         Index;\r
+  UINTN                         Col;\r
+  UINTN                         Row;\r
+  CHAR16                        RowString[50];\r
+  CHAR16                        ModeString[50];\r
+  UINTN                         MaxMode;\r
+  UINTN                         ValidMode;\r
+  EFI_STRING_ID                 *ModeToken;\r
+  IFR_OPTION                    *IfrOptionList;\r
+  EFI_STATUS                    Status;\r
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *ConOut;\r
+\r
+  ConOut    = gST->ConOut;\r
+  Index     = 0;\r
+  ValidMode = 0;\r
+  MaxMode   = (UINTN) (ConOut->Mode->MaxMode);\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  //\r
+  // Check valid mode\r
+  //\r
+  for (Mode = 0; Mode < MaxMode; Mode++) {\r
+    Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+    ValidMode++;\r
+  }\r
+\r
+  if (ValidMode == 0) {\r
+    return;\r
+  }\r
+\r
+  IfrOptionList       = EfiAllocateZeroPool (sizeof (IFR_OPTION) * ValidMode);\r
+  ASSERT(IfrOptionList != NULL);\r
+\r
+  ModeToken           = EfiAllocateZeroPool (sizeof (EFI_STRING_ID) * ValidMode);\r
+  ASSERT(ModeToken != NULL);\r
+\r
+  //\r
+  // Determin which mode should be the first entry in menu\r
+  //\r
+  GetConsoleOutMode (CallbackData);\r
+\r
+  //\r
+  // Build text mode options\r
+  //\r
+  for (Mode = 0; Mode < MaxMode; Mode++) {\r
+    Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+    //\r
+    // Build mode string Column x Row\r
+    //\r
+    UnicodeValueToString (ModeString, 0, Col, 0);\r
+    StrCat (ModeString, L" x ");\r
+    UnicodeValueToString (RowString, 0, Row, 0);\r
+    StrCat (ModeString, RowString);\r
+\r
+    IfrLibNewString (CallbackData->BmmHiiHandle, &ModeToken[Index], ModeString);\r
+\r
+    IfrOptionList[Index].StringToken  = ModeToken[Index];\r
+    IfrOptionList[Index].Value.u16    = (UINT16) Mode;\r
+    if (Mode == CallbackData->BmmFakeNvData.ConsoleOutMode) {\r
+      IfrOptionList[Index].Flags      = EFI_IFR_OPTION_DEFAULT;\r
+    } else {\r
+      IfrOptionList[Index].Flags      = 0;\r
+    }\r
+    Index++;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (EFI_QUESTION_ID) CON_MODE_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    CON_MODE_VAR_OFFSET,\r
+    STRING_TOKEN (STR_CON_MODE_SETUP),\r
+    STRING_TOKEN (STR_CON_MODE_SETUP),\r
+    EFI_IFR_FLAG_RESET_REQUIRED,\r
+    EFI_IFR_NUMERIC_SIZE_2,\r
+    IfrOptionList,\r
+    ValidMode,\r
+    &gUpdateData\r
+    );\r
+  SafeFreePool (IfrOptionList);\r
+  SafeFreePool (ModeToken);\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateTerminalPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  UINT8               Index;\r
+  UINT8               CheckFlags;\r
+  IFR_OPTION          *IfrOptionList;\r
+  BM_MENU_ENTRY       *NewMenuEntry;\r
+  BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  NewMenuEntry = BOpt_GetMenuEntry (\r
+                  &TerminalMenu,\r
+                  CallbackData->CurrentTerminal\r
+                  );\r
+\r
+  if (NewMenuEntry == NULL) {\r
+    return ;\r
+  }\r
+\r
+  NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+  IfrOptionList       = EfiAllocateZeroPool (sizeof (IFR_OPTION) * 19);\r
+  if (IfrOptionList == NULL) {\r
+    return ;\r
+  }\r
+\r
+  for (Index = 0; Index < 19; Index++) {\r
+    CheckFlags = 0;\r
+    if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[Index].Value)) {\r
+      CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+      NewTerminalContext->BaudRateIndex         = Index;\r
+      CallbackData->BmmFakeNvData.COMBaudRate  = NewTerminalContext->BaudRateIndex;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].StringToken  = BaudRateList[Index].StringToken;\r
+    IfrOptionList[Index].Value.u8     = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (EFI_QUESTION_ID) COM_BAUD_RATE_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    COM_BAUD_RATE_VAR_OFFSET,\r
+    STRING_TOKEN (STR_COM_BAUD_RATE),\r
+    STRING_TOKEN (STR_COM_BAUD_RATE),\r
+    0,\r
+    EFI_IFR_NUMERIC_SIZE_1,\r
+    IfrOptionList,\r
+    19,\r
+    &gUpdateData\r
+    );\r
+\r
+  for (Index = 0; Index < 4; Index++) {\r
+    CheckFlags = 0;\r
+\r
+    if (NewTerminalContext->DataBits == DataBitsList[Index].Value) {\r
+      NewTerminalContext->DataBitsIndex         = Index;\r
+      CallbackData->BmmFakeNvData.COMDataRate  = NewTerminalContext->DataBitsIndex;\r
+      CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].StringToken  = DataBitsList[Index].StringToken;\r
+    IfrOptionList[Index].Value.u8     = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (EFI_QUESTION_ID) COM_DATA_RATE_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    COM_DATA_RATE_VAR_OFFSET,\r
+    STRING_TOKEN (STR_COM_DATA_BITS),\r
+    STRING_TOKEN (STR_COM_DATA_BITS),\r
+    0,\r
+    EFI_IFR_NUMERIC_SIZE_1,\r
+    IfrOptionList,\r
+    4,\r
+    &gUpdateData\r
+    );\r
+\r
+  for (Index = 0; Index < 5; Index++) {\r
+    CheckFlags = 0;\r
+    if (NewTerminalContext->Parity == ParityList[Index].Value) {\r
+      CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+      NewTerminalContext->ParityIndex         = (UINT8) Index;\r
+      CallbackData->BmmFakeNvData.COMParity  = NewTerminalContext->ParityIndex;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].StringToken  = ParityList[Index].StringToken;\r
+    IfrOptionList[Index].Value.u8     = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (EFI_QUESTION_ID) COM_PARITY_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    COM_PARITY_VAR_OFFSET,\r
+    STRING_TOKEN (STR_COM_PARITY),\r
+    STRING_TOKEN (STR_COM_PARITY),\r
+    0,\r
+    EFI_IFR_NUMERIC_SIZE_1,\r
+    IfrOptionList,\r
+    5,\r
+    &gUpdateData\r
+    );\r
+\r
+  for (Index = 0; Index < 3; Index++) {\r
+    CheckFlags = 0;\r
+    if (NewTerminalContext->StopBits == StopBitsList[Index].Value) {\r
+      CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+      NewTerminalContext->StopBitsIndex         = (UINT8) Index;\r
+      CallbackData->BmmFakeNvData.COMStopBits  = NewTerminalContext->StopBitsIndex;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].StringToken  = StopBitsList[Index].StringToken;\r
+    IfrOptionList[Index].Value.u8     = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (EFI_QUESTION_ID) COM_STOP_BITS_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    COM_STOP_BITS_VAR_OFFSET,\r
+    STRING_TOKEN (STR_COM_STOP_BITS),\r
+    STRING_TOKEN (STR_COM_STOP_BITS),\r
+    0,\r
+    EFI_IFR_NUMERIC_SIZE_1,\r
+    IfrOptionList,\r
+    3,\r
+    &gUpdateData\r
+    );\r
+\r
+  for (Index = 0; Index < 4; Index++) {\r
+    CheckFlags = 0;\r
+    if (NewTerminalContext->TerminalType == Index) {\r
+      CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+      CallbackData->BmmFakeNvData.COMTerminalType = NewTerminalContext->TerminalType;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].StringToken  = (EFI_STRING_ID) TerminalType[Index];\r
+    IfrOptionList[Index].Value.u8     = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (EFI_QUESTION_ID) COM_TERMINAL_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    COM_TERMINAL_VAR_OFFSET,\r
+    STRING_TOKEN (STR_COM_TERMI_TYPE),\r
+    STRING_TOKEN (STR_COM_TERMI_TYPE),\r
+    0,\r
+    EFI_IFR_NUMERIC_SIZE_1,\r
+    IfrOptionList,\r
+    4,\r
+    &gUpdateData\r
+    );\r
+\r
+  SafeFreePool (IfrOptionList);\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdatePageBody (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  CleanUpPage (UpdatePageId, CallbackData);\r
+  switch (UpdatePageId) {\r
+  case FORM_CON_IN_ID:\r
+    UpdateConsolePage (UpdatePageId, &ConsoleInpMenu, CallbackData);\r
+    break;\r
+\r
+  case FORM_CON_OUT_ID:\r
+    UpdateConsolePage (UpdatePageId, &ConsoleOutMenu, CallbackData);\r
+    break;\r
+\r
+  case FORM_CON_ERR_ID:\r
+    UpdateConsolePage (UpdatePageId, &ConsoleErrMenu, CallbackData);\r
+    break;\r
+\r
+  case FORM_BOOT_CHG_ID:\r
+    UpdateOrderPage (UpdatePageId, &BootOptionMenu, CallbackData);\r
+    break;\r
+\r
+  case FORM_DRV_CHG_ID:\r
+    UpdateOrderPage (UpdatePageId, &DriverOptionMenu, CallbackData);\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+VOID *\r
+GetLegacyBootOptionVar (\r
+  IN  UINTN                            DeviceType,\r
+  OUT UINTN                            *OptionIndex,\r
+  OUT UINTN                            *OptionSize\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  VOID                      *OptionBuffer;\r
+  UINTN                     OrderSize;\r
+  UINTN                     Index;\r
+  UINT16                    *OrderBuffer;\r
+  CHAR16                    StrTemp[100];\r
+  UINT16                    FilePathSize;\r
+  UINT8                     *Ptr;\r
+  UINT8                     *OptionalData;\r
+\r
+  //\r
+  // Get Boot Option number from the size of BootOrder\r
+  //\r
+  OrderBuffer = BdsLibGetVariableAndSize (\r
+                  L"BootOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  &OrderSize\r
+                  );\r
+\r
+  for (Index = 0; Index < OrderSize / sizeof (UINT16); Index++) {\r
+    UnicodeSPrint (StrTemp, 100, L"Boot%04x", OrderBuffer[Index]);\r
+    OptionBuffer = BdsLibGetVariableAndSize (\r
+                    StrTemp,\r
+                    &gEfiGlobalVariableGuid,\r
+                    OptionSize\r
+                    );\r
+    if (NULL == OptionBuffer) {\r
+      continue;\r
+    }\r
+\r
+    Ptr       = (UINT8 *) OptionBuffer;\r
+    Ptr += sizeof (UINT32);\r
+\r
+    FilePathSize = *(UINT16 *) Ptr;\r
+    Ptr += sizeof (UINT16);\r
+\r
+    Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+    //\r
+    // Now Ptr point to Device Path\r
+    //\r
+    DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+    Ptr += FilePathSize;\r
+\r
+    //\r
+    // Now Ptr point to Optional Data\r
+    //\r
+    OptionalData = Ptr;\r
+\r
+    if ((DeviceType == ((BBS_TABLE *) OptionalData)->DeviceType) &&\r
+        (BBS_DEVICE_PATH == DevicePath->Type) &&\r
+        (BBS_BBS_DP == DevicePath->SubType)\r
+        ) {\r
+      *OptionIndex = OrderBuffer[Index];\r
+      SafeFreePool (OrderBuffer);\r
+      return OptionBuffer;\r
+    } else {\r
+      SafeFreePool (OptionBuffer);\r
+    }\r
+  }\r
+\r
+  SafeFreePool (OrderBuffer);\r
+  return NULL;\r
+}\r
+\r
+VOID\r
+UpdateSetLegacyDeviceOrderPage (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
+  BM_MENU_OPTION              *OptionMenu;\r
+  BM_MENU_ENTRY               *NewMenuEntry;\r
+  IFR_OPTION                  *IfrOptionList;\r
+  EFI_STRING_ID               StrRef;\r
+  EFI_STRING_ID               StrRefHelp;\r
+  BBS_TYPE                    BbsType;\r
+  UINTN                       VarSize;\r
+  UINTN                       Pos;\r
+  UINTN                       Bit;\r
+  UINT16                      Index;\r
+  UINT16                      Key;\r
+  CHAR16                      String[100];\r
+  CHAR16                      *TypeStr;\r
+  CHAR16                      *TypeStrHelp;\r
+  UINT16                      VarDevOrder;\r
+  UINT8                       *VarData;\r
+  UINT8                       *LegacyOrder;\r
+  UINT8                       *OldData;\r
+  UINT8                       *DisMap;\r
+\r
+  OptionMenu = NULL;\r
+  Key = 0;\r
+  StrRef = 0;\r
+  StrRefHelp = 0;\r
+  TypeStr = NULL;\r
+  TypeStrHelp = NULL;\r
+  BbsType = BBS_FLOPPY;\r
+  LegacyOrder = NULL;\r
+  OldData = NULL;\r
+  DisMap = NULL;\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+  UpdatePageStart (CallbackData);\r
+\r
+  DisMap = CallbackData->BmmOldFakeNVData.DisableMap;\r
+\r
+  SetMem (DisMap, 32, 0);\r
+  //\r
+  // Create oneof option list\r
+  //\r
+  switch (UpdatePageId) {\r
+  case FORM_SET_FD_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyFDMenu;\r
+    Key         = (UINT16) LEGACY_FD_QUESTION_ID;\r
+    TypeStr     = StrFloppy;\r
+    TypeStrHelp = StrFloppyHelp;\r
+    BbsType     = BBS_FLOPPY;\r
+    LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyFD;\r
+    break;\r
+\r
+  case FORM_SET_HD_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyHDMenu;\r
+    Key         = (UINT16) LEGACY_HD_QUESTION_ID;\r
+    TypeStr     = StrHardDisk;\r
+    TypeStrHelp = StrHardDiskHelp;\r
+    BbsType     = BBS_HARDDISK;\r
+    LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyHD;\r
+    break;\r
+\r
+  case FORM_SET_CD_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyCDMenu;\r
+    Key         = (UINT16) LEGACY_CD_QUESTION_ID;\r
+    TypeStr     = StrCDROM;\r
+    TypeStrHelp = StrCDROMHelp;\r
+    BbsType     = BBS_CDROM;\r
+    LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyCD;\r
+    break;\r
+\r
+  case FORM_SET_NET_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyNETMenu;\r
+    Key         = (UINT16) LEGACY_NET_QUESTION_ID;\r
+    TypeStr     = StrNET;\r
+    TypeStrHelp = StrNETHelp;\r
+    BbsType     = BBS_EMBED_NETWORK;\r
+    LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyNET;\r
+    break;\r
+\r
+  case FORM_SET_BEV_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
+    Key         = (UINT16) LEGACY_BEV_QUESTION_ID;\r
+    TypeStr     = StrBEV;\r
+    TypeStrHelp = StrBEVHelp;\r
+    BbsType     = BBS_BEV_DEVICE;\r
+    LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyBEV;\r
+    break;\r
+\r
+  }\r
+\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);\r
+\r
+  IfrOptionList = EfiAllocateZeroPool (sizeof (IFR_OPTION) * (OptionMenu->MenuNumber + 1));\r
+  if (NULL == IfrOptionList) {\r
+    return ;\r
+  }\r
+\r
+  for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+    NewMenuEntry                = BOpt_GetMenuEntry (OptionMenu, Index);\r
+    IfrOptionList[Index].Flags  = 0;\r
+    if (0 == Index) {\r
+      IfrOptionList[Index].Flags |= EFI_IFR_OPTION_DEFAULT;\r
+    }\r
+\r
+    IfrOptionList[Index].StringToken  = NewMenuEntry->DisplayStringToken;\r
+    IfrOptionList[Index].Value.u8     = (UINT8) ((BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->Index;\r
+  }\r
+  //\r
+  // for item "Disabled"\r
+  //\r
+  IfrOptionList[Index].Flags        = 0;\r
+  IfrOptionList[Index].StringToken  = STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE);\r
+  IfrOptionList[Index].Value.u8     = 0xFF;\r
+\r
+  //\r
+  // Get Device Order from variable\r
+  //\r
+  VarData = BdsLibGetVariableAndSize (\r
+              VarLegacyDevOrder,\r
+              &EfiLegacyDevOrderGuid,\r
+              &VarSize\r
+              );\r
+\r
+  if (NULL != VarData) {\r
+    DevOrder    = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+    while (VarData < VarData + VarSize) {\r
+      if (DevOrder->BbsType == BbsType) {\r
+        break;\r
+      }\r
+\r
+      VarData += sizeof (BBS_TYPE);\r
+      VarData += *(UINT16 *) VarData;\r
+      DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+    }\r
+    //\r
+    // Create oneof tag here for FD/HD/CD #1 #2\r
+    //\r
+    for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+      //\r
+      // Create the string for oneof tag\r
+      //\r
+      UnicodeSPrint (String, sizeof (String), TypeStr, Index);\r
+      StrRef = 0;\r
+      IfrLibNewString (CallbackData->BmmHiiHandle, &StrRef, String);\r
+\r
+      UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index);\r
+      StrRefHelp = 0;\r
+      IfrLibNewString (CallbackData->BmmHiiHandle, &StrRefHelp, String);\r
+\r
+      CreateOneOfOpCode (\r
+        (EFI_QUESTION_ID) (Key + Index),\r
+        VARSTORE_ID_BOOT_MAINT,\r
+        (UINT16) (Key + Index - CONFIG_OPTION_OFFSET),\r
+        StrRef,\r
+        StrRefHelp,\r
+        EFI_IFR_FLAG_CALLBACK,\r
+        EFI_IFR_NUMERIC_SIZE_1,\r
+        IfrOptionList,\r
+        OptionMenu->MenuNumber + 1,\r
+        &gUpdateData\r
+        );\r
+\r
+      VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16));\r
+\r
+      if (0xFF00 == (VarDevOrder & 0xFF00)) {\r
+        LegacyOrder[Index]  = 0xFF;\r
+        Pos                 = (VarDevOrder & 0xFF) / 8;\r
+        Bit                 = 7 - ((VarDevOrder & 0xFF) % 8);\r
+        DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
+      } else {\r
+        LegacyOrder[Index] = (UINT8) (VarDevOrder & 0xFF);\r
+      }\r
+    }\r
+  }\r
+\r
+  CopyMem (OldData, LegacyOrder, 100);\r
+\r
+  if (IfrOptionList != NULL) {\r
+    SafeFreePool (IfrOptionList);\r
+    IfrOptionList = NULL;\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdatePageId (\r
+  BMM_CALLBACK_DATA              *Private,\r
+  UINT16                         NewPageId\r
+  )\r
+{\r
+  if ((NewPageId < FILE_OPTION_OFFSET) && (NewPageId >= HANDLE_OPTION_OFFSET)) {\r
+    //\r
+    // If we select a handle to add driver option, advance to the add handle description page.\r
+    //\r
+    NewPageId = FORM_DRV_ADD_HANDLE_DESC_ID;\r
+  } else if ((NewPageId == KEY_VALUE_SAVE_AND_EXIT) || (NewPageId == KEY_VALUE_NO_SAVE_AND_EXIT)) {\r
+    //\r
+    // Return to main page after "Save Changes" or "Discard Changes".\r
+    //\r
+    NewPageId = FORM_MAIN_ID;\r
+  } else if ((NewPageId >= TERMINAL_OPTION_OFFSET) && (NewPageId < CONSOLE_OPTION_OFFSET)) {\r
+    NewPageId = FORM_CON_COM_SETUP_ID;\r
+  }\r
+\r
+  if ((NewPageId > 0) && (NewPageId < MAXIMUM_FORM_ID)) {\r
+    Private->BmmPreviousPageId  = Private->BmmCurrentPageId;\r
+    Private->BmmCurrentPageId   = NewPageId;\r
+  }\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/Variable.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/Variable.c
new file mode 100644 (file)
index 0000000..f5a1038
--- /dev/null
@@ -0,0 +1,1314 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  Variable.c\r
+\r
+Abstract:\r
+\r
+  Variable operation that will be used by bootmaint\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+EFI_STATUS\r
+Var_DelBootOption (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Delete Boot Option that represent a Deleted state in BootOptionMenu.\r
+  After deleting this boot option, call Var_ChangeBootOrder to\r
+  make sure BootOrder is in valid state.\r
+\r
+Arguments:\r
+  LoadOption -- Pointer to the boot option that to be deleted\r
+\r
+Returns:\r
+  EFI_SUCCESS\r
+  Others\r
+\r
+--*/\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  UINT16          BootString[10];\r
+  EFI_STATUS      Status;\r
+  UINTN           Index;\r
+  UINTN           Index2;\r
+\r
+  Status  = EFI_SUCCESS;\r
+  Index2  = 0;\r
+  for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2));\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (!NewLoadContext->Deleted) {\r
+      continue;\r
+    }\r
+\r
+    UnicodeSPrint (\r
+      BootString,\r
+      sizeof (BootString),\r
+      L"Boot%04x",\r
+      NewMenuEntry->OptionNumber\r
+      );\r
+\r
+    EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid);\r
+    Index2++;\r
+    //\r
+    // If current Load Option is the same as BootNext,\r
+    // must delete BootNext in order to make sure\r
+    // there will be no panic on next boot\r
+    //\r
+    if (NewLoadContext->IsBootNext) {\r
+      EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
+    }\r
+\r
+    RemoveEntryList (&NewMenuEntry->Link);\r
+    BOpt_DestroyMenuEntry (NewMenuEntry);\r
+    NewMenuEntry = NULL;\r
+  }\r
+\r
+  BootOptionMenu.MenuNumber -= Index2;\r
+\r
+  Status = Var_ChangeBootOrder ();\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+Var_ChangeBootOrder (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  After any operation on Boot####, there will be a discrepancy in BootOrder.\r
+  Since some are missing but in BootOrder, while some are present but are\r
+  not reflected by BootOrder. Then a function rebuild BootOrder from\r
+  scratch by content from BootOptionMenu is needed.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  EFI_SUCCESS\r
+  Others\r
+\r
+--*/\r
+{\r
+\r
+  EFI_STATUS    Status;\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        *BootOrderList;\r
+  UINT16        *BootOrderListPtr;\r
+  UINTN         BootOrderListSize;\r
+  UINTN         Index;\r
+\r
+  BootOrderList     = NULL;\r
+  BootOrderListSize = 0;\r
+\r
+  //\r
+  // First check whether BootOrder is present in current configuration\r
+  //\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+\r
+  //\r
+  // If exists, delete it to hold new BootOrder\r
+  //\r
+  if (BootOrderList) {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+    SafeFreePool (BootOrderList);\r
+    BootOrderList = NULL;\r
+  }\r
+  //\r
+  // Maybe here should be some check method to ensure that\r
+  // no new added boot options will be added\r
+  // but the setup engine now will give only one callback\r
+  // that is to say, user are granted only one chance to\r
+  // decide whether the boot option will be added or not\r
+  // there should be no indictor to show whether this\r
+  // is a "new" boot option\r
+  //\r
+  BootOrderListSize = BootOptionMenu.MenuNumber;\r
+\r
+  if (BootOrderListSize > 0) {\r
+    BootOrderList = EfiAllocateZeroPool (BootOrderListSize * sizeof (UINT16));\r
+    ASSERT (BootOrderList != NULL);\r
+    BootOrderListPtr = BootOrderList;\r
+\r
+    //\r
+    // Get all current used Boot#### from BootOptionMenu.\r
+    // OptionNumber in each BM_LOAD_OPTION is really its\r
+    // #### value.\r
+    //\r
+    for (Index = 0; Index < BootOrderListSize; Index++) {\r
+      NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+      *BootOrderList  = (UINT16) NewMenuEntry->OptionNumber;\r
+      BootOrderList++;\r
+    }\r
+\r
+    BootOrderList = BootOrderListPtr;\r
+\r
+    //\r
+    // After building the BootOrderList, write it back\r
+    //\r
+    Status = gRT->SetVariable (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    BootOrderListSize * sizeof (UINT16),\r
+                    BootOrderList\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+Var_DelDriverOption (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Delete Load Option that represent a Deleted state in BootOptionMenu.\r
+  After deleting this Driver option, call Var_ChangeDriverOrder to\r
+  make sure DriverOrder is in valid state.\r
+\r
+Arguments:\r
+  LoadOption -- Pointer to the Driver option that to be deleted\r
+\r
+Returns:\r
+  EFI_SUCCESS\r
+  Others\r
+\r
+--*/\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  UINT16          DriverString[12];\r
+  EFI_STATUS      Status;\r
+  UINTN           Index;\r
+  UINTN           Index2;\r
+\r
+  Status  = EFI_SUCCESS;\r
+  Index2  = 0;\r
+  for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2));\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (!NewLoadContext->Deleted) {\r
+      continue;\r
+    }\r
+\r
+    UnicodeSPrint (\r
+      DriverString,\r
+      sizeof (DriverString),\r
+      L"Driver%04x",\r
+      NewMenuEntry->OptionNumber\r
+      );\r
+\r
+    EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid);\r
+    Index2++;\r
+\r
+    RemoveEntryList (&NewMenuEntry->Link);\r
+    BOpt_DestroyMenuEntry (NewMenuEntry);\r
+    NewMenuEntry = NULL;\r
+  }\r
+\r
+  DriverOptionMenu.MenuNumber -= Index2;\r
+\r
+  Status = Var_ChangeDriverOrder ();\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+Var_ChangeDriverOrder (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  After any operation on Driver####, there will be a discrepancy in\r
+  DriverOrder. Since some are missing but in DriverOrder, while some\r
+  are present but are not reflected by DriverOrder. Then a function\r
+  rebuild DriverOrder from scratch by content from DriverOptionMenu is\r
+  needed.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  EFI_SUCCESS\r
+  Others\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        *DriverOrderList;\r
+  UINT16        *DriverOrderListPtr;\r
+  UINTN         DriverOrderListSize;\r
+  UINTN         Index;\r
+\r
+  DriverOrderList     = NULL;\r
+  DriverOrderListSize = 0;\r
+\r
+  //\r
+  // First check whether DriverOrder is present in current configuration\r
+  //\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+\r
+  //\r
+  // If exists, delete it to hold new DriverOrder\r
+  //\r
+  if (DriverOrderList) {\r
+    EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+    SafeFreePool (DriverOrderList);\r
+    DriverOrderList = NULL;\r
+  }\r
+\r
+  DriverOrderListSize = DriverOptionMenu.MenuNumber;\r
+\r
+  if (DriverOrderListSize > 0) {\r
+    DriverOrderList = EfiAllocateZeroPool (DriverOrderListSize * sizeof (UINT16));\r
+    ASSERT (DriverOrderList != NULL);\r
+    DriverOrderListPtr = DriverOrderList;\r
+\r
+    //\r
+    // Get all current used Driver#### from DriverOptionMenu.\r
+    // OptionNumber in each BM_LOAD_OPTION is really its\r
+    // #### value.\r
+    //\r
+    for (Index = 0; Index < DriverOrderListSize; Index++) {\r
+      NewMenuEntry      = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+      *DriverOrderList  = (UINT16) NewMenuEntry->OptionNumber;\r
+      DriverOrderList++;\r
+    }\r
+\r
+    DriverOrderList = DriverOrderListPtr;\r
+\r
+    //\r
+    // After building the DriverOrderList, write it back\r
+    //\r
+    Status = gRT->SetVariable (\r
+                    L"DriverOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    DriverOrderListSize * sizeof (UINT16),\r
+                    DriverOrderList\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+Var_UpdateAllConsoleOption (\r
+  VOID\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *OutDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *InpDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ErrDevicePath;\r
+  EFI_STATUS                Status;\r
+\r
+  OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);\r
+  InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);\r
+  ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);\r
+  if (OutDevicePath) {\r
+    ChangeVariableDevicePath (OutDevicePath);\r
+    Status = gRT->SetVariable (\r
+                    L"ConOut",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    GetDevicePathSize (OutDevicePath),\r
+                    OutDevicePath\r
+                    );\r
+    ASSERT (!EFI_ERROR (Status));\r
+  }\r
+\r
+  if (InpDevicePath) {\r
+    ChangeVariableDevicePath (InpDevicePath);\r
+    Status = gRT->SetVariable (\r
+                    L"ConIn",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    GetDevicePathSize (InpDevicePath),\r
+                    InpDevicePath\r
+                    );\r
+    ASSERT (!EFI_ERROR (Status));\r
+  }\r
+\r
+  if (ErrDevicePath) {\r
+    ChangeVariableDevicePath (ErrDevicePath);\r
+    Status = gRT->SetVariable (\r
+                    L"ErrOut",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    GetDevicePathSize (ErrDevicePath),\r
+                    ErrDevicePath\r
+                    );\r
+    ASSERT (!EFI_ERROR (Status));\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleOption (\r
+  IN UINT16                     *ConsoleName,\r
+  IN BM_MENU_OPTION             *ConsoleMenu,\r
+  IN UINT16                     UpdatePageId\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *ConDevicePath;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_CONSOLE_CONTEXT        *NewConsoleContext;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  EFI_STATUS                Status;\r
+  VENDOR_DEVICE_PATH        Vendor;\r
+  EFI_DEVICE_PATH_PROTOCOL  *TerminalDevicePath;\r
+  UINTN                     Index;\r
+\r
+  ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid);\r
+  if (ConDevicePath != NULL) {\r
+    EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid);\r
+    SafeFreePool (ConDevicePath);\r
+    ConDevicePath = NULL;\r
+  };\r
+\r
+  //\r
+  // First add all console input device to it from console input menu\r
+  //\r
+  for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (NewConsoleContext->IsActive) {\r
+      ConDevicePath = AppendDevicePathInstance (\r
+                        ConDevicePath,\r
+                        NewConsoleContext->DevicePath\r
+                        );\r
+    }\r
+  }\r
+\r
+  for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if ((NewTerminalContext->IsConIn && (UpdatePageId == FORM_CON_IN_ID)) ||\r
+        (NewTerminalContext->IsConOut && (UpdatePageId == FORM_CON_OUT_ID)) ||\r
+        (NewTerminalContext->IsStdErr && (UpdatePageId == FORM_CON_ERR_ID))\r
+        ) {\r
+      Vendor.Header.Type    = MESSAGING_DEVICE_PATH;\r
+      Vendor.Header.SubType = MSG_VENDOR_DP;\r
+      CopyMem (\r
+        &Vendor.Guid,\r
+        &Guid[NewTerminalContext->TerminalType],\r
+        sizeof (EFI_GUID)\r
+        );\r
+      SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));\r
+      TerminalDevicePath = AppendDevicePathNode (\r
+                            NewTerminalContext->DevicePath,\r
+                            (EFI_DEVICE_PATH_PROTOCOL *) &Vendor\r
+                            );\r
+      ASSERT (TerminalDevicePath != NULL);\r
+      ChangeTerminalDevicePath (TerminalDevicePath, TRUE);\r
+      ConDevicePath = AppendDevicePathInstance (\r
+                        ConDevicePath,\r
+                        TerminalDevicePath\r
+                        );\r
+    }\r
+  }\r
+\r
+  if (ConDevicePath) {\r
+    Status = gRT->SetVariable (\r
+                    ConsoleName,\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    GetDevicePathSize (ConDevicePath),\r
+                    ConDevicePath\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleInpOption (\r
+  VOID\r
+  )\r
+{\r
+  return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleOutOption (\r
+  VOID\r
+  )\r
+{\r
+  return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateErrorOutOption (\r
+  VOID\r
+  )\r
+{\r
+  return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateDriverOption (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData,\r
+  IN  EFI_HII_HANDLE            HiiHandle,\r
+  IN  UINT16                    *DescriptionData,\r
+  IN  UINT16                    *OptionalData,\r
+  IN  UINT8                     ForceReconnect\r
+  )\r
+{\r
+  UINT16          Index;\r
+  UINT16          *DriverOrderList;\r
+  UINT16          *NewDriverOrderList;\r
+  UINT16          DriverString[12];\r
+  UINTN           DriverOrderListSize;\r
+  VOID            *Buffer;\r
+  UINTN           BufferSize;\r
+  UINT8           *Ptr;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  BOOLEAN         OptionalDataExist;\r
+  EFI_STATUS      Status;\r
+\r
+  OptionalDataExist = FALSE;\r
+\r
+  Index             = BOpt_GetDriverOptionNumber ();\r
+  UnicodeSPrint (\r
+    DriverString,\r
+    sizeof (DriverString),\r
+    L"Driver%04x",\r
+    Index\r
+    );\r
+\r
+  if (*DescriptionData == 0x0000) {\r
+    StrCpy (DescriptionData, DriverString);\r
+  }\r
+\r
+  BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData);\r
+  BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+  if (*OptionalData != 0x0000) {\r
+    OptionalDataExist = TRUE;\r
+    BufferSize += StrSize (OptionalData);\r
+  }\r
+\r
+  Buffer = EfiAllocateZeroPool (BufferSize);\r
+  if (NULL == Buffer) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+  if (NULL == NewMenuEntry) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewLoadContext                  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+  NewLoadContext->Deleted         = FALSE;\r
+  NewLoadContext->LoadOptionSize  = BufferSize;\r
+  Ptr = (UINT8 *) Buffer;\r
+  NewLoadContext->LoadOption = Ptr;\r
+  *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);\r
+  NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
+  NewLoadContext->IsActive = TRUE;\r
+  NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+  Ptr += sizeof (UINT32);\r
+  *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+  NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
+\r
+  Ptr += sizeof (UINT16);\r
+  CopyMem (\r
+    Ptr,\r
+    DescriptionData,\r
+    StrSize (DescriptionData)\r
+    );\r
+\r
+  NewLoadContext->Description = EfiAllocateZeroPool (StrSize (DescriptionData));\r
+  ASSERT (NewLoadContext->Description != NULL);\r
+  NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+  CopyMem (\r
+    NewLoadContext->Description,\r
+    (VOID *) Ptr,\r
+    StrSize (DescriptionData)\r
+    );\r
+\r
+  Ptr += StrSize (DescriptionData);\r
+  CopyMem (\r
+    Ptr,\r
+    CallbackData->LoadContext->FilePathList,\r
+    GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+    );\r
+\r
+  NewLoadContext->FilePathList = EfiAllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
+  ASSERT (NewLoadContext->FilePathList != NULL);\r
+\r
+  CopyMem (\r
+    NewLoadContext->FilePathList,\r
+    (VOID *) Ptr,\r
+    GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+    );\r
+\r
+  NewMenuEntry->HelpString    = DevicePathToStr (NewLoadContext->FilePathList);\r
+  NewMenuEntry->OptionNumber  = Index;\r
+  NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                      CallbackData,\r
+                                      DriverOptionStrDepository\r
+                                      );\r
+  IfrLibNewString (HiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);\r
+\r
+  NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+                                    CallbackData,\r
+                                    DriverOptionHelpStrDepository\r
+                                    );\r
+  IfrLibNewString (HiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);\r
+\r
+  if (OptionalDataExist) {\r
+    Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+    CopyMem (\r
+      Ptr,\r
+      OptionalData,\r
+      StrSize (OptionalData)\r
+      );\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  DriverString,\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BufferSize,\r
+                  Buffer\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+  NewDriverOrderList = EfiAllocateZeroPool (DriverOrderListSize + sizeof (UINT16));\r
+  ASSERT (NewDriverOrderList != NULL);\r
+  CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);\r
+  NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;\r
+  if (DriverOrderList != NULL) {\r
+    EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  L"DriverOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  DriverOrderListSize + sizeof (UINT16),\r
+                  NewDriverOrderList\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+  SafeFreePool (DriverOrderList);\r
+  DriverOrderList = NULL;\r
+  SafeFreePool (NewDriverOrderList);\r
+  NewDriverOrderList = NULL;\r
+  InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
+  DriverOptionMenu.MenuNumber++;\r
+\r
+  *DescriptionData  = 0x0000;\r
+  *OptionalData     = 0x0000;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateBootOption (\r
+  IN  BMM_CALLBACK_DATA                   *CallbackData,\r
+  IN  FILE_EXPLORER_NV_DATA               *NvRamMap\r
+  )\r
+{\r
+  UINT16          *BootOrderList;\r
+  UINT16          *NewBootOrderList;\r
+  UINTN           BootOrderListSize;\r
+  UINT16          BootString[10];\r
+  VOID            *Buffer;\r
+  UINTN           BufferSize;\r
+  UINT8           *Ptr;\r
+  UINT16          Index;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  BOOLEAN         OptionalDataExist;\r
+  EFI_STATUS      Status;\r
+\r
+  OptionalDataExist = FALSE;\r
+\r
+  Index = BOpt_GetBootOptionNumber () ;\r
+  UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);\r
+\r
+  if (NvRamMap->DescriptionData[0] == 0x0000) {\r
+    StrCpy (NvRamMap->DescriptionData, BootString);\r
+  }\r
+\r
+  BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData);\r
+  BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+  if (NvRamMap->OptionalData[0] != 0x0000) {\r
+    OptionalDataExist = TRUE;\r
+    BufferSize += StrSize (NvRamMap->OptionalData);\r
+  }\r
+\r
+  Buffer = EfiAllocateZeroPool (BufferSize);\r
+  if (NULL == Buffer) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+  if (NULL == NewMenuEntry) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewLoadContext                  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+  NewLoadContext->Deleted         = FALSE;\r
+  NewLoadContext->LoadOptionSize  = BufferSize;\r
+  Ptr = (UINT8 *) Buffer;\r
+  NewLoadContext->LoadOption = Ptr;\r
+  *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
+  NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
+  NewLoadContext->IsActive = TRUE;\r
+  NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+  Ptr += sizeof (UINT32);\r
+  *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+  NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
+  Ptr += sizeof (UINT16);\r
+\r
+  CopyMem (\r
+    Ptr,\r
+    NvRamMap->DescriptionData,\r
+    StrSize (NvRamMap->DescriptionData)\r
+    );\r
+\r
+  NewLoadContext->Description = EfiAllocateZeroPool (StrSize (NvRamMap->DescriptionData));\r
+  ASSERT (NewLoadContext->Description != NULL);\r
+\r
+  NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+  CopyMem (\r
+    NewLoadContext->Description,\r
+    (VOID *) Ptr,\r
+    StrSize (NvRamMap->DescriptionData)\r
+    );\r
+\r
+  Ptr += StrSize (NvRamMap->DescriptionData);\r
+  CopyMem (\r
+    Ptr,\r
+    CallbackData->LoadContext->FilePathList,\r
+    GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+    );\r
+\r
+  NewLoadContext->FilePathList = EfiAllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
+  ASSERT (NewLoadContext->FilePathList != NULL);\r
+\r
+  CopyMem (\r
+    NewLoadContext->FilePathList,\r
+    (VOID *) Ptr,\r
+    GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+    );\r
+\r
+  NewMenuEntry->HelpString    = DevicePathToStr (NewLoadContext->FilePathList);\r
+  NewMenuEntry->OptionNumber  = Index;\r
+  NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                      CallbackData,\r
+                                      BootOptionStrDepository\r
+                                      );\r
+  IfrLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);\r
+\r
+  NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+                                    CallbackData,\r
+                                    BootOptionHelpStrDepository\r
+                                    );\r
+  IfrLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);\r
+\r
+  if (OptionalDataExist) {\r
+    Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+    CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData));\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  BootString,\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BufferSize,\r
+                  Buffer\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+\r
+  NewBootOrderList = EfiAllocateZeroPool (BootOrderListSize + sizeof (UINT16));\r
+  ASSERT (NewBootOrderList != NULL);\r
+  CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);\r
+  NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;\r
+\r
+  if (BootOrderList != NULL) {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  L"BootOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BootOrderListSize + sizeof (UINT16),\r
+                  NewBootOrderList\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  SafeFreePool (BootOrderList);\r
+  BootOrderList = NULL;\r
+  SafeFreePool (NewBootOrderList);\r
+  NewBootOrderList = NULL;\r
+  InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
+  BootOptionMenu.MenuNumber++;\r
+\r
+  NvRamMap->DescriptionData[0]  = 0x0000;\r
+  NvRamMap->OptionalData[0]     = 0x0000;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateBootNext (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY     *NewMenuEntry;\r
+  BM_LOAD_CONTEXT   *NewLoadContext;\r
+  BMM_FAKE_NV_DATA  *CurrentFakeNVMap;\r
+  UINT16            Index;\r
+  EFI_STATUS        Status;\r
+\r
+  Status            = EFI_SUCCESS;\r
+  CurrentFakeNVMap  = &CallbackData->BmmFakeNvData;\r
+  for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewLoadContext              = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewLoadContext->IsBootNext  = FALSE;\r
+  }\r
+\r
+  if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {\r
+    EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  NewMenuEntry = BOpt_GetMenuEntry (\r
+                  &BootOptionMenu,\r
+                  CurrentFakeNVMap->BootNext\r
+                  );\r
+  if (NULL == NewMenuEntry) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+  Status = gRT->SetVariable (\r
+                  L"BootNext",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  sizeof (UINT16),\r
+                  &NewMenuEntry->OptionNumber\r
+                  );\r
+  NewLoadContext->IsBootNext              = TRUE;\r
+  CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateBootOrder (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT16      Index;\r
+  UINT16      *BootOrderList;\r
+  UINT16      *NewBootOrderList;\r
+  UINTN       BootOrderListSize;\r
+  UINT8       *Map;\r
+\r
+  BootOrderList     = NULL;\r
+  BootOrderListSize = 0;\r
+\r
+  //\r
+  // First check whether BootOrder is present in current configuration\r
+  //\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+\r
+  NewBootOrderList = EfiAllocateZeroPool (BootOrderListSize);\r
+  if (!NewBootOrderList) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Map = EfiAllocateZeroPool (BootOrderListSize / sizeof (UINT16));\r
+  if (!Map) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // If exists, delete it to hold new BootOrder\r
+  //\r
+  if (BootOrderList) {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+    NewBootOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  L"BootOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BootOrderListSize,\r
+                  NewBootOrderList\r
+                  );\r
+  SafeFreePool (BootOrderList);\r
+  SafeFreePool (NewBootOrderList);\r
+  SafeFreePool (Map);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  BOpt_FreeMenu (&BootOptionMenu);\r
+  BOpt_GetBootOptions (CallbackData);\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateDriverOrder (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT16      Index;\r
+  UINT16      *DriverOrderList;\r
+  UINT16      *NewDriverOrderList;\r
+  UINTN       DriverOrderListSize;\r
+\r
+  DriverOrderList     = NULL;\r
+  DriverOrderListSize = 0;\r
+\r
+  //\r
+  // First check whether DriverOrder is present in current configuration\r
+  //\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+\r
+  NewDriverOrderList = EfiAllocateZeroPool (DriverOrderListSize);\r
+\r
+  if (!NewDriverOrderList) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // If exists, delete it to hold new DriverOrder\r
+  //\r
+  if (DriverOrderList) {\r
+    EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  for (Index = 0; Index < DriverOrderListSize; Index++) {\r
+    NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  L"DriverOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  DriverOrderListSize,\r
+                  NewDriverOrderList\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  SafeFreePool (DriverOrderList);\r
+\r
+  BOpt_FreeMenu (&DriverOptionMenu);\r
+  BOpt_GetDriverOptions (CallbackData);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateBBSOption (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  )\r
+{\r
+  UINTN                       Index;\r
+  UINTN                       Index2;\r
+  VOID                        *BootOptionVar;\r
+  CHAR16                      VarName[100];\r
+  UINTN                       OptionSize;\r
+  UINT8                       *Ptr;\r
+  EFI_STATUS                  Status;\r
+  CHAR16                      DescString[100];\r
+  CHAR8                       DescAsciiString[100];\r
+  UINTN                       NewOptionSize;\r
+  UINT8                       *NewOptionPtr;\r
+  UINT8                       *TempPtr;\r
+  UINT32                      *Attribute;\r
+  BM_MENU_OPTION              *OptionMenu;\r
+  BM_LEGACY_DEVICE_CONTEXT    *LegacyDeviceContext;\r
+  UINT8                       *LegacyDev;\r
+  UINT8                       *VarData;\r
+  UINTN                       VarSize;\r
+  BM_MENU_ENTRY               *NewMenuEntry;\r
+  BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
+  UINT8                       *OriginalPtr;\r
+  UINT8                       *DisMap;\r
+  UINTN                       Pos;\r
+  UINTN                       Bit;\r
+  UINT16                      *NewOrder;\r
+  UINT16                      Tmp;\r
+\r
+  LegacyDeviceContext = NULL;\r
+  DisMap              = NULL;\r
+  NewOrder            = NULL;\r
+\r
+  if (FORM_SET_FD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+    OptionMenu            = (BM_MENU_OPTION *) &LegacyFDMenu;\r
+    LegacyDev             = CallbackData->BmmFakeNvData.LegacyFD;\r
+    CallbackData->BbsType = BBS_FLOPPY;\r
+  } else {\r
+    if (FORM_SET_HD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+      OptionMenu            = (BM_MENU_OPTION *) &LegacyHDMenu;\r
+      LegacyDev             = CallbackData->BmmFakeNvData.LegacyHD;\r
+      CallbackData->BbsType = BBS_HARDDISK;\r
+    } else {\r
+      if (FORM_SET_CD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+        OptionMenu            = (BM_MENU_OPTION *) &LegacyCDMenu;\r
+        LegacyDev             = CallbackData->BmmFakeNvData.LegacyCD;\r
+        CallbackData->BbsType = BBS_CDROM;\r
+      } else {\r
+        if (FORM_SET_NET_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+          OptionMenu            = (BM_MENU_OPTION *) &LegacyNETMenu;\r
+          LegacyDev             = CallbackData->BmmFakeNvData.LegacyNET;\r
+          CallbackData->BbsType = BBS_EMBED_NETWORK;\r
+        } else {\r
+          OptionMenu            = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
+          LegacyDev             = CallbackData->BmmFakeNvData.LegacyBEV;\r
+          CallbackData->BbsType = BBS_BEV_DEVICE;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  DisMap  = CallbackData->BmmOldFakeNVData.DisableMap;\r
+  Status  = EFI_SUCCESS;\r
+\r
+  //\r
+  // Find the first device's context\r
+  // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext\r
+  // because we just use it to fill the desc string, and user can not see the string in UI\r
+  //\r
+  for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+    NewMenuEntry        = BOpt_GetMenuEntry (OptionMenu, Index);\r
+    LegacyDeviceContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (0xFF != LegacyDev[0] && LegacyDev[0] == LegacyDeviceContext->Index) {\r
+      DEBUG ((DEBUG_ERROR, "DescStr: %s\n", LegacyDeviceContext->Description));\r
+      break;\r
+    }\r
+  }\r
+  //\r
+  // Update the Variable "LegacyDevOrder"\r
+  //\r
+  VarData = (UINT8 *) BdsLibGetVariableAndSize (\r
+                        VarLegacyDevOrder,\r
+                        &EfiLegacyDevOrderGuid,\r
+                        &VarSize\r
+                        );\r
+\r
+  if (NULL == VarData) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  OriginalPtr = VarData;\r
+  DevOrder    = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+\r
+  while (VarData < VarData + VarSize) {\r
+    if (DevOrder->BbsType == CallbackData->BbsType) {\r
+      break;\r
+    }\r
+\r
+    VarData += sizeof (BBS_TYPE);\r
+    VarData += *(UINT16 *) VarData;\r
+    DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+  }\r
+\r
+  if (VarData >= VarData + VarSize) {\r
+    SafeFreePool (OriginalPtr);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  NewOrder = (UINT16 *) EfiAllocateZeroPool (DevOrder->Length - sizeof (UINT16));\r
+  if (NULL == NewOrder) {\r
+    SafeFreePool (VarData);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+    if (0xFF == LegacyDev[Index]) {\r
+      break;\r
+    }\r
+\r
+    NewOrder[Index] = LegacyDev[Index];\r
+  }\r
+  //\r
+  // Only the enable/disable state of each boot device with same device type can be changed,\r
+  // so we can count on the index information in DevOrder.\r
+  // DisMap bit array is the only reliable source to check a device's en/dis state,\r
+  // so we use DisMap to set en/dis state of each item in NewOrder array\r
+  //\r
+  for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {\r
+    Tmp = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index2 * sizeof (UINT16));\r
+    Tmp &= 0xFF;\r
+    Pos = Tmp / 8;\r
+    Bit = 7 - (Tmp % 8);\r
+    if (DisMap[Pos] & (1 << Bit)) {\r
+      NewOrder[Index] = (UINT16) (0xFF00 | Tmp);\r
+      Index++;\r
+    }\r
+  }\r
+\r
+  CopyMem (\r
+    (UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16),\r
+    NewOrder,\r
+    DevOrder->Length - sizeof (UINT16)\r
+    );\r
+  SafeFreePool (NewOrder);\r
+\r
+  Status = gRT->SetVariable (\r
+                  VarLegacyDevOrder,\r
+                  &EfiLegacyDevOrderGuid,\r
+                  VAR_FLAG,\r
+                  VarSize,\r
+                  OriginalPtr\r
+                  );\r
+\r
+  SafeFreePool (OriginalPtr);\r
+\r
+  //\r
+  // Update Optional Data of Boot####\r
+  //\r
+  BootOptionVar = GetLegacyBootOptionVar (CallbackData->BbsType, &Index, &OptionSize);\r
+\r
+  if (NULL != BootOptionVar) {\r
+    CopyMem (\r
+      DescString,\r
+      LegacyDeviceContext->Description,\r
+      StrSize (LegacyDeviceContext->Description)\r
+      );\r
+\r
+    UnicodeToAscii (DescString, StrSize (DescString), DescAsciiString);\r
+\r
+    NewOptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescString) +\r
+                    sizeof (BBS_BBS_DEVICE_PATH);\r
+    NewOptionSize += AsciiStrLen (DescAsciiString) +\r
+                    EFI_END_DEVICE_PATH_LENGTH + sizeof (BBS_TABLE) + sizeof (UINT16);\r
+\r
+    UnicodeSPrint (VarName, 100, L"Boot%04x", Index);\r
+\r
+    Ptr       = BootOptionVar;\r
+\r
+    Attribute = (UINT32 *) Ptr;\r
+    *Attribute |= LOAD_OPTION_ACTIVE;\r
+    if (0xFF == LegacyDev[0]) {\r
+      //\r
+      // Disable this legacy boot option\r
+      //\r
+      *Attribute &= ~LOAD_OPTION_ACTIVE;\r
+    }\r
+\r
+    Ptr += sizeof (UINT32);\r
+\r
+    Ptr += sizeof (UINT16);\r
+    Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+    NewOptionPtr = EfiAllocateZeroPool (NewOptionSize);\r
+    if (NULL == NewOptionPtr) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    TempPtr = NewOptionPtr;\r
+\r
+    //\r
+    // Attribute\r
+    //\r
+    CopyMem (\r
+      TempPtr,\r
+      BootOptionVar,\r
+      sizeof (UINT32)\r
+      );\r
+\r
+    TempPtr += sizeof (UINT32);\r
+\r
+    //\r
+    // BBS device path Length\r
+    //\r
+    *((UINT16 *) TempPtr) = (UINT16) (sizeof (BBS_BBS_DEVICE_PATH) +\r
+                         AsciiStrLen (DescAsciiString) +\r
+                         EFI_END_DEVICE_PATH_LENGTH);\r
+\r
+    TempPtr += sizeof (UINT16);\r
+\r
+    //\r
+    // Description string\r
+    //\r
+    CopyMem (\r
+      TempPtr,\r
+      DescString,\r
+      StrSize (DescString)\r
+      );\r
+\r
+    TempPtr += StrSize (DescString);\r
+\r
+    //\r
+    // BBS device path\r
+    //\r
+    CopyMem (\r
+      TempPtr,\r
+      Ptr,\r
+      sizeof (BBS_BBS_DEVICE_PATH)\r
+      );\r
+\r
+    CopyMem (\r
+      ((BBS_BBS_DEVICE_PATH*) TempPtr)->String,\r
+      DescAsciiString,\r
+      AsciiStrSize (DescAsciiString)\r
+      );\r
+\r
+    SetDevicePathNodeLength (\r
+          (EFI_DEVICE_PATH_PROTOCOL *) TempPtr,\r
+          sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString)\r
+          );\r
+\r
+    TempPtr += sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString);\r
+\r
+    //\r
+    // End node\r
+    //\r
+    CopyMem (\r
+      TempPtr,\r
+      EndDevicePath,\r
+      EFI_END_DEVICE_PATH_LENGTH\r
+      );\r
+    TempPtr += EFI_END_DEVICE_PATH_LENGTH;\r
+\r
+    //\r
+    // Now TempPtr point to optional data, i.e. Bbs Table\r
+    //\r
+    CopyMem (\r
+      TempPtr,\r
+      LegacyDeviceContext->BbsTable,\r
+      sizeof (BBS_TABLE)\r
+      );\r
+\r
+    //\r
+    // Now TempPtr point to BBS index\r
+    //\r
+    TempPtr += sizeof (BBS_TABLE);\r
+    *((UINT16 *) TempPtr) = (UINT16) LegacyDeviceContext->Index;\r
+\r
+    Status = gRT->SetVariable (\r
+                    VarName,\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    NewOptionSize,\r
+                    NewOptionPtr\r
+                    );\r
+\r
+    SafeFreePool (NewOptionPtr);\r
+    SafeFreePool (BootOptionVar);\r
+  }\r
+\r
+  BOpt_GetBootOptions (CallbackData);\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateConMode (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  UINTN             Mode;\r
+  CONSOLE_OUT_MODE  ModeInfo;\r
+\r
+  Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;\r
+\r
+  Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));\r
+  if (EFI_ERROR(Status)) {\r
+    ModeInfo.Column = 80;\r
+    ModeInfo.Row = 25;\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  VarConOutMode,\r
+                  &gEfiGenericPlatformVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  sizeof (CONSOLE_OUT_MODE),\r
+                  &ModeInfo\r
+                  );\r
+\r
+  return Status;\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.c b/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.c
new file mode 100644 (file)
index 0000000..fdf39ca
--- /dev/null
@@ -0,0 +1,335 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  BootManager.c\r
+\r
+Abstract:\r
+\r
+  The platform boot manager reference implement\r
+\r
+--*/\r
+\r
+#include "BootManager.h"\r
+\r
+UINT16             mKeyInput;\r
+EFI_GUID           mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID;\r
+LIST_ENTRY         *mBootOptionsList;\r
+BDS_COMMON_OPTION  *gOption;\r
+\r
+BOOT_MANAGER_CALLBACK_DATA  gBootManagerPrivate = {\r
+  BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,\r
+  NULL,\r
+  NULL,\r
+  {\r
+    FakeExtractConfig,\r
+    FakeRouteConfig,\r
+    BootManagerCallback\r
+  }\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    This function processes the results of changes in configuration.\r
+\r
+  Arguments:\r
+    This          - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+    Action        - Specifies the type of action taken by the browser.\r
+    QuestionId    - A unique value which is sent to the original exporting driver\r
+                    so that it can identify the type of data to expect.\r
+    Type          - The type of value for the question.\r
+    Value         - A pointer to the data being sent to the original exporting driver.\r
+    ActionRequest - On return, points to the action requested by the callback function.\r
+\r
+  Returns:\r
+    EFI_SUCCESS          - The callback successfully handled the action.\r
+    EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.\r
+    EFI_DEVICE_ERROR     - The variable could not be saved.\r
+    EFI_UNSUPPORTED      - The specified Action is not supported by the callback.\r
+\r
+--*/\r
+{\r
+  BDS_COMMON_OPTION       *Option;\r
+  LIST_ENTRY              *Link;\r
+  UINT16                  KeyCount;\r
+\r
+  if ((Value == NULL) || (ActionRequest == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Initialize the key count\r
+  //\r
+  KeyCount = 0;\r
+\r
+  for (Link = mBootOptionsList->ForwardLink; Link != mBootOptionsList; Link = Link->ForwardLink) {\r
+    Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+    KeyCount++;\r
+\r
+    gOption = Option;\r
+\r
+    //\r
+    // Is this device the one chosen?\r
+    //\r
+    if (KeyCount == QuestionId) {\r
+      //\r
+      // Assigning the returned Key to a global allows the original routine to know what was chosen\r
+      //\r
+      mKeyInput = QuestionId;\r
+\r
+      //\r
+      // Request to exit SendForm(), so that we could boot the selected option\r
+      //\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+      break;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeBootManager (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initialize HII information for the FrontPage\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+  //\r
+  // Create driver handle used by HII database\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&gBootManagerPrivate.DriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Install Config Access protocol to driver handle\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &gBootManagerPrivate.DriverHandle,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &gBootManagerPrivate.ConfigAccess\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Publish our HII data\r
+  //\r
+  PackageList = PreparePackageList (2, &mBootManagerGuid, BootManagerVfrBin, BdsStrings);\r
+  ASSERT (PackageList != NULL);\r
+\r
+  Status = gHiiDatabase->NewPackageList (\r
+                           gHiiDatabase,\r
+                           PackageList,\r
+                           gBootManagerPrivate.DriverHandle,\r
+                           &gBootManagerPrivate.HiiHandle\r
+                           );\r
+  FreePool (PackageList);\r
+\r
+  return Status;\r
+}\r
+\r
+VOID\r
+CallBootManager (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Hook to enable UI timeout override behavior.\r
+\r
+Arguments:\r
+  BdsDeviceList - Device List that BDS needs to connect.\r
+\r
+  Entry - Pointer to current Boot Entry.\r
+\r
+Returns:\r
+  NONE\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                  Status;\r
+  BDS_COMMON_OPTION           *Option;\r
+  LIST_ENTRY                  *Link;\r
+  EFI_HII_UPDATE_DATA         UpdateData;\r
+  CHAR16                      *ExitData;\r
+  UINTN                       ExitDataSize;\r
+  EFI_STRING_ID               Token;\r
+  EFI_INPUT_KEY               Key;\r
+  LIST_ENTRY                  BdsBootOptionList;\r
+  CHAR16                      *HelpString;\r
+  EFI_STRING_ID               HelpToken;\r
+  UINT16                      *TempStr;\r
+  EFI_HII_HANDLE              HiiHandle;\r
+  EFI_BROWSER_ACTION_REQUEST  ActionRequest;\r
+  UINTN                       TempSize;\r
+\r
+  gOption = NULL;\r
+  InitializeListHead (&BdsBootOptionList);\r
+\r
+  //\r
+  // Connect all prior to entering the platform setup menu.\r
+  //\r
+  if (!gConnectAllHappened) {\r
+    BdsLibConnectAllDriversToAllControllers ();\r
+    gConnectAllHappened = TRUE;\r
+  }\r
+  //\r
+  // BugBug: Here we can not remove the legacy refresh macro, so we need\r
+  // get the boot order every time from "BootOrder" variable.\r
+  // Recreate the boot option list base on the BootOrder variable\r
+  //\r
+  BdsLibEnumerateAllBootOption (&BdsBootOptionList);\r
+\r
+  mBootOptionsList  = &BdsBootOptionList;\r
+\r
+  HiiHandle = gBootManagerPrivate.HiiHandle;\r
+\r
+  //\r
+  // Allocate space for creation of UpdateData Buffer\r
+  //\r
+  UpdateData.BufferSize = 0x1000;\r
+  UpdateData.Offset = 0;\r
+  UpdateData.Data = AllocateZeroPool (0x1000);\r
+  ASSERT (UpdateData.Data != NULL);\r
+\r
+  mKeyInput = 0;\r
+\r
+  for (Link = BdsBootOptionList.ForwardLink; Link != &BdsBootOptionList; Link = Link->ForwardLink) {\r
+    Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+    //\r
+    // At this stage we are creating a menu entry, thus the Keys are reproduceable\r
+    //\r
+    mKeyInput++;\r
+\r
+    //\r
+    // Don't display the boot option marked as LOAD_OPTION_HIDDEN\r
+    //\r
+    if (Option->Attribute & LOAD_OPTION_HIDDEN) {\r
+      continue;\r
+    }\r
+\r
+    IfrLibNewString (HiiHandle, &Token, Option->Description);\r
+\r
+    TempStr = DevicePathToStr (Option->DevicePath);\r
+    TempSize = StrSize (TempStr);\r
+    HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));\r
+    StrCat (HelpString, L"Device Path : ");\r
+    StrCat (HelpString, TempStr);\r
+\r
+    IfrLibNewString (HiiHandle, &HelpToken, HelpString);\r
+\r
+    CreateActionOpCode (\r
+      mKeyInput,\r
+      Token,\r
+      HelpToken,\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      0,\r
+      &UpdateData\r
+      );\r
+  }\r
+\r
+  IfrLibUpdateForm (\r
+    HiiHandle,\r
+    &mBootManagerGuid,\r
+    BOOT_MANAGER_FORM_ID,\r
+    LABEL_BOOT_OPTION,\r
+    FALSE,\r
+    &UpdateData\r
+    );\r
+  FreePool (UpdateData.Data);\r
+\r
+  //\r
+  // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION\r
+  //\r
+  gBS->RestoreTPL (TPL_APPLICATION);\r
+\r
+  ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+  Status = gFormBrowser2->SendForm (\r
+                           gFormBrowser2,\r
+                           &HiiHandle,\r
+                           1,\r
+                           NULL,\r
+                           0,\r
+                           NULL,\r
+                           &ActionRequest\r
+                           );\r
+  if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+    EnableResetRequired ();\r
+  }\r
+\r
+  if (gOption == NULL) {\r
+    gBS->RaiseTPL (TPL_APPLICATION);\r
+    return ;\r
+  }\r
+\r
+  //\r
+  //Will leave browser, check any reset required change is applied? if yes, reset system\r
+  //\r
+  SetupResetReminder ();\r
+\r
+  //\r
+  // Raise the TPL level back to TPL_APPLICATION\r
+  //\r
+  gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+  //\r
+  // parse the selected option\r
+  //\r
+  Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
+    PlatformBdsBootSuccess (gOption);\r
+  } else {\r
+    gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
+    PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);\r
+    gST->ConOut->OutputString (\r
+                  gST->ConOut,\r
+                  GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))\r
+                  );\r
+    gBS->RestoreTPL (TPL_APPLICATION);\r
+    //\r
+    // BdsLibUiWaitForSingleEvent (gST->ConIn->WaitForKey, 0);\r
+    //\r
+    gBS->RaiseTPL (TPL_APPLICATION);\r
+    gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+  }\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.h b/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.h
new file mode 100644 (file)
index 0000000..fab04d2
--- /dev/null
@@ -0,0 +1,88 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  BootManager.h\r
+\r
+Abstract:\r
+\r
+  The platform boot manager reference implement\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_BOOT_MANAGER_H\r
+#define _EFI_BOOT_MANAGER_H\r
+\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+//\r
+// These are defined as the same with vfr file\r
+//\r
+#define BOOT_MANAGER_FORMSET_GUID \\r
+  { \\r
+  0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b} \\r
+  }\r
+\r
+#define BOOT_MANAGER_FORM_ID     0x1000\r
+\r
+#define LABEL_BOOT_OPTION        0x00\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8 BootManagerVfrBin[];\r
+\r
+#define BOOT_MANAGER_CALLBACK_DATA_SIGNATURE  EFI_SIGNATURE_32 ('B', 'M', 'C', 'B')\r
+\r
+typedef struct {\r
+  UINTN                           Signature;\r
+\r
+  //\r
+  // HII relative handles\r
+  //\r
+  EFI_HII_HANDLE                  HiiHandle;\r
+  EFI_HANDLE                      DriverHandle;\r
+\r
+  //\r
+  // Produced protocols\r
+  //\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL   ConfigAccess;\r
+} BOOT_MANAGER_CALLBACK_DATA;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+InitializeBootManager (\r
+  VOID\r
+  )\r
+;\r
+\r
+VOID\r
+CallBootManager (\r
+  VOID\r
+  )\r
+;\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni b/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni
new file mode 100644 (file)
index 0000000..99b0cdf
Binary files /dev/null and b/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni differ
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr b/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr
new file mode 100644 (file)
index 0000000..e31d229
--- /dev/null
@@ -0,0 +1,59 @@
+// *++\r
+//\r
+// Copyright (c) 2004 - 2007, Intel Corporation\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution.  The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// Module Name:\r
+//\r
+//   BootManager.vfr\r
+//\r
+// Abstract:\r
+//\r
+//   Browser formset.\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+\r
+#define FORMSET_GUID  { 0x847bc3fe, 0xb974, 0x446d, 0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b }\r
+\r
+#define BOOT_MANAGER_FORM_ID     0x1000\r
+\r
+#define LABEL_BOOT_OPTION        0x00\r
+#define LABEL_BOOT_OPTION_END    0x01\r
+\r
+#define BOOT_MANAGER_CLASS       0x00\r
+#define BOOT_MANAGER_SUBCLASS    0x00\r
+\r
+formset\r
+  guid     = FORMSET_GUID,\r
+  title    = STRING_TOKEN(STR_BM_BANNER),\r
+  help     = STRING_TOKEN(STR_LAST_STRING),\r
+  class    = BOOT_MANAGER_CLASS,\r
+  subclass = BOOT_MANAGER_SUBCLASS,\r
+\r
+  form formid = BOOT_MANAGER_FORM_ID,\r
+       title  = STRING_TOKEN(STR_BM_BANNER);\r
+\r
+    subtitle text = STRING_TOKEN(STR_LAST_STRING);\r
+    subtitle text = STRING_TOKEN(STR_BOOT_OPTION_BANNER);\r
+    subtitle text = STRING_TOKEN(STR_LAST_STRING);\r
+\r
+    //\r
+    // This is where we will dynamically add choices for the Boot Manager\r
+    //\r
+    label LABEL_BOOT_OPTION;\r
+    label LABEL_BOOT_OPTION_END;\r
+\r
+    subtitle text = STRING_TOKEN(STR_LAST_STRING);\r
+    subtitle text = STRING_TOKEN(STR_HELP_FOOTER);\r
+\r
+  endform;\r
+\r
+endformset;\r
diff --git a/MdeModulePkg/Universal/BdsDxe/Capsules.c b/MdeModulePkg/Universal/BdsDxe/Capsules.c
new file mode 100644 (file)
index 0000000..9969f48
--- /dev/null
@@ -0,0 +1,264 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  Capsules.c\r
+\r
+Abstract:\r
+\r
+  BDS routines to handle capsules.\r
+\r
+--*/\r
+#include "Bds.h"\r
+\r
+VOID\r
+BdsLockFv (\r
+  IN EFI_CPU_IO_PROTOCOL          *CpuIo,\r
+  IN EFI_PHYSICAL_ADDRESS         Base\r
+  )\r
+{\r
+  EFI_FV_BLOCK_MAP_ENTRY      *BlockMap;\r
+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;\r
+  EFI_PHYSICAL_ADDRESS        BaseAddress;\r
+  UINT8                       Data;\r
+  UINT32                      BlockLength;\r
+  UINTN                       Index;\r
+\r
+  BaseAddress = Base - 0x400000 + 2;\r
+  FvHeader    = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (Base));\r
+  BlockMap    = &(FvHeader->BlockMap[0]);\r
+\r
+  while ((BlockMap->NumBlocks != 0) && (BlockMap->Length != 0)) {\r
+    BlockLength = BlockMap->Length;\r
+    for (Index = 0; Index < BlockMap->NumBlocks; Index++) {\r
+      CpuIo->Mem.Read (\r
+                  CpuIo,\r
+                  EfiCpuIoWidthUint8,\r
+                  BaseAddress,\r
+                  1,\r
+                  &Data\r
+                  );\r
+      Data = (UINT8) (Data | 0x3);\r
+      CpuIo->Mem.Write (\r
+                  CpuIo,\r
+                  EfiCpuIoWidthUint8,\r
+                  BaseAddress,\r
+                  1,\r
+                  &Data\r
+                  );\r
+      BaseAddress += BlockLength;\r
+    }\r
+\r
+    BlockMap++;\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+ProcessCapsules (\r
+  EFI_BOOT_MODE BootMode\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine is called to see if there are any capsules we need to process.\r
+  If the boot mode is not UPDATE, then we do nothing. Otherwise find the\r
+  capsule HOBS and produce firmware volumes for them via the DXE service.\r
+  Then call the dispatcher to dispatch drivers from them. Finally, check\r
+  the status of the updates.\r
+\r
+Arguments:\r
+\r
+  BootMode - the current boot mode\r
+\r
+Returns:\r
+\r
+  EFI_INVALID_PARAMETER - boot mode is not correct for an update\r
+\r
+Note:\r
+\r
+ This function should be called by BDS in case we need to do some\r
+ sort of processing even if there is no capsule to process. We\r
+ need to do this if an earlier update went awry and we need to\r
+ clear the capsule variable so on the next reset PEI does not see it and\r
+ think there is a capsule available.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_PEI_HOB_POINTERS        HobPointer;\r
+  EFI_CAPSULE_HEADER          *CapsuleHeader;\r
+  UINT32                      Size;\r
+  UINT32                      CapsuleNumber;\r
+  UINT32                      CapsuleTotalNumber;\r
+  EFI_CAPSULE_TABLE           *CapsuleTable;\r
+  UINT32                      Index;\r
+  UINT32                      CacheIndex;\r
+  UINT32                      CacheNumber;\r
+  VOID                        **CapsulePtr;\r
+  VOID                        **CapsulePtrCache;\r
+  EFI_GUID                    *CapsuleGuidCache; \r
+  CAPSULE_HOB_INFO            *CapsuleHobInfo;\r
+\r
+  CapsuleNumber = 0;\r
+  CapsuleTotalNumber = 0;\r
+  CacheIndex   = 0;\r
+  CacheNumber  = 0;\r
+  CapsulePtr        = NULL;\r
+  CapsulePtrCache   = NULL;\r
+  CapsuleGuidCache  = NULL;\r
+\r
+  //\r
+  // We don't do anything else if the boot mode is not flash-update\r
+  //\r
+  if (BootMode != BOOT_ON_FLASH_UPDATE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  Status = EFI_SUCCESS;\r
+  //\r
+  // Find all capsule images from hob\r
+  //\r
+  HobPointer.Raw = GetHobList ();\r
+  while ((HobPointer.Raw = GetNextGuidHob (&gEfiCapsuleVendorGuid, HobPointer.Raw)) != NULL) {\r
+    CapsuleTotalNumber ++;\r
+\r
+    HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
+  }\r
+  \r
+  if (CapsuleTotalNumber == 0) {\r
+    //\r
+    // We didn't find a hob, so had no errors.\r
+    //\r
+    PlatformBdsLockNonUpdatableFlash ();\r
+    return EFI_SUCCESS;\r
+  }\r
+  \r
+  //\r
+  // Init temp Capsule Data table.\r
+  //\r
+  CapsulePtr       = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);\r
+  ASSERT (CapsulePtr != NULL);\r
+  CapsulePtrCache  = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);\r
+  ASSERT (CapsulePtrCache != NULL);\r
+  CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber);\r
+  ASSERT (CapsuleGuidCache != NULL);\r
+  \r
+  //\r
+  // Find all capsule images from hob\r
+  //\r
+  HobPointer.Raw = GetHobList ();\r
+  while ((HobPointer.Raw = GetNextGuidHob (&gEfiCapsuleVendorGuid, HobPointer.Raw)) != NULL) {\r
+    CapsuleHobInfo = GET_GUID_HOB_DATA (HobPointer.Guid);\r
+    CapsulePtr [CapsuleNumber++] = (VOID *)(UINTN)(CapsuleHobInfo->BaseAddress);\r
+\r
+    HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
+  }\r
+\r
+  //\r
+  //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install\r
+  //capsuleTable to configure table with EFI_CAPSULE_GUID\r
+  //\r
+\r
+  //\r
+  // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating\r
+  // System to have information persist across a system reset. EFI System Table must \r
+  // point to an array of capsules that contains the same CapsuleGuid value. And agents\r
+  // searching for this type capsule will look in EFI System Table and search for the \r
+  // capsule's Guid and associated pointer to retrieve the data. Two steps below describes\r
+  // how to sorting the capsules by the unique guid and install the array to EFI System Table. \r
+  // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an \r
+  // array for later sorting capsules by CapsuleGuid.\r
+  //\r
+  for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
+    CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
+    if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
+      //\r
+      // For each capsule, we compare it with known CapsuleGuid in the CacheArray.\r
+      // If already has the Guid, skip it. Whereas, record it in the CacheArray as \r
+      // an additional one.\r
+      //\r
+      CacheIndex = 0;\r
+      while (CacheIndex < CacheNumber) {\r
+        if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) {\r
+          break;\r
+        }\r
+        CacheIndex++;\r
+      }\r
+      if (CacheIndex == CacheNumber) {\r
+        CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID));\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules\r
+  // whose guid is the same as it, and malloc memory for an array which preceding\r
+  // with UINT32. The array fills with entry point of capsules that have the same\r
+  // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install\r
+  // this array into EFI System Table, so that agents searching for this type capsule\r
+  // will look in EFI System Table and search for the capsule's Guid and associated\r
+  // pointer to retrieve the data.\r
+  //\r
+  CacheIndex = 0;\r
+  while (CacheIndex < CacheNumber) {\r
+    CapsuleNumber = 0;  \r
+    for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
+      CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
+      if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
+        if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {\r
+          //\r
+          // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.\r
+          //\r
+          CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;\r
+        }\r
+      }\r
+    }\r
+    if (CapsuleNumber != 0) {\r
+      Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*);  \r
+      CapsuleTable = AllocateRuntimePool (Size);\r
+      ASSERT (CapsuleTable != NULL);\r
+      CapsuleTable->CapsuleArrayNumber =  CapsuleNumber;\r
+      CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));\r
+      Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+    CacheIndex++;\r
+  }\r
+\r
+  //\r
+  // Besides ones with CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag, all capsules left are\r
+  // recognized by platform with CapsuleGuid. For general platform driver, UpdateFlash \r
+  // type is commonly supported, so here only deal with encapsuled FVs capsule. Additional\r
+  // type capsule transaction could be extended. It depends on platform policy.\r
+  //\r
+  for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
+    CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
+    if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {\r
+      //\r
+      // Call capsule library to process capsule image.\r
+      //\r
+      ProcessCapsuleImage (CapsuleHeader);\r
+    }\r
+  }\r
+\r
+  PlatformBdsLockNonUpdatableFlash ();\r
+  \r
+  //\r
+  // Free the allocated temp memory space.\r
+  //\r
+  FreePool (CapsuleGuidCache);\r
+  FreePool (CapsulePtrCache);\r
+  FreePool (CapsulePtr);\r
+\r
+  return Status;\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c b/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c
new file mode 100644 (file)
index 0000000..0ec274d
--- /dev/null
@@ -0,0 +1,434 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  DeviceManager.c\r
+\r
+Abstract:\r
+\r
+  The platform device manager reference implement\r
+\r
+--*/\r
+\r
+#include "DeviceManager.h"\r
+\r
+DEVICE_MANAGER_CALLBACK_DATA  gDeviceManagerPrivate = {\r
+  DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE,\r
+  NULL,\r
+  NULL,\r
+  {\r
+    FakeExtractConfig,\r
+    FakeRouteConfig,\r
+    DeviceManagerCallback\r
+  }\r
+};\r
+\r
+EFI_GUID mDeviceManagerGuid = DEVICE_MANAGER_FORMSET_GUID;\r
+\r
+DEVICE_MANAGER_MENU_ITEM  mDeviceManagerMenuItemTable[] = {\r
+  { STRING_TOKEN (STR_DISK_DEVICE),     EFI_DISK_DEVICE_CLASS },\r
+  { STRING_TOKEN (STR_VIDEO_DEVICE),    EFI_VIDEO_DEVICE_CLASS },\r
+  { STRING_TOKEN (STR_NETWORK_DEVICE),  EFI_NETWORK_DEVICE_CLASS },\r
+  { STRING_TOKEN (STR_INPUT_DEVICE),    EFI_INPUT_DEVICE_CLASS },\r
+  { STRING_TOKEN (STR_ON_BOARD_DEVICE), EFI_ON_BOARD_DEVICE_CLASS },\r
+  { STRING_TOKEN (STR_OTHER_DEVICE),    EFI_OTHER_DEVICE_CLASS }\r
+};\r
+\r
+#define MENU_ITEM_NUM  \\r
+  (sizeof (mDeviceManagerMenuItemTable) / sizeof (DEVICE_MANAGER_MENU_ITEM))\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceManagerCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    This function processes the results of changes in configuration.\r
+\r
+  Arguments:\r
+    This          - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+    Action        - Specifies the type of action taken by the browser.\r
+    QuestionId    - A unique value which is sent to the original exporting driver\r
+                    so that it can identify the type of data to expect.\r
+    Type          - The type of value for the question.\r
+    Value         - A pointer to the data being sent to the original exporting driver.\r
+    ActionRequest - On return, points to the action requested by the callback function.\r
+\r
+  Returns:\r
+    EFI_SUCCESS          - The callback successfully handled the action.\r
+    EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.\r
+    EFI_DEVICE_ERROR     - The variable could not be saved.\r
+    EFI_UNSUPPORTED      - The specified Action is not supported by the callback.\r
+\r
+--*/\r
+{\r
+  DEVICE_MANAGER_CALLBACK_DATA *PrivateData;\r
+\r
+  if ((Value == NULL) || (ActionRequest == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PrivateData = DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS (This);\r
+\r
+  switch (QuestionId) {\r
+  case DEVICE_MANAGER_KEY_VBIOS:\r
+    PrivateData->VideoBios = Value->u8;\r
+    gRT->SetVariable (\r
+           L"VBIOS",\r
+           &gEfiGenericPlatformVariableGuid,\r
+           EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+           sizeof (UINT8),\r
+           &PrivateData->VideoBios\r
+           );\r
+\r
+    //\r
+    // Tell browser not to ask for confirmation of changes,\r
+    // since we have already applied.\r
+    //\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+    break;\r
+\r
+  default:\r
+    //\r
+    // The key corresponds the Handle Index which was requested to be displayed\r
+    //\r
+    gCallbackKey = QuestionId;\r
+\r
+    //\r
+    // Request to exit SendForm(), so as to switch to selected form\r
+    //\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+    break;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeDeviceManager (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initialize HII information for the FrontPage\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+  //\r
+  // Create driver handle used by HII database\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&gDeviceManagerPrivate.DriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Install Config Access protocol to driver handle\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &gDeviceManagerPrivate.DriverHandle,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &gDeviceManagerPrivate.ConfigAccess\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Publish our HII data\r
+  //\r
+  PackageList = PreparePackageList (2, &mDeviceManagerGuid, DeviceManagerVfrBin, BdsStrings);\r
+  ASSERT (PackageList != NULL);\r
+\r
+  Status = gHiiDatabase->NewPackageList (\r
+                           gHiiDatabase,\r
+                           PackageList,\r
+                           gDeviceManagerPrivate.DriverHandle,\r
+                           &gDeviceManagerPrivate.HiiHandle\r
+                           );\r
+  FreePool (PackageList);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+CallDeviceManager (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Call the browser and display the device manager\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+  EFI_SUCCESS            - Operation is successful.\r
+  EFI_INVALID_PARAMETER  - If the inputs to SendForm function is not valid.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                  Status;\r
+  UINTN                       Count;\r
+  UINTN                       Index;\r
+  CHAR16                      *String;\r
+  UINTN                       StringLength;\r
+  EFI_HII_UPDATE_DATA         UpdateData[MENU_ITEM_NUM];\r
+  EFI_STRING_ID               Token;\r
+  EFI_STRING_ID               TokenHelp;\r
+  IFR_OPTION                  *IfrOptionList;\r
+  UINT8                       *VideoOption;\r
+  UINTN                       VideoOptionSize;\r
+  EFI_HII_HANDLE              *HiiHandles;\r
+  UINTN                       HandleBufferLength;\r
+  UINTN                       NumberOfHiiHandles;\r
+  EFI_HII_HANDLE              HiiHandle;\r
+  UINT16                      FormSetClass;\r
+  EFI_STRING_ID               FormSetTitle;\r
+  EFI_STRING_ID               FormSetHelp;\r
+  EFI_BROWSER_ACTION_REQUEST  ActionRequest;\r
+  EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+  IfrOptionList       = NULL;\r
+  VideoOption         = NULL;\r
+  HiiHandles          = NULL;\r
+  HandleBufferLength  = 0;\r
+\r
+  Status        = EFI_SUCCESS;\r
+  gCallbackKey  = 0;\r
+\r
+  //\r
+  // Connect all prior to entering the platform setup menu.\r
+  //\r
+  if (!gConnectAllHappened) {\r
+    BdsLibConnectAllDriversToAllControllers ();\r
+    gConnectAllHappened = TRUE;\r
+  }\r
+\r
+  //\r
+  // Create Subtitle OpCodes\r
+  //\r
+  for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
+    //\r
+    // Allocate space for creation of UpdateData Buffer\r
+    //\r
+    UpdateData[Index].BufferSize = 0x1000;\r
+    UpdateData[Index].Offset = 0;\r
+    UpdateData[Index].Data = AllocatePool (0x1000);\r
+    ASSERT (UpdateData[Index].Data != NULL);\r
+\r
+    CreateSubTitleOpCode (mDeviceManagerMenuItemTable[Index].StringId, 0, 0, 1,  &UpdateData[Index]);\r
+  }\r
+\r
+  //\r
+  // Get all the Hii handles\r
+  //\r
+  Status = GetHiiHandles (&HandleBufferLength, &HiiHandles);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  HiiHandle = gDeviceManagerPrivate.HiiHandle;\r
+\r
+  StringLength  = 0x1000;\r
+  String        = AllocateZeroPool (StringLength);\r
+  ASSERT (String != NULL);\r
+\r
+  //\r
+  // Search for formset of each class type\r
+  //\r
+  NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE);\r
+  for (Index = 0; Index < NumberOfHiiHandles; Index++) {\r
+    HiiLibExtractClassFromHiiHandle (HiiHandles[Index], &FormSetClass, &FormSetTitle, &FormSetHelp);\r
+\r
+    if (FormSetClass == EFI_NON_DEVICE_CLASS) {\r
+      continue;\r
+    }\r
+\r
+    Token = 0;\r
+    *String = 0;\r
+    StringLength = 0x1000;\r
+    IfrLibGetString (HiiHandles[Index], FormSetTitle, String, &StringLength);\r
+    IfrLibNewString (HiiHandle, &Token, String);\r
+\r
+    TokenHelp = 0;\r
+    *String = 0;\r
+    StringLength = 0x1000;\r
+    IfrLibGetString (HiiHandles[Index], FormSetHelp, String, &StringLength);\r
+    IfrLibNewString (HiiHandle, &TokenHelp, String);\r
+\r
+    for (Count = 0; Count < MENU_ITEM_NUM; Count++) {\r
+      if (FormSetClass & mDeviceManagerMenuItemTable[Count].Class) {\r
+        CreateActionOpCode (\r
+          (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET),\r
+          Token,\r
+          TokenHelp,\r
+          EFI_IFR_FLAG_CALLBACK,\r
+          0,\r
+          &UpdateData[Count]\r
+          );\r
+      }\r
+    }\r
+  }\r
+  FreePool (String);\r
+\r
+  for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
+    //\r
+    // Add End Opcode for Subtitle\r
+    //\r
+    CreateEndOpCode (&UpdateData[Index]);\r
+\r
+    IfrLibUpdateForm (\r
+      HiiHandle,\r
+      &mDeviceManagerGuid,\r
+      DEVICE_MANAGER_FORM_ID,\r
+      mDeviceManagerMenuItemTable[Index].Class,\r
+      FALSE,\r
+      &UpdateData[Index]\r
+      );\r
+  }\r
+\r
+  //\r
+  // Add oneof for video BIOS selection\r
+  //\r
+  VideoOption = BdsLibGetVariableAndSize (\r
+                  L"VBIOS",\r
+                  &gEfiGenericPlatformVariableGuid,\r
+                  &VideoOptionSize\r
+                  );\r
+  if (NULL == VideoOption) {\r
+    gDeviceManagerPrivate.VideoBios = 0;\r
+  } else {\r
+    gDeviceManagerPrivate.VideoBios = VideoOption[0];\r
+    FreePool (VideoOption);\r
+  }\r
+\r
+  ASSERT (gDeviceManagerPrivate.VideoBios <= 1);\r
+\r
+  IfrOptionList = AllocatePool (2 * sizeof (IFR_OPTION));\r
+  ASSERT (IfrOptionList != NULL);\r
+  IfrOptionList[0].Flags        = 0;\r
+  IfrOptionList[0].StringToken  = STRING_TOKEN (STR_ONE_OF_PCI);\r
+  IfrOptionList[0].Value.u8     = 0;\r
+  IfrOptionList[1].Flags        = 0;\r
+  IfrOptionList[1].StringToken  = STRING_TOKEN (STR_ONE_OF_AGP);\r
+  IfrOptionList[1].Value.u8     = 1;\r
+  IfrOptionList[gDeviceManagerPrivate.VideoBios].Flags |= EFI_IFR_OPTION_DEFAULT;\r
+\r
+  UpdateData[0].Offset = 0;\r
+  CreateOneOfOpCode (\r
+    DEVICE_MANAGER_KEY_VBIOS,\r
+    0,\r
+    0,\r
+    STRING_TOKEN (STR_ONE_OF_VBIOS),\r
+    STRING_TOKEN (STR_ONE_OF_VBIOS_HELP),\r
+    EFI_IFR_FLAG_CALLBACK,\r
+    EFI_IFR_NUMERIC_SIZE_1,\r
+    IfrOptionList,\r
+    2,\r
+    &UpdateData[0]\r
+    );\r
+\r
+  IfrLibUpdateForm (\r
+    HiiHandle,\r
+    &mDeviceManagerGuid,\r
+    DEVICE_MANAGER_FORM_ID,\r
+    LABEL_VBIOS,\r
+    FALSE,\r
+    &UpdateData[0]\r
+    );\r
+\r
+  //\r
+  // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION\r
+  //\r
+  gBS->RestoreTPL (TPL_APPLICATION);\r
+\r
+  ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+  Status = gFormBrowser2->SendForm (\r
+                           gFormBrowser2,\r
+                           &HiiHandle,\r
+                           1,\r
+                           NULL,\r
+                           0,\r
+                           NULL,\r
+                           &ActionRequest\r
+                           );\r
+  if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+    EnableResetRequired ();\r
+  }\r
+\r
+  //\r
+  // We will have returned from processing a callback - user either hit ESC to exit, or selected\r
+  // a target to display\r
+  //\r
+  if (gCallbackKey != 0) {\r
+    ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+    Status = gFormBrowser2->SendForm (\r
+                             gFormBrowser2,\r
+                             &HiiHandles[gCallbackKey - DEVICE_KEY_OFFSET],\r
+                             1,\r
+                             NULL,\r
+                             0,\r
+                             NULL,\r
+                             &ActionRequest\r
+                             );\r
+\r
+    if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+      EnableResetRequired ();\r
+    }\r
+\r
+    //\r
+    // Force return to Device Manager\r
+    //\r
+    gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
+  }\r
+\r
+  //\r
+  // Cleanup dynamic created strings in HII database by reinstall the packagelist\r
+  //\r
+  gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);\r
+  PackageList = PreparePackageList (2, &mDeviceManagerGuid, DeviceManagerVfrBin, BdsStrings);\r
+  ASSERT (PackageList != NULL);\r
+  Status = gHiiDatabase->NewPackageList (\r
+                           gHiiDatabase,\r
+                           PackageList,\r
+                           gDeviceManagerPrivate.DriverHandle,\r
+                           &gDeviceManagerPrivate.HiiHandle\r
+                           );\r
+  FreePool (PackageList);\r
+\r
+  for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
+    FreePool (UpdateData[Index].Data);\r
+  }\r
+  FreePool (HiiHandles);\r
+\r
+  gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+  return Status;\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h b/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h
new file mode 100644 (file)
index 0000000..0469456
--- /dev/null
@@ -0,0 +1,108 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  DeviceManager.c\r
+\r
+Abstract:\r
+\r
+  The platform device manager reference implement\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _DEVICE_MANAGER_H\r
+#define _DEVICE_MANAGER_H\r
+\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+//\r
+// These are defined as the same with vfr file\r
+//\r
+#define DEVICE_MANAGER_FORMSET_GUID  \\r
+  { \\r
+  0x3ebfa8e6, 0x511d, 0x4b5b, {0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27} \\r
+  }\r
+\r
+#define LABEL_VBIOS                          0x0040\r
+\r
+#define DEVICE_MANAGER_FORM_ID               0x1000\r
+\r
+#define DEVICE_KEY_OFFSET                    0x1000\r
+#define DEVICE_MANAGER_KEY_VBIOS             0x2000\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8  DeviceManagerVfrBin[];\r
+\r
+#define DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE  EFI_SIGNATURE_32 ('D', 'M', 'C', 'B')\r
+\r
+typedef struct {\r
+  UINTN                           Signature;\r
+\r
+  //\r
+  // HII relative handles\r
+  //\r
+  EFI_HII_HANDLE                  HiiHandle;\r
+  EFI_HANDLE                      DriverHandle;\r
+\r
+  //\r
+  // Produced protocols\r
+  //\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  ConfigAccess;\r
+\r
+  //\r
+  // Configuration data\r
+  //\r
+  UINT8                           VideoBios;\r
+} DEVICE_MANAGER_CALLBACK_DATA;\r
+\r
+#define DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS(a) \\r
+  CR (a, \\r
+      DEVICE_MANAGER_CALLBACK_DATA, \\r
+      ConfigAccess, \\r
+      DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE \\r
+      )\r
+\r
+typedef struct {\r
+  EFI_STRING_ID  StringId;\r
+  UINT16         Class;\r
+} DEVICE_MANAGER_MENU_ITEM;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceManagerCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+InitializeDeviceManager (\r
+  VOID\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+CallDeviceManager (\r
+  VOID\r
+  )\r
+;\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni b/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni
new file mode 100644 (file)
index 0000000..99beee4
Binary files /dev/null and b/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni differ
diff --git a/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr b/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr
new file mode 100644 (file)
index 0000000..78fff23
--- /dev/null
@@ -0,0 +1,82 @@
+// *++\r
+//\r
+// Copyright (c) 2004 - 2007, Intel Corporation\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution.  The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// Module Name:\r
+//\r
+//   DeviceManagerVfr.vfr\r
+//\r
+// Abstract:\r
+//\r
+//   Device Manager formset.\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+\r
+#define FORMSET_GUID  { 0x3ebfa8e6, 0x511d, 0x4b5b, 0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27 }\r
+\r
+#define EFI_DISK_DEVICE_CLASS              0x0001\r
+#define EFI_VIDEO_DEVICE_CLASS             0x0002\r
+#define EFI_NETWORK_DEVICE_CLASS           0x0004\r
+#define EFI_INPUT_DEVICE_CLASS             0x0008\r
+#define EFI_ON_BOARD_DEVICE_CLASS          0x0010\r
+#define EFI_OTHER_DEVICE_CLASS             0x0020\r
+#define LABEL_VBIOS                        0x0040\r
+\r
+#define LABEL_END                          0xffff\r
+\r
+#define DEVICE_MANAGER_CLASS               0x0000\r
+#define FRONT_PAGE_SUBCLASS                       0x0003\r
+\r
+#define DEVICE_MANAGER_FORM_ID             0x1000\r
+\r
+formset\r
+  guid     = FORMSET_GUID,\r
+  title    = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE),\r
+  help     = STRING_TOKEN(STR_EMPTY_STRING),\r
+  class    = DEVICE_MANAGER_CLASS,\r
+  subclass = FRONT_PAGE_SUBCLASS,\r
+\r
+  form formid = DEVICE_MANAGER_FORM_ID,\r
+       title  = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE);\r
+\r
+    //\r
+    // This is where devices get added to the device manager hierarchy\r
+    //\r
+    label EFI_DISK_DEVICE_CLASS;\r
+//    label LABEL_END;  // Since next opcode is a label, so this one could be omitted to save code size\r
+\r
+    label EFI_VIDEO_DEVICE_CLASS;\r
+//    label LABEL_END;\r
+\r
+    label EFI_NETWORK_DEVICE_CLASS;\r
+//    label LABEL_END;\r
+\r
+    label EFI_INPUT_DEVICE_CLASS;\r
+//    label LABEL_END;\r
+\r
+    label EFI_ON_BOARD_DEVICE_CLASS;\r
+//    label LABEL_END;\r
+\r
+    label EFI_OTHER_DEVICE_CLASS;\r
+    label LABEL_END;\r
+\r
+    subtitle text = STRING_TOKEN(STR_EMPTY_STRING);\r
+\r
+    label LABEL_VBIOS;\r
+    label LABEL_END;\r
+\r
+    subtitle text = STRING_TOKEN(STR_EMPTY_STRING);\r
+    subtitle text = STRING_TOKEN(STR_EXIT_STRING);\r
+\r
+  endform;\r
+endformset;\r
+\r
diff --git a/MdeModulePkg/Universal/BdsDxe/FrontPage.c b/MdeModulePkg/Universal/BdsDxe/FrontPage.c
new file mode 100644 (file)
index 0000000..b82b40f
--- /dev/null
@@ -0,0 +1,1035 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  FrontPage.c\r
+\r
+Abstract:\r
+\r
+  FrontPage routines to handle the callbacks and browser calls\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+EFI_GUID  mFrontPageGuid      = FRONT_PAGE_FORMSET_GUID;\r
+\r
+BOOLEAN   gConnectAllHappened = FALSE;\r
+UINTN     gCallbackKey;\r
+\r
+EFI_HII_DATABASE_PROTOCOL       *gHiiDatabase;\r
+EFI_HII_STRING_PROTOCOL         *gHiiString;\r
+EFI_FORM_BROWSER2_PROTOCOL      *gFormBrowser2;\r
+EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting;\r
+\r
+FRONT_PAGE_CALLBACK_DATA  gFrontPagePrivate = {\r
+  FRONT_PAGE_CALLBACK_DATA_SIGNATURE,\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  {\r
+    FakeExtractConfig,\r
+    FakeRouteConfig,\r
+    FrontPageCallback\r
+  }\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FakeExtractConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Request,\r
+  OUT EFI_STRING                             *Progress,\r
+  OUT EFI_STRING                             *Results\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    This function allows a caller to extract the current configuration for one\r
+    or more named elements from the target driver.\r
+\r
+  Arguments:\r
+    This       - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+    Request    - A null-terminated Unicode string in <ConfigRequest> format.\r
+    Progress   - On return, points to a character in the Request string.\r
+                 Points to the string's null terminator if request was successful.\r
+                 Points to the most recent '&' before the first failing name/value\r
+                 pair (or the beginning of the string if the failure is in the\r
+                 first name/value pair) if the request was not successful.\r
+    Results    - A null-terminated Unicode string in <ConfigAltResp> format which\r
+                 has all values filled in for the names in the Request string.\r
+                 String to be allocated by the called function.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The Results is filled with the requested values.\r
+    EFI_OUT_OF_RESOURCES  - Not enough memory to store the results.\r
+    EFI_INVALID_PARAMETER - Request is NULL, illegal syntax, or unknown name.\r
+    EFI_NOT_FOUND         - Routing data doesn't match any storage in this driver.\r
+\r
+--*/\r
+{\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FakeRouteConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Configuration,\r
+  OUT EFI_STRING                             *Progress\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    This function processes the results of changes in configuration.\r
+\r
+  Arguments:\r
+    This          - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+    Configuration - A null-terminated Unicode string in <ConfigResp> format.\r
+    Progress      - A pointer to a string filled in with the offset of the most\r
+                    recent '&' before the first failing name/value pair (or the\r
+                    beginning of the string if the failure is in the first\r
+                    name/value pair) or the terminating NULL if all was successful.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The Results is processed successfully.\r
+    EFI_INVALID_PARAMETER - Configuration is NULL.\r
+    EFI_NOT_FOUND         - Routing data doesn't match any storage in this driver.\r
+\r
+--*/\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FrontPageCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    This function processes the results of changes in configuration.\r
+\r
+  Arguments:\r
+    This          - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+    Action        - Specifies the type of action taken by the browser.\r
+    QuestionId    - A unique value which is sent to the original exporting driver\r
+                    so that it can identify the type of data to expect.\r
+    Type          - The type of value for the question.\r
+    Value         - A pointer to the data being sent to the original exporting driver.\r
+    ActionRequest - On return, points to the action requested by the callback function.\r
+\r
+  Returns:\r
+    EFI_SUCCESS          - The callback successfully handled the action.\r
+    EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.\r
+    EFI_DEVICE_ERROR     - The variable could not be saved.\r
+    EFI_UNSUPPORTED      - The specified Action is not supported by the callback.\r
+\r
+--*/\r
+{\r
+  CHAR8                         *LanguageString;\r
+  CHAR8                         *LangCode;\r
+  CHAR8                         Lang[RFC_3066_ENTRY_SIZE];\r
+#ifdef LANG_SUPPORT\r
+  CHAR8                         OldLang[ISO_639_2_ENTRY_SIZE];\r
+#endif\r
+  UINTN                         Index;\r
+  EFI_STATUS                    Status;\r
+\r
+  if ((Value == NULL) || (ActionRequest == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  gCallbackKey = QuestionId;\r
+\r
+  //\r
+  // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can\r
+  // describe to their customers in documentation how to find their setup information (namely\r
+  // under the device manager and specific buckets)\r
+  //\r
+  switch (QuestionId) {\r
+  case FRONT_PAGE_KEY_CONTINUE:\r
+    //\r
+    // This is the continue - clear the screen and return an error to get out of FrontPage loop\r
+    //\r
+    break;\r
+\r
+  case FRONT_PAGE_KEY_LANGUAGE:\r
+    //\r
+    // Collect the languages from what our current Language support is based on our VFR\r
+    //\r
+    LanguageString = GetSupportedLanguages (gFrontPagePrivate.HiiHandle);\r
+    ASSERT (LanguageString != NULL);\r
+\r
+    Index = 0;\r
+    LangCode = LanguageString;\r
+    while (*LangCode != 0) {\r
+      GetNextLanguage (&LangCode, Lang);\r
+\r
+      if (Index == Value->u8) {\r
+        break;\r
+      }\r
+\r
+      Index++;\r
+    }\r
+\r
+    Status = gRT->SetVariable (\r
+                    L"PlatformLang",\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    AsciiStrSize (Lang),\r
+                    Lang\r
+                    );\r
+\r
+#ifdef LANG_SUPPORT\r
+    //\r
+    // Set UEFI deprecated variable "Lang" for backwards compatibility\r
+    //\r
+    Status = ConvertRfc3066LanguageToIso639Language (Lang, OldLang);\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = gRT->SetVariable (\r
+                      L"Lang",\r
+                      &gEfiGlobalVariableGuid,\r
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                      ISO_639_2_ENTRY_SIZE,\r
+                      OldLang\r
+                      );\r
+    }\r
+#endif\r
+\r
+    FreePool (LanguageString);\r
+    break;\r
+\r
+  case FRONT_PAGE_KEY_BOOT_MANAGER:\r
+    //\r
+    // Boot Manager\r
+    //\r
+    break;\r
+\r
+  case FRONT_PAGE_KEY_DEVICE_MANAGER:\r
+    //\r
+    // Device Manager\r
+    //\r
+    break;\r
+\r
+  case FRONT_PAGE_KEY_BOOT_MAINTAIN:\r
+    //\r
+    // Boot Maintenance Manager\r
+    //\r
+    break;\r
+\r
+  default:\r
+    gCallbackKey = 0;\r
+    break;\r
+  }\r
+\r
+  *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeFrontPage (\r
+  BOOLEAN                         ReInitializeStrings\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Initialize HII information for the FrontPage\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+  EFI_SUCCESS       - The operation is successful.\r
+  EFI_DEVICE_ERROR  - If the dynamic opcode creation failed.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+  EFI_HII_UPDATE_DATA         UpdateData;\r
+  IFR_OPTION                  *OptionList;\r
+  CHAR8                       *LanguageString;\r
+  CHAR8                       *LangCode;\r
+  CHAR8                       Lang[RFC_3066_ENTRY_SIZE];\r
+  CHAR8                       CurrentLang[RFC_3066_ENTRY_SIZE];\r
+  UINTN                       OptionCount;\r
+  EFI_STRING_ID               Token;\r
+  CHAR16                      *StringBuffer;\r
+  UINTN                       BufferSize;\r
+  UINTN                       Index;\r
+  EFI_HII_HANDLE              HiiHandle;\r
+\r
+  if (!ReInitializeStrings) {\r
+    //\r
+    // Initialize the Device Manager\r
+    //\r
+    InitializeDeviceManager ();\r
+\r
+    //\r
+    // Initialize the Device Manager\r
+    //\r
+    InitializeBootManager ();\r
+\r
+    gCallbackKey  = 0;\r
+\r
+    //\r
+    // Locate Hii relative protocols\r
+    //\r
+    Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gHiiDatabase);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &gHiiString);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFormBrowser2);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &gHiiConfigRouting);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Create driver handle used by HII database\r
+    //\r
+    Status = HiiLibCreateHiiDriverHandle (&gFrontPagePrivate.DriverHandle);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Install Config Access protocol to driver handle\r
+    //\r
+    Status = gBS->InstallProtocolInterface (\r
+                    &gFrontPagePrivate.DriverHandle,\r
+                    &gEfiHiiConfigAccessProtocolGuid,\r
+                    EFI_NATIVE_INTERFACE,\r
+                    &gFrontPagePrivate.ConfigAccess\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Publish our HII data\r
+    //\r
+    PackageList = PreparePackageList (2, &mFrontPageGuid, FrontPageVfrBin, BdsStrings);\r
+    ASSERT (PackageList != NULL);\r
+\r
+    Status = gHiiDatabase->NewPackageList (\r
+                             gHiiDatabase,\r
+                             PackageList,\r
+                             gFrontPagePrivate.DriverHandle,\r
+                             &gFrontPagePrivate.HiiHandle\r
+                             );\r
+    FreePool (PackageList);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Get current language setting\r
+  //\r
+  GetCurrentLanguage (CurrentLang);\r
+\r
+  //\r
+  // Allocate space for creation of UpdateData Buffer\r
+  //\r
+  UpdateData.BufferSize = 0x1000;\r
+  UpdateData.Data = AllocateZeroPool (0x1000);\r
+  ASSERT (UpdateData.Data != NULL);\r
+\r
+  OptionList = AllocateZeroPool (0x1000);\r
+  ASSERT (OptionList != NULL);\r
+\r
+  //\r
+  // Collect the languages from what our current Language support is based on our VFR\r
+  //\r
+  HiiHandle = gFrontPagePrivate.HiiHandle;\r
+  LanguageString = GetSupportedLanguages (HiiHandle);\r
+  ASSERT (LanguageString != NULL);\r
+\r
+  OptionCount = 0;\r
+  LangCode = LanguageString;\r
+  while (*LangCode != 0) {\r
+    GetNextLanguage (&LangCode, Lang);\r
+\r
+    if (gFrontPagePrivate.LanguageToken == NULL) {\r
+      //\r
+      // Get Language Name from String Package. The StringId of Printable Language\r
+      // Name is always 1 which is generated by StringGather Tool.\r
+      //\r
+      BufferSize = 0x100;\r
+      StringBuffer = AllocatePool (BufferSize);\r
+      Status = gHiiString->GetString (\r
+                           gHiiString,\r
+                           Lang,\r
+                           HiiHandle,\r
+                           PRINTABLE_LANGUAGE_NAME_STRING_ID,\r
+                           StringBuffer,\r
+                           &BufferSize,\r
+                           NULL\r
+                           );\r
+      if (Status == EFI_BUFFER_TOO_SMALL) {\r
+        FreePool (StringBuffer);\r
+        StringBuffer = AllocatePool (BufferSize);\r
+        Status = gHiiString->GetString (\r
+                             gHiiString,\r
+                             Lang,\r
+                             HiiHandle,\r
+                             PRINTABLE_LANGUAGE_NAME_STRING_ID,\r
+                             StringBuffer,\r
+                             &BufferSize,\r
+                             NULL\r
+                             );\r
+      }\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      Token = 0;\r
+      Status = IfrLibNewString (HiiHandle, &Token, StringBuffer);\r
+      FreePool (StringBuffer);\r
+    } else {\r
+      Token = gFrontPagePrivate.LanguageToken[OptionCount];\r
+    }\r
+\r
+    if (AsciiStrCmp (Lang, CurrentLang) == 0) {\r
+      OptionList[OptionCount].Flags = EFI_IFR_OPTION_DEFAULT;\r
+    } else {\r
+      OptionList[OptionCount].Flags = 0;\r
+    }\r
+    OptionList[OptionCount].StringToken = Token;\r
+    OptionList[OptionCount].Value.u8 = (UINT8) OptionCount;\r
+\r
+    OptionCount++;\r
+  }\r
+\r
+  FreePool (LanguageString);\r
+\r
+  UpdateData.Offset = 0;\r
+  CreateOneOfOpCode (\r
+    FRONT_PAGE_KEY_LANGUAGE,\r
+    0,\r
+    0,\r
+    STRING_TOKEN (STR_LANGUAGE_SELECT),\r
+    STRING_TOKEN (STR_LANGUAGE_SELECT_HELP),\r
+    EFI_IFR_FLAG_CALLBACK,\r
+    EFI_IFR_NUMERIC_SIZE_1,\r
+    OptionList,\r
+    OptionCount,\r
+    &UpdateData\r
+    );\r
+\r
+  Status = IfrLibUpdateForm (\r
+             HiiHandle,\r
+             &mFrontPageGuid,\r
+             FRONT_PAGE_FORM_ID,\r
+             LABEL_SELECT_LANGUAGE,\r
+             FALSE,\r
+             &UpdateData\r
+             );\r
+\r
+  //\r
+  // Save the string Id for each language\r
+  //\r
+  gFrontPagePrivate.LanguageToken = AllocatePool (OptionCount * sizeof (EFI_STRING_ID));\r
+  ASSERT (gFrontPagePrivate.LanguageToken != NULL);\r
+  for (Index = 0; Index < OptionCount; Index++) {\r
+    gFrontPagePrivate.LanguageToken[Index] = OptionList[Index].StringToken;\r
+  }\r
+\r
+  FreePool (UpdateData.Data);\r
+  FreePool (OptionList);\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+CallFrontPage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Call the browser and display the front page\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_BROWSER_ACTION_REQUEST  ActionRequest;\r
+\r
+  //\r
+  // Begin waiting for USER INPUT\r
+  //\r
+  REPORT_STATUS_CODE (\r
+    EFI_PROGRESS_CODE,\r
+    (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT)\r
+    );\r
+\r
+\r
+  //\r
+  // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION\r
+  //\r
+  gBS->RestoreTPL (TPL_APPLICATION);\r
+\r
+  ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+  Status = gFormBrowser2->SendForm (\r
+                            gFormBrowser2,\r
+                            &gFrontPagePrivate.HiiHandle,\r
+                            1,\r
+                            NULL,\r
+                            0,\r
+                            NULL,\r
+                            &ActionRequest\r
+                            );\r
+  //\r
+  // Check whether user  change any option setting which needs a reset to be effective\r
+  //\r
+  if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+    EnableResetRequired ();\r
+  }\r
+\r
+  gBS->RaiseTPL (TPL_APPLICATION);\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+GetProducerString (\r
+  IN      EFI_GUID                  *ProducerGuid,\r
+  IN      EFI_STRING_ID             Token,\r
+  OUT     CHAR16                    **String\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Acquire the string associated with the ProducerGuid and return it.\r
+\r
+Arguments:\r
+  ProducerGuid - The Guid to search the HII database for\r
+  Token - The token value of the string to extract\r
+  String - The string that is extracted\r
+\r
+Returns:\r
+  EFI_SUCCESS - The function returns EFI_SUCCESS always.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS      Status;\r
+\r
+  Status = GetStringFromToken (ProducerGuid, Token, String);\r
+  if (EFI_ERROR (Status)) {\r
+    *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+ConvertProcessorToString (\r
+  IN  EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency,\r
+  OUT CHAR16                            **String\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Convert Processor Frequency Data to a string\r
+\r
+Arguments:\r
+  ProcessorFrequency - The frequency data to process\r
+  String - The string that is created\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  CHAR16  *StringBuffer;\r
+  UINTN   Index;\r
+  UINT32  FreqMhz;\r
+\r
+  if (ProcessorFrequency->Exponent >= 6) {\r
+    FreqMhz = ProcessorFrequency->Value;\r
+    for (Index = 0; Index < (UINTN) (ProcessorFrequency->Exponent - 6); Index++) {\r
+      FreqMhz *= 10;\r
+    }\r
+  } else {\r
+    FreqMhz = 0;\r
+  }\r
+\r
+  StringBuffer = AllocateZeroPool (0x20);\r
+  ASSERT (StringBuffer != NULL);\r
+  Index = UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, FreqMhz / 1000, 3);\r
+  StrCat (StringBuffer, L".");\r
+  UnicodeValueToString (StringBuffer + Index + 1, PREFIX_ZERO, (FreqMhz % 1000) / 10, 2);\r
+  StrCat (StringBuffer, L" GHz");\r
+\r
+  *String = (CHAR16 *) StringBuffer;\r
+\r
+  return ;\r
+}\r
+\r
+VOID\r
+ConvertMemorySizeToString (\r
+  IN  UINT32          MemorySize,\r
+  OUT CHAR16          **String\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Convert Memory Size to a string\r
+\r
+Arguments:\r
+  MemorySize - The size of the memory to process\r
+  String - The string that is created\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  CHAR16  *StringBuffer;\r
+\r
+  StringBuffer = AllocateZeroPool (0x20);\r
+  ASSERT (StringBuffer != NULL);\r
+  UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, MemorySize, 6);\r
+  StrCat (StringBuffer, L" MB RAM");\r
+\r
+  *String = (CHAR16 *) StringBuffer;\r
+\r
+  return ;\r
+}\r
+\r
+VOID\r
+UpdateFrontPageStrings (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Update the banner information for the Front Page based on DataHub information\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_STRING_ID                     TokenToUpdate;\r
+  CHAR16                            *NewString;\r
+  UINT64                            MonotonicCount;\r
+  EFI_DATA_HUB_PROTOCOL             *DataHub;\r
+  EFI_DATA_RECORD_HEADER            *Record;\r
+  EFI_SUBCLASS_TYPE1_HEADER         *DataHeader;\r
+  EFI_MISC_BIOS_VENDOR_DATA         *BiosVendor;\r
+  EFI_MISC_SYSTEM_MANUFACTURER_DATA *SystemManufacturer;\r
+  EFI_PROCESSOR_VERSION_DATA        *ProcessorVersion;\r
+  EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency;\r
+  EFI_MEMORY_ARRAY_START_ADDRESS_DATA    *MemoryArray;\r
+  BOOLEAN                           Find[5];\r
+\r
+  ZeroMem (Find, sizeof (Find));\r
+\r
+  //\r
+  // Update Front Page strings\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiDataHubProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &DataHub\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  MonotonicCount  = 0;\r
+  Record          = NULL;\r
+  do {\r
+    Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record);\r
+    if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {\r
+      DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
+      if (CompareGuid (&Record->DataRecordGuid, &gEfiMiscSubClassGuid) &&\r
+          (DataHeader->RecordType == EFI_MISC_BIOS_VENDOR_RECORD_NUMBER)\r
+          ) {\r
+        BiosVendor = (EFI_MISC_BIOS_VENDOR_DATA *) (DataHeader + 1);\r
+        GetProducerString (&Record->ProducerName, BiosVendor->BiosVersion, &NewString);\r
+        TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION);\r
+        IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+        FreePool (NewString);\r
+        Find[0] = TRUE;\r
+      }\r
+\r
+      if (CompareGuid (&Record->DataRecordGuid, &gEfiMiscSubClassGuid) &&\r
+          (DataHeader->RecordType == EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER)\r
+          ) {\r
+        SystemManufacturer = (EFI_MISC_SYSTEM_MANUFACTURER_DATA *) (DataHeader + 1);\r
+        GetProducerString (&Record->ProducerName, SystemManufacturer->SystemProductName, &NewString);\r
+        TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL);\r
+        IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+        FreePool (NewString);\r
+        Find[1] = TRUE;\r
+      }\r
+\r
+      if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&\r
+          (DataHeader->RecordType == ProcessorVersionRecordType)\r
+          ) {\r
+        ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *) (DataHeader + 1);\r
+        GetProducerString (&Record->ProducerName, *ProcessorVersion, &NewString);\r
+        TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL);\r
+        IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+        FreePool (NewString);\r
+        Find[2] = TRUE;\r
+      }\r
+\r
+      if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&\r
+          (DataHeader->RecordType == ProcessorCoreFrequencyRecordType)\r
+          ) {\r
+        ProcessorFrequency = (EFI_PROCESSOR_CORE_FREQUENCY_DATA *) (DataHeader + 1);\r
+        ConvertProcessorToString (ProcessorFrequency, &NewString);\r
+        TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED);\r
+        IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+        FreePool (NewString);\r
+        Find[3] = TRUE;\r
+      }\r
+\r
+      if (CompareGuid (&Record->DataRecordGuid, &gEfiMemorySubClassGuid) &&\r
+          (DataHeader->RecordType == EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER)\r
+          ) {\r
+        MemoryArray = (EFI_MEMORY_ARRAY_START_ADDRESS_DATA *) (DataHeader + 1);\r
+        ConvertMemorySizeToString (\r
+          (UINT32)(RShiftU64((MemoryArray->MemoryArrayEndAddress - MemoryArray->MemoryArrayStartAddress + 1), 20)),\r
+          &NewString\r
+          );\r
+        TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE);\r
+        IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+        FreePool (NewString);\r
+        Find[4] = TRUE;\r
+      }\r
+    }\r
+  } while (!EFI_ERROR (Status) && (MonotonicCount != 0) && !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4]));\r
+\r
+  return ;\r
+}\r
+\r
+EFI_STATUS\r
+WaitForSingleEvent (\r
+  IN EFI_EVENT                  Event,\r
+  IN UINT64                     Timeout OPTIONAL\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Function waits for a given event to fire, or for an optional timeout to expire.\r
+\r
+Arguments:\r
+  Event            - The event to wait for\r
+  Timeout          - An optional timeout value in 100 ns units.\r
+\r
+Returns:\r
+  EFI_SUCCESS      - Event fired before Timeout expired.\r
+  EFI_TIME_OUT     - Timout expired before Event fired..\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Index;\r
+  EFI_EVENT   TimerEvent;\r
+  EFI_EVENT   WaitList[2];\r
+\r
+  if (Timeout) {\r
+    //\r
+    // Create a timer event\r
+    //\r
+    Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Set the timer event\r
+      //\r
+      gBS->SetTimer (\r
+            TimerEvent,\r
+            TimerRelative,\r
+            Timeout\r
+            );\r
+\r
+      //\r
+      // Wait for the original event or the timer\r
+      //\r
+      WaitList[0] = Event;\r
+      WaitList[1] = TimerEvent;\r
+      Status      = gBS->WaitForEvent (2, WaitList, &Index);\r
+      gBS->CloseEvent (TimerEvent);\r
+\r
+      //\r
+      // If the timer expired, change the return to timed out\r
+      //\r
+      if (!EFI_ERROR (Status) && Index == 1) {\r
+        Status = EFI_TIMEOUT;\r
+      }\r
+    }\r
+  } else {\r
+    //\r
+    // No timeout... just wait on the event\r
+    //\r
+    Status = gBS->WaitForEvent (1, &Event, &Index);\r
+    ASSERT (!EFI_ERROR (Status));\r
+    ASSERT (Index == 0);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+ShowProgress (\r
+  IN UINT16                       TimeoutDefault\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Function show progress bar to wait for user input.\r
+\r
+Arguments:\r
+  TimeoutDefault   - The fault time out value before the system\r
+                     continue to boot.\r
+\r
+Returns:\r
+  EFI_SUCCESS      - User pressed some key except "Enter"\r
+  EFI_TIME_OUT     - Timout expired or user press "Enter"\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                    Status;\r
+  CHAR16                        *TmpStr;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
+  EFI_INPUT_KEY                 Key;\r
+  UINT16                        TimeoutRemain;\r
+\r
+  if (TimeoutDefault == 0) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+  SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+  SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+\r
+  //\r
+  // Clear the progress status bar first\r
+  //\r
+  TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION));\r
+  if (TmpStr != NULL) {\r
+    PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0);\r
+  }\r
+\r
+  TimeoutRemain = TimeoutDefault;\r
+  while (TimeoutRemain != 0) {\r
+    Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);\r
+    if (Status != EFI_TIMEOUT) {\r
+      break;\r
+    }\r
+    TimeoutRemain--;\r
+\r
+    //\r
+    // Show progress\r
+    //\r
+    if (TmpStr != NULL) {\r
+      PlatformBdsShowProgress (\r
+        Foreground,\r
+        Background,\r
+        TmpStr,\r
+        Color,\r
+        ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),\r
+        0\r
+        );\r
+    }\r
+  }\r
+  gBS->FreePool (TmpStr);\r
+\r
+  //\r
+  // Timeout expired\r
+  //\r
+  if (TimeoutRemain == 0) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  //\r
+  // User pressed some key\r
+  //\r
+  Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+    //\r
+    // User pressed enter, equivalent to select "continue"\r
+    //\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+PlatformBdsEnterFrontPage (\r
+  IN UINT16                       TimeoutDefault,\r
+  IN BOOLEAN                      ConnectAllHappened\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  This function is the main entry of the platform setup entry.\r
+  The function will present the main menu of the system setup,\r
+  this is the platform reference part and can be customize.\r
+\r
+Arguments:\r
+  TimeoutDefault     - The fault time out value before the system\r
+                       continue to boot.\r
+  ConnectAllHappened - The indicater to check if the connect all have\r
+                       already happended.\r
+\r
+Returns:\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;\r
+\r
+  //\r
+  // Indicate if we need connect all in the platform setup\r
+  //\r
+  if (ConnectAllHappened) {\r
+    gConnectAllHappened = TRUE;\r
+  }\r
+\r
+  if (TimeoutDefault != 0xffff) {\r
+    gBS->RestoreTPL (TPL_APPLICATION);\r
+    Status = ShowProgress (TimeoutDefault);\r
+    gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Timeout or user press enter to continue\r
+      //\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  do {\r
+\r
+    InitializeFrontPage (TRUE);\r
+\r
+    //\r
+    // Update Front Page strings\r
+    //\r
+    UpdateFrontPageStrings ();\r
+\r
+    gCallbackKey = 0;\r
+    PERF_START (0, "BdsTimeOut", "BDS", 0);\r
+    Status = CallFrontPage ();\r
+    PERF_END (0, "BdsTimeOut", "BDS", 0);\r
+\r
+    //\r
+    // If gCallbackKey is greater than 1 and less or equal to 5,\r
+    // it will lauch configuration utilities.\r
+    // 2 = set language\r
+    // 3 = boot manager\r
+    // 4 = device manager\r
+    // 5 = boot maintainenance manager\r
+    //\r
+    if (gCallbackKey != 0) {\r
+      REPORT_STATUS_CODE (\r
+        EFI_PROGRESS_CODE,\r
+        (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP)\r
+        );\r
+    }\r
+    //\r
+    // Based on the key that was set, we can determine what to do\r
+    //\r
+    switch (gCallbackKey) {\r
+    //\r
+    // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can\r
+    // describe to their customers in documentation how to find their setup information (namely\r
+    // under the device manager and specific buckets)\r
+    //\r
+    // These entries consist of the Continue, Select language, Boot Manager, and Device Manager\r
+    //\r
+    case FRONT_PAGE_KEY_CONTINUE:\r
+      //\r
+      // User hit continue\r
+      //\r
+      break;\r
+\r
+    case FRONT_PAGE_KEY_LANGUAGE:\r
+      //\r
+      // User made a language setting change - display front page again\r
+      //\r
+      break;\r
+\r
+    case FRONT_PAGE_KEY_BOOT_MANAGER:\r
+      //\r
+      // User chose to run the Boot Manager\r
+      //\r
+      CallBootManager ();\r
+      break;\r
+\r
+    case FRONT_PAGE_KEY_DEVICE_MANAGER:\r
+      //\r
+      // Display the Device Manager\r
+      //\r
+      do {\r
+        CallDeviceManager();\r
+      } while (gCallbackKey == FRONT_PAGE_KEY_DEVICE_MANAGER);\r
+      break;\r
+\r
+    case FRONT_PAGE_KEY_BOOT_MAINTAIN:\r
+      //\r
+      // Display the Boot Maintenance Manager\r
+      //\r
+      BdsStartBootMaint ();\r
+      break;\r
+    }\r
+\r
+  } while ((Status == EFI_SUCCESS) && (gCallbackKey != FRONT_PAGE_KEY_CONTINUE));\r
+\r
+  //\r
+  //Will leave browser, check any reset required change is applied? if yes, reset system\r
+  //\r
+  gBS->RestoreTPL (TPL_APPLICATION);\r
+  SetupResetReminder ();\r
+  gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+Exit:\r
+  //\r
+  // Automatically load current entry\r
+  // Note: The following lines of code only execute when Auto boot\r
+  // takes affect\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
+  ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);\r
+\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/FrontPage.h b/MdeModulePkg/Universal/BdsDxe/FrontPage.h
new file mode 100644 (file)
index 0000000..fc01d16
--- /dev/null
@@ -0,0 +1,149 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  FrontPage.h\r
+\r
+Abstract:\r
+\r
+  FrontPage routines to handle the callbacks and browser calls\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _FRONT_PAGE_H\r
+#define _FRONT_PAGE_H\r
+\r
+#include "DeviceMngr/DeviceManager.h"\r
+#include "BootMaint/BootMaint.h"\r
+#include "BootMngr/BootManager.h"\r
+#include "String.h"\r
+\r
+#define ONE_SECOND  10000000\r
+\r
+//\r
+// This is the VFR compiler generated header file which defines the\r
+// string identifiers.\r
+//\r
+#define PRINTABLE_LANGUAGE_NAME_STRING_ID     0x0001\r
+\r
+//\r
+// These are defined as the same with vfr file\r
+//\r
+#define FRONT_PAGE_FORM_ID             0x1000\r
+\r
+#define FRONT_PAGE_KEY_CONTINUE        0x1000\r
+#define FRONT_PAGE_KEY_LANGUAGE        0x1234\r
+#define FRONT_PAGE_KEY_BOOT_MANAGER    0x1064\r
+#define FRONT_PAGE_KEY_DEVICE_MANAGER  0x8567\r
+#define FRONT_PAGE_KEY_BOOT_MAINTAIN   0x9876\r
+\r
+#define LABEL_SELECT_LANGUAGE          0x1000\r
+\r
+#define FRONT_PAGE_FORMSET_GUID \\r
+  { \\r
+    0x9e0c30bc, 0x3f06, 0x4ba6, 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe \\r
+  }\r
+\r
+#define FRONT_PAGE_CALLBACK_DATA_SIGNATURE  EFI_SIGNATURE_32 ('F', 'P', 'C', 'B')\r
+\r
+typedef struct {\r
+  UINTN                           Signature;\r
+\r
+  //\r
+  // HII relative handles\r
+  //\r
+  EFI_HII_HANDLE                  HiiHandle;\r
+  EFI_HANDLE                      DriverHandle;\r
+  EFI_STRING_ID                   *LanguageToken;\r
+\r
+  //\r
+  // Produced protocols\r
+  //\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  ConfigAccess;\r
+} FRONT_PAGE_CALLBACK_DATA;\r
+\r
+#define EFI_FP_CALLBACK_DATA_FROM_THIS(a) \\r
+  CR (a, \\r
+      FRONT_PAGE_CALLBACK_DATA, \\r
+      ConfigAccess, \\r
+      FRONT_PAGE_CALLBACK_DATA_SIGNATURE \\r
+      )\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8  FrontPageVfrBin[];\r
+\r
+extern EFI_HII_DATABASE_PROTOCOL       *gHiiDatabase;\r
+extern EFI_HII_STRING_PROTOCOL         *gHiiString;\r
+extern EFI_FORM_BROWSER2_PROTOCOL      *gFormBrowser2;\r
+extern EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting;\r
+\r
+extern UINTN    gCallbackKey;\r
+extern BOOLEAN  gConnectAllHappened;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FakeExtractConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Request,\r
+  OUT EFI_STRING                             *Progress,\r
+  OUT EFI_STRING                             *Results\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FakeRouteConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Configuration,\r
+  OUT EFI_STRING                             *Progress\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FrontPageCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  );\r
+\r
+EFI_STATUS\r
+InitializeFrontPage (\r
+  IN BOOLEAN    ReInitializeStrings\r
+  );\r
+\r
+EFI_STATUS\r
+GetProducerString (\r
+  IN      EFI_GUID                  *ProducerGuid,\r
+  IN      EFI_STRING_ID             Token,\r
+  OUT     CHAR16                    **String\r
+  );\r
+\r
+BOOLEAN\r
+TimeCompare (\r
+  IN EFI_TIME               *FirstTime,\r
+  IN EFI_TIME               *SecondTime\r
+  );\r
+\r
+VOID\r
+PlatformBdsEnterFrontPage (\r
+  IN UINT16                 TimeoutDefault,\r
+  IN BOOLEAN                ConnectAllHappened\r
+  );\r
+\r
+#endif // _FRONT_PAGE_H_\r
+\r
diff --git a/MdeModulePkg/Universal/BdsDxe/FrontPageStrings.uni b/MdeModulePkg/Universal/BdsDxe/FrontPageStrings.uni
new file mode 100644 (file)
index 0000000..b22fa5a
Binary files /dev/null and b/MdeModulePkg/Universal/BdsDxe/FrontPageStrings.uni differ
diff --git a/MdeModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr b/MdeModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr
new file mode 100644 (file)
index 0000000..e7332aa
--- /dev/null
@@ -0,0 +1,145 @@
+// *++\r
+//\r
+// Copyright (c) 2007, Intel Corporation\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution.  The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// Module Name:\r
+//\r
+//   FrontPageVfr.vfr\r
+//\r
+// Abstract:\r
+//\r
+//   Browser formset.\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+\r
+#define FORMSET_GUID  { 0x9e0c30bc, 0x3f06, 0x4ba6, 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe }\r
+\r
+#define FRONT_PAGE_CLASS               0x0000\r
+#define FRONT_PAGE_SUBCLASS            0x0002\r
+\r
+#define FRONT_PAGE_FORM_ID             0x1000\r
+\r
+#define FRONT_PAGE_ITEM_ONE            0x0001\r
+#define FRONT_PAGE_ITEM_TWO            0x0002\r
+#define FRONT_PAGE_ITEM_THREE          0x0003\r
+#define FRONT_PAGE_ITEM_FOUR           0x0004\r
+#define FRONT_PAGE_ITEM_FIVE           0x0005\r
+\r
+#define FRONT_PAGE_KEY_CONTINUE        0x1000\r
+#define FRONT_PAGE_KEY_LANGUAGE        0x1234\r
+#define FRONT_PAGE_KEY_BOOT_MANAGER    0x1064\r
+#define FRONT_PAGE_KEY_DEVICE_MANAGER  0x8567\r
+#define FRONT_PAGE_KEY_BOOT_MAINTAIN   0x9876\r
+\r
+#define LABEL_SELECT_LANGUAGE          0x1000\r
+#define LABEL_TIMEOUT                  0x2000\r
+#define LABEL_END                      0xffff\r
+\r
+formset\r
+  guid     = FORMSET_GUID,\r
+  title    = STRING_TOKEN(STR_FRONT_PAGE_TITLE),\r
+  help     = STRING_TOKEN(STR_NULL_STRING),\r
+  class    = FRONT_PAGE_CLASS,\r
+  subclass = FRONT_PAGE_SUBCLASS,\r
+\r
+  form formid = FRONT_PAGE_FORM_ID,\r
+       title  = STRING_TOKEN(STR_FRONT_PAGE_TITLE);\r
+\r
+    banner\r
+      title = STRING_TOKEN(STR_FRONT_PAGE_COMPUTER_MODEL),\r
+      line  0,\r
+      align left;\r
+\r
+    banner\r
+      title = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL),\r
+      line  1,\r
+      align left;\r
+\r
+    banner\r
+      title = STRING_TOKEN(STR_FRONT_PAGE_CPU_SPEED),\r
+      line  1,\r
+      align right;\r
+\r
+    banner\r
+      title = STRING_TOKEN(STR_FRONT_PAGE_BIOS_VERSION),\r
+      line  2,\r
+      align left;\r
+\r
+    banner\r
+      title = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE),\r
+      line  2,\r
+      align right;\r
+\r
+//    banner\r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_LEFT),\r
+//      line  0,\r
+//      align left;\r
+\r
+//    banner\r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_RIGHT),\r
+//      line  0,\r
+//      align right;\r
+\r
+//    banner\r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_LEFT),\r
+//      line  1,\r
+//      align left;\r
+\r
+//    banner\r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_RIGHT),\r
+//      line  1,\r
+//      align right;\r
+\r
+//    banner\r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_2_LEFT),\r
+//      line  2,\r
+//      align left;\r
+\r
+//    banner\r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_3_LEFT),\r
+//      line  3,\r
+//      align left;\r
+\r
+    goto FRONT_PAGE_ITEM_ONE,\r
+      prompt  = STRING_TOKEN(STR_CONTINUE_PROMPT),\r
+      help    = STRING_TOKEN(STR_CONTINUE_HELP),\r
+      flags   = INTERACTIVE,\r
+      key     = FRONT_PAGE_KEY_CONTINUE;\r
+\r
+    label LABEL_SELECT_LANGUAGE;\r
+    //\r
+    // This is where we will dynamically add a OneOf type op-code to select\r
+    // Languages from the currently available choices\r
+    //\r
+    label LABEL_END;\r
+\r
+    goto FRONT_PAGE_ITEM_THREE,\r
+      prompt  = STRING_TOKEN(STR_BOOT_MANAGER),\r
+      help    = STRING_TOKEN(STR_BOOT_MANAGER_HELP),\r
+      flags   = INTERACTIVE,\r
+      key     = FRONT_PAGE_KEY_BOOT_MANAGER;\r
+\r
+    goto FRONT_PAGE_ITEM_FOUR,\r
+      prompt  = STRING_TOKEN(STR_DEVICE_MANAGER),\r
+      help    = STRING_TOKEN(STR_DEVICE_MANAGER_HELP),\r
+      flags   = INTERACTIVE,\r
+      key     = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
+\r
+    goto FRONT_PAGE_ITEM_FIVE,\r
+      prompt  = STRING_TOKEN(STR_BOOT_MAINT_MANAGER),\r
+      help    = STRING_TOKEN(STR_BOOT_MAINT_MANAGER_HELP),\r
+      flags   = INTERACTIVE,\r
+      key     = FRONT_PAGE_KEY_BOOT_MAINTAIN;\r
+\r
+  endform;\r
+\r
+endformset;\r
diff --git a/MdeModulePkg/Universal/BdsDxe/Hotkey.c b/MdeModulePkg/Universal/BdsDxe/Hotkey.c
new file mode 100644 (file)
index 0000000..ea4bbf5
--- /dev/null
@@ -0,0 +1,769 @@
+/*++\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  Hotkey.h\r
+\r
+Abstract:\r
+\r
+  Provides a way for 3rd party applications to register themselves for launch by the\r
+  Boot Manager based on hot key\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "Hotkey.h"\r
+\r
+\r
+LIST_ENTRY      mHotkeyList = INITIALIZE_LIST_HEAD_VARIABLE (mHotkeyList);\r
+BOOLEAN         mHotkeyCallbackPending = FALSE;\r
+EFI_EVENT       mHotkeyEvent;\r
+VOID            *mHotkeyRegistration;\r
+\r
+\r
+BOOLEAN\r
+IsKeyOptionValid (\r
+  IN EFI_KEY_OPTION     *KeyOption\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Check if the Key Option is valid or not.\r
+\r
+Arguments:\r
+\r
+  KeyOption    - The Hot Key Option to be checked.\r
+\r
+Returns:\r
+\r
+  TRUE         - The Hot Key Option is valid.\r
+  FALSE        - The Hot Key Option is invalid.\r
+\r
+--*/\r
+{\r
+  UINT16   BootOptionName[10];\r
+  UINT8    *BootOptionVar;\r
+  UINTN    BootOptionSize;\r
+  UINT32   Crc;\r
+\r
+  //\r
+  // Check whether corresponding Boot Option exist\r
+  //\r
+  UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", KeyOption->BootOption);\r
+  BootOptionVar = BdsLibGetVariableAndSize (\r
+                    BootOptionName,\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOptionSize\r
+                    );\r
+\r
+  if (BootOptionVar == NULL || BootOptionSize == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check CRC for Boot Option\r
+  //\r
+  gBS->CalculateCrc32 (BootOptionVar, BootOptionSize, &Crc);\r
+  FreePool (BootOptionVar);\r
+\r
+  return (BOOLEAN) ((KeyOption->BootOptionCrc == Crc) ? TRUE : FALSE);\r
+}\r
+\r
+EFI_STATUS\r
+RegisterHotkey (\r
+  IN EFI_KEY_OPTION     *KeyOption,\r
+  OUT UINT16            *KeyOptionNumber\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create Key#### for the given hotkey.\r
+\r
+Arguments:\r
+\r
+  KeyOption             - The Hot Key Option to be added.\r
+  KeyOptionNumber       - The key option number for Key#### (optional).\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS           - Register hotkey successfully.\r
+  EFI_INVALID_PARAMETER - The hotkey option is invalid.\r
+\r
+--*/\r
+{\r
+  UINT16          KeyOptionName[10];\r
+  UINT16          *KeyOrder;\r
+  UINTN           KeyOrderSize;\r
+  UINT16          *NewKeyOrder;\r
+  UINTN           Index;\r
+  UINT16          MaxOptionNumber;\r
+  UINT16          RegisterOptionNumber;\r
+  EFI_KEY_OPTION  *TempOption;\r
+  UINTN           TempOptionSize;\r
+  EFI_STATUS      Status;\r
+  UINTN           KeyOptionSize;\r
+  BOOLEAN         UpdateBootOption;\r
+\r
+  //\r
+  // Validate the given key option\r
+  //\r
+  if (!IsKeyOptionValid (KeyOption)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  KeyOptionSize = sizeof (EFI_KEY_OPTION) + GET_KEY_CODE_COUNT (KeyOption->KeyOptions.PackedValue) * sizeof (EFI_INPUT_KEY);\r
+  UpdateBootOption = FALSE;\r
+\r
+  //\r
+  // check whether HotKey conflict with keys used by Setup Browser\r
+  //\r
+\r
+  KeyOrder = BdsLibGetVariableAndSize (\r
+               VarKeyOrder,\r
+               &gEfiGlobalVariableGuid,\r
+               &KeyOrderSize\r
+               );\r
+  if (KeyOrder == NULL) {\r
+    KeyOrderSize = 0;\r
+  }\r
+\r
+  //\r
+  // Find free key option number\r
+  //\r
+  MaxOptionNumber = 0;\r
+  TempOption = NULL;\r
+  for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {\r
+    if (MaxOptionNumber < KeyOrder[Index]) {\r
+      MaxOptionNumber = KeyOrder[Index];\r
+    }\r
+\r
+    UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
+    TempOption = BdsLibGetVariableAndSize (\r
+                   KeyOptionName,\r
+                   &gEfiGlobalVariableGuid,\r
+                   &TempOptionSize\r
+                   );\r
+\r
+    if (CompareMem (TempOption, KeyOption, TempOptionSize) == 0) {\r
+      //\r
+      // Got the option, so just return\r
+      //\r
+      FreePool (TempOption);\r
+      FreePool (KeyOrder);\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    if (KeyOption->KeyOptions.PackedValue == TempOption->KeyOptions.PackedValue) {\r
+      if (GET_KEY_CODE_COUNT (KeyOption->KeyOptions.PackedValue) == 0 ||\r
+          CompareMem (\r
+            ((UINT8 *) TempOption) + sizeof (EFI_KEY_OPTION),\r
+            ((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION),\r
+            KeyOptionSize - sizeof (EFI_KEY_OPTION)\r
+            ) == 0) {\r
+          //\r
+          // Hotkey is the same but BootOption changed, need update\r
+          //\r
+          UpdateBootOption = TRUE;\r
+          break;\r
+      }\r
+    }\r
+\r
+    FreePool (TempOption);\r
+  }\r
+\r
+  if (UpdateBootOption) {\r
+    RegisterOptionNumber = KeyOrder[Index];\r
+    FreePool (TempOption);\r
+  } else {\r
+    RegisterOptionNumber = (UINT16) (MaxOptionNumber + 1);\r
+  }\r
+\r
+  if (KeyOptionNumber != NULL) {\r
+    *KeyOptionNumber = RegisterOptionNumber;\r
+  }\r
+\r
+  //\r
+  // Create variable Key####\r
+  //\r
+  UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", RegisterOptionNumber);\r
+  Status = gRT->SetVariable (\r
+                  KeyOptionName,\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  KeyOptionSize,\r
+                  KeyOption\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePool (KeyOrder);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Update the key order variable - "KeyOrder"\r
+  //\r
+  if (!UpdateBootOption) {\r
+    Index = KeyOrderSize / sizeof (UINT16);\r
+    KeyOrderSize += sizeof (UINT16);\r
+  }\r
+\r
+  NewKeyOrder = AllocatePool (KeyOrderSize);\r
+  if (NewKeyOrder == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (KeyOrder != NULL) {\r
+    CopyMem (NewKeyOrder, KeyOrder, KeyOrderSize);\r
+  }\r
+\r
+  NewKeyOrder[Index] = RegisterOptionNumber;\r
+\r
+  Status = gRT->SetVariable (\r
+                  VarKeyOrder,\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  KeyOrderSize,\r
+                  NewKeyOrder\r
+                  );\r
+\r
+  FreePool (KeyOrder);\r
+  FreePool (NewKeyOrder);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+UnregisterHotkey (\r
+  IN UINT16     KeyOptionNumber\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Delete Key#### for the given Key Option number.\r
+\r
+Arguments:\r
+\r
+  KeyOptionNumber       - Key option number for Key####\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS           - Unregister hotkey successfully.\r
+  EFI_NOT_FOUND         - No Key#### is found for the given Key Option number.\r
+\r
+--*/\r
+{\r
+  UINT16      KeyOption[10];\r
+  UINTN       Index;\r
+  EFI_STATUS  Status;\r
+  UINTN       Index2Del;\r
+  UINT16      *KeyOrder;\r
+  UINTN       KeyOrderSize;\r
+\r
+  //\r
+  // Delete variable Key####\r
+  //\r
+  UnicodeSPrint (KeyOption, sizeof (KeyOption), L"Key%04x", KeyOptionNumber);\r
+  gRT->SetVariable (\r
+         KeyOption,\r
+         &gEfiGlobalVariableGuid,\r
+         EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+         0,\r
+         NULL\r
+         );\r
+\r
+  //\r
+  // Adjust key order array\r
+  //\r
+  KeyOrder = BdsLibGetVariableAndSize (\r
+               VarKeyOrder,\r
+               &gEfiGlobalVariableGuid,\r
+               &KeyOrderSize\r
+               );\r
+  if (KeyOrder == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Index2Del = 0;\r
+  for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {\r
+    if (KeyOrder[Index] == KeyOptionNumber) {\r
+      Index2Del = Index;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index != KeyOrderSize / sizeof (UINT16)) {\r
+    //\r
+    // KeyOptionNumber found in "KeyOrder", delete it\r
+    //\r
+    for (Index = Index2Del; Index < KeyOrderSize / sizeof (UINT16) - 1; Index++) {\r
+      KeyOrder[Index] = KeyOrder[Index + 1];\r
+    }\r
+\r
+    KeyOrderSize -= sizeof (UINT16);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  VarKeyOrder,\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  KeyOrderSize,\r
+                  KeyOrder\r
+                  );\r
+\r
+  FreePool (KeyOrder);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+HotkeyCallback (\r
+  IN EFI_KEY_DATA     *KeyData\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This is the common notification function for HotKeys, it will be registered\r
+  with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.\r
+\r
+Arguments:\r
+\r
+  KeyData               - A pointer to a buffer that is filled in with the keystroke\r
+                          information for the key that was pressed.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS           - KeyData is successfully processed.\r
+\r
+--*/\r
+{\r
+  BOOLEAN            HotkeyCatched;\r
+  LIST_ENTRY         BootLists;\r
+  LIST_ENTRY         *Link;\r
+  BDS_HOTKEY_OPTION  *Hotkey;\r
+  UINT16             Buffer[10];\r
+  BDS_COMMON_OPTION  *BootOption;\r
+  UINTN              ExitDataSize;\r
+  CHAR16             *ExitData;\r
+  EFI_TPL            OldTpl;\r
+  EFI_STATUS         Status;\r
+  EFI_KEY_DATA       *HotkeyData;\r
+\r
+  if (mHotkeyCallbackPending) {\r
+    //\r
+    // When responsing to a Hotkey, ignore sequential hotkey stroke until\r
+    // the current Boot#### load option returned\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  Link = GetFirstNode (&mHotkeyList);\r
+\r
+  while (!IsNull (&mHotkeyList, Link)) {\r
+    HotkeyCatched = FALSE;\r
+    Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
+\r
+    //\r
+    // Is this Key Stroke we are waiting for?\r
+    //\r
+    HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];\r
+    if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&\r
+       (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&\r
+       ((HotkeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : 1)) {\r
+      //\r
+      // Receive an expecting key stroke\r
+      //\r
+      if (Hotkey->CodeCount > 1) {\r
+        //\r
+        // For hotkey of key combination, transit to next waiting state\r
+        //\r
+        Hotkey->WaitingKey++;\r
+\r
+        if (Hotkey->WaitingKey == Hotkey->CodeCount) {\r
+          //\r
+          // Received the whole key stroke sequence\r
+          //\r
+          HotkeyCatched = TRUE;\r
+        }\r
+      } else {\r
+        //\r
+        // For hotkey of single key stroke\r
+        //\r
+        HotkeyCatched = TRUE;\r
+      }\r
+    } else {\r
+      //\r
+      // Receive an unexpected key stroke, reset to initial waiting state\r
+      //\r
+      Hotkey->WaitingKey = 0;\r
+    }\r
+\r
+    if (HotkeyCatched) {\r
+      //\r
+      // Reset to initial waiting state\r
+      //\r
+      Hotkey->WaitingKey = 0;\r
+\r
+      //\r
+      // Launch its BootOption\r
+      //\r
+      InitializeListHead (&BootLists);\r
+\r
+      UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);\r
+      BootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
+      BootOption->BootCurrent = Hotkey->BootOptionNumber;\r
+      BdsLibConnectDevicePath (BootOption->DevicePath);\r
+\r
+      //\r
+      // Clear the screen before launch this BootOption\r
+      //\r
+      gST->ConOut->Reset (gST->ConOut, FALSE);\r
+\r
+      //\r
+      // BdsLibBootViaBootOption() is expected to be invoked at TPL level TPL_APPLICATION,\r
+      // so raise the TPL to TPL_APPLICATION first, then restore it\r
+      //\r
+      OldTpl = gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+      mHotkeyCallbackPending = TRUE;\r
+      Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
+      mHotkeyCallbackPending = FALSE;\r
+\r
+      gBS->RestoreTPL (OldTpl);\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // Call platform action to indicate the boot fail\r
+        //\r
+        BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
+        PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);\r
+      } else {\r
+        //\r
+        // Call platform action to indicate the boot success\r
+        //\r
+        BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
+        PlatformBdsBootSuccess (BootOption);\r
+      }\r
+    }\r
+\r
+    Link = GetNextNode (&mHotkeyList, Link);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+HotkeyRegisterNotify (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *SimpleTextInEx\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Register the common HotKey notify function to given SimpleTextInEx protocol instance.\r
+\r
+Arguments:\r
+\r
+  SimpleTextInEx        - Simple Text Input Ex protocol instance\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS           - Register hotkey notification function successfully.\r
+  EFI_OUT_OF_RESOURCES  - Unable to allocate necessary data structures.\r
+\r
+--*/\r
+{\r
+  UINTN              Index;\r
+  EFI_STATUS         Status;\r
+  LIST_ENTRY         *Link;\r
+  BDS_HOTKEY_OPTION  *Hotkey;\r
+\r
+  //\r
+  // Register notification function for each hotkey\r
+  //\r
+  Link = GetFirstNode (&mHotkeyList);\r
+\r
+  while (!IsNull (&mHotkeyList, Link)) {\r
+    Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
+\r
+    Index = 0;\r
+    do {\r
+      Status = SimpleTextInEx->RegisterKeyNotify (\r
+                                 SimpleTextInEx,\r
+                                 &Hotkey->KeyData[Index],\r
+                                 HotkeyCallback,\r
+                                 &Hotkey->NotifyHandle\r
+                                 );\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // some of the hotkey registry failed\r
+        //\r
+        return Status;\r
+      }\r
+      Index ++;\r
+    } while (Index < Hotkey->CodeCount);\r
+\r
+    Link = GetNextNode (&mHotkeyList, Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+HotkeyEvent (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Callback function for SimpleTextInEx protocol install events\r
+\r
+Arguments:\r
+\r
+  Standard event notification function arguments:\r
+  Event         - the event that is signaled.\r
+  Context       - not used here.\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                         Status;\r
+  UINTN                              BufferSize;\r
+  EFI_HANDLE                         Handle;\r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *SimpleTextInEx;\r
+\r
+  while (TRUE) {\r
+    BufferSize = sizeof (EFI_HANDLE);\r
+    Status = gBS->LocateHandle (\r
+                    ByRegisterNotify,\r
+                    NULL,\r
+                    mHotkeyRegistration,\r
+                    &BufferSize,\r
+                    &Handle\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // If no more notification events exist\r
+      //\r
+      return ;\r
+    }\r
+\r
+    Status = gBS->HandleProtocol (\r
+                    Handle,\r
+                    &gEfiSimpleTextInputExProtocolGuid,\r
+                    (VOID **) &SimpleTextInEx\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    HotkeyRegisterNotify (SimpleTextInEx);\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+HotkeyInsertList (\r
+  IN EFI_KEY_OPTION     *KeyOption\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Insert Key Option to hotkey list.\r
+\r
+Arguments:\r
+\r
+  KeyOption   - The Hot Key Option to be added to hotkey list.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS - Add to hotkey list success.\r
+\r
+--*/\r
+{\r
+  BDS_HOTKEY_OPTION  *HotkeyLeft;\r
+  BDS_HOTKEY_OPTION  *HotkeyRight;\r
+  UINTN              Index;\r
+  UINT32             KeyOptions;\r
+  UINT32             KeyShiftStateLeft;\r
+  UINT32             KeyShiftStateRight;\r
+  EFI_INPUT_KEY      *InputKey;\r
+  EFI_KEY_DATA       *KeyData;\r
+\r
+  HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));\r
+  if (HotkeyLeft == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;\r
+  HotkeyLeft->BootOptionNumber = KeyOption->BootOption;\r
+\r
+  KeyOptions = KeyOption->KeyOptions.PackedValue;\r
+\r
+  HotkeyLeft->CodeCount = (UINT8) GET_KEY_CODE_COUNT (KeyOptions);\r
+\r
+  //\r
+  // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState\r
+  //\r
+  KeyShiftStateRight = (KeyOptions & EFI_KEY_OPTION_SHIFT) |\r
+                       ((KeyOptions & EFI_KEY_OPTION_CONTROL) << 1) |\r
+                       ((KeyOptions & EFI_KEY_OPTION_ALT) << 2) |\r
+                       ((KeyOptions & EFI_KEY_OPTION_LOGO) << 3) |\r
+                       ((KeyOptions & (EFI_KEY_OPTION_MENU | EFI_KEY_OPTION_SYSREQ)) << 4) |\r
+                       EFI_SHIFT_STATE_VALID;\r
+\r
+  KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);\r
+\r
+  InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));\r
+\r
+  Index = 0;\r
+  KeyData = &HotkeyLeft->KeyData[0];\r
+  do {\r
+    //\r
+    // If Key CodeCount is 0, then only KeyData[0] is used;\r
+    // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used\r
+    //\r
+    KeyData->Key.ScanCode = InputKey[Index].ScanCode;\r
+    KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;\r
+    KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;\r
+\r
+    Index++;\r
+    KeyData++;\r
+  } while (Index < HotkeyLeft->CodeCount);\r
+  InsertTailList (&mHotkeyList, &HotkeyLeft->Link);\r
+\r
+  if (KeyShiftStateLeft != KeyShiftStateRight) {\r
+    //\r
+    // Need an extra hotkey for shift key on right\r
+    //\r
+    HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);\r
+    if (HotkeyRight == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    Index = 0;\r
+    KeyData = &HotkeyRight->KeyData[0];\r
+    do {\r
+      //\r
+      // Key.ScanCode and Key.UnicodeChar have already been initialized,\r
+      // only need to update KeyState.KeyShiftState\r
+      //\r
+      KeyData->KeyState.KeyShiftState = KeyShiftStateRight;\r
+\r
+      Index++;\r
+      KeyData++;\r
+    } while (Index < HotkeyRight->CodeCount);\r
+    InsertTailList (&mHotkeyList, &HotkeyRight->Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeHotkeyService (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS   - Hotkey services successfully initialized.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS      Status;\r
+  UINT32          BootOptionSupport;\r
+  UINT16          *KeyOrder;\r
+  UINTN           KeyOrderSize;\r
+  UINTN           Index;\r
+  UINT16          KeyOptionName[8];\r
+  UINTN           KeyOptionSize;\r
+  EFI_KEY_OPTION  *KeyOption;\r
+\r
+  //\r
+  // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP\r
+  //\r
+  BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;\r
+  Status = gRT->SetVariable (\r
+                  L"BootOptionSupport",\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  sizeof (UINT32),\r
+                  &BootOptionSupport\r
+                  );\r
+\r
+  //\r
+  // Get valid Key Option List from private EFI variable "KeyOrder"\r
+  //\r
+  KeyOrder = BdsLibGetVariableAndSize (\r
+               VarKeyOrder,\r
+               &gEfiGlobalVariableGuid,\r
+               &KeyOrderSize\r
+               );\r
+\r
+  if (KeyOrder == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {\r
+    UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
+    KeyOption = BdsLibGetVariableAndSize (\r
+                  KeyOptionName,\r
+                  &gEfiGlobalVariableGuid,\r
+                  &KeyOptionSize\r
+                  );\r
+\r
+    if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {\r
+      UnregisterHotkey (KeyOrder[Index]);\r
+    } else {\r
+      HotkeyInsertList (KeyOption);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Register Protocol notify for Hotkey service\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  HotkeyEvent,\r
+                  NULL,\r
+                  &mHotkeyEvent\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Register for protocol notifications on this event\r
+  //\r
+  Status = gBS->RegisterProtocolNotify (\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  mHotkeyEvent,\r
+                  &mHotkeyRegistration\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
+\r
diff --git a/MdeModulePkg/Universal/BdsDxe/Hotkey.h b/MdeModulePkg/Universal/BdsDxe/Hotkey.h
new file mode 100644 (file)
index 0000000..87059e1
--- /dev/null
@@ -0,0 +1,117 @@
+/*++\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  Hotkey.h\r
+\r
+Abstract:\r
+\r
+  Provides a way for 3rd party applications to register themselves for launch by the\r
+  Boot Manager based on hot key\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _HOTKEY_H\r
+#define _HOTKEY_H\r
+\r
+#include "Bds.h"\r
+#include "String.h"\r
+\r
+#define GET_KEY_CODE_COUNT(KeyOptions)      (((KeyOptions) & EFI_KEY_CODE_COUNT) >> 8)\r
+\r
+#define BDS_HOTKEY_OPTION_SIGNATURE EFI_SIGNATURE_32 ('B', 'd', 'K', 'O')\r
+typedef struct {\r
+  UINTN                     Signature;\r
+  LIST_ENTRY                Link;\r
+\r
+  EFI_HANDLE                NotifyHandle;\r
+  UINT16                    BootOptionNumber;\r
+  UINT8                     CodeCount;\r
+  UINT8                     WaitingKey;\r
+  EFI_KEY_DATA              KeyData[3];\r
+} BDS_HOTKEY_OPTION;\r
+\r
+#define BDS_HOTKEY_OPTION_FROM_LINK(a) CR (a, BDS_HOTKEY_OPTION, Link, BDS_HOTKEY_OPTION_SIGNATURE)\r
+\r
+#define VarKeyOrder       L"KeyOrder"\r
+\r
+EFI_STATUS\r
+RegisterHotkey (\r
+  IN EFI_KEY_OPTION     *KeyOption,\r
+  OUT UINT16            *KeyOptionNumber\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create Key#### for the given hotkey.\r
+\r
+Arguments:\r
+\r
+  KeyOption             - The Hot Key Option to be added.\r
+  KeyOptionNumber       - The key option number for Key#### (optional).\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS           - Register hotkey successfully.\r
+  EFI_INVALID_PARAMETER - The hotkey option is invalid.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+UnregisterHotkey (\r
+  IN UINT16             KeyOptionNumber\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Delete Key#### for the given Key Option number.\r
+\r
+Arguments:\r
+\r
+  KeyOptionNumber       - Key option number for Key####\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS           - Unregister hotkey successfully.\r
+  EFI_NOT_FOUND         - No Key#### is found for the given Key Option number.\r
+\r
+--*/\r
+;\r
+\r
+\r
+EFI_STATUS\r
+InitializeHotkeyService (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS   - Hotkey services successfully initialized.\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.c b/MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.c
new file mode 100644 (file)
index 0000000..339361e
--- /dev/null
@@ -0,0 +1,62 @@
+/*++\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  HwErrRecSupport.c\r
+\r
+Abstract:\r
+\r
+  Set the level of support for Hardware Error Record Persistence that is\r
+  implemented by the platform.\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "HwErrRecSupport.h"\r
+\r
+VOID\r
+InitializeHwErrRecSupport (\r
+  IN UINT16       HwErrRecSupportLevel\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Set the HwErrRecSupport variable contains a binary UINT16 that supplies the\r
+    level of support for Hardware Error Record Persistence that is implemented\r
+    by the platform.\r
+\r
+  Arguments:\r
+    HwErrRecSupportLevel\r
+      zero value      - Indicates that the platform implements no support for\r
+                        Hardware Error Record Persistence.\r
+      non-zero value  - Indicates that the platform implements Hardware Error\r
+                        Record Persistence.\r
+\r
+  Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = gRT->SetVariable (\r
+                  L"HwErrRecSupport",\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                  sizeof (UINT16),\r
+                  &HwErrRecSupportLevel\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "HwErrRecSupport: Can not set the variable\n"));\r
+  }\r
+\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.h b/MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.h
new file mode 100644 (file)
index 0000000..fdd62ba
--- /dev/null
@@ -0,0 +1,53 @@
+/*++\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  HwErrRecSupport.h\r
+\r
+Abstract:\r
+\r
+  Set the level of support for Hardware Error Record Persistence that is\r
+  implemented by the platform.\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _HW_ERR_REC_SUPPORT_H\r
+#define _HW_ERR_REC_SUPPORT_H\r
+\r
+#include "Bds.h"\r
+\r
+VOID\r
+InitializeHwErrRecSupport (\r
+  IN UINT16       HwErrRecSupportLevel\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Set the HwErrRecSupport variable contains a binary UINT16 that supplies the\r
+    level of support for Hardware Error Record Persistence that is implemented\r
+    by the platform.\r
+\r
+  Arguments:\r
+    HwErrRecSupportLevel\r
+      zero value      - Indicates that the platform implements no support for\r
+                        Hardware Error Record Persistence.\r
+      non-zero value  - Indicates that the platform implements Hardware Error\r
+                        Record Persistence.\r
+\r
+  Returns:\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Universal/BdsDxe/Language.c b/MdeModulePkg/Universal/BdsDxe/Language.c
new file mode 100644 (file)
index 0000000..8a99e9b
--- /dev/null
@@ -0,0 +1,420 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  Language.c\r
+\r
+Abstract:\r
+\r
+  Language settings\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "Language.h"\r
+#include "FrontPage.h"\r
+\r
+#define NARROW_GLYPH_NUMBER 8\r
+#define WIDE_GLYPH_NUMBER   75\r
+\r
+EFI_GUID  mFontPackageGuid = {\r
+  0x78941450, 0x90ab, 0x4fb1, {0xb7, 0x5f, 0x58, 0x92, 0x14, 0xe2, 0x4a, 0xc}\r
+};\r
+\r
+typedef struct {\r
+  //\r
+  // This 4-bytes total array length is required by PreparePackageList()\r
+  //\r
+  UINT32                 Length;\r
+\r
+  //\r
+  // This is the Font package definition\r
+  //\r
+  EFI_HII_PACKAGE_HEADER Header;\r
+  UINT16                 NumberOfNarrowGlyphs;\r
+  UINT16                 NumberOfWideGlyphs;\r
+  EFI_NARROW_GLYPH       NarrowArray[NARROW_GLYPH_NUMBER];\r
+  EFI_WIDE_GLYPH         WideArray[WIDE_GLYPH_NUMBER];\r
+} FONT_PACK_BIN;\r
+\r
+FONT_PACK_BIN mFontBin = {\r
+  sizeof (FONT_PACK_BIN),\r
+  {\r
+    sizeof (FONT_PACK_BIN) - sizeof (UINT32),\r
+    EFI_HII_PACKAGE_SIMPLE_FONTS,\r
+  },\r
+  NARROW_GLYPH_NUMBER,\r
+  0,\r
+  {     // Narrow Glyphs\r
+    {\r
+      0x05d0,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x4E,\r
+        0x6E,\r
+        0x62,\r
+        0x32,\r
+        0x32,\r
+        0x3C,\r
+        0x68,\r
+        0x4C,\r
+        0x4C,\r
+        0x46,\r
+        0x76,\r
+        0x72,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d1,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x78,\r
+        0x7C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x7E,\r
+        0x7E,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d2,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x78,\r
+        0x7C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x1C,\r
+        0x3E,\r
+        0x66,\r
+        0x66,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d3,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x7E,\r
+        0x7E,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d4,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x7C,\r
+        0x7E,\r
+        0x06,\r
+        0x06,\r
+        0x06,\r
+        0x06,\r
+        0x66,\r
+        0x66,\r
+        0x66,\r
+        0x66,\r
+        0x66,\r
+        0x66,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d5,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x3C,\r
+        0x3C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d6,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x38,\r
+        0x38,\r
+        0x1E,\r
+        0x1E,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x0000,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    }\r
+  }\r
+};\r
+\r
+VOID\r
+ExportFonts (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Routine to export glyphs to the HII database.  This is in addition to whatever is defined in the Graphics Console driver.\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_HANDLE                   DriverHandle;\r
+  EFI_HII_HANDLE               HiiHandle;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *PackageList;\r
+\r
+  //\r
+  // Create driver handle used by HII database\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&DriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return ;\r
+  }\r
+\r
+  PackageList = PreparePackageList (1, &mFontPackageGuid, &mFontBin);\r
+  ASSERT (PackageList != NULL);\r
+\r
+  gHiiDatabase->NewPackageList (gHiiDatabase, PackageList, DriverHandle, &HiiHandle);\r
+  FreePool (PackageList);\r
+}\r
+\r
+VOID\r
+InitializeLanguage (\r
+  BOOLEAN LangCodesSettingRequired\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Determine the current language that will be used\r
+  based on language related EFI Variables\r
+\r
+Arguments:\r
+  LangCodesSettingRequired - If required to set LangCode variable\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Size;\r
+  CHAR8       *Lang;\r
+  CHAR8       LangCode[ISO_639_2_ENTRY_SIZE];\r
+  CHAR8       *LangCodes;\r
+  CHAR8       *PlatformLang;\r
+  CHAR8       *PlatformLangCodes;\r
+  UINTN       Index;\r
+  BOOLEAN     Invalid;\r
+\r
+  ExportFonts ();\r
+\r
+  LangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLangCodes);\r
+  if (LangCodesSettingRequired) {\r
+    if (!FeaturePcdGet (PcdUefiVariableDefaultLangDepricate)) {\r
+      //\r
+      // UEFI 2.1 depricated this variable so we support turning it off\r
+      //\r
+      Status = gRT->SetVariable (\r
+                      L"LangCodes",\r
+                      &gEfiGlobalVariableGuid,\r
+                      EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                      AsciiStrLen (LangCodes),\r
+                      LangCodes\r
+                      );\r
+    }\r
+\r
+\r
+    PlatformLangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes);\r
+    Status = gRT->SetVariable (\r
+                    L"PlatformLangCodes",\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    AsciiStrSize (PlatformLangCodes),\r
+                    PlatformLangCodes\r
+                    );\r
+  }\r
+\r
+  if (!FeaturePcdGet (PcdUefiVariableDefaultLangDepricate)) {\r
+    //\r
+    // UEFI 2.1 depricated this variable so we support turning it off\r
+    //\r
+\r
+    //\r
+    // Find current LangCode from Lang NV Variable\r
+    //\r
+    Size = ISO_639_2_ENTRY_SIZE;\r
+    Status = gRT->GetVariable (\r
+                    L"Lang",\r
+                    &gEfiGlobalVariableGuid,\r
+                    NULL,\r
+                    &Size,\r
+                    &LangCode\r
+                    );\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = EFI_NOT_FOUND;\r
+      for (Index = 0; LangCodes[Index] != 0; Index += ISO_639_2_ENTRY_SIZE) {\r
+        if (CompareMem (&LangCodes[Index], LangCode, ISO_639_2_ENTRY_SIZE) == 0) {\r
+          Status = EFI_SUCCESS;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+\r
+    //\r
+    // If we cannot get language code from Lang variable,\r
+    // or LangCode cannot be found from language table,\r
+    // set the mDefaultLangCode to Lang variable.\r
+    //\r
+    if (EFI_ERROR (Status)) {\r
+      Lang = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLang);\r
+      Status = gRT->SetVariable (\r
+                      L"Lang",\r
+                      &gEfiGlobalVariableGuid,\r
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                      ISO_639_2_ENTRY_SIZE,\r
+                      Lang\r
+                      );\r
+    }\r
+  }\r
+\r
+  Invalid = FALSE;\r
+  PlatformLang = BdsLibGetVariableAndSize (L"PlatformLang", &gEfiGlobalVariableGuid, &Size);\r
+  if (PlatformLang != NULL) {\r
+    //\r
+    // Check Current PlatformLang value against PlatformLangCode. Need a library that is TBD\r
+    // Set Invalid based on state of PlatformLang.\r
+    //\r
+\r
+    FreePool (PlatformLang);\r
+  } else {\r
+    // No valid variable is set\r
+    Invalid = TRUE;\r
+  }\r
+\r
+  if (Invalid) {\r
+    PlatformLang = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLang);\r
+    Status = gRT->SetVariable (\r
+                    L"PlatformLang",\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    AsciiStrSize (PlatformLang),\r
+                    PlatformLang\r
+                    );\r
+  }\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/Language.h b/MdeModulePkg/Universal/BdsDxe/Language.h
new file mode 100644 (file)
index 0000000..586a59a
--- /dev/null
@@ -0,0 +1,47 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  Language.h\r
+\r
+Abstract:\r
+\r
+  Language setting\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _LANGUAGE_H\r
+#define _LANGUAGE_H\r
+\r
+#include "String.h"\r
+\r
+VOID\r
+InitializeLanguage (\r
+  BOOLEAN LangCodesSettingRequired\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Determine the current language that will be used\r
+  based on language related EFI Variables\r
+\r
+Arguments:\r
+  LangCodesSettingRequired - If required to set LangCode variable\r
+\r
+Returns:\r
+\r
+--*/\r
+;\r
+\r
+#endif // _LANGUAGE_H_\r
diff --git a/MdeModulePkg/Universal/BdsDxe/MemoryTest.c b/MdeModulePkg/Universal/BdsDxe/MemoryTest.c
new file mode 100644 (file)
index 0000000..b9f24e6
--- /dev/null
@@ -0,0 +1,431 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  MemoryTest.c\r
+\r
+Abstract:\r
+\r
+  Perform the platform memory test\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "String.h"\r
+\r
+//\r
+// BDS Platform Functions\r
+//\r
+EFI_STATUS\r
+PlatformBdsShowProgress (\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
+  IN CHAR16                        *Title,\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
+  IN UINTN                         Progress,\r
+  IN UINTN                         PreviousValue\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Show progress bar with title above it. It only works in Graphics mode.\r
+\r
+Arguments:\r
+\r
+  TitleForeground - Foreground color for Title.\r
+  TitleBackground - Background color for Title.\r
+  Title           - Title above progress bar.\r
+  ProgressColor   - Progress bar color.\r
+  Progress        - Progress (0-100)\r
+\r
+Returns:\r
+\r
+  EFI_STATUS      - Success update the progress bar\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                     Status;\r
+  EFI_GRAPHICS_OUTPUT_PROTOCOL   *GraphicsOutput;\r
+  EFI_UGA_DRAW_PROTOCOL          *UgaDraw;\r
+  UINT32                         SizeOfX;\r
+  UINT32                         SizeOfY;\r
+  UINT32                         ColorDepth;\r
+  UINT32                         RefreshRate;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  Color;\r
+  UINTN                          BlockHeight;\r
+  UINTN                          BlockWidth;\r
+  UINTN                          BlockNum;\r
+  UINTN                          PosX;\r
+  UINTN                          PosY;\r
+  UINTN                          Index;\r
+\r
+  if (Progress > 100) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  UgaDraw = NULL;\r
+  Status = gBS->HandleProtocol (\r
+                  gST->ConsoleOutHandle,\r
+                  &gEfiGraphicsOutputProtocolGuid,\r
+                  (VOID **) &GraphicsOutput\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    GraphicsOutput = NULL;\r
+\r
+    Status = gBS->HandleProtocol (\r
+                    gST->ConsoleOutHandle,\r
+                    &gEfiUgaDrawProtocolGuid,\r
+                    (VOID **) &UgaDraw\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  if (GraphicsOutput != NULL) {\r
+    SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+    SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
+  } else {\r
+    Status = UgaDraw->GetMode (\r
+                        UgaDraw,\r
+                        &SizeOfX,\r
+                        &SizeOfY,\r
+                        &ColorDepth,\r
+                        &RefreshRate\r
+                        );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  BlockWidth  = SizeOfX / 100;\r
+  BlockHeight = SizeOfY / 50;\r
+\r
+  BlockNum    = Progress;\r
+\r
+  PosX        = 0;\r
+  PosY        = SizeOfY * 48 / 50;\r
+\r
+  if (BlockNum == 0) {\r
+    //\r
+    // Clear progress area\r
+    //\r
+    SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+\r
+    if (GraphicsOutput != NULL) {\r
+      Status = GraphicsOutput->Blt (\r
+                          GraphicsOutput,\r
+                          &Color,\r
+                          EfiBltVideoFill,\r
+                          0,\r
+                          0,\r
+                          0,\r
+                          PosY - GLYPH_HEIGHT - 1,\r
+                          SizeOfX,\r
+                          SizeOfY - (PosY - GLYPH_HEIGHT - 1),\r
+                          SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+                          );\r
+    } else {\r
+      Status = UgaDraw->Blt (\r
+                          UgaDraw,\r
+                          (EFI_UGA_PIXEL *) &Color,\r
+                          EfiUgaVideoFill,\r
+                          0,\r
+                          0,\r
+                          0,\r
+                          PosY - GLYPH_HEIGHT - 1,\r
+                          SizeOfX,\r
+                          SizeOfY - (PosY - GLYPH_HEIGHT - 1),\r
+                          SizeOfX * sizeof (EFI_UGA_PIXEL)\r
+                          );\r
+    }\r
+  }\r
+  //\r
+  // Show progress by drawing blocks\r
+  //\r
+  for (Index = PreviousValue; Index < BlockNum; Index++) {\r
+    PosX = Index * BlockWidth;\r
+    if (GraphicsOutput != NULL) {\r
+      Status = GraphicsOutput->Blt (\r
+                          GraphicsOutput,\r
+                          &ProgressColor,\r
+                          EfiBltVideoFill,\r
+                          0,\r
+                          0,\r
+                          PosX,\r
+                          PosY,\r
+                          BlockWidth - 1,\r
+                          BlockHeight,\r
+                          (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+                          );\r
+    } else {\r
+      Status = UgaDraw->Blt (\r
+                          UgaDraw,\r
+                          (EFI_UGA_PIXEL *) &ProgressColor,\r
+                          EfiUgaVideoFill,\r
+                          0,\r
+                          0,\r
+                          PosX,\r
+                          PosY,\r
+                          BlockWidth - 1,\r
+                          BlockHeight,\r
+                          (BlockWidth) * sizeof (EFI_UGA_PIXEL)\r
+                          );\r
+    }\r
+  }\r
+\r
+  PrintXY (\r
+    (SizeOfX - StrLen (Title) * GLYPH_WIDTH) / 2,\r
+    PosY - GLYPH_HEIGHT - 1,\r
+    &TitleForeground,\r
+    &TitleBackground,\r
+    Title\r
+    );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+BdsMemoryTest (\r
+  IN EXTENDMEM_COVERAGE_LEVEL Level\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Perform the memory test base on the memory test intensive level,\r
+  and update the memory resource.\r
+\r
+Arguments:\r
+\r
+  Level  - The memory test intensive level.\r
+\r
+Returns:\r
+\r
+  EFI_STATUS      - Success test all the system memory and update\r
+                    the memory resource\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_STATUS                        InitStatus;\r
+  EFI_STATUS                        ReturnStatus;\r
+  BOOLEAN                           RequireSoftECCInit;\r
+  EFI_GENERIC_MEMORY_TEST_PROTOCOL  *GenMemoryTest;\r
+  UINT64                            TestedMemorySize;\r
+  UINT64                            TotalMemorySize;\r
+  UINTN                             TestPercent;\r
+  UINT64                            PreviousValue;\r
+  BOOLEAN                           ErrorOut;\r
+  BOOLEAN                           TestAbort;\r
+  EFI_INPUT_KEY                     Key;\r
+  CHAR16                            StrPercent[16];\r
+  CHAR16                            *StrTotalMemory;\r
+  CHAR16                            *Pos;\r
+  CHAR16                            *TmpStr;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     Foreground;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     Background;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     Color;\r
+  UINT8                             Value;\r
+  UINTN                             DataSize;\r
+  UINT32                            Attributes;\r
+  UINT32                            TempData;\r
+\r
+  ReturnStatus = EFI_SUCCESS;\r
+  ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
+\r
+  Pos = AllocatePool (128);\r
+\r
+  if (Pos == NULL) {\r
+    return ReturnStatus;\r
+  }\r
+\r
+  StrTotalMemory    = Pos;\r
+\r
+  TestedMemorySize  = 0;\r
+  TotalMemorySize   = 0;\r
+  PreviousValue     = 0;\r
+  ErrorOut          = FALSE;\r
+  TestAbort         = FALSE;\r
+\r
+  SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+  SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+  SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+\r
+  RequireSoftECCInit = FALSE;\r
+\r
+  gST->ConOut->ClearScreen (gST->ConOut);\r
+  gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
+  gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiGenericMemTestProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &GenMemoryTest\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (Pos);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  InitStatus = GenMemoryTest->MemoryTestInit (\r
+                                GenMemoryTest,\r
+                                Level,\r
+                                &RequireSoftECCInit\r
+                                );\r
+  if (InitStatus == EFI_NO_MEDIA) {\r
+    //\r
+    // The PEI codes also have the relevant memory test code to check the memory,\r
+    // it can select to test some range of the memory or all of them. If PEI code\r
+    // checks all the memory, this BDS memory test will has no not-test memory to\r
+    // do the test, and then the status of EFI_NO_MEDIA will be returned by\r
+    // "MemoryTestInit". So it does not need to test memory again, just return.\r
+    //\r
+    FreePool (Pos);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  gST->ConOut->SetCursorPosition (gST->ConOut, 0, 2);\r
+  TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST));\r
+\r
+  if (TmpStr != NULL) {\r
+    gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
+    FreePool (TmpStr);\r
+  }\r
+\r
+  do {\r
+    Status = GenMemoryTest->PerformMemoryTest (\r
+                              GenMemoryTest,\r
+                              &TestedMemorySize,\r
+                              &TotalMemorySize,\r
+                              &ErrorOut,\r
+                              TestAbort\r
+                              );\r
+    if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {\r
+      TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR));\r
+      if (TmpStr != NULL) {\r
+        PrintXY (10, 10, NULL, NULL, TmpStr);\r
+        gST->ConOut->SetCursorPosition (gST->ConOut, 0, 4);\r
+        gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
+        FreePool (TmpStr);\r
+      }\r
+\r
+      ASSERT (0);\r
+    }\r
+\r
+    TempData = (UINT32) DivU64x32 (TotalMemorySize, 16);\r
+    TestPercent = (UINTN) DivU64x32 (\r
+                            DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),\r
+                            TempData\r
+                            );\r
+    if (TestPercent != PreviousValue) {\r
+      UnicodeValueToString (StrPercent, 0, TestPercent, 0);\r
+      gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
+      TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT));\r
+      if (TmpStr != NULL) {\r
+        BdsLibOutputStrings (gST->ConOut, StrPercent, TmpStr, NULL);\r
+        FreePool (TmpStr);\r
+      }\r
+\r
+      TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
+      if (TmpStr != NULL) {\r
+        PlatformBdsShowProgress (\r
+          Foreground,\r
+          Background,\r
+          TmpStr,\r
+          Color,\r
+          TestPercent,\r
+          (UINTN) PreviousValue\r
+          );\r
+        FreePool (TmpStr);\r
+      }\r
+    }\r
+\r
+    PreviousValue = TestPercent;\r
+\r
+    if (Key.ScanCode == SCAN_ESC) {\r
+      if (!RequireSoftECCInit) {\r
+        TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
+        if (TmpStr != NULL) {\r
+          PlatformBdsShowProgress (\r
+            Foreground,\r
+            Background,\r
+            TmpStr,\r
+            Color,\r
+            100,\r
+            (UINTN) PreviousValue\r
+            );\r
+          FreePool (TmpStr);\r
+        }\r
+\r
+        gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
+        gST->ConOut->OutputString (gST->ConOut, L"100");\r
+        Status = GenMemoryTest->Finished (GenMemoryTest);\r
+        goto Done;\r
+      }\r
+\r
+      TestAbort = TRUE;\r
+    }\r
+  } while (Status != EFI_NOT_FOUND);\r
+\r
+  Status = GenMemoryTest->Finished (GenMemoryTest);\r
+\r
+Done:\r
+  UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0);\r
+  if (StrTotalMemory[0] == L',') {\r
+    StrTotalMemory++;\r
+  }\r
+\r
+  TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED));\r
+  if (TmpStr != NULL) {\r
+    StrCat (StrTotalMemory, TmpStr);\r
+    FreePool (TmpStr);\r
+  }\r
+\r
+  gST->ConOut->ClearScreen (gST->ConOut);\r
+  gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
+  gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+  gST->ConOut->OutputString (gST->ConOut, StrTotalMemory);\r
+  PlatformBdsShowProgress (\r
+    Foreground,\r
+    Background,\r
+    StrTotalMemory,\r
+    Color,\r
+    100,\r
+    (UINTN) PreviousValue\r
+    );\r
+\r
+  FreePool (Pos);\r
+\r
+  DataSize = sizeof (Value);\r
+  Status = gRT->GetVariable (\r
+                  L"BootState",\r
+                  &gEfiBootStateGuid,\r
+                  &Attributes,\r
+                  &DataSize,\r
+                  &Value\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Value = 1;\r
+    gRT->SetVariable (\r
+          L"BootState",\r
+          &gEfiBootStateGuid,\r
+          EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+          sizeof (Value),\r
+          &Value\r
+          );\r
+  }\r
+\r
+  return ReturnStatus;\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/String.c b/MdeModulePkg/Universal/BdsDxe/String.c
new file mode 100644 (file)
index 0000000..84f9f96
--- /dev/null
@@ -0,0 +1,104 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  String.c\r
+\r
+Abstract:\r
+\r
+  String support\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "Language.h"\r
+#include "FrontPage.h"\r
+\r
+EFI_HII_HANDLE gStringPackHandle;\r
+\r
+EFI_GUID mBdsStringPackGuid = {\r
+  0x7bac95d3, 0xddf, 0x42f3, 0x9e, 0x24, 0x7c, 0x64, 0x49, 0x40, 0x37, 0x9a\r
+};\r
+\r
+EFI_STATUS\r
+InitializeStringSupport (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Initialize HII global accessor for string support\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+  EFI_SUCCESS - String support initialize success.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_HANDLE                   DriverHandle;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *PackageList;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gHiiDatabase);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Create driver handle used by HII database\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&DriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  PackageList = PreparePackageList (1, &mBdsStringPackGuid, &BdsStrings);\r
+  ASSERT (PackageList != NULL);\r
+\r
+  Status = gHiiDatabase->NewPackageList (\r
+                           gHiiDatabase,\r
+                           PackageList,\r
+                           DriverHandle,\r
+                           &gStringPackHandle\r
+                           );\r
+\r
+  FreePool (PackageList);\r
+  return Status;\r
+}\r
+\r
+CHAR16 *\r
+GetStringById (\r
+  IN  EFI_STRING_ID   Id\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Get string by string id from HII Interface\r
+\r
+Arguments:\r
+  Id       - String ID.\r
+\r
+Returns:\r
+  CHAR16 * - String from ID.\r
+  NULL     - If error occurs.\r
+\r
+--*/\r
+{\r
+  CHAR16 *String;\r
+\r
+  String = NULL;\r
+  GetStringFromHandle (gStringPackHandle, Id, &String);\r
+\r
+  return String;\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/String.h b/MdeModulePkg/Universal/BdsDxe/String.h
new file mode 100644 (file)
index 0000000..14c42a9
--- /dev/null
@@ -0,0 +1,61 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  String.h\r
+\r
+Abstract:\r
+\r
+  String support\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _STRING_H_\r
+#define _STRING_H_\r
+\r
+#include "Bds.h"\r
+\r
+extern EFI_HII_HANDLE gStringPackHandle;\r
+\r
+//\r
+// This is the VFR compiler generated header file which defines the\r
+// string identifiers.\r
+//\r
+\r
+extern UINT8  BdsStrings[];\r
+\r
+//\r
+// String Definition Guid for BDS Platform\r
+//\r
+#define EFI_BDS_PLATFORM_GUID \\r
+  { \\r
+    0x7777E939, 0xD57E, 0x4DCB, 0xA0, 0x8E, 0x64, 0xD7, 0x98, 0x57, 0x1E, 0x0F \\r
+  }\r
+\r
+CHAR16 *\r
+GetStringById (\r
+  IN  EFI_STRING_ID   Id\r
+  );\r
+\r
+EFI_STATUS\r
+InitializeStringSupport (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+CallFrontPage (\r
+  VOID\r
+  );\r
+\r
+#endif // _STRING_H_\r
diff --git a/MdeModulePkg/Universal/BdsDxe/Strings.uni b/MdeModulePkg/Universal/BdsDxe/Strings.uni
new file mode 100644 (file)
index 0000000..c83bb8a
Binary files /dev/null and b/MdeModulePkg/Universal/BdsDxe/Strings.uni differ
index 37e816af019f1f721f9244743ba726c248fdf8c9..77a209e1e44c9d6c75b87a6a85a117a965a62ba2 100644 (file)
@@ -83,10 +83,19 @@ GRAPHICS_CONSOLE_DEV        mGraphicsConsoleDevTemplate = {
     {  0,  0, 0, 0, 0, 0 }   // Mode 3\r
   },\r
   (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,\r
-  (EFI_HII_HANDLE) 0\r
+  (EFI_HII_HANDLE ) 0\r
 };\r
 \r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+EFI_HII_DATABASE_PROTOCOL   *mHiiDatabase;\r
+EFI_HII_FONT_PROTOCOL       *mHiiFont;\r
+BOOLEAN                     mFirstAccessFlag = TRUE;\r
+\r
+STATIC EFI_GUID             mFontPackageListGuid = {0xf5f219d3, 0x7006, 0x4648, 0xac, 0x8d, 0xd6, 0x1d, 0xfb, 0x7b, 0xc6, 0xad};\r
+\r
+#else\r
 EFI_HII_PROTOCOL            *mHii;\r
+#endif\r
 \r
 static CHAR16               mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };\r
 \r
@@ -194,6 +203,7 @@ GraphicsConsoleControllerDriverSupported (
   } else {\r
     goto Error;\r
   }\r
+\r
   //\r
   // Does Hii Exist?  If not, we aren't ready to run\r
   //\r
@@ -249,8 +259,6 @@ GraphicsConsoleControllerDriverStart (
 {\r
   EFI_STATUS                           Status;\r
   GRAPHICS_CONSOLE_DEV                 *Private;\r
-  EFI_HII_PACKAGES      *Package;\r
-  EFI_HII_FONT_PACK     *FontPack;\r
   UINTN                                NarrowFontSize;\r
   UINT32                               HorizontalResolution;\r
   UINT32                               VerticalResolution;\r
@@ -259,9 +267,8 @@ GraphicsConsoleControllerDriverStart (
   UINTN                                MaxMode;\r
   UINTN                                Columns;\r
   UINTN                                Rows;\r
-  UINT8                                *Location;\r
   UINT32                               ModeNumber;\r
-  \r
+\r
   ModeNumber = 0;\r
 \r
   //\r
@@ -301,17 +308,14 @@ GraphicsConsoleControllerDriverStart (
     }\r
   }\r
 \r
-  //\r
-  // Get the HII protocol. If Supported() succeeds, do we really\r
-  // need to get HII protocol again?\r
-  //\r
-  Status = EfiLocateHiiProtocol ();\r
-  if (EFI_ERROR (Status)) {\r
-    goto Error;\r
-  }\r
-\r
   NarrowFontSize  = ReturnNarrowFontSize ();\r
 \r
+#if 1\r
+  if (mFirstAccessFlag) {\r
+    HiiLibAddFontPackageToHiiDatabase (NarrowFontSize, (UINT8 *) UsStdNarrowGlyphData, &mFontPackageListGuid, &(Private->HiiHandle));\r
+    mFirstAccessFlag = FALSE;\r
+  }\r
+#else\r
   FontPack        = AllocateZeroPool (sizeof (EFI_HII_FONT_PACK) + NarrowFontSize);\r
   ASSERT (FontPack);\r
 \r
@@ -333,7 +337,7 @@ GraphicsConsoleControllerDriverStart (
   // Free the font database\r
   //\r
   FreePool (FontPack);\r
-\r
+#endif\r
   //\r
   // If the current mode information can not be retrieved, then attemp to set the default mode\r
   // of 800x600, 32 bit colot, 60 Hz refresh.\r
@@ -614,7 +618,14 @@ GraphicsConsoleControllerDriverStop (
     //\r
     // Remove the font pack\r
     //\r
+#if 1\r
+    Status = HiiLibRemovePackagesFromHiiDatabase (Private->HiiHandle);\r
+    if (!EFI_ERROR (Status)) {\r
+      mFirstAccessFlag = TRUE;\r
+    }\r
+#else    \r
     mHii->RemovePack (mHii, Private->HiiHandle);\r
+#endif\r
 \r
     //\r
     // Free our instance data\r
@@ -678,7 +689,7 @@ EfiLocateHiiProtocol (
 /*++\r
 \r
   Routine Description:\r
-    Find if the HII protocol is available. If yes, locate the HII protocol\r
+    Locate HII protocols for future usage.\r
 \r
   Arguments:\r
 \r
@@ -690,6 +701,43 @@ EfiLocateHiiProtocol (
   UINTN       Size;\r
   EFI_STATUS  Status;\r
 \r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+\r
+  //\r
+  // There should only be one - so buffer size is this\r
+  //\r
+  Size = sizeof (EFI_HANDLE);\r
+\r
+  Status = gBS->LocateHandle (\r
+                  ByProtocol,\r
+                  &gEfiHiiDatabaseProtocolGuid,\r
+                  NULL,\r
+                  &Size,\r
+                  (VOID **) &Handle\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiHiiDatabaseProtocolGuid,\r
+                  (VOID **) &mHiiDatabase\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiHiiFontProtocolGuid,\r
+                  (VOID **) &mHiiFont\r
+                  );\r
+  return Status;\r
+#else\r
+\r
   //\r
   // There should only be one - so buffer size is this\r
   //\r
@@ -710,11 +758,13 @@ EfiLocateHiiProtocol (
   Status = gBS->HandleProtocol (\r
                   Handle,\r
                   &gEfiHiiProtocolGuid,\r
-                  (VOID **)&mHii\r
+                  &mHii\r
                   );\r
 \r
   return Status;\r
+#endif\r
 }\r
+\r
 //\r
 // Body of the STO functions\r
 //\r
@@ -1090,15 +1140,31 @@ GraphicsConsoleConOutTestString (
 --*/\r
 {\r
   EFI_STATUS            Status;\r
-  UINT16                GlyphWidth;\r
-  UINT32                GlyphStatus;\r
   UINT16                Count;\r
-  GLYPH_UNION           *Glyph;\r
-\r
-  GlyphStatus = 0;\r
-  Count       = 0;\r
 \r
-  while (WString[Count]) {\r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+  EFI_IMAGE_OUTPUT      *Blt = NULL;\r
+#else\r
+  UINT16                GlyphWidth;\r
+  UINT32                GlyphStatus = 0;\r
+  GLYPH_UNION           *Glyph;  \r
+#endif\r
+\r
+  Count = 0;\r
+\r
+  while (WString[Count] != 0) {\r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+    Status = mHiiFont->GetGlyph (\r
+                         mHiiFont,\r
+                         WString[Count],\r
+                         NULL,\r
+                         &Blt,\r
+                         NULL\r
+                         );\r
+    SafeFreePool (Blt);\r
+    Blt = NULL;\r
+    Count++;\r
+#else\r
     Status = mHii->GetGlyph (\r
                     mHii,\r
                     WString,\r
@@ -1107,7 +1173,7 @@ GraphicsConsoleConOutTestString (
                     &GlyphWidth,\r
                     &GlyphStatus\r
                     );\r
-\r
+#endif\r
     if (EFI_ERROR (Status)) {\r
       return EFI_UNSUPPORTED;\r
     }\r
@@ -1654,6 +1720,69 @@ GetTextColors (
   return EFI_SUCCESS;\r
 }\r
 \r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+EFI_STATUS\r
+DrawUnicodeWeightAtCursorN (\r
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
+  IN  CHAR16                        *UnicodeWeight,\r
+  IN  UINTN                         Count\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  GRAPHICS_CONSOLE_DEV              *Private;\r
+  EFI_IMAGE_OUTPUT                  *Blt;\r
+  EFI_STRING                        String;\r
+  EFI_FONT_DISPLAY_INFO             *FontInfo;\r
+\r
+  Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
+  //\r
+  // GOP protocol is required in UEFI mode.\r
+  //\r
+  ASSERT (Private->GraphicsOutput != NULL);\r
+\r
+  Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
+  if (Blt == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Blt->Width        = (UINT16) (Private->ModeData[This->Mode->Mode].GopWidth);\r
+  Blt->Height       = (UINT16) (Private->ModeData[This->Mode->Mode].GopHeight);\r
+  Blt->Image.Screen = Private->GraphicsOutput;\r
+\r
+  String = AllocateCopyPool ((Count + 1) * sizeof (CHAR16), UnicodeWeight);\r
+  if (String == NULL) {\r
+    SafeFreePool (Blt);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  *(String + Count) = 0;\r
+\r
+  FontInfo = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));\r
+  if (FontInfo == NULL) {\r
+    SafeFreePool (Blt);\r
+    SafeFreePool (String);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  GetTextColors (This, &FontInfo->ForegroundColor, &FontInfo->BackgroundColor);\r
+\r
+  Status = mHiiFont->StringToImage (\r
+                       mHiiFont,\r
+                       EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN,\r
+                       String,\r
+                       FontInfo,\r
+                       &Blt,\r
+                       This->Mode->CursorColumn * GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,\r
+                       This->Mode->CursorRow * GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,\r
+                       NULL,\r
+                       NULL,\r
+                       NULL\r
+                       );\r
+\r
+  SafeFreePool (Blt);\r
+  SafeFreePool (String);\r
+  SafeFreePool (FontInfo);\r
+  return Status;\r
+}\r
+#else\r
 STATIC\r
 EFI_STATUS\r
 DrawUnicodeWeightAtCursorN (\r
@@ -1794,6 +1923,7 @@ DrawUnicodeWeightAtCursorN (
 \r
   return ReturnStatus;\r
 }\r
+#endif\r
 \r
 STATIC\r
 EFI_STATUS\r
index f78c22c564dc02c155a18d95ed71720bd066f7b9..1c182f3b9095041a91ac239841347b462a65df0c 100644 (file)
@@ -24,7 +24,7 @@ Revision History
 #define _GRAPHICS_CONSOLE_H\r
 \r
 #include <PiDxe.h>\r
-#include <Protocol/FrameworkHii.h>\r
+//#include <Protocol/FrameworkHii.h>\r
 #include <Protocol/SimpleTextOut.h>\r
 #include <Protocol/GraphicsOutput.h>\r
 #include <Protocol/UgaDraw.h>\r
@@ -32,10 +32,17 @@ Revision History
 #include <Library/DebugLib.h>\r
 #include <Library/UefiDriverEntryPoint.h>\r
 #include <Library/UefiLib.h>\r
-#include <Library/FrameworkHiiLib.h>\r
+//#include <Library/FrameworkHiiLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/BaseLib.h>\r
+\r
+#include <MdeModuleHii.h>\r
+\r
+#include <Protocol/HiiFont.h>\r
+#include <Protocol/HiiDatabase.h>\r
 \r
 \r
 extern EFI_COMPONENT_NAME_PROTOCOL   gGraphicsConsoleComponentName;\r
@@ -174,8 +181,8 @@ GraphicsConsoleComponentNameGetControllerName (
 //\r
 // Glyph database\r
 //\r
-#define GLYPH_WIDTH   8\r
-#define GLYPH_HEIGHT  19\r
+//#define GLYPH_WIDTH   8\r
+//#define GLYPH_HEIGHT  19\r
 \r
 //\r
 // User can define valid graphic resolution here\r
@@ -306,11 +313,6 @@ GraphicsConsoleConOutEnableCursor (
   IN  BOOLEAN                          Visible\r
   );\r
 \r
-EFI_STATUS\r
-EfiLocateHiiProtocol (\r
-  VOID\r
-  );\r
-\r
 EFI_STATUS\r
 EFIAPI\r
 GraphicsConsoleControllerDriverSupported (\r
@@ -336,4 +338,11 @@ GraphicsConsoleControllerDriverStop (
   IN  EFI_HANDLE                     *ChildHandleBuffer\r
   );\r
 \r
+EFI_STATUS\r
+EfiLocateHiiProtocol (\r
+  VOID\r
+  )\r
+;\r
+\r
+\r
 #endif\r
index 013bc183895e83751217126884254e9744d67c35..4ccfe2177c10e4bcaeeb793a2b85ce1ec0bafe69 100644 (file)
@@ -21,7 +21,7 @@
   MODULE_TYPE                    = DXE_DRIVER\r
   VERSION_STRING                 = 1.0\r
   EDK_RELEASE_VERSION            = 0x00020000\r
-  EFI_SPECIFICATION_VERSION      = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x0002000A\r
 \r
   ENTRY_POINT                    = InitializeGraphicsConsole\r
 \r
@@ -43,6 +43,7 @@
 [Packages]\r
   MdePkg/MdePkg.dec\r
   # currently use Hii for glyph lookup, need to change to UEFI scheme\r
+  MdeModulePkg/MdeModulePkg.dec\r
   IntelFrameworkPkg/IntelFrameworkPkg.dec\r
 \r
 [LibraryClasses]\r
   UefiLib\r
   UefiDriverEntryPoint\r
   DebugLib\r
-  FrameworkHiiLib\r
+  HiiLib\r
 \r
 [Protocols]\r
   gEfiDevicePathProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
   gEfiSimpleTextOutProtocolGuid                 # PROTOCOL BY_START\r
-  gEfiHiiProtocolGuid                           # PROTOCOL TO_START\r
   gEfiGraphicsOutputProtocolGuid                # PROTOCOL TO_START\r
   gEfiUgaDrawProtocolGuid                       # PROTOCOL TO_START\r
+  gEfiHiiFontProtocolGuid\r
+  gEfiHiiDatabaseProtocolGuid\r
 \r
index 187cc9b4ec84ed1f9caf406c2cd7238e95b56e61..4276a2d042f70f8b99b4a3411f0b0c1d2f71b8ec 100644 (file)
@@ -65,9 +65,6 @@
     <Protocol Usage="TO_START">\r
       <ProtocolCName>gEfiGraphicsOutputProtocolGuid</ProtocolCName>\r
     </Protocol>\r
-    <Protocol Usage="TO_START">\r
-      <ProtocolCName>gEfiHiiProtocolGuid</ProtocolCName>\r
-    </Protocol>\r
     <Protocol Usage="BY_START">\r
       <ProtocolCName>gEfiSimpleTextOutProtocolGuid</ProtocolCName>\r
     </Protocol>\r
index db93c6daa123b7011669c4cc11e467eb5f696924..7055c745711fe321507d2544eb49cd3e7f2d030c 100644 (file)
@@ -2359,14 +2359,14 @@ DevPathFromTextSata (
                                 MSG_SATA_DP,\r
                                 sizeof (SATA_DEVICE_PATH)\r
                                 );\r
-  Sata->HbaPortNumber = (UINT16) Xtoi (Param1);\r
+  Sata->HBAPortNumber = (UINT16) Xtoi (Param1);\r
   if (Param3 != NULL) {\r
-    Sata->PortMultiplierPort = (UINT16) Xtoi (Param2);\r
+    Sata->PortMultiplierPortNumber = (UINT16) Xtoi (Param2);\r
     Param2                   = Param3;\r
   } else {\r
-    Sata->PortMultiplierPort = 0;\r
+    Sata->PortMultiplierPortNumber = 0;\r
   }\r
-  Sata->LogicalUnitNumber = (UINT16) Xtoi (Param2);\r
+  Sata->Lun = (UINT16) Xtoi (Param2);\r
 \r
   return (EFI_DEVICE_PATH_PROTOCOL *) Sata;\r
 }\r
index 546c4a40e3fa290d5e248738c9f9628451d86cb3..78c95737a458090ad38037d896b0284f168ba78a 100644 (file)
@@ -830,9 +830,9 @@ DevPathToTextSata (
   CatPrint (\r
     Str,\r
     L"Sata(0x%x,0x%x,0x%x)",\r
-    (UINTN) Sata->HbaPortNumber,\r
-    (UINTN) Sata->PortMultiplierPort,\r
-    (UINTN) Sata->LogicalUnitNumber\r
+    (UINTN) Sata->HBAPortNumber,\r
+    (UINTN) Sata->PortMultiplierPortNumber,\r
+    (UINTN) Sata->Lun\r
     );\r
 }\r
 \r
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c b/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
new file mode 100644 (file)
index 0000000..f18e311
--- /dev/null
@@ -0,0 +1,788 @@
+/** @file\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+  DriverSample.c\r
+\r
+Abstract:\r
+\r
+  This is an example of how a driver might export data to the HII protocol to be\r
+  later utilized by the Setup Protocol\r
+\r
+\r
+**/\r
+\r
+\r
+#include "DriverSample.h"\r
+\r
+#define DISPLAY_ONLY_MY_ITEM  0x0002\r
+\r
+EFI_GUID   mFormSetGuid = FORMSET_GUID;\r
+EFI_GUID   mInventoryGuid = INVENTORY_GUID;\r
+\r
+CHAR16     VariableName[] = L"MyIfrNVData";\r
+\r
+VOID\r
+EncodePassword (\r
+  IN  CHAR16                      *Password,\r
+  IN  UINT8                       MaxSize\r
+  )\r
+{\r
+  UINTN   Index;\r
+  UINTN   Loop;\r
+  CHAR16  *Buffer;\r
+  CHAR16  *Key;\r
+\r
+  Key     = L"MAR10648567";\r
+  Buffer  = AllocateZeroPool (MaxSize);\r
+  ASSERT (Buffer != NULL);\r
+\r
+  for (Index = 0; Key[Index] != 0; Index++) {\r
+    for (Loop = 0; Loop < (UINT8) (MaxSize / 2); Loop++) {\r
+      Buffer[Loop] = (CHAR16) (Password[Loop] ^ Key[Index]);\r
+    }\r
+  }\r
+\r
+  CopyMem (Password, Buffer, MaxSize);\r
+\r
+  gBS->FreePool (Buffer);\r
+  return ;\r
+}\r
+\r
+EFI_STATUS\r
+ValidatePassword (\r
+  DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData,\r
+  EFI_STRING_ID                   StringId\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  UINTN                           Index;\r
+  UINTN                           BufferSize;\r
+  CHAR16                          *Password;\r
+  CHAR16                          *EncodedPassword;\r
+  BOOLEAN                         OldPassword;\r
+\r
+  //\r
+  // Get encoded password first\r
+  //\r
+  BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+  Status = gRT->GetVariable (\r
+                  VariableName,\r
+                  &mFormSetGuid,\r
+                  NULL,\r
+                  &BufferSize,\r
+                  &PrivateData->Configuration\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Old password not exist, prompt for new password\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  OldPassword = FALSE;\r
+  //\r
+  // Check whether we have any old password set\r
+  //\r
+  for (Index = 0; Index < 20; Index++) {\r
+    if (PrivateData->Configuration.WhatIsThePassword2[Index] != 0) {\r
+      OldPassword = TRUE;\r
+      break;\r
+    }\r
+  }\r
+  if (!OldPassword) {\r
+    //\r
+    // Old password not exist, return EFI_SUCCESS to prompt for new password\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Get user input password\r
+  //\r
+  BufferSize = 21 * sizeof (CHAR16);\r
+  Password = AllocateZeroPool (BufferSize);\r
+  ASSERT (Password != NULL);\r
+\r
+  Status = IfrLibGetString (PrivateData->HiiHandle[0], StringId, Password, &BufferSize);\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePool (Password);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Validate old password\r
+  //\r
+  EncodedPassword = AllocateCopyPool (21 * sizeof (CHAR16), Password);\r
+  ASSERT (EncodedPassword != NULL);\r
+  EncodePassword (EncodedPassword, 20 * sizeof (CHAR16));\r
+  if (CompareMem (EncodedPassword, PrivateData->Configuration.WhatIsThePassword2, 20 * sizeof (CHAR16)) != 0) {\r
+    //\r
+    // Old password mismatch, return EFI_NOT_READY to prompt for error message\r
+    //\r
+    Status = EFI_NOT_READY;\r
+  } else {\r
+    Status = EFI_SUCCESS;\r
+  }\r
+\r
+  gBS->FreePool (Password);\r
+  gBS->FreePool (EncodedPassword);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+SetPassword (\r
+  DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData,\r
+  EFI_STRING_ID                   StringId\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  UINTN                           BufferSize;\r
+  CHAR16                          *Password;\r
+  DRIVER_SAMPLE_CONFIGURATION     *Configuration;\r
+\r
+  //\r
+  // Get Buffer Storage data from EFI variable\r
+  //\r
+  BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+  Status = gRT->GetVariable (\r
+                  VariableName,\r
+                  &mFormSetGuid,\r
+                  NULL,\r
+                  &BufferSize,\r
+                  &PrivateData->Configuration\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get user input password\r
+  //\r
+  Password = &PrivateData->Configuration.WhatIsThePassword2[0];\r
+  ZeroMem (Password, 20 * sizeof (CHAR16));\r
+  Status = IfrLibGetString (PrivateData->HiiHandle[0], StringId, Password, &BufferSize);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Retrive uncommitted data from Browser\r
+  //\r
+  BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+  Configuration = AllocateZeroPool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));\r
+  ASSERT (Configuration != NULL);\r
+  Status = GetBrowserData (&mFormSetGuid, VariableName, &BufferSize, (UINT8 *) Configuration);\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Update password's clear text in the screen\r
+    //\r
+    CopyMem (Configuration->PasswordClearText, Password, 20 * sizeof (CHAR16));\r
+\r
+    //\r
+    // Update uncommitted data of Browser\r
+    //\r
+    BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+    Status = SetBrowserData (\r
+               &mFormSetGuid,\r
+               VariableName,\r
+               BufferSize,\r
+               (UINT8 *) Configuration,\r
+               NULL\r
+               );\r
+  }\r
+  gBS->FreePool (Configuration);\r
+\r
+  //\r
+  // Set password\r
+  //\r
+  EncodePassword (Password, 20 * sizeof (CHAR16));\r
+  Status = gRT->SetVariable(\r
+                  VariableName,\r
+                  &mFormSetGuid,\r
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                  sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
+                  &PrivateData->Configuration\r
+                  );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function allows a caller to extract the current configuration for one\r
+  or more named elements from the target driver.\r
+\r
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param  Request                A null-terminated Unicode string in\r
+                                 <ConfigRequest> format.\r
+  @param  Progress               On return, points to a character in the Request\r
+                                 string. Points to the string's null terminator if\r
+                                 request was successful. Points to the most recent\r
+                                 '&' before the first failing name/value pair (or\r
+                                 the beginning of the string if the failure is in\r
+                                 the first name/value pair) if the request was not\r
+                                 successful.\r
+  @param  Results                A null-terminated Unicode string in\r
+                                 <ConfigAltResp> format which has all values filled\r
+                                 in for the names in the Request string. String to\r
+                                 be allocated by the called function.\r
+\r
+  @retval EFI_SUCCESS            The Results is filled with the requested values.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.\r
+  @retval EFI_INVALID_PARAMETER  Request is NULL, illegal syntax, or unknown name.\r
+  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this\r
+                                 driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ExtractConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Request,\r
+  OUT EFI_STRING                             *Progress,\r
+  OUT EFI_STRING                             *Results\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  UINTN                            BufferSize;\r
+  DRIVER_SAMPLE_PRIVATE_DATA       *PrivateData;\r
+  EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;\r
+\r
+  PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
+  HiiConfigRouting = PrivateData->HiiConfigRouting;\r
+\r
+  //\r
+  // Get Buffer Storage data from EFI variable\r
+  //\r
+  BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+  Status = gRT->GetVariable (\r
+                  VariableName,\r
+                  &mFormSetGuid,\r
+                  NULL,\r
+                  &BufferSize,\r
+                  &PrivateData->Configuration\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
+  //\r
+  Status = HiiConfigRouting->BlockToConfig (\r
+                                HiiConfigRouting,\r
+                                Request,\r
+                                (UINT8 *) &PrivateData->Configuration,\r
+                                BufferSize,\r
+                                Results,\r
+                                Progress\r
+                                );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function processes the results of changes in configuration.\r
+\r
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param  Configuration          A null-terminated Unicode string in <ConfigResp>\r
+                                 format.\r
+  @param  Progress               A pointer to a string filled in with the offset of\r
+                                 the most recent '&' before the first failing\r
+                                 name/value pair (or the beginning of the string if\r
+                                 the failure is in the first name/value pair) or\r
+                                 the terminating NULL if all was successful.\r
+\r
+  @retval EFI_SUCCESS            The Results is processed successfully.\r
+  @retval EFI_INVALID_PARAMETER  Configuration is NULL.\r
+  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this\r
+                                 driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RouteConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Configuration,\r
+  OUT EFI_STRING                             *Progress\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  UINTN                            BufferSize;\r
+  DRIVER_SAMPLE_PRIVATE_DATA       *PrivateData;\r
+  EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;\r
+\r
+  PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
+  HiiConfigRouting = PrivateData->HiiConfigRouting;\r
+\r
+  //\r
+  // Get Buffer Storage data from EFI variable\r
+  //\r
+  BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+  Status = gRT->GetVariable (\r
+                  VariableName,\r
+                  &mFormSetGuid,\r
+                  NULL,\r
+                  &BufferSize,\r
+                  &PrivateData->Configuration\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()\r
+  //\r
+  BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+  Status = HiiConfigRouting->ConfigToBlock (\r
+                               HiiConfigRouting,\r
+                               Configuration,\r
+                               (UINT8 *) &PrivateData->Configuration,\r
+                               &BufferSize,\r
+                               Progress\r
+                               );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Store Buffer Storage back to EFI variable\r
+  //\r
+  Status = gRT->SetVariable(\r
+                  VariableName,\r
+                  &mFormSetGuid,\r
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                  sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
+                  &PrivateData->Configuration\r
+                  );\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function processes the results of changes in configuration.\r
+\r
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param  Action                 Specifies the type of action taken by the browser.\r
+  @param  QuestionId             A unique value which is sent to the original\r
+                                 exporting driver so that it can identify the type\r
+                                 of data to expect.\r
+  @param  Type                   The type of value for the question.\r
+  @param  Value                  A pointer to the data being sent to the original\r
+                                 exporting driver.\r
+  @param  ActionRequest          On return, points to the action requested by the\r
+                                 callback function.\r
+\r
+  @retval EFI_SUCCESS            The callback successfully handled the action.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the\r
+                                 variable and its data.\r
+  @retval EFI_DEVICE_ERROR       The variable could not be saved.\r
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the\r
+                                 callback.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+{\r
+  DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData;\r
+  EFI_STATUS                      Status;\r
+  EFI_HII_UPDATE_DATA             UpdateData;\r
+  IFR_OPTION                      *IfrOptionList;\r
+\r
+  if ((Value == NULL) || (ActionRequest == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
+\r
+  switch (QuestionId) {\r
+  case 0x1234:\r
+    //\r
+    // Create dynamic page for this interactive goto\r
+    //\r
+    UpdateData.BufferSize = 0x1000;\r
+    UpdateData.Offset = 0;\r
+    UpdateData.Data = AllocatePool (0x1000);\r
+    ASSERT (UpdateData.Data != NULL);\r
+\r
+    IfrOptionList = AllocatePool (2 * sizeof (IFR_OPTION));\r
+    ASSERT (IfrOptionList != NULL);\r
+\r
+    IfrOptionList[0].Flags        = 0;\r
+    IfrOptionList[0].StringToken  = STRING_TOKEN (STR_BOOT_OPTION1);\r
+    IfrOptionList[0].Value.u8     = 1;\r
+    IfrOptionList[1].Flags        = EFI_IFR_OPTION_DEFAULT;\r
+    IfrOptionList[1].StringToken  = STRING_TOKEN (STR_BOOT_OPTION2);\r
+    IfrOptionList[1].Value.u8     = 2;\r
+\r
+    CreateActionOpCode (\r
+      0x1237,\r
+      STRING_TOKEN(STR_EXIT_TEXT),\r
+      STRING_TOKEN(STR_EXIT_TEXT),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      0,\r
+      &UpdateData\r
+      );\r
+\r
+    CreateOneOfOpCode (\r
+      0x8001,\r
+      0,\r
+      0,\r
+      STRING_TOKEN (STR_ONE_OF_PROMPT),\r
+      STRING_TOKEN (STR_ONE_OF_HELP),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      EFI_IFR_NUMERIC_SIZE_1,\r
+      IfrOptionList,\r
+      2,\r
+      &UpdateData\r
+      );\r
+\r
+    CreateOrderedListOpCode (\r
+      0x8002,\r
+      0,\r
+      0,\r
+      STRING_TOKEN (STR_BOOT_OPTIONS),\r
+      STRING_TOKEN (STR_BOOT_OPTIONS),\r
+      EFI_IFR_FLAG_RESET_REQUIRED,\r
+      0,\r
+      EFI_IFR_NUMERIC_SIZE_1,\r
+      10,\r
+      IfrOptionList,\r
+      2,\r
+      &UpdateData\r
+      );\r
+\r
+    CreateGotoOpCode (\r
+      1,\r
+      STRING_TOKEN (STR_GOTO_FORM1),\r
+      STRING_TOKEN (STR_GOTO_HELP),\r
+      0,\r
+      0x8003,\r
+      &UpdateData\r
+      );\r
+\r
+    Status = IfrLibUpdateForm (\r
+               PrivateData->HiiHandle[0],\r
+               &mFormSetGuid,\r
+               0x1234,\r
+               0x1234,\r
+               TRUE,\r
+               &UpdateData\r
+               );\r
+    gBS->FreePool (IfrOptionList);\r
+    gBS->FreePool (UpdateData.Data);\r
+    break;\r
+\r
+  case 0x1237:\r
+    //\r
+    // User press "Exit now", request Browser to exit\r
+    //\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+    break;\r
+\r
+  case 0x1238:\r
+    //\r
+    // User press "Save now", request Browser to save the uncommitted data.\r
+    //\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+    break;\r
+\r
+  case 0x2000:\r
+    //\r
+    // When try to set a new password, user will be chanlleged with old password.\r
+    // The Callback is responsible for validating old password input by user,\r
+    // If Callback return EFI_SUCCESS, it indicates validation pass.\r
+    //\r
+    switch (PrivateData->PasswordState) {\r
+    case BROWSER_STATE_VALIDATE_PASSWORD:\r
+      Status = ValidatePassword (PrivateData, Value->string);\r
+      if (Status == EFI_SUCCESS) {\r
+        PrivateData->PasswordState = BROWSER_STATE_SET_PASSWORD;\r
+      }\r
+      break;\r
+\r
+    case BROWSER_STATE_SET_PASSWORD:\r
+      Status = SetPassword (PrivateData, Value->string);\r
+      PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DriverSampleInit (\r
+  IN EFI_HANDLE                   ImageHandle,\r
+  IN EFI_SYSTEM_TABLE             *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_STATUS                      SavedStatus;\r
+  EFI_HII_PACKAGE_LIST_HEADER     *PackageList;\r
+  EFI_HII_HANDLE                  HiiHandle[2];\r
+  EFI_HANDLE                      DriverHandle[2];\r
+  DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData;\r
+  EFI_SCREEN_DESCRIPTOR           Screen;\r
+  EFI_HII_DATABASE_PROTOCOL       *HiiDatabase;\r
+  EFI_HII_STRING_PROTOCOL         *HiiString;\r
+  EFI_FORM_BROWSER2_PROTOCOL      *FormBrowser2;\r
+  EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
+  CHAR16                          *NewString;\r
+  UINTN                           BufferSize;\r
+  DRIVER_SAMPLE_CONFIGURATION     *Configuration;\r
+  BOOLEAN                         ExtractIfrDefault;\r
+\r
+  //\r
+  // Initialize the library and our protocol.\r
+  //\r
+  //@MT: EfiInitializeDriverLib (ImageHandle, SystemTable);\r
+\r
+  //\r
+  // Initialize screen dimensions for SendForm().\r
+  // Remove 3 characters from top and bottom\r
+  //\r
+  ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+  gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);\r
+\r
+  Screen.TopRow     = 3;\r
+  Screen.BottomRow  = Screen.BottomRow - 3;\r
+\r
+  //\r
+  // Initialize driver private data\r
+  //\r
+  PrivateData = AllocatePool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));\r
+  if (PrivateData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  PrivateData->Signature = DRIVER_SAMPLE_PRIVATE_SIGNATURE;\r
+\r
+  PrivateData->ConfigAccess.ExtractConfig = ExtractConfig;\r
+  PrivateData->ConfigAccess.RouteConfig = RouteConfig;\r
+  PrivateData->ConfigAccess.Callback = DriverCallback;\r
+  PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;\r
+\r
+  //\r
+  // Locate Hii Database protocol\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  PrivateData->HiiDatabase = HiiDatabase;\r
+\r
+  //\r
+  // Locate HiiString protocol\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  PrivateData->HiiString = HiiString;\r
+\r
+  //\r
+  // Locate Formbrowser2 protocol\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  PrivateData->FormBrowser2 = FormBrowser2;\r
+\r
+  //\r
+  // Locate ConfigRouting protocol\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  PrivateData->HiiConfigRouting = HiiConfigRouting;\r
+\r
+  //\r
+  // Install Config Access protocol\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&DriverHandle[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  PrivateData->DriverHandle[0] = DriverHandle[0];\r
+\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &DriverHandle[0],\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &PrivateData->ConfigAccess\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Publish our HII data\r
+  //\r
+  PackageList = PreparePackageList (\r
+                  2,\r
+                  &mFormSetGuid,\r
+                  DriverSampleStrings,\r
+                  VfrBin\r
+                  );\r
+  if (PackageList == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = HiiDatabase->NewPackageList (\r
+                          HiiDatabase,\r
+                          PackageList,\r
+                          DriverHandle[0],\r
+                          &HiiHandle[0]\r
+                          );\r
+  gBS->FreePool (PackageList);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  PrivateData->HiiHandle[0] = HiiHandle[0];\r
+\r
+  //\r
+  // Publish another Fromset\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&DriverHandle[1]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  PrivateData->DriverHandle[1] = DriverHandle[1];\r
+\r
+  PackageList = PreparePackageList (\r
+                  2,\r
+                  &mInventoryGuid,\r
+                  DriverSampleStrings,\r
+                  InventoryBin\r
+                  );\r
+  if (PackageList == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = HiiDatabase->NewPackageList (\r
+                          HiiDatabase,\r
+                          PackageList,\r
+                          DriverHandle[1],\r
+                          &HiiHandle[1]\r
+                          );\r
+  gBS->FreePool (PackageList);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  PrivateData->HiiHandle[1] = HiiHandle[1];\r
+\r
+  //\r
+  // Very simple example of how one would update a string that is already\r
+  // in the HII database\r
+  //\r
+  NewString = L"700 Mhz";\r
+\r
+  Status = IfrLibSetString (HiiHandle[0], STRING_TOKEN (STR_CPU_STRING2), NewString);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Initialize configuration data\r
+  //\r
+  Configuration = &PrivateData->Configuration;\r
+  ZeroMem (Configuration, sizeof (DRIVER_SAMPLE_CONFIGURATION));\r
+\r
+  //\r
+  // Try to read NV config EFI variable first\r
+  //\r
+  ExtractIfrDefault = TRUE;\r
+  BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+  Status = gRT->GetVariable (VariableName, &mFormSetGuid, NULL, &BufferSize, Configuration);\r
+  if (!EFI_ERROR (Status) && (BufferSize == sizeof (DRIVER_SAMPLE_CONFIGURATION))) {\r
+    ExtractIfrDefault = FALSE;\r
+  }\r
+\r
+  if (ExtractIfrDefault) {\r
+    //\r
+    // EFI variable for NV config doesn't exit, we should build this variable\r
+    // based on default values stored in IFR\r
+    //\r
+    BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+    Status = ExtractDefault (Configuration, &BufferSize, 1, VfrMyIfrNVDataDefault0000);\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      gRT->SetVariable(\r
+             VariableName,\r
+             &mFormSetGuid,\r
+             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+             sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
+             Configuration\r
+             );\r
+    }\r
+  }\r
+\r
+  //\r
+  // Example of how to display only the item we sent to HII\r
+  //\r
+  if (DISPLAY_ONLY_MY_ITEM == 0x0001) {\r
+    //\r
+    // Have the browser pull out our copy of the data, and only display our data\r
+    //\r
+    //    Status = FormConfig->SendForm (FormConfig, TRUE, HiiHandle, NULL, NULL, NULL, &Screen, NULL);\r
+    //\r
+    Status = FormBrowser2->SendForm (\r
+                             FormBrowser2,\r
+                             HiiHandle,\r
+                             1,\r
+                             NULL,\r
+                             0,\r
+                             NULL,\r
+                             NULL\r
+                             );\r
+    SavedStatus = Status;\r
+\r
+    Status = HiiDatabase->RemovePackageList (HiiDatabase, HiiHandle[0]);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = HiiDatabase->RemovePackageList (HiiDatabase, HiiHandle[1]);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    return SavedStatus;\r
+  } else {\r
+    //\r
+    // Have the browser pull out all the data in the HII Database and display it.\r
+    //\r
+    //    Status = FormConfig->SendForm (FormConfig, TRUE, 0, NULL, NULL, NULL, NULL, NULL);\r
+    //\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.h b/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.h
new file mode 100644 (file)
index 0000000..9f19258
--- /dev/null
@@ -0,0 +1,97 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+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.
+
+Module Name:
+
+  DriverSample.h
+
+Abstract:
+
+
+Revision History
+
+
+**/
+
+#ifndef _DRIVER_SAMPLE_H
+#define _DRIVER_SAMPLE_H
+
+#include <PiDxe.h>
+
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/FormBrowser2.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/IfrSupportLib.h>
+#include <Library/HiiLib.h>
+
+#include <MdeModuleHii.h>
+
+
+#include "NVDataStruc.h"
+
+//
+// This is the generated <AltResp> for defaults defined in VFR
+//
+extern UINT8 VfrMyIfrNVDataDefault0000[];
+
+//
+// This is the generated IFR binary data for each formset defined in VFR.
+// This data array is ready to be used as input of PreparePackageList() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8  VfrBin[];
+extern UINT8  InventoryBin[];
+
+//
+// This is the generated String package data for all .UNI files.
+// This data array is ready to be used as input of PreparePackageList() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8  DriverSampleStrings[];
+
+#define SAMPLE_STRING               L"This is an error!"
+
+#define DRIVER_SAMPLE_PRIVATE_SIGNATURE EFI_SIGNATURE_32 ('D', 'S', 'p', 's')
+
+typedef struct {
+  UINTN                            Signature;
+
+  EFI_HANDLE                       DriverHandle[2];
+  EFI_HII_HANDLE                   HiiHandle[2];
+  DRIVER_SAMPLE_CONFIGURATION      Configuration;
+  UINT8                            PasswordState;
+
+  //
+  // Consumed protocol
+  //
+  EFI_HII_DATABASE_PROTOCOL        *HiiDatabase;
+  EFI_HII_STRING_PROTOCOL          *HiiString;
+  EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;
+  EFI_FORM_BROWSER2_PROTOCOL       *FormBrowser2;
+
+  //
+  // Produced protocol
+  //
+  EFI_HII_CONFIG_ACCESS_PROTOCOL   ConfigAccess;
+} DRIVER_SAMPLE_PRIVATE_DATA;
+
+#define DRIVER_SAMPLE_PRIVATE_FROM_THIS(a)  CR (a, DRIVER_SAMPLE_PRIVATE_DATA, ConfigAccess, DRIVER_SAMPLE_PRIVATE_SIGNATURE)
+
+#endif
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf b/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
new file mode 100644 (file)
index 0000000..42a3317
--- /dev/null
@@ -0,0 +1,72 @@
+#/** @file\r
+# Component name for module DriverSample\r
+#\r
+# FIX ME!\r
+# Copyright (c) 2007, Intel Corporation. All rights reserved.\r
+#\r
+#  All rights reserved. This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  \r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = DriverSample\r
+  FILE_GUID                      = FE3542FE-C1D3-4EF8-657C-8048606FF671\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x0002000A\r
+\r
+  ENTRY_POINT                    = DriverSampleInit\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+  DriverSample.c\r
+  inventorystrings.uni\r
+  NVDataStruc.h\r
+  VfrStrings.uni\r
+  DriverSample.h\r
+  Inventory.vfr\r
+  Vfr.vfr\r
+  VfrStrings.uni  \r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+  MemoryAllocationLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+  UefiRuntimeServicesTableLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  HiiLib\r
+  IfrSupportLib\r
+  BaseLib\r
+\r
+\r
+[Protocols]\r
+  gEfiHiiStringProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiHiiConfigRoutingProtocolGuid              # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiHiiConfigAccessProtocolGuid               # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiFormBrowser2ProtocolGuid                  # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiHiiDatabaseProtocolGuid                   # PROTOCOL ALWAYS_CONSUMED\r
+\r
+\r
+[Depex]\r
+  gEfiSimpleTextOutProtocolGuid AND gEfiHiiDatabaseProtocolGuid\r
+\r
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.msa b/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.msa
new file mode 100644 (file)
index 0000000..87bd7d8
--- /dev/null
@@ -0,0 +1,80 @@
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+  <MsaHeader>\r
+    <ModuleName>DriverSample</ModuleName>\r
+    <ModuleType>DXE_DRIVER</ModuleType>\r
+    <GuidValue>FE3542FE-C1D3-4EF8-657C-8048606FF671</GuidValue>\r
+    <Version>1.0</Version>\r
+    <Abstract>Component name for module DriverSample</Abstract>\r
+    <Description>FIX ME!</Description>\r
+    <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>\r
+    <License>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.</License>\r
+    <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION   0x00000052</Specification>\r
+  </MsaHeader>\r
+  <ModuleDefinitions>\r
+    <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+    <BinaryModule>false</BinaryModule>\r
+    <OutputFileBasename>DriverSample</OutputFileBasename>\r
+  </ModuleDefinitions>\r
+  <LibraryClassDefinitions>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DebugLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseMemoryLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiRuntimeServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiDriverEntryPoint</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiBootServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>MemoryAllocationLib</Keyword>\r
+    </LibraryClass>\r
+  </LibraryClassDefinitions>\r
+  <SourceFiles>\r
+    <Filename>DriverSample.h</Filename>\r
+    <Filename>VfrStrings.uni</Filename>\r
+    <Filename>NVDataStruc.h</Filename>\r
+    <Filename>inventorystrings.uni</Filename>\r
+    <Filename>DriverSample.c</Filename>\r
+    <Filename>DriverSample.dxs</Filename>\r
+  </SourceFiles>\r
+  <PackageDependencies>\r
+    <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+    <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+  </PackageDependencies>\r
+  <Protocols>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiHiiDatabaseProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiFormBrowser2ProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiHiiConfigAccessProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiHiiConfigRoutingProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiHiiStringProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+  </Protocols>\r
+  <Externs>\r
+    <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+    <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+    <Extern>\r
+      <ModuleEntryPoint>DriverSampleInit</ModuleEntryPoint>\r
+    </Extern>\r
+  </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/NVDataStruc.h b/MdeModulePkg/Universal/DriverSampleDxe/NVDataStruc.h
new file mode 100644 (file)
index 0000000..0ed3c8d
--- /dev/null
@@ -0,0 +1,64 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+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.
+
+Module Name:
+
+  NVDataStruc.h
+
+Abstract:
+
+  NVData structure used by the sample driver
+
+Revision History:
+
+
+**/
+
+#ifndef _NVDATASTRUC_H
+#define _NVDATASTRUC_H
+
+#define FORMSET_GUID \
+  { \
+    0xA04A27f4, 0xDF00, 0x4D42, 0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D \
+  }
+
+#define INVENTORY_GUID \
+  { \
+    0xb3f56470, 0x6141, 0x4621, 0x8f, 0x19, 0x70, 0x4e, 0x57, 0x7a, 0xa9, 0xe8 \
+  }
+
+#define VAR_EQ_TEST_NAME  0x100
+
+#pragma pack(1)
+typedef struct {
+  UINT16  WhatIsThePassword[20];
+  UINT16  WhatIsThePassword2[20];
+  UINT16  MyStringData[20];
+  UINT16  PasswordClearText[20];
+  UINT16  SomethingHiddenForHtml;
+  UINT8   HowOldAreYouInYearsManual;
+  UINT16  HowTallAreYouManual;
+  UINT8   HowOldAreYouInYears;
+  UINT16  HowTallAreYou;
+  UINT8   MyFavoriteNumber;
+  UINT8   TestLateCheck;
+  UINT8   TestLateCheck2;
+  UINT8   QuestionAboutTreeHugging;
+  UINT8   ChooseToActivateNuclearWeaponry;
+  UINT8   SuppressGrayOutSomething;
+  UINT8   OrderedList[8];
+  UINT8   BootOrder[8];
+  UINT8   BootOrderLarge;
+  UINT8   DynamicCheck;
+} DRIVER_SAMPLE_CONFIGURATION;
+#pragma pack()
+
+#endif
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr b/MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr
new file mode 100644 (file)
index 0000000..e88d708
--- /dev/null
@@ -0,0 +1,504 @@
+// *++\r
+//\r
+// Copyright (c) 2007, Intel Corporation\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution.  The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// Module Name:\r
+//\r
+//   Vfr.vfr\r
+//\r
+// Abstract:\r
+//\r
+//   Sample Setup formset\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+\r
+\r
+#include "NVDataStruc.h"\r
+\r
+//\r
+// Formset class used by Device Manager\r
+//\r
+#define EFI_NON_DEVICE_CLASS              0x00\r
+#define EFI_DISK_DEVICE_CLASS             0x01\r
+#define EFI_VIDEO_DEVICE_CLASS            0x02\r
+#define EFI_NETWORK_DEVICE_CLASS          0x04\r
+#define EFI_INPUT_DEVICE_CLASS            0x08\r
+#define EFI_ON_BOARD_DEVICE_CLASS         0x10\r
+#define EFI_OTHER_DEVICE_CLASS            0x20\r
+\r
+//\r
+// Formset subclass\r
+//\r
+#define EFI_SETUP_APPLICATION_SUBCLASS    0x00\r
+#define EFI_GENERAL_APPLICATION_SUBCLASS  0x01\r
+#define EFI_FRONT_PAGE_SUBCLASS           0x02\r
+#define EFI_SINGLE_USE_SUBCLASS           0x03\r
+\r
+//\r
+// EFI Variable attributes\r
+//\r
+#define EFI_VARIABLE_NON_VOLATILE       0x00000001\r
+#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002\r
+#define EFI_VARIABLE_RUNTIME_ACCESS     0x00000004\r
+#define EFI_VARIABLE_READ_ONLY          0x00000008\r
+\r
+//\r
+// NV data structure definition\r
+//\r
+typedef struct {\r
+  UINT8         Field8;\r
+  UINT16        Field16;\r
+  UINT8         OrderedList[3];\r
+} MY_DATA2;\r
+\r
+//\r
+// Labels definition\r
+//\r
+#define LABEL_1_VALUE               0x01\r
+#define LABEL_2_VALUE               0x1000\r
+#define LABEL_UPDATE_BBS            0x2222\r
+#define LABEL_END                   0x2223\r
+\r
+formset\r
+  guid     = FORMSET_GUID,\r
+  title    = STRING_TOKEN(STR_FORM_SET_TITLE),\r
+  help     = STRING_TOKEN(STR_FORM_SET_TITLE_HELP),\r
+  class    = EFI_ON_BOARD_DEVICE_CLASS,\r
+  subclass = EFI_SETUP_APPLICATION_SUBCLASS,\r
+\r
+  //\r
+  // Define a Buffer Storage (EFI_IFR_VARSTORE)\r
+  //\r
+  varstore DRIVER_SAMPLE_CONFIGURATION,     // This is the data structure type\r
+    varid = 0x1234,                         // Optional VarStore ID\r
+    name  = MyIfrNVData,                    // Define referenced name in vfr\r
+    guid  = FORMSET_GUID;                   // GUID of this buffer storage\r
+\r
+  //\r
+  // Define another Buffer Storage\r
+  //\r
+  varstore MY_DATA2,\r
+    name  = MyIfrNVData2,\r
+    guid  = FORMSET_GUID;\r
+\r
+  //\r
+  // Define a EFI variable Storage (EFI_IFR_VARSTORE_EFI)\r
+  //\r
+  efivarstore MyEfiVar,                           // Define referenced name in vfr\r
+    attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS,  // EFI variable attribures\r
+    name      = STRING_TOKEN(STR_VAR_NAME),       // EFI variable name\r
+    varsize   = 1,                                // Size of the EFI variable\r
+    guid      = FORMSET_GUID;                     // EFI variable GUID\r
+\r
+  //\r
+  // Define a Form (EFI_IFR_FORM)\r
+  //\r
+  form formid = 1,                                // Form ID\r
+       title  = STRING_TOKEN(STR_FORM1_TITLE);    // Form title\r
+\r
+    subtitle text = STRING_TOKEN(STR_SUBTITLE_TEXT);\r
+\r
+    subtitle text = STRING_TOKEN(STR_SUBTITLE_TEXT2);\r
+\r
+    //\r
+    // Define a display only text (EFI_IFR_TEXT)\r
+    //\r
+    text\r
+      help   = STRING_TOKEN(STR_TEXT_HELP),       // Help string\r
+      text   = STRING_TOKEN(STR_CPU_STRING),      // Prompt string\r
+        text   = STRING_TOKEN(STR_CPU_STRING2);   // TextTwo\r
+\r
+    text\r
+      help   = STRING_TOKEN(STR_EXIT_TEXT),\r
+      text   = STRING_TOKEN(STR_EXIT_TEXT),\r
+        text   = STRING_TOKEN(STR_EXIT_TEXT),\r
+      flags  = INTERACTIVE,\r
+      key    = 0x1237;\r
+\r
+    text\r
+      help   = STRING_TOKEN(STR_SAVE_TEXT),\r
+      text   = STRING_TOKEN(STR_SAVE_TEXT),\r
+        text   = STRING_TOKEN(STR_SAVE_TEXT),\r
+      flags  = INTERACTIVE,\r
+      key    = 0x1238;\r
+\r
+    //\r
+    // Define oneof (EFI_IFR_ONE_OF)\r
+    //\r
+    oneof varid   = MyIfrNVData.SuppressGrayOutSomething,    // Use "DataStructure.Member" to reference Buffer Storage\r
+      prompt      = STRING_TOKEN(STR_ONE_OF_PROMPT),\r
+      help        = STRING_TOKEN(STR_ONE_OF_HELP),\r
+      //\r
+      // Define an option (EFI_IFR_ONE_OF_OPTION)\r
+      //\r
+      option text = STRING_TOKEN(STR_ONE_OF_TEXT4), value = 0x0, flags = 0;\r
+      option text = STRING_TOKEN(STR_ONE_OF_TEXT5), value = 0x1, flags = 0;\r
+      //\r
+      // DEFAULT indicate this option will be marked with EFI_IFR_OPTION_DEFAULT\r
+      //\r
+      option text = STRING_TOKEN(STR_ONE_OF_TEXT6), value = 0x2, flags = DEFAULT;\r
+    endoneof;\r
+\r
+    oneof varid  = MyIfrNVData.BootOrderLarge,\r
+      prompt      = STRING_TOKEN(STR_ONE_OF_PROMPT),\r
+      help        = STRING_TOKEN(STR_ONE_OF_HELP),\r
+      option text = STRING_TOKEN(STR_BOOT_ORDER1), value = 0x0, flags = 0;\r
+      option text = STRING_TOKEN(STR_BOOT_ORDER2), value = 0x1, flags = DEFAULT;\r
+    endoneof;\r
+\r
+    grayoutif  ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1;\r
+      suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x0;\r
+\r
+        checkbox varid   = MyIfrNVData.ChooseToActivateNuclearWeaponry,\r
+                 prompt   = STRING_TOKEN(STR_CHECK_BOX_PROMPT),\r
+                 help     = STRING_TOKEN(STR_CHECK_BOX_HELP),\r
+                 //\r
+                 // CHECKBOX_DEFAULT indicate this checkbox is marked with EFI_IFR_CHECKBOX_DEFAULT\r
+                 //\r
+                 flags    = CHECKBOX_DEFAULT,\r
+                 key      = 0,\r
+\r
+        endcheckbox;\r
+      endif;\r
+       endif;\r
+\r
+    //\r
+    // Ordered list:\r
+    //   sizeof(MyIfrNVData) storage must be UINT8 array, and\r
+    //   size written for the variable must be size of the entire\r
+    //   variable.\r
+    //\r
+    //\r
+    suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x0;\r
+\r
+      //\r
+      // label is defined as an anchor where you want to insert some dynamic\r
+      // opcodes created on-the-fly\r
+      //\r
+      label LABEL_UPDATE_BBS;\r
+\r
+      orderedlist\r
+                varid       = MyIfrNVData.BootOrder,\r
+                prompt      = STRING_TOKEN(STR_BOOT_OPTIONS),\r
+                help        = STRING_TOKEN(STR_NULL_STRING),\r
+                option text = STRING_TOKEN(STR_BOOT_OPTION2), value = 2, flags = RESET_REQUIRED;\r
+                option text = STRING_TOKEN(STR_BOOT_OPTION1), value = 1, flags = RESET_REQUIRED;\r
+                option text = STRING_TOKEN(STR_BOOT_OPTION3), value = 3, flags = RESET_REQUIRED;\r
+              suppressif ideqval MyIfrNVData.BootOrderLarge == 0;\r
+                option text = STRING_TOKEN(STR_BOOT_OPTION4), value = 4, flags = 0;\r
+              endif\r
+      endlist;\r
+\r
+      //\r
+      // label should be paired with each other\r
+      //\r
+      label LABEL_END;\r
+\r
+    endif;    // end suppressif\r
+\r
+    suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x2;\r
+      orderedlist\r
+        varid       = MyIfrNVData.OrderedList,\r
+        prompt      = STRING_TOKEN(STR_TEST_OPCODE),\r
+        help        = STRING_TOKEN(STR_TEXT_HELP),\r
+        option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 3, flags = RESET_REQUIRED;\r
+        option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 2, flags = RESET_REQUIRED;\r
+        option text = STRING_TOKEN(STR_ONE_OF_TEXT3), value = 1, flags = RESET_REQUIRED;\r
+      endlist;\r
+    endif;\r
+\r
+    label 100;\r
+\r
+    //\r
+    // Define a hyperlink (EFI_IFR_REF)\r
+    //\r
+    goto 0x1234,                                  // Destination Form ID\r
+      prompt  = STRING_TOKEN(STR_GOTO_DYNAMIC),   // Prompt string\r
+      help    = STRING_TOKEN(STR_GOTO_HELP),      // Help string\r
+      flags   = INTERACTIVE,                      // INTERACTIVE indicate it's marked with EFI_IFR_FLAG_CALLBACK\r
+      key     = 0x1234;                           // Question ID which will be passed-in in COnfigAccess.Callback()\r
+\r
+    goto 0x1234,\r
+      prompt  = STRING_TOKEN(STR_GOTO_DYNAMIC2),\r
+      help    = STRING_TOKEN(STR_GOTO_HELP),\r
+      flags   = INTERACTIVE,\r
+      key     = 0x1235;\r
+\r
+    oneof varid  = MyIfrNVData.TestLateCheck,\r
+      prompt      = STRING_TOKEN(STR_TEST_OPCODE),\r
+      help        = STRING_TOKEN(STR_ONE_OF_HELP),\r
+      option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = RESET_REQUIRED;\r
+      option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = DEFAULT | RESET_REQUIRED;\r
+\r
+    endoneof;\r
+\r
+    oneof varid  = MyIfrNVData.TestLateCheck2,\r
+      prompt      = STRING_TOKEN(STR_TEST_OPCODE2),\r
+      help        = STRING_TOKEN(STR_ONE_OF_HELP),\r
+      option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = DEFAULT | RESET_REQUIRED;\r
+      option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = RESET_REQUIRED;\r
+\r
+      inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),\r
+        ideqid MyIfrNVData.TestLateCheck == MyIfrNVData.TestLateCheck2\r
+      endif\r
+\r
+    endoneof;\r
+\r
+    oneof varid  = MyIfrNVData.QuestionAboutTreeHugging,\r
+      prompt      = STRING_TOKEN(STR_ONE_OF_PROMPT),\r
+      help        = STRING_TOKEN(STR_ONE_OF_HELP),\r
+      option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = RESET_REQUIRED;\r
+      option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = DEFAULT | RESET_REQUIRED;\r
+      option text = STRING_TOKEN(STR_ONE_OF_TEXT3), value = 0x03, flags = RESET_REQUIRED;\r
+\r
+    endoneof;\r
+\r
+    //\r
+    // Define a string (EFI_IFR_STRING)\r
+    //\r
+    string    varid    = MyIfrNVData.MyStringData,\r
+              prompt   = STRING_TOKEN(STR_MY_STRING_PROMPT2),\r
+              help     = STRING_TOKEN(STR_MY_STRING_HELP2),\r
+              flags    = INTERACTIVE,\r
+              key      = 0x1236,\r
+              minsize  = 6,\r
+              maxsize  = 20,\r
+    endstring;\r
+\r
+    //\r
+    // Define a numeric (EFI_IFR_NUMERIC)\r
+    //\r
+    numeric varid   = MyIfrNVData.HowOldAreYouInYearsManual,\r
+            prompt  = STRING_TOKEN(STR_NUMERIC_READONLY_PROMPT),\r
+            help    = STRING_TOKEN(STR_NUMERIC_HELP0),\r
+            flags   = READ_ONLY,  // READ_ONLY indicate it's marked with EFI_IFR_FLAG_READ_ONLY\r
+            minimum = 0,\r
+            maximum = 0xf0,\r
+            step    = 0,          // Stepping of 0 equates to a manual entering\r
+                                  // of a value, otherwise it will be adjusted by "+"/"-"\r
+            default = 20,\r
+\r
+    endnumeric;\r
+\r
+    numeric varid   = MyIfrNVData.HowOldAreYouInYearsManual,\r
+            prompt  = STRING_TOKEN(STR_NUMERIC_MANUAL_PROMPT),\r
+            help    = STRING_TOKEN(STR_NUMERIC_HELP0),\r
+            minimum = 0,\r
+            maximum = 0xf0,\r
+            step    = 0,\r
+            default = 21,\r
+\r
+            inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),\r
+              ideqval MyIfrNVData.HowOldAreYouInYearsManual == 99\r
+              OR\r
+              ideqid  MyIfrNVData.HowOldAreYouInYearsManual == MyEfiVar\r
+              OR\r
+              ideqvallist MyIfrNVData.HowOldAreYouInYearsManual == 1 3 5 7\r
+            endif\r
+\r
+    endnumeric;\r
+\r
+    numeric varid   = MyEfiVar,                           // Reference of EFI variable storage\r
+            prompt  = STRING_TOKEN(STR_TALL_HEX_PROMPT),\r
+            help    = STRING_TOKEN(STR_NUMERIC_HELP1),\r
+            flags   = DISPLAY_UINT_HEX,                   // Display in HEX format (if not specified, default is in decimal format)\r
+            minimum = 0,\r
+            maximum = 250,\r
+            default = 175,\r
+\r
+    endnumeric;\r
+\r
+    label LABEL_1_VALUE;\r
+    label LABEL_2_VALUE;\r
+\r
+    grayoutif  ideqval MyIfrNVData.HowOldAreYouInYearsManual == 23 AND ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1;\r
+      numeric varid   = MyIfrNVData.HowOldAreYouInYears,\r
+              prompt  = STRING_TOKEN(STR_NUMERIC_STEP_PROMPT),\r
+              help    = STRING_TOKEN(STR_NUMERIC_HELP2),\r
+              minimum = 0,\r
+              maximum = 243,\r
+              step    = 1,\r
+              default = 18,\r
+      \r
+      endnumeric;\r
+    endif;\r
+\r
+    //\r
+    // Non-interactive password, validate by Setup Browser\r
+    //\r
+    password  varid    = MyIfrNVData.WhatIsThePassword,\r
+              prompt   = STRING_TOKEN(STR_PASSWORD_PROMPT),\r
+              help     = STRING_TOKEN(STR_PASSWORD_HELP),\r
+              minsize  = 6,\r
+              maxsize  = 20, // new opcode\r
+    endpassword;\r
+\r
+    string    varid    = MyIfrNVData.PasswordClearText,\r
+              prompt   = STRING_TOKEN(STR_MY_STRING_PROMPT),\r
+              help     = STRING_TOKEN(STR_MY_STRING_HELP),\r
+              minsize  = 6,\r
+              maxsize  = 0x14,\r
+    endstring;\r
+\r
+    //\r
+    // Interactive password, validate via ConfigAccess.Callback()\r
+    //\r
+    password  varid    = MyIfrNVData.WhatIsThePassword2,\r
+              prompt   = STRING_TOKEN(STR_PASSWORD_CALLBACK_PROMPT),\r
+              help     = STRING_TOKEN(STR_PASSWORD_HELP),\r
+              flags    = INTERACTIVE,\r
+              key      = 0x2000,\r
+              minsize  = 6,\r
+              maxsize  = 20, // new opcode\r
+    endpassword;\r
+\r
+    goto 2,\r
+      prompt = STRING_TOKEN(STR_GOTO_FORM2), //SecondSetupPage  // this too has no end-op and basically it's a jump to a form ONLY\r
+      help   = STRING_TOKEN(STR_GOTO_HELP);\r
+\r
+    goto 3,\r
+      prompt = STRING_TOKEN(STR_GOTO_FORM3), //ThirdSetupPage  // this too has no end-op and basically it's a jump to a form ONLY\r
+      help   = STRING_TOKEN(STR_GOTO_HELP);\r
+\r
+  endform;\r
+\r
+  form formid = 2,               // SecondSetupPage,\r
+    title = STRING_TOKEN(STR_FORM2_TITLE);  // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code\r
+\r
+\r
+    date    year varid  = Date.Year,    // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from\r
+            prompt      = STRING_TOKEN(STR_DATE_PROMPT),\r
+            help        = STRING_TOKEN(STR_DATE_YEAR_HELP),\r
+            minimum     = 1998,\r
+            maximum     = 2099,\r
+            step        = 1,\r
+            default     = 2004,\r
+\r
+            month varid = Date.Month,    // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from\r
+            prompt      = STRING_TOKEN(STR_DATE_PROMPT),\r
+            help        = STRING_TOKEN(STR_DATE_MONTH_HELP),\r
+            minimum     = 1,\r
+            maximum     = 12,\r
+            step        = 1,\r
+            default     = 1,\r
+\r
+            day varid   = Date.Day,          // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from\r
+            prompt      = STRING_TOKEN(STR_DATE_PROMPT),\r
+            help        = STRING_TOKEN(STR_DATE_DAY_HELP),\r
+            minimum     = 1,\r
+            maximum     = 31,\r
+            step        = 0x1,\r
+            default     = 1,\r
+\r
+      inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),\r
+        ideqval Date.Day == 31\r
+        AND\r
+        ideqvallist Date.Month == 2 4 6 9 11\r
+      endif\r
+\r
+      //\r
+      // If the day is 30 AND month is 2\r
+      //\r
+      inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),\r
+        ideqval Date.Day == 30\r
+        AND\r
+        ideqval Date.Month == 2\r
+      endif\r
+\r
+      //\r
+      // If the day is 29 AND month is 2 AND it year is NOT a leapyear\r
+      //\r
+      inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),\r
+        ideqval Date.Day == 0x1D\r
+        AND\r
+        ideqval Date.Month == 2\r
+        AND\r
+        NOT\r
+        ideqvallist Date.Year == 2004 2008 20012 20016 2020 2024 2028 2032 2036\r
+      endif\r
+\r
+    enddate;\r
+\r
+    time    hour varid  = Time.Hours,         // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from\r
+            prompt      = STRING_TOKEN(STR_TIME_PROMPT),\r
+            help        = STRING_TOKEN(STR_TIME_HOUR_HELP),\r
+            minimum     = 0,\r
+            maximum     = 23,\r
+            step        = 1,\r
+            default     = 0,\r
+\r
+            minute varid  = Time.Minutes,       // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from\r
+            prompt        = STRING_TOKEN(STR_TIME_PROMPT),\r
+            help          = STRING_TOKEN(STR_TIME_MINUTE_HELP),\r
+            minimum       = 0,\r
+            maximum       = 59,\r
+            step          = 1,\r
+            default       = 0,\r
+\r
+            second varid  = Time.Seconds,       // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from\r
+            prompt        = STRING_TOKEN(STR_TIME_PROMPT),\r
+            help          = STRING_TOKEN(STR_TIME_SECOND_HELP),\r
+            minimum       = 0,\r
+            maximum       = 59,\r
+            step          = 1,\r
+            default       = 0,\r
+\r
+    endtime;\r
+\r
+    checkbox varid   = MyIfrNVData.ChooseToActivateNuclearWeaponry,\r
+            prompt   = STRING_TOKEN(STR_CHECK_BOX_PROMPT),\r
+            help     = STRING_TOKEN(STR_CHECK_BOX_HELP),\r
+            flags    = CHECKBOX_DEFAULT,\r
+            key      = 0,\r
+    endcheckbox;\r
+\r
+    text\r
+      help = STRING_TOKEN(STR_TEXT_HELP),\r
+      text = STRING_TOKEN(STR_TEXT_TEXT_1);\r
+\r
+    text\r
+      help   = STRING_TOKEN(STR_TEXT_HELP),\r
+      text   = STRING_TOKEN(STR_TEXT_TEXT_1),\r
+      text   = STRING_TOKEN(STR_TEXT_TEXT_2);\r
+\r
+    goto 1,\r
+      prompt = STRING_TOKEN(STR_GOTO_FORM1), //MainSetupPage  // this too has no end-op and basically it's a jump to a form ONLY\r
+      help   = STRING_TOKEN(STR_GOTO_HELP);\r
+\r
+  endform;\r
+\r
+  form formid = 3, title = STRING_TOKEN(STR_FORM3_TITLE);  // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code\r
+\r
+    grayoutif  ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1;\r
+      text\r
+        help = STRING_TOKEN(STR_TEXT_HELP),\r
+        text = STRING_TOKEN(STR_TEXT_TEXT_1);\r
+    endif;\r
+\r
+  endform;\r
+\r
+  form formid = 4, title = STRING_TOKEN(STR_FORM3_TITLE);\r
+\r
+  endform;\r
+\r
+  form formid = 0x1234,            // Dynamically created page,\r
+       title = STRING_TOKEN(STR_DYNAMIC_TITLE);  // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code\r
+\r
+    label 0x1234;\r
+    //\r
+    // This is where we will insert dynamic created opcodes\r
+    //\r
+    label LABEL_END;\r
+\r
+  endform;\r
+\r
+endformset;\r
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/VfrStrings.uni b/MdeModulePkg/Universal/DriverSampleDxe/VfrStrings.uni
new file mode 100644 (file)
index 0000000..fb72d1a
Binary files /dev/null and b/MdeModulePkg/Universal/DriverSampleDxe/VfrStrings.uni differ
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/inventory.vfr b/MdeModulePkg/Universal/DriverSampleDxe/inventory.vfr
new file mode 100644 (file)
index 0000000..79dcf18
--- /dev/null
@@ -0,0 +1,121 @@
+// *++\r
+//\r
+// Copyright (c) 2007, Intel Corporation\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution.  The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// Module Name:\r
+//\r
+//   Inventory.vfr\r
+//\r
+// Abstract:\r
+//\r
+//   Sample Inventory Data.\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+\r
+#define INVENTORY_GUID    { 0xb3f56470, 0x6141, 0x4621, 0x8f, 0x19, 0x70, 0x4e, 0x57, 0x7a, 0xa9, 0xe8 }\r
+\r
+formset\r
+  guid     = INVENTORY_GUID,\r
+  title    = STRING_TOKEN(STR_INV_FORM_SET_TITLE),\r
+  help     = STRING_TOKEN(STR_INV_FORM_SET_HELP),\r
+  class    = 0x04,\r
+  subclass = 0x03,\r
+\r
+  form formid = 1,\r
+       title  = STRING_TOKEN(STR_INV_FORM1_TITLE);  // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code\r
+\r
+       text\r
+      help   = STRING_TOKEN(STR_INV_VERSION_HELP),\r
+      text   = STRING_TOKEN(STR_INV_VERSION_TEXT),\r
+           text   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      flags  = 0,\r
+      key    = 0;\r
+\r
+       text\r
+      help   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      text   = STRING_TOKEN(STR_INV_VERSION_TEXT2),\r
+           text   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      flags  = 0,\r
+      key    = 0;\r
+\r
+       text\r
+      help   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      text   = STRING_TOKEN(STR_INV_VERSION_TEXT3),\r
+           text   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      flags  = 0,\r
+      key    = 0;\r
+\r
+       text\r
+      help   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      text   = STRING_TOKEN(STR_INV_VERSION_TEXT4),\r
+           text   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      flags  = 0,\r
+      key    = 0;\r
+\r
+    subtitle text = STRING_TOKEN(STR_INV_EMPTY_STRING);\r
+\r
+       text\r
+      help   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      text   = STRING_TOKEN(STR_INV_VERSION_TEXT5),\r
+           text   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      flags  = 0,\r
+      key    = 0;\r
+\r
+       text\r
+      help   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      text   = STRING_TOKEN(STR_INV_VERSION_TEXT6),\r
+           text   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      flags  = 0,\r
+      key    = 0;\r
+\r
+       text\r
+      help   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      text   = STRING_TOKEN(STR_INV_VERSION_TEXT7),\r
+           text   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      flags  = 0,\r
+      key    = 0;\r
+\r
+       text\r
+      help   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      text   = STRING_TOKEN(STR_INV_VERSION_TEXT8),\r
+           text   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      flags  = 0,\r
+      key    = 0;\r
+\r
+       text\r
+      help   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      text   = STRING_TOKEN(STR_INV_VERSION_TEXT9),\r
+           text   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      flags  = 0,\r
+      key    = 0;\r
+\r
+       text\r
+      help   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      text   = STRING_TOKEN(STR_INV_VERSION_TEXT10),\r
+           text   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      flags  = 0,\r
+      key    = 0;\r
+\r
+       text\r
+      help   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      text   = STRING_TOKEN(STR_INV_VERSION_TEXT11),\r
+           text   = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+      flags  = 0,\r
+      key    = 0;\r
+\r
+    subtitle text = STRING_TOKEN(STR_INV_EMPTY_STRING);\r
+\r
+    subtitle text = STRING_TOKEN(STR_INV_VERSION_TEXT12);\r
+\r
+  endform;\r
+\r
+endformset;\r
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/inventorystrings.uni b/MdeModulePkg/Universal/DriverSampleDxe/inventorystrings.uni
new file mode 100644 (file)
index 0000000..8d94456
Binary files /dev/null and b/MdeModulePkg/Universal/DriverSampleDxe/inventorystrings.uni differ
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
new file mode 100644 (file)
index 0000000..15a55d7
--- /dev/null
@@ -0,0 +1,2116 @@
+/** @file\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+    ConfigRouting.c\r
+\r
+Abstract:\r
+\r
+    Implementation for EFI_HII_CONFIG_ROUTING_PROTOCOL.\r
+\r
+Revision History\r
+\r
+\r
+**/\r
+\r
+\r
+#include "HiiDatabase.h"\r
+\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+\r
+STATIC\r
+CHAR16\r
+NibbleToHexCharPrivate (\r
+  IN UINT8                         Nibble\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Converts the low nibble of a byte to hex unicode character.\r
+\r
+  Arguments:\r
+    Nibble - lower nibble of a byte.\r
+\r
+  Returns:\r
+    Hex unicode character between L'0' to L'f'.\r
+\r
+--*/\r
+{\r
+  Nibble &= 0x0F;\r
+\r
+  if (Nibble <= 0x9) {\r
+    return (CHAR16)(Nibble + L'0');\r
+  }\r
+\r
+  return (CHAR16)(Nibble - 0xA + L'a');\r
+}\r
+\r
+\r
+/**\r
+  Converts Unicode string to binary buffer.\r
+  The conversion may be partial.\r
+  The first character in the string that is not hex digit stops the conversion.\r
+  At a minimum, any blob of data could be represented as a hex string.\r
+\r
+  @param  Buf                    Pointer to buffer that receives the data.\r
+  @param  Len                    Length in bytes of the buffer to hold converted\r
+                                 data. If routine return with EFI_SUCCESS,\r
+                                 containing length of converted data. If routine\r
+                                 return with EFI_BUFFER_TOO_SMALL, containg length\r
+                                 of buffer desired.\r
+  @param  Str                    String to be converted from.\r
+  @param  ConvertedStrLen        Length of the Hex String consumed.\r
+\r
+  @retval EFI_SUCCESS            Routine Success.\r
+  @retval EFI_BUFFER_TOO_SMALL   The buffer is too small to hold converted data.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+HexStringToBufPrivate (\r
+  IN OUT UINT8                     *Buf,\r
+  IN OUT UINTN                     *Len,\r
+  IN     CHAR16                    *Str,\r
+  OUT    UINTN                     *ConvertedStrLen  OPTIONAL\r
+  )\r
+{\r
+  UINTN       HexCnt;\r
+  UINTN       Idx;\r
+  UINTN       BufferLength;\r
+  UINT8       Digit;\r
+  UINT8       Byte;\r
+\r
+  //\r
+  // Find out how many hex characters the string has.\r
+  //\r
+  for (Idx = 0, HexCnt = 0; R8_IsHexDigit (&Digit, Str[Idx]); Idx++, HexCnt++);\r
+\r
+  if (HexCnt == 0) {\r
+    *Len = 0;\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // Two Unicode characters make up 1 buffer byte. Round up.\r
+  //\r
+  BufferLength = (HexCnt + 1) / 2;\r
+\r
+  //\r
+  // Test if  buffer is passed enough.\r
+  //\r
+  if (BufferLength > (*Len)) {\r
+    *Len = BufferLength;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  *Len = BufferLength;\r
+\r
+  for (Idx = 0; Idx < HexCnt; Idx++) {\r
+\r
+    R8_IsHexDigit (&Digit, Str[Idx]);\r
+\r
+    //\r
+    // For odd charaters, write the lower nibble for each buffer byte,\r
+    // and for even characters, the upper nibble.\r
+    //\r
+    if ((Idx & 1) == 0) {\r
+      Byte = (UINT8) (Digit << 4);\r
+    } else {\r
+      Byte = Buf[Idx / 2];\r
+      Byte &= 0xF0;\r
+      Byte = (UINT8) (Byte | Digit);\r
+    }\r
+\r
+    Buf[Idx / 2] = Byte;\r
+  }\r
+\r
+  if (ConvertedStrLen != NULL) {\r
+    *ConvertedStrLen = HexCnt;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Converts binary buffer to Unicode string.\r
+  At a minimum, any blob of data could be represented as a hex string.\r
+\r
+  @param  Str                    Pointer to the string.\r
+  @param  HexStringBufferLength  Length in bytes of buffer to hold the hex string.\r
+                                 Includes tailing '\0' character. If routine return\r
+                                 with EFI_SUCCESS, containing length of hex string\r
+                                 buffer. If routine return with\r
+                                 EFI_BUFFER_TOO_SMALL, containg length of hex\r
+                                 string buffer desired.\r
+  @param  Buf                    Buffer to be converted from.\r
+  @param  Len                    Length in bytes of the buffer to be converted.\r
+  @param  Flag                   If TRUE, encode the data in the same order as the\r
+                                 it  resides in the Buf. Else encode it in the\r
+                                 reverse direction.\r
+\r
+  @retval EFI_SUCCESS            Routine  success.\r
+  @retval EFI_BUFFER_TOO_SMALL   The hex string buffer is too small.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+BufToHexStringPrivate (\r
+  IN OUT CHAR16                    *Str,\r
+  IN OUT UINTN                     *HexStringBufferLength,\r
+  IN     UINT8                     *Buf,\r
+  IN     UINTN                     Len,\r
+  IN     BOOLEAN                   Flag\r
+  )\r
+{\r
+  UINTN       Idx;\r
+  UINT8       Byte;\r
+  UINTN       StrLen;\r
+\r
+  //\r
+  // Make sure string is either passed or allocate enough.\r
+  // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.\r
+  // Plus the Unicode termination character.\r
+  //\r
+  StrLen = Len * 2;\r
+  if ((*HexStringBufferLength) < (StrLen + 1) * sizeof (CHAR16)) {\r
+    *HexStringBufferLength = (StrLen + 1) * sizeof (CHAR16);\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  *HexStringBufferLength = (StrLen + 1) * sizeof (CHAR16);\r
+\r
+  //\r
+  // Ends the string.\r
+  //\r
+  Str[StrLen] = 0;\r
+\r
+  for (Idx = 0; Idx < Len; Idx++) {\r
+\r
+    Byte = Buf[Idx];\r
+    if (Flag) {\r
+      Str[Idx * 2]     = NibbleToHexCharPrivate ((UINT8)(Byte >> 4));\r
+      Str[Idx * 2 + 1] = NibbleToHexCharPrivate (Byte);\r
+    } else {\r
+      Str[StrLen - 1 - Idx * 2] = NibbleToHexCharPrivate (Byte);\r
+      Str[StrLen - 2 - Idx * 2] = NibbleToHexCharPrivate ((UINT8)(Byte >> 4));\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Calculate the number of Unicode characters of the incoming Configuration string,\r
+  not including NULL terminator.\r
+\r
+  @param  String                 String in <MultiConfigRequest> or\r
+                                 <MultiConfigResp> format.\r
+\r
+  @return The number of Unicode characters.\r
+\r
+**/\r
+STATIC\r
+UINTN\r
+CalculateConfigStringLen (\r
+  IN EFI_STRING                    String\r
+  )\r
+{\r
+  UINTN Length;\r
+\r
+  //\r
+  // "GUID=" should be the first element of incoming string.\r
+  //\r
+  ASSERT (String != NULL);\r
+  ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);\r
+\r
+  Length  = StrLen (L"GUID=");\r
+  String += Length;\r
+\r
+  //\r
+  // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".\r
+  // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.\r
+  //\r
+  while (*String != 0 && StrnCmp (String, L"&GUID=", StrLen (L"&GUID=")) != 0) {\r
+    Length++;\r
+    String++;\r
+  }\r
+\r
+  return Length;\r
+}\r
+\r
+\r
+/**\r
+  Convert the hex UNICODE %02x encoding of a UEFI device path to binary\r
+  from <PathHdr> of <ConfigHdr>.\r
+\r
+  @param  String                 UEFI configuration string\r
+  @param  DevicePath             binary of a UEFI device path.\r
+\r
+  @retval EFI_INVALID_PARAMETER  Any incoming parameter is invalid.\r
+  @retval EFI_OUT_OF_RESOURCES   Lake of resources to store neccesary structures.\r
+  @retval EFI_SUCCESS            The device path is retrieved and translated to\r
+                                 binary format.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetDevicePath (\r
+  IN  EFI_STRING                   String,\r
+  OUT UINT8                        **DevicePath\r
+  )\r
+{\r
+  UINTN      Length;\r
+  EFI_STRING PathHdr;\r
+  EFI_STRING DevicePathString;\r
+\r
+  if (String == NULL || DevicePath == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Find the 'PATH=' of <PathHdr> and skip it.\r
+  //\r
+  for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);\r
+  if (*String == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  String += StrLen (L"PATH=");\r
+  PathHdr = String;\r
+\r
+  //\r
+  // The content between 'PATH=' of <ConfigHdr> and '&' of next element\r
+  // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding\r
+  // of UEFI device path.\r
+  //\r
+  for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
+  DevicePathString = (EFI_STRING) AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
+  if (DevicePathString == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  StrnCpy (DevicePathString, PathHdr, Length);\r
+  *(DevicePathString + Length) = 0;\r
+\r
+  //\r
+  // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order\r
+  // as the device path resides in RAM memory.\r
+  // Translate the data into binary.\r
+  // Two Unicode characters make up 1 buffer byte.\r
+  //\r
+  Length /= 2;\r
+  *DevicePath = (UINT8 *) AllocateZeroPool (Length);\r
+  if (*DevicePath == NULL) {\r
+    SafeFreePool (DevicePathString);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  HexStringToBufPrivate (*DevicePath, &Length, DevicePathString, NULL);\r
+\r
+  SafeFreePool (DevicePathString);\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+  Extract Storage from all Form Packages in current hii database.\r
+\r
+  @param  HiiDatabase            EFI_HII_DATABASE_PROTOCOL instance.\r
+  @param  StorageListHead        Storage link List head.\r
+\r
+  @retval EFI_NOT_FOUND          There is no form package in current hii database.\r
+  @retval EFI_INVALID_PARAMETER  Any parameter is invalid.\r
+  @retval EFI_SUCCESS            All existing storage is exported.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportAllStorage (\r
+  IN EFI_HII_DATABASE_PROTOCOL     *HiiDatabase,\r
+  IN OUT LIST_ENTRY                *StorageListHead\r
+)\r
+{\r
+  EFI_STATUS                   Status;\r
+  UINTN                        BufferSize;\r
+  UINTN                        HandleCount;\r
+  EFI_HII_HANDLE               *HandleBuffer;\r
+  UINTN                        Index;\r
+  UINTN                        Index2;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  EFI_HII_PACKAGE_HEADER       *Package;\r
+  UINT8                        *OpCodeData;\r
+  UINT8                        Operand;\r
+  UINT32                       Offset;\r
+  HII_FORMSET_STORAGE          *Storage;\r
+  EFI_HII_HANDLE               HiiHandle;\r
+  EFI_HANDLE                   DriverHandle;\r
+  CHAR8                        *AsciiString;\r
+  UINT32                       PackageListLength;\r
+  EFI_HII_PACKAGE_HEADER       PackageHeader;\r
+\r
+  //\r
+  // Find the package list which contains Form package.\r
+  //\r
+  BufferSize   = 0;\r
+  HandleBuffer = NULL;\r
+  Status = HiiListPackageLists (\r
+             HiiDatabase,\r
+             EFI_HII_PACKAGE_FORM,\r
+             NULL,\r
+             &BufferSize,\r
+             HandleBuffer\r
+             );\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HandleBuffer = AllocateZeroPool (BufferSize);\r
+    ASSERT (HandleBuffer != NULL);\r
+\r
+    Status = HiiListPackageLists (\r
+               HiiDatabase,\r
+               EFI_HII_PACKAGE_FORM,\r
+               NULL,\r
+               &BufferSize,\r
+               HandleBuffer\r
+               );\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    SafeFreePool (HandleBuffer);\r
+    return Status;\r
+  }\r
+\r
+  HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    HiiHandle = HandleBuffer[Index];\r
+\r
+    BufferSize     = 0;\r
+    HiiPackageList = NULL;\r
+    Status = HiiExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      HiiPackageList = AllocateZeroPool (BufferSize);\r
+      ASSERT (HiiPackageList != NULL);\r
+      Status = HiiExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      SafeFreePool (HandleBuffer);\r
+      SafeFreePool (HiiPackageList);\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Get Form package from this HII package List\r
+    //\r
+    Offset  = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+    CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
+    Package = NULL;\r
+    ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+    while (Offset < PackageListLength) {\r
+      Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);\r
+      CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+      if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {\r
+        break;\r
+      }\r
+      Offset += PackageHeader.Length;\r
+    }\r
+    if (Offset >= PackageListLength) {\r
+      //\r
+      // Error here: No Form package found in this Package List\r
+      //\r
+      ASSERT (FALSE);\r
+    }\r
+\r
+    //\r
+    // Search Storage definition in this Form package\r
+    //\r
+    Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
+    while (Offset < PackageHeader.Length) {\r
+      OpCodeData = ((UINT8 *) Package) + Offset;\r
+      Offset += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+\r
+      Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;\r
+\r
+      if ((Operand == EFI_IFR_VARSTORE_OP) ||\r
+          (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) ||\r
+          (Operand == EFI_IFR_VARSTORE_EFI_OP)) {\r
+\r
+        Storage = AllocateZeroPool (sizeof (HII_FORMSET_STORAGE));\r
+        ASSERT (Storage != NULL);\r
+        InsertTailList (StorageListHead, &Storage->Entry);\r
+\r
+        Storage->Signature = HII_FORMSET_STORAGE_SIGNATURE;\r
+        Storage->HiiHandle = HiiHandle;\r
+\r
+        Status = HiiGetPackageListHandle (HiiDatabase, HiiHandle, &DriverHandle);\r
+        if (EFI_ERROR (Status)) {\r
+          SafeFreePool (HandleBuffer);\r
+          SafeFreePool (HiiPackageList);\r
+          SafeFreePool (Storage);\r
+          return Status;\r
+        }\r
+        Storage->DriverHandle = DriverHandle;\r
+\r
+        if (Operand == EFI_IFR_VARSTORE_OP) {\r
+          Storage->Type = EFI_HII_VARSTORE_BUFFER;\r
+\r
+          CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
+          CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));\r
+\r
+          AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;\r
+          Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);\r
+          ASSERT (Storage->Name != NULL);\r
+          for (Index2 = 0; AsciiString[Index2] != 0; Index2++) {\r
+            Storage->Name[Index2] = (CHAR16) AsciiString[Index2];\r
+          }\r
+          //\r
+          // Append '\0' to the end of the unicode string.\r
+          //\r
+          Storage->Name[Index2] = 0;\r
+        } else if (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) {\r
+          Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;\r
+\r
+          CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
+        } else if (Operand == EFI_IFR_VARSTORE_EFI_OP) {\r
+          Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;\r
+\r
+          CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
+        }\r
+      }\r
+    }\r
+\r
+    SafeFreePool (HiiPackageList);\r
+  }\r
+\r
+  SafeFreePool (HandleBuffer);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Generate a sub string then output it.\r
+\r
+  @param  String                 A constant string which is the prefix of the to be\r
+                                 generated string, e.g. GUID=\r
+  @param  BufferLen              The length of the Buffer in bytes.\r
+  @param  Buffer                 Points to a buffer which will be converted to hex\r
+                                 string and to be the content of the generated\r
+                                 string.\r
+  @param  Flag                   If TRUE, convert the buffer data in the same order\r
+                                 as the it  resides in the Buffer. Else convert it\r
+                                 in the reverse direction.\r
+  @param  SubStr                 Points to the output string. It's caller's\r
+                                 responsibility to free this buffer.\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+GenerateSubStr (\r
+  IN CONST EFI_STRING              String,\r
+  IN  UINTN                        BufferLen,\r
+  IN  UINT8                        *Buffer,\r
+  IN  BOOLEAN                      Flag,\r
+  OUT EFI_STRING                   *SubStr\r
+  )\r
+{\r
+  UINTN       Length;\r
+  EFI_STRING  Str;\r
+  EFI_STATUS  Status;\r
+\r
+  ASSERT (String != NULL && SubStr != NULL);\r
+\r
+  if (Buffer == NULL) {\r
+    *SubStr = AllocateCopyPool (StrSize (String), String);\r
+    ASSERT (*SubStr != NULL);\r
+    return ;\r
+  }\r
+\r
+  Length = BufferLen * 2 + 1 + StrLen (String) + 1;\r
+  Str = AllocateZeroPool (Length * sizeof (CHAR16));\r
+  ASSERT (Str != NULL);\r
+\r
+  StrCpy (Str, String);\r
+  Length = (BufferLen * 2 + 1) * sizeof (CHAR16);\r
+\r
+  Status = BufToHexStringPrivate (\r
+             Str + StrLen (String),\r
+             &Length,\r
+             Buffer,\r
+             BufferLen,\r
+             Flag\r
+             );\r
+\r
+  ASSERT_EFI_ERROR (Status);\r
+  StrCat (Str, L"&");\r
+\r
+  *SubStr = Str;\r
+}\r
+\r
+\r
+/**\r
+  Retrieve the <ConfigBody> from String then output it.\r
+\r
+  @param  String                 A sub string of a configuration string in\r
+                                 <MultiConfigAltResp> format.\r
+  @param  ConfigBody             Points to the output string. It's caller's\r
+                                 responsibility to free this buffer.\r
+\r
+  @retval EFI_INVALID_PARAMETER  There is no form package in current hii database.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough memory to finish this operation.\r
+  @retval EFI_SUCCESS            All existing storage is exported.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+OutputConfigBody (\r
+  IN  EFI_STRING                   String,\r
+  OUT EFI_STRING                   *ConfigBody\r
+  )\r
+{\r
+  EFI_STRING  TmpPtr;\r
+  EFI_STRING  Result;\r
+  UINTN       Length;\r
+\r
+  if (String == NULL || ConfigBody == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  TmpPtr = StrStr (String, L"GUID=");\r
+  if (TmpPtr == NULL) {\r
+    //\r
+    // It is the last <ConfigResp> of the incoming configuration string.\r
+    //\r
+    Result = AllocateCopyPool (StrSize (String), String);\r
+    if (Result == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    } else {\r
+      *ConfigBody = Result;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  Length = TmpPtr - String;\r
+  Result = AllocateCopyPool (Length * sizeof (CHAR16), String);\r
+  if (Result == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  *(Result + Length - 1) = 0;\r
+  *ConfigBody = Result;\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+#endif\r
+\r
+VOID *\r
+ReallocatePool (\r
+  IN VOID                          *OldPool,\r
+  IN UINTN                         OldSize,\r
+  IN UINTN                         NewSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Adjusts the size of a previously allocated buffer.\r
+\r
+Arguments:\r
+  OldPool               - A pointer to the buffer whose size is being adjusted.\r
+  OldSize               - The size of the current buffer.\r
+  NewSize               - The size of the new buffer.\r
+\r
+Returns:\r
+  Points to the new buffer\r
+\r
+--*/\r
+{\r
+  VOID  *NewPool;\r
+\r
+  NewPool = NULL;\r
+  if (NewSize) {\r
+    NewPool = AllocateZeroPool (NewSize);\r
+  }\r
+\r
+  if (OldPool) {\r
+    if (NewPool) {\r
+      CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
+    }\r
+\r
+    gBS->FreePool (OldPool);\r
+  }\r
+\r
+  return NewPool;\r
+}\r
+\r
+\r
+/**\r
+  Append a string to a multi-string format.\r
+\r
+  @param  MultiString            String in <MultiConfigRequest>,\r
+                                 <MultiConfigAltResp>, or <MultiConfigResp>. On\r
+                                 input, the buffer length of  this string is\r
+                                 MAX_STRING_LENGTH. On output, the  buffer length\r
+                                 might be updated.\r
+  @param  AppendString           NULL-terminated Unicode string.\r
+\r
+  @retval EFI_INVALID_PARAMETER  Any incoming parameter is invalid.\r
+  @retval EFI_SUCCESS            AppendString is append to the end of MultiString\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+AppendToMultiString (\r
+  IN OUT EFI_STRING                *MultiString,\r
+  IN EFI_STRING                    AppendString\r
+  )\r
+{\r
+  UINTN AppendStringSize;\r
+  UINTN MultiStringSize;\r
+\r
+  if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  AppendStringSize = StrSize (AppendString);\r
+  MultiStringSize  = StrSize (*MultiString);\r
+\r
+  //\r
+  // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.\r
+  //\r
+  if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||\r
+      MultiStringSize > MAX_STRING_LENGTH) {\r
+    *MultiString = (EFI_STRING) ReallocatePool (\r
+                                  (VOID *) (*MultiString),\r
+                                  MultiStringSize,\r
+                                  MultiStringSize + AppendStringSize\r
+                                  );\r
+  }\r
+\r
+  //\r
+  // Append the incoming string\r
+  //\r
+  StrCat (*MultiString, AppendString);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET\r
+  or WIDTH or VALUE.\r
+  <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
+\r
+  @param  StringPtr              String in <BlockConfig> format and points to the\r
+                                 first character of <Number>.\r
+  @param  Number                 The output value. Caller takes the responsibility\r
+                                 to free memory.\r
+  @param  Len                    Length of the <Number>, in characters.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store neccessary\r
+                                 structures.\r
+  @retval EFI_SUCCESS            Value of <Number> is outputted in Number\r
+                                 successfully.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetValueOfNumber (\r
+  IN EFI_STRING                    StringPtr,\r
+  OUT UINT8                        **Number,\r
+  OUT UINTN                        *Len\r
+  )\r
+{\r
+  EFI_STRING               TmpPtr;\r
+  UINTN                    Length;\r
+  EFI_STRING               Str;\r
+  UINT8                    *Buf;\r
+  EFI_STATUS               Status;\r
+\r
+  ASSERT (StringPtr != NULL && Number != NULL && Len != NULL);\r
+  ASSERT (*StringPtr != 0);\r
+\r
+  Buf = NULL;\r
+\r
+  TmpPtr = StringPtr;\r
+  while (*StringPtr != 0 && *StringPtr != L'&') {\r
+    StringPtr++;\r
+  }\r
+  *Len   = StringPtr - TmpPtr;\r
+  Length = *Len + 1;\r
+\r
+  Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (EFI_STRING));\r
+  if (Str == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Exit;\r
+  }\r
+  CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));\r
+  *(Str + *Len) = 0;\r
+\r
+  Length = (Length + 1) / 2;\r
+  Buf = (UINT8 *) AllocateZeroPool (Length);\r
+  if (Buf == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Exit;\r
+  }\r
+\r
+  Status = R8_HexStringToBuf (Buf, &Length, Str, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  *Number = Buf;\r
+  Status  = EFI_SUCCESS;\r
+\r
+Exit:\r
+  SafeFreePool (Str);\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function allows a caller to extract the current configuration\r
+  for one or more named elements from one or more drivers.\r
+\r
+  @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+                                 instance.\r
+  @param  Request                A null-terminated Unicode string in\r
+                                 <MultiConfigRequest> format.\r
+  @param  Progress               On return, points to a character in the Request\r
+                                 string. Points to the string's null terminator if\r
+                                 request was successful. Points to the most recent\r
+                                 & before the first failing name / value pair (or\r
+                                 the beginning of the string if the failure is in\r
+                                 the first name / value pair) if the request was\r
+                                 not successful.\r
+  @param  Results                Null-terminated Unicode string in\r
+                                 <MultiConfigAltResp> format which has all values\r
+                                 filled in for the names in the Request string.\r
+                                 String to be allocated by the called function.\r
+\r
+  @retval EFI_SUCCESS            The Results string is filled with the values\r
+                                 corresponding to all requested names.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the parts of the\r
+                                 results that must be stored awaiting possible\r
+                                 future        protocols.\r
+  @retval EFI_NOT_FOUND          Routing data doesn't match any known driver.\r
+                                   Progress set to the "G" in "GUID" of the routing\r
+                                  header that doesn't match. Note: There is no\r
+                                    requirement that all routing data be validated\r
+                                 before any configuration extraction.\r
+  @retval EFI_INVALID_PARAMETER  For example, passing in a NULL for the Request\r
+                                 parameter would result in this type of error. The\r
+                                 Progress parameter is set to NULL.\r
+  @retval EFI_INVALID_PARAMETER  Illegal syntax. Progress set to most recent &\r
+                                 before the error or the beginning of the string.\r
+  @retval EFI_INVALID_PARAMETER  Unknown name. Progress points to the & before the\r
+                                 name in question.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiConfigRoutingExtractConfig (\r
+  IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,\r
+  IN  CONST EFI_STRING                       Request,\r
+  OUT EFI_STRING                             *Progress,\r
+  OUT EFI_STRING                             *Results\r
+  )\r
+{\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  EFI_STRING                          StringPtr;\r
+  EFI_STRING                          ConfigRequest;\r
+  UINTN                               Length;\r
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;\r
+  EFI_STATUS                          Status;\r
+  LIST_ENTRY                          *Link;\r
+  HII_DATABASE_RECORD                 *Database;\r
+  UINT8                               *CurrentDevicePath;\r
+  EFI_HANDLE                          DriverHandle;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL      *ConfigAccess;\r
+  EFI_STRING                          AccessProgress;\r
+  EFI_STRING                          AccessResults;\r
+  UINTN                               RemainSize;\r
+  EFI_STRING                          TmpPtr;\r
+\r
+  if (This == NULL || Progress == NULL || Results == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Request == NULL) {\r
+    *Progress = NULL;\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private   = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  StringPtr = Request;\r
+  *Progress = StringPtr;\r
+\r
+  //\r
+  // The first element of <MultiConfigRequest> should be\r
+  // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
+  //\r
+  if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Allocate a fix length of memory to store Results. Reallocate memory for\r
+  // Results if this fix length is insufficient.\r
+  //\r
+  *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
+  if (*Results == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
+    //\r
+    // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
+    // or most recent & before the error.\r
+    //\r
+    if (StringPtr == Request) {\r
+      *Progress = StringPtr;\r
+    } else {\r
+      *Progress = StringPtr - 1;\r
+    }\r
+\r
+    //\r
+    // Process each <ConfigRequest> of <MultiConfigRequest>\r
+    //\r
+    Length = CalculateConfigStringLen (StringPtr);\r
+    ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
+    if (ConfigRequest == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    *(ConfigRequest + Length) = 0;\r
+\r
+    //\r
+    // Get the UEFI device path\r
+    //\r
+    Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
+    if (EFI_ERROR (Status)) {\r
+      SafeFreePool (ConfigRequest);\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Find driver which matches the routing data.\r
+    //\r
+    DriverHandle = NULL;\r
+    for (Link = Private->DatabaseList.ForwardLink;\r
+         Link != &Private->DatabaseList;\r
+         Link = Link->ForwardLink\r
+        ) {\r
+      Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+      CurrentDevicePath = Database->PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
+      if (CurrentDevicePath != NULL) {\r
+        if (CompareMem (\r
+              DevicePath,\r
+              CurrentDevicePath,\r
+              GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
+              ) == 0) {\r
+          DriverHandle = Database->DriverHandle;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+\r
+    SafeFreePool (DevicePath);\r
+\r
+    if (DriverHandle == NULL) {\r
+      //\r
+      // Routing data does not match any known driver.\r
+      // Set Progress to the 'G' in "GUID" of the routing header.\r
+      //\r
+      *Progress = StringPtr;\r
+      SafeFreePool (ConfigRequest);\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    //\r
+    // Call corresponding ConfigAccess protocol to extract settings\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    DriverHandle,\r
+                    &gEfiHiiConfigAccessProtocolGuid,\r
+                    (VOID **) &ConfigAccess\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    Status = ConfigAccess->ExtractConfig (\r
+                             ConfigAccess,\r
+                             ConfigRequest,\r
+                             &AccessProgress,\r
+                             &AccessResults\r
+                             );\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
+      // Map it to the progress on <MultiConfigRequest> then return it.\r
+      //\r
+      RemainSize = StrSize (AccessProgress);\r
+      for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++);\r
+      *Progress = TmpPtr;\r
+\r
+      SafeFreePool (ConfigRequest);\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Attach this <ConfigAltResp> to a <MultiConfigAltResp>\r
+    //\r
+    ASSERT (*AccessProgress == 0);\r
+    Status = AppendToMultiString (Results, AccessResults);\r
+    ASSERT_EFI_ERROR (Status);\r
+    SafeFreePool (AccessResults);\r
+    AccessResults = NULL;\r
+    SafeFreePool (ConfigRequest);\r
+    ConfigRequest = NULL;\r
+\r
+    //\r
+    // Go to next <ConfigRequest> (skip '&').\r
+    //\r
+    StringPtr += Length;\r
+    if (*StringPtr == 0) {\r
+      *Progress = StringPtr;\r
+      break;\r
+    }\r
+\r
+    StringPtr++;\r
+\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+#else\r
+  return EFI_UNSUPPORTED;\r
+#endif\r
+\r
+}\r
+\r
+\r
+/**\r
+  This function allows the caller to request the current configuration for the\r
+  entirety of the current HII database and returns the data in a\r
+  null-terminated Unicode string.\r
+\r
+  @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+                                 instance.\r
+  @param  Results                Null-terminated Unicode string in\r
+                                 <MultiConfigAltResp> format which has all values\r
+                                 filled in for the names in the Request string.\r
+                                 String to be allocated by the  called function.\r
+                                 De-allocation is up to the caller.\r
+\r
+  @retval EFI_SUCCESS            The Results string is filled with the values\r
+                                 corresponding to all requested names.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the parts of the\r
+                                 results that must be stored awaiting possible\r
+                                 future        protocols.\r
+  @retval EFI_INVALID_PARAMETER  For example, passing in a NULL for the Results\r
+                                 parameter would result in this type of error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiConfigRoutingExportConfig (\r
+  IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,\r
+  OUT EFI_STRING                             *Results\r
+  )\r
+{\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+\r
+  EFI_STATUS                          Status;\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  LIST_ENTRY                          StorageListHdr;\r
+  HII_FORMSET_STORAGE                 *Storage;\r
+  LIST_ENTRY                          *Link;\r
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;\r
+  UINTN                               Length;\r
+  EFI_STRING                          PathHdr;\r
+  UINTN                               PathHdrSize;\r
+  EFI_STRING                          ConfigRequest;\r
+  UINTN                               RequestSize;\r
+  EFI_STRING                          StringPtr;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL      *ConfigAccess;\r
+  EFI_STRING                          AccessProgress;\r
+  EFI_STRING                          AccessResults;\r
+  UINTN                               TmpSize;\r
+\r
+  if (This == NULL || Results == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  InitializeListHead (&StorageListHdr);\r
+\r
+  Status = ExportAllStorage (&Private->HiiDatabase, &StorageListHdr);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Allocate a fix length of memory to store Results. Reallocate memory for\r
+  // Results if this fix length is insufficient.\r
+  //\r
+  *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
+  if (*Results == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Parsing all formset storages.\r
+  //\r
+  for (Link = StorageListHdr.ForwardLink; Link != &StorageListHdr; Link = Link->ForwardLink) {\r
+    Storage = CR (Link, HII_FORMSET_STORAGE, Entry, HII_FORMSET_STORAGE_SIGNATURE);\r
+    //\r
+    // Find the corresponding device path instance\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    Storage->DriverHandle,\r
+                    &gEfiDevicePathProtocolGuid,\r
+                    (VOID **) &DevicePath\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    //\r
+    // Convert the device path binary to hex UNICODE %02x bytes in the same order\r
+    // as the device path resides in RAM memory.\r
+    //\r
+    Length      = GetDevicePathSize (DevicePath);\r
+    PathHdrSize = (Length * 2 + 1) * sizeof (CHAR16);\r
+    PathHdr     = (EFI_STRING) AllocateZeroPool (PathHdrSize);\r
+    if (PathHdr == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    Status = BufToHexStringPrivate (PathHdr, &PathHdrSize, (UINT8 *) DevicePath, Length, TRUE);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Generate a <ConfigRequest> with one <ConfigHdr> and zero <RequestElement>.\r
+    // It means extract all possible configurations from this specific driver.\r
+    //\r
+    TmpSize = StrLen (L"GUID=&NAME=&PATH=");\r
+    RequestSize   = (TmpSize + sizeof (EFI_GUID) * 2 +  StrLen (Storage->Name))\r
+                     * sizeof (CHAR16) + PathHdrSize;\r
+    ConfigRequest = (EFI_STRING) AllocateZeroPool (RequestSize);\r
+    if (ConfigRequest == NULL) {\r
+      SafeFreePool (PathHdr);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    //\r
+    // Add <GuidHdr>\r
+    // <GuidHdr> ::= 'GUID='<Guid>\r
+    //\r
+    StringPtr = ConfigRequest;\r
+    StrnCpy (StringPtr, L"GUID=", StrLen (L"GUID="));\r
+    StringPtr += StrLen (L"GUID=");\r
+\r
+    Status = BufToHexStringPrivate (\r
+               StringPtr,\r
+               &RequestSize,\r
+               (UINT8 *) (&Storage->Guid),\r
+               sizeof (EFI_GUID),\r
+               FALSE\r
+               );\r
+    ASSERT_EFI_ERROR (Status);\r
+    StringPtr += RequestSize / 2 - 1;\r
+    ASSERT (*StringPtr == 0);\r
+    *StringPtr = L'&';\r
+    StringPtr++;\r
+\r
+    //\r
+    // Add <NameHdr>\r
+    // <NameHdr> ::= 'NAME='<String>\r
+    //\r
+    StrnCpy (StringPtr, L"NAME=", StrLen (L"NAME="));\r
+    StringPtr += StrLen (L"NAME=");\r
+    StrnCpy (StringPtr, Storage->Name, StrLen (Storage->Name));\r
+    StringPtr += StrLen (Storage->Name);\r
+    *StringPtr = L'&';\r
+    StringPtr++;\r
+\r
+    //\r
+    // Add <PathHdr>\r
+    // <PathHdr> ::= '<PATH=>'<UEFI binary represented as hex UNICODE %02x>\r
+    //\r
+    StrnCpy (StringPtr, L"PATH=", StrLen (L"PATH="));\r
+    StringPtr += StrLen (L"PATH=");\r
+    StrCpy (StringPtr, PathHdr);\r
+\r
+    SafeFreePool (PathHdr);\r
+    PathHdr = NULL;\r
+\r
+    //\r
+    // BUGBUG: The "Implementation note" of ExportConfig() in UEFI spec makes the\r
+    // code somewhat complex. Let's TBD here whether a <ConfigRequest> or a <ConfigHdr>\r
+    // is required to call ConfigAccess.ExtractConfig().\r
+    //\r
+    // Here we use <ConfigHdr> to call ConfigAccess instance. It requires ConfigAccess\r
+    // to handle such kind of "ConfigRequest". It is not supported till now.\r
+    //\r
+    // Either the ExportConfig will be updated or the ConfigAccess.ExtractConfig()\r
+    // will be updated as soon as the decision is made.\r
+\r
+    //\r
+    // Route the request to corresponding ConfigAccess protocol to extract settings.\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    Storage->DriverHandle,\r
+                    &gEfiHiiConfigAccessProtocolGuid,\r
+                    (VOID **)  &ConfigAccess\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    Status = ConfigAccess->ExtractConfig (\r
+                             ConfigAccess,\r
+                             ConfigRequest,\r
+                             &AccessProgress,\r
+                             &AccessResults\r
+                             );\r
+    if (EFI_ERROR (Status)) {\r
+      SafeFreePool (ConfigRequest);\r
+      SafeFreePool (AccessResults);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    //\r
+    // Attach this <ConfigAltResp> to a <MultiConfigAltResp>\r
+    //\r
+    ASSERT (*AccessProgress == 0);\r
+    Status = AppendToMultiString (Results, AccessResults);\r
+    ASSERT_EFI_ERROR (Status);\r
+    SafeFreePool (AccessResults);\r
+    AccessResults = NULL;\r
+    SafeFreePool (ConfigRequest);\r
+    ConfigRequest = NULL;\r
+\r
+  }\r
+\r
+  //\r
+  // Free the exported storage resource\r
+  //\r
+  while (!IsListEmpty (&StorageListHdr)) {\r
+    Storage = CR (\r
+                StorageListHdr.ForwardLink,\r
+                HII_FORMSET_STORAGE,\r
+                Entry,\r
+                HII_FORMSET_STORAGE_SIGNATURE\r
+                );\r
+    RemoveEntryList (&Storage->Entry);\r
+    SafeFreePool (Storage->Name);\r
+    SafeFreePool (Storage);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+#else\r
+  return EFI_UNSUPPORTED;\r
+#endif\r
+}\r
+\r
+\r
+/**\r
+  This function processes the results of processing forms and routes it to the\r
+  appropriate handlers or storage.\r
+\r
+  @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+                                 instance.\r
+  @param  Configuration          A null-terminated Unicode string in\r
+                                 <MulltiConfigResp> format.\r
+  @param  Progress               A pointer to a string filled in with the offset of\r
+                                 the most recent & before the first failing name /\r
+                                 value pair (or the beginning of the string if the\r
+                                 failure is in the first name / value pair) or the\r
+                                 terminating NULL if all was successful.\r
+\r
+  @retval EFI_SUCCESS            The results have been distributed or are awaiting\r
+                                 distribution.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the parts of the\r
+                                 results that must be stored awaiting possible\r
+                                 future        protocols.\r
+  @retval EFI_INVALID_PARAMETER  Passing in a NULL for the Configuration parameter\r
+                                 would result in this type of error.\r
+  @retval EFI_NOT_FOUND          Target for the specified routing data was not\r
+                                 found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiConfigRoutingRoutConfig (\r
+  IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,\r
+  IN  CONST EFI_STRING                       Configuration,\r
+  OUT EFI_STRING                             *Progress\r
+  )\r
+{\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  EFI_STRING                          StringPtr;\r
+  EFI_STRING                          ConfigResp;\r
+  UINTN                               Length;\r
+  EFI_STATUS                          Status;\r
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;\r
+  LIST_ENTRY                          *Link;\r
+  HII_DATABASE_RECORD                 *Database;\r
+  UINT8                               *CurrentDevicePath;\r
+  EFI_HANDLE                          DriverHandle;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL      *ConfigAccess;\r
+  EFI_STRING                          AccessProgress;\r
+  UINTN                               RemainSize;\r
+  EFI_STRING                          TmpPtr;\r
+\r
+  if (This == NULL || Progress == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Configuration == NULL) {\r
+    *Progress = NULL;\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private   = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  StringPtr = Configuration;\r
+  *Progress = StringPtr;\r
+\r
+  //\r
+  // The first element of <MultiConfigResp> should be\r
+  // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
+  //\r
+  if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
+    //\r
+    // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
+    // or most recent & before the error.\r
+    //\r
+    if (StringPtr == Configuration) {\r
+      *Progress = StringPtr;\r
+    } else {\r
+      *Progress = StringPtr - 1;\r
+    }\r
+\r
+    //\r
+    // Process each <ConfigResp> of <MultiConfigResp>\r
+    //\r
+    Length = CalculateConfigStringLen (StringPtr);\r
+    ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
+    if (ConfigResp == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    //\r
+    // Append '\0' to the end of ConfigRequest\r
+    //\r
+    *(ConfigResp + Length) = 0;\r
+\r
+    //\r
+    // Get the UEFI device path\r
+    //\r
+    Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
+    if (EFI_ERROR (Status)) {\r
+      SafeFreePool (ConfigResp);\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Find driver which matches the routing data.\r
+    //\r
+    DriverHandle = NULL;\r
+    for (Link = Private->DatabaseList.ForwardLink;\r
+         Link != &Private->DatabaseList;\r
+         Link = Link->ForwardLink\r
+        ) {\r
+      Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+      CurrentDevicePath = Database->PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
+      if (CurrentDevicePath != NULL) {\r
+        if (CompareMem (\r
+              DevicePath,\r
+              CurrentDevicePath,\r
+              GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
+              ) == 0) {\r
+          DriverHandle = Database->DriverHandle;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+\r
+    SafeFreePool (DevicePath);\r
+\r
+    if (DriverHandle == NULL) {\r
+      //\r
+      // Routing data does not match any known driver.\r
+      // Set Progress to the 'G' in "GUID" of the routing header.\r
+      //\r
+      *Progress = StringPtr;\r
+      SafeFreePool (ConfigResp);\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    //\r
+    // Call corresponding ConfigAccess protocol to route settings\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    DriverHandle,\r
+                    &gEfiHiiConfigAccessProtocolGuid,\r
+                    (VOID **)  &ConfigAccess\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    Status = ConfigAccess->RouteConfig (\r
+                             ConfigAccess,\r
+                             ConfigResp,\r
+                             &AccessProgress\r
+                             );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // AccessProgress indicates the parsing progress on <ConfigResp>.\r
+      // Map it to the progress on <MultiConfigResp> then return it.\r
+      //\r
+      RemainSize = StrSize (AccessProgress);\r
+      for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++);\r
+      *Progress = TmpPtr;\r
+\r
+      SafeFreePool (ConfigResp);\r
+      return Status;\r
+    }\r
+\r
+    SafeFreePool (ConfigResp);\r
+    ConfigResp = NULL;\r
+\r
+    //\r
+    // Go to next <ConfigResp> (skip '&').\r
+    //\r
+    StringPtr += Length;\r
+    if (*StringPtr == 0) {\r
+      *Progress = StringPtr;\r
+      break;\r
+    }\r
+\r
+    StringPtr++;\r
+\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+#else\r
+  return EFI_UNSUPPORTED;\r
+#endif\r
+}\r
+\r
+\r
+/**\r
+  This helper function is to be called by drivers to map configuration data\r
+  stored in byte array ("block") formats such as UEFI Variables into current\r
+  configuration strings.\r
+\r
+  @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+                                 instance.\r
+  @param  ConfigRequest          A null-terminated Unicode string in\r
+                                 <ConfigRequest> format.\r
+  @param  Block                  Array of bytes defining the block's configuration.\r
+  @param  BlockSize              Length in bytes of Block.\r
+  @param  Config                 Filled-in configuration string. String allocated\r
+                                 by  the function. Returned only if call is\r
+                                 successful.\r
+  @param  Progress               A pointer to a string filled in with the offset of\r
+                                  the most recent & before the first failing\r
+                                 name/value pair (or the beginning of the string if\r
+                                 the failure is in the first name / value pair) or\r
+                                 the terminating NULL if all was successful.\r
+\r
+  @retval EFI_SUCCESS            The request succeeded. Progress points to the null\r
+                                 terminator at the end of the ConfigRequest\r
+                                 string.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough memory to allocate Config.     Progress\r
+                                 points to the first character of ConfigRequest.\r
+  @retval EFI_INVALID_PARAMETER  Passing in a NULL for the ConfigRequest or\r
+                                 Block parameter would result in this type of\r
+                                 error. Progress points to the first character of\r
+                                 ConfigRequest.\r
+  @retval EFI_DEVICE_ERROR       Block not large enough. Progress undefined.\r
+  @retval EFI_INVALID_PARAMETER  Encountered non <BlockName> formatted string.\r
+                                     Block is left updated and Progress points at\r
+                                 the "&" preceding the first non-<BlockName>.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiBlockToConfig (\r
+  IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,\r
+  IN  CONST EFI_STRING                       ConfigRequest,\r
+  IN  CONST UINT8                            *Block,\r
+  IN  CONST UINTN                            BlockSize,\r
+  OUT EFI_STRING                             *Config,\r
+  OUT EFI_STRING                             *Progress\r
+  )\r
+{\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  EFI_STRING                          StringPtr;\r
+  UINTN                               Length;\r
+  EFI_STATUS                          Status;\r
+  EFI_STRING                          TmpPtr;\r
+  UINT8                               *TmpBuffer;\r
+  UINTN                               Offset;\r
+  UINTN                               Width;\r
+  UINT8                               *Value;\r
+  EFI_STRING                          ValueStr;\r
+  EFI_STRING                          ConfigElement;\r
+\r
+  if (This == NULL || Progress == NULL || Config == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Block == NULL || ConfigRequest == NULL) {\r
+    *Progress = ConfigRequest;\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+\r
+  Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  ASSERT (Private != NULL);\r
+\r
+  StringPtr     = ConfigRequest;\r
+  ValueStr      = NULL;\r
+  Value         = NULL;\r
+  ConfigElement = NULL;\r
+\r
+  //\r
+  // Allocate a fix length of memory to store Results. Reallocate memory for\r
+  // Results if this fix length is insufficient.\r
+  //\r
+  *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
+  if (*Config == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Jump <ConfigHdr>\r
+  //\r
+  if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+    *Progress = StringPtr;\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Exit;\r
+  }\r
+  while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
+    StringPtr++;\r
+  }\r
+  if (*StringPtr == 0) {\r
+    *Progress = StringPtr;\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Exit;\r
+  }\r
+  while (*StringPtr++ != L'&');\r
+\r
+  //\r
+  // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
+  //\r
+  Length = StringPtr - ConfigRequest;\r
+  CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16));\r
+\r
+  //\r
+  // Parse each <RequestElement> if exists\r
+  // Only <BlockName> format is supported by this help function.\r
+  // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
+  //\r
+  while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
+    //\r
+    // Back up the header of one <BlockName>\r
+    //\r
+    TmpPtr = StringPtr;\r
+\r
+    StringPtr += StrLen (L"OFFSET=");\r
+    //\r
+    // Get Offset\r
+    //\r
+    Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+    if (Status == EFI_OUT_OF_RESOURCES) {\r
+      *Progress = ConfigRequest;\r
+      goto Exit;\r
+    }\r
+    Offset = 0;\r
+    CopyMem (\r
+      &Offset,\r
+      TmpBuffer,\r
+      (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
+      );\r
+    SafeFreePool (TmpBuffer);\r
+\r
+    StringPtr += Length;\r
+    if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
+      *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Exit;\r
+    }\r
+    StringPtr += StrLen (L"&WIDTH=");\r
+\r
+    //\r
+    // Get Width\r
+    //\r
+    Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+    if (Status == EFI_OUT_OF_RESOURCES) {\r
+      *Progress = ConfigRequest;\r
+      goto Exit;\r
+    }\r
+    Width = 0;\r
+    CopyMem (\r
+      &Width,\r
+      TmpBuffer,\r
+      (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
+      );\r
+    SafeFreePool (TmpBuffer);\r
+\r
+    StringPtr += Length;\r
+    if (*StringPtr != 0 && *StringPtr != L'&') {\r
+      *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Exit;\r
+    }\r
+\r
+    //\r
+    // Calculate Value and convert it to hex string.\r
+    //\r
+    if (Offset + Width > BlockSize) {\r
+      *Progress = StringPtr;\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto Exit;\r
+    }\r
+\r
+    Value = (UINT8 *) AllocateZeroPool (Width);\r
+    if (Value == NULL) {\r
+      *Progress = ConfigRequest;\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Exit;\r
+    }\r
+\r
+    CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
+\r
+    Length = Width * 2 + 1;\r
+    ValueStr = (EFI_STRING) AllocateZeroPool (Length  * sizeof (CHAR16));\r
+    if (ValueStr == NULL) {\r
+      *Progress = ConfigRequest;\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Exit;\r
+    }\r
+\r
+    Status = R8_BufToHexString (ValueStr, &Length, Value, Width);\r
+    ASSERT_EFI_ERROR (Status);\r
+    SafeFreePool (Value);\r
+    Value = NULL;\r
+\r
+    //\r
+    // Build a ConfigElement\r
+    //\r
+    Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
+    ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
+    if (ConfigElement == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Exit;\r
+    }\r
+    CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
+    if (*StringPtr == 0) {\r
+      *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
+    }\r
+    *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
+    StrCat (ConfigElement, L"VALUE=");\r
+    StrCat (ConfigElement, ValueStr);\r
+\r
+    AppendToMultiString (Config, ConfigElement);\r
+\r
+    SafeFreePool (ConfigElement);\r
+    SafeFreePool (ValueStr);\r
+    ConfigElement = NULL;\r
+    ValueStr = NULL;\r
+\r
+    //\r
+    // If '\0', parsing is finished. Otherwise skip '&' to continue\r
+    //\r
+    if (*StringPtr == 0) {\r
+      break;\r
+    }\r
+    AppendToMultiString (Config, L"&");\r
+    StringPtr++;\r
+\r
+  }\r
+\r
+  if (*StringPtr != 0) {\r
+    *Progress = StringPtr - 1;\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Exit;\r
+  }\r
+\r
+  *Progress = StringPtr;\r
+  return EFI_SUCCESS;\r
+\r
+Exit:\r
+\r
+  SafeFreePool (*Config);\r
+  SafeFreePool (ValueStr);\r
+  SafeFreePool (Value);\r
+  SafeFreePool (ConfigElement);\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+\r
+/**\r
+  This helper function is to be called by drivers to map configuration strings\r
+  to configurations stored in byte array ("block") formats such as UEFI Variables.\r
+\r
+  @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+                                 instance.\r
+  @param  ConfigResp             A null-terminated Unicode string in <ConfigResp>\r
+                                 format.\r
+  @param  Block                  A possibly null array of bytes representing the\r
+                                 current  block. Only bytes referenced in the\r
+                                 ConfigResp string  in the block are modified. If\r
+                                 this parameter is null or if the *BlockSize\r
+                                 parameter is (on input) shorter than required by\r
+                                 the Configuration string, only the BlockSize\r
+                                 parameter is updated and an appropriate status\r
+                                 (see below)  is returned.\r
+  @param  BlockSize              The length of the Block in units of UINT8.  On\r
+                                 input, this is the size of the Block. On output,\r
+                                 if successful, contains the index of the  last\r
+                                 modified byte in the Block.\r
+  @param  Progress               On return, points to an element of the ConfigResp\r
+                                 string filled in with the offset of the most\r
+                                 recent '&' before the first failing name / value\r
+                                 pair (or  the beginning of the string if the\r
+                                 failure is in the  first name / value pair) or the\r
+                                 terminating NULL if all was successful.\r
+\r
+  @retval EFI_SUCCESS            The request succeeded. Progress points to the null\r
+                                 terminator at the end of the ConfigResp string.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough memory to allocate Config.     Progress\r
+                                 points to the first character of ConfigResp.\r
+  @retval EFI_INVALID_PARAMETER  Passing in a NULL for the ConfigResp or\r
+                                 Block parameter would result in this type of\r
+                                 error. Progress points to the first character of\r
+                                         ConfigResp.\r
+  @retval EFI_INVALID_PARAMETER  Encountered non <BlockName> formatted name /\r
+                                 value pair. Block is left updated and\r
+                                 Progress points at the '&' preceding the first\r
+                                 non-<BlockName>.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiConfigToBlock (\r
+  IN     CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
+  IN     CONST EFI_STRING                      ConfigResp,\r
+  IN OUT UINT8                                 *Block,\r
+  IN OUT UINTN                                 *BlockSize,\r
+  OUT    EFI_STRING                            *Progress\r
+  )\r
+{\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  EFI_STRING                          StringPtr;\r
+  UINTN                               Length;\r
+  EFI_STATUS                          Status;\r
+  UINT8                               *TmpBuffer;\r
+  UINTN                               Offset;\r
+  UINTN                               Width;\r
+  UINT8                               *Value;\r
+  UINTN                               BufferSize;\r
+\r
+  if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (ConfigResp == NULL || Block == NULL) {\r
+    *Progress = ConfigResp;\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  ASSERT (Private != NULL);\r
+\r
+  StringPtr  = ConfigResp;\r
+  BufferSize = *BlockSize;\r
+  Value      = NULL;\r
+\r
+  //\r
+  // Jump <ConfigHdr>\r
+  //\r
+  if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+    *Progress = StringPtr;\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Exit;\r
+  }\r
+  while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
+    StringPtr++;\r
+  }\r
+  if (*StringPtr == 0) {\r
+    *Progress = StringPtr;\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Exit;\r
+  }\r
+  while (*StringPtr++ != L'&');\r
+\r
+  //\r
+  // Parse each <ConfigElement> if exists\r
+  // Only <BlockConfig> format is supported by this help function.\r
+  // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
+  //\r
+  while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
+    StringPtr += StrLen (L"OFFSET=");\r
+    //\r
+    // Get Offset\r
+    //\r
+    Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+    if (Status == EFI_OUT_OF_RESOURCES) {\r
+      *Progress = ConfigResp;\r
+      goto Exit;\r
+    }\r
+    Offset = 0;\r
+    CopyMem (\r
+      &Offset,\r
+      TmpBuffer,\r
+      (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
+      );\r
+    SafeFreePool (TmpBuffer);\r
+\r
+    StringPtr += Length;\r
+    if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
+      *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Exit;\r
+    }\r
+    StringPtr += StrLen (L"&WIDTH=");\r
+\r
+    //\r
+    // Get Width\r
+    //\r
+    Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+    if (Status == EFI_OUT_OF_RESOURCES) {\r
+      *Progress = ConfigResp;\r
+      goto Exit;\r
+    }\r
+    Width = 0;\r
+    CopyMem (\r
+      &Width,\r
+      TmpBuffer,\r
+      (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
+      );\r
+    SafeFreePool (TmpBuffer);\r
+\r
+    StringPtr += Length;\r
+    if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
+      *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Exit;\r
+    }\r
+    StringPtr += StrLen (L"&VALUE=");\r
+\r
+    //\r
+    // Get Value\r
+    //\r
+    Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
+    if (Status == EFI_OUT_OF_RESOURCES) {\r
+      *Progress = ConfigResp;\r
+      goto Exit;\r
+    }\r
+\r
+    StringPtr += Length;\r
+    if (*StringPtr != 0 && *StringPtr != L'&') {\r
+      *Progress = StringPtr - Length - 7;\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Exit;\r
+    }\r
+\r
+    //\r
+    // Update the Block with configuration info\r
+    //\r
+\r
+    if (Offset + Width > BufferSize) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+\r
+    CopyMem (Block + Offset, Value, Width);\r
+    *BlockSize = Offset + Width - 1;\r
+\r
+    SafeFreePool (Value);\r
+    Value = NULL;\r
+\r
+    //\r
+    // If '\0', parsing is finished. Otherwise skip '&' to continue\r
+    //\r
+    if (*StringPtr == 0) {\r
+      break;\r
+    }\r
+\r
+    StringPtr++;\r
+  }\r
+\r
+  if (*StringPtr != 0) {\r
+    *Progress = StringPtr - 1;\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Exit;\r
+  }\r
+\r
+  *Progress = StringPtr;\r
+  return EFI_SUCCESS;\r
+\r
+Exit:\r
+\r
+  SafeFreePool (Value);\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This helper function is to be called by drivers to extract portions of\r
+  a larger configuration string.\r
+\r
+  @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+                                 instance.\r
+  @param  Configuration          A null-terminated Unicode string in\r
+                                 <MultiConfigAltResp> format.\r
+  @param  Guid                   A pointer to the GUID value to search for in the\r
+                                 routing portion of the ConfigResp string when\r
+                                 retrieving  the requested data. If Guid is NULL,\r
+                                 then all GUID  values will be searched for.\r
+  @param  Name                   A pointer to the NAME value to search for in the\r
+                                 routing portion of the ConfigResp string when\r
+                                 retrieving  the requested data. If Name is NULL,\r
+                                 then all Name  values will be searched for.\r
+  @param  DevicePath             A pointer to the PATH value to search for in the\r
+                                 routing portion of the ConfigResp string when\r
+                                 retrieving  the requested data. If DevicePath is\r
+                                 NULL, then all  DevicePath values will be searched\r
+                                 for.\r
+  @param  AltCfgId               A pointer to the ALTCFG value to search for in the\r
+                                  routing portion of the ConfigResp string when\r
+                                 retrieving  the requested data.  If this parameter\r
+                                 is NULL,  then the current setting will be\r
+                                 retrieved.\r
+  @param  AltCfgResp             A pointer to a buffer which will be allocated by\r
+                                 the  function which contains the retrieved string\r
+                                 as requested.   This buffer is only allocated if\r
+                                 the call was successful.\r
+\r
+  @retval EFI_SUCCESS            The request succeeded. The requested data was\r
+                                 extracted  and placed in the newly allocated\r
+                                 AltCfgResp buffer.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough memory to allocate AltCfgResp.\r
+  @retval EFI_INVALID_PARAMETER  Any parameter is invalid.\r
+  @retval EFI_NOT_FOUND          Target for the specified routing data was not\r
+                                 found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetAltCfg (\r
+  IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL    *This,\r
+  IN  CONST EFI_STRING                         Configuration,\r
+  IN  CONST EFI_GUID                           *Guid,\r
+  IN  CONST EFI_STRING                         Name,\r
+  IN  CONST EFI_DEVICE_PATH_PROTOCOL           *DevicePath,\r
+  IN  CONST UINT16                             *AltCfgId,\r
+  OUT EFI_STRING                               *AltCfgResp\r
+  )\r
+{\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+\r
+  EFI_STATUS                          Status;\r
+  EFI_STRING                          StringPtr;\r
+  EFI_STRING                          HdrStart = NULL;\r
+  EFI_STRING                          HdrEnd   = NULL;\r
+  EFI_STRING                          TmpPtr;\r
+  UINTN                               Length;\r
+  EFI_STRING                          GuidStr  = NULL;\r
+  EFI_STRING                          NameStr  = NULL;\r
+  EFI_STRING                          PathStr  = NULL;\r
+  EFI_STRING                          AltIdStr = NULL;\r
+  EFI_STRING                          Result   = NULL;\r
+  BOOLEAN                             GuidFlag = FALSE;\r
+  BOOLEAN                             NameFlag = FALSE;\r
+  BOOLEAN                             PathFlag = FALSE;\r
+\r
+  if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  StringPtr = Configuration;\r
+  if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Generate the sub string for later matching.\r
+  //\r
+  GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (UINT8 *) Guid, FALSE, &GuidStr);\r
+  GenerateSubStr (\r
+    L"PATH=",\r
+    GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
+    (UINT8 *) DevicePath,\r
+    TRUE,\r
+    &PathStr\r
+    );\r
+  if (AltCfgId != NULL) {\r
+    GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (UINT8 *) AltCfgId, FALSE, &AltIdStr);\r
+  }\r
+  if (Name != NULL) {\r
+    Length  = StrLen (Name);\r
+    Length  += StrLen (L"NAME=&") + 1;\r
+    NameStr = AllocateZeroPool (Length * sizeof (CHAR16));\r
+    if (NameStr == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Exit;\r
+    }\r
+    StrCpy (NameStr, L"NAME=");\r
+    StrCat (NameStr, Name);\r
+    StrCat (NameStr, L"&");\r
+  } else {\r
+    GenerateSubStr (L"NAME=", 0, NULL, FALSE, &NameStr);\r
+  }\r
+\r
+  while (*StringPtr != 0) {\r
+    //\r
+    // Try to match the GUID\r
+    //\r
+    if (!GuidFlag) {\r
+      TmpPtr = StrStr (StringPtr, GuidStr);\r
+      if (TmpPtr == NULL) {\r
+        Status = EFI_NOT_FOUND;\r
+        goto Exit;\r
+      }\r
+      HdrStart = TmpPtr;\r
+\r
+      //\r
+      // Jump to <NameHdr>\r
+      //\r
+      if (Guid != NULL) {\r
+        StringPtr = TmpPtr + StrLen (GuidStr);\r
+      } else {\r
+        StringPtr = StrStr (TmpPtr, L"NAME=");\r
+        if (StringPtr == NULL) {\r
+          Status = EFI_NOT_FOUND;\r
+          goto Exit;\r
+        }\r
+      }\r
+      GuidFlag = TRUE;\r
+    }\r
+\r
+    //\r
+    // Try to match the NAME\r
+    //\r
+    if (GuidFlag && !NameFlag) {\r
+      if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
+        GuidFlag = FALSE;\r
+      } else {\r
+        //\r
+        // Jump to <PathHdr>\r
+        //\r
+        if (Name != NULL) {\r
+          StringPtr += StrLen (NameStr);\r
+        } else {\r
+          StringPtr = StrStr (StringPtr, L"PATH=");\r
+          if (StringPtr == NULL) {\r
+            Status = EFI_NOT_FOUND;\r
+            goto Exit;\r
+          }\r
+        }\r
+        NameFlag = TRUE;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Try to match the DevicePath\r
+    //\r
+    if (GuidFlag && NameFlag && !PathFlag) {\r
+      if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
+        GuidFlag = FALSE;\r
+        NameFlag = FALSE;\r
+      } else {\r
+        //\r
+        // Jump to '&' before <DescHdr> or <ConfigBody>\r
+        //\r
+        if (DevicePath != NULL) {\r
+          StringPtr += StrLen (PathStr);\r
+        } else {\r
+          StringPtr = StrStr (StringPtr, L"&");\r
+          if (StringPtr == NULL) {\r
+            Status = EFI_NOT_FOUND;\r
+            goto Exit;\r
+          }\r
+        }\r
+        PathFlag = TRUE;\r
+        HdrEnd   = ++StringPtr;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Try to match the AltCfgId\r
+    //\r
+    if (GuidFlag && NameFlag && PathFlag) {\r
+      if (AltCfgId == NULL) {\r
+        //\r
+        // Return Current Setting when AltCfgId is NULL.\r
+        //\r
+        Status = OutputConfigBody (StringPtr, &Result);\r
+        goto Exit;\r
+      }\r
+      //\r
+      // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
+      //\r
+      if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
+        GuidFlag = FALSE;\r
+        NameFlag = FALSE;\r
+        PathFlag = FALSE;\r
+      } else {\r
+        Status = OutputConfigBody (StringPtr, &Result);\r
+        goto Exit;\r
+      }\r
+    }\r
+  }\r
+\r
+  Status = EFI_NOT_FOUND;\r
+\r
+Exit:\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Copy the <ConfigHdr> and <ConfigBody>\r
+    //\r
+    Length = HdrEnd - HdrStart + StrLen (Result);\r
+    *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
+    if (*AltCfgResp == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+    } else {\r
+      StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);\r
+      StrCat (*AltCfgResp, Result);\r
+      Status = EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  SafeFreePool (GuidStr);\r
+  SafeFreePool (NameStr);\r
+  SafeFreePool (PathStr);\r
+  SafeFreePool (AltIdStr);\r
+  SafeFreePool (Result);\r
+\r
+  return Status;\r
+\r
+#else\r
+  return EFI_UNSUPPORTED;\r
+#endif\r
+\r
+}\r
+\r
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
new file mode 100644 (file)
index 0000000..a24c59b
--- /dev/null
@@ -0,0 +1,3727 @@
+/** @file\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+    Database.c\r
+\r
+Abstract:\r
+\r
+    Implementation for EFI_HII_DATABASE_PROTOCOL.\r
+\r
+Revision History\r
+\r
+\r
+**/\r
+\r
+\r
+#include "HiiDatabase.h"\r
+\r
+//\r
+// Global variables\r
+//\r
+STATIC EFI_GUID mHiiDatabaseNotifyGuid = HII_DATABASE_NOTIFY_GUID;\r
+\r
+\r
+/**\r
+  This function generates a HII_DATABASE_RECORD node and adds into hii database.\r
+\r
+  @param  Private                hii database private structure\r
+  @param  DatabaseRecord         HII_DATABASE_RECORD node which is used to store a\r
+                                 package list\r
+\r
+  @retval EFI_SUCCESS            A database record is generated successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new\r
+                                 database contents.\r
+  @retval EFI_INVALID_PARAMETER  Private is NULL or DatabaseRecord is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GenerateHiiDatabaseRecord (\r
+  IN  HII_DATABASE_PRIVATE_DATA *Private,\r
+  OUT HII_DATABASE_RECORD       **DatabaseNode\r
+  )\r
+{\r
+  HII_DATABASE_RECORD                *DatabaseRecord;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;\r
+  HII_HANDLE                         *HiiHandle;\r
+\r
+  if (Private == NULL || DatabaseNode == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  DatabaseRecord = (HII_DATABASE_RECORD *) AllocateZeroPool (sizeof (HII_DATABASE_RECORD));\r
+  if (DatabaseRecord == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  DatabaseRecord->Signature = HII_DATABASE_RECORD_SIGNATURE;\r
+\r
+  DatabaseRecord->PackageList = AllocateZeroPool (sizeof (HII_DATABASE_PACKAGE_LIST_INSTANCE));\r
+  if (DatabaseRecord->PackageList == NULL) {\r
+    SafeFreePool (DatabaseRecord);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  PackageList = DatabaseRecord->PackageList;\r
+\r
+  InitializeListHead (&PackageList->GuidPkgHdr);\r
+  InitializeListHead (&PackageList->FormPkgHdr);\r
+  InitializeListHead (&PackageList->KeyboardLayoutHdr);\r
+  InitializeListHead (&PackageList->StringPkgHdr);\r
+  InitializeListHead (&PackageList->FontPkgHdr);\r
+  InitializeListHead (&PackageList->SimpleFontPkgHdr);\r
+  PackageList->ImagePkg      = NULL;\r
+  PackageList->DevicePathPkg = NULL;\r
+\r
+  //\r
+  // Create a new hii handle\r
+  //\r
+  HiiHandle = (HII_HANDLE *) AllocateZeroPool (sizeof (HII_HANDLE));\r
+  if (HiiHandle == NULL) {\r
+    SafeFreePool (DatabaseRecord->PackageList);\r
+    SafeFreePool (DatabaseRecord);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  HiiHandle->Signature = HII_HANDLE_SIGNATURE;\r
+  //\r
+  // Backup the number of Hii handles\r
+  //\r
+  Private->HiiHandleCount++;\r
+  HiiHandle->Key = Private->HiiHandleCount;\r
+  //\r
+  // Insert the handle to hii handle list of the whole database.\r
+  //\r
+  InsertTailList (&Private->HiiHandleList, &HiiHandle->Handle);\r
+\r
+  DatabaseRecord->Handle = (EFI_HII_HANDLE) HiiHandle;\r
+\r
+  //\r
+  // Insert the Package List node to Package List link of the whole database.\r
+  //\r
+  InsertTailList (&Private->DatabaseList, &DatabaseRecord->DatabaseEntry);\r
+\r
+  *DatabaseNode = DatabaseRecord;\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+  This function checks whether a handle is a valid EFI_HII_HANDLE\r
+\r
+  @param  Handle                 Pointer to a EFI_HII_HANDLE\r
+\r
+  @retval TRUE                   Valid\r
+  @retval FALSE                  Invalid\r
+\r
+**/\r
+BOOLEAN\r
+IsHiiHandleValid (\r
+  EFI_HII_HANDLE Handle\r
+  )\r
+{\r
+  HII_HANDLE    *HiiHandle;\r
+\r
+  HiiHandle = (HII_HANDLE *) Handle;\r
+\r
+  if (HiiHandle == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (HiiHandle->Signature != HII_HANDLE_SIGNATURE) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
+/**\r
+  This function invokes the matching registered function.\r
+\r
+  @param  Private                HII Database driver private structure.\r
+  @param  NotifyType             The type of change concerning the database.\r
+  @param  PackageInstance        Points to the package referred to by the\r
+                                 notification.\r
+  @param  PackageType            Package type\r
+  @param  Handle                 The handle of the package list which contains the\r
+                                 specified package.\r
+\r
+  @retval EFI_SUCCESS            Already checked all registered function and\r
+                                 invoked  if matched.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InvokeRegisteredFunction (\r
+  IN HII_DATABASE_PRIVATE_DATA    *Private,\r
+  IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
+  IN VOID                         *PackageInstance,\r
+  IN UINT8                        PackageType,\r
+  IN EFI_HII_HANDLE               Handle\r
+  )\r
+{\r
+  HII_DATABASE_NOTIFY             *Notify;\r
+  LIST_ENTRY                      *Link;\r
+  EFI_HII_PACKAGE_HEADER          *Package;\r
+  UINT8                           *Buffer;\r
+  UINT32                          BufferSize;\r
+  UINT32                          HeaderSize;\r
+  UINT32                          ImageBlockSize;\r
+  UINT32                          PaletteInfoSize;\r
+\r
+  if (Private == NULL || (NotifyType & 0xF) == 0 || PackageInstance == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (!IsHiiHandleValid (Handle)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Buffer  = NULL;\r
+  Package = NULL;\r
+\r
+  //\r
+  // Convert the incoming package from hii database storage format to UEFI\r
+  // storage format. e.g. HII_GUID_PACKAGE_INSTANCE to EFI_HII_GUID_PACKAGE_HDR.\r
+  //\r
+  switch (PackageType) {\r
+  case EFI_HII_PACKAGE_TYPE_GUID:\r
+    Package = (EFI_HII_PACKAGE_HEADER *) (((HII_GUID_PACKAGE_INSTANCE *) PackageInstance)->GuidPkg);\r
+    break;\r
+\r
+  case EFI_HII_PACKAGE_FORM:\r
+    BufferSize = ((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->FormPkgHdr.Length;\r
+    Buffer = (UINT8 *) AllocateZeroPool (BufferSize);\r
+    ASSERT (Buffer != NULL);\r
+    CopyMem (\r
+      Buffer,\r
+      &((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->FormPkgHdr,\r
+      sizeof (EFI_HII_PACKAGE_HEADER)\r
+      );\r
+    CopyMem (\r
+      Buffer + sizeof (EFI_HII_PACKAGE_HEADER),\r
+      ((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->IfrData,\r
+      BufferSize - sizeof (EFI_HII_PACKAGE_HEADER)\r
+      );\r
+    Package = (EFI_HII_PACKAGE_HEADER *) Buffer;\r
+    break;\r
+\r
+  case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
+    Package = (EFI_HII_PACKAGE_HEADER *) (((HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *) PackageInstance)->KeyboardPkg);\r
+    break;\r
+\r
+  case EFI_HII_PACKAGE_STRINGS:\r
+    BufferSize = ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr->Header.Length;\r
+    HeaderSize = ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr->HdrSize;\r
+    Buffer = (UINT8 *) AllocateZeroPool (BufferSize);\r
+    ASSERT (Buffer != NULL);\r
+    CopyMem (\r
+      Buffer,\r
+      ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr,\r
+      HeaderSize\r
+      );\r
+    CopyMem (\r
+      Buffer + HeaderSize,\r
+      ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringBlock,\r
+      BufferSize - HeaderSize\r
+      );\r
+    Package = (EFI_HII_PACKAGE_HEADER *) Buffer;\r
+    break;\r
+\r
+  case EFI_HII_PACKAGE_FONTS:\r
+    BufferSize = ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr->Header.Length;\r
+    HeaderSize = ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr->HdrSize;\r
+    Buffer = (UINT8 *) AllocateZeroPool (BufferSize);\r
+    ASSERT (Buffer != NULL);\r
+    CopyMem (\r
+      Buffer,\r
+      ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr,\r
+      HeaderSize\r
+      );\r
+    CopyMem (\r
+      Buffer + HeaderSize,\r
+      ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->GlyphBlock,\r
+      BufferSize - HeaderSize\r
+      );\r
+    Package = (EFI_HII_PACKAGE_HEADER *) Buffer;\r
+    break;\r
+\r
+  case EFI_HII_PACKAGE_IMAGES:\r
+    BufferSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImagePkgHdr.Header.Length;\r
+    HeaderSize = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);\r
+    Buffer = (UINT8 *) AllocateZeroPool (BufferSize);\r
+    ASSERT (Buffer != NULL);\r
+\r
+    CopyMem (\r
+      Buffer,\r
+      &((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImagePkgHdr,\r
+      HeaderSize\r
+      );\r
+    CopyMem (\r
+      Buffer + sizeof (EFI_HII_PACKAGE_HEADER),\r
+      &HeaderSize,\r
+      sizeof (UINT32)\r
+      );\r
+\r
+    ImageBlockSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImageBlockSize;\r
+    if (ImageBlockSize != 0) {\r
+      CopyMem (\r
+        Buffer + HeaderSize,\r
+        ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImageBlock,\r
+        ImageBlockSize\r
+        );\r
+    }\r
+\r
+    PaletteInfoSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->PaletteInfoSize;\r
+    if (PaletteInfoSize != 0) {\r
+      CopyMem (\r
+        Buffer + HeaderSize + ImageBlockSize,\r
+        ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->PaletteBlock,\r
+        PaletteInfoSize\r
+        );\r
+      HeaderSize += ImageBlockSize;\r
+      CopyMem (\r
+        Buffer + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT32),\r
+        &HeaderSize,\r
+        sizeof (UINT32)\r
+        );\r
+    }\r
+    Package = (EFI_HII_PACKAGE_HEADER *) Buffer;\r
+    break;\r
+\r
+  case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
+    BufferSize = ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *) PackageInstance)->SimpleFontPkgHdr->Header.Length;\r
+    Buffer = (UINT8 *) AllocateZeroPool (BufferSize);\r
+    ASSERT (Buffer != NULL);\r
+    CopyMem (\r
+      Buffer,\r
+      ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *) PackageInstance)->SimpleFontPkgHdr,\r
+      BufferSize\r
+      );\r
+    Package = (EFI_HII_PACKAGE_HEADER *) Buffer;\r
+    break;\r
+\r
+  case EFI_HII_PACKAGE_DEVICE_PATH:\r
+    Package = (EFI_HII_PACKAGE_HEADER *) PackageInstance;\r
+    break;\r
+\r
+  default:\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  for (Link = Private->DatabaseNotifyList.ForwardLink;\r
+       Link != &Private->DatabaseNotifyList;\r
+       Link = Link->ForwardLink\r
+      ) {\r
+    Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);\r
+    if (Notify->NotifyType == NotifyType && Notify->PackageType == PackageType) {\r
+      //\r
+      // Check in case PackageGuid is not NULL when Package is GUID package\r
+      //\r
+      if (PackageType != EFI_HII_PACKAGE_TYPE_GUID) {\r
+        Notify->PackageGuid = NULL;\r
+      }\r
+      //\r
+      // Status of Registered Function is unknown so did not check it\r
+      //\r
+      Notify->PackageNotifyFn (\r
+        Notify->PackageType,\r
+        Notify->PackageGuid,\r
+        Package,\r
+        Handle,\r
+        NotifyType\r
+        );\r
+    }\r
+  }\r
+\r
+  SafeFreePool (Buffer);\r
+  Buffer = NULL;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function insert a GUID package to a package list node.\r
+\r
+  @param  PackageHdr             Pointer to a buffer stored with GUID package\r
+                                 information.\r
+  @param  NotifyType             The type of change concerning the database.\r
+  @param  PackageList            Pointer to a package list which will be inserted\r
+                                 to.\r
+  @param  Package                Created GUID pacakge\r
+\r
+  @retval EFI_SUCCESS            Guid Package is inserted successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new\r
+                                 Guid package.\r
+  @retval EFI_INVALID_PARAMETER  PackageHdr is NULL or PackageList is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertGuidPackage (\r
+  IN     VOID                               *PackageHdr,\r
+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  OUT    HII_GUID_PACKAGE_INSTANCE          **Package\r
+  )\r
+{\r
+  HII_GUID_PACKAGE_INSTANCE            *GuidPackage;\r
+  EFI_HII_PACKAGE_HEADER               PackageHeader;\r
+\r
+  if (PackageHdr == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+  //\r
+  // Create a GUID package node\r
+  //\r
+  GuidPackage = (HII_GUID_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_GUID_PACKAGE_INSTANCE));\r
+  if (GuidPackage == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  GuidPackage->GuidPkg = (UINT8 *) AllocateZeroPool (PackageHeader.Length);\r
+  if (GuidPackage->GuidPkg == NULL) {\r
+    SafeFreePool (GuidPackage);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  GuidPackage->Signature = HII_GUID_PACKAGE_SIGNATURE;\r
+  CopyMem (GuidPackage->GuidPkg, PackageHdr, PackageHeader.Length);\r
+  InsertTailList (&PackageList->GuidPkgHdr, &GuidPackage->GuidEntry);\r
+  *Package = GuidPackage;\r
+\r
+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+    PackageList->PackageListHdr.PackageLength += PackageHeader.Length;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function exports GUID packages to a buffer.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  Handle                 Identification of a package list.\r
+  @param  PackageList            Pointer to a package list which will be exported.\r
+  @param  UsedSize               The length of buffer be used.\r
+  @param  BufferSize             Length of the Buffer.\r
+  @param  Buffer                 Allocated space for storing exported data.\r
+  @param  ResultSize             The size of the already exported content of  this\r
+                                 package list.\r
+\r
+  @retval EFI_SUCCESS            Guid Packages are exported successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportGuidPackages (\r
+  IN HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN EFI_HII_HANDLE                     Handle,\r
+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  IN UINTN                              UsedSize,\r
+  IN UINTN                              BufferSize,\r
+  IN OUT VOID                           *Buffer,\r
+  IN OUT UINTN                          *ResultSize\r
+  )\r
+{\r
+  HII_GUID_PACKAGE_INSTANCE            *GuidPackage;\r
+  LIST_ENTRY                           *Link;\r
+  UINTN                                PackageLength;\r
+  EFI_HII_PACKAGE_HEADER               PackageHeader;\r
+  EFI_STATUS                           Status;\r
+\r
+  if (PackageList == NULL || ResultSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (BufferSize > 0 && Buffer == NULL ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PackageLength = 0;\r
+  Status        = EFI_SUCCESS;\r
+\r
+  for (Link = PackageList->GuidPkgHdr.ForwardLink; Link != &PackageList->GuidPkgHdr; Link = Link->ForwardLink) {\r
+    GuidPackage = CR (Link, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);\r
+    CopyMem (&PackageHeader, GuidPackage->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));\r
+    PackageLength += PackageHeader.Length;\r
+    if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
+      Status = InvokeRegisteredFunction (\r
+                 Private,\r
+                 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+                 (VOID *) GuidPackage,\r
+                 EFI_HII_PACKAGE_TYPE_GUID,\r
+                 Handle\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+      CopyMem (Buffer, GuidPackage->GuidPkg, PackageHeader.Length);\r
+      Buffer = (UINT8 *) Buffer + PackageHeader.Length;\r
+    }\r
+  }\r
+\r
+  *ResultSize += PackageLength;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function deletes all GUID packages from a package list node.\r
+\r
+  @param  Private                Hii database private data.\r
+  @param  Handle                 Handle of the package list which contains the to\r
+                                 be  removed GUID packages.\r
+  @param  PackageList            Pointer to a package list that contains removing\r
+                                 packages.\r
+\r
+  @retval EFI_SUCCESS            GUID Package(s) is deleted successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveGuidPackages (\r
+  IN     HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN     EFI_HII_HANDLE                     Handle,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+  )\r
+{\r
+  LIST_ENTRY                           *ListHead;\r
+  HII_GUID_PACKAGE_INSTANCE            *Package;\r
+  EFI_STATUS                           Status;\r
+  EFI_HII_PACKAGE_HEADER               PackageHeader;\r
+\r
+  ListHead = &PackageList->GuidPkgHdr;\r
+\r
+  while (!IsListEmpty (ListHead)) {\r
+    Package = CR (\r
+                ListHead->ForwardLink,\r
+                HII_GUID_PACKAGE_INSTANCE,\r
+                GuidEntry,\r
+                HII_GUID_PACKAGE_SIGNATURE\r
+                );\r
+    Status = InvokeRegisteredFunction (\r
+               Private,\r
+               EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+               (VOID *) Package,\r
+               EFI_HII_PACKAGE_TYPE_GUID,\r
+               Handle\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    RemoveEntryList (&Package->GuidEntry);\r
+    CopyMem (&PackageHeader, Package->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));\r
+    PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;\r
+    SafeFreePool (Package->GuidPkg);\r
+    SafeFreePool (Package);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function insert a Form package to a package list node.\r
+\r
+  @param  PackageHdr             Pointer to a buffer stored with Form package\r
+                                 information.\r
+  @param  NotifyType             The type of change concerning the database.\r
+  @param  PackageList            Pointer to a package list which will be inserted\r
+                                 to.\r
+  @param  Package                Created Form package\r
+\r
+  @retval EFI_SUCCESS            Form Package is inserted successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new\r
+                                 Form package.\r
+  @retval EFI_INVALID_PARAMETER  PackageHdr is NULL or PackageList is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertFormPackage (\r
+  IN     VOID                               *PackageHdr,\r
+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  OUT    HII_IFR_PACKAGE_INSTANCE           **Package\r
+  )\r
+{\r
+  HII_IFR_PACKAGE_INSTANCE *FormPackage;\r
+  EFI_HII_PACKAGE_HEADER   PackageHeader;\r
+\r
+  if (PackageHdr == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Get the length of the package, including package header itself\r
+  //\r
+  CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+  //\r
+  // Create a Form package node\r
+  //\r
+  FormPackage = (HII_IFR_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IFR_PACKAGE_INSTANCE));\r
+  if (FormPackage == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  FormPackage->IfrData = (UINT8 *) AllocateZeroPool (PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER));\r
+  if (FormPackage->IfrData == NULL) {\r
+    SafeFreePool (FormPackage);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  FormPackage->Signature = HII_IFR_PACKAGE_SIGNATURE;\r
+  //\r
+  // Copy Package Header\r
+  //\r
+  CopyMem (&FormPackage->FormPkgHdr, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+  //\r
+  // Copy Ifr contents\r
+  //\r
+  CopyMem (\r
+    FormPackage->IfrData,\r
+    (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER),\r
+    PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER)\r
+    );\r
+\r
+  InsertTailList (&PackageList->FormPkgHdr, &FormPackage->IfrEntry);\r
+  *Package = FormPackage;\r
+\r
+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+    PackageList->PackageListHdr.PackageLength += FormPackage->FormPkgHdr.Length;\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function exports Form packages to a buffer.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  Handle                 Identification of a package list.\r
+  @param  PackageList            Pointer to a package list which will be exported.\r
+  @param  UsedSize               The length of buffer be used.\r
+  @param  BufferSize             Length of the Buffer.\r
+  @param  Buffer                 Allocated space for storing exported data.\r
+  @param  ResultSize             The size of the already exported content of  this\r
+                                 package list.\r
+\r
+  @retval EFI_SUCCESS            Form Packages are exported successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportFormPackages (\r
+  IN HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN EFI_HII_HANDLE                     Handle,\r
+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  IN UINTN                              UsedSize,\r
+  IN UINTN                              BufferSize,\r
+  IN OUT VOID                           *Buffer,\r
+  IN OUT UINTN                          *ResultSize\r
+  )\r
+{\r
+  HII_IFR_PACKAGE_INSTANCE *FormPackage;\r
+  UINTN                    PackageLength;\r
+  LIST_ENTRY               *Link;\r
+  EFI_STATUS               Status;\r
+\r
+  if (Private == NULL || PackageList == NULL || ResultSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (BufferSize > 0 && Buffer == NULL ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PackageLength = 0;\r
+  Status        = EFI_SUCCESS;\r
+\r
+  //\r
+  // Export Form packages.\r
+  //\r
+  for (Link = PackageList->FormPkgHdr.ForwardLink; Link != &PackageList->FormPkgHdr; Link = Link->ForwardLink) {\r
+    FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);\r
+    PackageLength += FormPackage->FormPkgHdr.Length;\r
+    if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
+      //\r
+      // Invoke registered notification if exists\r
+      //\r
+      Status = InvokeRegisteredFunction (\r
+                 Private,\r
+                 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+                 (VOID *) FormPackage,\r
+                 EFI_HII_PACKAGE_FORM,\r
+                 Handle\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+      //\r
+      // Copy the Form package content.\r
+      //\r
+      CopyMem (Buffer, (VOID *) (&FormPackage->FormPkgHdr), sizeof (EFI_HII_PACKAGE_HEADER));\r
+      Buffer = (UINT8 *) Buffer + sizeof (EFI_HII_PACKAGE_HEADER);\r
+      CopyMem (\r
+        Buffer,\r
+        (VOID *) FormPackage->IfrData,\r
+        FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER)\r
+        );\r
+      Buffer = (UINT8 *) Buffer + FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);\r
+    }\r
+  }\r
+\r
+  *ResultSize += PackageLength;\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+  This function deletes all Form packages from a package list node.\r
+\r
+  @param  Private                Hii database private data.\r
+  @param  Handle                 Handle of the package list which contains the to\r
+                                 be  removed Form packages.\r
+  @param  PackageList            Pointer to a package list that contains removing\r
+                                 packages.\r
+\r
+  @retval EFI_SUCCESS            Form Package(s) is deleted successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveFormPackages (\r
+  IN     HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN     EFI_HII_HANDLE                     Handle,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+  )\r
+{\r
+  LIST_ENTRY                      *ListHead;\r
+  HII_IFR_PACKAGE_INSTANCE        *Package;\r
+  EFI_STATUS                      Status;\r
+\r
+  ListHead = &PackageList->FormPkgHdr;\r
+\r
+  while (!IsListEmpty (ListHead)) {\r
+    Package = CR (\r
+                ListHead->ForwardLink,\r
+                HII_IFR_PACKAGE_INSTANCE,\r
+                IfrEntry,\r
+                HII_IFR_PACKAGE_SIGNATURE\r
+                );\r
+    Status = InvokeRegisteredFunction (\r
+               Private,\r
+               EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+               (VOID *) Package,\r
+               EFI_HII_PACKAGE_FORM,\r
+               Handle\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    RemoveEntryList (&Package->IfrEntry);\r
+    PackageList->PackageListHdr.PackageLength -= Package->FormPkgHdr.Length;\r
+    SafeFreePool (Package->IfrData);\r
+    SafeFreePool (Package);\r
+\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+/**\r
+  This function insert a String package to a package list node.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  PackageHdr             Pointer to a buffer stored with String package\r
+                                 information.\r
+  @param  NotifyType             The type of change concerning the database.\r
+  @param  PackageList            Pointer to a package list which will be inserted\r
+                                 to.\r
+  @param  Package                Created String package\r
+\r
+  @retval EFI_SUCCESS            String Package is inserted successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new\r
+                                 String package.\r
+  @retval EFI_INVALID_PARAMETER  PackageHdr is NULL or PackageList is NULL.\r
+  @retval EFI_UNSUPPORTED        A string package with the same language already\r
+                                 exists in current package list.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertStringPackage (\r
+  IN     HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN     VOID                               *PackageHdr,\r
+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  OUT    HII_STRING_PACKAGE_INSTANCE        **Package\r
+\r
+  )\r
+{\r
+  HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
+  UINT32                      HeaderSize;\r
+  EFI_STATUS                  Status;\r
+  EFI_HII_PACKAGE_HEADER      PackageHeader;\r
+  CHAR8                       *Language;\r
+  UINT32                      LanguageSize;\r
+  LIST_ENTRY                  *Link;\r
+\r
+  if (Private == NULL || PackageHdr == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+  CopyMem (&HeaderSize, (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));\r
+\r
+  //\r
+  // It is illegal to have two string packages with same language within one packagelist\r
+  // since the stringid will be duplicate if so. Check it to avoid this potential issue.\r
+  //\r
+  LanguageSize = HeaderSize - sizeof (EFI_HII_STRING_PACKAGE_HDR) + sizeof (CHAR8);\r
+  Language = (CHAR8 *) AllocateZeroPool (LanguageSize);\r
+  if (Language == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  AsciiStrCpy (Language, (CHAR8 *) PackageHdr + HeaderSize - LanguageSize);\r
+  for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {\r
+    StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+    if (R8_EfiLibCompareLanguage (Language, StringPackage->StringPkgHdr->Language)) {\r
+      SafeFreePool (Language);\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+  SafeFreePool (Language);\r
+\r
+  //\r
+  // Create a String package node\r
+  //\r
+  StringPackage = (HII_STRING_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));\r
+  if (StringPackage == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+\r
+  StringPackage->StringPkgHdr = (EFI_HII_STRING_PACKAGE_HDR *) AllocateZeroPool (HeaderSize);\r
+  if (StringPackage->StringPkgHdr == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+\r
+  StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (PackageHeader.Length - HeaderSize);\r
+  if (StringPackage->StringBlock == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+\r
+  StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;\r
+  StringPackage->FontId    = 0;\r
+  InitializeListHead (&StringPackage->FontInfoList);\r
+\r
+  //\r
+  // Copy the String package header.\r
+  //\r
+  CopyMem (StringPackage->StringPkgHdr, PackageHdr, HeaderSize);\r
+\r
+  //\r
+  // Copy the String blocks\r
+  //\r
+  CopyMem (\r
+    StringPackage->StringBlock,\r
+    (UINT8 *) PackageHdr + HeaderSize,\r
+    PackageHeader.Length - HeaderSize\r
+    );\r
+\r
+  //\r
+  // Collect all font block info\r
+  //\r
+  Status = FindStringBlock (Private, StringPackage, (EFI_STRING_ID) (-1), NULL, NULL, NULL, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Insert to String package array\r
+  //\r
+  InsertTailList (&PackageList->StringPkgHdr, &StringPackage->StringEntry);\r
+  *Package = StringPackage;\r
+\r
+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+    PackageList->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+Error:\r
+\r
+  SafeFreePool (StringPackage->StringBlock);\r
+  SafeFreePool (StringPackage->StringPkgHdr);\r
+  SafeFreePool (StringPackage);\r
+  return Status;\r
+\r
+}\r
+\r
+\r
+/**\r
+  This function exports String packages to a buffer.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  Handle                 Identification of a package list.\r
+  @param  PackageList            Pointer to a package list which will be exported.\r
+  @param  UsedSize               The length of buffer be used.\r
+  @param  BufferSize             Length of the Buffer.\r
+  @param  Buffer                 Allocated space for storing exported data.\r
+  @param  ResultSize             The size of the already exported content of  this\r
+                                 package list.\r
+\r
+  @retval EFI_SUCCESS            String Packages are exported successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportStringPackages (\r
+  IN HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN EFI_HII_HANDLE                     Handle,\r
+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  IN UINTN                              UsedSize,\r
+  IN UINTN                              BufferSize,\r
+  IN OUT VOID                           *Buffer,\r
+  IN OUT UINTN                          *ResultSize\r
+  )\r
+{\r
+  LIST_ENTRY                  *Link;\r
+  UINTN                       PackageLength;\r
+  EFI_STATUS                  Status;\r
+  HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
+\r
+  if (Private == NULL || PackageList == NULL || ResultSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (BufferSize > 0 && Buffer == NULL ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PackageLength = 0;\r
+  Status        = EFI_SUCCESS;\r
+\r
+  for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {\r
+    StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+    PackageLength += StringPackage->StringPkgHdr->Header.Length;\r
+    if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
+      //\r
+      // Invoke registered notification function with EXPORT_PACK notify type\r
+      //\r
+      Status = InvokeRegisteredFunction (\r
+                 Private,\r
+                 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+                 (VOID *) StringPackage,\r
+                 EFI_HII_PACKAGE_STRINGS,\r
+                 Handle\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+      //\r
+      // Copy String package header\r
+      //\r
+      CopyMem (Buffer, StringPackage->StringPkgHdr, StringPackage->StringPkgHdr->HdrSize);\r
+      Buffer = (UINT8 *) Buffer + StringPackage->StringPkgHdr->HdrSize;\r
+\r
+      //\r
+      // Copy String blocks information\r
+      //\r
+      CopyMem (\r
+        Buffer,\r
+        StringPackage->StringBlock,\r
+        StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize\r
+        );\r
+      Buffer = (UINT8 *) Buffer + StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
+    }\r
+  }\r
+\r
+  *ResultSize += PackageLength;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function deletes all String packages from a package list node.\r
+\r
+  @param  Private                Hii database private data.\r
+  @param  Handle                 Handle of the package list which contains the to\r
+                                 be  removed String packages.\r
+  @param  PackageList            Pointer to a package list that contains removing\r
+                                 packages.\r
+\r
+  @retval EFI_SUCCESS            String Package(s) is deleted successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveStringPackages (\r
+  IN     HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN     EFI_HII_HANDLE                     Handle,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+  )\r
+{\r
+  LIST_ENTRY                      *ListHead;\r
+  HII_STRING_PACKAGE_INSTANCE     *Package;\r
+  HII_FONT_INFO                   *FontInfo;\r
+  EFI_STATUS                      Status;\r
+\r
+  ListHead = &PackageList->StringPkgHdr;\r
+\r
+  while (!IsListEmpty (ListHead)) {\r
+    Package = CR (\r
+                ListHead->ForwardLink,\r
+                HII_STRING_PACKAGE_INSTANCE,\r
+                StringEntry,\r
+                HII_STRING_PACKAGE_SIGNATURE\r
+                );\r
+    Status = InvokeRegisteredFunction (\r
+               Private,\r
+               EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+               (VOID *) Package,\r
+               EFI_HII_PACKAGE_STRINGS,\r
+               Handle\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    RemoveEntryList (&Package->StringEntry);\r
+    PackageList->PackageListHdr.PackageLength -= Package->StringPkgHdr->Header.Length;\r
+    SafeFreePool (Package->StringBlock);\r
+    SafeFreePool (Package->StringPkgHdr);\r
+    //\r
+    // Delete font information\r
+    //\r
+    while (!IsListEmpty (&Package->FontInfoList)) {\r
+      FontInfo = CR (\r
+                   Package->FontInfoList.ForwardLink,\r
+                   HII_FONT_INFO,\r
+                   Entry,\r
+                   HII_FONT_INFO_SIGNATURE\r
+                   );\r
+      RemoveEntryList (&FontInfo->Entry);\r
+      SafeFreePool (FontInfo);\r
+    }\r
+\r
+    SafeFreePool (Package);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function insert a Font package to a package list node.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  PackageHdr             Pointer to a buffer stored with Font package\r
+                                 information.\r
+  @param  NotifyType             The type of change concerning the database.\r
+  @param  PackageList            Pointer to a package list which will be inserted\r
+                                 to.\r
+  @param  Package                Created Font package\r
+\r
+  @retval EFI_SUCCESS            Font Package is inserted successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new\r
+                                 Font package.\r
+  @retval EFI_INVALID_PARAMETER  PackageHdr is NULL or PackageList is NULL.\r
+  @retval EFI_UNSUPPORTED        A font package with same EFI_FONT_INFO already\r
+                                 exists in current hii database.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertFontPackage (\r
+  IN     HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN     VOID                               *PackageHdr,\r
+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  OUT    HII_FONT_PACKAGE_INSTANCE          **Package\r
+  )\r
+{\r
+  HII_FONT_PACKAGE_INSTANCE *FontPackage;\r
+  EFI_HII_FONT_PACKAGE_HDR  *FontPkgHdr;\r
+  UINT32                    HeaderSize;\r
+  EFI_STATUS                Status;\r
+  EFI_HII_PACKAGE_HEADER    PackageHeader;\r
+  EFI_FONT_INFO             *FontInfo;\r
+  UINT32                    FontInfoSize;\r
+  HII_GLOBAL_FONT_INFO      *GlobalFont;\r
+\r
+  if (Private == NULL || PackageHdr == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+  CopyMem (&HeaderSize, (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));\r
+\r
+  FontInfo    = NULL;\r
+  FontPackage = NULL;\r
+  GlobalFont  = NULL;\r
+\r
+  //\r
+  // It is illegal to have two font packages with same EFI_FONT_INFO within hii\r
+  // database. EFI_FONT_INFO (FontName, FontSize, FontStyle) describes font's\r
+  // attributes and identify a font uniquely.\r
+  //\r
+  FontPkgHdr = (EFI_HII_FONT_PACKAGE_HDR *) AllocateZeroPool (HeaderSize);\r
+  if (FontPkgHdr == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+  CopyMem (FontPkgHdr, PackageHdr, HeaderSize);\r
+\r
+  FontInfoSize = sizeof (EFI_FONT_INFO) + HeaderSize - sizeof (EFI_HII_FONT_PACKAGE_HDR);\r
+  FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoSize);\r
+  if (FontInfo == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+  FontInfo->FontStyle = FontPkgHdr->FontStyle;\r
+  FontInfo->FontSize  = FontPkgHdr->Cell.Height;\r
+  StrCpy (FontInfo->FontName, FontPkgHdr->FontFamily);\r
+\r
+  if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, NULL)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto Error;\r
+  }\r
+\r
+  //\r
+  // Create a Font package node\r
+  //\r
+  FontPackage = (HII_FONT_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_FONT_PACKAGE_INSTANCE));\r
+  if (FontPackage == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+  FontPackage->Signature  = HII_FONT_PACKAGE_SIGNATURE;\r
+  FontPackage->FontPkgHdr = FontPkgHdr;\r
+  InitializeListHead (&FontPackage->GlyphInfoList);\r
+\r
+  FontPackage->GlyphBlock = (UINT8 *) AllocateZeroPool (PackageHeader.Length - HeaderSize);\r
+  if (FontPackage->GlyphBlock == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+  CopyMem (FontPackage->GlyphBlock, (UINT8 *) PackageHdr + HeaderSize, PackageHeader.Length - HeaderSize);\r
+\r
+  //\r
+  // Collect all default character cell information and backup in GlyphInfoList.\r
+  //\r
+  Status = FindGlyphBlock (FontPackage, (CHAR16) (-1), NULL, NULL, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Error;\r
+  }\r
+\r
+  //\r
+  // This font package describes an unique EFI_FONT_INFO. Backup it in global\r
+  // font info list.\r
+  //\r
+  GlobalFont = (HII_GLOBAL_FONT_INFO *) AllocateZeroPool (sizeof (HII_GLOBAL_FONT_INFO));\r
+  if (GlobalFont == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+  GlobalFont->Signature    = HII_GLOBAL_FONT_INFO_SIGNATURE;\r
+  GlobalFont->FontPackage  = FontPackage;\r
+  GlobalFont->FontInfoSize = FontInfoSize;\r
+  GlobalFont->FontInfo     = FontInfo;\r
+  InsertTailList (&Private->FontInfoList, &GlobalFont->Entry);\r
+\r
+  //\r
+  // Insert this font package to Font package array\r
+  //\r
+  InsertTailList (&PackageList->FontPkgHdr, &FontPackage->FontEntry);\r
+  *Package = FontPackage;\r
+\r
+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+    PackageList->PackageListHdr.PackageLength += FontPackage->FontPkgHdr->Header.Length;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+Error:\r
+\r
+  SafeFreePool (FontPkgHdr);\r
+  SafeFreePool (FontInfo);\r
+  SafeFreePool (FontPackage->GlyphBlock);\r
+  SafeFreePool (FontPackage);\r
+  SafeFreePool (GlobalFont);\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+\r
+/**\r
+  This function exports Font packages to a buffer.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  Handle                 Identification of a package list.\r
+  @param  PackageList            Pointer to a package list which will be exported.\r
+  @param  UsedSize               The length of buffer be used.\r
+  @param  BufferSize             Length of the Buffer.\r
+  @param  Buffer                 Allocated space for storing exported data.\r
+  @param  ResultSize             The size of the already exported content of  this\r
+                                 package list.\r
+\r
+  @retval EFI_SUCCESS            Font Packages are exported successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportFontPackages (\r
+  IN HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN EFI_HII_HANDLE                     Handle,\r
+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  IN UINTN                              UsedSize,\r
+  IN UINTN                              BufferSize,\r
+  IN OUT VOID                           *Buffer,\r
+  IN OUT UINTN                          *ResultSize\r
+  )\r
+{\r
+  LIST_ENTRY                  *Link;\r
+  UINTN                       PackageLength;\r
+  EFI_STATUS                  Status;\r
+  HII_FONT_PACKAGE_INSTANCE   *Package;\r
+\r
+\r
+  if (Private == NULL || PackageList == NULL || ResultSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (BufferSize > 0 && Buffer == NULL ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PackageLength = 0;\r
+  Status        = EFI_SUCCESS;\r
+\r
+  for (Link = PackageList->FontPkgHdr.ForwardLink; Link != &PackageList->FontPkgHdr; Link = Link->ForwardLink) {\r
+    Package = CR (Link, HII_FONT_PACKAGE_INSTANCE, FontEntry, HII_FONT_PACKAGE_SIGNATURE);\r
+    PackageLength += Package->FontPkgHdr->Header.Length;\r
+    if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
+      //\r
+      // Invoke registered notification function with EXPORT_PACK notify type\r
+      //\r
+      Status = InvokeRegisteredFunction (\r
+                 Private,\r
+                 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+                 (VOID *) Package,\r
+                 EFI_HII_PACKAGE_FONTS,\r
+                 Handle\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+      //\r
+      // Copy Font package header\r
+      //\r
+      CopyMem (Buffer, Package->FontPkgHdr, Package->FontPkgHdr->HdrSize);\r
+      Buffer = (UINT8 *) Buffer + Package->FontPkgHdr->HdrSize;\r
+\r
+      //\r
+      // Copy Glyph blocks information\r
+      //\r
+      CopyMem (\r
+        Buffer,\r
+        Package->GlyphBlock,\r
+        Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize\r
+        );\r
+      Buffer = (UINT8 *) Buffer + Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize;\r
+    }\r
+  }\r
+\r
+  *ResultSize += PackageLength;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function deletes all Font packages from a package list node.\r
+\r
+  @param  Private                Hii database private data.\r
+  @param  Handle                 Handle of the package list which contains the to\r
+                                 be  removed Font packages.\r
+  @param  PackageList            Pointer to a package list that contains removing\r
+                                 packages.\r
+\r
+  @retval EFI_SUCCESS            Font Package(s) is deleted successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveFontPackages (\r
+  IN     HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN     EFI_HII_HANDLE                     Handle,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+  )\r
+{\r
+  LIST_ENTRY                      *ListHead;\r
+  HII_FONT_PACKAGE_INSTANCE       *Package;\r
+  EFI_STATUS                      Status;\r
+  HII_GLYPH_INFO                  *GlyphInfo;\r
+  LIST_ENTRY                      *Link;\r
+  HII_GLOBAL_FONT_INFO            *GlobalFont;\r
+\r
+  ListHead = &PackageList->FontPkgHdr;\r
+\r
+  while (!IsListEmpty (ListHead)) {\r
+    Package = CR (\r
+                ListHead->ForwardLink,\r
+                HII_FONT_PACKAGE_INSTANCE,\r
+                FontEntry,\r
+                HII_FONT_PACKAGE_SIGNATURE\r
+                );\r
+    Status = InvokeRegisteredFunction (\r
+               Private,\r
+               EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+               (VOID *) Package,\r
+               EFI_HII_PACKAGE_FONTS,\r
+               Handle\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    RemoveEntryList (&Package->FontEntry);\r
+    PackageList->PackageListHdr.PackageLength -= Package->FontPkgHdr->Header.Length;\r
+    SafeFreePool (Package->GlyphBlock);\r
+    SafeFreePool (Package->FontPkgHdr);\r
+    //\r
+    // Delete default character cell information\r
+    //\r
+    while (!IsListEmpty (&Package->GlyphInfoList)) {\r
+      GlyphInfo = CR (\r
+                    Package->GlyphInfoList.ForwardLink,\r
+                    HII_GLYPH_INFO,\r
+                    Entry,\r
+                    HII_GLYPH_INFO_SIGNATURE\r
+                    );\r
+      RemoveEntryList (&GlyphInfo->Entry);\r
+      SafeFreePool (GlyphInfo);\r
+    }\r
+\r
+    //\r
+    // Remove corresponding global font info\r
+    //\r
+    for (Link = Private->FontInfoList.ForwardLink; Link != &Private->FontInfoList; Link = Link->ForwardLink) {\r
+      GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);\r
+      if (GlobalFont->FontPackage == Package) {\r
+        RemoveEntryList (&GlobalFont->Entry);\r
+        SafeFreePool (GlobalFont->FontInfo);\r
+        SafeFreePool (GlobalFont);\r
+        break;\r
+      }\r
+    }\r
+\r
+    SafeFreePool (Package);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function insert a Image package to a package list node.\r
+\r
+  @param  PackageHdr             Pointer to a buffer stored with Image package\r
+                                 information.\r
+  @param  NotifyType             The type of change concerning the database.\r
+  @param  PackageList            Pointer to a package list which will be inserted\r
+                                 to.\r
+  @param  Package                Created Image package\r
+\r
+  @retval EFI_SUCCESS            Image Package is inserted successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new\r
+                                 Image package.\r
+  @retval EFI_INVALID_PARAMETER  PackageHdr is NULL or PackageList is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertImagePackage (\r
+  IN     VOID                               *PackageHdr,\r
+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  OUT    HII_IMAGE_PACKAGE_INSTANCE         **Package\r
+  )\r
+{\r
+  HII_IMAGE_PACKAGE_INSTANCE        *ImagePackage;\r
+  UINT32                            PaletteSize;\r
+  UINT32                            ImageSize;\r
+  UINT16                            Index;\r
+  EFI_HII_IMAGE_PALETTE_INFO_HEADER *PaletteHdr;\r
+  EFI_HII_IMAGE_PALETTE_INFO        *PaletteInfo;\r
+  UINT32                            PaletteInfoOffset;\r
+  UINT32                            ImageInfoOffset;\r
+  UINT16                            CurrentSize;\r
+\r
+  if (PackageHdr == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Less than one image package is allowed in one package list.\r
+  //\r
+  if (PackageList->ImagePkg != NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Create a Image package node\r
+  //\r
+  ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));\r
+  if (ImagePackage == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Copy the Image package header.\r
+  //\r
+  CopyMem (&ImagePackage->ImagePkgHdr, PackageHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));\r
+\r
+  PaletteInfoOffset = ImagePackage->ImagePkgHdr.PaletteInfoOffset;\r
+  ImageInfoOffset   = ImagePackage->ImagePkgHdr.ImageInfoOffset;\r
+\r
+  //\r
+  // If PaletteInfoOffset is zero, there are no palettes in this image package.\r
+  //\r
+  PaletteSize                = 0;\r
+  ImagePackage->PaletteBlock = NULL;\r
+  if (PaletteInfoOffset != 0) {\r
+    PaletteHdr  = (EFI_HII_IMAGE_PALETTE_INFO_HEADER *) ((UINT8 *) PackageHdr + PaletteInfoOffset);\r
+    PaletteSize = sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);\r
+    PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *) ((UINT8 *) PaletteHdr + PaletteSize);\r
+\r
+    for (Index = 0; Index < PaletteHdr->PaletteCount; Index++) {\r
+      CopyMem (&CurrentSize, PaletteInfo, sizeof (UINT16));\r
+      CurrentSize += sizeof (UINT16);\r
+      PaletteSize += (UINT32) CurrentSize;\r
+      PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *) ((UINT8 *) PaletteInfo + CurrentSize);\r
+    }\r
+\r
+    ImagePackage->PaletteBlock = (UINT8 *) AllocateZeroPool (PaletteSize);\r
+    if (ImagePackage->PaletteBlock == NULL) {\r
+      SafeFreePool (ImagePackage);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    CopyMem (\r
+      ImagePackage->PaletteBlock,\r
+      (UINT8 *) PackageHdr + PaletteInfoOffset,\r
+      PaletteSize\r
+      );\r
+  }\r
+\r
+  //\r
+  // If ImageInfoOffset is zero, there are no images in this package.\r
+  //\r
+  ImageSize                = 0;\r
+  ImagePackage->ImageBlock = NULL;\r
+  if (ImageInfoOffset != 0) {\r
+    ImageSize = ImagePackage->ImagePkgHdr.Header.Length -\r
+                sizeof (EFI_HII_IMAGE_PACKAGE_HDR) - PaletteSize;\r
+    ImagePackage->ImageBlock = (UINT8 *) AllocateZeroPool (ImageSize);\r
+    if (ImagePackage->ImageBlock == NULL) {\r
+      SafeFreePool (ImagePackage->PaletteBlock);\r
+      SafeFreePool (ImagePackage);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    CopyMem (\r
+      ImagePackage->ImageBlock,\r
+      (UINT8 *) PackageHdr + ImageInfoOffset,\r
+      ImageSize\r
+      );\r
+  }\r
+\r
+  ImagePackage->ImageBlockSize  = ImageSize;\r
+  ImagePackage->PaletteInfoSize = PaletteSize;\r
+  PackageList->ImagePkg         = ImagePackage;\r
+  *Package                      = ImagePackage;\r
+\r
+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+    PackageList->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function exports Image packages to a buffer.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  Handle                 Identification of a package list.\r
+  @param  PackageList            Pointer to a package list which will be exported.\r
+  @param  UsedSize               The length of buffer be used.\r
+  @param  BufferSize             Length of the Buffer.\r
+  @param  Buffer                 Allocated space for storing exported data.\r
+  @param  ResultSize             The size of the already exported content of  this\r
+                                 package list.\r
+\r
+  @retval EFI_SUCCESS            Image Packages are exported successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportImagePackages (\r
+  IN HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN EFI_HII_HANDLE                     Handle,\r
+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  IN UINTN                              UsedSize,\r
+  IN UINTN                              BufferSize,\r
+  IN OUT VOID                           *Buffer,\r
+  IN OUT UINTN                          *ResultSize\r
+  )\r
+{\r
+  UINTN                       PackageLength;\r
+  EFI_STATUS                  Status;\r
+  HII_IMAGE_PACKAGE_INSTANCE  *Package;\r
+\r
+\r
+  if (Private == NULL || PackageList == NULL || ResultSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (BufferSize > 0 && Buffer == NULL ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Package = PackageList->ImagePkg;\r
+\r
+  if (Package == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  PackageLength = Package->ImagePkgHdr.Header.Length;\r
+\r
+  if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
+    //\r
+    // Invoke registered notification function with EXPORT_PACK notify type\r
+    //\r
+    Status = InvokeRegisteredFunction (\r
+               Private,\r
+               EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+               (VOID *) Package,\r
+               EFI_HII_PACKAGE_IMAGES,\r
+               Handle\r
+               );\r
+    ASSERT_EFI_ERROR (Status);\r
+    ASSERT (Package->ImagePkgHdr.Header.Length ==\r
+            sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + Package->ImageBlockSize + Package->PaletteInfoSize);\r
+    //\r
+    // Copy Image package header,\r
+    // then justify the offset for image info and palette info in the header.\r
+    //\r
+    CopyMem (Buffer, &Package->ImagePkgHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));\r
+    Buffer = (UINT8 *) Buffer + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);\r
+\r
+    //\r
+    // Copy Image blocks information\r
+    //\r
+    if (Package->ImageBlockSize != 0) {\r
+      CopyMem (Buffer, Package->ImageBlock, Package->ImageBlockSize);\r
+      Buffer = (UINT8 *) Buffer + Package->ImageBlockSize;\r
+    }\r
+    //\r
+    // Copy Palette information\r
+    //\r
+    if (Package->PaletteInfoSize != 0) {\r
+      CopyMem (Buffer, Package->PaletteBlock, Package->PaletteInfoSize);\r
+      Buffer = (UINT8 *) Buffer + Package->PaletteInfoSize;\r
+    }\r
+  }\r
+\r
+  *ResultSize += PackageLength;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function deletes Image package from a package list node.\r
+\r
+  @param  Private                Hii database private data.\r
+  @param  Handle                 Handle of the package list which contains the to\r
+                                 be  removed Image packages.\r
+  @param  PackageList            Package List which contains the to be  removed\r
+                                 Image package.\r
+\r
+  @retval EFI_SUCCESS            Image Package(s) is deleted successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveImagePackages (\r
+  IN     HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN     EFI_HII_HANDLE                     Handle,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+  )\r
+{\r
+  HII_IMAGE_PACKAGE_INSTANCE      *Package;\r
+  EFI_STATUS                      Status;\r
+\r
+  Package = PackageList->ImagePkg;\r
+\r
+  //\r
+  // Image package does not exist, return directly.\r
+  //\r
+  if (Package == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Status = InvokeRegisteredFunction (\r
+             Private,\r
+             EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+             (VOID *) Package,\r
+             EFI_HII_PACKAGE_IMAGES,\r
+             Handle\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  PackageList->PackageListHdr.PackageLength -= Package->ImagePkgHdr.Header.Length;\r
+\r
+  SafeFreePool (Package->ImageBlock);\r
+  SafeFreePool (Package->PaletteBlock);\r
+  SafeFreePool (Package);\r
+\r
+  PackageList->ImagePkg = NULL;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function insert a Simple Font package to a package list node.\r
+\r
+  @param  PackageHdr             Pointer to a buffer stored with Simple Font\r
+                                 package information.\r
+  @param  NotifyType             The type of change concerning the database.\r
+  @param  PackageList            Pointer to a package list which will be inserted\r
+                                 to.\r
+  @param  Package                Created Simple Font package\r
+\r
+  @retval EFI_SUCCESS            Simple Font Package is inserted successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new\r
+                                 Simple Font package.\r
+  @retval EFI_INVALID_PARAMETER  PackageHdr is NULL or PackageList is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertSimpleFontPackage (\r
+  IN     VOID                               *PackageHdr,\r
+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  OUT HII_SIMPLE_FONT_PACKAGE_INSTANCE      **Package\r
+  )\r
+{\r
+  HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;\r
+  EFI_STATUS                       Status;\r
+  EFI_HII_PACKAGE_HEADER           Header;\r
+\r
+  if (PackageHdr == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Create a Simple Font package node\r
+  //\r
+  SimpleFontPackage = AllocateZeroPool (sizeof (HII_SIMPLE_FONT_PACKAGE_INSTANCE));\r
+  if (SimpleFontPackage == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+  SimpleFontPackage->Signature = HII_S_FONT_PACKAGE_SIGNATURE;\r
+\r
+  //\r
+  // Copy the Simple Font package.\r
+  //\r
+  CopyMem (&Header, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+  SimpleFontPackage->SimpleFontPkgHdr = AllocateZeroPool (Header.Length);\r
+  if (SimpleFontPackage->SimpleFontPkgHdr == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+\r
+  CopyMem (SimpleFontPackage->SimpleFontPkgHdr, PackageHdr, Header.Length);\r
+\r
+  //\r
+  // Insert to Simple Font package array\r
+  //\r
+  InsertTailList (&PackageList->SimpleFontPkgHdr, &SimpleFontPackage->SimpleFontEntry);\r
+  *Package = SimpleFontPackage;\r
+\r
+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+    PackageList->PackageListHdr.PackageLength += Header.Length;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+Error:\r
+\r
+  SafeFreePool (SimpleFontPackage->SimpleFontPkgHdr);\r
+  SafeFreePool (SimpleFontPackage);\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function exports SimpleFont packages to a buffer.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  Handle                 Identification of a package list.\r
+  @param  PackageList            Pointer to a package list which will be exported.\r
+  @param  UsedSize               The length of buffer be used.\r
+  @param  BufferSize             Length of the Buffer.\r
+  @param  Buffer                 Allocated space for storing exported data.\r
+  @param  ResultSize             The size of the already exported content of  this\r
+                                 package list.\r
+\r
+  @retval EFI_SUCCESS            SimpleFont Packages are exported successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportSimpleFontPackages (\r
+  IN HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN EFI_HII_HANDLE                     Handle,\r
+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  IN UINTN                              UsedSize,\r
+  IN UINTN                              BufferSize,\r
+  IN OUT VOID                           *Buffer,\r
+  IN OUT UINTN                          *ResultSize\r
+  )\r
+{\r
+  LIST_ENTRY                        *Link;\r
+  UINTN                             PackageLength;\r
+  EFI_STATUS                        Status;\r
+  HII_SIMPLE_FONT_PACKAGE_INSTANCE  *Package;\r
+\r
+  if (Private == NULL || PackageList == NULL || ResultSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (BufferSize > 0 && Buffer == NULL ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PackageLength = 0;\r
+  Status        = EFI_SUCCESS;\r
+\r
+  for (Link = PackageList->SimpleFontPkgHdr.ForwardLink; Link != &PackageList->SimpleFontPkgHdr; Link = Link->ForwardLink) {\r
+    Package = CR (Link, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);\r
+    PackageLength += Package->SimpleFontPkgHdr->Header.Length;\r
+    if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
+      //\r
+      // Invoke registered notification function with EXPORT_PACK notify type\r
+      //\r
+      Status = InvokeRegisteredFunction (\r
+                 Private,\r
+                 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+                 (VOID *) Package,\r
+                 EFI_HII_PACKAGE_SIMPLE_FONTS,\r
+                 Handle\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      //\r
+      // Copy SimpleFont package\r
+      //\r
+      CopyMem (Buffer, Package->SimpleFontPkgHdr, Package->SimpleFontPkgHdr->Header.Length);\r
+      Buffer = (UINT8 *) Buffer + Package->SimpleFontPkgHdr->Header.Length;\r
+    }\r
+  }\r
+\r
+  *ResultSize += PackageLength;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function deletes all Simple Font packages from a package list node.\r
+\r
+  @param  Private                Hii database private data.\r
+  @param  Handle                 Handle of the package list which contains the to\r
+                                 be  removed Simple Font packages.\r
+  @param  PackageList            Pointer to a package list that contains removing\r
+                                 packages.\r
+\r
+  @retval EFI_SUCCESS            Simple Font Package(s) is deleted successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveSimpleFontPackages (\r
+  IN     HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN     EFI_HII_HANDLE                     Handle,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+  )\r
+{\r
+  LIST_ENTRY                       *ListHead;\r
+  HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;\r
+  EFI_STATUS                       Status;\r
+\r
+  ListHead = &PackageList->SimpleFontPkgHdr;\r
+\r
+  while (!IsListEmpty (ListHead)) {\r
+    Package = CR (\r
+                ListHead->ForwardLink,\r
+                HII_SIMPLE_FONT_PACKAGE_INSTANCE,\r
+                SimpleFontEntry,\r
+                HII_S_FONT_PACKAGE_SIGNATURE\r
+                );\r
+    Status = InvokeRegisteredFunction (\r
+               Private,\r
+               EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+               (VOID *) Package,\r
+               EFI_HII_PACKAGE_SIMPLE_FONTS,\r
+               Handle\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    RemoveEntryList (&Package->SimpleFontEntry);\r
+    PackageList->PackageListHdr.PackageLength -= Package->SimpleFontPkgHdr->Header.Length;\r
+    SafeFreePool (Package->SimpleFontPkgHdr);\r
+    SafeFreePool (Package);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function insert a Device path package to a package list node.\r
+\r
+  @param  DevicePath             Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol\r
+                                 instance\r
+  @param  NotifyType             The type of change concerning the database.\r
+  @param  PackageList            Pointer to a package list which will be inserted\r
+                                 to.\r
+\r
+  @retval EFI_SUCCESS            Device path Package is inserted successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new\r
+                                 Device path package.\r
+  @retval EFI_INVALID_PARAMETER  DevicePath is NULL or PackageList is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertDevicePathPackage (\r
+  IN     EFI_DEVICE_PATH_PROTOCOL           *DevicePath,\r
+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+  )\r
+{\r
+  UINT32                           PackageLength;\r
+  EFI_HII_PACKAGE_HEADER           Header;\r
+\r
+  if (DevicePath == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Less than one device path package is allowed in one package list.\r
+  //\r
+  if (PackageList->DevicePathPkg != NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PackageLength = (UINT32) GetDevicePathSize (DevicePath) + sizeof (EFI_HII_PACKAGE_HEADER);\r
+  PackageList->DevicePathPkg = (UINT8 *) AllocateZeroPool (PackageLength);\r
+  if (PackageList->DevicePathPkg == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Header.Length = PackageLength;\r
+  Header.Type   = EFI_HII_PACKAGE_DEVICE_PATH;\r
+  CopyMem (PackageList->DevicePathPkg, &Header, sizeof (EFI_HII_PACKAGE_HEADER));\r
+  CopyMem (\r
+    PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER),\r
+    DevicePath,\r
+    PackageLength - sizeof (EFI_HII_PACKAGE_HEADER)\r
+    );\r
+\r
+  //\r
+  // Since Device Path package is created by NewPackageList, either NEW_PACK\r
+  // or ADD_PACK should increase the length of package list.\r
+  //\r
+  PackageList->PackageListHdr.PackageLength += PackageLength;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function exports device path package to a buffer.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  Handle                 Identification of a package list.\r
+  @param  PackageList            Pointer to a package list which will be exported.\r
+  @param  UsedSize               The length of buffer be used.\r
+  @param  BufferSize             Length of the Buffer.\r
+  @param  Buffer                 Allocated space for storing exported data.\r
+  @param  ResultSize             The size of the already exported content of  this\r
+                                 package list.\r
+\r
+  @retval EFI_SUCCESS            Device path Package is exported successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportDevicePathPackage (\r
+  IN HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN EFI_HII_HANDLE                     Handle,\r
+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  IN UINTN                              UsedSize,\r
+  IN UINTN                              BufferSize,\r
+  IN OUT VOID                           *Buffer,\r
+  IN OUT UINTN                          *ResultSize\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  UINT8                            *Package;\r
+  EFI_HII_PACKAGE_HEADER           Header;\r
+\r
+  if (Private == NULL || PackageList == NULL || ResultSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (BufferSize > 0 && Buffer == NULL ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Package = PackageList->DevicePathPkg;\r
+\r
+  if (Package == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+  if (Header.Length + *ResultSize + UsedSize <= BufferSize) {\r
+    //\r
+    // Invoke registered notification function with EXPORT_PACK notify type\r
+    //\r
+    Status = InvokeRegisteredFunction (\r
+               Private,\r
+               EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+               (VOID *) Package,\r
+               EFI_HII_PACKAGE_DEVICE_PATH,\r
+               Handle\r
+               );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Copy Device path package\r
+    //\r
+    CopyMem (Buffer, Package, Header.Length);\r
+  }\r
+\r
+  *ResultSize += Header.Length;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function deletes Device Path package from a package list node.\r
+\r
+  @param  Private                Hii database private data.\r
+  @param  Handle                 Handle of the package list.\r
+  @param  PackageList            Package List which contains the to be  removed\r
+                                 Device Path package.\r
+\r
+  @retval EFI_SUCCESS            Device Path Package is deleted successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveDevicePathPackage (\r
+  IN     HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN     EFI_HII_HANDLE                     Handle,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  UINT8                            *Package;\r
+  EFI_HII_PACKAGE_HEADER           Header;\r
+\r
+  Package = PackageList->DevicePathPkg;\r
+\r
+  //\r
+  // No device path, return directly.\r
+  //\r
+  if (Package == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Status = InvokeRegisteredFunction (\r
+             Private,\r
+             EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+             (VOID *) Package,\r
+             EFI_HII_PACKAGE_DEVICE_PATH,\r
+             Handle\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+  PackageList->PackageListHdr.PackageLength -= Header.Length;\r
+\r
+  SafeFreePool (Package);\r
+\r
+  PackageList->DevicePathPkg = NULL;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function will insert a device path package to package list firstly then\r
+  invoke notification functions if any.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  NotifyType             The type of change concerning the database.\r
+  @param  DevicePath             Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol\r
+                                 instance\r
+  @param  DatabaseRecord         Pointer to a database record contains  a package\r
+                                 list which will be inserted to.\r
+\r
+  @retval EFI_SUCCESS            Device path Package is inserted successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new\r
+                                 Device path package.\r
+  @retval EFI_INVALID_PARAMETER  DevicePath is NULL or PackageList is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+AddDevicePathPackage (\r
+  IN HII_DATABASE_PRIVATE_DATA        *Private,\r
+  IN EFI_HII_DATABASE_NOTIFY_TYPE     NotifyType,\r
+  IN EFI_DEVICE_PATH_PROTOCOL         *DevicePath,\r
+  IN OUT HII_DATABASE_RECORD          *DatabaseRecord\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+\r
+  if (DevicePath == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  ASSERT (Private != NULL);\r
+  ASSERT (DatabaseRecord != NULL);\r
+\r
+  //\r
+  // Create a device path package and insert to packagelist\r
+  //\r
+  Status = InsertDevicePathPackage (\r
+               DevicePath,\r
+               NotifyType,\r
+               DatabaseRecord->PackageList\r
+               );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return InvokeRegisteredFunction (\r
+            Private,\r
+            NotifyType,\r
+            (VOID *) DatabaseRecord->PackageList->DevicePathPkg,\r
+            EFI_HII_PACKAGE_DEVICE_PATH,\r
+            DatabaseRecord->Handle\r
+            );\r
+}\r
+\r
+\r
+/**\r
+  This function insert a Keyboard Layout package to a package list node.\r
+\r
+  @param  PackageHdr             Pointer to a buffer stored with Keyboard Layout\r
+                                 package information.\r
+  @param  NotifyType             The type of change concerning the database.\r
+  @param  PackageList            Pointer to a package list which will be inserted\r
+                                 to.\r
+  @param  Package                Created Keyboard Layout package\r
+\r
+  @retval EFI_SUCCESS            Keyboard Layout Package is inserted successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new\r
+                                 Keyboard Layout package.\r
+  @retval EFI_INVALID_PARAMETER  PackageHdr is NULL or PackageList is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertKeyboardLayoutPackage (\r
+  IN     VOID                               *PackageHdr,\r
+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  OUT HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE  **Package\r
+  )\r
+{\r
+  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;\r
+  EFI_HII_PACKAGE_HEADER               PackageHeader;\r
+  EFI_STATUS                           Status;\r
+\r
+  if (PackageHdr == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+  //\r
+  // Create a Keyboard Layout package node\r
+  //\r
+  KeyboardLayoutPackage = AllocateZeroPool (sizeof (HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE));\r
+  if (KeyboardLayoutPackage == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+  KeyboardLayoutPackage->Signature = HII_KB_LAYOUT_PACKAGE_SIGNATURE;\r
+\r
+  KeyboardLayoutPackage->KeyboardPkg = (UINT8 *) AllocateZeroPool (PackageHeader.Length);\r
+  if (KeyboardLayoutPackage->KeyboardPkg == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+\r
+  CopyMem (KeyboardLayoutPackage->KeyboardPkg, PackageHdr, PackageHeader.Length);\r
+  InsertTailList (&PackageList->KeyboardLayoutHdr, &KeyboardLayoutPackage->KeyboardEntry);\r
+\r
+  *Package = KeyboardLayoutPackage;\r
+\r
+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+    PackageList->PackageListHdr.PackageLength += PackageHeader.Length;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+Error:\r
+\r
+  SafeFreePool (KeyboardLayoutPackage->KeyboardPkg);\r
+  SafeFreePool (KeyboardLayoutPackage);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function exports Keyboard Layout packages to a buffer.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  Handle                 Identification of a package list.\r
+  @param  PackageList            Pointer to a package list which will be exported.\r
+  @param  UsedSize               The length of buffer be used.\r
+  @param  BufferSize             Length of the Buffer.\r
+  @param  Buffer                 Allocated space for storing exported data.\r
+  @param  ResultSize             The size of the already exported content of  this\r
+                                 package list.\r
+\r
+  @retval EFI_SUCCESS            Keyboard Layout Packages are exported\r
+                                 successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportKeyboardLayoutPackages (\r
+  IN HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN EFI_HII_HANDLE                     Handle,\r
+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  IN UINTN                              UsedSize,\r
+  IN UINTN                              BufferSize,\r
+  IN OUT VOID                           *Buffer,\r
+  IN OUT UINTN                          *ResultSize\r
+  )\r
+{\r
+  LIST_ENTRY                           *Link;\r
+  UINTN                                PackageLength;\r
+  EFI_STATUS                           Status;\r
+  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;\r
+  EFI_HII_PACKAGE_HEADER               PackageHeader;\r
+\r
+  if (Private == NULL || PackageList == NULL || ResultSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (BufferSize > 0 && Buffer == NULL ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PackageLength = 0;\r
+  Status        = EFI_SUCCESS;\r
+\r
+  for (Link = PackageList->KeyboardLayoutHdr.ForwardLink; Link != &PackageList->KeyboardLayoutHdr; Link = Link->ForwardLink) {\r
+    Package = CR (Link, HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE, KeyboardEntry, HII_KB_LAYOUT_PACKAGE_SIGNATURE);\r
+    CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));\r
+    PackageLength += PackageHeader.Length;\r
+    if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
+      //\r
+      // Invoke registered notification function with EXPORT_PACK notify type\r
+      //\r
+      Status = InvokeRegisteredFunction (\r
+                 Private,\r
+                 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+                 (EFI_HII_PACKAGE_HEADER *) Package,\r
+                 EFI_HII_PACKAGE_KEYBOARD_LAYOUT,\r
+                 Handle\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      //\r
+      // Copy Keyboard Layout package\r
+      //\r
+      CopyMem (Buffer, Package->KeyboardPkg, PackageHeader.Length);\r
+      Buffer = (UINT8 *) Buffer + PackageHeader.Length;\r
+    }\r
+  }\r
+\r
+  *ResultSize += PackageLength;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function deletes all Keyboard Layout packages from a package list node.\r
+\r
+  @param  Private                Hii database private data.\r
+  @param  Handle                 Handle of the package list which contains the to\r
+                                 be  removed Keyboard Layout packages.\r
+  @param  PackageList            Pointer to a package list that contains removing\r
+                                 packages.\r
+\r
+  @retval EFI_SUCCESS            Keyboard Layout Package(s) is deleted\r
+                                 successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveKeyboardLayoutPackages (\r
+  IN     HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN     EFI_HII_HANDLE                     Handle,\r
+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+  )\r
+{\r
+  LIST_ENTRY                           *ListHead;\r
+  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;\r
+  EFI_HII_PACKAGE_HEADER               PackageHeader;\r
+  EFI_STATUS                           Status;\r
+\r
+  ListHead = &PackageList->KeyboardLayoutHdr;\r
+\r
+  while (!IsListEmpty (ListHead)) {\r
+    Package = CR (\r
+                ListHead->ForwardLink,\r
+                HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,\r
+                KeyboardEntry,\r
+                HII_KB_LAYOUT_PACKAGE_SIGNATURE\r
+                );\r
+    Status = InvokeRegisteredFunction (\r
+               Private,\r
+               EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+               (VOID *) Package,\r
+               EFI_HII_PACKAGE_KEYBOARD_LAYOUT,\r
+               Handle\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    RemoveEntryList (&Package->KeyboardEntry);\r
+    CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));\r
+    PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;\r
+    SafeFreePool (Package->KeyboardPkg);\r
+    SafeFreePool (Package);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function will insert a package list to hii database firstly then\r
+  invoke notification functions if any. It is the worker function of\r
+  HiiNewPackageList and HiiUpdatePackageList.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  NotifyType             The type of change concerning the database.\r
+  @param  PackageList            Pointer to a package list.\r
+  @param  DatabaseRecord         Pointer to a database record contains  a package\r
+                                 list instance which will be inserted to.\r
+\r
+  @retval EFI_SUCCESS            All incoming packages are inserted to current\r
+                                 database.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new\r
+                                 Device path package.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+AddPackages (\r
+  IN HII_DATABASE_PRIVATE_DATA         *Private,\r
+  IN EFI_HII_DATABASE_NOTIFY_TYPE      NotifyType,\r
+  IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,\r
+  IN OUT   HII_DATABASE_RECORD         *DatabaseRecord\r
+  )\r
+{\r
+  EFI_STATUS                           Status;\r
+  HII_GUID_PACKAGE_INSTANCE            *GuidPackage;\r
+  HII_IFR_PACKAGE_INSTANCE             *FormPackage;\r
+  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;\r
+  HII_STRING_PACKAGE_INSTANCE          *StringPackage;\r
+  HII_FONT_PACKAGE_INSTANCE            *FontPackage;\r
+  HII_SIMPLE_FONT_PACKAGE_INSTANCE     *SimpleFontPackage;\r
+  HII_IMAGE_PACKAGE_INSTANCE           *ImagePackage;\r
+  EFI_HII_PACKAGE_HEADER               *PackageHdrPtr;\r
+  EFI_HII_PACKAGE_HEADER               PackageHeader;\r
+  UINT32                               OldPackageListLen;\r
+\r
+  //\r
+  // Process the package list header\r
+  //\r
+  OldPackageListLen = DatabaseRecord->PackageList->PackageListHdr.PackageLength;\r
+  CopyMem (\r
+    &DatabaseRecord->PackageList->PackageListHdr,\r
+    (VOID *) PackageList,\r
+    sizeof (EFI_HII_PACKAGE_LIST_HEADER)\r
+    );\r
+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+    DatabaseRecord->PackageList->PackageListHdr.PackageLength = OldPackageListLen;\r
+  }\r
+\r
+  PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
+  CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  while (PackageHeader.Type != EFI_HII_PACKAGE_END) {\r
+    switch (PackageHeader.Type) {\r
+    case EFI_HII_PACKAGE_TYPE_GUID:\r
+      Status = InsertGuidPackage (\r
+                 PackageHdrPtr,\r
+                 NotifyType,\r
+                 DatabaseRecord->PackageList,\r
+                 &GuidPackage\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Status = InvokeRegisteredFunction (\r
+                 Private,\r
+                 NotifyType,\r
+                 (VOID *) GuidPackage,\r
+                 (UINT8) (PackageHeader.Type),\r
+                 DatabaseRecord->Handle\r
+                 );\r
+      break;\r
+    case EFI_HII_PACKAGE_FORM:\r
+      Status = InsertFormPackage (\r
+                 PackageHdrPtr,\r
+                 NotifyType,\r
+                 DatabaseRecord->PackageList,\r
+                 &FormPackage\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Status = InvokeRegisteredFunction (\r
+                 Private,\r
+                 NotifyType,\r
+                 (VOID *) FormPackage,\r
+                 (UINT8) (PackageHeader.Type),\r
+                 DatabaseRecord->Handle\r
+                 );\r
+      break;\r
+    case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
+      Status = InsertKeyboardLayoutPackage (\r
+                 PackageHdrPtr,\r
+                 NotifyType,\r
+                 DatabaseRecord->PackageList,\r
+                 &KeyboardLayoutPackage\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Status = InvokeRegisteredFunction (\r
+                 Private,\r
+                 NotifyType,\r
+                 (VOID *) KeyboardLayoutPackage,\r
+                 (UINT8) (PackageHeader.Type),\r
+                 DatabaseRecord->Handle\r
+                 );\r
+      break;\r
+    case EFI_HII_PACKAGE_STRINGS:\r
+      Status = InsertStringPackage (\r
+                 Private,\r
+                 PackageHdrPtr,\r
+                 NotifyType,\r
+                 DatabaseRecord->PackageList,\r
+                 &StringPackage\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Status = InvokeRegisteredFunction (\r
+                 Private,\r
+                 NotifyType,\r
+                 (VOID *) StringPackage,\r
+                 (UINT8) (PackageHeader.Type),\r
+                 DatabaseRecord->Handle\r
+                 );\r
+      break;\r
+    case EFI_HII_PACKAGE_FONTS:\r
+      Status = InsertFontPackage (\r
+                 Private,\r
+                 PackageHdrPtr,\r
+                 NotifyType,\r
+                 DatabaseRecord->PackageList,\r
+                 &FontPackage\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Status = InvokeRegisteredFunction (\r
+                 Private,\r
+                 NotifyType,\r
+                 (VOID *) FontPackage,\r
+                 (UINT8) (PackageHeader.Type),\r
+                 DatabaseRecord->Handle\r
+                 );\r
+      break;\r
+    case EFI_HII_PACKAGE_IMAGES:\r
+      Status = InsertImagePackage (\r
+                 PackageHdrPtr,\r
+                 NotifyType,\r
+                 DatabaseRecord->PackageList,\r
+                 &ImagePackage\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Status = InvokeRegisteredFunction (\r
+                 Private,\r
+                 NotifyType,\r
+                 (VOID *) ImagePackage,\r
+                 (UINT8) (PackageHeader.Type),\r
+                 DatabaseRecord->Handle\r
+                 );\r
+      break;\r
+    case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
+      Status = InsertSimpleFontPackage (\r
+                 PackageHdrPtr,\r
+                 NotifyType,\r
+                 DatabaseRecord->PackageList,\r
+                 &SimpleFontPackage\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Status = InvokeRegisteredFunction (\r
+                 Private,\r
+                 NotifyType,\r
+                 (VOID *) SimpleFontPackage,\r
+                 (UINT8) (PackageHeader.Type),\r
+                 DatabaseRecord->Handle\r
+                 );\r
+      break;\r
+    case EFI_HII_PACKAGE_DEVICE_PATH:\r
+      Status = AddDevicePathPackage (\r
+                 Private,\r
+                 NotifyType,\r
+                 (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8 *) PackageHdrPtr + sizeof (EFI_HII_PACKAGE_HEADER)),\r
+                 DatabaseRecord\r
+                 );\r
+      break;\r
+    default:\r
+      break;\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    //\r
+    // goto header of next package\r
+    //\r
+    PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHdrPtr + PackageHeader.Length);\r
+    CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function exports a package list to a buffer. It is the worker function\r
+  of HiiExportPackageList.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  Handle                 Identification of a package list.\r
+  @param  PackageList            Pointer to a package list which will be exported.\r
+  @param  UsedSize               The length of buffer has been used by exporting\r
+                                 package lists when Handle is NULL.\r
+  @param  BufferSize             Length of the Buffer.\r
+  @param  Buffer                 Allocated space for storing exported data.\r
+\r
+  @retval EFI_SUCCESS            Keyboard Layout Packages are exported\r
+                                 successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportPackageList (\r
+  IN HII_DATABASE_PRIVATE_DATA          *Private,\r
+  IN EFI_HII_HANDLE                     Handle,\r
+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+  IN OUT UINTN                          *UsedSize,\r
+  IN UINTN                              BufferSize,\r
+  OUT EFI_HII_PACKAGE_LIST_HEADER       *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  UINTN                               ResultSize;\r
+  EFI_HII_PACKAGE_HEADER              EndofPackageList;\r
+\r
+  ASSERT (Private != NULL || PackageList != NULL || UsedSize != NULL);\r
+  ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
+  ASSERT (IsHiiHandleValid (Handle));\r
+\r
+  if (BufferSize > 0 && Buffer == NULL ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Copy the package list header\r
+  // ResultSize indicates the length of the exported bytes of this package list\r
+  //\r
+  ResultSize = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+  if (ResultSize + *UsedSize <= BufferSize) {\r
+    CopyMem ((VOID *) Buffer, PackageList, ResultSize);\r
+  }\r
+  //\r
+  // Copy the packages and invoke EXPORT_PACK notify functions if exists.\r
+  //\r
+  Status = ExportGuidPackages (\r
+             Private,\r
+             Handle,\r
+             PackageList,\r
+             *UsedSize,\r
+             BufferSize,\r
+             (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+             &ResultSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  Status = ExportFormPackages (\r
+             Private,\r
+             Handle,\r
+             PackageList,\r
+             *UsedSize,\r
+             BufferSize,\r
+             (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+             &ResultSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  Status = ExportKeyboardLayoutPackages (\r
+             Private,\r
+             Handle,\r
+             PackageList,\r
+             *UsedSize,\r
+             BufferSize,\r
+             (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+             &ResultSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  Status = ExportStringPackages (\r
+             Private,\r
+             Handle,\r
+             PackageList,\r
+             *UsedSize,\r
+             BufferSize,\r
+             (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+             &ResultSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  Status = ExportFontPackages (\r
+             Private,\r
+             Handle,\r
+             PackageList,\r
+             *UsedSize,\r
+             BufferSize,\r
+             (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+             &ResultSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  Status = ExportImagePackages (\r
+             Private,\r
+             Handle,\r
+             PackageList,\r
+             *UsedSize,\r
+             BufferSize,\r
+             (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+             &ResultSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  Status = ExportSimpleFontPackages (\r
+             Private,\r
+             Handle,\r
+             PackageList,\r
+             *UsedSize,\r
+             BufferSize,\r
+             (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+             &ResultSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  Status = ExportDevicePathPackage (\r
+             Private,\r
+             Handle,\r
+             PackageList,\r
+             *UsedSize,\r
+             BufferSize,\r
+             (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+             &ResultSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Append the package list end.\r
+  //\r
+  EndofPackageList.Length = sizeof (EFI_HII_PACKAGE_HEADER);\r
+  EndofPackageList.Type   = EFI_HII_PACKAGE_END;\r
+  if (ResultSize + *UsedSize + sizeof (EFI_HII_PACKAGE_HEADER) <= BufferSize) {\r
+    CopyMem (\r
+      (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+      (VOID *) &EndofPackageList,\r
+      sizeof (EFI_HII_PACKAGE_HEADER)\r
+      );\r
+  }\r
+\r
+  *UsedSize += ResultSize + sizeof (EFI_HII_PACKAGE_HEADER);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function adds the packages in the package list to the database and returns a handle. If there is a\r
+  EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then this function will\r
+  create a package of type EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list.\r
+\r
+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+                                 instance.\r
+  @param  PackageList            A pointer to an EFI_HII_PACKAGE_LIST_HEADER\r
+                                 structure.\r
+  @param  DriverHandle           Associate the package list with this EFI handle.\r
+  @param  Handle                 A pointer to the EFI_HII_HANDLE instance.\r
+\r
+  @retval EFI_SUCCESS            The package list associated with the Handle was\r
+                                 added to the HII database.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new\r
+                                 database contents.\r
+  @retval EFI_INVALID_PARAMETER  PackageList is NULL or Handle is NULL.\r
+  @retval EFI_INVALID_PARAMETER  PackageListGuid already exists in database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiNewPackageList (\r
+  IN CONST EFI_HII_DATABASE_PROTOCOL    *This,\r
+  IN CONST EFI_HII_PACKAGE_LIST_HEADER  *PackageList,\r
+  IN CONST EFI_HANDLE                   DriverHandle,\r
+  OUT EFI_HII_HANDLE                    *Handle\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  HII_DATABASE_RECORD                 *DatabaseRecord;\r
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;\r
+  LIST_ENTRY                          *Link;\r
+  EFI_GUID                            PackageListGuid;\r
+\r
+  if (This == NULL || PackageList == NULL || Handle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  CopyMem (&PackageListGuid, (VOID *) PackageList, sizeof (EFI_GUID));\r
+\r
+  //\r
+  // Check the Package list GUID to guarantee this GUID is unique in database.\r
+  //\r
+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+    DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if (CompareGuid (\r
+          &(DatabaseRecord->PackageList->PackageListHdr.PackageListGuid),\r
+          &PackageListGuid\r
+          )\r
+        ) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Build a PackageList node\r
+  //\r
+  Status = GenerateHiiDatabaseRecord (Private, &DatabaseRecord);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Fill in information of the created Package List node\r
+  // according to incoming package list.\r
+  //\r
+  Status = AddPackages (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, PackageList, DatabaseRecord);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  DatabaseRecord->DriverHandle = DriverHandle;\r
+\r
+  //\r
+  // Create a Device path package and add into the package list if exists.\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  DriverHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &DevicePath\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = AddDevicePathPackage (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, DevicePath, DatabaseRecord);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  *Handle = DatabaseRecord->Handle;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function removes the package list that is associated with a handle Handle\r
+  from the HII database. Before removing the package, any registered functions\r
+  with the notification type REMOVE_PACK and the same package type will be called.\r
+\r
+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+                                 instance.\r
+  @param  Handle                 The handle that was registered to the data that is\r
+                                 requested  for removal.\r
+\r
+  @retval EFI_SUCCESS            The data associated with the Handle was removed\r
+                                 from  the HII database.\r
+  @retval EFI_NOT_FOUND          The specified PackageList could not be found in\r
+                                 database.\r
+  @retval EFI_INVALID_PARAMETER  The Handle was not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiRemovePackageList (\r
+  IN CONST EFI_HII_DATABASE_PROTOCOL    *This,\r
+  IN EFI_HII_HANDLE                     Handle\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  LIST_ENTRY                          *Link;\r
+  HII_DATABASE_RECORD                 *Node;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageList;\r
+  HII_HANDLE                          *HiiHandle;\r
+\r
+  if (This == NULL || !IsHiiHandleValid (Handle)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // Get the packagelist to be removed.\r
+  //\r
+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if (Node->Handle == Handle) {\r
+      PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);\r
+      ASSERT (PackageList != NULL);\r
+\r
+      //\r
+      // Call registered functions with REMOVE_PACK before removing packages\r
+      // then remove them.\r
+      //\r
+      Status = RemoveGuidPackages (Private, Handle, PackageList);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Status = RemoveFormPackages (Private, Handle, PackageList);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Status = RemoveKeyboardLayoutPackages (Private, Handle, PackageList);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Status = RemoveStringPackages (Private, Handle, PackageList);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Status = RemoveFontPackages (Private, Handle, PackageList);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Status = RemoveImagePackages (Private, Handle, PackageList);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Status = RemoveSimpleFontPackages (Private, Handle, PackageList);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Status = RemoveDevicePathPackage (Private, Handle, PackageList);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Free resources of the package list\r
+      //\r
+      RemoveEntryList (&Node->DatabaseEntry);\r
+\r
+      HiiHandle = (HII_HANDLE *) Handle;\r
+      RemoveEntryList (&HiiHandle->Handle);\r
+      Private->HiiHandleCount--;\r
+      ASSERT (Private->HiiHandleCount >= 0);\r
+\r
+      HiiHandle->Signature = 0;\r
+      SafeFreePool (HiiHandle);\r
+      SafeFreePool (Node->PackageList);\r
+      SafeFreePool (Node);\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  This function updates the existing package list (which has the specified Handle)\r
+  in the HII databases, using the new package list specified by PackageList.\r
+\r
+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+                                 instance.\r
+  @param  Handle                 The handle that was registered to the data that is\r
+                                  requested to be updated.\r
+  @param  PackageList            A pointer to an EFI_HII_PACKAGE_LIST_HEADER\r
+                                 package.\r
+\r
+  @retval EFI_SUCCESS            The HII database was successfully updated.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate enough memory for the updated\r
+                                 database.\r
+  @retval EFI_INVALID_PARAMETER  Handle or PackageList was NULL.\r
+  @retval EFI_NOT_FOUND          The Handle was not valid or could not be found in\r
+                                 database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiUpdatePackageList (\r
+  IN CONST EFI_HII_DATABASE_PROTOCOL    *This,\r
+  IN EFI_HII_HANDLE                     Handle,\r
+  IN CONST EFI_HII_PACKAGE_LIST_HEADER  *PackageList\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  LIST_ENTRY                          *Link;\r
+  HII_DATABASE_RECORD                 *Node;\r
+  EFI_HII_PACKAGE_HEADER              *PackageHdrPtr;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *OldPackageList;\r
+  EFI_HII_PACKAGE_HEADER              PackageHeader;\r
+\r
+  if (This == NULL || PackageList == NULL || Handle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!IsHiiHandleValid (Handle)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // Get original packagelist to be updated\r
+  //\r
+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if (Node->Handle == Handle) {\r
+      OldPackageList = Node->PackageList;\r
+      //\r
+      // Remove the package if its type matches one of the package types which is\r
+      // contained in the new package list.\r
+      //\r
+      CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+      while (PackageHeader.Type != EFI_HII_PACKAGE_END) {\r
+        switch (PackageHeader.Type) {\r
+        case EFI_HII_PACKAGE_TYPE_GUID:\r
+          Status = RemoveGuidPackages (Private, Handle, OldPackageList);\r
+          break;\r
+        case EFI_HII_PACKAGE_FORM:\r
+          Status = RemoveFormPackages (Private, Handle, OldPackageList);\r
+          break;\r
+        case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
+          Status = RemoveKeyboardLayoutPackages (Private, Handle, OldPackageList);\r
+          break;\r
+        case EFI_HII_PACKAGE_STRINGS:\r
+          Status = RemoveStringPackages (Private, Handle, OldPackageList);\r
+          break;\r
+        case EFI_HII_PACKAGE_FONTS:\r
+          Status = RemoveFontPackages (Private, Handle, OldPackageList);\r
+          break;\r
+        case EFI_HII_PACKAGE_IMAGES:\r
+          Status = RemoveImagePackages (Private, Handle, OldPackageList);\r
+          break;\r
+        case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
+          Status = RemoveSimpleFontPackages (Private, Handle, OldPackageList);\r
+          break;\r
+        case EFI_HII_PACKAGE_DEVICE_PATH:\r
+          Status = RemoveDevicePathPackage (Private, Handle, OldPackageList);\r
+          break;\r
+        }\r
+\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+\r
+        PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHdrPtr + PackageHeader.Length);\r
+        CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+      }\r
+\r
+      //\r
+      // Add all of the packages within the new package list\r
+      //\r
+      return AddPackages (Private, EFI_HII_DATABASE_NOTIFY_ADD_PACK, PackageList, Node);\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  This function returns a list of the package handles of the specified type\r
+  that are currently active in the database. The pseudo-type\r
+  EFI_HII_PACKAGE_TYPE_ALL will cause all package handles to be listed.\r
+\r
+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+                                 instance.\r
+  @param  PackageType            Specifies the package type of the packages to list\r
+                                 or EFI_HII_PACKAGE_TYPE_ALL for all packages to be\r
+                                 listed.\r
+  @param  PackageGuid            If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then\r
+                                 this  is the pointer to the GUID which must match\r
+                                 the Guid field of EFI_HII_GUID_PACKAGE_GUID_HDR.\r
+                                 Otherwise,  it must be NULL.\r
+  @param  HandleBufferLength     On input, a pointer to the length of the handle\r
+                                 buffer.  On output, the length of the handle\r
+                                 buffer that is required for the handles found.\r
+  @param  Handle                 An array of EFI_HII_HANDLE instances returned.\r
+\r
+  @retval EFI_SUCCESS            The matching handles are outputed successfully.\r
+  @retval EFI_BUFFER_TO_SMALL    The HandleBufferLength parameter indicates that\r
+                                 Handle is too small to support the number of\r
+                                 handles. HandleBufferLength is updated with a\r
+                                 value that will  enable the data to fit.\r
+  @retval EFI_NOT_FOUND          No matching handle could not be found in database.\r
+  @retval EFI_INVALID_PARAMETER  Handle or HandleBufferLength was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiListPackageLists (\r
+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,\r
+  IN  UINT8                             PackageType,\r
+  IN  CONST EFI_GUID                    *PackageGuid,\r
+  IN  OUT UINTN                         *HandleBufferLength,\r
+  OUT EFI_HII_HANDLE                    *Handle\r
+  )\r
+{\r
+  HII_GUID_PACKAGE_INSTANCE           *GuidPackage;\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  HII_DATABASE_RECORD                 *Node;\r
+  LIST_ENTRY                          *Link;\r
+  BOOLEAN                             Matched;\r
+  HII_HANDLE                          **Result;\r
+  UINTN                               ResultSize;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageList;\r
+  LIST_ENTRY                          *Link1;\r
+\r
+  //\r
+  // Check input parameters\r
+  //\r
+  if (This == NULL || HandleBufferLength == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (*HandleBufferLength > 0 && Handle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if ((PackageType == EFI_HII_PACKAGE_TYPE_GUID && PackageGuid == NULL) ||\r
+      (PackageType != EFI_HII_PACKAGE_TYPE_GUID && PackageGuid != NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private    = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  Matched    = FALSE;\r
+  Result     = (HII_HANDLE **) Handle;\r
+  ResultSize = 0;\r
+\r
+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);\r
+    switch (PackageType) {\r
+      case EFI_HII_PACKAGE_TYPE_GUID:\r
+        for (Link1 = PackageList->GuidPkgHdr.ForwardLink; Link1 != &PackageList->GuidPkgHdr; Link1 = Link1->ForwardLink) {\r
+          GuidPackage = CR (Link1, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);\r
+          if (CompareGuid (\r
+                (EFI_GUID *) PackageGuid,\r
+                (EFI_GUID *) (GuidPackage->GuidPkg + sizeof (EFI_HII_PACKAGE_HEADER))\r
+                )) {\r
+            Matched = TRUE;\r
+            break;\r
+          }\r
+        }\r
+        break;\r
+      case EFI_HII_PACKAGE_FORM:\r
+        if (!IsListEmpty (&PackageList->FormPkgHdr)) {\r
+          Matched = TRUE;\r
+        }\r
+        break;\r
+      case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
+        if (!IsListEmpty (&PackageList->KeyboardLayoutHdr)) {\r
+          Matched = TRUE;\r
+        }\r
+        break;\r
+      case EFI_HII_PACKAGE_STRINGS:\r
+        if (!IsListEmpty (&PackageList->StringPkgHdr)) {\r
+          Matched = TRUE;\r
+        }\r
+        break;\r
+      case EFI_HII_PACKAGE_FONTS:\r
+        if (!IsListEmpty (&PackageList->FontPkgHdr)) {\r
+          Matched = TRUE;\r
+        }\r
+        break;\r
+      case EFI_HII_PACKAGE_IMAGES:\r
+        if (PackageList->ImagePkg != NULL) {\r
+          Matched = TRUE;\r
+        }\r
+        break;\r
+      case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
+        if (!IsListEmpty (&PackageList->SimpleFontPkgHdr)) {\r
+          Matched = TRUE;\r
+        }\r
+        break;\r
+      case EFI_HII_PACKAGE_DEVICE_PATH:\r
+        if (PackageList->DevicePathPkg != NULL) {\r
+          Matched = TRUE;\r
+        }\r
+        break;\r
+        //\r
+        // Pesudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package handles\r
+        // to be listed.\r
+        //\r
+      case EFI_HII_PACKAGE_TYPE_ALL:\r
+        Matched = TRUE;\r
+        break;\r
+      default:\r
+        break;\r
+    }\r
+\r
+    //\r
+    // This active package list has the specified package type, list it.\r
+    //\r
+    if (Matched) {\r
+      ResultSize += sizeof (EFI_HII_HANDLE);\r
+      if (ResultSize <= *HandleBufferLength) {\r
+        *Result++ = Node->Handle;\r
+      }\r
+    }\r
+    Matched = FALSE;\r
+  }\r
+\r
+  if (ResultSize == 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (*HandleBufferLength < ResultSize) {\r
+    *HandleBufferLength = ResultSize;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  *HandleBufferLength = ResultSize;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function will export one or all package lists in the database to a buffer.\r
+  For each package list exported, this function will call functions registered\r
+  with EXPORT_PACK and then copy the package list to the buffer.\r
+\r
+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+                                 instance.\r
+  @param  Handle                 An EFI_HII_HANDLE that corresponds to the desired\r
+                                 package list in the HII database to export or NULL\r
+                                 to indicate  all package lists should be exported.\r
+  @param  BufferSize             On input, a pointer to the length of the buffer.\r
+                                 On output, the length of the buffer that is\r
+                                 required for the exported data.\r
+  @param  Buffer                 A pointer to a buffer that will contain the\r
+                                 results of  the export function.\r
+\r
+  @retval EFI_SUCCESS            Package exported.\r
+  @retval EFI_BUFFER_TO_SMALL    The HandleBufferLength parameter indicates that\r
+                                 Handle is too small to support the number of\r
+                                 handles.      HandleBufferLength is updated with a\r
+                                 value that will enable the data to fit.\r
+  @retval EFI_NOT_FOUND          The specifiecd Handle could not be found in the\r
+                                 current database.\r
+  @retval EFI_INVALID_PARAMETER  Handle or Buffer or BufferSize was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiExportPackageLists (\r
+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,\r
+  IN  EFI_HII_HANDLE                    Handle,\r
+  IN  OUT UINTN                         *BufferSize,\r
+  OUT EFI_HII_PACKAGE_LIST_HEADER       *Buffer\r
+  )\r
+{\r
+  LIST_ENTRY                          *Link;\r
+  EFI_STATUS                          Status;\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  HII_DATABASE_RECORD                 *Node;\r
+  UINTN                               UsedSize;\r
+\r
+  if (This == NULL || BufferSize == NULL || Handle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (*BufferSize > 0 && Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (!IsHiiHandleValid (Handle)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Private  = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  UsedSize = 0;\r
+\r
+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if (Handle == NULL) {\r
+      //\r
+      // Export all package lists in current hii database.\r
+      //\r
+      Status = ExportPackageList (\r
+                 Private,\r
+                 Node->Handle,\r
+                 (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList),\r
+                 &UsedSize,\r
+                 *BufferSize,\r
+                 (EFI_HII_PACKAGE_LIST_HEADER *)((UINT8 *) Buffer + UsedSize)\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+    else if (Handle != NULL && Node->Handle == Handle) {\r
+      Status = ExportPackageList (\r
+                 Private,\r
+                 Handle,\r
+                 (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList),\r
+                 &UsedSize,\r
+                 *BufferSize,\r
+                 Buffer\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+      if (*BufferSize < UsedSize) {\r
+        *BufferSize = UsedSize;\r
+        return EFI_BUFFER_TOO_SMALL;\r
+      }\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  if (Handle == NULL && UsedSize != 0) {\r
+    if (*BufferSize < UsedSize) {\r
+      *BufferSize = UsedSize;\r
+      return EFI_BUFFER_TOO_SMALL;\r
+    }\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  This function registers a function which will be called when specified actions related to packages of\r
+  the specified type occur in the HII database. By registering a function, other HII-related drivers are\r
+  notified when specific package types are added, removed or updated in the HII database.\r
+  Each driver or application which registers a notification should use\r
+  EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify() before exiting.\r
+\r
+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+                                 instance.\r
+  @param  PackageType            Specifies the package type of the packages to list\r
+                                 or EFI_HII_PACKAGE_TYPE_ALL for all packages to be\r
+                                 listed.\r
+  @param  PackageGuid            If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then\r
+                                 this is the pointer to the GUID which must match\r
+                                 the Guid field of\r
+                                 EFI_HII_GUID_PACKAGE_GUID_HDR. Otherwise, it must\r
+                                 be NULL.\r
+  @param  PackageNotifyFn        Points to the function to be called when the event\r
+                                 specified by\r
+                                 NotificationType occurs.\r
+  @param  NotifyType             Describes the types of notification which this\r
+                                 function will be receiving.\r
+  @param  NotifyHandle           Points to the unique handle assigned to the\r
+                                 registered notification. Can be used in\r
+                                 EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify()\r
+                                 to stop notifications.\r
+\r
+  @retval EFI_SUCCESS            Notification registered successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary data structures\r
+  @retval EFI_INVALID_PARAMETER  NotifyHandle is NULL.\r
+  @retval EFI_INVALID_PARAMETER  PackageGuid is not NULL when PackageType is not\r
+                                 EFI_HII_PACKAGE_TYPE_GUID.\r
+  @retval EFI_INVALID_PARAMETER  PackageGuid is NULL when PackageType is\r
+                                 EFI_HII_PACKAGE_TYPE_GUID.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiRegisterPackageNotify (\r
+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,\r
+  IN  UINT8                             PackageType,\r
+  IN  CONST EFI_GUID                    *PackageGuid,\r
+  IN  CONST EFI_HII_DATABASE_NOTIFY     PackageNotifyFn,\r
+  IN  EFI_HII_DATABASE_NOTIFY_TYPE      NotifyType,\r
+  OUT EFI_HANDLE                        *NotifyHandle\r
+  )\r
+{\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  HII_DATABASE_NOTIFY                 *Notify;\r
+  EFI_STATUS                          Status;\r
+\r
+  if (This == NULL || NotifyHandle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if ((PackageType == EFI_HII_PACKAGE_TYPE_GUID && PackageGuid == NULL) ||\r
+      (PackageType != EFI_HII_PACKAGE_TYPE_GUID && PackageGuid != NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // Allocate a notification node\r
+  //\r
+  Notify = (HII_DATABASE_NOTIFY *) AllocateZeroPool (sizeof (HII_DATABASE_NOTIFY));\r
+  if (Notify == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Generate a notify handle\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &Notify->NotifyHandle,\r
+                  &mHiiDatabaseNotifyGuid,\r
+                  NULL,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Fill in the information to the notification node\r
+  //\r
+  Notify->Signature       = HII_DATABASE_NOTIFY_SIGNATURE;\r
+  Notify->PackageType     = PackageType;\r
+  Notify->PackageGuid     = (EFI_GUID *) PackageGuid;\r
+  Notify->PackageNotifyFn = (EFI_HII_DATABASE_NOTIFY) PackageNotifyFn;\r
+  Notify->NotifyType      = NotifyType;\r
+\r
+  InsertTailList (&Private->DatabaseNotifyList, &Notify->DatabaseNotifyEntry);\r
+  *NotifyHandle = Notify->NotifyHandle;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Removes the specified HII database package-related notification.\r
+\r
+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+                                 instance.\r
+  @param  NotifyHandle           The handle of the notification function being\r
+                                 unregistered.\r
+\r
+  @retval EFI_SUCCESS            Notification is unregistered successfully.\r
+  @retval EFI_INVALID_PARAMETER  The Handle is invalid.\r
+  @retval EFI_NOT_FOUND          The incoming notification handle does not exist\r
+                                 in current hii database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiUnregisterPackageNotify (\r
+  IN CONST EFI_HII_DATABASE_PROTOCOL    *This,\r
+  IN EFI_HANDLE                         NotificationHandle\r
+  )\r
+{\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  HII_DATABASE_NOTIFY                 *Notify;\r
+  LIST_ENTRY                          *Link;\r
+  EFI_STATUS                          Status;\r
+\r
+  if (This == NULL || NotificationHandle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  NotificationHandle,\r
+                  &mHiiDatabaseNotifyGuid,\r
+                  NULL,\r
+                  NULL,\r
+                  NULL,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  for (Link = Private->DatabaseNotifyList.ForwardLink; Link != &Private->DatabaseNotifyList; Link = Link->ForwardLink) {\r
+    Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);\r
+    if (Notify->NotifyHandle == NotificationHandle) {\r
+      //\r
+      // Remove the matching notification node\r
+      //\r
+      RemoveEntryList (&Notify->DatabaseNotifyEntry);\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                      Notify->NotifyHandle,\r
+                      &mHiiDatabaseNotifyGuid,\r
+                      NULL,\r
+                      NULL\r
+                      );\r
+      ASSERT_EFI_ERROR (Status);\r
+      SafeFreePool (Notify);\r
+      Notify = NULL;\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  This routine retrieves an array of GUID values for each keyboard layout that\r
+  was previously registered in the system.\r
+\r
+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+                                 instance.\r
+  @param  KeyGuidBufferLength    On input, a pointer to the length of the keyboard\r
+                                 GUID  buffer. On output, the length of the handle\r
+                                 buffer  that is required for the handles found.\r
+  @param  KeyGuidBuffer          An array of keyboard layout GUID instances\r
+                                 returned.\r
+\r
+  @retval EFI_SUCCESS            KeyGuidBuffer was updated successfully.\r
+  @retval EFI_BUFFER_TOO_SMALL   The KeyGuidBufferLength parameter indicates\r
+                                 that KeyGuidBuffer is too small to support the\r
+                                 number of GUIDs. KeyGuidBufferLength is\r
+                                 updated with a value that will enable the data to\r
+                                 fit.\r
+  @retval EFI_INVALID_PARAMETER  The KeyGuidBuffer or KeyGuidBufferLength was NULL.\r
+  @retval EFI_NOT_FOUND          There was no keyboard layout.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiFindKeyboardLayouts (\r
+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,\r
+  IN  OUT UINT16                        *KeyGuidBufferLength,\r
+  OUT EFI_GUID                          *KeyGuidBuffer\r
+  )\r
+{\r
+  HII_DATABASE_PRIVATE_DATA            *Private;\r
+  HII_DATABASE_RECORD                  *Node;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE   *PackageList;\r
+  LIST_ENTRY                           *Link;\r
+  LIST_ENTRY                           *Link1;\r
+  UINT16                               ResultSize;\r
+  UINTN                                Index;\r
+  UINT16                               LayoutCount;\r
+  UINT16                               LayoutLength;\r
+  UINT8                                *Layout;\r
+  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;\r
+\r
+  if (This == NULL || KeyGuidBufferLength == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (*KeyGuidBufferLength > 0 && KeyGuidBuffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private     = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  ResultSize  = 0;\r
+\r
+  //\r
+  // Search all package lists in whole database to retrieve keyboard layout.\r
+  //\r
+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    PackageList = Node->PackageList;\r
+    for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;\r
+         Link1 != &PackageList->KeyboardLayoutHdr;\r
+         Link1 = Link1->ForwardLink\r
+        ) {\r
+      //\r
+      // Find out all Keyboard Layout packages in this package list.\r
+      //\r
+      Package = CR (\r
+                  Link1,\r
+                  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,\r
+                  KeyboardEntry,\r
+                  HII_KB_LAYOUT_PACKAGE_SIGNATURE\r
+                  );\r
+      Layout = (UINT8 *) Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);\r
+      CopyMem (\r
+        &LayoutCount,\r
+        (UINT8 *) Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER),\r
+        sizeof (UINT16)\r
+        );\r
+      for (Index = 0; Index < LayoutCount; Index++) {\r
+        ResultSize += sizeof (EFI_GUID);\r
+        if (ResultSize <= *KeyGuidBufferLength) {\r
+          CopyMem (KeyGuidBuffer + Index, Layout + sizeof (UINT16), sizeof (EFI_GUID));\r
+          CopyMem (&LayoutLength, Layout, sizeof (UINT16));\r
+          Layout = Layout + LayoutLength;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (ResultSize == 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (*KeyGuidBufferLength < ResultSize) {\r
+    *KeyGuidBufferLength = ResultSize;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  *KeyGuidBufferLength = ResultSize;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This routine retrieves the requested keyboard layout. The layout is a physical description of the keys\r
+  on a keyboard and the character(s) that are associated with a particular set of key strokes.\r
+\r
+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+                                 instance.\r
+  @param  KeyGuid                A pointer to the unique ID associated with a given\r
+                                 keyboard layout. If KeyGuid is NULL then the\r
+                                 current layout will be retrieved.\r
+  @param  KeyboardLayoutLength   On input, a pointer to the length of the\r
+                                 KeyboardLayout buffer.  On output, the length of\r
+                                 the data placed into KeyboardLayout.\r
+  @param  KeyboardLayout         A pointer to a buffer containing the retrieved\r
+                                 keyboard layout.\r
+\r
+  @retval EFI_SUCCESS            The keyboard layout was retrieved successfully.\r
+  @retval EFI_NOT_FOUND          The requested keyboard layout was not found.\r
+  @retval EFI_INVALID_PARAMETER  The KeyboardLayout or KeyboardLayoutLength was\r
+                                 NULL.\r
+  @retval EFI_BUFFER_TOO_SMALL   The KeyboardLayoutLength parameter indicates\r
+                                 that KeyboardLayout is too small to support the\r
+                                 requested keyboard layout. KeyboardLayoutLength is\r
+                                        updated with a value that will enable the\r
+                                 data to fit.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetKeyboardLayout (\r
+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,\r
+  IN  CONST EFI_GUID                          *KeyGuid,\r
+  IN OUT UINT16                         *KeyboardLayoutLength,\r
+  OUT EFI_HII_KEYBOARD_LAYOUT           *KeyboardLayout\r
+  )\r
+{\r
+  HII_DATABASE_PRIVATE_DATA            *Private;\r
+  HII_DATABASE_RECORD                  *Node;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE   *PackageList;\r
+  LIST_ENTRY                           *Link;\r
+  LIST_ENTRY                           *Link1;\r
+  UINTN                                Index;\r
+  UINT8                                *Layout;\r
+  UINT16                               LayoutCount;\r
+  UINT16                               LayoutLength;\r
+  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;\r
+\r
+  if (This == NULL || KeyboardLayoutLength == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (*KeyboardLayoutLength > 0 && KeyboardLayout == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  //\r
+  // Retrieve the current keyboard layout.\r
+  //\r
+  if (KeyGuid == NULL) {\r
+    if (Private->CurrentLayout == NULL) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+    CopyMem (&LayoutLength, Private->CurrentLayout, sizeof (UINT16));\r
+    if (*KeyboardLayoutLength < LayoutLength) {\r
+      *KeyboardLayoutLength = LayoutLength;\r
+      return EFI_BUFFER_TOO_SMALL;\r
+    }\r
+    CopyMem (KeyboardLayout, Private->CurrentLayout, LayoutLength);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);\r
+    for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;\r
+         Link1 != &PackageList->KeyboardLayoutHdr;\r
+         Link1 = Link1->ForwardLink\r
+        ) {\r
+      Package = CR (\r
+                  Link1,\r
+                  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,\r
+                  KeyboardEntry,\r
+                  HII_KB_LAYOUT_PACKAGE_SIGNATURE\r
+                  );\r
+\r
+      Layout = (UINT8 *) Package->KeyboardPkg +\r
+               sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);\r
+      CopyMem (&LayoutCount, Layout - sizeof (UINT16), sizeof (UINT16));\r
+      for (Index = 0; Index < LayoutCount; Index++) {\r
+        CopyMem (&LayoutLength, Layout, sizeof (UINT16));\r
+        if (CompareMem (Layout + sizeof (UINT16), KeyGuid, sizeof (EFI_GUID)) == 0) {\r
+          if (LayoutLength <= *KeyboardLayoutLength) {\r
+            CopyMem (KeyboardLayout, Layout, LayoutLength);\r
+            return EFI_SUCCESS;\r
+          } else {\r
+            *KeyboardLayoutLength = LayoutLength;\r
+            return EFI_BUFFER_TOO_SMALL;\r
+          }\r
+        }\r
+        Layout = Layout + LayoutLength;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  This routine sets the default keyboard layout to the one referenced by KeyGuid. When this routine\r
+  is called, an event will be signaled of the EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID\r
+  group type. This is so that agents which are sensitive to the current keyboard layout being changed\r
+  can be notified of this change.\r
+\r
+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+                                 instance.\r
+  @param  KeyGuid                A pointer to the unique ID associated with a given\r
+                                 keyboard layout.\r
+\r
+  @retval EFI_SUCCESS            The current keyboard layout was successfully set.\r
+  @retval EFI_NOT_FOUND          The referenced keyboard layout was not found, so\r
+                                 action was taken.\r
+  @retval EFI_INVALID_PARAMETER  The KeyGuid was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiSetKeyboardLayout (\r
+  IN CONST EFI_HII_DATABASE_PROTOCOL          *This,\r
+  IN CONST EFI_GUID                           *KeyGuid\r
+  )\r
+{\r
+  HII_DATABASE_PRIVATE_DATA            *Private;\r
+  EFI_HII_KEYBOARD_LAYOUT              *KeyboardLayout;\r
+  UINT16                               KeyboardLayoutLength;\r
+  EFI_STATUS                           Status;\r
+\r
+  if (This == NULL || KeyGuid == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // The specified GUID equals the current keyboard layout GUID,\r
+  // return directly.\r
+  //\r
+  if (CompareGuid (&Private->CurrentLayoutGuid, KeyGuid)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Try to find the incoming keyboard layout data in current database.\r
+  //\r
+  KeyboardLayoutLength = 0;\r
+  KeyboardLayout       = NULL;\r
+  Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    return Status;\r
+  }\r
+\r
+  KeyboardLayout = (EFI_HII_KEYBOARD_LAYOUT *) AllocateZeroPool (KeyboardLayoutLength);\r
+  ASSERT (KeyboardLayout != NULL);\r
+  Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Backup current keyboard layout.\r
+  //\r
+  CopyMem (&Private->CurrentLayoutGuid, KeyGuid, sizeof (EFI_GUID));\r
+  SafeFreePool(Private->CurrentLayout);\r
+  Private->CurrentLayout = KeyboardLayout;\r
+\r
+  //\r
+  // Signal EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group to notify\r
+  // current keyboard layout is changed.\r
+  //\r
+  Status = gBS->SignalEvent (gHiiKeyboardLayoutChanged);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Return the EFI handle associated with a package list.\r
+\r
+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+                                 instance.\r
+  @param  PackageListHandle      An EFI_HII_HANDLE that corresponds to the desired\r
+                                 package list in the HIIdatabase.\r
+  @param  DriverHandle           On return, contains the EFI_HANDLE which was\r
+                                 registered with the package list in\r
+                                 NewPackageList().\r
+\r
+  @retval EFI_SUCCESS            The DriverHandle was returned successfully.\r
+  @retval EFI_INVALID_PARAMETER  The PackageListHandle was not valid or\r
+                                 DriverHandle was NULL.\r
+  @retval EFI_NOT_FOUND          This PackageList handle can not be found in\r
+                                 current database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetPackageListHandle (\r
+  IN  CONST EFI_HII_DATABASE_PROTOCOL         *This,\r
+  IN  EFI_HII_HANDLE                    PackageListHandle,\r
+  OUT EFI_HANDLE                        *DriverHandle\r
+  )\r
+{\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  HII_DATABASE_RECORD                 *Node;\r
+  LIST_ENTRY                          *Link;\r
+\r
+  if (This == NULL || DriverHandle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!IsHiiHandleValid (PackageListHandle)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if (Node->Handle == PackageListHandle) {\r
+      *DriverHandle = Node->DriverHandle;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c
new file mode 100644 (file)
index 0000000..a5363d4
--- /dev/null
@@ -0,0 +1,2395 @@
+/** @file\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+    Font.c\r
+\r
+Abstract:\r
+\r
+    Implementation for EFI_HII_FONT_PROTOCOL.\r
+\r
+Revision History\r
+\r
+\r
+**/\r
+\r
+\r
+#include "HiiDatabase.h"\r
+\r
+static EFI_GRAPHICS_OUTPUT_BLT_PIXEL        mEfiColors[16] = {\r
+  //\r
+  // B     G     R\r
+  //\r
+  0x00, 0x00, 0x00, 0x00,  // BLACK\r
+  0x98, 0x00, 0x00, 0x00,  // BLUE\r
+  0x00, 0x98, 0x00, 0x00,  // GREEN\r
+  0x98, 0x98, 0x00, 0x00,  // CYAN\r
+  0x00, 0x00, 0x98, 0x00,  // RED\r
+  0x98, 0x00, 0x98, 0x00,  // MAGENTA\r
+  0x00, 0x98, 0x98, 0x00,  // BROWN\r
+  0x98, 0x98, 0x98, 0x00,  // LIGHTGRAY\r
+  0x30, 0x30, 0x30, 0x00,  // DARKGRAY - BRIGHT BLACK\r
+  0xff, 0x00, 0x00, 0x00,  // LIGHTBLUE\r
+  0x00, 0xff, 0x00, 0x00,  // LIGHTGREEN\r
+  0xff, 0xff, 0x00, 0x00,  // LIGHTCYAN\r
+  0x00, 0x00, 0xff, 0x00,  // LIGHTRED\r
+  0xff, 0x00, 0xff, 0x00,  // LIGHTMAGENTA\r
+  0x00, 0xff, 0xff, 0x00,  // YELLOW\r
+  0xff, 0xff, 0xff, 0x00,  // WHITE\r
+};\r
+\r
+\r
+/**\r
+  Insert a character cell information to the list specified by GlyphInfoList.\r
+\r
+  @param  CharValue               Unicode character value, which identifies a glyph\r
+                                  block.\r
+  @param  GlyphInfoList           HII_GLYPH_INFO list head.\r
+  @param  Cell                    Incoming character cell information.\r
+\r
+  @retval EFI_SUCCESS             Cell information is added to the GlyphInfoList.\r
+  @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the\r
+                                  task.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+NewCell (\r
+  IN  CHAR16                         CharValue,\r
+  IN  LIST_ENTRY                     *GlyphInfoList,\r
+  IN  EFI_HII_GLYPH_INFO             *Cell\r
+  )\r
+{\r
+  HII_GLYPH_INFO           *GlyphInfo;\r
+\r
+  ASSERT (Cell != NULL && GlyphInfoList != NULL);\r
+\r
+  GlyphInfo = (HII_GLYPH_INFO *) AllocateZeroPool (sizeof (HII_GLYPH_INFO));\r
+  if (GlyphInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // GlyphInfoList stores a list of default character cell information, each is\r
+  // identified by "CharId".\r
+  //\r
+  GlyphInfo->Signature = HII_GLYPH_INFO_SIGNATURE;\r
+  GlyphInfo->CharId    = CharValue;\r
+  CopyMem (&GlyphInfo->Cell, Cell, sizeof (EFI_HII_GLYPH_INFO));\r
+  InsertTailList (GlyphInfoList, &GlyphInfo->Entry);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Get a character cell information from the list specified by GlyphInfoList.\r
+\r
+  @param  CharValue               Unicode character value, which identifies a glyph\r
+                                  block.\r
+  @param  GlyphInfoList           HII_GLYPH_INFO list head.\r
+  @param  Cell                    Buffer which stores output character cell\r
+                                  information.\r
+\r
+  @retval EFI_SUCCESS             Cell information is added to the GlyphInfoList.\r
+  @retval EFI_NOT_FOUND           The character info specified by CharValue does\r
+                                  not exist.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetCell (\r
+  IN  CHAR16                         CharValue,\r
+  IN  LIST_ENTRY                     *GlyphInfoList,\r
+  OUT EFI_HII_GLYPH_INFO             *Cell\r
+  )\r
+{\r
+  HII_GLYPH_INFO           *GlyphInfo;\r
+  LIST_ENTRY               *Link;\r
+\r
+  ASSERT (Cell != NULL && GlyphInfoList != NULL);\r
+\r
+  //\r
+  // Since the EFI_HII_GIBT_DEFAULTS block won't increment CharValueCurrent,\r
+  // the value of "CharId" of a default character cell which is used for a\r
+  // EFI_HII_GIBT_GLYPH_DEFAULT or EFI_HII_GIBT_GLYPHS_DEFAULT should be\r
+  // less or equal to the value of "CharValueCurrent" of this default block.\r
+  //\r
+  // For instance, if the CharId of a GlyphInfoList is {1, 3, 7}, a default glyph\r
+  // with CharValue equals "7" uses the GlyphInfo with CharId = 7;\r
+  // a default glyph with CharValue equals "6" uses the GlyphInfo with CharId = 3.\r
+  //\r
+  for (Link = GlyphInfoList->BackLink; Link != GlyphInfoList; Link = Link->BackLink) {\r
+    GlyphInfo = CR (Link, HII_GLYPH_INFO, Entry, HII_GLYPH_INFO_SIGNATURE);\r
+    if (GlyphInfo->CharId <= CharValue) {\r
+      CopyMem (Cell, &GlyphInfo->Cell, sizeof (EFI_HII_GLYPH_INFO));\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  Convert the glyph for a single character into a bitmap.\r
+\r
+  @param  Private                 HII database driver private data.\r
+  @param  Char                    Character to retrieve.\r
+  @param  StringInfo              Points to the string font and color information\r
+                                  or NULL  if the string should use the default\r
+                                  system font and color.\r
+  @param  GlyphBuffer             Buffer to store the retrieved bitmap data.\r
+  @param  Cell                    Points to EFI_HII_GLYPH_INFO structure.\r
+  @param  Attributes              If not NULL, output the glyph attributes if any.\r
+\r
+  @retval EFI_SUCCESS             Glyph bitmap outputted.\r
+  @retval EFI_OUT_OF_RESOURCES    Unable to allocate the output buffer GlyphBuffer.\r
+  @retval EFI_NOT_FOUND           The glyph was unknown can not be found.\r
+  @retval EFI_INVALID_PARAMETER   Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetGlyphBuffer (\r
+  IN  HII_DATABASE_PRIVATE_DATA      *Private,\r
+  IN  CHAR16                         Char,\r
+  IN  EFI_FONT_INFO                  *StringInfo,\r
+  OUT UINT8                          **GlyphBuffer,\r
+  OUT EFI_HII_GLYPH_INFO             *Cell,\r
+  OUT UINT8                          *Attributes OPTIONAL\r
+  )\r
+{\r
+  HII_DATABASE_RECORD                *Node;\r
+  LIST_ENTRY                         *Link;\r
+  HII_SIMPLE_FONT_PACKAGE_INSTANCE   *SimpleFont;\r
+  LIST_ENTRY                         *Link1;\r
+  UINT16                             Index;\r
+  EFI_NARROW_GLYPH                   Narrow;\r
+  EFI_WIDE_GLYPH                     Wide;\r
+  HII_GLOBAL_FONT_INFO               *GlobalFont;\r
+  UINTN                              HeaderSize;\r
+  EFI_NARROW_GLYPH                   *NarrowPtr;\r
+  EFI_WIDE_GLYPH                     *WidePtr;\r
+\r
+  if (GlyphBuffer == NULL || Cell == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (Private == NULL || Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ZeroMem (Cell, sizeof (EFI_HII_GLYPH_INFO));\r
+\r
+  //\r
+  // If StringInfo is not NULL, it must point to an existing EFI_FONT_INFO rather\r
+  // than system default font and color.\r
+  // If NULL, try to find the character in simplified font packages since\r
+  // default system font is the fixed font (narrow or wide glyph).\r
+  //\r
+  if (StringInfo != NULL) {\r
+    if(!IsFontInfoExisted (Private, StringInfo, NULL, NULL, &GlobalFont)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    if (Attributes != NULL) {\r
+      *Attributes = PROPORTIONAL_GLYPH;\r
+    }\r
+    return FindGlyphBlock (GlobalFont->FontPackage, Char, GlyphBuffer, Cell, NULL);\r
+  } else {\r
+    HeaderSize = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR);\r
+\r
+    for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+      Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+      for (Link1 = Node->PackageList->SimpleFontPkgHdr.ForwardLink;\r
+           Link1 != &Node->PackageList->SimpleFontPkgHdr;\r
+           Link1 = Link1->ForwardLink\r
+          ) {\r
+        SimpleFont = CR (Link1, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);\r
+        //\r
+        // Search the narrow glyph array\r
+        //\r
+        NarrowPtr = (EFI_NARROW_GLYPH *) ((UINT8 *) (SimpleFont->SimpleFontPkgHdr) + HeaderSize);\r
+        for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs; Index++) {\r
+          CopyMem (&Narrow, NarrowPtr + Index,sizeof (EFI_NARROW_GLYPH));\r
+          if (Narrow.UnicodeWeight == Char) {\r
+            *GlyphBuffer = (UINT8 *) AllocateZeroPool (EFI_GLYPH_HEIGHT);\r
+            if (*GlyphBuffer == NULL) {\r
+              return EFI_OUT_OF_RESOURCES;\r
+            }\r
+            Cell->Width    = EFI_GLYPH_WIDTH;\r
+            Cell->Height   = EFI_GLYPH_HEIGHT;\r
+            Cell->OffsetY  = NARROW_BASELINE;\r
+            Cell->AdvanceX = Cell->Width;\r
+            CopyMem (*GlyphBuffer, Narrow.GlyphCol1, Cell->Height);\r
+            if (Attributes != NULL) {\r
+              *Attributes = (UINT8) (Narrow.Attributes | NARROW_GLYPH);\r
+            }\r
+            return EFI_SUCCESS;\r
+          }\r
+        }\r
+        //\r
+        // Search the wide glyph array\r
+        //\r
+        WidePtr = (EFI_WIDE_GLYPH *) (NarrowPtr + SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs);\r
+        for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfWideGlyphs; Index++) {\r
+          CopyMem (&Wide, WidePtr + Index, sizeof (EFI_WIDE_GLYPH));\r
+          if (Wide.UnicodeWeight == Char) {\r
+            *GlyphBuffer    = (UINT8 *) AllocateZeroPool (EFI_GLYPH_HEIGHT * 2);\r
+            if (*GlyphBuffer == NULL) {\r
+              return EFI_OUT_OF_RESOURCES;\r
+            }\r
+            Cell->Width    = EFI_GLYPH_WIDTH * 2;\r
+            Cell->Height   = EFI_GLYPH_HEIGHT;\r
+            Cell->OffsetY  = WIDE_BASELINE;\r
+            Cell->AdvanceX = Cell->Width;\r
+            CopyMem (*GlyphBuffer, Wide.GlyphCol1, EFI_GLYPH_HEIGHT);\r
+            CopyMem (*GlyphBuffer + EFI_GLYPH_HEIGHT, Wide.GlyphCol2, EFI_GLYPH_HEIGHT);\r
+            if (Attributes != NULL) {\r
+              *Attributes = (UINT8) (Wide.Attributes | EFI_GLYPH_WIDE);\r
+            }\r
+            return EFI_SUCCESS;\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+STATIC\r
+VOID\r
+NarrowGlyphToBlt (\r
+  IN     UINT8                         *GlyphBuffer,\r
+  IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,\r
+  IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,\r
+  IN     UINTN                         ImageWidth,\r
+  IN     UINTN                         ImageHeight,\r
+  IN     BOOLEAN                       Transparent,\r
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin\r
+  )\r
+{\r
+  UINT8                                X;\r
+  UINT8                                Y;\r
+  UINT8                                Height;\r
+  UINT8                                Width;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL        *Buffer;\r
+\r
+  ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);\r
+\r
+  Height = EFI_GLYPH_HEIGHT;\r
+  Width  = EFI_GLYPH_WIDTH;\r
+\r
+  ASSERT (Width <= ImageWidth && Height <= ImageHeight);\r
+\r
+  Buffer = *Origin;\r
+\r
+  for (Y = 0; Y < Height; Y++) {\r
+    for (X = 0; X < Width; X++) {\r
+      if ((GlyphBuffer[Y] & (1 << X)) != 0) {\r
+        Buffer[Y * ImageWidth + (Width - X - 1)] = Foreground;\r
+      } else {\r
+        if (!Transparent) {\r
+          Buffer[Y * ImageWidth + (Width - X - 1)] = Background;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  *Origin = Buffer + Width;\r
+}\r
+\r
+\r
+/**\r
+  Convert bitmap data of the glyph to blt structure.\r
+\r
+  @param  GlyphBuffer             Buffer points to bitmap data of glyph.\r
+  @param  Foreground              The color of the "on" pixels in the glyph in the\r
+                                  bitmap.\r
+  @param  Background              The color of the "off" pixels in the glyph in the\r
+                                  bitmap.\r
+  @param  Width                   Width of the character or character cell, in\r
+                                  pixels.\r
+  @param  Height                  Height of the character or character cell, in\r
+                                  pixels.\r
+  @param  Transparent             If TRUE, the Background color is ignored and all\r
+                                  "off" pixels in the character's drawn wil use the\r
+                                  pixel value from BltBuffer.\r
+  @param  BltBuffer               Points to the blt buffer.\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+GlyphToBlt (\r
+  IN     UINT8                         *GlyphBuffer,\r
+  IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,\r
+  IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,\r
+  IN     UINTN                         ImageWidth,\r
+  IN     UINTN                         ImageHeight,\r
+  IN     BOOLEAN                       Transparent,\r
+  IN     EFI_HII_GLYPH_INFO            Cell,\r
+  IN     UINT8                         Attributes,\r
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin\r
+  )\r
+{\r
+  UINT8                                X;\r
+  UINT8                                Y;\r
+  UINT8                                Data;\r
+  UINT8                                Index;\r
+  UINTN                                OffsetY;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL        *BltBuffer;\r
+\r
+  ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);\r
+  ASSERT (Cell.Width <= ImageWidth && Cell.Height <= ImageHeight);\r
+\r
+  BltBuffer = *Origin;\r
+\r
+  //\r
+  // Since non-spacing key will be printed OR'd with the previous glyph, don't\r
+  // write 0.\r
+  //\r
+  if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) {\r
+    Transparent = TRUE;\r
+  }\r
+\r
+  //\r
+  // The glyph's upper left hand corner pixel is the most significant bit of the\r
+  // first bitmap byte.\r
+  //\r
+  for (Y = 0; Y < Cell.Height; Y++) {\r
+    OffsetY = BITMAP_LEN_1_BIT (Cell.Width, Y);\r
+\r
+    //\r
+    // All bits in these bytes are meaningful.\r
+    //\r
+    for (X = 0; X < Cell.Width / 8; X++) {\r
+      Data  = *(GlyphBuffer + OffsetY + X);\r
+      for (Index = 0; Index < 8; Index++) {\r
+        if ((Data & (1 << Index)) != 0) {\r
+          BltBuffer[Y * ImageWidth + X * 8 + (8 - Index - 1)] = Foreground;\r
+        } else {\r
+          if (!Transparent) {\r
+            BltBuffer[Y * ImageWidth + X * 8 + (8 - Index - 1)] = Background;\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    if (Cell.Width % 8 != 0) {\r
+      //\r
+      // There are some padding bits in this byte. Ignore them.\r
+      //\r
+      Data  = *(GlyphBuffer + OffsetY + X);\r
+      for (Index = 0; Index < Cell.Width % 8; Index++) {\r
+        if ((Data & (1 << (8 - Index - 1))) != 0) {\r
+          BltBuffer[Y * ImageWidth + X * 8 + Index] = Foreground;\r
+        } else {\r
+          if (!Transparent) {\r
+            BltBuffer[Y * ImageWidth + X * 8 + Index] = Background;\r
+          }\r
+        }\r
+      }\r
+    } // end of if (Width % 8...)\r
+\r
+  } // end of for (Y=0...)\r
+\r
+  *Origin = BltBuffer + Cell.Width;\r
+}\r
+\r
+\r
+/**\r
+  Convert bitmap data of the glyph to blt structure.\r
+\r
+  @param  GlyphBuffer             Buffer points to bitmap data of glyph.\r
+  @param  Foreground              The color of the "on" pixels in the glyph in the\r
+                                  bitmap.\r
+  @param  Background              The color of the "off" pixels in the glyph in the\r
+                                  bitmap.\r
+  @param  Width                   Width of the character or character cell, in\r
+                                  pixels.\r
+  @param  Height                  Height of the character or character cell, in\r
+                                  pixels.\r
+  @param  Transparent             If TRUE, the Background color is ignored and all\r
+                                  "off" pixels in the character's drawn wil use the\r
+                                  pixel value from BltBuffer.\r
+  @param  Cell                    Points to EFI_HII_GLYPH_INFO structure.\r
+  @param  Attributes              The attribute of incoming glyph in GlyphBuffer.\r
+  @param  Origin                  On input, points to the origin of the to be\r
+                                  displayed character, on output, points to the\r
+                                  next glyph's origin.\r
+\r
+  @return Points to the address of next origin node in BltBuffer.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+GlyphToImage (\r
+  IN     UINT8                         *GlyphBuffer,\r
+  IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,\r
+  IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,\r
+  IN     UINTN                         ImageWidth,\r
+  IN     UINTN                         ImageHeight,\r
+  IN     BOOLEAN                       Transparent,\r
+  IN     EFI_HII_GLYPH_INFO            Cell,\r
+  IN     UINT8                         Attributes,\r
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin\r
+  )\r
+{\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL        *Buffer;\r
+\r
+  ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);\r
+  ASSERT (Cell.Width <= ImageWidth && Cell.Height <= ImageHeight);\r
+\r
+  Buffer = *Origin;\r
+\r
+  if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) {\r
+    //\r
+    // This character is a non-spacing key, print it OR'd with the previous glyph.\r
+    // without advancing cursor.\r
+    //\r
+    Buffer -= Cell.Width;\r
+    GlyphToBlt (\r
+      GlyphBuffer,\r
+      Foreground,\r
+      Background,\r
+      ImageWidth,\r
+      ImageHeight,\r
+      Transparent,\r
+      Cell,\r
+      Attributes,\r
+      &Buffer\r
+      );\r
+\r
+  } else if ((Attributes & EFI_GLYPH_WIDE) == EFI_GLYPH_WIDE) {\r
+    //\r
+    // This character is wide glyph, i.e. 16 pixels * 19 pixels.\r
+    // Draw it as two narrow glyphs.\r
+    //\r
+    NarrowGlyphToBlt (\r
+      GlyphBuffer,\r
+      Foreground,\r
+      Background,\r
+      ImageWidth,\r
+      ImageHeight,\r
+      Transparent,\r
+      Origin\r
+      );\r
+\r
+    NarrowGlyphToBlt (\r
+      GlyphBuffer + EFI_GLYPH_HEIGHT,\r
+      Foreground,\r
+      Background,\r
+      ImageWidth,\r
+      ImageHeight,\r
+      Transparent,\r
+      Origin\r
+      );\r
+\r
+  } else if ((Attributes & NARROW_GLYPH) == NARROW_GLYPH) {\r
+    //\r
+    // This character is narrow glyph, i.e. 8 pixels * 19 pixels.\r
+    //\r
+    NarrowGlyphToBlt (\r
+      GlyphBuffer,\r
+      Foreground,\r
+      Background,\r
+      ImageWidth,\r
+      ImageHeight,\r
+      Transparent,\r
+      Origin\r
+      );\r
+\r
+  } else if ((Attributes & PROPORTIONAL_GLYPH) == PROPORTIONAL_GLYPH) {\r
+    //\r
+    // This character is proportional glyph, i.e. Cell.Width * Cell.Height pixels.\r
+    //\r
+    GlyphToBlt (\r
+      GlyphBuffer,\r
+      Foreground,\r
+      Background,\r
+      ImageWidth,\r
+      ImageHeight,\r
+      Transparent,\r
+      Cell,\r
+      Attributes,\r
+      Origin\r
+      );\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Write the output parameters of FindGlyphBlock().\r
+\r
+  @param  BufferIn                Buffer which stores the bitmap data of the found\r
+                                  block.\r
+  @param  BufferLen               Length of BufferIn.\r
+  @param  InputCell               Buffer which stores cell information of the\r
+                                  encoded bitmap.\r
+  @param  GlyphBuffer             Output the corresponding bitmap data of the found\r
+                                  block. It is the caller's responsiblity to free\r
+                                  this buffer.\r
+  @param  Cell                    Output cell information of the encoded bitmap.\r
+  @param  GlyphBufferLen          If not NULL, output the length of GlyphBuffer.\r
+\r
+  @retval EFI_SUCCESS             The operation is performed successfully.\r
+  @retval EFI_INVALID_PARAMETER   Any input parameter is invalid.\r
+  @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the\r
+                                  task.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+WriteOutputParam (\r
+  IN  UINT8                          *BufferIn,\r
+  IN  UINTN                          BufferLen,\r
+  IN  EFI_HII_GLYPH_INFO             *InputCell,\r
+  OUT UINT8                          **GlyphBuffer, OPTIONAL\r
+  OUT EFI_HII_GLYPH_INFO             *Cell, OPTIONAL\r
+  OUT UINTN                          *GlyphBufferLen OPTIONAL\r
+  )\r
+{\r
+  if (BufferIn == NULL || BufferLen < 1 || InputCell == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Cell != NULL) {\r
+    CopyMem (Cell, InputCell, sizeof (EFI_HII_GLYPH_INFO));\r
+  }\r
+\r
+  if (GlyphBuffer != NULL) {\r
+    *GlyphBuffer = (UINT8 *) AllocateZeroPool (BufferLen);\r
+    if (*GlyphBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    CopyMem (*GlyphBuffer, BufferIn, BufferLen);\r
+  }\r
+\r
+  if (GlyphBufferLen != NULL) {\r
+    *GlyphBufferLen = BufferLen;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Parse all glyph blocks to find a glyph block specified by CharValue.\r
+  If CharValue = (CHAR16) (-1), collect all default character cell information\r
+  within this font package and backup its information.\r
+\r
+  @param  FontPackage             Hii string package instance.\r
+  @param  CharValue               Unicode character value, which identifies a glyph\r
+                                  block.\r
+  @param  GlyphBuffer             Output the corresponding bitmap data of the found\r
+                                  block. It is the caller's responsiblity to free\r
+                                  this buffer.\r
+  @param  Cell                    Output cell information of the encoded bitmap.\r
+  @param  GlyphBufferLen          If not NULL, output the length of GlyphBuffer.\r
+\r
+  @retval EFI_SUCCESS             The bitmap data is retrieved successfully.\r
+  @retval EFI_NOT_FOUND           The specified CharValue does not exist in current\r
+                                  database.\r
+  @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the\r
+                                  task.\r
+\r
+**/\r
+EFI_STATUS\r
+FindGlyphBlock (\r
+  IN  HII_FONT_PACKAGE_INSTANCE      *FontPackage,\r
+  IN  CHAR16                         CharValue,\r
+  OUT UINT8                          **GlyphBuffer, OPTIONAL\r
+  OUT EFI_HII_GLYPH_INFO             *Cell, OPTIONAL\r
+  OUT UINTN                          *GlyphBufferLen OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  UINT8                               *BlockPtr;\r
+  UINT16                              CharCurrent;\r
+  UINT16                              Length16;\r
+  UINT32                              Length32;\r
+  EFI_HII_GIBT_GLYPHS_BLOCK           Glyphs;\r
+  UINTN                               BufferLen;\r
+  UINT16                              Index;\r
+  EFI_HII_GLYPH_INFO                  DefaultCell;\r
+  EFI_HII_GLYPH_INFO                  LocalCell;\r
+\r
+  ASSERT (FontPackage != NULL);\r
+  ASSERT (FontPackage->Signature == HII_FONT_PACKAGE_SIGNATURE);\r
+\r
+  if (CharValue == (CHAR16) (-1)) {\r
+    //\r
+    // Collect the cell information specified in font package fixed header.\r
+    // Use CharValue =0 to represent this particular cell.\r
+    //\r
+    Status = NewCell (\r
+               0,\r
+               &FontPackage->GlyphInfoList,\r
+               (EFI_HII_GLYPH_INFO *) ((UINT8 *) FontPackage->FontPkgHdr + 3 * sizeof (UINT32))\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  BlockPtr    = FontPackage->GlyphBlock;\r
+  CharCurrent = 1;\r
+  BufferLen   = 0;\r
+\r
+  while (*BlockPtr != EFI_HII_GIBT_END) {\r
+    switch (*BlockPtr) {\r
+    case EFI_HII_GIBT_DEFAULTS:\r
+      //\r
+      // Collect all default character cell information specified by\r
+      // EFI_HII_GIBT_DEFAULTS.\r
+      //\r
+      if (CharValue == (CHAR16) (-1)) {\r
+        Status = NewCell (\r
+                   CharCurrent,\r
+                   &FontPackage->GlyphInfoList,\r
+                   (EFI_HII_GLYPH_INFO *) (BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK))\r
+                   );\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+      }\r
+      BlockPtr += sizeof (EFI_HII_GIBT_DEFAULTS_BLOCK);\r
+      break;\r
+\r
+    case EFI_HII_GIBT_DUPLICATE:\r
+      if (CharCurrent == CharValue) {\r
+        CopyMem (&CharValue, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (CHAR16));\r
+        CharCurrent = 1;\r
+        BlockPtr    = FontPackage->GlyphBlock;\r
+        continue;\r
+      }\r
+      CharCurrent++;\r
+      BlockPtr += sizeof (EFI_HII_GIBT_DUPLICATE_BLOCK);\r
+      break;\r
+\r
+    case EFI_HII_GIBT_EXT1:\r
+      BlockPtr += *(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8));\r
+      break;\r
+    case EFI_HII_GIBT_EXT2:\r
+      CopyMem (\r
+        &Length16,\r
+        BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8),\r
+        sizeof (UINT16)\r
+        );\r
+      BlockPtr += Length16;\r
+      break;\r
+    case EFI_HII_GIBT_EXT4:\r
+      CopyMem (\r
+        &Length32,\r
+        BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8),\r
+        sizeof (UINT32)\r
+        );\r
+      BlockPtr += Length32;\r
+      break;\r
+\r
+    case EFI_HII_GIBT_GLYPH:\r
+      CopyMem (\r
+        &LocalCell,\r
+        BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),\r
+        sizeof (EFI_HII_GLYPH_INFO)\r
+        );\r
+      BufferLen = BITMAP_LEN_1_BIT (LocalCell.Width, LocalCell.Height);\r
+      if (CharCurrent == CharValue) {\r
+        return WriteOutputParam (\r
+                 BlockPtr + sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8),\r
+                 BufferLen,\r
+                 &LocalCell,\r
+                 GlyphBuffer,\r
+                 Cell,\r
+                 GlyphBufferLen\r
+                 );\r
+      }\r
+      CharCurrent++;\r
+      BlockPtr += sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8) + BufferLen;\r
+      break;\r
+\r
+    case EFI_HII_GIBT_GLYPHS:\r
+      BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK);\r
+      CopyMem (&Glyphs.Cell, BlockPtr, sizeof (EFI_HII_GLYPH_INFO));\r
+      BlockPtr += sizeof (EFI_HII_GLYPH_INFO);\r
+      CopyMem (&Glyphs.Count, BlockPtr, sizeof (UINT16));\r
+      BlockPtr += sizeof (UINT16);\r
+\r
+      BufferLen = BITMAP_LEN_1_BIT (Glyphs.Cell.Width, Glyphs.Cell.Height);\r
+      for (Index = 0; Index < Glyphs.Count; Index++) {\r
+        if (CharCurrent + Index == CharValue) {\r
+          return WriteOutputParam (\r
+                   BlockPtr,\r
+                   BufferLen,\r
+                   &Glyphs.Cell,\r
+                   GlyphBuffer,\r
+                   Cell,\r
+                   GlyphBufferLen\r
+                   );\r
+        }\r
+        BlockPtr += BufferLen;\r
+      }\r
+      CharCurrent = (UINT16) (CharCurrent + Glyphs.Count);\r
+      break;\r
+\r
+    case EFI_HII_GIBT_GLYPH_DEFAULT:\r
+      Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height);\r
+\r
+      if (CharCurrent == CharValue) {\r
+        return WriteOutputParam (\r
+                 BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),\r
+                 BufferLen,\r
+                 &DefaultCell,\r
+                 GlyphBuffer,\r
+                 Cell,\r
+                 GlyphBufferLen\r
+                 );\r
+      }\r
+      CharCurrent++;\r
+      BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK) + BufferLen;\r
+      break;\r
+\r
+    case EFI_HII_GIBT_GLYPHS_DEFAULT:\r
+      CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16));\r
+      Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height);\r
+      BlockPtr += sizeof (EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK) - sizeof (UINT8);\r
+      for (Index = 0; Index < Length16; Index++) {\r
+        if (CharCurrent + Index == CharValue) {\r
+          return WriteOutputParam (\r
+                   BlockPtr,\r
+                   BufferLen,\r
+                   &DefaultCell,\r
+                   GlyphBuffer,\r
+                   Cell,\r
+                   GlyphBufferLen\r
+                   );\r
+        }\r
+        BlockPtr += BufferLen;\r
+      }\r
+      CharCurrent = (UINT16) (CharCurrent + Length16);\r
+      break;\r
+\r
+    case EFI_HII_GIBT_SKIP1:\r
+      CharCurrent = (UINT16) (CharCurrent + (UINT16) (*(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK))));\r
+      BlockPtr    += sizeof (EFI_HII_GIBT_SKIP1_BLOCK);\r
+      break;\r
+    case EFI_HII_GIBT_SKIP2:\r
+      CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16));\r
+      CharCurrent = (UINT16) (CharCurrent + Length16);\r
+      BlockPtr    += sizeof (EFI_HII_GIBT_SKIP2_BLOCK);\r
+      break;\r
+    default:\r
+      ASSERT (FALSE);\r
+      break;\r
+    }\r
+\r
+    if (CharValue < CharCurrent) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  }\r
+\r
+  if (CharValue == (CHAR16) (-1)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  Copy a Font Name to a new created EFI_FONT_INFO structure.\r
+\r
+  @param  FontName                NULL-terminated string.\r
+  @param  FontInfo                a new EFI_FONT_INFO which stores the FontName.\r
+                                  It's caller's responsibility to free this buffer.\r
+\r
+  @retval EFI_SUCCESS             FontInfo is allocated and copied with FontName.\r
+  @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the\r
+                                  task.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+SaveFontName (\r
+  IN  EFI_STRING                       FontName,\r
+  OUT EFI_FONT_INFO                    **FontInfo\r
+  )\r
+{\r
+  UINTN         FontInfoLen;\r
+\r
+  ASSERT (FontName != NULL && FontInfo != NULL);\r
+\r
+  FontInfoLen = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StrSize (FontName);\r
+  *FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoLen);\r
+  if (*FontInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  StrCpy ((*FontInfo)->FontName, FontName);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Retrieve system default font and color.\r
+\r
+  @param  Private                 HII database driver private data.\r
+  @param  FontInfo                Points to system default font output-related\r
+                                  information. It's caller's responsibility to free\r
+                                  this buffer.\r
+  @param  FontInfoSize            If not NULL, output the size of buffer FontInfo.\r
+\r
+  @retval EFI_SUCCESS             Cell information is added to the GlyphInfoList.\r
+  @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the\r
+                                  task.\r
+  @retval EFI_INVALID_PARAMETER   Any input parameter is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+GetSystemFont (\r
+  IN  HII_DATABASE_PRIVATE_DATA      *Private,\r
+  OUT EFI_FONT_DISPLAY_INFO          **FontInfo,\r
+  OUT UINTN                          *FontInfoSize OPTIONAL\r
+  )\r
+{\r
+  EFI_FONT_DISPLAY_INFO              *Info;\r
+  UINTN                              InfoSize;\r
+\r
+  if (Private == NULL || Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (FontInfo == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // The standard font always has the name "sysdefault".\r
+  //\r
+  InfoSize = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + StrSize (L"sysdefault");\r
+  Info = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (InfoSize);\r
+  if (Info == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Info->ForegroundColor    = mEfiColors[Private->Attribute & 0x0f];\r
+  Info->BackgroundColor    = mEfiColors[Private->Attribute >> 4];\r
+  Info->FontInfoMask       = EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_SYS_STYLE;\r
+  Info->FontInfo.FontStyle = 0;\r
+  Info->FontInfo.FontSize  = EFI_GLYPH_HEIGHT;\r
+  StrCpy (Info->FontInfo.FontName, L"sysdefault");\r
+\r
+  *FontInfo = Info;\r
+  if (FontInfoSize != NULL) {\r
+    *FontInfoSize = InfoSize;\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Check whether EFI_FONT_DISPLAY_INFO points to system default font and color.\r
+\r
+  @param  Private                 HII database driver private data.\r
+  @param  StringInfo              Points to the string output information,\r
+                                  including the color and font.\r
+  @param  SystemInfo              If not NULL, points to system default font and\r
+                                  color when incoming StringInfo does not match the\r
+                                  default.  Points to NULL if matches. It's\r
+                                  caller's reponsibility to free this buffer.\r
+  @param  SystemInfoLen           If not NULL, output the length of default system\r
+                                  info.\r
+\r
+  @retval TRUE                    Yes, it points to system default.\r
+  @retval FALSE                   No.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+IsSystemFontInfo (\r
+  IN  HII_DATABASE_PRIVATE_DATA      *Private,\r
+  IN  EFI_FONT_DISPLAY_INFO          *StringInfo,\r
+  OUT EFI_FONT_DISPLAY_INFO          **SystemInfo, OPTIONAL\r
+  OUT UINTN                          *SystemInfoLen OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  EFI_FONT_DISPLAY_INFO               *SystemDefault;\r
+  UINTN                               DefaultLen;\r
+\r
+  ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
+\r
+  if (StringInfo == NULL && SystemInfo == NULL) {\r
+    return TRUE;\r
+  }\r
+\r
+  //\r
+  // Check whether incoming string font and color matches system default.\r
+  //\r
+  Status = GetSystemFont (Private, &SystemDefault, &DefaultLen);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  if (SystemInfo != NULL) {\r
+    *SystemInfo = SystemDefault;\r
+  } else {\r
+    SafeFreePool (SystemDefault);\r
+  }\r
+\r
+  if (SystemInfoLen != NULL) {\r
+    *SystemInfoLen = DefaultLen;\r
+  }\r
+\r
+  if (StringInfo == NULL ||\r
+      (StringInfo != NULL && CompareMem (SystemDefault, StringInfo, DefaultLen) == 0)) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+\r
+/**\r
+  This function checks whether EFI_FONT_INFO exists in current database. If\r
+  FontInfoMask is specified, check what options can be used to make a match.\r
+  Note that the masks relate to where the system default should be supplied\r
+  are ignored by this function.\r
+\r
+  @param  Private                 Hii database private structure.\r
+  @param  FontInfo                Points to EFI_FONT_INFO structure.\r
+  @param  FontInfoMask            If not NULL, describes what options can be used\r
+                                  to make a match between the font requested and\r
+                                  the font available. The caller must guarantee\r
+                                  this mask is valid.\r
+  @param  FontHandle              On entry, Points to the font handle returned by a\r
+                                  previous  call to GetFontInfo() or NULL to start\r
+                                  with the first font.\r
+  @param  GlobalFontInfo          If not NULL, output the corresponding globa font\r
+                                  info.\r
+\r
+  @retval TRUE                    Existed\r
+  @retval FALSE                   Not existed\r
+\r
+**/\r
+BOOLEAN\r
+IsFontInfoExisted (\r
+  IN  HII_DATABASE_PRIVATE_DATA *Private,\r
+  IN  EFI_FONT_INFO             *FontInfo,\r
+  IN  EFI_FONT_INFO_MASK        *FontInfoMask,   OPTIONAL\r
+  IN  EFI_FONT_HANDLE           FontHandle,      OPTIONAL\r
+  OUT HII_GLOBAL_FONT_INFO      **GlobalFontInfo OPTIONAL\r
+  )\r
+{\r
+  HII_GLOBAL_FONT_INFO          *GlobalFont;\r
+  HII_GLOBAL_FONT_INFO          *GlobalFontBackup1;\r
+  HII_GLOBAL_FONT_INFO          *GlobalFontBackup2;\r
+  LIST_ENTRY                    *Link;\r
+  EFI_FONT_INFO_MASK            Mask;\r
+  BOOLEAN                       Matched;\r
+  BOOLEAN                       VagueMatched1;\r
+  BOOLEAN                       VagueMatched2;\r
+\r
+  ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
+  ASSERT (FontInfo != NULL);\r
+\r
+  //\r
+  // Matched flag represents an exactly match; VagueMatched1 repensents a RESIZE\r
+  // or RESTYLE match; VagueMatched2 represents a RESIZE | RESTYLE match.\r
+  //\r
+  Matched           = FALSE;\r
+  VagueMatched1     = FALSE;\r
+  VagueMatched2     = FALSE;\r
+\r
+  Mask              = 0;\r
+  GlobalFontBackup1 = NULL;\r
+  GlobalFontBackup2 = NULL;\r
+\r
+  // The process of where the system default should be supplied instead of\r
+  // the specified font info beyonds this function's scope.\r
+  //\r
+  if (FontInfoMask != NULL) {\r
+    Mask = *FontInfoMask & (~SYS_FONT_INFO_MASK);\r
+  }\r
+\r
+  //\r
+  // If not NULL, FontHandle points to the next node of the last searched font\r
+  // node by previous call.\r
+  //\r
+  if (FontHandle == NULL) {\r
+    Link = Private->FontInfoList.ForwardLink;\r
+  } else {\r
+    Link = (LIST_ENTRY     *) FontHandle;\r
+  }\r
+\r
+  for (; Link != &Private->FontInfoList; Link = Link->ForwardLink) {\r
+    GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);\r
+    if (FontInfoMask == NULL) {\r
+      if (CompareMem (GlobalFont->FontInfo, FontInfo, GlobalFont->FontInfoSize) == 0) {\r
+        if (GlobalFontInfo != NULL) {\r
+          *GlobalFontInfo = GlobalFont;\r
+        }\r
+        return TRUE;\r
+      }\r
+    } else {\r
+      //\r
+      // Check which options could be used to make a match.\r
+      //\r
+      switch (Mask) {\r
+      case EFI_FONT_INFO_ANY_FONT:\r
+        if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle &&\r
+            GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {\r
+          Matched = TRUE;\r
+        }\r
+        break;\r
+      case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE:\r
+        if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+          Matched = TRUE;\r
+        }\r
+        break;\r
+      case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE:\r
+        if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+          Matched = TRUE;\r
+        }\r
+        break;\r
+      case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_ANY_STYLE:\r
+        Matched   = TRUE;\r
+        break;\r
+      //\r
+      // If EFI_FONT_INFO_RESTYLE is specified, then the system may attempt to\r
+      // remove some of the specified styles to meet the style requested.\r
+      //\r
+      case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE:\r
+        if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+          if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+            Matched           = TRUE;\r
+          } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {\r
+            VagueMatched1     = TRUE;\r
+            GlobalFontBackup1 = GlobalFont;\r
+          }\r
+        }\r
+        break;\r
+      //\r
+      // If EFI_FONT_INFO_RESIZE is specified, then the sytem may attempt to\r
+      // stretch or shrink a font to meet the size requested.\r
+      //\r
+      case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESIZE:\r
+        if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+          if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {\r
+            Matched           = TRUE;\r
+          } else {\r
+            VagueMatched1     = TRUE;\r
+            GlobalFontBackup1 = GlobalFont;\r
+          }\r
+        }\r
+        break;\r
+      case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_RESIZE:\r
+        if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+          if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {\r
+            Matched           = TRUE;\r
+          } else {\r
+            VagueMatched1     = TRUE;\r
+            GlobalFontBackup1 = GlobalFont;\r
+          }\r
+        } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {\r
+          if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {\r
+            VagueMatched1     = TRUE;\r
+            GlobalFontBackup1 = GlobalFont;\r
+          } else {\r
+            VagueMatched2     = TRUE;\r
+            GlobalFontBackup2 = GlobalFont;\r
+          }\r
+        }\r
+        break;\r
+      case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:\r
+        if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {\r
+          Matched           = TRUE;\r
+        } else {\r
+          VagueMatched1     = TRUE;\r
+          GlobalFontBackup1 = GlobalFont;\r
+        }\r
+        break;\r
+      case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:\r
+        if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+          Matched           = TRUE;\r
+        } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {\r
+          VagueMatched1     = TRUE;\r
+          GlobalFontBackup1 = GlobalFont;\r
+        }\r
+        break;\r
+      case EFI_FONT_INFO_ANY_STYLE:\r
+        if ((CompareMem (\r
+               GlobalFont->FontInfo->FontName,\r
+               FontInfo->FontName,\r
+               StrSize (FontInfo->FontName)\r
+               ) == 0) &&\r
+            GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {\r
+          Matched = TRUE;\r
+        }\r
+        break;\r
+      case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_ANY_SIZE:\r
+        if (CompareMem (\r
+              GlobalFont->FontInfo->FontName,\r
+              FontInfo->FontName,\r
+              StrSize (FontInfo->FontName)\r
+              ) == 0) {\r
+          Matched = TRUE;\r
+        }\r
+        break;\r
+      case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:\r
+        if (CompareMem (\r
+              GlobalFont->FontInfo->FontName,\r
+              FontInfo->FontName,\r
+              StrSize (FontInfo->FontName)\r
+              ) == 0) {\r
+          if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {\r
+            Matched           = TRUE;\r
+          } else {\r
+            VagueMatched1     = TRUE;\r
+            GlobalFontBackup1 = GlobalFont;\r
+          }\r
+        }\r
+        break;\r
+      case EFI_FONT_INFO_ANY_SIZE:\r
+        if ((CompareMem (\r
+               GlobalFont->FontInfo->FontName,\r
+               FontInfo->FontName,\r
+               StrSize (FontInfo->FontName)\r
+               ) == 0) &&\r
+            GlobalFont->FontInfo->FontStyle  == FontInfo->FontStyle) {\r
+          Matched = TRUE;\r
+        }\r
+        break;\r
+      case EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:\r
+        if (CompareMem (\r
+              GlobalFont->FontInfo->FontName,\r
+              FontInfo->FontName,\r
+              StrSize (FontInfo->FontName)\r
+              ) == 0) {\r
+          if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+            Matched           = TRUE;\r
+          } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {\r
+            VagueMatched1     = TRUE;\r
+            GlobalFontBackup1 = GlobalFont;\r
+          }\r
+        }\r
+        break;\r
+      case EFI_FONT_INFO_RESTYLE:\r
+        if ((CompareMem (\r
+               GlobalFont->FontInfo->FontName,\r
+               FontInfo->FontName,\r
+               StrSize (FontInfo->FontName)\r
+               ) == 0) &&\r
+            GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {\r
+\r
+          if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+            Matched           = TRUE;\r
+          } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {\r
+            VagueMatched1     = TRUE;\r
+            GlobalFontBackup1 = GlobalFont;\r
+          }\r
+        }\r
+        break;\r
+      case EFI_FONT_INFO_RESIZE:\r
+        if ((CompareMem (\r
+               GlobalFont->FontInfo->FontName,\r
+               FontInfo->FontName,\r
+               StrSize (FontInfo->FontName)\r
+               ) == 0) &&\r
+            GlobalFont->FontInfo->FontStyle  == FontInfo->FontStyle) {\r
+\r
+          if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {\r
+            Matched           = TRUE;\r
+          } else {\r
+            VagueMatched1     = TRUE;\r
+            GlobalFontBackup1 = GlobalFont;\r
+          }\r
+        }\r
+        break;\r
+      case EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_RESTYLE:\r
+        if (CompareMem (\r
+              GlobalFont->FontInfo->FontName,\r
+              FontInfo->FontName,\r
+              StrSize (FontInfo->FontName)\r
+              ) == 0) {\r
+          if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+            if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {\r
+              Matched           = TRUE;\r
+            } else {\r
+              VagueMatched1     = TRUE;\r
+              GlobalFontBackup1 = GlobalFont;\r
+            }\r
+          } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {\r
+            if (GlobalFont->FontInfo->FontSize  == FontInfo->FontSize) {\r
+              VagueMatched1     = TRUE;\r
+              GlobalFontBackup1 = GlobalFont;\r
+            } else {\r
+              VagueMatched2     = TRUE;\r
+              GlobalFontBackup2 = GlobalFont;\r
+            }\r
+          }\r
+        }\r
+        break;\r
+      default:\r
+        break;\r
+      }\r
+\r
+      if (Matched) {\r
+        if (GlobalFontInfo != NULL) {\r
+          *GlobalFontInfo = GlobalFont;\r
+        }\r
+        return TRUE;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (VagueMatched1) {\r
+    if (GlobalFontInfo != NULL) {\r
+      *GlobalFontInfo = GlobalFontBackup1;\r
+    }\r
+    return TRUE;\r
+  } else if (VagueMatched2) {\r
+    if (GlobalFontInfo != NULL) {\r
+      *GlobalFontInfo = GlobalFontBackup2;\r
+    }\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+\r
+/**\r
+  Check whether the unicode represents a line break or not.\r
+\r
+  @param  Char                    Unicode character\r
+\r
+  @retval 0                       Yes, it is a line break.\r
+  @retval 1                       Yes, it is a hyphen that desires a line break\r
+                                  after this character.\r
+  @retval 2                       Yes, it is a dash that desires a line break\r
+                                  before and after it.\r
+  @retval -1                      No, it is not a link break.\r
+\r
+**/\r
+STATIC\r
+INT8\r
+IsLineBreak (\r
+  IN  CHAR16    Char\r
+  )\r
+{\r
+  UINT8         Byte1;\r
+  UINT8         Byte2;\r
+\r
+  //\r
+  // In little endian, Byte1 is the low byte of Char, Byte2 is the high byte of Char.\r
+  //\r
+  Byte1 = *((UINT8 *) (&Char));\r
+  Byte2 = *(((UINT8 *) (&Char) + 1));\r
+\r
+  if (Byte2 == 0x20) {\r
+    switch (Byte1) {\r
+    case 0x00:\r
+    case 0x01:\r
+    case 0x02:\r
+    case 0x03:\r
+    case 0x04:\r
+    case 0x05:\r
+    case 0x06:\r
+    case 0x08:\r
+    case 0x09:\r
+    case 0x0A:\r
+    case 0x0B:\r
+    case 0x28:\r
+    case 0x29:\r
+    case 0x5F:\r
+      return 0;\r
+    case 0x10:\r
+    case 0x12:\r
+    case 0x13:\r
+      return 1;\r
+    case 0x14:\r
+      //\r
+      // BUGBUG: Does it really require line break before it and after it?\r
+      //\r
+      return 2;\r
+    }\r
+  } else if (Byte2 == 0x00) {\r
+    switch (Byte1) {\r
+    case 0x20:\r
+    case 0x0C:\r
+    case 0x0D:\r
+      return 0;\r
+    }\r
+  }\r
+\r
+  switch (Char) {\r
+    case 0x1680:\r
+      return 0;\r
+    case 0x058A:\r
+    case 0x0F0B:\r
+    case 0x1361:\r
+    case 0x17D5:\r
+      return 1;\r
+  }\r
+\r
+  return -1;\r
+}\r
+\r
+\r
+/**\r
+  Renders a string to a bitmap or to the display.\r
+\r
+  @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.\r
+  @param  Flags                   Describes how the string is to be drawn.\r
+  @param  String                  Points to the null-terminated string to be\r
+                                  displayed.\r
+  @param  StringInfo              Points to the string output information,\r
+                                  including the color and font.  If NULL, then the\r
+                                  string will be output in the default system font\r
+                                  and color.\r
+  @param  Blt                     If this points to a non-NULL on entry, this\r
+                                  points to the image, which is Width pixels   wide\r
+                                  and Height pixels high. The string will be drawn\r
+                                  onto this image and\r
+                                  EFI_HII_OUT_FLAG_CLIP is implied. If this points\r
+                                  to a NULL on entry, then a              buffer\r
+                                  will be allocated to hold the generated image and\r
+                                  the pointer updated on exit. It is the caller¡¯s\r
+                                  responsibility to free this buffer.\r
+  @param  BltX,BLTY               Specifies the offset from the left and top edge\r
+                                  of the image of the first character cell in the\r
+                                  image.\r
+  @param  RowInfoArray            If this is non-NULL on entry, then on exit, this\r
+                                  will point to an allocated buffer    containing\r
+                                  row information and RowInfoArraySize will be\r
+                                  updated to contain the        number of elements.\r
+                                  This array describes the characters which were at\r
+                                  least partially drawn and the heights of the\r
+                                  rows. It is the caller¡¯s responsibility to free\r
+                                  this buffer.\r
+  @param  RowInfoArraySize        If this is non-NULL on entry, then on exit it\r
+                                  contains the number of elements in RowInfoArray.\r
+  @param  ColumnInfoArray         If this is non-NULL, then on return it will be\r
+                                  filled with the horizontal offset for each\r
+                                  character in the string on the row where it is\r
+                                  displayed. Non-printing characters will     have\r
+                                  the offset ~0. The caller is responsible to\r
+                                  allocate a buffer large enough so that    there\r
+                                  is one entry for each character in the string,\r
+                                  not including the null-terminator. It is possible\r
+                                  when character display is normalized that some\r
+                                  character cells overlap.\r
+\r
+  @retval EFI_SUCCESS             The string was successfully rendered.\r
+  @retval EFI_OUT_OF_RESOURCES    Unable to allocate an output buffer for\r
+                                  RowInfoArray or Blt.\r
+  @retval EFI_INVALID_PARAMETER   The String or Blt was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiStringToImage (\r
+  IN  CONST EFI_HII_FONT_PROTOCOL    *This,\r
+  IN  EFI_HII_OUT_FLAGS              Flags,\r
+  IN  CONST EFI_STRING               String,\r
+  IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfo       OPTIONAL,\r
+  IN  OUT EFI_IMAGE_OUTPUT           **Blt,\r
+  IN  UINTN                          BltX,\r
+  IN  UINTN                          BltY,\r
+  OUT EFI_HII_ROW_INFO               **RowInfoArray    OPTIONAL,\r
+  OUT UINTN                          *RowInfoArraySize OPTIONAL,\r
+  OUT UINTN                          *ColumnInfoArray  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  UINT8                               **GlyphBuf;\r
+  EFI_HII_GLYPH_INFO                  *Cell;\r
+  UINT8                               *Attributes;\r
+  EFI_IMAGE_OUTPUT                    *Image;\r
+  EFI_STRING                          StringPtr;\r
+  EFI_STRING                          StringTmp;\r
+  EFI_HII_ROW_INFO                    *RowInfo;\r
+  UINTN                               LineWidth;\r
+  UINTN                               LineHeight;\r
+  UINTN                               BaseLineOffset;\r
+  UINT16                              MaxRowNum;\r
+  UINT16                              RowIndex;\r
+  UINTN                               Index;\r
+  UINTN                               Index1;\r
+  EFI_FONT_DISPLAY_INFO               *StringInfoOut;\r
+  EFI_FONT_DISPLAY_INFO               *SystemDefault;\r
+  EFI_FONT_HANDLE                     FontHandle;\r
+  EFI_STRING                          StringIn;\r
+  EFI_STRING                          StringIn2;\r
+  UINT16                              Height;\r
+  EFI_FONT_INFO                       *FontInfo;\r
+  BOOLEAN                             SysFontFlag;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL       Foreground;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL       Background;\r
+  BOOLEAN                             Transparent;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL       *BltBuffer;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL       *BufferPtr;\r
+  UINTN                               RowInfoSize;\r
+  BOOLEAN                             LineBreak;\r
+\r
+  //\r
+  // Check incoming parameters.\r
+  //\r
+\r
+  if (This == NULL || String == NULL || Blt == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (*Blt == NULL) {\r
+    //\r
+    // These two flag cannot be used if Blt is NULL upon entry.\r
+    //\r
+    if ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    if ((Flags & EFI_HII_OUT_FLAG_CLIP) == EFI_HII_OUT_FLAG_CLIP) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  //\r
+  // These two flags require that EFI_HII_OUT_FLAG_CLIP be also set.\r
+  //\r
+  if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLEAN_X)) ==  EFI_HII_OUT_FLAG_CLEAN_X) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLEAN_Y)) ==  EFI_HII_OUT_FLAG_CLEAN_Y) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // This flag cannot be used with EFI_HII_OUT_FLAG_CLEAN_X.\r
+  //\r
+  if ((Flags & (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLEAN_X)) ==  (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLEAN_X)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  GlyphBuf = (UINT8 **) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (UINT8 *));\r
+  ASSERT (GlyphBuf != NULL);\r
+  Cell = (EFI_HII_GLYPH_INFO *) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (EFI_HII_GLYPH_INFO));\r
+  ASSERT (Cell != NULL);\r
+  Attributes = (UINT8 *) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (UINT8));\r
+  ASSERT (Attributes != NULL);\r
+\r
+  RowInfo       = NULL;\r
+  Status        = EFI_SUCCESS;\r
+  StringIn2     = NULL;\r
+  SystemDefault = NULL;\r
+\r
+  //\r
+  // Calculate the string output information, including specified color and font .\r
+  // If StringInfo does not points to system font info, it must indicate an existing\r
+  // EFI_FONT_INFO.\r
+  //\r
+  StringInfoOut = NULL;\r
+  FontHandle    = NULL;\r
+  Private       = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  SysFontFlag   = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL);\r
+\r
+  if (SysFontFlag) {\r
+    FontInfo   = NULL;\r
+    Height     = SystemDefault->FontInfo.FontSize;\r
+    Foreground = SystemDefault->ForegroundColor;\r
+    Background = SystemDefault->BackgroundColor;\r
+\r
+  } else {\r
+    Status = HiiGetFontInfo (This, &FontHandle, (EFI_FONT_DISPLAY_INFO *) StringInfo, &StringInfoOut, NULL);\r
+    if (Status == EFI_NOT_FOUND) {\r
+      //\r
+      // The specified EFI_FONT_DISPLAY_INFO does not exist in current database.\r
+      // Use the system font instead. Still use the color specified by StringInfo.\r
+      //\r
+      SysFontFlag = TRUE;\r
+      FontInfo    = NULL;\r
+      Height      = SystemDefault->FontInfo.FontSize;\r
+      Foreground  = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->ForegroundColor;\r
+      Background  = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->BackgroundColor;\r
+\r
+    } else {\r
+      FontInfo   = &StringInfoOut->FontInfo;\r
+      Height     = StringInfoOut->FontInfo.FontSize;\r
+      Foreground = StringInfoOut->ForegroundColor;\r
+      Background = StringInfoOut->BackgroundColor;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Parse the string to be displayed to drop some ignored characters.\r
+  //\r
+\r
+  StringPtr = String;\r
+  StringIn  = NULL;\r
+\r
+  //\r
+  // Ignore line-break characters only. Hyphens or dash character will be displayed\r
+  // without line-break opportunity.\r
+  //\r
+  if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == EFI_HII_IGNORE_LINE_BREAK) {\r
+    StringIn = AllocateZeroPool (StrSize (StringPtr));\r
+    if (StringIn == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Exit;\r
+    }\r
+    StringTmp = StringIn;\r
+    while (*StringPtr != 0) {\r
+      if (IsLineBreak (*StringPtr) == 0) {\r
+        StringPtr++;\r
+      } else {\r
+        *StringTmp++ = *StringPtr++;\r
+      }\r
+    }\r
+    *StringTmp = 0;\r
+    StringPtr  = StringIn;\r
+  }\r
+  //\r
+  // If EFI_HII_IGNORE_IF_NO_GLYPH is set, then characters which have no glyphs\r
+  // are not drawn. Otherwise they are replaced wth Unicode character 0xFFFD.\r
+  //\r
+  StringIn2  = AllocateZeroPool (StrSize (StringPtr));\r
+  if (StringIn2 == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Exit;\r
+  }\r
+  Index     = 0;\r
+  StringTmp = StringIn2;\r
+\r
+  while (*StringPtr != 0 && Index < MAX_STRING_LENGTH) {\r
+    Status = GetGlyphBuffer (Private, *StringPtr, FontInfo, &GlyphBuf[Index], &Cell[Index], &Attributes[Index]);\r
+    if (Status == EFI_NOT_FOUND) {\r
+      if ((Flags & EFI_HII_IGNORE_IF_NO_GLYPH) == EFI_HII_IGNORE_IF_NO_GLYPH) {\r
+        SafeFreePool (GlyphBuf[Index]);\r
+        GlyphBuf[Index] = NULL;\r
+        StringPtr++;\r
+      } else {\r
+        //\r
+        // Unicode 0xFFFD must exist in current hii database if this flag is not set.\r
+        //\r
+        Status = GetGlyphBuffer (\r
+                   Private,\r
+                   REPLACE_UNKNOWN_GLYPH,\r
+                   FontInfo,\r
+                   &GlyphBuf[Index],\r
+                   &Cell[Index],\r
+                   &Attributes[Index]\r
+                   );\r
+        if (EFI_ERROR (Status)) {\r
+          Status = EFI_INVALID_PARAMETER;\r
+          goto Exit;\r
+        }\r
+        *StringTmp++ = *StringPtr++;\r
+        Index++;\r
+      }\r
+    } else if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    } else {\r
+      *StringTmp++ = *StringPtr++;\r
+      Index++;\r
+    }\r
+  }\r
+  *StringTmp = 0;\r
+  StringPtr  = StringIn2;\r
+\r
+  //\r
+  // Draw the string according to the specified EFI_HII_OUT_FLAGS and Blt.\r
+  // If Blt is not NULL, then EFI_HII_OUT_FLAG_CLIP is implied, render this string\r
+  // to an existing image (bitmap or screen depending on flags) pointed by "*Blt".\r
+  // Otherwise render this string to a new allocated image and output it.\r
+  //\r
+  if (*Blt != NULL) {\r
+    Image     = *Blt;\r
+    BufferPtr = Image->Image.Bitmap + Image->Width * BltY + BltX;\r
+    MaxRowNum = (UINT16) (Image->Height / Height);\r
+    if (Image->Height % Height != 0) {\r
+      MaxRowNum++;\r
+    }\r
+\r
+    RowInfo = (EFI_HII_ROW_INFO *) AllocateZeroPool (MaxRowNum * sizeof (EFI_HII_ROW_INFO));\r
+    if (RowInfo == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Exit;\r
+    }\r
+\r
+    //\r
+    // Format the glyph buffer according to flags.\r
+    //\r
+\r
+    Transparent = (BOOLEAN) ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT ? TRUE : FALSE);\r
+    if ((Flags & EFI_HII_OUT_FLAG_CLEAN_Y) == EFI_HII_OUT_FLAG_CLEAN_Y) {\r
+      //\r
+      // Don't draw at all if there is only one row and\r
+      // the row's bottom-most on pixel cannot fit.\r
+      //\r
+      if (MaxRowNum == 1 && SysFontFlag) {\r
+        Status = EFI_SUCCESS;\r
+        goto Exit;\r
+      }\r
+    }\r
+\r
+    for (RowIndex = 0, Index = 0; RowIndex < MaxRowNum && StringPtr[Index] != 0; ) {\r
+      LineWidth      = 0;\r
+      LineHeight     = 0;\r
+      BaseLineOffset = 0;\r
+      LineBreak      = FALSE;\r
+\r
+      //\r
+      // Calculate how many characters there are in a row.\r
+      //\r
+      RowInfo[RowIndex].StartIndex = Index;\r
+\r
+      while (LineWidth + BltX < Image->Width && StringPtr[Index] != 0) {\r
+        LineWidth += (UINTN) Cell[Index].AdvanceX;\r
+        if (LineHeight < Cell[Index].Height) {\r
+          LineHeight = (UINTN) Cell[Index].Height;\r
+        }\r
+        BaseLineOffset += (UINTN) Cell[Index].OffsetY;\r
+\r
+        if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0 &&\r
+            (Flags & EFI_HII_OUT_FLAG_WRAP) == 0 &&\r
+             IsLineBreak (StringPtr[Index]) > 0) {\r
+          //\r
+          // It is a line break that ends this row.\r
+          //\r
+          Index++;\r
+          break;\r
+        }\r
+\r
+        Index++;\r
+      }\r
+\r
+      //\r
+      // If this character is the last character of a row, we need not\r
+      // draw its (AdvanceX - Width) for next character.\r
+      //\r
+      Index--;\r
+      if (!SysFontFlag) {\r
+        LineWidth -= (UINTN) (Cell[Index].AdvanceX - Cell[Index].Width);\r
+      }\r
+\r
+      //\r
+      // EFI_HII_OUT_FLAG_WRAP will wrap the text at the right-most line-break\r
+      // opportunity prior to a character whose right-most extent would exceed Width.\r
+      // Search the right-most line-break opportunity here.\r
+      //\r
+      if ((Flags & EFI_HII_OUT_FLAG_WRAP) == EFI_HII_OUT_FLAG_WRAP) {\r
+        if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) {\r
+          for (Index1 = RowInfo[RowIndex].EndIndex; Index1 >= RowInfo[RowIndex].StartIndex; Index1--) {\r
+            if (IsLineBreak (StringPtr[Index1]) > 0) {\r
+              LineBreak = TRUE;\r
+              RowInfo[RowIndex].EndIndex = Index1 - 1;\r
+              break;\r
+            }\r
+          }\r
+        }\r
+        //\r
+        // If no line-break opportunity can be found, then the text will\r
+        // behave as if EFI_HII_OUT_FLAG_CLEAN_X is set.\r
+        //\r
+        if (!LineBreak) {\r
+          Flags &= (~ (EFI_HII_OUT_FLAGS) EFI_HII_OUT_FLAG_WRAP);\r
+          Flags |= EFI_HII_OUT_FLAG_CLEAN_X;\r
+        }\r
+      }\r
+\r
+      //\r
+      // Clip the right-most character if cannot fit when EFI_HII_OUT_FLAG_CLEAN_X is set.\r
+      //\r
+      if (LineWidth + BltX <= Image->Width ||\r
+          (LineWidth + BltX > Image->Width && (Flags & EFI_HII_OUT_FLAG_CLEAN_X) == 0)) {\r
+        //\r
+        // Record right-most character in RowInfo even if it is partially displayed.\r
+        //\r
+        RowInfo[RowIndex].EndIndex       = Index;\r
+        RowInfo[RowIndex].LineWidth      = LineWidth;\r
+        RowInfo[RowIndex].LineHeight     = LineHeight;\r
+        RowInfo[RowIndex].BaselineOffset = BaseLineOffset;\r
+      } else {\r
+        //\r
+        // When EFI_HII_OUT_FLAG_CLEAN_X is set, it will not draw a character\r
+        // if its right-most on pixel cannot fit.\r
+        //\r
+        if (Index > 0) {\r
+          RowInfo[RowIndex].EndIndex       = Index - 1;\r
+          RowInfo[RowIndex].LineWidth      = LineWidth - Cell[Index].AdvanceX;\r
+          RowInfo[RowIndex].BaselineOffset = BaseLineOffset - Cell[Index].OffsetY;\r
+          if (LineHeight > Cell[Index - 1].Height) {\r
+            LineHeight = Cell[Index - 1].Height;\r
+          }\r
+          RowInfo[RowIndex].LineHeight     = LineHeight;\r
+        } else {\r
+          //\r
+          // There is only one column and it can not be drawn so that return directly.\r
+          //\r
+          Status = EFI_SUCCESS;\r
+          goto Exit;\r
+        }\r
+      }\r
+\r
+      //\r
+      // Clip the final row if the row's bottom-most on pixel cannot fit when\r
+      // EFI_HII_OUT_FLAG_CLEAN_Y is set.\r
+      //\r
+      if (RowIndex == MaxRowNum - 1 && Image->Height < LineHeight) {\r
+        LineHeight = Image->Height;\r
+        if ((Flags & EFI_HII_OUT_FLAG_CLEAN_Y) == EFI_HII_OUT_FLAG_CLEAN_Y) {\r
+          //\r
+          // Don't draw at all if the row's bottom-most on pixel cannot fit.\r
+          //\r
+          break;\r
+        }\r
+      }\r
+\r
+      //\r
+      // Draw it to screen or existing bitmap depending on whether\r
+      // EFI_HII_DIRECT_TO_SCREEN is set.\r
+      //\r
+      if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {\r
+        BltBuffer = AllocateZeroPool (RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+        if (BltBuffer == NULL) {\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          goto Exit;\r
+        }\r
+        BufferPtr = BltBuffer;\r
+        for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {\r
+          GlyphToImage (\r
+            GlyphBuf[Index1],\r
+            Foreground,\r
+            Background,\r
+            RowInfo[RowIndex].LineWidth,\r
+            RowInfo[RowIndex].LineHeight,\r
+            Transparent,\r
+            Cell[Index1],\r
+            Attributes[Index1],\r
+            &BufferPtr\r
+            );\r
+          if (ColumnInfoArray != NULL) {\r
+            if (Index1 == RowInfo[RowIndex].StartIndex) {\r
+              *ColumnInfoArray = 0;\r
+            } else {\r
+              *ColumnInfoArray = Cell[Index1 -1].AdvanceX;\r
+            }\r
+            ColumnInfoArray++;\r
+          }\r
+        }\r
+        Status = Image->Image.Screen->Blt (\r
+                                        Image->Image.Screen,\r
+                                        BltBuffer,\r
+                                        EfiBltBufferToVideo,\r
+                                        0,\r
+                                        0,\r
+                                        BltX,\r
+                                        BltY,\r
+                                        RowInfo[RowIndex].LineWidth,\r
+                                        RowInfo[RowIndex].LineHeight,\r
+                                        0\r
+                                        );\r
+        if (EFI_ERROR (Status)) {\r
+          SafeFreePool (BltBuffer);\r
+          goto Exit;\r
+        }\r
+\r
+        SafeFreePool (BltBuffer);\r
+\r
+      } else {\r
+        for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {\r
+          GlyphToImage (\r
+            GlyphBuf[Index1],\r
+            Foreground,\r
+            Background,\r
+            Image->Width,\r
+            Image->Height,\r
+            Transparent,\r
+            Cell[Index1],\r
+            Attributes[Index1],\r
+            &BufferPtr\r
+            );\r
+          if (ColumnInfoArray != NULL) {\r
+            if (Index1 == RowInfo[RowIndex].StartIndex) {\r
+              *ColumnInfoArray = 0;\r
+            } else {\r
+              *ColumnInfoArray = Cell[Index1 -1].AdvanceX;\r
+            }\r
+            ColumnInfoArray++;\r
+          }\r
+        }\r
+        //\r
+        // Jump to next row\r
+        //\r
+        BufferPtr += BltX + Image->Width * (LineHeight - 1);\r
+      }\r
+\r
+      Index++;\r
+      RowIndex++;\r
+\r
+    }\r
+\r
+    //\r
+    // Write output parameters.\r
+    //\r
+    RowInfoSize = RowIndex * sizeof (EFI_HII_ROW_INFO);\r
+    if (RowInfoArray != NULL) {\r
+      *RowInfoArray = AllocateZeroPool (RowInfoSize);\r
+      if (*RowInfoArray == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto Exit;\r
+      }\r
+      CopyMem (*RowInfoArray, RowInfo, RowInfoSize);\r
+    }\r
+    if (RowInfoArraySize != NULL) {\r
+      *RowInfoArraySize = RowIndex;\r
+    }\r
+\r
+  } else {\r
+    //\r
+    // Create a new bitmap and draw the string onto this image.\r
+    //\r
+    Image = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
+    if (Image == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    Image->Width  = 800;\r
+    Image->Height = 600;\r
+    Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height *sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+    if (Image->Image.Bitmap == NULL) {\r
+      SafeFreePool (Image);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    //\r
+    // Other flags are not permitted when Blt is NULL.\r
+    //\r
+    Flags &= EFI_HII_OUT_FLAG_WRAP | EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK;\r
+    Status = HiiStringToImage (\r
+               This,\r
+               Flags,\r
+               String,\r
+               StringInfo,\r
+               &Image,\r
+               BltX,\r
+               BltY,\r
+               RowInfoArray,\r
+               RowInfoArraySize,\r
+               ColumnInfoArray\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    *Blt = Image;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+\r
+  for (Index = 0; Index < MAX_STRING_LENGTH; Index++) {\r
+    SafeFreePool (GlyphBuf[Index]);\r
+  }\r
+  SafeFreePool (StringIn);\r
+  SafeFreePool (StringIn2);\r
+  SafeFreePool (StringInfoOut);\r
+  SafeFreePool (RowInfo);\r
+  SafeFreePool (SystemDefault);\r
+  SafeFreePool (GlyphBuf);\r
+  SafeFreePool (Cell);\r
+  SafeFreePool (Attributes);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Render a string to a bitmap or the screen containing the contents of the specified string.\r
+\r
+  @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.\r
+  @param  Flags                   Describes how the string is to be drawn.\r
+  @param  PackageList             The package list in the HII database to search\r
+                                  for the specified string.\r
+  @param  StringId                The string¡¯s id, which is unique within\r
+                                  PackageList.\r
+  @param  Language                Points to the language for the retrieved string.\r
+                                  If NULL, then the current system language is\r
+                                  used.\r
+  @param  StringInfo              Points to the string output information,\r
+                                  including the color and font.  If NULL, then the\r
+                                  string will be output in the default system font\r
+                                  and color.\r
+  @param  Blt                     If this points to a non-NULL on entry, this\r
+                                  points to the image, which is Width pixels   wide\r
+                                  and Height pixels high. The string will be drawn\r
+                                  onto this image and\r
+                                  EFI_HII_OUT_FLAG_CLIP is implied. If this points\r
+                                  to a NULL on entry, then a              buffer\r
+                                  will be allocated to hold the generated image and\r
+                                  the pointer updated on exit. It is the caller¡¯s\r
+                                  responsibility to free this buffer.\r
+  @param  BltX,BLTY               Specifies the offset from the left and top edge\r
+                                  of the image of the first character cell in the\r
+                                  image.\r
+  @param  RowInfoArray            If this is non-NULL on entry, then on exit, this\r
+                                  will point to an allocated buffer    containing\r
+                                  row information and RowInfoArraySize will be\r
+                                  updated to contain the        number of elements.\r
+                                  This array describes the characters which were at\r
+                                  least partially drawn and the heights of the\r
+                                  rows. It is the caller¡¯s responsibility to free\r
+                                  this buffer.\r
+  @param  RowInfoArraySize        If this is non-NULL on entry, then on exit it\r
+                                  contains the number of elements in RowInfoArray.\r
+  @param  ColumnInfoArray         If this is non-NULL, then on return it will be\r
+                                  filled with the horizontal offset for each\r
+                                  character in the string on the row where it is\r
+                                  displayed. Non-printing characters will     have\r
+                                  the offset ~0. The caller is responsible to\r
+                                  allocate a buffer large enough so that    there\r
+                                  is one entry for each character in the string,\r
+                                  not including the null-terminator. It is possible\r
+                                  when character display is normalized that some\r
+                                  character cells overlap.\r
+\r
+  @retval EFI_SUCCESS             The string was successfully rendered.\r
+  @retval EFI_OUT_OF_RESOURCES    Unable to allocate an output buffer for\r
+                                  RowInfoArray or Blt.\r
+  @retval EFI_INVALID_PARAMETER   The PackageList was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiStringIdToImage (\r
+  IN  CONST EFI_HII_FONT_PROTOCOL    *This,\r
+  IN  EFI_HII_OUT_FLAGS              Flags,\r
+  IN  EFI_HII_HANDLE                 PackageList,\r
+  IN  EFI_STRING_ID                  StringId,\r
+  IN  CONST CHAR8*                   Language,\r
+  IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfo       OPTIONAL,\r
+  IN  OUT EFI_IMAGE_OUTPUT           **Blt,\r
+  IN  UINTN                          BltX,\r
+  IN  UINTN                          BltY,\r
+  OUT EFI_HII_ROW_INFO               **RowInfoArray    OPTIONAL,\r
+  OUT UINTN                          *RowInfoArraySize OPTIONAL,\r
+  OUT UINTN                          *ColumnInfoArray  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  EFI_STRING                          String;\r
+  UINTN                               StringSize;\r
+\r
+  if (This == NULL || PackageList == NULL || Blt == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!IsHiiHandleValid (PackageList)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // Get the string to be displayed.\r
+  //\r
+\r
+  StringSize = MAX_STRING_LENGTH;\r
+  String = (EFI_STRING) AllocateZeroPool (StringSize);\r
+  if (String == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = Private->HiiString.GetString (\r
+                                &Private->HiiString,\r
+                                Language,\r
+                                PackageList,\r
+                                StringId,\r
+                                String,\r
+                                &StringSize,\r
+                                NULL\r
+                                );\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    SafeFreePool (String);\r
+    String = (EFI_STRING) AllocateZeroPool (StringSize);\r
+    if (String == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    Status = Private->HiiString.GetString (\r
+                                  &Private->HiiString,\r
+                                  Language,\r
+                                  PackageList,\r
+                                  StringId,\r
+                                  String,\r
+                                  &StringSize,\r
+                                  NULL\r
+                                  );\r
+\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    SafeFreePool (String);\r
+    return Status;\r
+  }\r
+\r
+  return HiiStringToImage (\r
+           This,\r
+           Flags,\r
+           String,\r
+           StringInfo,\r
+           Blt,\r
+           BltX,\r
+           BltY,\r
+           RowInfoArray,\r
+           RowInfoArraySize,\r
+           ColumnInfoArray\r
+           );\r
+\r
+}\r
+\r
+\r
+/**\r
+  Convert the glyph for a single character into a bitmap.\r
+\r
+  @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.\r
+  @param  Char                    Character to retrieve.\r
+  @param  StringInfo              Points to the string font and color information\r
+                                  or NULL if the string should use the default\r
+                                  system font and color.\r
+  @param  Blt                     Thus must point to a NULL on entry. A buffer will\r
+                                  be allocated to hold the output and the pointer\r
+                                  updated on exit. It is the caller¡¯s\r
+                                  responsibility to free this buffer.\r
+  @param  Baseline                Number of pixels from the bottom of the bitmap to\r
+                                  the baseline.\r
+\r
+  @retval EFI_SUCCESS             Glyph bitmap created.\r
+  @retval EFI_OUT_OF_RESOURCES    Unable to allocate the output buffer Blt.\r
+  @retval EFI_WARN_UNKNOWN_GLYPH  The glyph was unknown and was replaced with the\r
+                                  glyph for Unicode character 0xFFFD.\r
+  @retval EFI_INVALID_PARAMETER   Blt is NULL or *Blt is not NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetGlyph (\r
+  IN  CONST EFI_HII_FONT_PROTOCOL    *This,\r
+  IN  CHAR16                         Char,\r
+  IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfo,\r
+  OUT EFI_IMAGE_OUTPUT               **Blt,\r
+  OUT UINTN                          *Baseline OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                         Status;\r
+  HII_DATABASE_PRIVATE_DATA          *Private;\r
+  EFI_IMAGE_OUTPUT                   *Image;\r
+  UINT8                              *GlyphBuffer;\r
+  EFI_FONT_DISPLAY_INFO              *SystemDefault;\r
+  EFI_FONT_DISPLAY_INFO              *StringInfoOut;\r
+  BOOLEAN                            Default;\r
+  EFI_FONT_HANDLE                    FontHandle;\r
+  EFI_STRING                         String;\r
+  EFI_HII_GLYPH_INFO                 Cell;\r
+  EFI_FONT_INFO                      *FontInfo;\r
+  UINT8                              Attributes;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      Foreground;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      Background;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BltBuffer;\r
+\r
+  if (This == NULL || Blt == NULL || *Blt != NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  Default       = FALSE;\r
+  Image         = NULL;\r
+  SystemDefault = NULL;\r
+  FontHandle    = NULL;\r
+  String        = NULL;\r
+  GlyphBuffer   = NULL;\r
+  StringInfoOut = NULL;\r
+  FontInfo      = NULL;\r
+\r
+  ZeroMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+  ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+\r
+  Default = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL);\r
+\r
+  if (!Default) {\r
+    //\r
+    // Find out a EFI_FONT_DISPLAY_INFO which could display the character in\r
+    // the specified color and font.\r
+    //\r
+    String = (EFI_STRING) AllocateZeroPool (sizeof (CHAR16) * 2);\r
+    if (String == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Exit;\r
+    }\r
+    *String = Char;\r
+    *(String + 1) = 0;\r
+\r
+    Status = HiiGetFontInfo (This, &FontHandle, StringInfo, &StringInfoOut, String);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
+    FontInfo   = &StringInfoOut->FontInfo;\r
+    Foreground = StringInfoOut->ForegroundColor;\r
+    Background = StringInfoOut->BackgroundColor;\r
+  } else {\r
+    Foreground = SystemDefault->ForegroundColor;\r
+    Background = SystemDefault->BackgroundColor;\r
+  }\r
+\r
+  Status = GetGlyphBuffer (Private, Char, FontInfo, &GlyphBuffer, &Cell, &Attributes);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  Image = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
+  if (Image == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Exit;\r
+  }\r
+  Image->Width   = Cell.Width;\r
+  Image->Height  = Cell.Height;\r
+\r
+  Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+  if (Image->Image.Bitmap == NULL) {\r
+    SafeFreePool (Image);\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Exit;\r
+  }\r
+\r
+  BltBuffer = Image->Image.Bitmap;\r
+  GlyphToImage (\r
+    GlyphBuffer,\r
+    Foreground,\r
+    Background,\r
+    Image->Width,\r
+    Image->Height,\r
+    FALSE,\r
+    Cell,\r
+    Attributes,\r
+    &BltBuffer\r
+    );\r
+\r
+  *Blt = Image;\r
+  if (Baseline != NULL) {\r
+    *Baseline = Cell.OffsetY;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+\r
+  if (Status == EFI_NOT_FOUND) {\r
+    //\r
+    // Glyph is unknown and replaced with the glyph for unicode character 0xFFFD\r
+    //\r
+    if (Char != REPLACE_UNKNOWN_GLYPH) {\r
+      Status = HiiGetGlyph (This, REPLACE_UNKNOWN_GLYPH, StringInfo, Blt, Baseline);\r
+      if (!EFI_ERROR (Status)) {\r
+        Status = EFI_WARN_UNKNOWN_GLYPH;\r
+      }\r
+    } else {\r
+      Status = EFI_WARN_UNKNOWN_GLYPH;\r
+    }\r
+  }\r
+\r
+  SafeFreePool (SystemDefault);\r
+  SafeFreePool (StringInfoOut);\r
+  SafeFreePool (String);\r
+  SafeFreePool (GlyphBuffer);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function iterates through fonts which match the specified font, using\r
+  the specified criteria. If String is non-NULL, then all of the characters in\r
+  the string must exist in order for a candidate font to be returned.\r
+\r
+  @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.\r
+  @param  FontHandle              On entry, points to the font handle returned by a\r
+                                   previous call to GetFontInfo() or NULL to start\r
+                                  with the  first font. On return, points to the\r
+                                  returned font handle or points to NULL if there\r
+                                  are no more matching fonts.\r
+  @param  StringInfoIn            Upon entry, points to the font to return\r
+                                  information about.\r
+  @param  StringInfoOut           Upon return, contains the matching font¡¯s\r
+                                  information.  If NULL, then no information is\r
+                                  returned. It's caller's responsibility to free\r
+                                  this buffer.\r
+  @param  String                  Points to the string which will be tested to\r
+                                  determine  if all characters are available. If\r
+                                  NULL, then any font  is acceptable.\r
+\r
+  @retval EFI_SUCCESS             Matching font returned successfully.\r
+  @retval EFI_NOT_FOUND           No matching font was found.\r
+  @retval EFI_INVALID_PARAMETER   StringInfoIn is NULL.\r
+  @retval EFI_OUT_OF_RESOURCES    There were insufficient resources to complete the\r
+                                  request.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetFontInfo (\r
+  IN  CONST EFI_HII_FONT_PROTOCOL    *This,\r
+  IN  OUT   EFI_FONT_HANDLE          *FontHandle,\r
+  IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfoIn,\r
+  OUT       EFI_FONT_DISPLAY_INFO    **StringInfoOut,\r
+  IN  CONST EFI_STRING               String OPTIONAL\r
+  )\r
+{\r
+  HII_DATABASE_PRIVATE_DATA          *Private;\r
+  EFI_STATUS                         Status;\r
+  EFI_FONT_DISPLAY_INFO              *SystemDefault;\r
+  EFI_FONT_DISPLAY_INFO              InfoOut;\r
+  UINTN                              StringInfoOutLen;\r
+  EFI_FONT_INFO                      *FontInfo;\r
+  HII_GLOBAL_FONT_INFO               *GlobalFont;\r
+  EFI_STRING                         StringIn;\r
+  EFI_FONT_HANDLE                    LocalFontHandle;\r
+\r
+  if (This == NULL || StringInfoIn == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Check the font information mask to make sure it is valid.\r
+  //\r
+  if (((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_FONT  | EFI_FONT_INFO_ANY_FONT))  ==\r
+       (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT))   ||\r
+      ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE  | EFI_FONT_INFO_ANY_SIZE))  ==\r
+       (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE))   ||\r
+      ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ==\r
+       (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ||\r
+      ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESIZE    | EFI_FONT_INFO_ANY_SIZE))  ==\r
+       (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE))     ||\r
+      ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESTYLE   | EFI_FONT_INFO_ANY_STYLE)) ==\r
+       (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE))) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  FontInfo        = NULL;\r
+  LocalFontHandle = NULL;\r
+  if (FontHandle != NULL) {\r
+    LocalFontHandle = *FontHandle;\r
+  }\r
+\r
+  //\r
+  // Get default system display info, if StringInfoIn points to\r
+  // system display info, return it directly.\r
+  //\r
+  Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  if (IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, &SystemDefault, &StringInfoOutLen)) {\r
+    if (StringInfoOut != NULL) {\r
+      *StringInfoOut = AllocateCopyPool (StringInfoOutLen, (EFI_FONT_DISPLAY_INFO *) StringInfoIn);\r
+      if (*StringInfoOut == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        LocalFontHandle = NULL;\r
+        goto Exit;\r
+      }\r
+    }\r
+\r
+    LocalFontHandle = Private->FontInfoList.ForwardLink;\r
+    Status = EFI_SUCCESS;\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Parse the font information mask to find a matching font.\r
+  //\r
+\r
+  CopyMem (&InfoOut, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, sizeof (EFI_FONT_DISPLAY_INFO));\r
+\r
+  if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FONT) == EFI_FONT_INFO_SYS_FONT) {\r
+    Status = SaveFontName (SystemDefault->FontInfo.FontName, &FontInfo);\r
+  } else {\r
+    Status = SaveFontName (((EFI_FONT_DISPLAY_INFO *) StringInfoIn)->FontInfo.FontName, &FontInfo);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_SIZE) == EFI_FONT_INFO_SYS_SIZE) {\r
+    InfoOut.FontInfo.FontSize = SystemDefault->FontInfo.FontSize;\r
+  } else if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_STYLE) == EFI_FONT_INFO_SYS_STYLE) {\r
+    InfoOut.FontInfo.FontStyle = SystemDefault->FontInfo.FontStyle;\r
+  } else if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == EFI_FONT_INFO_SYS_FORE_COLOR) {\r
+    InfoOut.ForegroundColor = SystemDefault->ForegroundColor;\r
+  } else if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == EFI_FONT_INFO_SYS_BACK_COLOR) {\r
+    InfoOut.BackgroundColor = SystemDefault->BackgroundColor;\r
+  }\r
+\r
+  FontInfo->FontSize  = InfoOut.FontInfo.FontSize;\r
+  FontInfo->FontStyle = InfoOut.FontInfo.FontStyle;\r
+\r
+  if (IsFontInfoExisted (Private, FontInfo, &InfoOut.FontInfoMask, LocalFontHandle, &GlobalFont)) {\r
+    if (String != NULL) {\r
+      //\r
+      // Test to guarantee all characters are available in the found font.\r
+      //\r
+      StringIn = String;\r
+      while (*StringIn != 0) {\r
+        Status = FindGlyphBlock (GlobalFont->FontPackage, *StringIn, NULL, NULL, NULL);\r
+        if (EFI_ERROR (Status)) {\r
+          LocalFontHandle = NULL;\r
+          goto Exit;\r
+        }\r
+        StringIn++;\r
+      }\r
+\r
+      //\r
+      // Write to output parameter\r
+      //\r
+      if (StringInfoOut != NULL) {\r
+        StringInfoOutLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (EFI_FONT_INFO) + GlobalFont->FontInfoSize;\r
+        *StringInfoOut   = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (StringInfoOutLen);\r
+        if (*StringInfoOut == NULL) {\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          LocalFontHandle = NULL;\r
+          goto Exit;\r
+        }\r
+        CopyMem (*StringInfoOut, &InfoOut, sizeof (EFI_FONT_DISPLAY_INFO));\r
+        CopyMem (&(*StringInfoOut)->FontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);\r
+      }\r
+      LocalFontHandle = GlobalFont->Entry.ForwardLink;\r
+\r
+      Status = EFI_SUCCESS;\r
+      goto Exit;\r
+    }\r
+  } else {\r
+    LocalFontHandle = NULL;\r
+  }\r
+\r
+  Status = EFI_NOT_FOUND;\r
+\r
+Exit:\r
+\r
+  if (FontHandle != NULL) {\r
+    *FontHandle = LocalFontHandle;\r
+  }\r
+\r
+  SafeFreePool (SystemDefault);\r
+  SafeFreePool (FontInfo);\r
+  return Status;\r
+}\r
+\r
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
new file mode 100644 (file)
index 0000000..cf3519b
--- /dev/null
@@ -0,0 +1,1694 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+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.
+
+Module Name:
+
+    HiiDatabase.h
+
+Abstract:
+
+    Private structures definitions in HiiDatabase.
+
+Revision History
+
+
+**/
+
+#ifndef __HII_DATABASE_PRIVATE_H__
+#define __HII_DATABASE_PRIVATE_H__
+
+#include <PiDxe.h>
+
+#include <Protocol/ConsoleControl.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/HiiFont.h>
+#include <Protocol/HiiImage.h>
+#include <Protocol/HiiString.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/SimpleTextOut.h>
+
+#include <Guid/HiiKeyBoardLayout.h>
+
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#define HII_DATABASE_NOTIFY_GUID \
+  { \
+    0xc1c76, 0xd79e, 0x42fe, 0x86, 0xb, 0x8b, 0xe8, 0x7b, 0x3e, 0x7a, 0x78 \
+  }
+
+#define MAX_STRING_LENGTH                  1024
+#define MAX_FONT_NAME_LEN                  256
+#define NARROW_BASELINE                    15
+#define WIDE_BASELINE                      14
+#define SYS_FONT_INFO_MASK                 0x37
+#define REPLACE_UNKNOWN_GLYPH              0xFFFD
+#define PROPORTIONAL_GLYPH                 0x80
+#define NARROW_GLYPH                       0x40
+
+#define BITMAP_LEN_1_BIT(Width, Height)  (((Width) + 7) / 8 * (Height))
+#define BITMAP_LEN_4_BIT(Width, Height)  (((Width) + 1) / 2 * (Height))
+#define BITMAP_LEN_8_BIT(Width, Height)  ((Width) * (Height))
+#define BITMAP_LEN_24_BIT(Width, Height) ((Width) * (Height) * 3)
+
+//
+// Storage types
+//
+#define EFI_HII_VARSTORE_BUFFER            0
+#define EFI_HII_VARSTORE_NAME_VALUE        1
+#define EFI_HII_VARSTORE_EFI_VARIABLE      2
+
+#define HII_FORMSET_STORAGE_SIGNATURE           EFI_SIGNATURE_32 ('H', 'S', 'T', 'G')
+typedef struct {
+  UINTN               Signature;
+  LIST_ENTRY          Entry;
+
+  EFI_HII_HANDLE      HiiHandle;
+  EFI_HANDLE          DriverHandle;
+
+  UINT8               Type;   // EFI_HII_VARSTORE_BUFFER, EFI_HII_VARSTORE_NAME_VALUE, EFI_HII_VARSTORE_EFI_VARIABLE
+  EFI_GUID            Guid;
+  CHAR16              *Name;
+  UINT16              Size;
+} HII_FORMSET_STORAGE;
+
+#define HII_FORMSET_STORAGE_FROM_LINK(a)  CR (a, HII_FORMSET_STORAGE, Link, HII_FORMSET_STORAGE_SIGNATURE)
+
+
+//
+// String Package definitions
+//
+#define HII_STRING_PACKAGE_SIGNATURE    EFI_SIGNATURE_32 ('h','i','s','p')
+typedef struct _HII_STRING_PACKAGE_INSTANCE {
+  UINTN                                 Signature;
+  EFI_HII_STRING_PACKAGE_HDR            *StringPkgHdr;
+  UINT8                                 *StringBlock;
+  LIST_ENTRY                            StringEntry;
+  LIST_ENTRY                            FontInfoList;  // local font info list
+  UINT8                                 FontId;
+} HII_STRING_PACKAGE_INSTANCE;
+
+//
+// Form Package definitions
+//
+#define HII_IFR_PACKAGE_SIGNATURE       EFI_SIGNATURE_32 ('h','f','r','p')
+typedef struct _HII_IFR_PACKAGE_INSTANCE {
+  UINTN                                 Signature;
+  EFI_HII_PACKAGE_HEADER                FormPkgHdr;
+  UINT8                                 *IfrData;
+  LIST_ENTRY                            IfrEntry;
+} HII_IFR_PACKAGE_INSTANCE;
+
+//
+// Simple Font Package definitions
+//
+#define HII_S_FONT_PACKAGE_SIGNATURE    EFI_SIGNATURE_32 ('h','s','f','p')
+typedef struct _HII_SIMPLE_FONT_PACKAGE_INSTANCE {
+  UINTN                                 Signature;
+  EFI_HII_SIMPLE_FONT_PACKAGE_HDR       *SimpleFontPkgHdr;
+  LIST_ENTRY                            SimpleFontEntry;
+} HII_SIMPLE_FONT_PACKAGE_INSTANCE;
+
+//
+// Font Package definitions
+//
+#define HII_FONT_PACKAGE_SIGNATURE      EFI_SIGNATURE_32 ('h','i','f','p')
+typedef struct _HII_FONT_PACKAGE_INSTANCE {
+  UINTN                                 Signature;
+  EFI_HII_FONT_PACKAGE_HDR              *FontPkgHdr;
+  UINT8                                 *GlyphBlock;
+  LIST_ENTRY                            FontEntry;
+  LIST_ENTRY                            GlyphInfoList;
+} HII_FONT_PACKAGE_INSTANCE;
+
+#define HII_GLYPH_INFO_SIGNATURE        EFI_SIGNATURE_32 ('h','g','i','s')
+typedef struct _HII_GLYPH_INFO {
+  UINTN                                 Signature;
+  LIST_ENTRY                            Entry;
+  CHAR16                                CharId;
+  EFI_HII_GLYPH_INFO                    Cell;
+} HII_GLYPH_INFO;
+
+#define HII_FONT_INFO_SIGNATURE         EFI_SIGNATURE_32 ('h','l','f','i')
+typedef struct _HII_FONT_INFO {
+  UINTN                                 Signature;
+  LIST_ENTRY                            Entry;
+  LIST_ENTRY                            *GlobalEntry;
+  UINT8                                 FontId;
+} HII_FONT_INFO;
+
+#define HII_GLOBAL_FONT_INFO_SIGNATURE  EFI_SIGNATURE_32 ('h','g','f','i')
+typedef struct _HII_GLOBAL_FONT_INFO {
+  UINTN                                 Signature;
+  LIST_ENTRY                            Entry;
+  HII_FONT_PACKAGE_INSTANCE             *FontPackage;
+  UINTN                                 FontInfoSize;
+  EFI_FONT_INFO                         *FontInfo;
+} HII_GLOBAL_FONT_INFO;
+
+//
+// Image Package definitions
+//
+
+#define HII_PIXEL_MASK                  0x80
+
+typedef struct _HII_IMAGE_PACKAGE_INSTANCE {
+  EFI_HII_IMAGE_PACKAGE_HDR             ImagePkgHdr;
+  UINT32                                ImageBlockSize;
+  UINT32                                PaletteInfoSize;
+  UINT8                                 *ImageBlock;
+  UINT8                                 *PaletteBlock;
+} HII_IMAGE_PACKAGE_INSTANCE;
+
+//
+// Keyboard Layout Pacakge definitions
+//
+#define HII_KB_LAYOUT_PACKAGE_SIGNATURE EFI_SIGNATURE_32 ('h','k','l','p')
+typedef struct _HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE {
+  UINTN                                 Signature;
+  UINT8                                 *KeyboardPkg;
+  LIST_ENTRY                            KeyboardEntry;
+} HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE;
+
+//
+// Guid Package definitions
+//
+#define HII_GUID_PACKAGE_SIGNATURE      EFI_SIGNATURE_32 ('h','i','g','p')
+typedef struct _HII_GUID_PACKAGE_INSTANCE {
+  UINTN                                 Signature;
+  UINT8                                 *GuidPkg;
+  LIST_ENTRY                            GuidEntry;
+} HII_GUID_PACKAGE_INSTANCE;
+
+//
+// A package list can contain only one or less than one device path package.
+// This rule also applies to image package since ImageId can not be duplicate.
+//
+typedef struct _HII_DATABASE_PACKAGE_LIST_INSTANCE {
+  EFI_HII_PACKAGE_LIST_HEADER           PackageListHdr;
+  LIST_ENTRY                            GuidPkgHdr;
+  LIST_ENTRY                            FormPkgHdr;
+  LIST_ENTRY                            KeyboardLayoutHdr;
+  LIST_ENTRY                            StringPkgHdr;
+  LIST_ENTRY                            FontPkgHdr;
+  HII_IMAGE_PACKAGE_INSTANCE            *ImagePkg;
+  LIST_ENTRY                            SimpleFontPkgHdr;
+  UINT8                                 *DevicePathPkg;
+} HII_DATABASE_PACKAGE_LIST_INSTANCE;
+
+#define HII_HANDLE_SIGNATURE            EFI_SIGNATURE_32 ('h','i','h','l')
+
+typedef struct {
+  UINTN               Signature;
+  LIST_ENTRY          Handle;
+  UINTN               Key;
+} HII_HANDLE;
+
+#define HII_DATABASE_RECORD_SIGNATURE   EFI_SIGNATURE_32 ('h','i','d','r')
+
+typedef struct _HII_DATABASE_RECORD {
+  UINTN                                 Signature;
+  HII_DATABASE_PACKAGE_LIST_INSTANCE    *PackageList;
+  EFI_HANDLE                            DriverHandle;
+  EFI_HII_HANDLE                        Handle;
+  LIST_ENTRY                            DatabaseEntry;
+} HII_DATABASE_RECORD;
+
+#define HII_DATABASE_NOTIFY_SIGNATURE   EFI_SIGNATURE_32 ('h','i','d','n')
+
+typedef struct _HII_DATABASE_NOTIFY {
+  UINTN                                 Signature;
+  EFI_HANDLE                            NotifyHandle;
+  UINT8                                 PackageType;
+  EFI_GUID                              *PackageGuid;
+  EFI_HII_DATABASE_NOTIFY               PackageNotifyFn;
+  EFI_HII_DATABASE_NOTIFY_TYPE          NotifyType;
+  LIST_ENTRY                            DatabaseNotifyEntry;
+} HII_DATABASE_NOTIFY;
+
+#define HII_DATABASE_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('H', 'i', 'D', 'p')
+
+typedef struct _HII_DATABASE_PRIVATE_DATA {
+  UINTN                                 Signature;
+  LIST_ENTRY                            DatabaseList;
+  LIST_ENTRY                            DatabaseNotifyList;
+  EFI_HII_FONT_PROTOCOL                 HiiFont;
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+  EFI_HII_IMAGE_PROTOCOL                HiiImage;
+#endif
+  EFI_HII_STRING_PROTOCOL               HiiString;
+  EFI_HII_DATABASE_PROTOCOL             HiiDatabase;
+  EFI_HII_CONFIG_ROUTING_PROTOCOL       ConfigRouting;
+  LIST_ENTRY                            HiiHandleList;
+  INTN                                  HiiHandleCount;
+  LIST_ENTRY                            FontInfoList;  // global font info list
+  UINTN                                 Attribute;     // default system color
+  EFI_GUID                              CurrentLayoutGuid;
+  EFI_HII_KEYBOARD_LAYOUT               *CurrentLayout;
+} HII_DATABASE_PRIVATE_DATA;
+
+#define HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
+  CR (a, \
+      HII_DATABASE_PRIVATE_DATA, \
+      HiiFont, \
+      HII_DATABASE_PRIVATE_DATA_SIGNATURE \
+      )
+
+#define HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
+  CR (a, \
+      HII_DATABASE_PRIVATE_DATA, \
+      HiiImage, \
+      HII_DATABASE_PRIVATE_DATA_SIGNATURE \
+      )
+
+#define HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
+  CR (a, \
+      HII_DATABASE_PRIVATE_DATA, \
+      HiiString, \
+      HII_DATABASE_PRIVATE_DATA_SIGNATURE \
+      )
+
+#define HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
+  CR (a, \
+      HII_DATABASE_PRIVATE_DATA, \
+      HiiDatabase, \
+      HII_DATABASE_PRIVATE_DATA_SIGNATURE \
+      )
+
+#define CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
+  CR (a, \
+      HII_DATABASE_PRIVATE_DATA, \
+      ConfigRouting, \
+      HII_DATABASE_PRIVATE_DATA_SIGNATURE \
+      )
+
+//
+// Internal function prototypes.
+//
+
+/**
+  This function checks whether a handle is a valid EFI_HII_HANDLE
+
+  @param  Handle                  Pointer to a EFI_HII_HANDLE
+
+  @retval TRUE                    Valid
+  @retval FALSE                   Invalid
+
+**/
+BOOLEAN
+IsHiiHandleValid (
+  EFI_HII_HANDLE Handle
+  )
+;
+
+
+/**
+  This function checks whether EFI_FONT_INFO exists in current database. If
+  FontInfoMask is specified, check what options can be used to make a match.
+  Note that the masks relate to where the system default should be supplied
+  are ignored by this function.
+
+  @param  Private                 Hii database private structure.
+  @param  FontInfo                Points to EFI_FONT_INFO structure.
+  @param  FontInfoMask            If not NULL, describes what options can be used
+                                  to make a match between the font requested and
+                                  the font available. The caller must guarantee
+                                  this mask is valid.
+  @param  FontHandle              On entry, Points to the font handle returned by a
+                                  previous  call to GetFontInfo() or NULL to start
+                                  with the first font.
+  @param  GlobalFontInfo          If not NULL, output the corresponding globa font
+                                  info.
+
+  @retval TRUE                    Existed
+  @retval FALSE                   Not existed
+
+**/
+BOOLEAN
+IsFontInfoExisted (
+  IN  HII_DATABASE_PRIVATE_DATA *Private,
+  IN  EFI_FONT_INFO             *FontInfo,
+  IN  EFI_FONT_INFO_MASK        *FontInfoMask,   OPTIONAL
+  IN  EFI_FONT_HANDLE           FontHandle,      OPTIONAL
+  OUT HII_GLOBAL_FONT_INFO      **GlobalFontInfo OPTIONAL
+  )
+;
+
+
+/**
+  Retrieve system default font and color.
+
+  @param  Private                 HII database driver private data.
+  @param  FontInfo                Points to system default font output-related
+                                  information. It's caller's responsibility to free
+                                  this buffer.
+  @param  FontInfoSize            If not NULL, output the size of buffer FontInfo.
+
+  @retval EFI_SUCCESS             Cell information is added to the GlyphInfoList.
+  @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the
+                                  task.
+  @retval EFI_INVALID_PARAMETER   Any input parameter is invalid.
+
+**/
+EFI_STATUS
+GetSystemFont (
+  IN  HII_DATABASE_PRIVATE_DATA      *Private,
+  OUT EFI_FONT_DISPLAY_INFO          **FontInfo,
+  OUT UINTN                          *FontInfoSize OPTIONAL
+  )
+;
+
+
+/**
+  Parse all string blocks to find a String block specified by StringId.
+  If StringId = (EFI_STRING_ID) (-1), find out all EFI_HII_SIBT_FONT blocks
+  within this string package and backup its information.
+  If StringId = 0, output the string id of last string block (EFI_HII_SIBT_END).
+
+  @param  Private                 Hii database private structure.
+  @param  StringPackage           Hii string package instance.
+  @param  StringId                The string¡¯s id, which is unique within
+                                  PackageList.
+  @param  BlockType               Output the block type of found string block.
+  @param  StringBlockAddr         Output the block address of found string block.
+  @param  StringTextOffset        Offset, relative to the found block address, of
+                                  the  string text information.
+  @param  LastStringId            Output the last string id when StringId = 0.
+
+  @retval EFI_SUCCESS             The string text and font is retrieved
+                                  successfully.
+  @retval EFI_NOT_FOUND           The specified text or font info can not be found
+                                  out.
+  @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the
+                                  task.
+
+**/
+EFI_STATUS
+FindStringBlock (
+  IN HII_DATABASE_PRIVATE_DATA        *Private,
+  IN  HII_STRING_PACKAGE_INSTANCE     *StringPackage,
+  IN  EFI_STRING_ID                   StringId,
+  OUT UINT8                           *BlockType, OPTIONAL
+  OUT UINT8                           **StringBlockAddr, OPTIONAL
+  OUT UINTN                           *StringTextOffset, OPTIONAL
+  OUT EFI_STRING_ID                   *LastStringId OPTIONAL
+  )
+;
+
+
+/**
+  Parse all glyph blocks to find a glyph block specified by CharValue.
+  If CharValue = (CHAR16) (-1), collect all default character cell information
+  within this font package and backup its information.
+
+  @param  FontPackage             Hii string package instance.
+  @param  CharValue               Unicode character value, which identifies a glyph
+                                  block.
+  @param  GlyphBuffer             Output the corresponding bitmap data of the found
+                                  block. It is the caller's responsiblity to free
+                                  this buffer.
+  @param  Cell                    Output cell information of the encoded bitmap.
+  @param  GlyphBufferLen          If not NULL, output the length of GlyphBuffer.
+
+  @retval EFI_SUCCESS             The bitmap data is retrieved successfully.
+  @retval EFI_NOT_FOUND           The specified CharValue does not exist in current
+                                  database.
+  @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the
+                                  task.
+
+**/
+EFI_STATUS
+FindGlyphBlock (
+  IN  HII_FONT_PACKAGE_INSTANCE      *FontPackage,
+  IN  CHAR16                         CharValue,
+  OUT UINT8                          **GlyphBuffer, OPTIONAL
+  OUT EFI_HII_GLYPH_INFO             *Cell, OPTIONAL
+  OUT UINTN                          *GlyphBufferLen OPTIONAL
+  )
+;
+
+//
+// EFI_HII_FONT_PROTOCOL protocol interfaces
+//
+
+
+/**
+  Renders a string to a bitmap or to the display.
+
+  @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.
+  @param  Flags                   Describes how the string is to be drawn.
+  @param  String                  Points to the null-terminated string to be
+                                  displayed.
+  @param  StringInfo              Points to the string output information,
+                                  including the color and font.  If NULL, then the
+                                  string will be output in the default system font
+                                  and color.
+  @param  Blt                     If this points to a non-NULL on entry, this
+                                  points to the image, which is Width pixels   wide
+                                  and Height pixels high. The string will be drawn
+                                  onto this image and
+                                  EFI_HII_OUT_FLAG_CLIP is implied. If this points
+                                  to a NULL on entry, then a              buffer
+                                  will be allocated to hold the generated image and
+                                  the pointer updated on exit. It is the caller¡¯s
+                                  responsibility to free this buffer.
+  @param  BltX,BLTY               Specifies the offset from the left and top edge
+                                  of the image of the first character cell in the
+                                  image.
+  @param  RowInfoArray            If this is non-NULL on entry, then on exit, this
+                                  will point to an allocated buffer    containing
+                                  row information and RowInfoArraySize will be
+                                  updated to contain the        number of elements.
+                                  This array describes the characters which were at
+                                  least partially drawn and the heights of the
+                                  rows. It is the caller¡¯s responsibility to free
+                                  this buffer.
+  @param  RowInfoArraySize        If this is non-NULL on entry, then on exit it
+                                  contains the number of elements in RowInfoArray.
+  @param  ColumnInfoArray         If this is non-NULL, then on return it will be
+                                  filled with the horizontal offset for each
+                                  character in the string on the row where it is
+                                  displayed. Non-printing characters will     have
+                                  the offset ~0. The caller is responsible to
+                                  allocate a buffer large enough so that    there
+                                  is one entry for each character in the string,
+                                  not including the null-terminator. It is possible
+                                  when character display is normalized that some
+                                  character cells overlap.
+
+  @retval EFI_SUCCESS             The string was successfully rendered.
+  @retval EFI_OUT_OF_RESOURCES    Unable to allocate an output buffer for
+                                  RowInfoArray or Blt.
+  @retval EFI_INVALID_PARAMETER   The String was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiStringToImage (
+  IN  CONST EFI_HII_FONT_PROTOCOL    *This,
+  IN  EFI_HII_OUT_FLAGS              Flags,
+  IN  CONST EFI_STRING               String,
+  IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfo       OPTIONAL,
+  IN  OUT EFI_IMAGE_OUTPUT           **Blt,
+  IN  UINTN                          BltX,
+  IN  UINTN                          BltY,
+  OUT EFI_HII_ROW_INFO               **RowInfoArray    OPTIONAL,
+  OUT UINTN                          *RowInfoArraySize OPTIONAL,
+  OUT UINTN                          *ColumnInfoArray  OPTIONAL
+  )
+;
+
+
+/**
+  Render a string to a bitmap or the screen containing the contents of the specified string.
+
+  @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.
+  @param  Flags                   Describes how the string is to be drawn.
+  @param  PackageList             The package list in the HII database to search
+                                  for the specified string.
+  @param  StringId                The string¡¯s id, which is unique within
+                                  PackageList.
+  @param  Language                Points to the language for the retrieved string.
+                                  If NULL, then the current system language is
+                                  used.
+  @param  StringInfo              Points to the string output information,
+                                  including the color and font.  If NULL, then the
+                                  string will be output in the default system font
+                                  and color.
+  @param  Blt                     If this points to a non-NULL on entry, this
+                                  points to the image, which is Width pixels   wide
+                                  and Height pixels high. The string will be drawn
+                                  onto this image and
+                                  EFI_HII_OUT_FLAG_CLIP is implied. If this points
+                                  to a NULL on entry, then a              buffer
+                                  will be allocated to hold the generated image and
+                                  the pointer updated on exit. It is the caller¡¯s
+                                  responsibility to free this buffer.
+  @param  BltX,BLTY               Specifies the offset from the left and top edge
+                                  of the image of the first character cell in the
+                                  image.
+  @param  RowInfoArray            If this is non-NULL on entry, then on exit, this
+                                  will point to an allocated buffer    containing
+                                  row information and RowInfoArraySize will be
+                                  updated to contain the        number of elements.
+                                  This array describes the characters which were at
+                                  least partially drawn and the heights of the
+                                  rows. It is the caller¡¯s responsibility to free
+                                  this buffer.
+  @param  RowInfoArraySize        If this is non-NULL on entry, then on exit it
+                                  contains the number of elements in RowInfoArray.
+  @param  ColumnInfoArray         If this is non-NULL, then on return it will be
+                                  filled with the horizontal offset for each
+                                  character in the string on the row where it is
+                                  displayed. Non-printing characters will     have
+                                  the offset ~0. The caller is responsible to
+                                  allocate a buffer large enough so that    there
+                                  is one entry for each character in the string,
+                                  not including the null-terminator. It is possible
+                                  when character display is normalized that some
+                                  character cells overlap.
+
+  @retval EFI_SUCCESS             The string was successfully rendered.
+  @retval EFI_OUT_OF_RESOURCES    Unable to allocate an output buffer for
+                                  RowInfoArray or Blt.
+  @retval EFI_INVALID_PARAMETER   The String was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiStringIdToImage (
+  IN  CONST EFI_HII_FONT_PROTOCOL    *This,
+  IN  EFI_HII_OUT_FLAGS              Flags,
+  IN  EFI_HII_HANDLE                 PackageList,
+  IN  EFI_STRING_ID                  StringId,
+  IN  CONST CHAR8*                   Language,
+  IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfo       OPTIONAL,
+  IN  OUT EFI_IMAGE_OUTPUT           **Blt,
+  IN  UINTN                          BltX,
+  IN  UINTN                          BltY,
+  OUT EFI_HII_ROW_INFO               **RowInfoArray    OPTIONAL,
+  OUT UINTN                          *RowInfoArraySize OPTIONAL,
+  OUT UINTN                          *ColumnInfoArray  OPTIONAL
+  )
+;
+
+
+/**
+  Convert the glyph for a single character into a bitmap.
+
+  @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.
+  @param  Char                    Character to retrieve.
+  @param  StringInfo              Points to the string font and color information
+                                  or NULL if the string should use the default
+                                  system font and color.
+  @param  Blt                     Thus must point to a NULL on entry. A buffer will
+                                  be allocated to hold the output and the pointer
+                                  updated on exit. It is the caller¡¯s
+                                  responsibility to free this buffer.
+  @param  Baseline                Number of pixels from the bottom of the bitmap to
+                                  the baseline.
+
+  @retval EFI_SUCCESS             Glyph bitmap created.
+  @retval EFI_OUT_OF_RESOURCES    Unable to allocate the output buffer Blt.
+  @retval EFI_WARN_UNKNOWN_GLYPH  The glyph was unknown and was replaced with the
+                                  glyph for Unicode character 0xFFFD.
+  @retval EFI_INVALID_PARAMETER   Blt is NULL or *Blt is not NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetGlyph (
+  IN  CONST EFI_HII_FONT_PROTOCOL    *This,
+  IN  CHAR16                         Char,
+  IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfo,
+  OUT EFI_IMAGE_OUTPUT               **Blt,
+  OUT UINTN                          *Baseline OPTIONAL
+  )
+;
+
+
+/**
+  This function iterates through fonts which match the specified font, using
+  the specified criteria. If String is non-NULL, then all of the characters in
+  the string must exist in order for a candidate font to be returned.
+
+  @param  This                    A pointer to the EFI_HII_FONT_PROTOCOL instance.
+  @param  FontHandle              On entry, points to the font handle returned by a
+                                   previous call to GetFontInfo() or NULL to start
+                                  with the  first font. On return, points to the
+                                  returned font handle or points to NULL if there
+                                  are no more matching fonts.
+  @param  StringInfoIn            Upon entry, points to the font to return
+                                  information about.
+  @param  StringInfoOut           Upon return, contains the matching font¡¯s
+                                  information.  If NULL, then no information is
+                                  returned. It's caller's responsibility to free
+                                  this buffer.
+  @param  String                  Points to the string which will be tested to
+                                  determine  if all characters are available. If
+                                  NULL, then any font  is acceptable.
+
+  @retval EFI_SUCCESS             Matching font returned successfully.
+  @retval EFI_NOT_FOUND           No matching font was found.
+  @retval EFI_INVALID_PARAMETER   StringInfoIn is NULL.
+  @retval EFI_OUT_OF_RESOURCES    There were insufficient resources to complete the
+                                  request.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetFontInfo (
+  IN  CONST EFI_HII_FONT_PROTOCOL    *This,
+  IN  OUT   EFI_FONT_HANDLE          *FontHandle,
+  IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfoIn,
+  OUT       EFI_FONT_DISPLAY_INFO    **StringInfoOut,
+  IN  CONST EFI_STRING               String OPTIONAL
+  )
+;
+
+//
+// EFI_HII_IMAGE_PROTOCOL interfaces
+//
+
+
+/**
+  This function adds the image Image to the group of images owned by PackageList, and returns
+  a new image identifier (ImageId).
+
+  @param  This                    A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+  @param  PackageList             Handle of the package list where this image will
+                                  be added.
+  @param  ImageId                 On return, contains the new image id, which is
+                                  unique within PackageList.
+  @param  Image                   Points to the image.
+
+  @retval EFI_SUCCESS             The new image was added successfully.
+  @retval EFI_NOT_FOUND           The specified PackageList could not be found in
+                                  database.
+  @retval EFI_OUT_OF_RESOURCES    Could not add the image due to lack of resources.
+  @retval EFI_INVALID_PARAMETER   Image is NULL or ImageId is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiNewImage (
+  IN  CONST EFI_HII_IMAGE_PROTOCOL   *This,
+  IN  EFI_HII_HANDLE                 PackageList,
+  OUT EFI_IMAGE_ID                   *ImageId,
+  IN  CONST EFI_IMAGE_INPUT          *Image
+  )
+;
+
+
+/**
+  This function retrieves the image specified by ImageId which is associated with
+  the specified PackageList and copies it into the buffer specified by Image.
+
+  @param  This                    A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+  @param  PackageList             Handle of the package list where this image will
+                                  be searched.
+  @param  ImageId                 The image¡¯s id,, which is unique within
+                                  PackageList.
+  @param  Image                   Points to the image.
+  @param  ImageSize               On entry, points to the size of the buffer
+                                  pointed to by Image, in bytes. On return, points
+                                  to the length of the image, in bytes.
+
+  @retval EFI_SUCCESS             The new image was returned successfully.
+  @retval EFI_NOT_FOUND           The image specified by ImageId is not available.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer specified by ImageSize is too small to
+                                  hold the image.
+  @retval EFI_INVALID_PARAMETER   The Image or ImageSize was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetImage (
+  IN  CONST EFI_HII_IMAGE_PROTOCOL   *This,
+  IN  EFI_HII_HANDLE                 PackageList,
+  IN  EFI_IMAGE_ID                   ImageId,
+  OUT EFI_IMAGE_INPUT                *Image,
+  OUT UINTN                          *ImageSize
+  )
+;
+
+
+/**
+  This function updates the image specified by ImageId in the specified PackageListHandle to
+  the image specified by Image.
+
+  @param  This                    A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+  @param  PackageList             The package list containing the images.
+  @param  ImageId                 The image¡¯s id,, which is unique within
+                                  PackageList.
+  @param  Image                   Points to the image.
+
+  @retval EFI_SUCCESS             The new image was updated successfully.
+  @retval EFI_NOT_FOUND           The image specified by ImageId is not in the
+                                  database.
+  @retval EFI_INVALID_PARAMETER   The Image was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiSetImage (
+  IN CONST EFI_HII_IMAGE_PROTOCOL    *This,
+  IN EFI_HII_HANDLE                  PackageList,
+  IN EFI_IMAGE_ID                    ImageId,
+  IN CONST EFI_IMAGE_INPUT           *Image
+  )
+;
+
+
+/**
+  This function renders an image to a bitmap or the screen using the specified
+  color and options. It draws the image on an existing bitmap, allocates a new
+  bitmap or uses the screen. The images can be clipped.
+
+  @param  This                    A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+  @param  Flags                   Describes how the image is to be drawn.
+  @param  Image                   Points to the image to be displayed.
+  @param  Blt                     If this points to a non-NULL on entry, this
+                                  points to the image, which is Width pixels wide
+                                  and Height pixels high.  The image will be drawn
+                                  onto this image and  EFI_HII_DRAW_FLAG_CLIP is
+                                  implied. If this points to a  NULL on entry, then
+                                  a buffer will be allocated to hold  the generated
+                                  image and the pointer updated on exit. It is the
+                                  caller¡¯s responsibility to free this buffer.
+  @param  BltY                    Specifies the offset from the left and top edge
+                                  of the  output image of the first pixel in the
+                                  image.
+
+  @retval EFI_SUCCESS             The image was successfully drawn.
+  @retval EFI_OUT_OF_RESOURCES    Unable to allocate an output buffer for Blt.
+  @retval EFI_INVALID_PARAMETER   The Image or Blt was NULL.
+  @retval EFI_INVALID_PARAMETER   Any combination of Flags is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiDrawImage (
+  IN CONST EFI_HII_IMAGE_PROTOCOL    *This,
+  IN EFI_HII_DRAW_FLAGS              Flags,
+  IN CONST EFI_IMAGE_INPUT           *Image,
+  IN OUT EFI_IMAGE_OUTPUT            **Blt,
+  IN UINTN                           BltX,
+  IN UINTN                           BltY
+  )
+;
+
+
+/**
+  This function renders an image to a bitmap or the screen using the specified
+  color and options. It draws the image on an existing bitmap, allocates a new
+  bitmap or uses the screen. The images can be clipped.
+
+  @param  This                    A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+  @param  Flags                   Describes how the image is to be drawn.
+  @param  PackageList             The package list in the HII database to search
+                                  for the  specified image.
+  @param  ImageId                 The image's id, which is unique within
+                                  PackageList.
+  @param  Blt                     If this points to a non-NULL on entry, this
+                                  points to the image, which is Width pixels wide
+                                  and Height pixels high. The image will be drawn
+                                  onto this image and
+                                  EFI_HII_DRAW_FLAG_CLIP is implied. If this points
+                                  to a  NULL on entry, then a buffer will be
+                                  allocated to hold  the generated image and the
+                                  pointer updated on exit. It is the caller¡¯s
+                                  responsibility to free this buffer.
+  @param  BltY                    Specifies the offset from the left and top edge
+                                  of the  output image of the first pixel in the
+                                  image.
+
+  @retval EFI_SUCCESS             The image was successfully drawn.
+  @retval EFI_OUT_OF_RESOURCES    Unable to allocate an output buffer for Blt.
+  @retval EFI_INVALID_PARAMETER   The Image was NULL.
+  @retval EFI_NOT_FOUND           The specified packagelist could not be found in
+                                  current database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiDrawImageId (
+  IN CONST EFI_HII_IMAGE_PROTOCOL    *This,
+  IN EFI_HII_DRAW_FLAGS              Flags,
+  IN EFI_HII_HANDLE                  PackageList,
+  IN EFI_IMAGE_ID                    ImageId,
+  IN OUT EFI_IMAGE_OUTPUT            **Blt,
+  IN UINTN                           BltX,
+  IN UINTN                           BltY
+  )
+
+;
+
+//
+// EFI_HII_STRING_PROTOCOL
+//
+
+
+/**
+  This function adds the string String to the group of strings owned by PackageList, with the
+  specified font information StringFontInfo and returns a new string id.
+
+  @param  This                    A pointer to the EFI_HII_STRING_PROTOCOL
+                                  instance.
+  @param  PackageList             Handle of the package list where this string will
+                                  be added.
+  @param  StringId                On return, contains the new strings id, which is
+                                  unique within PackageList.
+  @param  Language                Points to the language for the new string.
+  @param  LanguageName            Points to the printable language name to
+                                  associate with the passed in  Language field.If
+                                  LanguageName is not NULL and the string package
+                                  header's LanguageName  associated with a given
+                                  Language is not zero, the LanguageName being
+                                  passed  in will be ignored.
+  @param  String                  Points to the new null-terminated string.
+  @param  StringFontInfo          Points to the new string¡¯s font information or
+                                  NULL if the string should have the default system
+                                  font, size and style.
+
+  @retval EFI_SUCCESS             The new string was added successfully.
+  @retval EFI_NOT_FOUND           The specified PackageList could not be found in
+                                  database.
+  @retval EFI_OUT_OF_RESOURCES    Could not add the string due to lack of
+                                  resources.
+  @retval EFI_INVALID_PARAMETER   String is NULL or StringId is NULL or Language is
+                                  NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiNewString (
+  IN  CONST EFI_HII_STRING_PROTOCOL   *This,
+  IN  EFI_HII_HANDLE                  PackageList,
+  OUT EFI_STRING_ID                   *StringId,
+  IN  CONST CHAR8                     *Language,
+  IN  CONST CHAR16                    *LanguageName, OPTIONAL
+  IN  CONST EFI_STRING                String,
+  IN  CONST EFI_FONT_INFO             *StringFontInfo OPTIONAL
+  )
+;
+
+
+/**
+  This function retrieves the string specified by StringId which is associated
+  with the specified PackageList in the language Language and copies it into
+  the buffer specified by String.
+
+  @param  This                    A pointer to the EFI_HII_STRING_PROTOCOL
+                                  instance.
+  @param  Language                Points to the language for the retrieved string.
+  @param  PackageList             The package list in the HII database to search
+                                  for the  specified string.
+  @param  StringId                The string's id, which is unique within
+                                  PackageList.
+  @param  String                  Points to the new null-terminated string.
+  @param  StringSize              On entry, points to the size of the buffer
+                                  pointed to by  String, in bytes. On return,
+                                  points to the length of the string, in bytes.
+  @param  StringFontInfo          If not NULL, points to the string¡¯s font
+                                  information.  It's caller's responsibility to
+                                  free this buffer.
+
+  @retval EFI_SUCCESS             The string was returned successfully.
+  @retval EFI_NOT_FOUND           The string specified by StringId is not
+                                  available.
+  @retval EFI_NOT_FOUND           The string specified by StringId is available but
+                                  not in the specified language.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer specified by StringSize is too small
+                                  to  hold the string.
+  @retval EFI_INVALID_PARAMETER   The String or Language or StringSize was NULL.
+  @retval EFI_OUT_OF_RESOURCES    There were insufficient resources to complete the
+                                   request.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetString (
+  IN  CONST EFI_HII_STRING_PROTOCOL   *This,
+  IN  CONST CHAR8                     *Language,
+  IN  EFI_HII_HANDLE                  PackageList,
+  IN  EFI_STRING_ID                   StringId,
+  OUT EFI_STRING                      String,
+  IN  OUT UINTN                       *StringSize,
+  OUT EFI_FONT_INFO                   **StringFontInfo OPTIONAL
+  )
+;
+
+
+/**
+  This function updates the string specified by StringId in the specified PackageList to the text
+  specified by String and, optionally, the font information specified by StringFontInfo.
+
+  @param  This                    A pointer to the EFI_HII_STRING_PROTOCOL
+                                  instance.
+  @param  PackageList             The package list containing the strings.
+  @param  StringId                The string¡¯s id, which is unique within
+                                  PackageList.
+  @param  Language                Points to the language for the updated string.
+  @param  String                  Points to the new null-terminated string.
+  @param  StringFontInfo          Points to the string¡¯s font information or NULL
+                                  if the string font information is not changed.
+
+  @retval EFI_SUCCESS             The string was updated successfully.
+  @retval EFI_NOT_FOUND           The string specified by StringId is not in the
+                                  database.
+  @retval EFI_INVALID_PARAMETER   The String or Language was NULL.
+  @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the
+                                  task.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiSetString (
+  IN CONST EFI_HII_STRING_PROTOCOL    *This,
+  IN EFI_HII_HANDLE                   PackageList,
+  IN EFI_STRING_ID                    StringId,
+  IN CONST CHAR8                      *Language,
+  IN CONST EFI_STRING                 String,
+  IN CONST EFI_FONT_INFO              *StringFontInfo OPTIONAL
+  )
+;
+
+
+/**
+  This function returns the list of supported languages, in the format specified
+  in Appendix M of UEFI 2.1 spec.
+
+  @param  This                    A pointer to the EFI_HII_STRING_PROTOCOL
+                                  instance.
+  @param  PackageList             The package list to examine.
+  @param  Languages               Points to the buffer to hold the returned string.
+  @param  LanguagesSize           On entry, points to the size of the buffer
+                                  pointed to by  Languages, in bytes. On  return,
+                                  points to the length of Languages, in bytes.
+
+  @retval EFI_SUCCESS             The languages were returned successfully.
+  @retval EFI_INVALID_PARAMETER   The Languages or LanguagesSize was NULL.
+  @retval EFI_BUFFER_TOO_SMALL    The LanguagesSize is too small to hold the list
+                                  of  supported languages. LanguageSize is updated
+                                  to contain the required size.
+  @retval EFI_NOT_FOUND           Could not find string package in specified
+                                  packagelist.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetLanguages (
+  IN CONST EFI_HII_STRING_PROTOCOL    *This,
+  IN EFI_HII_HANDLE                   PackageList,
+  IN OUT CHAR8                        *Languages,
+  IN OUT UINTN                        *LanguagesSize
+  )
+;
+
+
+/**
+  Each string package has associated with it a single primary language and zero
+  or more secondary languages. This routine returns the secondary languages
+  associated with a package list.
+
+  @param  This                    A pointer to the EFI_HII_STRING_PROTOCOL
+                                  instance.
+  @param  PackageList             The package list to examine.
+  @param  FirstLanguage           Points to the primary language.
+  @param  SecondaryLanguages      Points to the buffer to hold the returned list of
+                                   secondary languages for the specified
+                                  FirstLanguage. If there are no secondary
+                                  languages, the function  returns successfully,
+                                  but this is set to NULL.
+  @param  SecondaryLanguageSize   On entry, points to the size of the buffer
+                                  pointed to  by SecondLanguages, in bytes. On
+                                  return, points to the length of SecondLanguages
+                                  in bytes.
+
+  @retval EFI_SUCCESS             Secondary languages were correctly returned.
+  @retval EFI_INVALID_PARAMETER   FirstLanguage or SecondLanguages or
+                                  SecondLanguagesSize was NULL.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer specified by SecondLanguagesSize is
+                                  too small to hold the returned information.
+                                  SecondLanguageSize is updated to hold the size of
+                                  the buffer required.
+  @retval EFI_NOT_FOUND           The language specified by FirstLanguage is not
+                                  present in the specified package list.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetSecondaryLanguages (
+  IN CONST EFI_HII_STRING_PROTOCOL   *This,
+  IN EFI_HII_HANDLE                  PackageList,
+  IN CONST CHAR8                     *FirstLanguage,
+  IN OUT CHAR8                       *SecondLanguages,
+  IN OUT UINTN                       *SecondLanguagesSize
+  )
+;
+
+//
+// EFI_HII_DATABASE_PROTOCOL protocol interfaces
+//
+
+
+/**
+  This function adds the packages in the package list to the database and returns a handle. If there is a
+  EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then this function will
+  create a package of type EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list.
+
+  @param  This                    A pointer to the EFI_HII_DATABASE_PROTOCOL
+                                  instance.
+  @param  PackageList             A pointer to an EFI_HII_PACKAGE_LIST_HEADER
+                                  structure.
+  @param  DriverHandle            Associate the package list with this EFI handle.
+  @param  Handle                  A pointer to the EFI_HII_HANDLE instance.
+
+  @retval EFI_SUCCESS             The package list associated with the Handle was
+                                  added to the HII database.
+  @retval EFI_OUT_OF_RESOURCES    Unable to allocate necessary resources for the
+                                  new database contents.
+  @retval EFI_INVALID_PARAMETER   PackageList is NULL or Handle is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiNewPackageList (
+  IN CONST EFI_HII_DATABASE_PROTOCOL    *This,
+  IN CONST EFI_HII_PACKAGE_LIST_HEADER  *PackageList,
+  IN CONST EFI_HANDLE                   DriverHandle,
+  OUT EFI_HII_HANDLE                    *Handle
+  )
+;
+
+
+/**
+  This function removes the package list that is associated with a handle Handle
+  from the HII database. Before removing the package, any registered functions
+  with the notification type REMOVE_PACK and the same package type will be called.
+
+  @param  This                    A pointer to the EFI_HII_DATABASE_PROTOCOL
+                                  instance.
+  @param  Handle                  The handle that was registered to the data that
+                                  is requested  for removal.
+
+  @retval EFI_SUCCESS             The data associated with the Handle was removed
+                                  from  the HII database.
+  @retval EFI_NOT_FOUND           The specified PackageList could not be found in
+                                  database.
+  @retval EFI_INVALID_PARAMETER   The Handle was not valid.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiRemovePackageList (
+  IN CONST EFI_HII_DATABASE_PROTOCOL    *This,
+  IN EFI_HII_HANDLE                     Handle
+  )
+;
+
+
+/**
+  This function updates the existing package list (which has the specified Handle)
+  in the HII databases, using the new package list specified by PackageList.
+
+  @param  This                    A pointer to the EFI_HII_DATABASE_PROTOCOL
+                                  instance.
+  @param  Handle                  The handle that was registered to the data that
+                                  is  requested to be updated.
+  @param  PackageList             A pointer to an EFI_HII_PACKAGE_LIST_HEADER
+                                  package.
+
+  @retval EFI_SUCCESS             The HII database was successfully updated.
+  @retval EFI_OUT_OF_RESOURCES    Unable to allocate enough memory for the updated
+                                  database.
+  @retval EFI_INVALID_PARAMETER   Handle or PackageList was NULL.
+  @retval EFI_NOT_FOUND           The Handle was not valid or could not be found in
+                                  database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiUpdatePackageList (
+  IN CONST EFI_HII_DATABASE_PROTOCOL    *This,
+  IN EFI_HII_HANDLE                     Handle,
+  IN CONST EFI_HII_PACKAGE_LIST_HEADER  *PackageList
+  )
+;
+
+
+/**
+  This function returns a list of the package handles of the specified type
+  that are currently active in the database. The pseudo-type
+  EFI_HII_PACKAGE_TYPE_ALL will cause all package handles to be listed.
+
+  @param  This                    A pointer to the EFI_HII_DATABASE_PROTOCOL
+                                  instance.
+  @param  PackageType             Specifies the package type of the packages to
+                                  list or EFI_HII_PACKAGE_TYPE_ALL for all packages
+                                  to be listed.
+  @param  PackageGuid             If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then
+                                  this  is the pointer to the GUID which must match
+                                  the Guid field of EFI_HII_GUID_PACKAGE_GUID_HDR.
+                                  Otherwise,  it must be NULL.
+  @param  HandleBufferLength      On input, a pointer to the length of the handle
+                                  buffer.  On output, the length of the handle
+                                  buffer that is required for the handles found.
+  @param  Handle                  An array of EFI_HII_HANDLE instances returned.
+
+  @retval EFI_SUCCESS             The matching handles are outputed successfully.
+  @retval EFI_BUFFER_TO_SMALL     The HandleBufferLength parameter indicates that
+                                  Handle is too small to support the number of
+                                  handles. HandleBufferLength is updated with a
+                                  value that will  enable the data to fit.
+  @retval EFI_NOT_FOUND           No matching handle could not be found in
+                                  database.
+  @retval EFI_INVALID_PARAMETER   Handle or HandleBufferLength was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiListPackageLists (
+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,
+  IN  UINT8                             PackageType,
+  IN  CONST EFI_GUID                    *PackageGuid,
+  IN  OUT UINTN                         *HandleBufferLength,
+  OUT EFI_HII_HANDLE                    *Handle
+  )
+;
+
+
+/**
+  This function will export one or all package lists in the database to a buffer.
+  For each package list exported, this function will call functions registered
+  with EXPORT_PACK and then copy the package list to the buffer.
+
+  @param  This                    A pointer to the EFI_HII_DATABASE_PROTOCOL
+                                  instance.
+  @param  Handle                  An EFI_HII_HANDLE that corresponds to the desired
+                                  package list in the HII database to export or
+                                  NULL to indicate  all package lists should be
+                                  exported.
+  @param  BufferSize              On input, a pointer to the length of the buffer.
+                                  On output, the length of the buffer that is
+                                  required for the exported data.
+  @param  Buffer                  A pointer to a buffer that will contain the
+                                  results of  the export function.
+
+  @retval EFI_SUCCESS             Package exported.
+  @retval EFI_BUFFER_TO_SMALL     The HandleBufferLength parameter indicates that
+                                  Handle is too small to support the number of
+                                  handles.      HandleBufferLength is updated with
+                                  a value that will enable the data to fit.
+  @retval EFI_NOT_FOUND           The specifiecd Handle could not be found in the
+                                  current database.
+  @retval EFI_INVALID_PARAMETER   Handle or Buffer or BufferSize was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiExportPackageLists (
+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,
+  IN  EFI_HII_HANDLE                    Handle,
+  IN  OUT UINTN                         *BufferSize,
+  OUT EFI_HII_PACKAGE_LIST_HEADER       *Buffer
+  )
+;
+
+
+/**
+  This function registers a function which will be called when specified actions related to packages of
+  the specified type occur in the HII database. By registering a function, other HII-related drivers are
+  notified when specific package types are added, removed or updated in the HII database.
+  Each driver or application which registers a notification should use
+  EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify() before exiting.
+
+  @param  This                    A pointer to the EFI_HII_DATABASE_PROTOCOL
+                                  instance.
+  @param  PackageType             Specifies the package type of the packages to
+                                  list or EFI_HII_PACKAGE_TYPE_ALL for all packages
+                                  to be listed.
+  @param  PackageGuid             If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then
+                                  this is the pointer to the GUID which must match
+                                  the Guid field of
+                                  EFI_HII_GUID_PACKAGE_GUID_HDR. Otherwise, it must
+                                  be NULL.
+  @param  PackageNotifyFn         Points to the function to be called when the
+                                  event specified by
+                                  NotificationType occurs.
+  @param  NotifyType              Describes the types of notification which this
+                                  function will be receiving.
+  @param  NotifyHandle            Points to the unique handle assigned to the
+                                  registered notification. Can be used in
+                                  EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify()
+                                  to stop notifications.
+
+  @retval EFI_SUCCESS             Notification registered successfully.
+  @retval EFI_OUT_OF_RESOURCES    Unable to allocate necessary data structures
+  @retval EFI_INVALID_PARAMETER   NotifyHandle is NULL.
+  @retval EFI_INVALID_PARAMETER   PackageGuid is not NULL when PackageType is not
+                                  EFI_HII_PACKAGE_TYPE_GUID.
+  @retval EFI_INVALID_PARAMETER   PackageGuid is NULL when PackageType is
+                                  EFI_HII_PACKAGE_TYPE_GUID.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiRegisterPackageNotify (
+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,
+  IN  UINT8                             PackageType,
+  IN  CONST EFI_GUID                    *PackageGuid,
+  IN  CONST EFI_HII_DATABASE_NOTIFY     PackageNotifyFn,
+  IN  EFI_HII_DATABASE_NOTIFY_TYPE      NotifyType,
+  OUT EFI_HANDLE                        *NotifyHandle
+  )
+;
+
+
+/**
+  Removes the specified HII database package-related notification.
+
+  @param  This                    A pointer to the EFI_HII_DATABASE_PROTOCOL
+                                  instance.
+  @param  NotifyHandle            The handle of the notification function being
+                                  unregistered.
+
+  @retval EFI_SUCCESS             Notification is unregistered successfully.
+  @retval EFI_INVALID_PARAMETER   The Handle is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiUnregisterPackageNotify (
+  IN CONST EFI_HII_DATABASE_PROTOCOL    *This,
+  IN EFI_HANDLE                         NotificationHandle
+  )
+;
+
+
+/**
+  This routine retrieves an array of GUID values for each keyboard layout that
+  was previously registered in the system.
+
+  @param  This                    A pointer to the EFI_HII_DATABASE_PROTOCOL
+                                  instance.
+  @param  KeyGuidBufferLength     On input, a pointer to the length of the keyboard
+                                  GUID  buffer. On output, the length of the handle
+                                  buffer  that is required for the handles found.
+  @param  KeyGuidBuffer           An array of keyboard layout GUID instances
+                                  returned.
+
+  @retval EFI_SUCCESS             KeyGuidBuffer was updated successfully.
+  @retval EFI_BUFFER_TOO_SMALL    The KeyGuidBufferLength parameter indicates
+                                  that KeyGuidBuffer is too small to support the
+                                  number of GUIDs. KeyGuidBufferLength is
+                                  updated with a value that will enable the data to
+                                  fit.
+  @retval EFI_INVALID_PARAMETER   The KeyGuidBuffer or KeyGuidBufferLength was
+                                  NULL.
+  @retval EFI_NOT_FOUND           There was no keyboard layout.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiFindKeyboardLayouts (
+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,
+  IN  OUT UINT16                        *KeyGuidBufferLength,
+  OUT EFI_GUID                          *KeyGuidBuffer
+  )
+;
+
+
+/**
+  This routine retrieves the requested keyboard layout. The layout is a physical description of the keys
+  on a keyboard and the character(s) that are associated with a particular set of key strokes.
+
+  @param  This                    A pointer to the EFI_HII_DATABASE_PROTOCOL
+                                  instance.
+  @param  KeyGuid                 A pointer to the unique ID associated with a
+                                  given keyboard layout. If KeyGuid is NULL then
+                                  the current layout will be retrieved.
+  @param  KeyboardLayoutLength    On input, a pointer to the length of the
+                                  KeyboardLayout buffer.  On output, the length of
+                                  the data placed into KeyboardLayout.
+  @param  KeyboardLayout          A pointer to a buffer containing the retrieved
+                                  keyboard layout.
+
+  @retval EFI_SUCCESS             The keyboard layout was retrieved successfully.
+  @retval EFI_NOT_FOUND           The requested keyboard layout was not found.
+  @retval EFI_INVALID_PARAMETER   The KeyboardLayout or KeyboardLayoutLength was
+                                  NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetKeyboardLayout (
+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,
+  IN  CONST EFI_GUID                          *KeyGuid,
+  IN OUT UINT16                         *KeyboardLayoutLength,
+  OUT EFI_HII_KEYBOARD_LAYOUT           *KeyboardLayout
+  )
+;
+
+
+/**
+  This routine sets the default keyboard layout to the one referenced by KeyGuid. When this routine
+  is called, an event will be signaled of the EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
+  group type. This is so that agents which are sensitive to the current keyboard layout being changed
+  can be notified of this change.
+
+  @param  This                    A pointer to the EFI_HII_DATABASE_PROTOCOL
+                                  instance.
+  @param  KeyGuid                 A pointer to the unique ID associated with a
+                                  given keyboard layout.
+
+  @retval EFI_SUCCESS             The current keyboard layout was successfully set.
+  @retval EFI_NOT_FOUND           The referenced keyboard layout was not found, so
+                                  action was taken.
+  @retval EFI_INVALID_PARAMETER   The KeyGuid was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiSetKeyboardLayout (
+  IN CONST EFI_HII_DATABASE_PROTOCOL          *This,
+  IN CONST EFI_GUID                           *KeyGuid
+  )
+;
+
+
+/**
+  Return the EFI handle associated with a package list.
+
+  @param  This                    A pointer to the EFI_HII_DATABASE_PROTOCOL
+                                  instance.
+  @param  PackageListHandle       An EFI_HII_HANDLE that corresponds to the desired
+                                  package list in the HIIdatabase.
+  @param  DriverHandle            On return, contains the EFI_HANDLE which was
+                                  registered with the package list in
+                                  NewPackageList().
+
+  @retval EFI_SUCCESS             The DriverHandle was returned successfully.
+  @retval EFI_INVALID_PARAMETER   The PackageListHandle was not valid or
+                                  DriverHandle was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetPackageListHandle (
+  IN  CONST EFI_HII_DATABASE_PROTOCOL         *This,
+  IN  EFI_HII_HANDLE                    PackageListHandle,
+  OUT EFI_HANDLE                        *DriverHandle
+  )
+;
+
+//
+// EFI_HII_CONFIG_ROUTING_PROTOCOL interfaces
+//
+
+
+/**
+  This function allows a caller to extract the current configuration
+  for one or more named elements from one or more drivers.
+
+  @param  This                    A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+                                  instance.
+  @param  Request                 A null-terminated Unicode string in
+                                  <MultiConfigRequest> 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                 Null-terminated Unicode string in
+                                  <MultiConfigAltResp> 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 string is filled with the values
+                                  corresponding to all requested names.
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the parts of the
+                                  results that must be stored awaiting possible
+                                  future        protocols.
+  @retval EFI_NOT_FOUND           Routing data doesn¡¯t match any known driver.
+                                     Progress set to the Â¡Â°G¡± in Â¡Â°GUID¡± of the
+                                  routing  header that doesn¡¯t match. Note: There
+                                  is no         requirement that all routing data
+                                  be validated before any configuration extraction.
+  @retval EFI_INVALID_PARAMETER   For example, passing in a NULL for the Request
+                                  parameter would result in this type of error. The
+                                  Progress parameter is set to NULL.
+  @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set to most recent &
+                                  before the error or the beginning of the string.
+  @retval EFI_INVALID_PARAMETER   Unknown name. Progress points to the & before the
+                                  name in question.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiConfigRoutingExtractConfig (
+  IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
+  IN  CONST EFI_STRING                       Request,
+  OUT EFI_STRING                             *Progress,
+  OUT EFI_STRING                             *Results
+  )
+;
+
+
+/**
+  This function allows the caller to request the current configuration for the
+  entirety of the current HII database and returns the data in a null-terminated Unicode string.
+
+  @param  This                    A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+                                  instance.
+  @param  Results                 Null-terminated Unicode string in
+                                  <MultiConfigAltResp> format which has all values
+                                  filled in for the names in the Request string.
+                                  String to be allocated by the  called function.
+                                  De-allocation is up to the caller.
+
+  @retval EFI_SUCCESS             The Results string is filled with the values
+                                  corresponding to all requested names.
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the parts of the
+                                  results that must be stored awaiting possible
+                                  future        protocols.
+  @retval EFI_INVALID_PARAMETER   For example, passing in a NULL for the Results
+                                  parameter would result in this type of error.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiConfigRoutingExportConfig (
+  IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
+  OUT EFI_STRING                             *Results
+  )
+;
+
+
+/**
+  This function processes the results of processing forms and routes it to the
+  appropriate handlers or storage.
+
+  @param  This                    A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+                                  instance.
+  @param  Configuration           A null-terminated Unicode string in
+                                  <MulltiConfigResp> 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 have been distributed or are awaiting
+                                  distribution.
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the parts of the
+                                  results that must be stored awaiting possible
+                                  future        protocols.
+  @retval EFI_INVALID_PARAMETER   Passing in a NULL for the Configuration parameter
+                                  would result in this type of error.
+  @retval EFI_NOT_FOUND           Target for the specified routing data was not
+                                  found.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiConfigRoutingRoutConfig (
+  IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
+  IN  CONST EFI_STRING                       Configuration,
+  OUT EFI_STRING                             *Progress
+  )
+;
+
+
+
+/**
+  This helper function is to be called by drivers to map configuration data stored
+  in byte array (¡°block¡±) formats such as UEFI Variables into current configuration strings.
+
+  @param  This                    A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+                                  instance.
+  @param  ConfigRequest           A null-terminated Unicode string in
+                                  <ConfigRequest> format.
+  @param  Block                   Array of bytes defining the block's
+                                  configuration.
+  @param  BlockSize               Length in bytes of Block.
+  @param  Config                  Filled-in configuration string. String allocated
+                                  by  the function. Returned only if call is
+                                  successful.
+  @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 request succeeded. Progress points to the
+                                  null terminator at the end of the ConfigRequest
+                                        string.
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to allocate Config.
+                                  Progress points to the first character of
+                                  ConfigRequest.
+  @retval EFI_INVALID_PARAMETER   Passing in a NULL for the ConfigRequest or
+                                  Block parameter would result in this type of
+                                  error. Progress points to the first character of
+                                  ConfigRequest.
+  @retval EFI_NOT_FOUND           Target for the specified routing data was not
+                                  found. Progress points to the Â¡Â°G¡± in Â¡Â°GUID¡± of
+                                  the      errant routing data.
+  @retval EFI_DEVICE_ERROR        Block not large enough. Progress undefined.
+  @retval EFI_INVALID_PARAMETER   Encountered non <BlockName> formatted string.
+                                       Block is left updated and Progress points at
+                                  the Â¡Â®&¡¯ preceding the first non-<BlockName>.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiBlockToConfig (
+  IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
+  IN  CONST EFI_STRING                       ConfigRequest,
+  IN  CONST UINT8                            *Block,
+  IN  CONST UINTN                            BlockSize,
+  OUT EFI_STRING                             *Config,
+  OUT EFI_STRING                             *Progress
+  )
+;
+
+
+/**
+  This helper function is to be called by drivers to map configuration strings
+  to configurations stored in byte array (¡°block¡±) formats such as UEFI Variables.
+
+  @param  This                    A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+                                  instance.
+  @param  ConfigResp              A null-terminated Unicode string in <ConfigResp>
+                                  format.
+  @param  Block                   A possibly null array of bytes representing the
+                                  current  block. Only bytes referenced in the
+                                  ConfigResp string  in the block are modified. If
+                                  this parameter is null or if the *BlockSize
+                                  parameter is (on input) shorter than required by
+                                  the Configuration string, only the BlockSize
+                                  parameter is updated and an appropriate status
+                                  (see below)  is returned.
+  @param  BlockSize               The length of the Block in units of UINT8.  On
+                                  input, this is the size of the Block. On output,
+                                  if successful, contains the index of the  last
+                                  modified byte in the Block.
+  @param  Progress                On return, points to an element of the ConfigResp
+                                   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 request succeeded. Progress points to the
+                                  null terminator at the end of the ConfigResp
+                                  string.
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to allocate Config.
+                                  Progress points to the first character of
+                                  ConfigResp.
+  @retval EFI_INVALID_PARAMETER   Passing in a NULL for the ConfigResp or
+                                  Block parameter would result in this type of
+                                  error. Progress points to the first character of
+                                           ConfigResp.
+  @retval EFI_NOT_FOUND           Target for the specified routing data was not
+                                  found. Progress points to the Â¡Â°G¡± in Â¡Â°GUID¡± of
+                                  the      errant routing data.
+  @retval EFI_INVALID_PARAMETER   Encountered non <BlockName> formatted name /
+                                  value pair. Block is left updated and
+                                  Progress points at the Â¡Â®&¡¯ preceding the first
+                                  non-<BlockName>.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiConfigToBlock (
+  IN     CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+  IN     CONST EFI_STRING                      ConfigResp,
+  IN OUT UINT8                                 *Block,
+  IN OUT UINTN                                 *BlockSize,
+  OUT    EFI_STRING                            *Progress
+  )
+;
+
+
+/**
+  This helper function is to be called by drivers to extract portions of
+  a larger configuration string.
+
+  @param  This                    A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+                                  instance.
+  @param  Configuration           A null-terminated Unicode string in
+                                  <MultiConfigAltResp> format.
+  @param  Guid                    A pointer to the GUID value to search for in the
+                                  routing portion of the ConfigResp string when
+                                  retrieving  the requested data. If Guid is NULL,
+                                  then all GUID  values will be searched for.
+  @param  Name                    A pointer to the NAME value to search for in the
+                                  routing portion of the ConfigResp string when
+                                  retrieving  the requested data. If Name is NULL,
+                                  then all Name  values will be searched for.
+  @param  DevicePath              A pointer to the PATH value to search for in the
+                                  routing portion of the ConfigResp string when
+                                  retrieving  the requested data. If DevicePath is
+                                  NULL, then all  DevicePath values will be
+                                  searched for.
+  @param  AltCfgId                A pointer to the ALTCFG value to search for in
+                                  the  routing portion of the ConfigResp string
+                                  when retrieving  the requested data.  If this
+                                  parameter is NULL,  then the current setting will
+                                  be retrieved.
+  @param  AltCfgResp              A pointer to a buffer which will be allocated by
+                                  the  function which contains the retrieved string
+                                  as requested.   This buffer is only allocated if
+                                  the call was successful.
+
+  @retval EFI_SUCCESS             The request succeeded. The requested data was
+                                  extracted  and placed in the newly allocated
+                                  AltCfgResp buffer.
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to allocate AltCfgResp.
+  @retval EFI_INVALID_PARAMETER   Any parameter is invalid.
+  @retval EFI_NOT_FOUND           Target for the specified routing data was not
+                                  found.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetAltCfg (
+  IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL    *This,
+  IN  CONST EFI_STRING                         Configuration,
+  IN  CONST EFI_GUID                           *Guid,
+  IN  CONST EFI_STRING                         Name,
+  IN  CONST EFI_DEVICE_PATH_PROTOCOL           *DevicePath,
+  IN  CONST UINT16                             *AltCfgId,
+  OUT EFI_STRING                               *AltCfgResp
+  )
+;
+
+
+//
+// Global variables
+//
+extern EFI_EVENT gHiiKeyboardLayoutChanged;
+
+#include "R8Lib.h"
+
+#endif
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.msa b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.msa
new file mode 100644 (file)
index 0000000..2b3cf9b
--- /dev/null
@@ -0,0 +1,79 @@
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+  <MsaHeader>\r
+    <ModuleName>HiiDatabase</ModuleName>\r
+    <ModuleType>DXE_DRIVER</ModuleType>\r
+    <GuidValue>348C4D62-BFBD-4882-9ECE-C80BB1C4783B</GuidValue>\r
+    <Version>1.0</Version>\r
+    <Abstract>Component name for module HiiDatabase</Abstract>\r
+    <Description>FIX ME!</Description>\r
+    <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>\r
+    <License>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.</License>\r
+    <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION   0x00000052</Specification>\r
+  </MsaHeader>\r
+  <ModuleDefinitions>\r
+    <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+    <BinaryModule>false</BinaryModule>\r
+    <OutputFileBasename>HiiDatabase</OutputFileBasename>\r
+  </ModuleDefinitions>\r
+  <LibraryClassDefinitions>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DebugLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseMemoryLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiDriverEntryPoint</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiBootServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DevicePathLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>MemoryAllocationLib</Keyword>\r
+    </LibraryClass>\r
+  </LibraryClassDefinitions>\r
+  <SourceFiles>\r
+    <Filename>R8Lib.c</Filename>\r
+    <Filename>R8Lib.h</Filename>\r
+    <Filename>Font.c</Filename>\r
+    <Filename>Database.c</Filename>\r
+    <Filename>String.c</Filename>\r
+    <Filename>ConfigRouting.c</Filename>\r
+    <Filename>HiiDatabase.dxs</Filename>\r
+    <Filename>HiiDatabase.h</Filename>\r
+    <Filename>Image.c</Filename>\r
+    <Filename>HiiDatabaseEntry.c</Filename>\r
+    <Filename>CVS\TortoiseCVS.Status</Filename>\r
+  </SourceFiles>\r
+  <PackageDependencies>\r
+    <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+    <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+  </PackageDependencies>\r
+  <Protocols>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiConsoleControlProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+  </Protocols>\r
+  <Externs>\r
+    <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+    <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+    <Extern>\r
+      <ModuleEntryPoint>InitializeHiiDatabase</ModuleEntryPoint>\r
+    </Extern>\r
+  </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
new file mode 100644 (file)
index 0000000..2bafb25
--- /dev/null
@@ -0,0 +1,75 @@
+#/** @file\r
+# Component name for module HiiDatabase\r
+#\r
+# FIX ME!\r
+# Copyright (c) 2007, Intel Corporation. All rights reserved.\r
+#\r
+#  All rights reserved. This program and the accompanying materials       \r
+#  are licensed and made available under the terms and conditions of the BSD License   \r
+#  which accompanies this distribution. The full text of the license may be found at  \r
+#  http://opensource.org/licenses/bsd-license.php           \r
+#  \r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,      \r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = HiiDatabase\r
+  FILE_GUID                      = 348C4D62-BFBD-4882-9ECE-C80BB1C4783B\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x0002000A\r
+\r
+  ENTRY_POINT                    = InitializeHiiDatabase\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+  HiiDatabaseEntry.c\r
+  Image.c\r
+  HiiDatabase.h\r
+  ConfigRouting.c\r
+  String.c\r
+  Database.c\r
+  Font.c\r
+  R8Lib.h\r
+  R8Lib.c\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+  MemoryAllocationLib\r
+  DevicePathLib\r
+  BaseLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+  BaseMemoryLib\r
+  DebugLib\r
+\r
+\r
+[Protocols]\r
+  gEfiConsoleControlProtocolGuid                \r
+  gEfiDevicePathProtocolGuid                    \r
+  gEfiHiiStringProtocolGuid\r
+  gEfiHiiImageProtocolGuid\r
+  gEfiHiiConfigRoutingProtocolGuid\r
+  gEfiHiiDatabaseProtocolGuid\r
+  gEfiHiiFontProtocolGuid\r
+  gEfiHiiConfigAccessProtocolGuid\r
+\r
+\r
+[Depex]\r
+  TRUE\r
+\r
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c
new file mode 100644 (file)
index 0000000..99084db
--- /dev/null
@@ -0,0 +1,197 @@
+/** @file\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+    HiiDatabaseEntry.c\r
+\r
+Abstract:\r
+\r
+    This file contains the entry code to the HII database, which is defined by\r
+    UEFI 2.1 specification.\r
+\r
+Revision History\r
+\r
+\r
+**/\r
+\r
+\r
+#include "HiiDatabase.h"\r
+\r
+//\r
+// Global variables\r
+//\r
+EFI_EVENT gHiiKeyboardLayoutChanged;\r
+STATIC EFI_GUID gHiiSetKbdLayoutEventGuid = EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID;\r
+\r
+STATIC HII_DATABASE_PRIVATE_DATA mPrivate = {\r
+  HII_DATABASE_PRIVATE_DATA_SIGNATURE,\r
+  {\r
+    (LIST_ENTRY *) NULL,\r
+    (LIST_ENTRY *) NULL\r
+  },\r
+  {\r
+    (LIST_ENTRY *) NULL,\r
+    (LIST_ENTRY *) NULL\r
+  },\r
+  {\r
+    HiiStringToImage,\r
+    HiiStringIdToImage,\r
+    HiiGetGlyph,\r
+    HiiGetFontInfo\r
+  },\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+  {\r
+    HiiNewImage,\r
+    HiiGetImage,\r
+    HiiSetImage,\r
+    HiiDrawImage,\r
+    HiiDrawImageId\r
+  },\r
+#endif\r
+  {\r
+    HiiNewString,\r
+    HiiGetString,\r
+    HiiSetString,\r
+    HiiGetLanguages,\r
+    HiiGetSecondaryLanguages\r
+  },\r
+  {\r
+    HiiNewPackageList,\r
+    HiiRemovePackageList,\r
+    HiiUpdatePackageList,\r
+    HiiListPackageLists,\r
+    HiiExportPackageLists,\r
+    HiiRegisterPackageNotify,\r
+    HiiUnregisterPackageNotify,\r
+    HiiFindKeyboardLayouts,\r
+    HiiGetKeyboardLayout,\r
+    HiiSetKeyboardLayout,\r
+    HiiGetPackageListHandle\r
+  },\r
+  {\r
+    HiiConfigRoutingExtractConfig,\r
+    HiiConfigRoutingExportConfig,\r
+    HiiConfigRoutingRoutConfig,\r
+    HiiBlockToConfig,\r
+    HiiConfigToBlock,\r
+    HiiGetAltCfg\r
+  },\r
+  {\r
+    (LIST_ENTRY *) NULL,\r
+    (LIST_ENTRY *) NULL\r
+  },\r
+  0,\r
+  {\r
+    (LIST_ENTRY *) NULL,\r
+    (LIST_ENTRY *) NULL\r
+  },\r
+  EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK),\r
+  {\r
+    0x00000000,\r
+    0x0000,\r
+    0x0000,\r
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\r
+  },\r
+  NULL\r
+};\r
+\r
+//@MT: EFI_DRIVER_ENTRY_POINT (InitializeHiiDatabase)\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeHiiDatabase (\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Initialize HII Database\r
+\r
+Arguments:\r
+  (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
+\r
+Returns:\r
+  EFI_SUCCESS -\r
+  other       -\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                             Status;\r
+  EFI_HANDLE                             Handle;\r
+  EFI_HANDLE                             *HandleBuffer;\r
+  UINTN                                  HandleCount;\r
+\r
+  //@MT: EfiInitializeDriverLib (ImageHandle, SystemTable);\r
+\r
+  //\r
+  // There will be only one HII Database in the system\r
+  // If there is another out there, someone is trying to install us\r
+  // again.  Fail that scenario.\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiHiiDatabaseProtocolGuid,\r
+                  NULL,\r
+                  &HandleCount,\r
+                  &HandleBuffer\r
+                  );\r
+\r
+  //\r
+  // If there was no error, assume there is an installation and fail to load\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+    if (HandleBuffer != NULL) {\r
+      gBS->FreePool (HandleBuffer);\r
+    }\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  InitializeListHead (&mPrivate.DatabaseList);\r
+  InitializeListHead (&mPrivate.DatabaseNotifyList);\r
+  InitializeListHead (&mPrivate.HiiHandleList);\r
+  InitializeListHead (&mPrivate.FontInfoList);\r
+\r
+  //\r
+  // Create a event with EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group type.\r
+  //\r
+  Status = gBS->CreateEventEx (\r
+                  0,\r
+                  0,\r
+                  NULL,\r
+                  NULL,\r
+                  &gHiiSetKbdLayoutEventGuid,\r
+                  &gHiiKeyboardLayoutChanged\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Handle = NULL;\r
+  return gBS->InstallMultipleProtocolInterfaces (\r
+                &Handle,\r
+                &gEfiHiiFontProtocolGuid,\r
+                &mPrivate.HiiFont,\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+                &gEfiHiiImageProtocolGuid,\r
+                &mPrivate.HiiImage,\r
+#endif\r
+                &gEfiHiiStringProtocolGuid,\r
+                &mPrivate.HiiString,\r
+                &gEfiHiiDatabaseProtocolGuid,\r
+                &mPrivate.HiiDatabase,\r
+                &gEfiHiiConfigRoutingProtocolGuid,\r
+                &mPrivate.ConfigRouting,\r
+                NULL\r
+                );\r
+}\r
+\r
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
new file mode 100644 (file)
index 0000000..06d783a
--- /dev/null
@@ -0,0 +1,1509 @@
+/** @file\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+    Image.c\r
+\r
+Abstract:\r
+\r
+    Implementation for EFI_HII_IMAGE_PROTOCOL.\r
+\r
+Revision History\r
+\r
+\r
+**/\r
+\r
+\r
+#include "HiiDatabase.h"\r
+\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+\r
+STATIC\r
+UINT8*\r
+GetImageIdOrAddress (\r
+  IN  UINT8           *ImageBlock,\r
+  IN OUT EFI_IMAGE_ID *ImageId\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input\r
+    ImageId is zero, otherwise return the address of the\r
+    corresponding image block with identifier specified by ImageId.\r
+\r
+  Arguments:\r
+    ImageBlock     - Points to the beginning of a series of image blocks stored in order.\r
+    ImageId        - If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK;\r
+                     else use this id to find its corresponding image block address.\r
+\r
+  Returns:\r
+    The image block address when input ImageId is not zero; otherwise return NULL.\r
+\r
+--*/\r
+{\r
+  EFI_IMAGE_ID                   ImageIdCurrent;\r
+  UINT8                          *ImageBlockHdr;\r
+  UINT8                          Length8;\r
+  UINT16                         Length16;\r
+  UINT32                         Length32;\r
+  EFI_HII_IIBT_IMAGE_1BIT_BLOCK  Iibt1bit;\r
+  EFI_HII_IIBT_IMAGE_4BIT_BLOCK  Iibt4bit;\r
+  EFI_HII_IIBT_IMAGE_8BIT_BLOCK  Iibt8bit;\r
+  UINT16                         Width;\r
+  UINT16                         Height;\r
+\r
+  ASSERT (ImageBlock != NULL && ImageId != NULL);\r
+\r
+  ImageBlockHdr  = ImageBlock;\r
+  ImageIdCurrent = 1;\r
+\r
+  while (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType != EFI_HII_IIBT_END) {\r
+    if (*ImageId > 0) {\r
+      if (*ImageId == ImageIdCurrent) {\r
+        //\r
+        // If the found image block is a duplicate block, update the ImageId to\r
+        // find the previous defined image block.\r
+        //\r
+        if (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType == EFI_HII_IIBT_DUPLICATE) {\r
+          CopyMem (ImageId, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (EFI_IMAGE_ID));\r
+          ASSERT (*ImageId != ImageIdCurrent);\r
+          ImageBlock = ImageBlockHdr;\r
+          ImageIdCurrent = 1;\r
+          continue;\r
+        }\r
+\r
+        return ImageBlock;\r
+      }\r
+      if (*ImageId < ImageIdCurrent) {\r
+        //\r
+        // Can not find the specified image block in this image.\r
+        //\r
+        return NULL;\r
+      }\r
+    }\r
+    switch (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType) {\r
+    case EFI_HII_IIBT_EXT1:\r
+      Length8 = *(ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8));\r
+      ImageBlock += Length8;\r
+      ImageIdCurrent++;\r
+      break;\r
+    case EFI_HII_IIBT_EXT2:\r
+      CopyMem (\r
+        &Length16,\r
+        ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8),\r
+        sizeof (UINT16)\r
+        );\r
+      ImageBlock += Length16;\r
+      ImageIdCurrent++;\r
+      break;\r
+    case EFI_HII_IIBT_EXT4:\r
+      CopyMem (\r
+        &Length32,\r
+        ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8),\r
+        sizeof (UINT32)\r
+        );\r
+      ImageBlock += Length32;\r
+      ImageIdCurrent++;\r
+      break;\r
+\r
+    case EFI_HII_IIBT_IMAGE_1BIT:\r
+    case EFI_HII_IIBT_IMAGE_1BIT_TRANS:\r
+      CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));\r
+      ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +\r
+                    BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height);\r
+      ImageIdCurrent++;\r
+      break;\r
+\r
+    case EFI_HII_IIBT_IMAGE_4BIT:\r
+    case EFI_HII_IIBT_IMAGE_4BIT_TRANS:\r
+      CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK));\r
+      ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +\r
+                    BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height);\r
+      ImageIdCurrent++;\r
+      break;\r
+\r
+    case EFI_HII_IIBT_IMAGE_8BIT:\r
+    case EFI_HII_IIBT_IMAGE_8BIT_TRANS:\r
+      CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK));\r
+      ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +\r
+                    BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height);\r
+      ImageIdCurrent++;\r
+      break;\r
+\r
+    case EFI_HII_IIBT_IMAGE_24BIT:\r
+    case EFI_HII_IIBT_IMAGE_24BIT_TRANS:\r
+      CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));\r
+      CopyMem (\r
+        &Height,\r
+        ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),\r
+        sizeof (UINT16)\r
+        );\r
+      ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +\r
+                    BITMAP_LEN_24_BIT (Width, Height);\r
+      ImageIdCurrent++;\r
+      break;\r
+\r
+    case EFI_HII_IIBT_DUPLICATE:\r
+      ImageBlock += sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK);\r
+      ImageIdCurrent++;\r
+      break;\r
+\r
+    case EFI_HII_IIBT_IMAGE_JPEG:\r
+      CopyMem (&Length32, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT32));\r
+      ImageBlock += Length32;\r
+      ImageIdCurrent++;\r
+      break;\r
+\r
+    case EFI_HII_IIBT_SKIP1:\r
+      Length8 = *(ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK));\r
+      ImageBlock += sizeof (EFI_HII_IIBT_SKIP1_BLOCK);\r
+      ImageIdCurrent = (UINT16) (ImageIdCurrent + Length8);\r
+      break;\r
+\r
+    case EFI_HII_IIBT_SKIP2:\r
+      CopyMem (&Length16, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));\r
+      ImageBlock += sizeof (EFI_HII_IIBT_SKIP2_BLOCK);\r
+      ImageIdCurrent = (UINT16) (ImageIdCurrent + Length16);\r
+      break;\r
+\r
+    default:\r
+      //\r
+      // Unknown image blocks can not be skipped, processing halts.\r
+      //\r
+      ASSERT (FALSE);\r
+    }\r
+  }\r
+\r
+  //\r
+  // When ImageId is zero, return the imageid of last image block: EFI_HII_IIBT_END_BLOCK.\r
+  //\r
+  if (*ImageId == 0) {\r
+    *ImageId = ImageIdCurrent;\r
+    return ImageBlock;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Convert pixels from EFI_GRAPHICS_OUTPUT_BLT_PIXEL to EFI_HII_RGB_PIXEL style.\r
+\r
+  @param  BitMapOut              Pixels in EFI_HII_RGB_PIXEL format.\r
+  @param  BitMapIn               Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.\r
+  @param  PixelNum               The number of pixels to be converted.\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+CopyGopToRgbPixel (\r
+  OUT EFI_HII_RGB_PIXEL              *BitMapOut,\r
+  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *BitMapIn,\r
+  IN  UINTN                          PixelNum\r
+  )\r
+{\r
+  UINTN Index;\r
+\r
+  ASSERT (BitMapOut != NULL && BitMapIn != NULL);\r
+\r
+  for (Index = 0; Index < PixelNum; Index++) {\r
+    CopyMem (BitMapOut + Index, BitMapIn + Index, sizeof (EFI_HII_RGB_PIXEL));\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Convert pixels from EFI_HII_RGB_PIXEL to EFI_GRAPHICS_OUTPUT_BLT_PIXEL style.\r
+\r
+  @param  BitMapOut              Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.\r
+  @param  BitMapIn               Pixels in EFI_HII_RGB_PIXEL format.\r
+  @param  PixelNum               The number of pixels to be converted.\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+CopyRgbToGopPixel (\r
+  OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *BitMapOut,\r
+  IN  EFI_HII_RGB_PIXEL              *BitMapIn,\r
+  IN  UINTN                          PixelNum\r
+  )\r
+{\r
+  UINTN Index;\r
+\r
+  ASSERT (BitMapOut != NULL && BitMapIn != NULL);\r
+\r
+  for (Index = 0; Index < PixelNum; Index++) {\r
+    CopyMem (BitMapOut + Index, BitMapIn + Index, sizeof (EFI_HII_RGB_PIXEL));\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Output pixels in "1 bit per pixel" format to an image.\r
+\r
+  @param  Image                  Points to the image which will store the pixels.\r
+  @param  Data                   Stores the value of output pixels, 0 or 1.\r
+  @param  PaletteInfo            PaletteInfo which stores the color of the output\r
+                                 pixels. First entry corresponds to color 0 and\r
+                                 second one to color 1.\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+Output1bitPixel (\r
+  IN OUT EFI_IMAGE_INPUT             *Image,\r
+  IN UINT8                           *Data,\r
+  IN EFI_HII_IMAGE_PALETTE_INFO      *PaletteInfo\r
+  )\r
+{\r
+  UINT16                             X;\r
+  UINT16                             Y;\r
+  UINTN                              OffsetY;\r
+  UINT8                              Index;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BitMapPtr;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      PaletteValue[2];\r
+  EFI_HII_IMAGE_PALETTE_INFO         *Palette;\r
+  UINT16                             PaletteSize;\r
+  UINT8                              Byte;\r
+\r
+  ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);\r
+\r
+  BitMapPtr = Image->Bitmap;\r
+\r
+  //\r
+  // First entry corresponds to color 0 and second entry corresponds to color 1.\r
+  //\r
+  CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));\r
+  PaletteSize += sizeof (UINT16);\r
+  Palette = AllocateZeroPool (PaletteSize);\r
+  ASSERT (Palette != NULL);\r
+  CopyMem (Palette, PaletteInfo, PaletteSize);\r
+\r
+  ZeroMem (PaletteValue, sizeof (PaletteValue));\r
+  CopyRgbToGopPixel (&PaletteValue[0], &Palette->PaletteValue[0], 1);\r
+  CopyRgbToGopPixel (&PaletteValue[1], &Palette->PaletteValue[1], 1);\r
+  SafeFreePool (Palette);\r
+\r
+  //\r
+  // Convert the pixel from one bit to corresponding color.\r
+  //\r
+  for (Y = 0; Y < Image->Height; Y++) {\r
+    OffsetY = BITMAP_LEN_1_BIT (Image->Width, Y);\r
+    //\r
+    // All bits in these bytes are meaningful\r
+    //\r
+    for (X = 0; X < Image->Width / 8; X++) {\r
+      Byte = *(Data + OffsetY + X);\r
+      for (Index = 0; Index < 8; Index++) {\r
+        if ((Byte & (1 << Index)) != 0) {\r
+          BitMapPtr[Y * Image->Width + X * 8 + (8 - Index - 1)] = PaletteValue[1];\r
+        } else {\r
+          BitMapPtr[Y * Image->Width + X * 8 + (8 - Index - 1)] = PaletteValue[0];\r
+        }\r
+      }\r
+    }\r
+\r
+    if (Image->Width % 8 != 0) {\r
+      //\r
+      // Padding bits in this byte should be ignored.\r
+      //\r
+      Byte = *(Data + OffsetY + X);\r
+      for (Index = 0; Index < Image->Width % 8; Index++) {\r
+        if ((Byte & (1 << (8 - Index - 1))) != 0) {\r
+          BitMapPtr[Y * Image->Width + X * 8 + Index] = PaletteValue[1];\r
+        } else {\r
+          BitMapPtr[Y * Image->Width + X * 8 + Index] = PaletteValue[0];\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Output pixels in "4 bit per pixel" format to an image.\r
+\r
+  @param  Image                  Points to the image which will store the pixels.\r
+  @param  Data                   Stores the value of output pixels, 0 ~ 15.\r
+  @param  PaletteInfo            PaletteInfo which stores the color of the output\r
+                                 pixels. Each entry corresponds to a color within\r
+                                 [0, 15].\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+Output4bitPixel (\r
+  IN OUT EFI_IMAGE_INPUT             *Image,\r
+  IN UINT8                           *Data,\r
+  IN EFI_HII_IMAGE_PALETTE_INFO      *PaletteInfo\r
+  )\r
+{\r
+  UINT16                             X;\r
+  UINT16                             Y;\r
+  UINTN                              OffsetY;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BitMapPtr;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      PaletteValue[16];\r
+  EFI_HII_IMAGE_PALETTE_INFO         *Palette;\r
+  UINT16                             PaletteSize;\r
+  UINT16                             PaletteNum;\r
+  UINT8                              Byte;\r
+\r
+  ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);\r
+\r
+  BitMapPtr = Image->Bitmap;\r
+\r
+  //\r
+  // The bitmap should allocate each color index starting from 0.\r
+  //\r
+  CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));\r
+  PaletteSize += sizeof (UINT16);\r
+  Palette = AllocateZeroPool (PaletteSize);\r
+  ASSERT (Palette != NULL);\r
+  CopyMem (Palette, PaletteInfo, PaletteSize);\r
+  PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));\r
+\r
+  ZeroMem (PaletteValue, sizeof (PaletteValue));\r
+  CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, PaletteNum);\r
+  SafeFreePool (Palette);\r
+\r
+  //\r
+  // Convert the pixel from 4 bit to corresponding color.\r
+  //\r
+  for (Y = 0; Y < Image->Height; Y++) {\r
+    OffsetY = BITMAP_LEN_4_BIT (Image->Width, Y);\r
+    //\r
+    // All bits in these bytes are meaningful\r
+    //\r
+    for (X = 0; X < Image->Width / 2; X++) {\r
+      Byte = *(Data + OffsetY + X);\r
+      BitMapPtr[Y * Image->Width + X * 2]     = PaletteValue[Byte >> 4];\r
+      BitMapPtr[Y * Image->Width + X * 2 + 1] = PaletteValue[Byte & 0x0F];\r
+    }\r
+\r
+    if (Image->Width % 2 != 0) {\r
+      //\r
+      // Padding bits in this byte should be ignored.\r
+      //\r
+      Byte = *(Data + OffsetY + X);\r
+      BitMapPtr[Y * Image->Width + X * 2]     = PaletteValue[Byte >> 4];\r
+    }\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Output pixels in "8 bit per pixel" format to an image.\r
+\r
+  @param  Image                  Points to the image which will store the pixels.\r
+  @param  Data                   Stores the value of output pixels, 0 ~ 255.\r
+  @param  PaletteInfo            PaletteInfo which stores the color of the output\r
+                                 pixels. Each entry corresponds to a color within\r
+                                 [0, 255].\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+Output8bitPixel (\r
+  IN OUT EFI_IMAGE_INPUT             *Image,\r
+  IN UINT8                           *Data,\r
+  IN EFI_HII_IMAGE_PALETTE_INFO      *PaletteInfo\r
+  )\r
+{\r
+  UINT16                             X;\r
+  UINT16                             Y;\r
+  UINTN                              OffsetY;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BitMapPtr;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      PaletteValue[256];\r
+  EFI_HII_IMAGE_PALETTE_INFO         *Palette;\r
+  UINT16                             PaletteSize;\r
+  UINT16                             PaletteNum;\r
+  UINT8                              Byte;\r
+\r
+  ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);\r
+\r
+  BitMapPtr = Image->Bitmap;\r
+\r
+  //\r
+  // The bitmap should allocate each color index starting from 0.\r
+  //\r
+  CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));\r
+  PaletteSize += sizeof (UINT16);\r
+  Palette = AllocateZeroPool (PaletteSize);\r
+  ASSERT (Palette != NULL);\r
+  CopyMem (Palette, PaletteInfo, PaletteSize);\r
+  PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));\r
+  ZeroMem (PaletteValue, sizeof (PaletteValue));\r
+  CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, PaletteNum);\r
+  SafeFreePool (Palette);\r
+\r
+  //\r
+  // Convert the pixel from 8 bits to corresponding color.\r
+  //\r
+  for (Y = 0; Y < Image->Height; Y++) {\r
+    OffsetY = BITMAP_LEN_8_BIT (Image->Width, Y);\r
+    //\r
+    // All bits are meaningful since the bitmap is 8 bits per pixel.\r
+    //\r
+    for (X = 0; X < Image->Width; X++) {\r
+      Byte = *(Data + OffsetY + X);\r
+      BitMapPtr[OffsetY + X] = PaletteValue[Byte];\r
+    }\r
+  }\r
+\r
+}\r
+\r
+\r
+/**\r
+  Output pixels in "24 bit per pixel" format to an image.\r
+\r
+  @param  Image                  Points to the image which will store the pixels.\r
+  @param  Data                   Stores the color of output pixels, allowing 16.8\r
+                                 millions colors.\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+Output24bitPixel (\r
+  IN OUT EFI_IMAGE_INPUT             *Image,\r
+  IN EFI_HII_RGB_PIXEL               *Data\r
+  )\r
+{\r
+  UINT16                             Y;\r
+  UINTN                              OffsetY;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BitMapPtr;\r
+\r
+  ASSERT (Image != NULL && Data != NULL);\r
+\r
+  BitMapPtr = Image->Bitmap;\r
+\r
+  for (Y = 0; Y < Image->Height; Y++) {\r
+    OffsetY = BITMAP_LEN_8_BIT (Image->Width, Y);\r
+    CopyRgbToGopPixel (&BitMapPtr[OffsetY], &Data[OffsetY], Image->Width);\r
+  }\r
+\r
+}\r
+\r
+\r
+/**\r
+  Convert the image from EFI_IMAGE_INPUT to EFI_IMAGE_OUTPUT format.\r
+\r
+  @param  BltBuffer              Buffer points to bitmap data of incoming image.\r
+  @param  BltY                   Specifies the offset from the left and top edge of\r
+                                  the output image of the first pixel in the image.\r
+  @param  Width                  Width of the incoming image, in pixels.\r
+  @param  Height                 Height of the incoming image, in pixels.\r
+  @param  Transparent            If TRUE, all "off" pixels in the image will be\r
+                                 drawn using the pixel value from blt and all other\r
+                                 pixels will be copied.\r
+  @param  Blt                    Buffer points to bitmap data of output image.\r
+\r
+  @retval EFI_SUCCESS            The image was successfully converted.\r
+  @retval EFI_INVALID_PARAMETER  Any incoming parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ImageToBlt (\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,\r
+  IN UINTN                           BltX,\r
+  IN UINTN                           BltY,\r
+  IN UINTN                           Width,\r
+  IN UINTN                           Height,\r
+  IN BOOLEAN                         Transparent,\r
+  IN OUT EFI_IMAGE_OUTPUT            **Blt\r
+  )\r
+{\r
+  EFI_IMAGE_OUTPUT                   *ImageOut;\r
+  UINTN                              X;\r
+  UINTN                              Y;\r
+  UINTN                              OffsetY1; // src buffer\r
+  UINTN                              OffsetY2; // dest buffer\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      SrcPixel;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      ZeroPixel;\r
+\r
+  if (BltBuffer == NULL || Blt == NULL || *Blt == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ImageOut = *Blt;\r
+\r
+  if (Width + BltX > ImageOut->Width) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (Height + BltY > ImageOut->Height) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ZeroMem (&ZeroPixel, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+\r
+  for (Y = 0; Y < Height; Y++) {\r
+    OffsetY1 = Width * Y;\r
+    OffsetY2 = ImageOut->Width * (BltY + Y);\r
+    for (X = 0; X < Width; X++) {\r
+      SrcPixel = BltBuffer[OffsetY1 + X];\r
+      if (Transparent) {\r
+        if (CompareMem (&SrcPixel, &ZeroPixel, 3) != 0) {\r
+          ImageOut->Image.Bitmap[OffsetY2 + BltX + X] = SrcPixel;\r
+        }\r
+      } else {\r
+        ImageOut->Image.Bitmap[OffsetY2 + BltX + X] = SrcPixel;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function adds the image Image to the group of images owned by PackageList, and returns\r
+  a new image identifier (ImageId).\r
+\r
+  @param  This                   A pointer to the EFI_HII_IMAGE_PROTOCOL instance.\r
+  @param  PackageList            Handle of the package list where this image will\r
+                                 be added.\r
+  @param  ImageId                On return, contains the new image id, which is\r
+                                 unique within PackageList.\r
+  @param  Image                  Points to the image.\r
+\r
+  @retval EFI_SUCCESS            The new image was added successfully.\r
+  @retval EFI_NOT_FOUND          The specified PackageList could not be found in\r
+                                 database.\r
+  @retval EFI_OUT_OF_RESOURCES   Could not add the image due to lack of resources.\r
+  @retval EFI_INVALID_PARAMETER  Image is NULL or ImageId is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiNewImage (\r
+  IN  CONST EFI_HII_IMAGE_PROTOCOL   *This,\r
+  IN  EFI_HII_HANDLE                 PackageList,\r
+  OUT EFI_IMAGE_ID                   *ImageId,\r
+  IN  CONST EFI_IMAGE_INPUT          *Image\r
+  )\r
+{\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  LIST_ENTRY                          *Link;\r
+  HII_DATABASE_RECORD                 *DatabaseRecord;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
+  HII_IMAGE_PACKAGE_INSTANCE          *ImagePackage;\r
+  UINT8                               *ImageBlock;\r
+  UINTN                               BlockSize;\r
+  UINT8                               *NewBlock;\r
+  UINT8                               *NewBlockPtr;\r
+  UINTN                               NewBlockSize;\r
+  EFI_IMAGE_INPUT                     *ImageIn;\r
+\r
+  if (This == NULL || ImageId == NULL || Image == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!IsHiiHandleValid (PackageList)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // Get the specified package list\r
+  //\r
+\r
+  PackageListNode = NULL;\r
+\r
+  for (Link = Private->DatabaseList.ForwardLink;\r
+       Link != &Private->DatabaseList;\r
+       Link = Link->ForwardLink\r
+      ) {\r
+    DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if (DatabaseRecord->Handle == PackageList) {\r
+      PackageListNode = DatabaseRecord->PackageList;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (PackageListNode == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  ImageIn = (EFI_IMAGE_INPUT *) Image;\r
+\r
+  NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +\r
+                 BITMAP_LEN_24_BIT (ImageIn->Width, ImageIn->Height);\r
+\r
+  //\r
+  // Get the image package in the package list,\r
+  // or create a new image package if image package does not exist.\r
+  //\r
+  if (PackageListNode->ImagePkg != NULL) {\r
+    ImagePackage = PackageListNode->ImagePkg;\r
+\r
+    //\r
+    // Output the image id of the incoming image being inserted, which is the\r
+    // image id of the EFI_HII_IIBT_END block of old image package.\r
+    //\r
+    *ImageId = 0;\r
+    GetImageIdOrAddress (ImagePackage->ImageBlock, ImageId);\r
+\r
+    //\r
+    // Update the package's image block by appending the new block to the end.\r
+    //\r
+    BlockSize  = ImagePackage->ImageBlockSize + NewBlockSize;\r
+    ImageBlock = (UINT8 *) AllocateZeroPool (BlockSize);\r
+    if (ImageBlock == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    //\r
+    // Copy the original content.\r
+    //\r
+    CopyMem (\r
+      ImageBlock,\r
+      ImagePackage->ImageBlock,\r
+      ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)\r
+      );\r
+    SafeFreePool (ImagePackage->ImageBlock);\r
+    ImagePackage->ImageBlock = ImageBlock;\r
+    ImageBlock += ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK);\r
+    //\r
+    // Temp memory to store new block.\r
+    //\r
+    NewBlock = AllocateZeroPool (NewBlockSize);\r
+    if (NewBlock == NULL) {\r
+      SafeFreePool (ImagePackage->ImageBlock);\r
+      ImagePackage->ImageBlock = NULL;\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    NewBlockPtr = NewBlock;\r
+\r
+    //\r
+    // Update the length record.\r
+    //\r
+    ImagePackage->ImageBlockSize = (UINT32) BlockSize;\r
+    ImagePackage->ImagePkgHdr.Header.Length += (UINT32) NewBlockSize;\r
+    PackageListNode->PackageListHdr.PackageLength += (UINT32) NewBlockSize;\r
+\r
+  } else {\r
+    //\r
+    // The specified package list does not contain image package.\r
+    // Create one to add this image block.\r
+    //\r
+    ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));\r
+    if (ImagePackage == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    //\r
+    // Output the image id of the incoming image being inserted, which is the\r
+    // first image block so that id is initially to one.\r
+    //\r
+    *ImageId = 1;\r
+    BlockSize    = sizeof (EFI_HII_IIBT_END_BLOCK) + NewBlockSize;\r
+    //\r
+    // Fill in image package header.\r
+    //\r
+    ImagePackage->ImagePkgHdr.Header.Length     = (UINT32) BlockSize + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);\r
+    ImagePackage->ImagePkgHdr.Header.Type       = EFI_HII_PACKAGE_IMAGES;\r
+    ImagePackage->ImagePkgHdr.ImageInfoOffset   = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);\r
+    ImagePackage->ImagePkgHdr.PaletteInfoOffset = 0;\r
+\r
+    //\r
+    // Fill in palette info.\r
+    //\r
+    ImagePackage->PaletteBlock    = NULL;\r
+    ImagePackage->PaletteInfoSize = 0;\r
+\r
+    //\r
+    // Fill in image blocks.\r
+    //\r
+    ImagePackage->ImageBlockSize = (UINT32) BlockSize;\r
+    ImagePackage->ImageBlock = (UINT8 *) AllocateZeroPool (BlockSize);\r
+    if (ImagePackage->ImageBlock == NULL) {\r
+      SafeFreePool (ImagePackage);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    ImageBlock = ImagePackage->ImageBlock;\r
+\r
+    //\r
+    // Temp memory to store new block.\r
+    //\r
+    NewBlock = AllocateZeroPool (NewBlockSize);\r
+    if (NewBlock == NULL) {\r
+      SafeFreePool (ImagePackage->ImageBlock);\r
+      SafeFreePool (ImagePackage);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    NewBlockPtr = NewBlock;\r
+\r
+    //\r
+    // Insert this image package.\r
+    //\r
+    PackageListNode->ImagePkg = ImagePackage;\r
+    PackageListNode->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;\r
+  }\r
+\r
+  //\r
+  // Append the new block here\r
+  //\r
+  if (ImageIn->Flags == EFI_IMAGE_TRANSPARENT) {\r
+    *NewBlock = EFI_HII_IIBT_IMAGE_24BIT_TRANS;\r
+  } else {\r
+    *NewBlock = EFI_HII_IIBT_IMAGE_24BIT;\r
+  }\r
+  NewBlock++;\r
+  CopyMem (NewBlock, &ImageIn->Width, sizeof (UINT16));\r
+  NewBlock += sizeof (UINT16);\r
+  CopyMem (NewBlock, &ImageIn->Height, sizeof (UINT16));\r
+  NewBlock += sizeof (UINT16);\r
+  CopyGopToRgbPixel ((EFI_HII_RGB_PIXEL *) NewBlock, ImageIn->Bitmap, ImageIn->Width * ImageIn->Height);\r
+\r
+  CopyMem (ImageBlock, NewBlockPtr, NewBlockSize);\r
+  SafeFreePool (NewBlockPtr);\r
+\r
+  //\r
+  // Append the block end\r
+  //\r
+  ImageBlock += NewBlockSize;\r
+  ((EFI_HII_IIBT_END_BLOCK *) (ImageBlock))->Header.BlockType = EFI_HII_IIBT_END;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function retrieves the image specified by ImageId which is associated with\r
+  the specified PackageList and copies it into the buffer specified by Image.\r
+\r
+  @param  This                   A pointer to the EFI_HII_IMAGE_PROTOCOL instance.\r
+  @param  PackageList            Handle of the package list where this image will\r
+                                 be searched.\r
+  @param  ImageId                The image¡¯s id,, which is unique within\r
+                                 PackageList.\r
+  @param  Image                  Points to the image.\r
+  @param  ImageSize              On entry, points to the size of the buffer pointed\r
+                                 to by Image, in bytes.  On return, points to the\r
+                                 length of the image, in bytes.\r
+\r
+  @retval EFI_SUCCESS            The new image was returned successfully.\r
+  @retval EFI_NOT_FOUND          The image specified by ImageId is not available.\r
+  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by ImageSize is too small to\r
+                                 hold the image.\r
+  @retval EFI_INVALID_PARAMETER  The Image or ImageSize was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetImage (\r
+  IN  CONST EFI_HII_IMAGE_PROTOCOL   *This,\r
+  IN  EFI_HII_HANDLE                 PackageList,\r
+  IN  EFI_IMAGE_ID                   ImageId,\r
+  OUT EFI_IMAGE_INPUT                *Image,\r
+  OUT UINTN                          *ImageSize\r
+  )\r
+{\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  LIST_ENTRY                          *Link;\r
+  HII_DATABASE_RECORD                 *DatabaseRecord;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
+  HII_IMAGE_PACKAGE_INSTANCE          *ImagePackage;\r
+  UINT8                               *ImageBlock;\r
+  EFI_IMAGE_ID                        LocalImageId;\r
+  UINT8                               BlockType;\r
+  EFI_HII_IIBT_IMAGE_1BIT_BLOCK       Iibt1bit;\r
+  UINT16                              Width;\r
+  UINT16                              Height;\r
+  UINTN                               ImageLength;\r
+  BOOLEAN                             Flag;\r
+  UINT8                               *PaletteInfo;\r
+  UINT8                               PaletteIndex;\r
+  UINT16                              PaletteSize;\r
+\r
+  if (This == NULL || ImageSize == NULL || Image == NULL || ImageId < 1 || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!IsHiiHandleValid (PackageList)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // Get the specified package list and image package.\r
+  //\r
+  PackageListNode = NULL;\r
+  for (Link = Private->DatabaseList.ForwardLink;\r
+       Link != &Private->DatabaseList;\r
+       Link = Link->ForwardLink\r
+      ) {\r
+    DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if (DatabaseRecord->Handle == PackageList) {\r
+      PackageListNode = DatabaseRecord->PackageList;\r
+      break;\r
+    }\r
+  }\r
+  if (PackageListNode == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  ImagePackage = PackageListNode->ImagePkg;\r
+  if (ImagePackage == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Find the image block specified by ImageId\r
+  //\r
+  LocalImageId = ImageId;\r
+  ImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &LocalImageId);\r
+  if (ImageBlock == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Flag      = FALSE;\r
+  BlockType = *ImageBlock;\r
+\r
+  switch (BlockType) {\r
+  case EFI_HII_IIBT_IMAGE_JPEG:\r
+    //\r
+    // BUGBUG: need to be supported as soon as image tool is designed.\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+    break;\r
+\r
+  case EFI_HII_IIBT_IMAGE_1BIT_TRANS:\r
+  case EFI_HII_IIBT_IMAGE_4BIT_TRANS:\r
+  case EFI_HII_IIBT_IMAGE_8BIT_TRANS:\r
+    Flag = TRUE;\r
+    //\r
+    // fall through\r
+    //\r
+  case EFI_HII_IIBT_IMAGE_1BIT:\r
+  case EFI_HII_IIBT_IMAGE_4BIT:\r
+  case EFI_HII_IIBT_IMAGE_8BIT:\r
+    //\r
+    // Use the common block code since the definition of these structures is the same.\r
+    //\r
+    CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));\r
+    ImageLength = sizeof (EFI_IMAGE_INPUT) + sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) *\r
+                  (Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height - 1);\r
+    if (*ImageSize < ImageLength) {\r
+      *ImageSize = ImageLength;\r
+      return EFI_BUFFER_TOO_SMALL;\r
+    }\r
+    ZeroMem (Image, ImageLength);\r
+\r
+    if (Flag) {\r
+      Image->Flags = EFI_IMAGE_TRANSPARENT;\r
+    }\r
+    Image->Width  = Iibt1bit.Bitmap.Width;\r
+    Image->Height = Iibt1bit.Bitmap.Height;\r
+\r
+    PaletteInfo = ImagePackage->PaletteBlock + sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);\r
+    for (PaletteIndex = 1; PaletteIndex < Iibt1bit.PaletteIndex; PaletteIndex++) {\r
+      CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));\r
+      PaletteInfo += PaletteSize + sizeof (UINT16);\r
+    }\r
+    ASSERT (PaletteIndex == Iibt1bit.PaletteIndex);\r
+\r
+    //\r
+    // Output bitmap data\r
+    //\r
+    if (BlockType == EFI_HII_IIBT_IMAGE_1BIT || BlockType == EFI_HII_IIBT_IMAGE_1BIT_TRANS) {\r
+      Output1bitPixel (\r
+        Image,\r
+        (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8)),\r
+        (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo\r
+        );\r
+    } else if (BlockType == EFI_HII_IIBT_IMAGE_4BIT || BlockType == EFI_HII_IIBT_IMAGE_4BIT_TRANS) {\r
+      Output4bitPixel (\r
+        Image,\r
+        (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8)),\r
+        (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo\r
+        );\r
+    } else {\r
+      Output8bitPixel (\r
+        Image,\r
+        (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8)),\r
+        (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo\r
+        );\r
+    }\r
+\r
+    return EFI_SUCCESS;\r
+    break;\r
+\r
+  case EFI_HII_IIBT_IMAGE_24BIT_TRANS:\r
+    Flag = TRUE;\r
+    //\r
+    // fall through\r
+    //\r
+  case EFI_HII_IIBT_IMAGE_24BIT:\r
+    CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));\r
+    CopyMem (\r
+      &Height,\r
+      ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),\r
+      sizeof (UINT16)\r
+      );\r
+    ImageLength = sizeof (EFI_IMAGE_INPUT) +\r
+                  sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (Width * Height - 1);\r
+    if (*ImageSize < ImageLength) {\r
+      *ImageSize = ImageLength;\r
+      return EFI_BUFFER_TOO_SMALL;\r
+    }\r
+    ZeroMem (Image, ImageLength);\r
+\r
+    if (Flag) {\r
+      Image->Flags = EFI_IMAGE_TRANSPARENT;\r
+    }\r
+    Image->Width  = Width;\r
+    Image->Height = Height;\r
+\r
+    //\r
+    // Output the bimap data directly.\r
+    //\r
+    Output24bitPixel (\r
+      Image,\r
+      (EFI_HII_RGB_PIXEL *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))\r
+      );\r
+    return EFI_SUCCESS;\r
+    break;\r
+\r
+  default:\r
+    return EFI_NOT_FOUND;\r
+    break;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  This function updates the image specified by ImageId in the specified PackageListHandle to\r
+  the image specified by Image.\r
+\r
+  @param  This                   A pointer to the EFI_HII_IMAGE_PROTOCOL instance.\r
+  @param  PackageList            The package list containing the images.\r
+  @param  ImageId                The image¡¯s id,, which is unique within\r
+                                 PackageList.\r
+  @param  Image                  Points to the image.\r
+\r
+  @retval EFI_SUCCESS            The new image was updated successfully.\r
+  @retval EFI_NOT_FOUND          The image specified by ImageId is not in the\r
+                                 database.\r
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiSetImage (\r
+  IN CONST EFI_HII_IMAGE_PROTOCOL    *This,\r
+  IN EFI_HII_HANDLE                  PackageList,\r
+  IN EFI_IMAGE_ID                    ImageId,\r
+  IN CONST EFI_IMAGE_INPUT           *Image\r
+  )\r
+{\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  LIST_ENTRY                          *Link;\r
+  HII_DATABASE_RECORD                 *DatabaseRecord;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
+  HII_IMAGE_PACKAGE_INSTANCE          *ImagePackage;\r
+  UINT8                               *ImageBlock;\r
+  EFI_IMAGE_ID                        LocalImageId;\r
+  UINT8                               BlockType;\r
+  EFI_HII_IIBT_IMAGE_1BIT_BLOCK       Iibt1bit;\r
+  EFI_HII_IIBT_IMAGE_4BIT_BLOCK       Iibt4bit;\r
+  EFI_HII_IIBT_IMAGE_8BIT_BLOCK       Iibt8bit;\r
+  UINT16                              Width;\r
+  UINT16                              Height;\r
+  UINT32                              BlockSize;\r
+  UINT32                              NewBlockSize;\r
+  UINT32                              OldBlockSize;\r
+  EFI_IMAGE_INPUT                     *ImageIn;\r
+  UINT8                               *NewBlock;\r
+  UINT8                               *NewBlockPtr;\r
+  UINT8                               *Block;\r
+  UINT8                               *BlockPtr;\r
+  UINT32                               Part1Size;\r
+  UINT32                               Part2Size;\r
+\r
+  if (This == NULL || Image == NULL || ImageId < 1 || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!IsHiiHandleValid (PackageList)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // Get the specified package list and image package.\r
+  //\r
+  PackageListNode = NULL;\r
+  for (Link = Private->DatabaseList.ForwardLink;\r
+       Link != &Private->DatabaseList;\r
+       Link = Link->ForwardLink\r
+      ) {\r
+    DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if (DatabaseRecord->Handle == PackageList) {\r
+      PackageListNode = DatabaseRecord->PackageList;\r
+      break;\r
+    }\r
+  }\r
+  if (PackageListNode == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  ImagePackage = PackageListNode->ImagePkg;\r
+  if (ImagePackage == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Find the image block specified by ImageId\r
+  //\r
+  LocalImageId = ImageId;\r
+  ImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &LocalImageId);\r
+  if (ImageBlock == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  BlockType = *ImageBlock;\r
+\r
+  //\r
+  // Get the size of original image block. Use some common block code here\r
+  // since the definition of some structures is the same.\r
+  //\r
+  switch (BlockType) {\r
+  case EFI_HII_IIBT_IMAGE_JPEG:\r
+    //\r
+    // BUGBUG: need to be supported as soon as image tool is designed.\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+    break;\r
+\r
+  case EFI_HII_IIBT_IMAGE_1BIT:\r
+  case EFI_HII_IIBT_IMAGE_1BIT_TRANS:\r
+    CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));\r
+    OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +\r
+                   BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height);\r
+    break;\r
+  case EFI_HII_IIBT_IMAGE_4BIT:\r
+  case EFI_HII_IIBT_IMAGE_4BIT_TRANS:\r
+    CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK));\r
+    OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +\r
+                   BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height);\r
+    break;\r
+  case EFI_HII_IIBT_IMAGE_8BIT:\r
+  case EFI_HII_IIBT_IMAGE_8BIT_TRANS:\r
+    CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK));\r
+    OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +\r
+                   BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height);\r
+    break;\r
+  case EFI_HII_IIBT_IMAGE_24BIT:\r
+  case EFI_HII_IIBT_IMAGE_24BIT_TRANS:\r
+    CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));\r
+    CopyMem (\r
+      &Height,\r
+      ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),\r
+      sizeof (UINT16)\r
+      );\r
+    OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +\r
+                   BITMAP_LEN_24_BIT (Width , Height);\r
+    break;\r
+  default:\r
+    return EFI_NOT_FOUND;\r
+    break;\r
+  }\r
+\r
+  //\r
+  // Create the new image block according to input image.\r
+  //\r
+  ImageIn = (EFI_IMAGE_INPUT *) Image;\r
+  NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +\r
+                 BITMAP_LEN_24_BIT (ImageIn->Width, ImageIn->Height);\r
+  NewBlock = (UINT8 *) AllocateZeroPool (NewBlockSize);\r
+  if (NewBlock == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewBlockPtr = NewBlock;\r
+  if ((ImageIn->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {\r
+    *NewBlockPtr = EFI_HII_IIBT_IMAGE_24BIT_TRANS;\r
+  } else {\r
+    *NewBlockPtr = EFI_HII_IIBT_IMAGE_24BIT;\r
+  }\r
+  NewBlockPtr++;\r
+\r
+  CopyMem (NewBlockPtr, &ImageIn->Width, sizeof (UINT16));\r
+  NewBlockPtr += sizeof (UINT16);\r
+  CopyMem (NewBlockPtr, &ImageIn->Height, sizeof (UINT16));\r
+  NewBlockPtr += sizeof (UINT16);\r
+\r
+  CopyGopToRgbPixel ((EFI_HII_RGB_PIXEL *) NewBlockPtr, ImageIn->Bitmap, ImageIn->Width * ImageIn->Height);\r
+\r
+  //\r
+  // Adjust the image package to remove the original block firstly then add the new block.\r
+  //\r
+  BlockSize = ImagePackage->ImageBlockSize + NewBlockSize - OldBlockSize;\r
+  Block = (UINT8 *) AllocateZeroPool (BlockSize);\r
+  if (Block == NULL) {\r
+    SafeFreePool (NewBlock);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  BlockPtr  = Block;\r
+  Part1Size = (UINT32) (ImageBlock - ImagePackage->ImageBlock);\r
+  Part2Size = ImagePackage->ImageBlockSize - Part1Size - OldBlockSize;\r
+  CopyMem (BlockPtr, ImagePackage->ImageBlock, Part1Size);\r
+  BlockPtr += Part1Size;\r
+  CopyMem (BlockPtr, NewBlock, NewBlockSize);\r
+  BlockPtr += NewBlockSize;\r
+  CopyMem (BlockPtr, ImageBlock + OldBlockSize, Part2Size);\r
+\r
+  SafeFreePool (ImagePackage->ImageBlock);\r
+  SafeFreePool (NewBlock);\r
+  ImagePackage->ImageBlock     = Block;\r
+  ImagePackage->ImageBlockSize = BlockSize;\r
+  ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize - OldBlockSize;\r
+  PackageListNode->PackageListHdr.PackageLength += NewBlockSize - OldBlockSize;\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+  This function renders an image to a bitmap or the screen using the specified\r
+  color and options. It draws the image on an existing bitmap, allocates a new\r
+  bitmap or uses the screen. The images can be clipped.\r
+\r
+  @param  This                   A pointer to the EFI_HII_IMAGE_PROTOCOL instance.\r
+  @param  Flags                  Describes how the image is to be drawn.\r
+  @param  Image                  Points to the image to be displayed.\r
+  @param  Blt                    If this points to a non-NULL on entry, this points\r
+                                 to the image, which is Width pixels wide and\r
+                                 Height pixels high.  The image will be drawn onto\r
+                                 this image and  EFI_HII_DRAW_FLAG_CLIP is implied.\r
+                                 If this points to a  NULL on entry, then a buffer\r
+                                 will be allocated to hold  the generated image and\r
+                                 the pointer updated on exit. It is the caller¡¯s\r
+                                 responsibility to free this buffer.\r
+  @param  BltY                   Specifies the offset from the left and top edge of\r
+                                 the  output image of the first pixel in the image.\r
+\r
+  @retval EFI_SUCCESS            The image was successfully drawn.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate an output buffer for Blt.\r
+  @retval EFI_INVALID_PARAMETER  The Image or Blt was NULL.\r
+  @retval EFI_INVALID_PARAMETER  Any combination of Flags is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiDrawImage (\r
+  IN CONST EFI_HII_IMAGE_PROTOCOL    *This,\r
+  IN EFI_HII_DRAW_FLAGS              Flags,\r
+  IN CONST EFI_IMAGE_INPUT           *Image,\r
+  IN OUT EFI_IMAGE_OUTPUT            **Blt,\r
+  IN UINTN                           BltX,\r
+  IN UINTN                           BltY\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  BOOLEAN                             Transparent;\r
+  EFI_IMAGE_INPUT                     *ImageIn;\r
+  EFI_IMAGE_OUTPUT                    *ImageOut;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL       *BltBuffer;\r
+  UINTN                               BufferLen;\r
+  UINTN                               Width;\r
+  UINTN                               Height;\r
+  UINTN                               X;\r
+  UINTN                               Y;\r
+  UINTN                               OffsetY1;\r
+  UINTN                               OffsetY2;\r
+  EFI_FONT_DISPLAY_INFO               *FontInfo;\r
+  UINTN                               Index;\r
+  EFI_CONSOLE_CONTROL_PROTOCOL        *Console;\r
+\r
+  if (This == NULL || Image == NULL || Blt == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((Flags & EFI_HII_DRAW_FLAG_CLIP) == EFI_HII_DRAW_FLAG_CLIP && *Blt == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_TRANSPARENT) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ImageIn = (EFI_IMAGE_INPUT *) Image;\r
+\r
+  //\r
+  // Check whether the image will be drawn transparently or opaquely.\r
+  //\r
+  Transparent = FALSE;\r
+  if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_TRANS) {\r
+    Transparent = TRUE;\r
+  } else if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_OPAQUE){\r
+    Transparent = FALSE;\r
+  } else {\r
+    //\r
+    // Now EFI_HII_DRAW_FLAG_DEFAULT is set, whether image will be drawn depending\r
+    // on the image's transparency setting.\r
+    //\r
+    if ((ImageIn->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {\r
+      Transparent = TRUE;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Image cannot be drawn transparently if Blt points to NULL on entry.\r
+  // Currently output to Screen transparently is not supported, either.\r
+  //\r
+  if (Transparent) {\r
+    if (*Blt == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    } else if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+\r
+  Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // When Blt points to a non-NULL on entry, this image will be drawn onto\r
+  // this bitmap or screen pointed by "*Blt" and EFI_HII_DRAW_FLAG_CLIP is implied.\r
+  // Otherwise a new bitmap will be allocated to hold this image.\r
+  //\r
+  if (*Blt != NULL) {\r
+    //\r
+    // Clip the image by (Width, Height)\r
+    //\r
+\r
+    Width  = ImageIn->Width;\r
+    Height = ImageIn->Height;\r
+\r
+    if (Width > (*Blt)->Width - BltX) {\r
+      Width = (*Blt)->Width - BltX;\r
+    }\r
+    if (Height > (*Blt)->Height - BltY) {\r
+      Height = (*Blt)->Height - BltY;\r
+    }\r
+\r
+    BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+    BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);\r
+    if (BltBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    if (Width == ImageIn->Width && Height == ImageIn->Height) {\r
+      CopyMem (BltBuffer, ImageIn->Bitmap, BufferLen);\r
+    } else {\r
+      for (Y = 0; Y < Height; Y++) {\r
+        OffsetY1 = ImageIn->Width * Y;\r
+        OffsetY2 = Width * Y;\r
+        for (X = 0; X < Width; X++) {\r
+          BltBuffer[OffsetY2 + X] = ImageIn->Bitmap[OffsetY1 + X];\r
+        }\r
+      }\r
+    }\r
+\r
+    //\r
+    // Draw the image to existing bitmap or screen depending on flag.\r
+    //\r
+    if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {\r
+      Status = gBS->LocateProtocol (\r
+                      &gEfiConsoleControlProtocolGuid,\r
+                      NULL,\r
+                      (VOID **) &Console\r
+                      );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      Console->SetMode (Console, EfiConsoleControlScreenGraphics);\r
+      //\r
+      // Write the image directly to the output device specified by Screen.\r
+      //\r
+      Status = (*Blt)->Image.Screen->Blt (\r
+                                       (*Blt)->Image.Screen,\r
+                                       BltBuffer,\r
+                                       EfiBltBufferToVideo,\r
+                                       0,\r
+                                       0,\r
+                                       BltX,\r
+                                       BltY,\r
+                                       Width,\r
+                                       Height,\r
+                                       0\r
+                                       );\r
+    } else {\r
+      //\r
+      // Draw the image onto the existing bitmap specified by Bitmap.\r
+      //\r
+      Status = ImageToBlt (\r
+                 BltBuffer,\r
+                 BltX,\r
+                 BltY,\r
+                 Width,\r
+                 Height,\r
+                 Transparent,\r
+                 Blt\r
+                 );\r
+\r
+    }\r
+\r
+    SafeFreePool (BltBuffer);\r
+    return Status;\r
+\r
+  } else {\r
+    //\r
+    // Allocate a new bitmap to hold the incoming image.\r
+    //\r
+    Width  = ImageIn->Width  + BltX;\r
+    Height = ImageIn->Height + BltY;\r
+\r
+    BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+    BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);\r
+    if (BltBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    ImageOut = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
+    if (ImageOut == NULL) {\r
+      SafeFreePool (BltBuffer);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    ImageOut->Width        = (UINT16) Width;\r
+    ImageOut->Height       = (UINT16) Height;\r
+    ImageOut->Image.Bitmap = BltBuffer;\r
+\r
+    //\r
+    // BUGBUG: Now all the "blank" pixels are filled with system default background\r
+    // color. Not sure if it need to be updated or not.\r
+    //\r
+    Status = GetSystemFont (Private, &FontInfo, NULL);\r
+    if (EFI_ERROR (Status)) {\r
+      SafeFreePool (BltBuffer);\r
+      SafeFreePool (ImageOut);\r
+      return Status;\r
+    }\r
+    for (Index = 0; Index < Width * Height; Index++) {\r
+      BltBuffer[Index] = FontInfo->BackgroundColor;\r
+    }\r
+    SafeFreePool (FontInfo);\r
+\r
+    //\r
+    // Draw the incoming image to the new created image.\r
+    //\r
+    *Blt = ImageOut;\r
+    return ImageToBlt (\r
+             ImageIn->Bitmap,\r
+             BltX,\r
+             BltY,\r
+             ImageIn->Width,\r
+             ImageIn->Height,\r
+             Transparent,\r
+             Blt\r
+             );\r
+\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  This function renders an image to a bitmap or the screen using the specified\r
+  color and options. It draws the image on an existing bitmap, allocates a new\r
+  bitmap or uses the screen. The images can be clipped.\r
+\r
+  @param  This                   A pointer to the EFI_HII_IMAGE_PROTOCOL instance.\r
+  @param  Flags                  Describes how the image is to be drawn.\r
+  @param  PackageList            The package list in the HII database to search for\r
+                                 the  specified image.\r
+  @param  ImageId                The image's id, which is unique within\r
+                                 PackageList.\r
+  @param  Blt                    If this points to a non-NULL on entry, this points\r
+                                 to the image, which is Width pixels wide and\r
+                                 Height pixels high. The image will be drawn onto\r
+                                 this image and\r
+                                 EFI_HII_DRAW_FLAG_CLIP is implied. If this points\r
+                                 to a  NULL on entry, then a buffer will be\r
+                                 allocated to hold  the generated image and the\r
+                                 pointer updated on exit. It is the caller¡¯s\r
+                                 responsibility to free this buffer.\r
+  @param  BltY                   Specifies the offset from the left and top edge of\r
+                                 the  output image of the first pixel in the image.\r
+\r
+  @retval EFI_SUCCESS            The image was successfully drawn.\r
+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate an output buffer for Blt.\r
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.\r
+  @retval EFI_NOT_FOUND          The specified packagelist could not be found in\r
+                                 current database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiDrawImageId (\r
+  IN CONST EFI_HII_IMAGE_PROTOCOL    *This,\r
+  IN EFI_HII_DRAW_FLAGS              Flags,\r
+  IN EFI_HII_HANDLE                  PackageList,\r
+  IN EFI_IMAGE_ID                    ImageId,\r
+  IN OUT EFI_IMAGE_OUTPUT            **Blt,\r
+  IN UINTN                           BltX,\r
+  IN UINTN                           BltY\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  EFI_IMAGE_INPUT                     ImageTemp;\r
+  EFI_IMAGE_INPUT                     *Image;\r
+  UINTN                               ImageSize;\r
+\r
+  //\r
+  // Check input parameter.\r
+  //\r
+  if (This == NULL || PackageList == NULL || Blt == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!IsHiiHandleValid (PackageList)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Get the specified Image.\r
+  //\r
+  ImageSize = 0;\r
+  Status = HiiGetImage (This, PackageList, ImageId, &ImageTemp, &ImageSize);\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    return Status;\r
+  }\r
+\r
+  Image = (EFI_IMAGE_INPUT *) AllocateZeroPool (ImageSize);\r
+  if (Image == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  Status = HiiGetImage (This, PackageList, ImageId, Image, &ImageSize);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Draw this image.\r
+  //\r
+  Status = HiiDrawImage (This, Flags, Image, Blt, BltX, BltY);\r
+  SafeFreePool (Image);\r
+  return Status;\r
+}\r
+\r
+#endif\r
+\r
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.c b/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.c
new file mode 100644 (file)
index 0000000..5458b16
--- /dev/null
@@ -0,0 +1,284 @@
+/**@file\r
+  Copyright (c) 2007, Intel Corporation\r
+\r
+  All rights reserved. This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+#include "HiiDatabase.h"\r
+\r
+\r
+CHAR16\r
+NibbleToHexChar (\r
+  IN UINT8      Nibble\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Converts the low nibble of a byte  to hex unicode character.\r
+\r
+  Arguments:\r
+    Nibble - lower nibble of a byte.\r
+\r
+  Returns:\r
+    Hex unicode character.\r
+\r
+--*/\r
+{\r
+  Nibble &= 0x0F;\r
+  if (Nibble <= 0x9) {\r
+    return (CHAR16)(Nibble + L'0');\r
+  }\r
+\r
+  return (CHAR16)(Nibble - 0xA + L'A');\r
+}\r
+\r
+/**\r
+  Compare whether two names of languages are identical.\r
+\r
+  @param  Language1              Name of language 1\r
+  @param  Language2              Name of language 2\r
+\r
+  @retval TRUE                   same\r
+  @retval FALSE                  not same\r
+\r
+**/\r
+BOOLEAN\r
+R8_EfiLibCompareLanguage (\r
+  IN  CHAR8  *Language1,\r
+  IN  CHAR8  *Language2\r
+  )\r
+{\r
+  //\r
+  // Porting Guide:\r
+  // This library interface is simply obsolete.\r
+  // Include the source code to user code.\r
+  //\r
+  UINTN Index;\r
+\r
+  for (Index = 0; (Language1[Index] != 0) && (Language2[Index] != 0); Index++) {\r
+    if (Language1[Index] != Language2[Index]) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  if (((Language1[Index] == 0) && (Language2[Index] == 0))   || \r
+         ((Language1[Index] == 0) && (Language2[Index] != ';')) ||\r
+         ((Language1[Index] == ';') && (Language2[Index] != 0)) ||\r
+         ((Language1[Index] == ';') && (Language2[Index] != ';'))) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+\r
+\r
+\r
+/**\r
+  Converts binary buffer to Unicode string.\r
+  At a minimum, any blob of data could be represented as a hex string.\r
+\r
+  @param  Str                    Pointer to the string.\r
+  @param  HexStringBufferLength  Length in bytes of buffer to hold the hex string.\r
+                                 Includes tailing '\0' character. If routine return\r
+                                 with EFI_SUCCESS, containing length of hex string\r
+                                 buffer. If routine return with\r
+                                 EFI_BUFFER_TOO_SMALL, containg length of hex\r
+                                 string buffer desired.\r
+  @param  Buf                    Buffer to be converted from.\r
+  @param  Len                    Length in bytes of the buffer to be converted.\r
+\r
+  @retval EFI_SUCCESS            Routine success.\r
+  @retval EFI_BUFFER_TOO_SMALL   The hex string buffer is too small.\r
+\r
+**/\r
+EFI_STATUS\r
+R8_BufToHexString (\r
+  IN OUT CHAR16                    *Str,\r
+  IN OUT UINTN                     *HexStringBufferLength,\r
+  IN     UINT8                     *Buf,\r
+  IN     UINTN                      Len\r
+  )\r
+{\r
+  //\r
+  // Porting Guide:\r
+  // This library interface is simply obsolete.\r
+  // Include the source code to user code.\r
+  //\r
+  UINTN       Idx;\r
+  UINT8       Byte;\r
+  UINTN       StrLen;\r
+\r
+  //\r
+  // Make sure string is either passed or allocate enough.\r
+  // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.\r
+  // Plus the Unicode termination character.\r
+  //\r
+  StrLen = Len * 2;\r
+  if (StrLen > ((*HexStringBufferLength) - 1)) {\r
+    *HexStringBufferLength = StrLen + 1;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  *HexStringBufferLength = StrLen + 1;\r
+  //\r
+  // Ends the string.\r
+  //\r
+  Str[StrLen] = L'\0';\r
+\r
+  for (Idx = 0; Idx < Len; Idx++) {\r
+\r
+    Byte = Buf[Idx];\r
+    Str[StrLen - 1 - Idx * 2] = NibbleToHexChar (Byte);\r
+    Str[StrLen - 2 - Idx * 2] = NibbleToHexChar ((UINT8)(Byte >> 4));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+\r
+/**\r
+  Converts Unicode string to binary buffer.\r
+  The conversion may be partial.\r
+  The first character in the string that is not hex digit stops the conversion.\r
+  At a minimum, any blob of data could be represented as a hex string.\r
+\r
+  @param  Buf                    Pointer to buffer that receives the data.\r
+  @param  Len                    Length in bytes of the buffer to hold converted\r
+                                 data. If routine return with EFI_SUCCESS,\r
+                                 containing length of converted data. If routine\r
+                                 return with EFI_BUFFER_TOO_SMALL, containg length\r
+                                 of buffer desired.\r
+  @param  Str                    String to be converted from.\r
+  @param  ConvertedStrLen        Length of the Hex String consumed.\r
+\r
+  @retval EFI_SUCCESS            Routine Success.\r
+  @retval EFI_BUFFER_TOO_SMALL   The buffer is too small to hold converted data.\r
+\r
+**/\r
+EFI_STATUS\r
+R8_HexStringToBuf (\r
+  IN OUT UINT8                     *Buf,\r
+  IN OUT UINTN                    *Len,\r
+  IN     CHAR16                    *Str,\r
+  OUT    UINTN                     *ConvertedStrLen  OPTIONAL\r
+  )\r
+{\r
+  //\r
+  // Porting Guide:\r
+  // This library interface is simply obsolete.\r
+  // Include the source code to user code.\r
+  //\r
+\r
+  UINTN       HexCnt;\r
+  UINTN       Idx;\r
+  UINTN       BufferLength;\r
+  UINT8       Digit;\r
+  UINT8       Byte;\r
+\r
+  //\r
+  // Find out how many hex characters the string has.\r
+  //\r
+  for (Idx = 0, HexCnt = 0; R8_IsHexDigit (&Digit, Str[Idx]); Idx++, HexCnt++);\r
+\r
+  if (HexCnt == 0) {\r
+    *Len = 0;\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // Two Unicode characters make up 1 buffer byte. Round up.\r
+  //\r
+  BufferLength = (HexCnt + 1) / 2;\r
+\r
+  //\r
+  // Test if  buffer is passed enough.\r
+  //\r
+  if (BufferLength > (*Len)) {\r
+    *Len = BufferLength;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  *Len = BufferLength;\r
+\r
+  for (Idx = 0; Idx < HexCnt; Idx++) {\r
+\r
+    R8_IsHexDigit (&Digit, Str[HexCnt - 1 - Idx]);\r
+\r
+    //\r
+    // For odd charaters, write the lower nibble for each buffer byte,\r
+    // and for even characters, the upper nibble.\r
+    //\r
+    if ((Idx & 1) == 0) {\r
+      Byte = Digit;\r
+    } else {\r
+      Byte = Buf[Idx / 2];\r
+      Byte &= 0x0F;\r
+      Byte = (UINT8) (Byte | Digit << 4);\r
+    }\r
+\r
+    Buf[Idx / 2] = Byte;\r
+  }\r
+\r
+  if (ConvertedStrLen != NULL) {\r
+    *ConvertedStrLen = HexCnt;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+\r
+/**\r
+  Determines if a Unicode character is a hexadecimal digit.\r
+  The test is case insensitive.\r
+\r
+  @param  Digit                  Pointer to byte that receives the value of the hex\r
+                                 character.\r
+  @param  Char                   Unicode character to test.\r
+\r
+  @retval TRUE                   If the character is a hexadecimal digit.\r
+  @retval FALSE                  Otherwise.\r
+\r
+**/\r
+BOOLEAN\r
+R8_IsHexDigit (\r
+  OUT UINT8      *Digit,\r
+  IN  CHAR16      Char\r
+  )\r
+{\r
+  //\r
+  // Porting Guide:\r
+  // This library interface is simply obsolete.\r
+  // Include the source code to user code.\r
+  //\r
+\r
+  if ((Char >= L'0') && (Char <= L'9')) {\r
+    *Digit = (UINT8) (Char - L'0');\r
+    return TRUE;\r
+  }\r
+\r
+  if ((Char >= L'A') && (Char <= L'F')) {\r
+    *Digit = (UINT8) (Char - L'A' + 0x0A);\r
+    return TRUE;\r
+  }\r
+\r
+  if ((Char >= L'a') && (Char <= L'f')) {\r
+    *Digit = (UINT8) (Char - L'a' + 0x0A);\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+\r
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.h b/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.h
new file mode 100644 (file)
index 0000000..4e6e1a1
--- /dev/null
@@ -0,0 +1,121 @@
+/**@file
+  Copyright (c) 2007, Intel Corporation
+
+  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 __R8_LIB_H__
+#define __R8_LIB_H__
+
+
+/**
+  Compare whether two names of languages are identical.
+
+  @param  Language1              Name of language 1
+  @param  Language2              Name of language 2
+
+  @retval TRUE                   same
+  @retval FALSE                  not same
+
+**/
+BOOLEAN
+R8_EfiLibCompareLanguage (
+  IN  CHAR8  *Language1,
+  IN  CHAR8  *Language2
+  )
+;
+
+
+
+
+/**
+  Converts binary buffer to Unicode string.
+  At a minimum, any blob of data could be represented as a hex string.
+
+  @param  Str                    Pointer to the string.
+  @param  HexStringBufferLength  Length in bytes of buffer to hold the hex string.
+                                 Includes tailing '\0' character. If routine return
+                                 with EFI_SUCCESS, containing length of hex string
+                                 buffer. If routine return with
+                                 EFI_BUFFER_TOO_SMALL, containg length of hex
+                                 string buffer desired.
+  @param  Buf                    Buffer to be converted from.
+  @param  Len                    Length in bytes of the buffer to be converted.
+
+  @retval EFI_SUCCESS            Routine success.
+  @retval EFI_BUFFER_TOO_SMALL   The hex string buffer is too small.
+
+**/
+EFI_STATUS
+R8_BufToHexString (
+  IN OUT CHAR16                    *Str,
+  IN OUT UINTN                     *HexStringBufferLength,
+  IN     UINT8                     *Buf,
+  IN     UINTN                      Len
+  )
+;
+
+
+
+
+/**
+  Converts Unicode string to binary buffer.
+  The conversion may be partial.
+  The first character in the string that is not hex digit stops the conversion.
+  At a minimum, any blob of data could be represented as a hex string.
+
+  @param  Buf                    Pointer to buffer that receives the data.
+  @param  Len                    Length in bytes of the buffer to hold converted
+                                 data. If routine return with EFI_SUCCESS,
+                                 containing length of converted data. If routine
+                                 return with EFI_BUFFER_TOO_SMALL, containg length
+                                 of buffer desired.
+  @param  Str                    String to be converted from.
+  @param  ConvertedStrLen        Length of the Hex String consumed.
+
+  @retval EFI_SUCCESS            Routine Success.
+  @retval EFI_BUFFER_TOO_SMALL   The buffer is too small to hold converted data.
+
+**/
+EFI_STATUS
+R8_HexStringToBuf (
+  IN OUT UINT8                     *Buf,
+  IN OUT UINTN                    *Len,
+  IN     CHAR16                    *Str,
+  OUT    UINTN                     *ConvertedStrLen  OPTIONAL
+  )
+;
+
+
+
+
+/**
+  Determines if a Unicode character is a hexadecimal digit.
+  The test is case insensitive.
+
+  @param  Digit                  Pointer to byte that receives the value of the hex
+                                 character.
+  @param  Char                   Unicode character to test.
+
+  @retval TRUE                   If the character is a hexadecimal digit.
+  @retval FALSE                  Otherwise.
+
+**/
+BOOLEAN
+R8_IsHexDigit (
+  OUT UINT8      *Digit,
+  IN  CHAR16      Char
+  )
+;
+
+
+#endif
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/String.c b/MdeModulePkg/Universal/HiiDatabaseDxe/String.c
new file mode 100644 (file)
index 0000000..d408365
--- /dev/null
@@ -0,0 +1,1606 @@
+/** @file\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+    String.c\r
+\r
+Abstract:\r
+\r
+    Implementation for EFI_HII_STRING_PROTOCOL.\r
+\r
+Revision History\r
+\r
+\r
+**/\r
+\r
+\r
+#include "HiiDatabase.h"\r
+\r
+CHAR16 mLanguageWindow[16] = {\r
+  0x0000, 0x0080, 0x0100, 0x0300,\r
+  0x2000, 0x2080, 0x2100, 0x3000,\r
+  0x0080, 0x00C0, 0x0400, 0x0600,\r
+  0x0900, 0x3040, 0x30A0, 0xFF00\r
+};\r
+\r
+\r
+/**\r
+  This function checks whether a global font info is referred by local\r
+  font info list or not. (i.e. HII_FONT_INFO is generated.) If not, create\r
+  a HII_FONT_INFO to refer it locally.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  StringPackage          HII string package instance.\r
+  @param  DuplicateEnable        If true, duplicate HII_FONT_INFO which refers to\r
+                                 the same EFI_FONT_INFO is permitted. Otherwise it\r
+                                 is not allowed.\r
+  @param  GlobalFontInfo         Input a global font info which specify a\r
+                                 EFI_FONT_INFO.\r
+  @param  LocalFontInfo          Output a local font info which refers to a\r
+                                 EFI_FONT_INFO.\r
+\r
+  @retval TRUE                   Already referred before calling this function.\r
+  @retval FALSE                  Not referred before calling this function.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+ReferFontInfoLocally (\r
+  IN  HII_DATABASE_PRIVATE_DATA   *Private,\r
+  IN  HII_STRING_PACKAGE_INSTANCE *StringPackage,\r
+  IN  BOOLEAN                     DuplicateEnable,\r
+  IN  HII_GLOBAL_FONT_INFO        *GlobalFontInfo,\r
+  OUT HII_FONT_INFO               **LocalFontInfo\r
+  )\r
+{\r
+  HII_FONT_INFO                 *LocalFont;\r
+  LIST_ENTRY                    *Link;\r
+\r
+  ASSERT (Private != NULL && StringPackage != NULL && GlobalFontInfo != NULL && LocalFontInfo != NULL);\r
+\r
+  if (!DuplicateEnable) {\r
+    for (Link = StringPackage->FontInfoList.ForwardLink;\r
+         Link != &StringPackage->FontInfoList;\r
+         Link = Link->ForwardLink\r
+        ) {\r
+      LocalFont = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE);\r
+      if (LocalFont->GlobalEntry == &GlobalFontInfo->Entry) {\r
+        //\r
+        // Already referred by local font info list, return directly.\r
+        //\r
+        *LocalFontInfo = LocalFont;\r
+        return TRUE;\r
+      }\r
+    }\r
+  }\r
+  //\r
+  // Since string package tool set FontId initially to 0 and increases it\r
+  // progressively by one, StringPackage->FondId always represents an unique\r
+  // and available FontId.\r
+  //\r
+  // FontId identifies EFI_FONT_INFO in local string package uniquely.\r
+  // GlobalEntry points to a HII_GLOBAL_FONT_INFO which identifies\r
+  // EFI_FONT_INFO uniquely in whole hii database.\r
+  //\r
+  LocalFont = (HII_FONT_INFO *) AllocateZeroPool (sizeof (HII_FONT_INFO));\r
+  ASSERT (LocalFont != NULL);\r
+\r
+  LocalFont->Signature   = HII_FONT_INFO_SIGNATURE;\r
+  LocalFont->FontId      = StringPackage->FontId;\r
+  LocalFont->GlobalEntry = &GlobalFontInfo->Entry;\r
+  InsertTailList (&StringPackage->FontInfoList, &LocalFont->Entry);\r
+\r
+  StringPackage->FontId++;\r
+\r
+  *LocalFontInfo = LocalFont;\r
+  return FALSE;\r
+}\r
+\r
+\r
+/**\r
+  Convert Ascii string text to unicode string test.\r
+\r
+  @param  StringSrc              Points to current null-terminated Ascii string.\r
+  @param  StringDest             Buffer to store the converted string text.\r
+  @param  BufferSize             Length of the buffer.\r
+\r
+  @retval EFI_SUCCESS            The string text was outputed successfully.\r
+  @retval EFI_BUFFER_TOO_SMALL   Buffer is insufficient to store the found string\r
+                                 text. BufferSize is updated to the required buffer\r
+                                 size.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ConvertToUnicodeText (\r
+  OUT EFI_STRING       StringDest,\r
+  IN  CHAR8            *StringSrc,\r
+  IN  OUT UINTN        *BufferSize\r
+  )\r
+{\r
+  UINTN  StringSize;\r
+  UINTN  Index;\r
+\r
+  ASSERT (StringSrc != NULL && BufferSize != NULL);\r
+\r
+  StringSize = AsciiStrSize (StringSrc) * 2;\r
+  if (*BufferSize < StringSize) {\r
+    *BufferSize = StringSize;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  for (Index = 0; Index < AsciiStrLen (StringSrc); Index++) {\r
+    StringDest[Index] = (CHAR16) StringSrc[Index];\r
+  }\r
+\r
+  StringDest[Index] = 0;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Calculate the size of StringSrc and output it. If StringDest is not NULL,\r
+  copy string text from src to dest.\r
+\r
+  @param  StringSrc              Points to current null-terminated string.\r
+  @param  StringDest             Buffer to store the string text.\r
+  @param  BufferSize             Length of the buffer.\r
+\r
+  @retval EFI_SUCCESS            The string text was outputed successfully.\r
+  @retval EFI_BUFFER_TOO_SMALL   Buffer is insufficient to store the found string\r
+                                 text. BufferSize is updated to the required buffer\r
+                                 size.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetUnicodeStringTextOrSize (\r
+  OUT EFI_STRING       StringDest, OPTIONAL\r
+  IN  UINT8            *StringSrc,\r
+  IN  OUT UINTN        *BufferSize\r
+  )\r
+{\r
+  UINTN  StringSize;\r
+  CHAR16 Zero;\r
+  UINT8  *StringPtr;\r
+\r
+  ASSERT (StringSrc != NULL && BufferSize != NULL);\r
+\r
+  ZeroMem (&Zero, sizeof (CHAR16));\r
+  StringSize = sizeof (CHAR16);\r
+  StringPtr  = StringSrc;\r
+  while (CompareMem (StringPtr, &Zero, sizeof (CHAR16)) != 0) {\r
+    StringSize += sizeof (CHAR16);\r
+    StringPtr += sizeof (CHAR16);\r
+  }\r
+\r
+  if (StringDest != NULL) {\r
+    if (*BufferSize < StringSize) {\r
+      *BufferSize = StringSize;\r
+      return EFI_BUFFER_TOO_SMALL;\r
+    }\r
+    CopyMem (StringDest, StringSrc, StringSize);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  *BufferSize = StringSize;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Copy string font info to a buffer.\r
+\r
+  @param  StringPackage          Hii string package instance.\r
+  @param  FontId                 Font identifier which is unique in a string\r
+                                 package.\r
+  @param  StringFontInfo         Buffer to record the output font info. It's\r
+                                 caller's responsibility to free this buffer.\r
+\r
+  @retval EFI_SUCCESS            The string font is outputed successfully.\r
+  @retval EFI_NOT_FOUND          The specified font id does not exist.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetStringFontInfo (\r
+  IN  HII_STRING_PACKAGE_INSTANCE     *StringPackage,\r
+  IN  UINT8                           FontId,\r
+  OUT EFI_FONT_INFO                   **StringFontInfo\r
+  )\r
+{\r
+  LIST_ENTRY                           *Link;\r
+  HII_FONT_INFO                        *FontInfo;\r
+  HII_GLOBAL_FONT_INFO                 *GlobalFont;\r
+\r
+  ASSERT (StringFontInfo != NULL && StringPackage != NULL);\r
+\r
+  for (Link = StringPackage->FontInfoList.ForwardLink; Link != &StringPackage->FontInfoList; Link = Link->ForwardLink) {\r
+    FontInfo = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE);\r
+    if (FontInfo->FontId == FontId) {\r
+      GlobalFont = CR (FontInfo->GlobalEntry, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);\r
+      *StringFontInfo = (EFI_FONT_INFO *) AllocateZeroPool (GlobalFont->FontInfoSize);\r
+      if (*StringFontInfo == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      CopyMem (*StringFontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  Parse all string blocks to find a String block specified by StringId.\r
+  If StringId = (EFI_STRING_ID) (-1), find out all EFI_HII_SIBT_FONT blocks\r
+  within this string package and backup its information.\r
+  If StringId = 0, output the string id of last string block (EFI_HII_SIBT_END).\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  StringPackage          Hii string package instance.\r
+  @param  StringId               The string¡¯s id, which is unique within\r
+                                 PackageList.\r
+  @param  BlockType              Output the block type of found string block.\r
+  @param  StringBlockAddr        Output the block address of found string block.\r
+  @param  StringTextOffset       Offset, relative to the found block address, of\r
+                                 the  string text information.\r
+  @param  LastStringId           Output the last string id when StringId = 0.\r
+\r
+  @retval EFI_SUCCESS            The string text and font is retrieved\r
+                                 successfully.\r
+  @retval EFI_NOT_FOUND          The specified text or font info can not be found\r
+                                 out.\r
+  @retval EFI_OUT_OF_RESOURCES   The system is out of resources to accomplish the\r
+                                 task.\r
+\r
+**/\r
+EFI_STATUS\r
+FindStringBlock (\r
+  IN HII_DATABASE_PRIVATE_DATA        *Private,\r
+  IN  HII_STRING_PACKAGE_INSTANCE     *StringPackage,\r
+  IN  EFI_STRING_ID                   StringId,\r
+  OUT UINT8                           *BlockType, OPTIONAL\r
+  OUT UINT8                           **StringBlockAddr, OPTIONAL\r
+  OUT UINTN                           *StringTextOffset, OPTIONAL\r
+  OUT EFI_STRING_ID                   *LastStringId OPTIONAL\r
+  )\r
+{\r
+  UINT8                                *BlockHdr;\r
+  EFI_STRING_ID                        CurrentStringId;\r
+  UINTN                                BlockSize;\r
+  UINTN                                Index;\r
+  UINT8                                *StringTextPtr;\r
+  UINTN                                Offset;\r
+  HII_FONT_INFO                        *LocalFont;\r
+  EFI_FONT_INFO                        *FontInfo;\r
+  HII_GLOBAL_FONT_INFO                 *GlobalFont;\r
+  UINTN                                FontInfoSize;\r
+  UINT16                               StringCount;\r
+  UINT16                               SkipCount;\r
+  EFI_HII_FONT_STYLE                   FontStyle;\r
+  UINT16                               FontSize;\r
+  UINT8                                Length8;\r
+  EFI_HII_SIBT_EXT2_BLOCK              Ext2;\r
+  UINT32                               Length32;\r
+  UINTN                                StringSize;\r
+  CHAR16                               Zero;\r
+\r
+  ASSERT (StringPackage != NULL);\r
+  ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);\r
+\r
+  CurrentStringId = 1;\r
+\r
+  if (StringId != (EFI_STRING_ID) (-1) && StringId != 0) {\r
+    ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);\r
+  } else {\r
+    ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
+  }\r
+\r
+  ZeroMem (&Zero, sizeof (CHAR16));\r
+\r
+  //\r
+  // Parse the string blocks to get the string text and font.\r
+  //\r
+  BlockHdr  = StringPackage->StringBlock;\r
+  BlockSize = 0;\r
+  Offset    = 0;\r
+  while (*BlockHdr != EFI_HII_SIBT_END) {\r
+    switch (*BlockHdr) {\r
+    case EFI_HII_SIBT_STRING_SCSU:\r
+      Offset = sizeof (EFI_HII_STRING_BLOCK);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+      CurrentStringId++;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRING_SCSU_FONT:\r
+      Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+      CurrentStringId++;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRINGS_SCSU:\r
+      CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+      StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8);\r
+      BlockSize += StringTextPtr - BlockHdr;\r
+\r
+      for (Index = 0; Index < StringCount; Index++) {\r
+        BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+        if (CurrentStringId == StringId) {\r
+          *BlockType        = *BlockHdr;\r
+          *StringBlockAddr  = BlockHdr;\r
+          *StringTextOffset = StringTextPtr - BlockHdr;\r
+          return EFI_SUCCESS;\r
+        }\r
+        StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+        CurrentStringId++;\r
+      }\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
+      CopyMem (\r
+        &StringCount,\r
+        BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+        sizeof (UINT16)\r
+        );\r
+      StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8);\r
+      BlockSize += StringTextPtr - BlockHdr;\r
+\r
+      for (Index = 0; Index < StringCount; Index++) {\r
+        BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+        if (CurrentStringId == StringId) {\r
+          *BlockType        = *BlockHdr;\r
+          *StringBlockAddr  = BlockHdr;\r
+          *StringTextOffset = StringTextPtr - BlockHdr;\r
+          return EFI_SUCCESS;\r
+        }\r
+        StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+        CurrentStringId++;\r
+      }\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRING_UCS2:\r
+      Offset        = sizeof (EFI_HII_STRING_BLOCK);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      //\r
+      // Use StringSize to store the size of the specified string, including the NULL\r
+      // terminator.\r
+      //\r
+      GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);\r
+      BlockSize += Offset + StringSize;\r
+      CurrentStringId++;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRING_UCS2_FONT:\r
+      Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK)  - sizeof (CHAR16);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      //\r
+      // Use StrSize to store the size of the specified string, including the NULL\r
+      // terminator.\r
+      //\r
+      GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);\r
+      BlockSize += Offset + StringSize;\r
+      CurrentStringId++;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRINGS_UCS2:\r
+      Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      BlockSize += Offset;\r
+      CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+      for (Index = 0; Index < StringCount; Index++) {\r
+        GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);\r
+        BlockSize += StringSize;\r
+        if (CurrentStringId == StringId) {\r
+          *BlockType        = *BlockHdr;\r
+          *StringBlockAddr  = BlockHdr;\r
+          *StringTextOffset = StringTextPtr - BlockHdr;\r
+          return EFI_SUCCESS;\r
+        }\r
+        StringTextPtr = StringTextPtr + StringSize;\r
+        CurrentStringId++;\r
+      }\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
+      Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      BlockSize += Offset;\r
+      CopyMem (\r
+        &StringCount,\r
+        BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+        sizeof (UINT16)\r
+        );\r
+      for (Index = 0; Index < StringCount; Index++) {\r
+        GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);\r
+        BlockSize += StringSize;\r
+        if (CurrentStringId == StringId) {\r
+          *BlockType        = *BlockHdr;\r
+          *StringBlockAddr  = BlockHdr;\r
+          *StringTextOffset = StringTextPtr - BlockHdr;\r
+          return EFI_SUCCESS;\r
+        }\r
+        StringTextPtr = StringTextPtr + StringSize;\r
+        CurrentStringId++;\r
+      }\r
+      break;\r
+\r
+    case EFI_HII_SIBT_DUPLICATE:\r
+      if (CurrentStringId == StringId) {\r
+        //\r
+        // Incoming StringId is an id of a duplicate string block.\r
+        // Update the StringId to be the previous string block.\r
+        // Go back to the header of string block to search.\r
+        //\r
+        CopyMem (\r
+          &StringId,\r
+          BlockHdr + sizeof (EFI_HII_STRING_BLOCK),\r
+          sizeof (EFI_STRING_ID)\r
+          );\r
+        ASSERT (StringId != CurrentStringId);\r
+        CurrentStringId = 1;\r
+        BlockSize       = 0;\r
+      } else {\r
+        BlockSize       += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);\r
+        CurrentStringId++;\r
+      }\r
+      break;\r
+\r
+    case EFI_HII_SIBT_SKIP1:\r
+      SkipCount = (UINT16) (*(BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));\r
+      CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
+      BlockSize       +=  sizeof (EFI_HII_SIBT_SKIP1_BLOCK);\r
+      break;\r
+\r
+    case EFI_HII_SIBT_SKIP2:\r
+      CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+      CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
+      BlockSize       +=  sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
+      break;\r
+\r
+    case EFI_HII_SIBT_EXT1:\r
+      CopyMem (\r
+        &Length8,\r
+        BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+        sizeof (UINT8)\r
+        );\r
+      BlockSize += Length8;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_EXT2:\r
+      CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));\r
+      if (Ext2.BlockType2 == EFI_HII_SIBT_FONT && StringId == (EFI_STRING_ID) (-1)) {\r
+        //\r
+        // Find the relationship between global font info and the font info of\r
+        // this EFI_HII_SIBT_FONT block then backup its information in local package.\r
+        //\r
+        BlockHdr += sizeof (EFI_HII_SIBT_EXT2_BLOCK) + sizeof (UINT8);\r
+        CopyMem (&FontSize, BlockHdr, sizeof (UINT16));\r
+        BlockHdr += sizeof (UINT16);\r
+        CopyMem (&FontStyle, BlockHdr, sizeof (EFI_HII_FONT_STYLE));\r
+        BlockHdr += sizeof (EFI_HII_FONT_STYLE);\r
+        GetUnicodeStringTextOrSize (NULL, BlockHdr, &StringSize);\r
+\r
+        FontInfoSize = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StringSize;\r
+        FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoSize);\r
+        if (FontInfo == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+        FontInfo->FontStyle = FontStyle;\r
+        FontInfo->FontSize  = FontSize;\r
+        CopyMem (FontInfo->FontName, BlockHdr, StringSize);\r
+\r
+        if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) {\r
+          //\r
+          // If find the corresponding global font info, save the relationship.\r
+          //\r
+          ReferFontInfoLocally (Private, StringPackage, TRUE, GlobalFont, &LocalFont);\r
+        }\r
+\r
+        //\r
+        // If can not find, ignore this EFI_HII_SIBT_FONT block.\r
+        //\r
+        SafeFreePool (FontInfo);\r
+      }\r
+\r
+      BlockSize += Ext2.Length;\r
+\r
+      break;\r
+\r
+    case EFI_HII_SIBT_EXT4:\r
+      CopyMem (\r
+        &Length32,\r
+        BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+        sizeof (UINT32)\r
+        );\r
+\r
+      BlockSize += Length32;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+\r
+    if (StringId > 0) {\r
+      if (StringId == CurrentStringId - 1) {\r
+        *BlockType        = *BlockHdr;\r
+        *StringBlockAddr  = BlockHdr;\r
+        *StringTextOffset = Offset;\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      if (StringId < CurrentStringId - 1) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+    }\r
+    BlockHdr  = StringPackage->StringBlock + BlockSize;\r
+\r
+  }\r
+\r
+  if (StringId == (EFI_STRING_ID) (-1)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (StringId == 0 && LastStringId != NULL) {\r
+    *LastStringId = CurrentStringId;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  Parse all string blocks to get a string specified by StringId.\r
+\r
+  @param  Private                Hii database private structure.\r
+  @param  StringPackage          Hii string package instance.\r
+  @param  StringId               The string¡¯s id, which is unique within\r
+                                 PackageList.\r
+  @param  String                 Points to retrieved null-terminated string.\r
+  @param  StringSize             On entry, points to the size of the buffer pointed\r
+                                 to by String, in bytes. On return, points to the\r
+                                 length of the string, in bytes.\r
+  @param  StringFontInfo         If not NULL, allocate a buffer to record the\r
+                                 output font info. It's caller's responsibility to\r
+                                 free this buffer.\r
+\r
+  @retval EFI_SUCCESS            The string text and font is retrieved\r
+                                 successfully.\r
+  @retval EFI_NOT_FOUND          The specified text or font info can not be found\r
+                                 out.\r
+  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by StringSize is too small to\r
+                                 hold the string.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetStringWorker (\r
+  IN HII_DATABASE_PRIVATE_DATA        *Private,\r
+  IN  HII_STRING_PACKAGE_INSTANCE     *StringPackage,\r
+  IN  EFI_STRING_ID                   StringId,\r
+  OUT EFI_STRING                      String,\r
+  IN  OUT UINTN                       *StringSize,\r
+  OUT EFI_FONT_INFO                   **StringFontInfo OPTIONAL\r
+  )\r
+{\r
+  UINT8                                *StringTextPtr;\r
+  UINT8                                BlockType;\r
+  UINT8                                *StringBlockAddr;\r
+  UINTN                                StringTextOffset;\r
+  EFI_STATUS                           Status;\r
+  UINT8                                FontId;\r
+\r
+  ASSERT (StringPackage != NULL && StringSize != NULL);\r
+  ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
+\r
+  //\r
+  // Find the specified string block\r
+  //\r
+  Status = FindStringBlock (\r
+             Private,\r
+             StringPackage,\r
+             StringId,\r
+             &BlockType,\r
+             &StringBlockAddr,\r
+             &StringTextOffset,\r
+             NULL\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get the string text.\r
+  //\r
+  StringTextPtr = StringBlockAddr + StringTextOffset;\r
+  switch (BlockType) {\r
+  case EFI_HII_SIBT_STRING_SCSU:\r
+  case EFI_HII_SIBT_STRING_SCSU_FONT:\r
+  case EFI_HII_SIBT_STRINGS_SCSU:\r
+  case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
+    Status = ConvertToUnicodeText (String, (CHAR8 *) StringTextPtr, StringSize);\r
+    break;\r
+  case EFI_HII_SIBT_STRING_UCS2:\r
+  case EFI_HII_SIBT_STRING_UCS2_FONT:\r
+  case EFI_HII_SIBT_STRINGS_UCS2:\r
+  case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
+    Status = GetUnicodeStringTextOrSize (String, StringTextPtr, StringSize);\r
+    break;\r
+  default:\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get the string font.\r
+  //\r
+  if (StringFontInfo != NULL) {\r
+    switch (BlockType) {\r
+    case EFI_HII_SIBT_STRING_SCSU_FONT:\r
+    case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
+    case EFI_HII_SIBT_STRING_UCS2_FONT:\r
+    case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
+      FontId = *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK));\r
+      return GetStringFontInfo (StringPackage, FontId, StringFontInfo);\r
+      break;\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Parse all string blocks to set a String specified by StringId.\r
+\r
+  @param  Private                HII database driver private structure.\r
+  @param  StringPackage          HII string package instance.\r
+  @param  StringId               The string¡¯s id, which is unique within\r
+                                 PackageList.\r
+  @param  String                 Points to the new null-terminated string.\r
+  @param  StringFontInfo         Points to the input font info.\r
+\r
+  @retval EFI_SUCCESS            The string was updated successfully.\r
+  @retval EFI_NOT_FOUND          The string specified by StringId is not in the\r
+                                 database.\r
+  @retval EFI_INVALID_PARAMETER  The String or Language was NULL.\r
+  @retval EFI_INVALID_PARAMETER  The specified StringFontInfo does not exist in\r
+                                 current database.\r
+  @retval EFI_OUT_OF_RESOURCES   The system is out of resources to accomplish the\r
+                                 task.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+SetStringWorker (\r
+  IN  HII_DATABASE_PRIVATE_DATA       *Private,\r
+  IN OUT HII_STRING_PACKAGE_INSTANCE  *StringPackage,\r
+  IN  EFI_STRING_ID                   StringId,\r
+  IN  EFI_STRING                      String,\r
+  IN  EFI_FONT_INFO                   *StringFontInfo OPTIONAL\r
+  )\r
+{\r
+  UINT8                                *StringTextPtr;\r
+  UINT8                                BlockType;\r
+  UINT8                                *StringBlockAddr;\r
+  UINTN                                StringTextOffset;\r
+  EFI_STATUS                           Status;\r
+  UINT8                                *Block;\r
+  UINT8                                *BlockPtr;\r
+  UINTN                                BlockSize;\r
+  UINTN                                OldBlockSize;\r
+  HII_FONT_INFO                        *LocalFont;\r
+  HII_GLOBAL_FONT_INFO                 *GlobalFont;\r
+  BOOLEAN                              Referred;\r
+  EFI_HII_SIBT_EXT2_BLOCK              Ext2;\r
+  UINTN                                StringSize;\r
+  UINTN                                TmpSize;\r
+\r
+\r
+  ASSERT (Private != NULL && StringPackage != NULL && String != NULL);\r
+  ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
+  //\r
+  // Find the specified string block\r
+  //\r
+  Status = FindStringBlock (\r
+             Private,\r
+             StringPackage,\r
+             StringId,\r
+             &BlockType,\r
+             &StringBlockAddr,\r
+             &StringTextOffset,\r
+             NULL\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  LocalFont  = NULL;\r
+  GlobalFont = NULL;\r
+  Referred   = FALSE;\r
+\r
+  //\r
+  // Set the string font according to input font information.\r
+  //\r
+  if (StringFontInfo != NULL) {\r
+    //\r
+    // The input StringFontInfo should exist in current database\r
+    //\r
+    if (!IsFontInfoExisted (Private, StringFontInfo, NULL, NULL, &GlobalFont)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    } else {\r
+      Referred = ReferFontInfoLocally (Private, StringPackage, FALSE, GlobalFont, &LocalFont);\r
+    }\r
+\r
+    //\r
+    // Update the FontId of the specified string block\r
+    //\r
+    switch (BlockType) {\r
+    case EFI_HII_SIBT_STRING_SCSU_FONT:\r
+    case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
+    case EFI_HII_SIBT_STRING_UCS2_FONT:\r
+    case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
+      *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK)) = LocalFont->FontId;\r
+      break;\r
+    default:\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+  }\r
+\r
+  OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
+\r
+  //\r
+  // Set the string text.\r
+  //\r
+  StringTextPtr = StringBlockAddr + StringTextOffset;\r
+  switch (BlockType) {\r
+  case EFI_HII_SIBT_STRING_SCSU:\r
+  case EFI_HII_SIBT_STRING_SCSU_FONT:\r
+  case EFI_HII_SIBT_STRINGS_SCSU:\r
+  case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
+    BlockSize = OldBlockSize + StrLen (String);\r
+    BlockSize -= AsciiStrLen ((CHAR8 *) StringTextPtr);\r
+    Block = AllocateZeroPool (BlockSize);\r
+    if (Block == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);\r
+    BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);\r
+\r
+    while (*String != 0) {\r
+      *BlockPtr++ = (CHAR8) *String++;\r
+    }\r
+    *BlockPtr++ = 0;\r
+\r
+    \r
+    TmpSize = OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+    CopyMem (\r
+      BlockPtr,\r
+      StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr),\r
+      TmpSize\r
+      );\r
+\r
+    SafeFreePool (StringPackage->StringBlock);\r
+    StringPackage->StringBlock = Block;\r
+    StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize);\r
+    break;\r
+\r
+  case EFI_HII_SIBT_STRING_UCS2:\r
+  case EFI_HII_SIBT_STRING_UCS2_FONT:\r
+  case EFI_HII_SIBT_STRINGS_UCS2:\r
+  case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
+    //\r
+    // Use StrSize to store the size of the specified string, including the NULL\r
+    // terminator.\r
+    //\r
+    GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);\r
+\r
+    BlockSize = OldBlockSize + StrSize (String) - StringSize;\r
+    Block = AllocateZeroPool (BlockSize);\r
+    if (Block == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);\r
+    BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);\r
+\r
+    CopyMem (BlockPtr, String, StrSize (String));\r
+    BlockPtr += StrSize (String);\r
+\r
+    CopyMem (\r
+      BlockPtr,\r
+      StringTextPtr + StringSize,\r
+      OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - StringSize\r
+      );\r
+\r
+    SafeFreePool (StringPackage->StringBlock);\r
+    StringPackage->StringBlock = Block;\r
+    StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize);\r
+    break;\r
+\r
+  default:\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Insert a new EFI_HII_SIBT_FONT_BLOCK to the header of string block, if incoming\r
+  // StringFontInfo does not exist in current string package.\r
+  //\r
+  // This new block does not impact on the value of StringId.\r
+  //\r
+  //\r
+  if (StringFontInfo == NULL || Referred) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
+  BlockSize = OldBlockSize + sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16) +\r
+              StrSize (GlobalFont->FontInfo->FontName);\r
+\r
+  Block = AllocateZeroPool (BlockSize);\r
+  if (Block == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  BlockPtr = Block;\r
+  Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;\r
+  Ext2.BlockType2       = EFI_HII_SIBT_FONT;\r
+  Ext2.Length           = (UINT16) (BlockSize - OldBlockSize);\r
+  CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));\r
+  BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);\r
+\r
+  *BlockPtr = LocalFont->FontId;\r
+  BlockPtr += sizeof (UINT8);\r
+  CopyMem (BlockPtr, &GlobalFont->FontInfo->FontSize, sizeof (UINT16));\r
+  BlockPtr += sizeof (UINT16);\r
+  CopyMem (BlockPtr, &GlobalFont->FontInfo->FontStyle, sizeof (UINT32));\r
+  BlockPtr += sizeof (UINT32);\r
+  CopyMem (\r
+    BlockPtr,\r
+    GlobalFont->FontInfo->FontName,\r
+    StrSize (GlobalFont->FontInfo->FontName)\r
+    );\r
+  BlockPtr += StrSize (GlobalFont->FontInfo->FontName);\r
+\r
+  CopyMem (BlockPtr, StringPackage->StringBlock, OldBlockSize);\r
+\r
+  SafeFreePool (StringPackage->StringBlock);\r
+  StringPackage->StringBlock = Block;\r
+  StringPackage->StringPkgHdr->Header.Length += Ext2.Length;\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+  This function adds the string String to the group of strings owned by PackageList, with the\r
+  specified font information StringFontInfo and returns a new string id.\r
+\r
+  @param  This                   A pointer to the EFI_HII_STRING_PROTOCOL instance.\r
+  @param  PackageList            Handle of the package list where this string will\r
+                                 be added.\r
+  @param  StringId               On return, contains the new strings id, which is\r
+                                 unique within PackageList.\r
+  @param  Language               Points to the language for the new string.\r
+  @param  LanguageName           Points to the printable language name to associate\r
+                                 with the passed in  Language field.If LanguageName\r
+                                 is not NULL and the string package header's\r
+                                 LanguageName  associated with a given Language is\r
+                                 not zero, the LanguageName being passed  in will\r
+                                 be ignored.\r
+  @param  String                 Points to the new null-terminated string.\r
+  @param  StringFontInfo         Points to the new string¡¯s font information or\r
+                                 NULL if the string should have the default system\r
+                                 font, size and style.\r
+\r
+  @retval EFI_SUCCESS            The new string was added successfully.\r
+  @retval EFI_NOT_FOUND          The specified PackageList could not be found in\r
+                                 database.\r
+  @retval EFI_OUT_OF_RESOURCES   Could not add the string due to lack of resources.\r
+  @retval EFI_INVALID_PARAMETER  String is NULL or StringId is NULL or Language is\r
+                                 NULL.\r
+  @retval EFI_INVALID_PARAMETER  The specified StringFontInfo does not exist in\r
+                                 current database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiNewString (\r
+  IN  CONST EFI_HII_STRING_PROTOCOL   *This,\r
+  IN  EFI_HII_HANDLE                  PackageList,\r
+  OUT EFI_STRING_ID                   *StringId,\r
+  IN  CONST CHAR8                     *Language,\r
+  IN  CONST CHAR16                    *LanguageName, OPTIONAL\r
+  IN  CONST EFI_STRING                String,\r
+  IN  CONST EFI_FONT_INFO             *StringFontInfo OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  LIST_ENTRY                          *Link;\r
+  BOOLEAN                             Matched;\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  HII_DATABASE_RECORD                 *DatabaseRecord;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
+  HII_STRING_PACKAGE_INSTANCE         *StringPackage;\r
+  UINT32                              HeaderSize;\r
+  UINT32                              BlockSize;\r
+  UINT32                              OldBlockSize;\r
+  UINT8                               *StringBlock;\r
+  UINT8                               *BlockPtr;\r
+  UINT32                              Ucs2BlockSize;\r
+  UINT32                              FontBlockSize;\r
+  UINT32                              Ucs2FontBlockSize;\r
+  EFI_HII_SIBT_EXT2_BLOCK             Ext2;\r
+  HII_FONT_INFO                       *LocalFont;\r
+  HII_GLOBAL_FONT_INFO                *GlobalFont;\r
+\r
+  if (This == NULL || String == NULL || StringId == NULL || Language == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!IsHiiHandleValid (PackageList)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Private    = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  GlobalFont = NULL;\r
+\r
+  //\r
+  // If StringFontInfo specify a paritcular font, it should exist in current database.\r
+  //\r
+  if (StringFontInfo != NULL) {\r
+    if (!IsFontInfoExisted (Private, (EFI_FONT_INFO *) StringFontInfo, NULL, NULL, &GlobalFont)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Get the matching package list.\r
+  //\r
+  PackageListNode = NULL;\r
+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+    DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if (DatabaseRecord->Handle == PackageList) {\r
+      PackageListNode = DatabaseRecord->PackageList;\r
+      break;\r
+    }\r
+  }\r
+  if (PackageListNode == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Try to get the matching string package. Create a new string package when failed.\r
+  //\r
+  StringPackage = NULL;\r
+  Matched       = FALSE;\r
+  for (Link = PackageListNode->StringPkgHdr.ForwardLink;\r
+       Link != &PackageListNode->StringPkgHdr;\r
+       Link = Link->ForwardLink\r
+      ) {\r
+    StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+    if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
+      Matched = TRUE;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (!Matched) {\r
+    //\r
+    // LanguageName is required to create a new string package.\r
+    //\r
+    if (LanguageName == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    StringPackage = AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));\r
+    if (StringPackage == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;\r
+    StringPackage->FontId    = 0;\r
+    InitializeListHead (&StringPackage->FontInfoList);\r
+\r
+    //\r
+    // Fill in the string package header\r
+    //\r
+    HeaderSize = (UINT32) (AsciiStrSize ((CHAR8 *) Language) - 1 + sizeof (EFI_HII_STRING_PACKAGE_HDR));\r
+    StringPackage->StringPkgHdr = AllocateZeroPool (HeaderSize);\r
+    if (StringPackage->StringPkgHdr == NULL) {\r
+      SafeFreePool (StringPackage);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    StringPackage->StringPkgHdr->Header.Type      = EFI_HII_PACKAGE_STRINGS;\r
+    StringPackage->StringPkgHdr->HdrSize          = HeaderSize;\r
+    StringPackage->StringPkgHdr->StringInfoOffset = HeaderSize;\r
+    CopyMem (StringPackage->StringPkgHdr->LanguageWindow, mLanguageWindow, 16 * sizeof (CHAR16));;\r
+    StringPackage->StringPkgHdr->LanguageName     = 1;\r
+    AsciiStrCpy (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language);\r
+\r
+    //\r
+    // Calculate the length of the string blocks, including string block to record\r
+    // printable language full name and EFI_HII_SIBT_END_BLOCK.\r
+    //\r
+    Ucs2BlockSize = (UINT32) (StrSize ((CHAR16 *) LanguageName) +\r
+                              sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16));\r
+\r
+    BlockSize     = Ucs2BlockSize + sizeof (EFI_HII_SIBT_END_BLOCK);\r
+    StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (BlockSize);\r
+    if (StringPackage->StringBlock == NULL) {\r
+      SafeFreePool (StringPackage->StringPkgHdr);\r
+      SafeFreePool (StringPackage);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    //\r
+    // Insert the string block of printable language full name\r
+    //\r
+    BlockPtr  = StringPackage->StringBlock;\r
+    *BlockPtr = EFI_HII_SIBT_STRING_UCS2;\r
+    BlockPtr  += sizeof (EFI_HII_STRING_BLOCK);\r
+    CopyMem (BlockPtr, (EFI_STRING) LanguageName, StrSize ((EFI_STRING) LanguageName));\r
+    BlockPtr += StrSize ((EFI_STRING) LanguageName);\r
+\r
+    //\r
+    // Insert the end block\r
+    //\r
+    *BlockPtr = EFI_HII_SIBT_END;\r
+\r
+    //\r
+    // Append this string package node to string package array in this package list.\r
+    //\r
+    StringPackage->StringPkgHdr->Header.Length    = HeaderSize + BlockSize;\r
+    PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;\r
+    InsertTailList (&PackageListNode->StringPkgHdr, &StringPackage->StringEntry);\r
+\r
+  }\r
+\r
+  //\r
+  // Create a string block and corresponding font block if exists, then append them\r
+  // to the end of the string package.\r
+  //\r
+  Status = FindStringBlock (\r
+             Private,\r
+             StringPackage,\r
+             0,\r
+             NULL,\r
+             NULL,\r
+             NULL,\r
+             StringId\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
+\r
+  if (StringFontInfo == NULL) {\r
+    //\r
+    // Create a EFI_HII_SIBT_STRING_UCS2_BLOCK since font info is not specified.\r
+    //\r
+\r
+    Ucs2BlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK)\r
+                              - sizeof (CHAR16));\r
+\r
+    StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2BlockSize);\r
+    if (StringBlock == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    //\r
+    // Copy original string blocks, except the EFI_HII_SIBT_END.\r
+    //\r
+    CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));\r
+    //\r
+    // Create a EFI_HII_SIBT_STRING_UCS2 block\r
+    //\r
+    BlockPtr  = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);\r
+    *BlockPtr = EFI_HII_SIBT_STRING_UCS2;\r
+    BlockPtr  += sizeof (EFI_HII_STRING_BLOCK);\r
+    CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));\r
+    BlockPtr += StrSize ((EFI_STRING) String);\r
+\r
+    //\r
+    // Append a EFI_HII_SIBT_END block to the end.\r
+    //\r
+    *BlockPtr = EFI_HII_SIBT_END;\r
+    SafeFreePool (StringPackage->StringBlock);\r
+    StringPackage->StringBlock = StringBlock;\r
+    StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize;\r
+    PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize;\r
+\r
+  } else {\r
+    //\r
+    // StringFontInfo is specified here. If there is a EFI_HII_SIBT_FONT_BLOCK\r
+    // which refers to this font info, create a EFI_HII_SIBT_STRING_UCS2_FONT block\r
+    // only. Otherwise create a EFI_HII_SIBT_FONT block with a EFI_HII_SIBT_STRING\r
+    // _UCS2_FONT block.\r
+    //\r
+    Ucs2FontBlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) -\r
+                                  sizeof (CHAR16));\r
+    if (ReferFontInfoLocally (Private, StringPackage, FALSE, GlobalFont, &LocalFont)) {\r
+      //\r
+      // Create a EFI_HII_SIBT_STRING_UCS2_FONT block only.\r
+      //\r
+      StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2FontBlockSize);\r
+      if (StringBlock == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      //\r
+      // Copy original string blocks, except the EFI_HII_SIBT_END.\r
+      //\r
+      CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));\r
+      //\r
+      // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK\r
+      //\r
+      BlockPtr  = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);\r
+      *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;\r
+      BlockPtr  += sizeof (EFI_HII_STRING_BLOCK);\r
+      *BlockPtr = LocalFont->FontId;\r
+      BlockPtr  += sizeof (UINT8);\r
+      CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));\r
+      BlockPtr += StrSize ((EFI_STRING) String);\r
+\r
+      //\r
+      // Append a EFI_HII_SIBT_END block to the end.\r
+      //\r
+      *BlockPtr = EFI_HII_SIBT_END;\r
+      SafeFreePool (StringPackage->StringBlock);\r
+      StringPackage->StringBlock = StringBlock;\r
+      StringPackage->StringPkgHdr->Header.Length += Ucs2FontBlockSize;\r
+      PackageListNode->PackageListHdr.PackageLength += Ucs2FontBlockSize;\r
+\r
+    } else {\r
+      //\r
+      // EFI_HII_SIBT_FONT_BLOCK does not exist in current string package, so\r
+      // create a EFI_HII_SIBT_FONT block to record the font info, then generate\r
+      // a EFI_HII_SIBT_STRING_UCS2_FONT block to record the incoming string.\r
+      //\r
+      FontBlockSize = (UINT32) (StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName) +\r
+                                sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16));\r
+      StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + FontBlockSize + Ucs2FontBlockSize);\r
+      if (StringBlock == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      //\r
+      // Copy original string blocks, except the EFI_HII_SIBT_END.\r
+      //\r
+      CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));\r
+\r
+      //\r
+      // Create a EFI_HII_SIBT_FONT block firstly and then backup its info in string\r
+      // package instance for future reference.\r
+      //\r
+      BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);\r
+\r
+      Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;\r
+      Ext2.BlockType2       = EFI_HII_SIBT_FONT;\r
+      Ext2.Length           = (UINT16) FontBlockSize;\r
+      CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));\r
+      BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);\r
+\r
+      *BlockPtr = LocalFont->FontId;\r
+      BlockPtr += sizeof (UINT8);\r
+      CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontSize, sizeof (UINT16));\r
+      BlockPtr += sizeof (UINT16);\r
+      CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontStyle, sizeof (EFI_HII_FONT_STYLE));\r
+      BlockPtr += sizeof (EFI_HII_FONT_STYLE);\r
+      CopyMem (\r
+        BlockPtr,\r
+        &((EFI_FONT_INFO *) StringFontInfo)->FontName,\r
+        StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName)\r
+        );\r
+\r
+      //\r
+      // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK\r
+      //\r
+      *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;\r
+      BlockPtr  += sizeof (EFI_HII_STRING_BLOCK);\r
+      *BlockPtr = LocalFont->FontId;\r
+      BlockPtr  += sizeof (UINT8);\r
+      CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));\r
+      BlockPtr += StrSize ((EFI_STRING) String);\r
+\r
+      //\r
+      // Append a EFI_HII_SIBT_END block to the end.\r
+      //\r
+      *BlockPtr = EFI_HII_SIBT_END;\r
+      SafeFreePool (StringPackage->StringBlock);\r
+      StringPackage->StringBlock = StringBlock;\r
+      StringPackage->StringPkgHdr->Header.Length += FontBlockSize + Ucs2FontBlockSize;\r
+      PackageListNode->PackageListHdr.PackageLength += FontBlockSize + Ucs2FontBlockSize;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function retrieves the string specified by StringId which is associated\r
+  with the specified PackageList in the language Language and copies it into\r
+  the buffer specified by String.\r
+\r
+  @param  This                   A pointer to the EFI_HII_STRING_PROTOCOL instance.\r
+  @param  Language               Points to the language for the retrieved string.\r
+  @param  PackageList            The package list in the HII database to search for\r
+                                 the  specified string.\r
+  @param  StringId               The string's id, which is unique within\r
+                                 PackageList.\r
+  @param  String                 Points to the new null-terminated string.\r
+  @param  StringSize             On entry, points to the size of the buffer pointed\r
+                                 to by  String, in bytes. On return, points to the\r
+                                 length of the string, in bytes.\r
+  @param  StringFontInfo         If not NULL, points to the string¡¯s font\r
+                                 information.  It's caller's responsibility to free\r
+                                 this buffer.\r
+\r
+  @retval EFI_SUCCESS            The string was returned successfully.\r
+  @retval EFI_NOT_FOUND          The string specified by StringId is not available.\r
+  @retval EFI_NOT_FOUND          The string specified by StringId is available but\r
+                                 not in the specified language.\r
+  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by StringSize is too small to\r
+                                  hold the string.\r
+  @retval EFI_INVALID_PARAMETER  The String or Language or StringSize was NULL.\r
+  @retval EFI_OUT_OF_RESOURCES   There were insufficient resources to complete the\r
+                                 request.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetString (\r
+  IN  CONST EFI_HII_STRING_PROTOCOL   *This,\r
+  IN  CONST CHAR8                     *Language,\r
+  IN  EFI_HII_HANDLE                  PackageList,\r
+  IN  EFI_STRING_ID                   StringId,\r
+  OUT EFI_STRING                      String,\r
+  IN  OUT UINTN                       *StringSize,\r
+  OUT EFI_FONT_INFO                   **StringFontInfo OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  LIST_ENTRY                          *Link;\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  HII_DATABASE_RECORD                 *DatabaseRecord;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
+  HII_STRING_PACKAGE_INSTANCE         *StringPackage;\r
+\r
+  if (This == NULL || Language == NULL || StringId < 1 || StringSize == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (String == NULL && *StringSize != 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!IsHiiHandleValid (PackageList)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  PackageListNode = NULL;\r
+\r
+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+    DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if (DatabaseRecord->Handle == PackageList) {\r
+      PackageListNode = DatabaseRecord->PackageList;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (PackageListNode != NULL) {\r
+    for (Link =  PackageListNode->StringPkgHdr.ForwardLink;\r
+         Link != &PackageListNode->StringPkgHdr;\r
+         Link =  Link->ForwardLink\r
+        ) {\r
+      StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+      if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
+        Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo);\r
+        if (Status != EFI_NOT_FOUND) {\r
+          return Status;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+\r
+/**\r
+  This function updates the string specified by StringId in the specified PackageList to the text\r
+  specified by String and, optionally, the font information specified by StringFontInfo.\r
+\r
+  @param  This                   A pointer to the EFI_HII_STRING_PROTOCOL instance.\r
+  @param  PackageList            The package list containing the strings.\r
+  @param  StringId               The string¡¯s id, which is unique within\r
+                                 PackageList.\r
+  @param  Language               Points to the language for the updated string.\r
+  @param  String                 Points to the new null-terminated string.\r
+  @param  StringFontInfo         Points to the string¡¯s font information or NULL if\r
+                                 the  string font information is not changed.\r
+\r
+  @retval EFI_SUCCESS            The string was updated successfully.\r
+  @retval EFI_NOT_FOUND          The string specified by StringId is not in the\r
+                                 database.\r
+  @retval EFI_INVALID_PARAMETER  The String or Language was NULL.\r
+  @retval EFI_INVALID_PARAMETER  The specified StringFontInfo does not exist in\r
+                                 current database.\r
+  @retval EFI_OUT_OF_RESOURCES   The system is out of resources to accomplish the\r
+                                 task.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiSetString (\r
+  IN CONST EFI_HII_STRING_PROTOCOL    *This,\r
+  IN EFI_HII_HANDLE                   PackageList,\r
+  IN EFI_STRING_ID                    StringId,\r
+  IN CONST CHAR8                      *Language,\r
+  IN CONST EFI_STRING                 String,\r
+  IN CONST EFI_FONT_INFO              *StringFontInfo OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  LIST_ENTRY                          *Link;\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  HII_DATABASE_RECORD                 *DatabaseRecord;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
+  HII_STRING_PACKAGE_INSTANCE         *StringPackage;\r
+  UINT32                              OldPackageLen;\r
+\r
+  if (This == NULL || Language == NULL || StringId < 1 || String == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!IsHiiHandleValid (PackageList)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  PackageListNode = NULL;\r
+\r
+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+    DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if (DatabaseRecord->Handle == PackageList) {\r
+      PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (DatabaseRecord->PackageList);\r
+    }\r
+  }\r
+\r
+  if (PackageListNode != NULL) {\r
+    for (Link =  PackageListNode->StringPkgHdr.ForwardLink;\r
+         Link != &PackageListNode->StringPkgHdr;\r
+         Link =  Link->ForwardLink\r
+        ) {\r
+      StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+      if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
+        OldPackageLen = StringPackage->StringPkgHdr->Header.Length;\r
+        Status = SetStringWorker (\r
+                   Private,\r
+                   StringPackage,\r
+                   StringId,\r
+                   (EFI_STRING) String,\r
+                   (EFI_FONT_INFO *) StringFontInfo\r
+                   );\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+        PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length - OldPackageLen;\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+\r
+/**\r
+  This function returns the list of supported languages, in the format specified\r
+  in Appendix M of UEFI 2.1 spec.\r
+\r
+  @param  This                   A pointer to the EFI_HII_STRING_PROTOCOL instance.\r
+  @param  PackageList            The package list to examine.\r
+  @param  Languages              Points to the buffer to hold the returned string.\r
+  @param  LanguagesSize          On entry, points to the size of the buffer pointed\r
+                                 to by  Languages, in bytes. On  return, points to\r
+                                 the length of Languages, in bytes.\r
+\r
+  @retval EFI_SUCCESS            The languages were returned successfully.\r
+  @retval EFI_INVALID_PARAMETER  The Languages or LanguagesSize was NULL.\r
+  @retval EFI_BUFFER_TOO_SMALL   The LanguagesSize is too small to hold the list of\r
+                                  supported languages. LanguageSize is updated to\r
+                                 contain the required size.\r
+  @retval EFI_NOT_FOUND          Could not find string package in specified\r
+                                 packagelist.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetLanguages (\r
+  IN CONST EFI_HII_STRING_PROTOCOL    *This,\r
+  IN EFI_HII_HANDLE                   PackageList,\r
+  IN OUT CHAR8                        *Languages,\r
+  IN OUT UINTN                        *LanguagesSize\r
+  )\r
+{\r
+  LIST_ENTRY                          *Link;\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  HII_DATABASE_RECORD                 *DatabaseRecord;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
+  HII_STRING_PACKAGE_INSTANCE         *StringPackage;\r
+  UINTN                               ResultSize;\r
+\r
+  if (This == NULL || Languages == NULL || LanguagesSize == NULL || PackageList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (!IsHiiHandleValid (PackageList)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  PackageListNode = NULL;\r
+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+    DatabaseRecord  = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if (DatabaseRecord->Handle == PackageList) {\r
+      PackageListNode = DatabaseRecord->PackageList;\r
+      break;\r
+    }\r
+  }\r
+  if (PackageListNode == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Search the languages in the specified packagelist.\r
+  //\r
+  ResultSize = 0;\r
+  for (Link = PackageListNode->StringPkgHdr.ForwardLink;\r
+       Link != &PackageListNode->StringPkgHdr;\r
+       Link = Link->ForwardLink\r
+      ) {\r
+    StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+    ResultSize += AsciiStrSize (StringPackage->StringPkgHdr->Language);\r
+    if (ResultSize < *LanguagesSize) {\r
+      AsciiStrCpy (Languages, StringPackage->StringPkgHdr->Language);\r
+      Languages += AsciiStrSize (StringPackage->StringPkgHdr->Language);\r
+      *(Languages - 1) = L';';\r
+    }\r
+  }\r
+  if (ResultSize == 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (*LanguagesSize < ResultSize) {\r
+    *LanguagesSize = ResultSize;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  *(Languages - 1) = 0;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Each string package has associated with it a single primary language and zero\r
+  or more secondary languages. This routine returns the secondary languages\r
+  associated with a package list.\r
+\r
+  @param  This                   A pointer to the EFI_HII_STRING_PROTOCOL instance.\r
+  @param  PackageList            The package list to examine.\r
+  @param  FirstLanguage          Points to the primary language.\r
+  @param  SecondaryLanguages     Points to the buffer to hold the returned list of\r
+                                 secondary languages for the specified\r
+                                 FirstLanguage. If there are no secondary\r
+                                 languages, the function  returns successfully, but\r
+                                 this is set to NULL.\r
+  @param  SecondaryLanguageSize  On entry, points to the size of the buffer pointed\r
+                                 to  by SecondLanguages, in bytes. On return,\r
+                                 points to the length of SecondLanguages in bytes.\r
+\r
+  @retval EFI_SUCCESS            Secondary languages were correctly returned.\r
+  @retval EFI_INVALID_PARAMETER  FirstLanguage or SecondLanguages or\r
+                                 SecondLanguagesSize was NULL.\r
+  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by SecondLanguagesSize is\r
+                                 too small to hold the returned information.\r
+                                 SecondLanguageSize is updated to hold the size of\r
+                                 the buffer required.\r
+  @retval EFI_NOT_FOUND          The language specified by FirstLanguage is not\r
+                                 present in the specified package list.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetSecondaryLanguages (\r
+  IN CONST EFI_HII_STRING_PROTOCOL   *This,\r
+  IN EFI_HII_HANDLE                  PackageList,\r
+  IN CONST CHAR8                     *FirstLanguage,\r
+  IN OUT CHAR8                       *SecondLanguages,\r
+  IN OUT UINTN                       *SecondLanguagesSize\r
+  )\r
+{\r
+  LIST_ENTRY                          *Link;\r
+  LIST_ENTRY                          *Link1;\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  HII_DATABASE_RECORD                 *DatabaseRecord;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
+  HII_STRING_PACKAGE_INSTANCE         *StringPackage;\r
+  CHAR8                               *Languages;\r
+  UINTN                               ResultSize;\r
+\r
+  if (This == NULL || PackageList == NULL || FirstLanguage == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (SecondLanguages == NULL || SecondLanguagesSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (!IsHiiHandleValid (PackageList)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Private    = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  Languages  = NULL;\r
+  ResultSize = 0;\r
+\r
+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+    DatabaseRecord  = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if (DatabaseRecord->Handle == PackageList) {\r
+      PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (DatabaseRecord->PackageList);\r
+      for (Link1 = PackageListNode->StringPkgHdr.ForwardLink;\r
+           Link1 != &PackageListNode->StringPkgHdr;\r
+           Link1 = Link1->ForwardLink\r
+          ) {\r
+        StringPackage = CR (Link1, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+        if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) FirstLanguage)) {\r
+          Languages = StringPackage->StringPkgHdr->Language;\r
+          //\r
+          // Language is a series of ';' terminated strings, first one is primary\r
+          // language and following with other secondary languages or NULL if no\r
+          // secondary languages any more.\r
+          //\r
+          Languages = AsciiStrStr (Languages, ";");\r
+          if (Languages == NULL) {\r
+            break;\r
+          }\r
+          Languages++;\r
+\r
+          ResultSize = AsciiStrSize (Languages);\r
+          if (ResultSize <= *SecondLanguagesSize) {\r
+            AsciiStrCpy (SecondLanguages, Languages);\r
+          } else {\r
+            *SecondLanguagesSize = ResultSize;\r
+            return EFI_BUFFER_TOO_SMALL;\r
+          }\r
+\r
+          return EFI_SUCCESS;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h b/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h
new file mode 100644 (file)
index 0000000..1b355ec
--- /dev/null
@@ -0,0 +1,55 @@
+/** @file
+
+Copyright (c) 2004, Intel Corporation
+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.
+
+Module Name:
+
+  Colors.h
+
+Abstract:
+
+
+Revision History
+
+
+**/
+
+#ifndef _COLORS_H
+#define _COLORS_H
+
+//
+// Screen Color Settings
+//
+#define PICKLIST_HIGHLIGHT_TEXT       EFI_WHITE
+#define PICKLIST_HIGHLIGHT_BACKGROUND EFI_BACKGROUND_CYAN
+#define TITLE_TEXT                    EFI_WHITE
+#define TITLE_BACKGROUND              EFI_BACKGROUND_BLUE
+#define KEYHELP_TEXT                  EFI_LIGHTGRAY
+#define KEYHELP_BACKGROUND            EFI_BACKGROUND_BLACK
+#define SUBTITLE_TEXT                 EFI_BLUE
+#define SUBTITLE_BACKGROUND           EFI_BACKGROUND_LIGHTGRAY
+#define BANNER_TEXT                   EFI_BLUE
+#define BANNER_BACKGROUND             EFI_BACKGROUND_LIGHTGRAY
+#define FIELD_TEXT                    EFI_BLACK
+#define FIELD_TEXT_GRAYED             EFI_DARKGRAY
+#define FIELD_BACKGROUND              EFI_BACKGROUND_LIGHTGRAY
+#define FIELD_TEXT_HIGHLIGHT          EFI_LIGHTGRAY
+#define FIELD_BACKGROUND_HIGHLIGHT    EFI_BACKGROUND_BLACK
+#define POPUP_TEXT                    EFI_LIGHTGRAY
+#define POPUP_BACKGROUND              EFI_BACKGROUND_BLUE
+#define POPUP_INVERSE_TEXT            EFI_LIGHTGRAY
+#define POPUP_INVERSE_BACKGROUND      EFI_BACKGROUND_BLACK
+#define HELP_TEXT                     EFI_BLUE
+#define ERROR_TEXT                    EFI_RED | EFI_BRIGHT
+#define INFO_TEXT                     EFI_YELLOW | EFI_BRIGHT
+#define ARROW_TEXT                    EFI_RED | EFI_BRIGHT
+#define ARROW_BACKGROUND              EFI_BACKGROUND_LIGHTGRAY
+
+#endif
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
new file mode 100644 (file)
index 0000000..adeada2
--- /dev/null
@@ -0,0 +1,1938 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+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.
+
+Module Name:
+
+  Expression.c
+
+Abstract:
+
+  Expression evaluation.
+
+
+**/
+
+#include "Ui.h"
+#include "Setup.h"
+
+//
+// Global stack used to evaluate boolean expresions
+//
+EFI_HII_VALUE *mOpCodeScopeStack = NULL;
+EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;
+EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
+
+EFI_HII_VALUE *mExpressionEvaluationStack = NULL;
+EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;
+EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;
+
+//
+// Unicode collation protocol interface
+//
+EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
+
+
+/**
+  Grow size of the stack
+
+  @param  Stack                  On input: old stack; On output: new stack
+  @param  StackPtr               On input: old stack pointer; On output: new stack
+                                 pointer
+  @param  StackPtr               On input: old stack end; On output: new stack end
+
+  @retval EFI_SUCCESS            Grow stack success.
+  @retval EFI_OUT_OF_RESOURCES   No enough memory for stack space.
+
+**/
+STATIC
+EFI_STATUS
+GrowStack (
+  IN OUT EFI_HII_VALUE  **Stack,
+  IN OUT EFI_HII_VALUE  **StackPtr,
+  IN OUT EFI_HII_VALUE  **StackEnd
+  )
+{
+  UINTN           Size;
+  EFI_HII_VALUE  *NewStack;
+
+  Size = EXPRESSION_STACK_SIZE_INCREMENT;
+  if (*StackPtr != NULL) {
+    Size = Size + (*StackEnd - *Stack);
+  }
+
+  NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));
+  if (NewStack == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  if (*StackPtr != NULL) {
+    //
+    // Copy from Old Stack to the New Stack
+    //
+    CopyMem (
+      NewStack,
+      *Stack,
+      (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)
+      );
+
+    //
+    // Free The Old Stack
+    //
+    gBS->FreePool (*Stack);
+  }
+
+  //
+  // Make the Stack pointer point to the old data in the new stack
+  //
+  *StackPtr = NewStack + (*StackPtr - *Stack);
+  *Stack    = NewStack;
+  *StackEnd = NewStack + Size;
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Push an element onto the Boolean Stack
+
+  @param  Stack                  On input: old stack; On output: new stack
+  @param  StackPtr               On input: old stack pointer; On output: new stack
+                                 pointer
+  @param  StackPtr               On input: old stack end; On output: new stack end
+  @param  Data                   Data to push.
+
+  @retval EFI_SUCCESS            Push stack success.
+
+**/
+EFI_STATUS
+PushStack (
+  IN OUT EFI_HII_VALUE       **Stack,
+  IN OUT EFI_HII_VALUE       **StackPtr,
+  IN OUT EFI_HII_VALUE       **StackEnd,
+  IN EFI_HII_VALUE           *Data
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Check for a stack overflow condition
+  //
+  if (*StackPtr >= *StackEnd) {
+    //
+    // Grow the stack
+    //
+    Status = GrowStack (Stack, StackPtr, StackEnd);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  //
+  // Push the item onto the stack
+  //
+  CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));
+  *StackPtr = *StackPtr + 1;
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Pop an element from the stack.
+
+  @param  Stack                  On input: old stack; On output: new stack
+  @param  StackPtr               On input: old stack pointer; On output: new stack
+                                 pointer
+  @param  StackPtr               On input: old stack end; On output: new stack end
+  @param  Data                   Data to pop.
+
+  @retval EFI_SUCCESS            The value was popped onto the stack.
+  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
+
+**/
+EFI_STATUS
+PopStack (
+  IN OUT EFI_HII_VALUE       **Stack,
+  IN OUT EFI_HII_VALUE       **StackPtr,
+  IN OUT EFI_HII_VALUE       **StackEnd,
+  OUT EFI_HII_VALUE          *Data
+  )
+{
+  //
+  // Check for a stack underflow condition
+  //
+  if (*StackPtr == *Stack) {
+    return EFI_ACCESS_DENIED;
+  }
+
+  //
+  // Pop the item off the stack
+  //
+  *StackPtr = *StackPtr - 1;
+  CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Reset stack pointer to begin of the stack.
+
+  None.
+
+  @return None.
+
+**/
+VOID
+ResetScopeStack (
+  VOID
+  )
+{
+  mOpCodeScopeStackPointer = mOpCodeScopeStack;
+}
+
+
+/**
+  Push an Operand onto the Stack
+
+  @param  Operand                Operand to push.
+
+  @retval EFI_SUCCESS            The value was pushed onto the stack.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
+                                 stack.
+
+**/
+EFI_STATUS
+PushScope (
+  IN UINT8   Operand
+  )
+{
+  EFI_HII_VALUE  Data;
+
+  Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;
+  Data.Value.u8 = Operand;
+
+  return PushStack (
+           &mOpCodeScopeStack,
+           &mOpCodeScopeStackPointer,
+           &mOpCodeScopeStackEnd,
+           &Data
+           );
+}
+
+
+/**
+  Pop an Operand from the Stack
+
+  @param  Operand                Operand to pop.
+
+  @retval EFI_SUCCESS            The value was pushed onto the stack.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
+                                 stack.
+
+**/
+EFI_STATUS
+PopScope (
+  OUT UINT8     *Operand
+  )
+{
+  EFI_STATUS     Status;
+  EFI_HII_VALUE  Data;
+
+  Status = PopStack (
+             &mOpCodeScopeStack,
+             &mOpCodeScopeStackPointer,
+             &mOpCodeScopeStackEnd,
+             &Data
+             );
+
+  *Operand = Data.Value.u8;
+
+  return Status;
+}
+
+
+/**
+  Reset stack pointer to begin of the stack.
+
+  None.
+
+  @return None.
+
+**/
+VOID
+ResetExpressionStack (
+  VOID
+  )
+{
+  mExpressionEvaluationStackPointer = mExpressionEvaluationStack;
+}
+
+
+/**
+  Push an Expression value onto the Stack
+
+  @param  Value                  Expression value to push.
+
+  @retval EFI_SUCCESS            The value was pushed onto the stack.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
+                                 stack.
+
+**/
+EFI_STATUS
+PushExpression (
+  IN EFI_HII_VALUE  *Value
+  )
+{
+  return PushStack (
+           &mExpressionEvaluationStack,
+           &mExpressionEvaluationStackPointer,
+           &mExpressionEvaluationStackEnd,
+           Value
+           );
+}
+
+
+/**
+  Pop an Expression value from the stack.
+
+  @param  Value                  Expression value to pop.
+
+  @retval EFI_SUCCESS            The value was popped onto the stack.
+  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
+
+**/
+EFI_STATUS
+PopExpression (
+  OUT EFI_HII_VALUE  *Value
+  )
+{
+  return PopStack (
+           &mExpressionEvaluationStack,
+           &mExpressionEvaluationStackPointer,
+           &mExpressionEvaluationStackEnd,
+           Value
+           );
+}
+
+
+/**
+  Get Form given its FormId.
+
+  @param  FormSet                The formset which contains this form.
+  @param  FormId                 Id of this form.
+
+  @retval Pointer                The form.
+  @retval NULL                   Specified Form is not found in the formset.
+
+**/
+FORM_BROWSER_FORM *
+IdToForm (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  IN UINT16                FormId
+)
+{
+  LIST_ENTRY         *Link;
+  FORM_BROWSER_FORM  *Form;
+
+  Link = GetFirstNode (&FormSet->FormListHead);
+  while (!IsNull (&FormSet->FormListHead, Link)) {
+    Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+
+    if (Form->FormId == FormId) {
+      return Form;
+    }
+
+    Link = GetNextNode (&FormSet->FormListHead, Link);
+  }
+
+  return NULL;
+}
+
+
+/**
+  Search a Question in Form scope using its QuestionId.
+
+  @param  Form                   The form which contains this Question.
+  @param  QuestionId             Id of this Question.
+
+  @retval Pointer                The Question.
+  @retval NULL                   Specified Question not found in the form.
+
+**/
+FORM_BROWSER_STATEMENT *
+IdToQuestion2 (
+  IN FORM_BROWSER_FORM  *Form,
+  IN UINT16             QuestionId
+  )
+{
+  LIST_ENTRY              *Link;
+  FORM_BROWSER_STATEMENT  *Question;
+
+  if (QuestionId == 0) {
+    //
+    // The value of zero is reserved
+    //
+    return NULL;
+  }
+
+  Link = GetFirstNode (&Form->StatementListHead);
+  while (!IsNull (&Form->StatementListHead, Link)) {
+    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+
+    if (Question->QuestionId == QuestionId) {
+      return Question;
+    }
+
+    Link = GetNextNode (&Form->StatementListHead, Link);
+  }
+
+  return NULL;
+}
+
+
+/**
+  Search a Question in Formset scope using its QuestionId.
+
+  @param  FormSet                The formset which contains this form.
+  @param  Form                   The form which contains this Question.
+  @param  QuestionId             Id of this Question.
+
+  @retval Pointer                The Question.
+  @retval NULL                   Specified Question not found in the form.
+
+**/
+FORM_BROWSER_STATEMENT *
+IdToQuestion (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  IN FORM_BROWSER_FORM     *Form,
+  IN UINT16                QuestionId
+  )
+{
+  LIST_ENTRY              *Link;
+  FORM_BROWSER_STATEMENT  *Question;
+
+  //
+  // Search in the form scope first
+  //
+  Question = IdToQuestion2 (Form, QuestionId);
+  if (Question != NULL) {
+    return Question;
+  }
+
+  //
+  // Search in the formset scope
+  //
+  Link = GetFirstNode (&FormSet->FormListHead);
+  while (!IsNull (&FormSet->FormListHead, Link)) {
+    Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+
+    Question = IdToQuestion2 (Form, QuestionId);
+    if (Question != NULL) {
+      return Question;
+    }
+
+    Link = GetNextNode (&FormSet->FormListHead, Link);
+  }
+
+  return NULL;
+}
+
+
+/**
+  Get Expression given its RuleId.
+
+  @param  Form                   The form which contains this Expression.
+  @param  RuleId                 Id of this Expression.
+
+  @retval Pointer                The Expression.
+  @retval NULL                   Specified Expression not found in the form.
+
+**/
+FORM_EXPRESSION *
+RuleIdToExpression (
+  IN FORM_BROWSER_FORM  *Form,
+  IN UINT8              RuleId
+  )
+{
+  LIST_ENTRY       *Link;
+  FORM_EXPRESSION  *Expression;
+
+  Link = GetFirstNode (&Form->ExpressionListHead);
+  while (!IsNull (&Form->ExpressionListHead, Link)) {
+    Expression = FORM_EXPRESSION_FROM_LINK (Link);
+
+    if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {
+      return Expression;
+    }
+
+    Link = GetNextNode (&Form->ExpressionListHead, Link);
+  }
+
+  return NULL;
+}
+
+
+/**
+  Locate the Unicode Collation Protocol interface for later use.
+
+  None.
+
+  @retval EFI_SUCCESS            Protocol interface initialize success.
+  @retval Other                  Protocol interface initialize failed.
+
+**/
+EFI_STATUS
+InitializeUnicodeCollationProtocol (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  if (mUnicodeCollation != NULL) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
+  // instances first and then select one which support English language.
+  // Current implementation just pick the first instance.
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiUnicodeCollation2ProtocolGuid,
+                  NULL,
+                  (VOID **) &mUnicodeCollation
+                  );
+  return Status;
+}
+
+VOID
+IfrStrToUpper (
+  CHAR16                   *String
+  )
+{
+  while (*String != 0) {
+    if ((*String >= 'a') && (*String <= 'z')) {
+      *String = (UINT16) ((*String) & ((UINT16) ~0x20));
+    }
+    String++;
+  }
+}
+
+
+/**
+  Evaluate opcode EFI_IFR_TO_STRING.
+
+  @param  FormSet                Formset which contains this opcode.
+  @param  Format                 String format in EFI_IFR_TO_STRING.
+  @param  Result                 Evaluation result for this opcode.
+
+  @retval EFI_SUCCESS            Opcode evaluation success.
+  @retval Other                  Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrToString (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  IN UINT8                 Format,
+  OUT  EFI_HII_VALUE       *Result
+  )
+{
+  EFI_STATUS     Status;
+  EFI_HII_VALUE  Value;
+  CHAR16         *String;
+  CHAR16         *PrintFormat;
+  CHAR16         Buffer[MAXIMUM_VALUE_CHARACTERS];
+  UINTN          BufferSize;
+
+  Status = PopExpression (&Value);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  switch (Value.Type) {
+  case EFI_IFR_TYPE_NUM_SIZE_8:
+  case EFI_IFR_TYPE_NUM_SIZE_16:
+  case EFI_IFR_TYPE_NUM_SIZE_32:
+  case EFI_IFR_TYPE_NUM_SIZE_64:
+    BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);
+    switch (Format) {
+    case EFI_IFR_STRING_UNSIGNED_DEC:
+    case EFI_IFR_STRING_SIGNED_DEC:
+      PrintFormat = L"%ld";
+      break;
+
+    case EFI_IFR_STRING_LOWERCASE_HEX:
+      PrintFormat = L"%lx";
+      break;
+
+    case EFI_IFR_STRING_UPPERCASE_HEX:
+      PrintFormat = L"%lX";
+      break;
+
+    default:
+      return EFI_UNSUPPORTED;
+    }
+    UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);
+    String = Buffer;
+    break;
+
+  case EFI_IFR_TYPE_STRING:
+    CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
+    return EFI_SUCCESS;
+
+  case EFI_IFR_TYPE_BOOLEAN:
+    String = (Value.Value.b) ? L"True" : L"False";
+    break;
+
+  default:
+    return EFI_UNSUPPORTED;
+  }
+
+  Result->Type = EFI_IFR_TYPE_STRING;
+  Result->Value.string = NewString (String, FormSet->HiiHandle);
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Evaluate opcode EFI_IFR_TO_UINT.
+
+  @param  FormSet                Formset which contains this opcode.
+  @param  Result                 Evaluation result for this opcode.
+
+  @retval EFI_SUCCESS            Opcode evaluation success.
+  @retval Other                  Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrToUint (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  OUT  EFI_HII_VALUE       *Result
+  )
+{
+  EFI_STATUS     Status;
+  EFI_HII_VALUE  Value;
+  CHAR16         *String;
+  CHAR16         *StringPtr;
+  UINTN          BufferSize;
+
+  Status = PopExpression (&Value);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (Value.Type >= EFI_IFR_TYPE_OTHER) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = EFI_SUCCESS;
+  if (Value.Type == EFI_IFR_TYPE_STRING) {
+    String = GetToken (Value.Value.string, FormSet->HiiHandle);
+    if (String == NULL) {
+      return EFI_NOT_FOUND;
+    }
+
+    IfrStrToUpper (String);
+    StringPtr = StrStr (String, L"0X");
+    if (StringPtr != NULL) {
+      //
+      // Hex string
+      //
+      BufferSize = sizeof (UINT64);
+      Status = R8_HexStringToBuf ((UINT8 *) &Result->Value.u64, &BufferSize, StringPtr + 2, NULL);
+    } else {
+      //
+      // BUGBUG: Need handle decimal string
+      //
+    }
+    gBS->FreePool (String);
+  } else {
+    CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
+  }
+
+  Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+  return Status;
+}
+
+
+/**
+  Evaluate opcode EFI_IFR_CATENATE.
+
+  @param  FormSet                Formset which contains this opcode.
+  @param  Result                 Evaluation result for this opcode.
+
+  @retval EFI_SUCCESS            Opcode evaluation success.
+  @retval Other                  Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrCatenate (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  OUT  EFI_HII_VALUE       *Result
+  )
+{
+  EFI_STATUS     Status;
+  EFI_HII_VALUE  Value;
+  CHAR16         *String[2];
+  UINTN          Index;
+  CHAR16         *StringPtr;
+  UINTN          Size;
+
+  //
+  // String[0] - The second string
+  // String[1] - The first string
+  //
+  String[0] = NULL;
+  String[1] = NULL;
+  StringPtr = NULL;
+  Status = EFI_SUCCESS;
+
+  for (Index = 0; Index < 2; Index++) {
+    Status = PopExpression (&Value);
+    if (EFI_ERROR (Status)) {
+      goto Done;
+    }
+
+    if (Value.Type != EFI_IFR_TYPE_STRING) {
+      Status = EFI_UNSUPPORTED;
+      goto Done;
+    }
+
+    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
+    if (String== NULL) {
+      Status = EFI_NOT_FOUND;
+      goto Done;
+    }
+  }
+
+  Size = StrSize (String[0]);
+  StringPtr= AllocatePool (StrSize (String[1]) + Size);
+  ASSERT (StringPtr != NULL);
+  StrCpy (StringPtr, String[1]);
+  StrCat (StringPtr, String[0]);
+
+  Result->Type = EFI_IFR_TYPE_STRING;
+  Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);
+
+Done:
+  SafeFreePool (String[0]);
+  SafeFreePool (String[1]);
+  SafeFreePool (StringPtr);
+
+  return Status;
+}
+
+
+/**
+  Evaluate opcode EFI_IFR_MATCH.
+
+  @param  FormSet                Formset which contains this opcode.
+  @param  Result                 Evaluation result for this opcode.
+
+  @retval EFI_SUCCESS            Opcode evaluation success.
+  @retval Other                  Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrMatch (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  OUT  EFI_HII_VALUE       *Result
+  )
+{
+  EFI_STATUS     Status;
+  EFI_HII_VALUE  Value;
+  CHAR16         *String[2];
+  UINTN          Index;
+
+  //
+  // String[0] - The string to search
+  // String[1] - pattern
+  //
+  String[0] = NULL;
+  String[1] = NULL;
+  Status = EFI_SUCCESS;
+  for (Index = 0; Index < 2; Index++) {
+    Status = PopExpression (&Value);
+    if (EFI_ERROR (Status)) {
+      goto Done;
+    }
+
+    if (Value.Type != EFI_IFR_TYPE_STRING) {
+      Status = EFI_UNSUPPORTED;
+      goto Done;
+    }
+
+    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
+    if (String== NULL) {
+      Status = EFI_NOT_FOUND;
+      goto Done;
+    }
+  }
+
+  Result->Type = EFI_IFR_TYPE_BOOLEAN;
+  Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);
+
+Done:
+  SafeFreePool (String[0]);
+  SafeFreePool (String[1]);
+
+  return Status;
+}
+
+
+/**
+  Evaluate opcode EFI_IFR_FIND.
+
+  @param  FormSet                Formset which contains this opcode.
+  @param  Format                 Case sensitive or insensitive.
+  @param  Result                 Evaluation result for this opcode.
+
+  @retval EFI_SUCCESS            Opcode evaluation success.
+  @retval Other                  Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrFind (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  IN UINT8                 Format,
+  OUT  EFI_HII_VALUE       *Result
+  )
+{
+  EFI_STATUS     Status;
+  EFI_HII_VALUE  Value;
+  CHAR16         *String[2];
+  UINTN          Base;
+  CHAR16         *StringPtr;
+  UINTN          Index;
+
+  if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = PopExpression (&Value);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+    return EFI_UNSUPPORTED;
+  }
+  Base = (UINTN) Value.Value.u64;
+
+  //
+  // String[0] - sub-string
+  // String[1] - The string to search
+  //
+  String[0] = NULL;
+  String[1] = NULL;
+  for (Index = 0; Index < 2; Index++) {
+    Status = PopExpression (&Value);
+    if (EFI_ERROR (Status)) {
+      goto Done;
+    }
+
+    if (Value.Type != EFI_IFR_TYPE_STRING) {
+      Status = EFI_UNSUPPORTED;
+      goto Done;
+    }
+
+    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
+    if (String== NULL) {
+      Status = EFI_NOT_FOUND;
+      goto Done;
+    }
+
+    if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {
+      //
+      // Case insensitive, convert both string to upper case
+      //
+      IfrStrToUpper (String[Index]);
+    }
+  }
+
+  Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+  if (Base >= StrLen (String[1])) {
+    Result->Value.u64 = 0xFFFFFFFFFFFFFFFF;
+  } else {
+    StringPtr = StrStr (String[1] + Base, String[0]);
+    Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFF : (StringPtr - String[1]);
+  }
+
+Done:
+  SafeFreePool (String[0]);
+  SafeFreePool (String[1]);
+
+  return Status;
+}
+
+
+/**
+  Evaluate opcode EFI_IFR_MID.
+
+  @param  FormSet                Formset which contains this opcode.
+  @param  Result                 Evaluation result for this opcode.
+
+  @retval EFI_SUCCESS            Opcode evaluation success.
+  @retval Other                  Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrMid (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  OUT  EFI_HII_VALUE       *Result
+  )
+{
+  EFI_STATUS     Status;
+  EFI_HII_VALUE  Value;
+  CHAR16         *String;
+  UINTN          Base;
+  UINTN          Length;
+  CHAR16         *SubString;
+
+  Status = PopExpression (&Value);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+    return EFI_UNSUPPORTED;
+  }
+  Length = (UINTN) Value.Value.u64;
+
+  Status = PopExpression (&Value);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+    return EFI_UNSUPPORTED;
+  }
+  Base = (UINTN) Value.Value.u64;
+
+  Status = PopExpression (&Value);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  if (Value.Type != EFI_IFR_TYPE_STRING) {
+    return EFI_UNSUPPORTED;
+  }
+  String = GetToken (Value.Value.string, FormSet->HiiHandle);
+  if (String == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  if (Length == 0 || Base >= StrLen (String)) {
+    SubString = gEmptyString;
+  } else {
+    SubString = String + Base;
+    if ((Base + Length) < StrLen (String)) {
+      SubString[Length] = L'\0';
+    }
+  }
+
+  Result->Type = EFI_IFR_TYPE_STRING;
+  Result->Value.string = NewString (SubString, FormSet->HiiHandle);
+
+  gBS->FreePool (String);
+
+  return Status;
+}
+
+
+/**
+  Evaluate opcode EFI_IFR_TOKEN.
+
+  @param  FormSet                Formset which contains this opcode.
+  @param  Result                 Evaluation result for this opcode.
+
+  @retval EFI_SUCCESS            Opcode evaluation success.
+  @retval Other                  Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrToken (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  OUT  EFI_HII_VALUE       *Result
+  )
+{
+  EFI_STATUS     Status;
+  EFI_HII_VALUE  Value;
+  CHAR16         *String[2];
+  UINTN          Count;
+  CHAR16         *Delimiter;
+  CHAR16         *SubString;
+  CHAR16         *StringPtr;
+  UINTN          Index;
+
+  Status = PopExpression (&Value);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+    return EFI_UNSUPPORTED;
+  }
+  Count = (UINTN) Value.Value.u64;
+
+  //
+  // String[0] - Delimiter
+  // String[1] - The string to search
+  //
+  String[0] = NULL;
+  String[1] = NULL;
+  for (Index = 0; Index < 2; Index++) {
+    Status = PopExpression (&Value);
+    if (EFI_ERROR (Status)) {
+      goto Done;
+    }
+
+    if (Value.Type != EFI_IFR_TYPE_STRING) {
+      Status = EFI_UNSUPPORTED;
+      goto Done;
+    }
+
+    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
+    if (String== NULL) {
+      Status = EFI_NOT_FOUND;
+      goto Done;
+    }
+  }
+
+  Delimiter = String[0];
+  SubString = String[1];
+  while (Count > 0) {
+    SubString = StrStr (SubString, Delimiter);
+    if (SubString != NULL) {
+      //
+      // Skip over the delimiter
+      //
+      SubString = SubString + StrLen (Delimiter);
+    } else {
+      break;
+    }
+    Count--;
+  }
+
+  if (SubString == NULL) {
+    //
+    // nth delimited sub-string not found, push an empty string
+    //
+    SubString = gEmptyString;
+  } else {
+    //
+    // Put a NULL terminator for nth delimited sub-string
+    //
+    StringPtr = StrStr (SubString, Delimiter);
+    if (StringPtr != NULL) {
+      *StringPtr = L'\0';
+    }
+  }
+
+  Result->Type = EFI_IFR_TYPE_STRING;
+  Result->Value.string = NewString (SubString, FormSet->HiiHandle);
+
+Done:
+  SafeFreePool (String[0]);
+  SafeFreePool (String[1]);
+
+  return Status;
+}
+
+
+/**
+  Evaluate opcode EFI_IFR_SPAN.
+
+  @param  FormSet                Formset which contains this opcode.
+  @param  Flags                  FIRST_MATCHING or FIRST_NON_MATCHING.
+  @param  Result                 Evaluation result for this opcode.
+
+  @retval EFI_SUCCESS            Opcode evaluation success.
+  @retval Other                  Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrSpan (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  IN UINT8                 Flags,
+  OUT  EFI_HII_VALUE       *Result
+  )
+{
+  EFI_STATUS     Status;
+  EFI_HII_VALUE  Value;
+  CHAR16         *String[2];
+  CHAR16         *Charset;
+  UINTN          Base;
+  UINTN          Index;
+  CHAR16         *StringPtr;
+  BOOLEAN        Found;
+
+  Status = PopExpression (&Value);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+    return EFI_UNSUPPORTED;
+  }
+  Base = (UINTN) Value.Value.u64;
+
+  //
+  // String[0] - Charset
+  // String[1] - The string to search
+  //
+  String[0] = NULL;
+  String[1] = NULL;
+  for (Index = 0; Index < 2; Index++) {
+    Status = PopExpression (&Value);
+    if (EFI_ERROR (Status)) {
+      goto Done;
+    }
+
+    if (Value.Type != EFI_IFR_TYPE_STRING) {
+      Status = EFI_UNSUPPORTED;
+      goto Done;
+    }
+
+    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
+    if (String== NULL) {
+      Status = EFI_NOT_FOUND;
+      goto Done;
+    }
+  }
+
+  if (Base >= StrLen (String[1])) {
+    Status = EFI_UNSUPPORTED;
+    goto Done;
+  }
+
+  Found = FALSE;
+  StringPtr = String[1] + Base;
+  Charset = String[0];
+  while (*StringPtr != 0 && !Found) {
+    Index = 0;
+    while (Charset[Index] != 0) {
+      if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {
+        if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {
+          Found = TRUE;
+          break;
+        }
+      } else {
+        if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {
+          Found = TRUE;
+          break;
+        }
+      }
+      //
+      // Skip characters pair representing low-end of a range and high-end of a range
+      //
+      Index += 2;
+    }
+
+    if (!Found) {
+      StringPtr++;
+    }
+  }
+
+  Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+  Result->Value.u64 = StringPtr - String[1];
+
+Done:
+  SafeFreePool (String[0]);
+  SafeFreePool (String[1]);
+
+  return Status;
+}
+
+
+/**
+  Zero extend integer/boolean/date/time to UINT64 for comparing.
+
+  @param  Value                  HII Value to be converted.
+
+  @return None.
+
+**/
+VOID
+ExtendValueToU64 (
+  IN  EFI_HII_VALUE   *Value
+  )
+{
+  UINT64  Temp;
+
+  Temp = 0;
+  switch (Value->Type) {
+  case EFI_IFR_TYPE_NUM_SIZE_8:
+    Temp = Value->Value.u8;
+    break;
+
+  case EFI_IFR_TYPE_NUM_SIZE_16:
+    Temp = Value->Value.u16;
+    break;
+
+  case EFI_IFR_TYPE_NUM_SIZE_32:
+    Temp = Value->Value.u32;
+    break;
+
+  case EFI_IFR_TYPE_BOOLEAN:
+    Temp = Value->Value.b;
+    break;
+
+  case EFI_IFR_TYPE_TIME:
+    Temp = Value->Value.u32 & 0xffffff;
+    break;
+
+  case EFI_IFR_TYPE_DATE:
+    Temp = Value->Value.u32;
+    break;
+
+  default:
+    return;
+  }
+
+  Value->Value.u64 = Temp;
+}
+
+
+/**
+  Compare two Hii value.
+
+  @param  Value1                 Expression value to compare on left-hand
+  @param  Value2                 Expression value to compare on right-hand
+  @param  HiiHandle              Only required for string compare
+
+  @retval EFI_INVALID_PARAMETER  Could not perform comparation on two values
+  @retval 0                      Two operators equeal
+  @retval 0                      Value1 is greater than Value2
+  @retval 0                      Value1 is less than Value2
+
+**/
+INTN
+CompareHiiValue (
+  IN  EFI_HII_VALUE   *Value1,
+  IN  EFI_HII_VALUE   *Value2,
+  IN  EFI_HII_HANDLE  HiiHandle OPTIONAL
+  )
+{
+  INTN    Result;
+  INT64   Temp64;
+  CHAR16  *Str1;
+  CHAR16  *Str2;
+
+  if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {
+    if (Value1->Type != Value2->Type) {
+      //
+      // Both Operator should be type of String
+      //
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if (Value1->Value.string == 0 || Value2->Value.string == 0) {
+      //
+      // StringId 0 is reserved
+      //
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if (Value1->Value.string == Value2->Value.string) {
+      return 0;
+    }
+
+    Str1 = GetToken (Value1->Value.string, HiiHandle);
+    if (Str1 == NULL) {
+      //
+      // String not found
+      //
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Str2 = GetToken (Value2->Value.string, HiiHandle);
+    if (Str2 == NULL) {
+      gBS->FreePool (Str1);
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Result = StrCmp (Str1, Str2);
+
+    gBS->FreePool (Str1);
+    gBS->FreePool (Str2);
+
+    return Result;
+  }
+
+  //
+  // Take remain types(integer, boolean, date/time) as integer
+  //
+  Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);
+  if (Temp64 > 0) {
+    Result = 1;
+  } else if (Temp64 < 0) {
+    Result = -1;
+  } else {
+    Result = 0;
+  }
+
+  return Result;
+}
+
+
+/**
+  Evaluate the result of a HII expression
+
+  @param  FormSet                FormSet associated with this expression.
+  @param  Form                   Form associated with this expression.
+  @param  Expression             Expression to be evaluated.
+
+  @retval EFI_SUCCESS            The expression evaluated successfuly
+  @retval EFI_NOT_FOUND          The Question which referenced by a QuestionId
+                                 could not be found.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
+                                 stack.
+  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
+  @retval EFI_INVALID_PARAMETER  Syntax error with the Expression
+
+**/
+EFI_STATUS
+EvaluateExpression (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  IN FORM_BROWSER_FORM     *Form,
+  IN OUT FORM_EXPRESSION   *Expression
+  )
+{
+  EFI_STATUS              Status;
+  LIST_ENTRY              *Link;
+  EXPRESSION_OPCODE       *OpCode;
+  FORM_BROWSER_STATEMENT  *Question;
+  FORM_BROWSER_STATEMENT  *Question2;
+  UINT16                  Index;
+  EFI_HII_VALUE           Data1;
+  EFI_HII_VALUE           Data2;
+  EFI_HII_VALUE           Data3;
+  FORM_EXPRESSION         *RuleExpression;
+  EFI_HII_VALUE           *Value;
+  INTN                    Result;
+  CHAR16                  *StrPtr;
+  UINT32                  TempValue;
+
+  //
+  // Always reset the stack before evaluating an Expression
+  //
+  ResetExpressionStack ();
+
+  Expression->Result.Type = EFI_IFR_TYPE_OTHER;
+
+  Link = GetFirstNode (&Expression->OpCodeListHead);
+  while (!IsNull (&Expression->OpCodeListHead, Link)) {
+    OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
+
+    Link = GetNextNode (&Expression->OpCodeListHead, Link);
+
+    ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
+    ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
+    ZeroMem (&Data3, sizeof (EFI_HII_VALUE));
+
+    Value = &Data3;
+    Value->Type = EFI_IFR_TYPE_BOOLEAN;
+    Status = EFI_SUCCESS;
+
+    switch (OpCode->Operand) {
+    //
+    // Built-in functions
+    //
+    case EFI_IFR_EQ_ID_VAL_OP:
+      Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
+      if (Question == NULL) {
+        return EFI_NOT_FOUND;
+      }
+
+      Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);
+      if (Result == EFI_INVALID_PARAMETER) {
+        return EFI_INVALID_PARAMETER;
+      }
+      Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
+      break;
+
+    case EFI_IFR_EQ_ID_ID_OP:
+      Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
+      if (Question == NULL) {
+        return EFI_NOT_FOUND;
+      }
+
+      Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);
+      if (Question2 == NULL) {
+        return EFI_NOT_FOUND;
+      }
+
+      Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);
+      if (Result == EFI_INVALID_PARAMETER) {
+        return EFI_INVALID_PARAMETER;
+      }
+      Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
+      break;
+
+    case EFI_IFR_EQ_ID_LIST_OP:
+      Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
+      if (Question == NULL) {
+        return EFI_NOT_FOUND;
+      }
+
+      Value->Value.b = FALSE;
+      for (Index =0; Index < OpCode->ListLength; Index++) {
+        if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {
+          Value->Value.b = TRUE;
+          break;
+        }
+      }
+      break;
+
+    case EFI_IFR_DUP_OP:
+      Status = PopExpression (Value);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      Status = PushExpression (Value);
+      break;
+
+    case EFI_IFR_QUESTION_REF1_OP:
+    case EFI_IFR_THIS_OP:
+      Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
+      if (Question == NULL) {
+        return EFI_NOT_FOUND;
+      }
+
+      Value = &Question->HiiValue;
+      break;
+
+    case EFI_IFR_QUESTION_REF3_OP:
+      if (OpCode->DevicePath == 0) {
+        //
+        // EFI_IFR_QUESTION_REF3
+        // Pop an expression from the expression stack
+        //
+        Status = PopExpression (Value);
+        if (EFI_ERROR (Status)) {
+          return Status;
+        }
+
+        //
+        // Validate the expression value
+        //
+        if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
+          return EFI_NOT_FOUND;
+        }
+
+        Question = IdToQuestion (FormSet, Form, Value->Value.u16);
+        if (Question == NULL) {
+          return EFI_NOT_FOUND;
+        }
+
+        //
+        // push the questions' value on to the expression stack
+        //
+        Value = &Question->HiiValue;
+      } else {
+        //
+        // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
+        // since it is impractical to evaluate the value of a Question in another
+        // Hii Package list.
+        //
+        ZeroMem (Value, sizeof (EFI_HII_VALUE));
+      }
+      break;
+
+    case EFI_IFR_RULE_REF_OP:
+      //
+      // Find expression for this rule
+      //
+      RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);
+      if (RuleExpression == NULL) {
+        return EFI_NOT_FOUND;
+      }
+
+      //
+      // Evaluate this rule expression
+      //
+      Status = EvaluateExpression (FormSet, Form, RuleExpression);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      Value = &RuleExpression->Result;
+      break;
+
+    case EFI_IFR_STRING_REF1_OP:
+      Value->Type = EFI_IFR_TYPE_STRING;
+      Value->Value.string = OpCode->Value.Value.string;
+      break;
+
+    //
+    // Constant
+    //
+    case EFI_IFR_TRUE_OP:
+    case EFI_IFR_FALSE_OP:
+    case EFI_IFR_ONE_OP:
+    case EFI_IFR_ONES_OP:
+    case EFI_IFR_UINT8_OP:
+    case EFI_IFR_UINT16_OP:
+    case EFI_IFR_UINT32_OP:
+    case EFI_IFR_UINT64_OP:
+    case EFI_IFR_UNDEFINED_OP:
+    case EFI_IFR_VERSION_OP:
+    case EFI_IFR_ZERO_OP:
+      Value = &OpCode->Value;
+      break;
+
+    //
+    // unary-op
+    //
+    case EFI_IFR_LENGTH_OP:
+      Status = PopExpression (Value);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+      if (Value->Type != EFI_IFR_TYPE_STRING) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
+      if (StrPtr == NULL) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+      Value->Value.u64 = StrLen (StrPtr);
+      gBS->FreePool (StrPtr);
+      break;
+
+    case EFI_IFR_NOT_OP:
+      Status = PopExpression (Value);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+      if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
+        return EFI_INVALID_PARAMETER;
+      }
+      Value->Value.b = (BOOLEAN) (!Value->Value.b);
+      break;
+
+    case EFI_IFR_QUESTION_REF2_OP:
+      //
+      // Pop an expression from the expression stack
+      //
+      Status = PopExpression (Value);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      //
+      // Validate the expression value
+      //
+      if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
+        return EFI_NOT_FOUND;
+      }
+
+      Question = IdToQuestion (FormSet, Form, Value->Value.u16);
+      if (Question == NULL) {
+        return EFI_NOT_FOUND;
+      }
+
+      Value = &Question->HiiValue;
+      break;
+
+    case EFI_IFR_STRING_REF2_OP:
+      //
+      // Pop an expression from the expression stack
+      //
+      Status = PopExpression (Value);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      //
+      // Validate the expression value
+      //
+      if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
+        return EFI_NOT_FOUND;
+      }
+
+      Value->Type = EFI_IFR_TYPE_STRING;
+      StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);
+      if (StrPtr == NULL) {
+        //
+        // If String not exit, push an empty string
+        //
+        Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);
+      } else {
+        Index = (UINT16) Value->Value.u64;
+        Value->Value.string = Index;
+        gBS->FreePool (StrPtr);
+      }
+      break;
+
+    case EFI_IFR_TO_BOOLEAN_OP:
+      //
+      // Pop an expression from the expression stack
+      //
+      Status = PopExpression (Value);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      //
+      // Convert an expression to a Boolean
+      //
+      if (Value->Type <= EFI_IFR_TYPE_DATE) {
+        //
+        // When converting from an unsigned integer, zero will be converted to
+        // FALSE and any other value will be converted to TRUE.
+        //
+        Value->Value.b = (BOOLEAN) ((Value->Value.u64) ? TRUE : FALSE);
+
+        Value->Type = EFI_IFR_TYPE_BOOLEAN;
+      } else if (Value->Type == EFI_IFR_TYPE_STRING) {
+        //
+        // When converting from a string, if case-insensitive compare
+        // with "true" is True, then push True. If a case-insensitive compare
+        // with "false" is True, then push False.
+        //
+        StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
+        if (StrPtr == NULL) {
+          return EFI_INVALID_PARAMETER;
+        }
+
+        if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){
+          Value->Value.b = TRUE;
+        } else {
+          Value->Value.b = FALSE;
+        }
+        gBS->FreePool (StrPtr);
+        Value->Type = EFI_IFR_TYPE_BOOLEAN;
+      }
+      break;
+
+    case EFI_IFR_TO_STRING_OP:
+      Status = IfrToString (FormSet, OpCode->Format, Value);
+      break;
+
+    case EFI_IFR_TO_UINT_OP:
+      Status = IfrToUint (FormSet, Value);
+      break;
+
+    case EFI_IFR_TO_LOWER_OP:
+    case EFI_IFR_TO_UPPER_OP:
+      Status = InitializeUnicodeCollationProtocol ();
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      Status = PopExpression (Value);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      if (Value->Type != EFI_IFR_TYPE_STRING) {
+        return EFI_UNSUPPORTED;
+      }
+
+      StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
+      if (StrPtr == NULL) {
+        return EFI_NOT_FOUND;
+      }
+
+      if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {
+        mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);
+      } else {
+        mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);
+      }
+      Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);
+      gBS->FreePool (StrPtr);
+      break;
+
+    case EFI_IFR_BITWISE_NOT_OP:
+      //
+      // Pop an expression from the expression stack
+      //
+      Status = PopExpression (Value);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+      if (Value->Type > EFI_IFR_TYPE_DATE) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+      Value->Value.u64 = ~Value->Value.u64;
+      break;
+
+    //
+    // binary-op
+    //
+    case EFI_IFR_ADD_OP:
+    case EFI_IFR_SUBTRACT_OP:
+    case EFI_IFR_MULTIPLY_OP:
+    case EFI_IFR_DIVIDE_OP:
+    case EFI_IFR_MODULO_OP:
+    case EFI_IFR_BITWISE_AND_OP:
+    case EFI_IFR_BITWISE_OR_OP:
+    case EFI_IFR_SHIFT_LEFT_OP:
+    case EFI_IFR_SHIFT_RIGHT_OP:
+      //
+      // Pop an expression from the expression stack
+      //
+      Status = PopExpression (&Data2);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+      if (Data2.Type > EFI_IFR_TYPE_DATE) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      //
+      // Pop another expression from the expression stack
+      //
+      Status = PopExpression (&Data1);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+      if (Data1.Type > EFI_IFR_TYPE_DATE) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+
+      switch (OpCode->Operand) {
+        case EFI_IFR_ADD_OP:
+          Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;
+          break;
+
+        case EFI_IFR_SUBTRACT_OP:
+          Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;
+          break;
+
+        case EFI_IFR_MULTIPLY_OP:
+          Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
+          break;
+
+        case EFI_IFR_DIVIDE_OP:
+          Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
+          break;
+
+        case EFI_IFR_MODULO_OP:
+          DivU64x32Remainder  (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);
+          Value->Value.u64 = TempValue;
+          break;
+
+        case EFI_IFR_BITWISE_AND_OP:
+          Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;
+          break;
+
+        case EFI_IFR_BITWISE_OR_OP:
+          Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;
+          break;
+
+        case EFI_IFR_SHIFT_LEFT_OP:
+          Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
+          break;
+
+        case EFI_IFR_SHIFT_RIGHT_OP:
+          Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
+          break;
+
+        default:
+          break;
+      }
+      break;
+
+    case EFI_IFR_AND_OP:
+    case EFI_IFR_OR_OP:
+      //
+      // Two Boolean operator
+      //
+      Status = PopExpression (&Data2);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+      if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      //
+      // Pop another expression from the expression stack
+      //
+      Status = PopExpression (&Data1);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+      if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      if (OpCode->Operand == EFI_IFR_AND_OP) {
+        Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);
+      } else {
+        Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);
+      }
+      break;
+
+    case EFI_IFR_EQUAL_OP:
+    case EFI_IFR_NOT_EQUAL_OP:
+    case EFI_IFR_GREATER_EQUAL_OP:
+    case EFI_IFR_GREATER_THAN_OP:
+    case EFI_IFR_LESS_EQUAL_OP:
+    case EFI_IFR_LESS_THAN_OP:
+      //
+      // Compare two integer, string, boolean or date/time
+      //
+      Status = PopExpression (&Data2);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+      if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      //
+      // Pop another expression from the expression stack
+      //
+      Status = PopExpression (&Data1);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);
+      if (Result == EFI_INVALID_PARAMETER) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      switch (OpCode->Operand) {
+      case EFI_IFR_EQUAL_OP:
+        Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
+        break;
+
+      case EFI_IFR_NOT_EQUAL_OP:
+        Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
+        break;
+
+      case EFI_IFR_GREATER_EQUAL_OP:
+        Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);
+        break;
+
+      case EFI_IFR_GREATER_THAN_OP:
+        Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);
+        break;
+
+      case EFI_IFR_LESS_EQUAL_OP:
+        Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);
+        break;
+
+      case EFI_IFR_LESS_THAN_OP:
+        Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);
+        break;
+
+      default:
+        break;
+      }
+      break;
+
+    case EFI_IFR_MATCH_OP:
+      Status = IfrMatch (FormSet, Value);
+      break;
+
+    case EFI_IFR_CATENATE_OP:
+      Status = IfrCatenate (FormSet, Value);
+      break;
+
+    //
+    // ternary-op
+    //
+    case EFI_IFR_CONDITIONAL_OP:
+      //
+      // Pop third expression from the expression stack
+      //
+      Status = PopExpression (&Data3);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      //
+      // Pop second expression from the expression stack
+      //
+      Status = PopExpression (&Data2);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      //
+      // Pop first expression from the expression stack
+      //
+      Status = PopExpression (&Data1);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+      if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      if (Data1.Value.b) {
+        Value = &Data3;
+      } else {
+        Value = &Data2;
+      }
+      break;
+
+    case EFI_IFR_FIND_OP:
+      Status = IfrFind (FormSet, OpCode->Format, Value);
+      break;
+
+    case EFI_IFR_MID_OP:
+      Status = IfrMid (FormSet, Value);
+      break;
+
+    case EFI_IFR_TOKEN_OP:
+      Status = IfrToken (FormSet, Value);
+      break;
+
+    case EFI_IFR_SPAN_OP:
+      Status = IfrSpan (FormSet, OpCode->Flags, Value);
+      break;
+
+    default:
+      break;
+    }
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    Status = PushExpression (Value);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  //
+  // Pop the final result from expression stack
+  //
+  Value = &Data1;
+  Status = PopExpression (Value);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // After evaluating an expression, there should be only one value left on the expression stack
+  //
+  if (PopExpression (Value) != EFI_ACCESS_DENIED) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
new file mode 100644 (file)
index 0000000..4b68047
--- /dev/null
@@ -0,0 +1,1640 @@
+/** @file
+Copyright (c) 2007, Intel Corporation
+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.
+
+Module Name:
+
+  IfrParse.c
+
+Abstract:
+
+  Parser for IFR binary encoding.
+
+
+**/
+
+#include "Setup.h"
+#include "Ui.h"
+//@MT:#include "EfiPrintLib.h"
+
+UINT16           mStatementIndex;
+UINT16           mExpressionOpCodeIndex;
+
+BOOLEAN          mInScopeSubtitle;
+BOOLEAN          mInScopeSuppress;
+BOOLEAN          mInScopeGrayOut;
+FORM_EXPRESSION  *mSuppressExpression;
+FORM_EXPRESSION  *mGrayOutExpression;
+
+EFI_GUID  gTianoHiiIfrGuid = EFI_IFR_TIANO_GUID;
+
+
+/**
+  Initialize Statement header members.
+
+  @param  OpCodeData             Pointer of the raw OpCode data.
+  @param  FormSet                Pointer of the current FormSe.
+  @param  Form                   Pointer of the current Form.
+
+  @return The Statement.
+
+**/
+FORM_BROWSER_STATEMENT *
+CreateStatement (
+  IN UINT8                        *OpCodeData,
+  IN OUT FORM_BROWSER_FORMSET     *FormSet,
+  IN OUT FORM_BROWSER_FORM        *Form
+  )
+{
+  FORM_BROWSER_STATEMENT    *Statement;
+  EFI_IFR_STATEMENT_HEADER  *StatementHdr;
+
+  if (Form == NULL) {
+    //
+    // We are currently not in a Form Scope, so just skip this Statement
+    //
+    return NULL;
+  }
+
+  Statement = &FormSet->StatementBuffer[mStatementIndex];
+  mStatementIndex++;
+
+  InitializeListHead (&Statement->DefaultListHead);
+  InitializeListHead (&Statement->OptionListHead);
+  InitializeListHead (&Statement->InconsistentListHead);
+  InitializeListHead (&Statement->NoSubmitListHead);
+
+  Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;
+
+  Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
+
+  StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
+  CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));
+  CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID));
+
+  if (mInScopeSuppress) {
+    Statement->SuppressExpression = mSuppressExpression;
+  }
+
+  if (mInScopeGrayOut) {
+    Statement->GrayOutExpression = mGrayOutExpression;
+  }
+
+  Statement->InSubtitle = mInScopeSubtitle;
+
+  //
+  // Insert this Statement into current Form
+  //
+  InsertTailList (&Form->StatementListHead, &Statement->Link);
+
+  return Statement;
+}
+
+
+/**
+  Initialize Question's members.
+
+  @param  OpCodeData             Pointer of the raw OpCode data.
+  @param  FormSet                Pointer of the current FormSet.
+  @param  Form                   Pointer of the current Form.
+
+  @return The Question.
+
+**/
+FORM_BROWSER_STATEMENT *
+CreateQuestion (
+  IN UINT8                        *OpCodeData,
+  IN OUT FORM_BROWSER_FORMSET     *FormSet,
+  IN OUT FORM_BROWSER_FORM        *Form
+  )
+{
+  FORM_BROWSER_STATEMENT   *Statement;
+  EFI_IFR_QUESTION_HEADER  *QuestionHdr;
+  LIST_ENTRY               *Link;
+  FORMSET_STORAGE          *Storage;
+  NAME_VALUE_NODE          *NameValueNode;
+
+  Statement = CreateStatement (OpCodeData, FormSet, Form);
+  if (Statement == NULL) {
+    return NULL;
+  }
+
+  QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
+  CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID));
+  CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID));
+  CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16));
+
+  Statement->QuestionFlags = QuestionHdr->Flags;
+
+  if (Statement->VarStoreId == 0) {
+    //
+    // VarStoreId of zero indicates no variable storage
+    //
+    return Statement;
+  }
+
+  //
+  // Find Storage for this Question
+  //
+  Link = GetFirstNode (&FormSet->StorageListHead);
+  while (!IsNull (&FormSet->StorageListHead, Link)) {
+    Storage = FORMSET_STORAGE_FROM_LINK (Link);
+
+    if (Storage->VarStoreId == Statement->VarStoreId) {
+      Statement->Storage = Storage;
+      break;
+    }
+
+    Link = GetNextNode (&FormSet->StorageListHead, Link);
+  }
+  ASSERT (Statement->Storage != NULL);
+
+  //
+  // Initialilze varname for Name/Value or EFI Variable
+  //
+  if ((Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||
+      (Statement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
+    Statement->VariableName = GetToken (Statement->VarStoreInfo.VarName, FormSet->HiiHandle);
+    ASSERT (Statement->VariableName != NULL);
+
+    if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+      //
+      // Insert to Name/Value varstore list
+      //
+      NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE));
+      ASSERT (NameValueNode != NULL);
+      NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE;
+      NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName);
+      ASSERT (NameValueNode->Name != NULL);
+      NameValueNode->Value = AllocateZeroPool (0x10);
+      ASSERT (NameValueNode->Value != NULL);
+      NameValueNode->EditValue = AllocateZeroPool (0x10);
+      ASSERT (NameValueNode->EditValue != NULL);
+
+      InsertTailList (&Statement->Storage->NameValueListHead, &NameValueNode->Link);
+    }
+  }
+
+  return Statement;
+}
+
+
+/**
+  Allocate a FORM_EXPRESSION node.
+
+  @param  Form                   The Form associated with this Expression
+
+  @return Pointer to a FORM_EXPRESSION data structure.
+
+**/
+FORM_EXPRESSION *
+CreateExpression (
+  IN OUT FORM_BROWSER_FORM        *Form
+  )
+{
+  FORM_EXPRESSION  *Expression;
+
+  Expression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
+  Expression->Signature = FORM_EXPRESSION_SIGNATURE;
+  InitializeListHead (&Expression->OpCodeListHead);
+
+  return Expression;
+}
+
+
+/**
+  Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
+
+  @param  FormSet                Pointer of the current FormSet
+
+  @return Pointer to a FORMSET_STORAGE data structure.
+
+**/
+FORMSET_STORAGE *
+CreateStorage (
+  IN FORM_BROWSER_FORMSET  *FormSet
+  )
+{
+  FORMSET_STORAGE  *Storage;
+
+  Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE));
+  Storage->Signature = FORMSET_STORAGE_SIGNATURE;
+  InitializeListHead (&Storage->NameValueListHead);
+  InsertTailList (&FormSet->StorageListHead, &Storage->Link);
+
+  return Storage;
+}
+
+
+/**
+  Create ConfigHdr string for a storage.
+
+  @param  FormSet                Pointer of the current FormSet
+  @param  Storage                Pointer of the storage
+
+  @retval EFI_SUCCESS            Initialize ConfigHdr success
+
+**/
+EFI_STATUS
+InitializeConfigHdr (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  IN OUT FORMSET_STORAGE   *Storage
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       StrBufferLen;
+  CHAR16      *Name;
+
+  if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
+    Name = Storage->Name;
+  } else {
+    Name = NULL;
+  }
+
+  StrBufferLen = 0;
+  Status = ConstructConfigHdr (
+             Storage->ConfigHdr,
+             &StrBufferLen,
+             &Storage->Guid,
+             Name,
+             FormSet->DriverHandle
+             );
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    Storage->ConfigHdr = AllocateZeroPool (StrBufferLen);
+    Status = ConstructConfigHdr (
+               Storage->ConfigHdr,
+               &StrBufferLen,
+               &Storage->Guid,
+               Name,
+               FormSet->DriverHandle
+               );
+  }
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Storage->ConfigRequest = AllocateCopyPool (StrBufferLen, Storage->ConfigHdr);
+  Storage->SpareStrLen = 0;
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label>
+
+  @param  FormSet                Pointer of the current FormSet.
+  @param  Question               The Question to be initialized.
+
+  @retval EFI_SUCCESS            Function success.
+  @retval EFI_INVALID_PARAMETER  No storage associated with the Question.
+
+**/
+EFI_STATUS
+InitializeRequestElement (
+  IN OUT FORM_BROWSER_FORMSET     *FormSet,
+  IN OUT FORM_BROWSER_STATEMENT   *Question
+  )
+{
+  FORMSET_STORAGE  *Storage;
+  UINTN            StrLen;
+  UINTN            StringSize;
+  CHAR16           *NewStr;
+  CHAR16           RequestElement[30];
+
+  Storage = Question->Storage;
+  if (Storage == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+    //
+    // <ConfigRequest> is unnecessary for EFI variable storage,
+    // GetVariable()/SetVariable() will be used to retrieve/save values
+    //
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Prepare <RequestElement>
+  //
+  if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
+    StrLen = UnicodeSPrint (
+               RequestElement,
+               30 * sizeof (CHAR16),
+               L"&OFFSET=%x&WIDTH=%x",
+               Question->VarStoreInfo.VarOffset,
+               Question->StorageWidth
+               );
+    Question->BlockName = AllocateCopyPool ((StrLen + 1) * sizeof (CHAR16), RequestElement);
+  } else {
+    StrLen = UnicodeSPrint (RequestElement, 30 * sizeof (CHAR16), L"&%s", Question->VariableName);
+  }
+
+  if ((Question->Operand == EFI_IFR_PASSWORD_OP) && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)) {
+    //
+    // Password with CALLBACK flag is stored in encoded format,
+    // so don't need to append it to <ConfigRequest>\
+    //
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Append <RequestElement> to <ConfigRequest>
+  //
+  if (StrLen > Storage->SpareStrLen) {
+    //
+    // Old String buffer is not sufficient for RequestElement, allocate a new one
+    //
+    StringSize = (Storage->ConfigRequest != NULL) ? StrSize (Storage->ConfigRequest) : 0;
+    NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));
+    if (Storage->ConfigRequest != NULL) {
+      CopyMem (NewStr, Storage->ConfigRequest, StringSize);
+      gBS->FreePool (Storage->ConfigRequest);
+    }
+    Storage->ConfigRequest = NewStr;
+    Storage->SpareStrLen   = CONFIG_REQUEST_STRING_INCREMENTAL;
+  }
+
+  StrCat (Storage->ConfigRequest, RequestElement);
+  Storage->ElementCount++;
+  Storage->SpareStrLen -= StrLen;
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Free resources of a Expression
+
+  @param  FormSet                Pointer of the Expression
+
+  @return None.
+
+**/
+VOID
+DestroyExpression (
+  IN FORM_EXPRESSION   *Expression
+  )
+{
+  LIST_ENTRY         *Link;
+  EXPRESSION_OPCODE  *OpCode;
+
+  while (!IsListEmpty (&Expression->OpCodeListHead)) {
+    Link = GetFirstNode (&Expression->OpCodeListHead);
+    OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
+    RemoveEntryList (&OpCode->Link);
+
+    SafeFreePool (OpCode->ValueList);
+  }
+
+  //
+  // Free this Expression
+  //
+  gBS->FreePool (Expression);
+}
+
+
+/**
+  Free resources of a storage
+
+  @param  Storage                Pointer of the storage
+
+  @return None.
+
+**/
+VOID
+DestroyStorage (
+  IN FORMSET_STORAGE   *Storage
+  )
+{
+  LIST_ENTRY         *Link;
+  NAME_VALUE_NODE    *NameValueNode;
+
+  if (Storage == NULL) {
+    return;
+  }
+
+  SafeFreePool (Storage->Name);
+  SafeFreePool (Storage->Buffer);
+  SafeFreePool (Storage->EditBuffer);
+
+  while (!IsListEmpty (&Storage->NameValueListHead)) {
+    Link = GetFirstNode (&Storage->NameValueListHead);
+    NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link);
+    RemoveEntryList (&NameValueNode->Link);
+
+    SafeFreePool (NameValueNode->Name);
+    SafeFreePool (NameValueNode->Value);
+    SafeFreePool (NameValueNode->EditValue);
+    SafeFreePool (NameValueNode);
+  }
+
+  SafeFreePool (Storage->ConfigHdr);
+  SafeFreePool (Storage->ConfigRequest);
+
+  gBS->FreePool (Storage);
+}
+
+
+/**
+  Free resources of a Statement
+
+  @param  Statement              Pointer of the Statement
+
+  @return None.
+
+**/
+VOID
+DestroyStatement (
+  IN OUT FORM_BROWSER_STATEMENT  *Statement
+  )
+{
+  LIST_ENTRY        *Link;
+  QUESTION_DEFAULT  *Default;
+  QUESTION_OPTION   *Option;
+  FORM_EXPRESSION   *Expression;
+
+  //
+  // Free Default value List
+  //
+  while (!IsListEmpty (&Statement->DefaultListHead)) {
+    Link = GetFirstNode (&Statement->DefaultListHead);
+    Default = QUESTION_DEFAULT_FROM_LINK (Link);
+    RemoveEntryList (&Default->Link);
+
+    gBS->FreePool (Default);
+  }
+
+  //
+  // Free Options List
+  //
+  while (!IsListEmpty (&Statement->OptionListHead)) {
+    Link = GetFirstNode (&Statement->OptionListHead);
+    Option = QUESTION_OPTION_FROM_LINK (Link);
+    RemoveEntryList (&Option->Link);
+
+    gBS->FreePool (Option);
+  }
+
+  //
+  // Free Inconsistent List
+  //
+  while (!IsListEmpty (&Statement->InconsistentListHead)) {
+    Link = GetFirstNode (&Statement->InconsistentListHead);
+    Expression = FORM_EXPRESSION_FROM_LINK (Link);
+    RemoveEntryList (&Expression->Link);
+
+    DestroyExpression (Expression);
+  }
+
+  //
+  // Free NoSubmit List
+  //
+  while (!IsListEmpty (&Statement->NoSubmitListHead)) {
+    Link = GetFirstNode (&Statement->NoSubmitListHead);
+    Expression = FORM_EXPRESSION_FROM_LINK (Link);
+    RemoveEntryList (&Expression->Link);
+
+    DestroyExpression (Expression);
+  }
+
+  SafeFreePool (Statement->VariableName);
+  SafeFreePool (Statement->BlockName);
+}
+
+
+/**
+  Free resources of a Form
+
+  @param  Form                   Pointer of the Form
+
+  @return None.
+
+**/
+VOID
+DestroyForm (
+  IN OUT FORM_BROWSER_FORM  *Form
+  )
+{
+  LIST_ENTRY              *Link;
+  FORM_EXPRESSION         *Expression;
+  FORM_BROWSER_STATEMENT  *Statement;
+
+  //
+  // Free Form Expressions
+  //
+  while (!IsListEmpty (&Form->ExpressionListHead)) {
+    Link = GetFirstNode (&Form->ExpressionListHead);
+    Expression = FORM_EXPRESSION_FROM_LINK (Link);
+    RemoveEntryList (&Expression->Link);
+
+    DestroyExpression (Expression);
+  }
+
+  //
+  // Free Statements/Questions
+  //
+  while (!IsListEmpty (&Form->StatementListHead)) {
+    Link = GetFirstNode (&Form->StatementListHead);
+    Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+    RemoveEntryList (&Statement->Link);
+
+    DestroyStatement (Statement);
+  }
+
+  //
+  // Free this Form
+  //
+  gBS->FreePool (Form);
+}
+
+
+/**
+  Free resources allocated for a FormSet
+
+  @param  FormSet                Pointer of the FormSet
+
+  @return None.
+
+**/
+VOID
+DestroyFormSet (
+  IN OUT FORM_BROWSER_FORMSET  *FormSet
+  )
+{
+  LIST_ENTRY            *Link;
+  FORMSET_STORAGE       *Storage;
+  FORMSET_DEFAULTSTORE  *DefaultStore;
+  FORM_BROWSER_FORM     *Form;
+
+  //
+  // Free IFR binary buffer
+  //
+  SafeFreePool (FormSet->IfrBinaryData);
+
+  //
+  // Free FormSet Storage
+  //
+  if (FormSet->StorageListHead.ForwardLink != NULL) {
+    while (!IsListEmpty (&FormSet->StorageListHead)) {
+      Link = GetFirstNode (&FormSet->StorageListHead);
+      Storage = FORMSET_STORAGE_FROM_LINK (Link);
+      RemoveEntryList (&Storage->Link);
+
+      DestroyStorage (Storage);
+    }
+  }
+
+  //
+  // Free FormSet Default Store
+  //
+  if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {
+    while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
+      Link = GetFirstNode (&FormSet->DefaultStoreListHead);
+      DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (Link);
+      RemoveEntryList (&DefaultStore->Link);
+
+      gBS->FreePool (DefaultStore);
+    }
+  }
+
+  //
+  // Free Forms
+  //
+  if (FormSet->FormListHead.ForwardLink != NULL) {
+    while (!IsListEmpty (&FormSet->FormListHead)) {
+      Link = GetFirstNode (&FormSet->FormListHead);
+      Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+      RemoveEntryList (&Form->Link);
+
+      DestroyForm (Form);
+    }
+  }
+
+  SafeFreePool (FormSet->StatementBuffer);
+  SafeFreePool (FormSet->ExpressionBuffer);
+
+  SafeFreePool (FormSet);
+}
+
+
+/**
+  Tell whether this Operand is an Expression OpCode or not
+
+  @param  Operand                Operand of an IFR OpCode.
+
+  @retval TRUE                   This is an Expression OpCode.
+  @retval FALSE                  Not an Expression OpCode.
+
+**/
+BOOLEAN
+IsExpressionOpCode (
+  IN UINT8              Operand
+  )
+{
+  if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||
+      ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||
+      (Operand == EFI_IFR_CATENATE_OP)
+     ) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+/**
+  Calculate number of Statemens(Questions) and Expression OpCodes.
+
+  @param  FormSet                The FormSet to be counted.
+  @param  NumberOfStatement      Number of Statemens(Questions)
+  @param  NumberOfExpression     Number of Expression OpCodes
+
+  @return None.
+
+**/
+VOID
+CountOpCodes (
+  IN  FORM_BROWSER_FORMSET  *FormSet,
+  IN OUT  UINT16            *NumberOfStatement,
+  IN OUT  UINT16            *NumberOfExpression
+  )
+{
+  UINT16  StatementCount;
+  UINT16  ExpressionCount;
+  UINT8   *OpCodeData;
+  UINTN   Offset;
+  UINTN   OpCodeLen;
+
+  Offset = 0;
+  StatementCount = 0;
+  ExpressionCount = 0;
+
+  while (Offset < FormSet->IfrBinaryLength) {
+    OpCodeData = FormSet->IfrBinaryData + Offset;
+    OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+    Offset += OpCodeLen;
+
+    if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) {
+      ExpressionCount++;
+    } else {
+      StatementCount++;
+    }
+  }
+
+  *NumberOfStatement = StatementCount;
+  *NumberOfExpression = ExpressionCount;
+}
+
+
+/**
+  Parse opcodes in the formset IFR binary.
+
+  @param  FormSet                Pointer of the FormSet data structure.
+
+  @retval EFI_SUCCESS            Opcode parse success.
+  @retval Other                  Opcode parse fail.
+
+**/
+EFI_STATUS
+ParseOpCodes (
+  IN FORM_BROWSER_FORMSET              *FormSet
+  )
+{
+  EFI_STATUS              Status;
+  UINT16                  Index;
+  FORM_BROWSER_FORM       *CurrentForm;
+  FORM_BROWSER_STATEMENT  *CurrentStatement;
+  EXPRESSION_OPCODE       *ExpressionOpCode;
+  FORM_EXPRESSION         *CurrentExpression;
+  UINT8                   Operand;
+  UINT8                   Scope;
+  UINTN                   OpCodeOffset;
+  UINTN                   OpCodeLength;
+  UINT8                   *OpCodeData;
+  UINT8                   ScopeOpCode;
+  FORMSET_STORAGE         *Storage;
+  FORMSET_DEFAULTSTORE    *DefaultStore;
+  QUESTION_DEFAULT        *CurrentDefault;
+  QUESTION_OPTION         *CurrentOption;
+  CHAR8                   *AsciiString;
+  UINT16                  NumberOfStatement;
+  UINT16                  NumberOfExpression;
+  EFI_IMAGE_ID            *ImageId;
+  BOOLEAN                 SuppressForOption;
+  BOOLEAN                 InScopeOptionSuppress;
+  FORM_EXPRESSION         *OptionSuppressExpression;
+  BOOLEAN                 InScopeDisable;
+  UINT16                  DepthOfDisable;
+  BOOLEAN                 OpCodeDisabled;
+  BOOLEAN                 SingleOpCodeExpression;
+  BOOLEAN                 InScopeDefault;
+  EFI_HII_VALUE           *Value;
+
+  mInScopeSubtitle         = FALSE;
+  SuppressForOption        = FALSE;
+  mInScopeSuppress         = FALSE;
+  InScopeOptionSuppress    = FALSE;
+  mInScopeGrayOut          = FALSE;
+  InScopeDisable           = FALSE;
+  DepthOfDisable           = 0;
+  OpCodeDisabled           = FALSE;
+  SingleOpCodeExpression   = FALSE;
+  InScopeDefault           = FALSE;
+  CurrentExpression        = NULL;
+  CurrentDefault           = NULL;
+  CurrentOption            = NULL;
+  OptionSuppressExpression = NULL;
+
+  //
+  // Get the number of Statements and Expressions
+  //
+  CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
+
+  mStatementIndex = 0;
+  FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
+  if (FormSet->StatementBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  mExpressionOpCodeIndex = 0;
+  FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE));
+  if (FormSet->ExpressionBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  InitializeListHead (&FormSet->StorageListHead);
+  InitializeListHead (&FormSet->DefaultStoreListHead);
+  InitializeListHead (&FormSet->FormListHead);
+
+  CurrentForm = NULL;
+  CurrentStatement = NULL;
+
+  ResetScopeStack ();
+
+  OpCodeOffset = 0;
+  while (OpCodeOffset < FormSet->IfrBinaryLength) {
+    OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
+
+    OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+    OpCodeOffset += OpCodeLength;
+    Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
+    Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;
+
+    //
+    // If scope bit set, push onto scope stack
+    //
+    if (Scope) {
+      PushScope (Operand);
+    }
+
+    if (OpCodeDisabled) {
+      //
+      // DisableIf Expression is evaluated to be TRUE, try to find its end.
+      // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
+      //
+      if (Operand == EFI_IFR_DISABLE_IF_OP) {
+        DepthOfDisable++;
+      } else if (Operand == EFI_IFR_END_OP) {
+        Status = PopScope (&ScopeOpCode);
+        if (EFI_ERROR (Status)) {
+          return Status;
+        }
+
+        if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
+          if (DepthOfDisable == 0) {
+            InScopeDisable = FALSE;
+            OpCodeDisabled = FALSE;
+          } else {
+            DepthOfDisable--;
+          }
+        }
+      }
+      continue;
+    }
+
+    if (IsExpressionOpCode (Operand)) {
+      ExpressionOpCode = &FormSet->ExpressionBuffer[mExpressionOpCodeIndex];
+      mExpressionOpCodeIndex++;
+
+      ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;
+      ExpressionOpCode->Operand = Operand;
+      Value = &ExpressionOpCode->Value;
+
+      switch (Operand) {
+      case EFI_IFR_EQ_ID_VAL_OP:
+        CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
+
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
+        CopyMem (&Value->Value.u16, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->Value, sizeof (UINT16));
+        break;
+
+      case EFI_IFR_EQ_ID_ID_OP:
+        CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));
+        CopyMem (&ExpressionOpCode->QuestionId2, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));
+        break;
+
+      case EFI_IFR_EQ_ID_LIST_OP:
+        CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
+        CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->ListLength, sizeof (UINT16));
+        ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->ValueList);
+        break;
+
+      case EFI_IFR_TO_STRING_OP:
+      case EFI_IFR_FIND_OP:
+        ExpressionOpCode->Format = (( EFI_IFR_TO_STRING *) OpCodeData)->Format;
+        break;
+
+      case EFI_IFR_STRING_REF1_OP:
+        Value->Type = EFI_IFR_TYPE_STRING;
+        CopyMem (&Value->Value.string, &(( EFI_IFR_STRING_REF1 *) OpCodeData)->StringId, sizeof (EFI_STRING_ID));
+        break;
+
+      case EFI_IFR_RULE_REF_OP:
+        ExpressionOpCode->RuleId = (( EFI_IFR_RULE_REF *) OpCodeData)->RuleId;
+        break;
+
+      case EFI_IFR_SPAN_OP:
+        ExpressionOpCode->Flags = (( EFI_IFR_SPAN *) OpCodeData)->Flags;
+        break;
+
+      case EFI_IFR_THIS_OP:
+        ExpressionOpCode->QuestionId = CurrentStatement->QuestionId;
+        break;
+
+      case EFI_IFR_QUESTION_REF1_OP:
+        CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
+        break;
+
+      case EFI_IFR_QUESTION_REF3_OP:
+        if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {
+          CopyMem (&ExpressionOpCode->DevicePath, &(( EFI_IFR_QUESTION_REF3_2 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
+
+          if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {
+            CopyMem (&ExpressionOpCode->Guid, &(( EFI_IFR_QUESTION_REF3_3 *) OpCodeData)->Guid, sizeof (EFI_GUID));
+          }
+        }
+        break;
+
+      //
+      // constant
+      //
+      case EFI_IFR_TRUE_OP:
+        Value->Type = EFI_IFR_TYPE_BOOLEAN;
+        Value->Value.b = TRUE;
+        break;
+
+      case EFI_IFR_FALSE_OP:
+        Value->Type = EFI_IFR_TYPE_BOOLEAN;
+        Value->Value.b = FALSE;
+        break;
+
+      case EFI_IFR_ONE_OP:
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+        Value->Value.u8 = 1;
+        break;
+
+      case EFI_IFR_ZERO_OP:
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+        Value->Value.u8 = 0;
+        break;
+
+      case EFI_IFR_ONES_OP:
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+        Value->Value.u64 = 0xffffffffffffffff;
+        break;
+
+      case EFI_IFR_UINT8_OP:
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+        Value->Value.u8 = (( EFI_IFR_UINT8 *) OpCodeData)->Value;
+        break;
+
+      case EFI_IFR_UINT16_OP:
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
+        CopyMem (&Value->Value.u16, &(( EFI_IFR_UINT16 *) OpCodeData)->Value, sizeof (UINT16));
+        break;
+
+      case EFI_IFR_UINT32_OP:
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
+        CopyMem (&Value->Value.u32, &(( EFI_IFR_UINT32 *) OpCodeData)->Value, sizeof (UINT32));
+        break;
+
+      case EFI_IFR_UINT64_OP:
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+        CopyMem (&Value->Value.u64, &(( EFI_IFR_UINT64 *) OpCodeData)->Value, sizeof (UINT64));
+        break;
+
+      case EFI_IFR_UNDEFINED_OP:
+        Value->Type = EFI_IFR_TYPE_OTHER;
+        break;
+
+      case EFI_IFR_VERSION_OP:
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
+        Value->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;
+        break;
+
+      default:
+        break;
+      }
+
+      InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
+
+      if (SingleOpCodeExpression) {
+        //
+        // There are two cases to indicate the end of an Expression:
+        // for single OpCode expression: one Expression OpCode
+        // for expression consists of more than one OpCode: EFI_IFR_END
+        //
+        SingleOpCodeExpression = FALSE;
+
+        if (InScopeDisable) {
+          //
+          // Evaluate DisableIf expression
+          //
+          Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
+          if (EFI_ERROR (Status)) {
+            return Status;
+          }
+          if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
+            return EFI_INVALID_PARAMETER;
+          }
+
+          OpCodeDisabled = CurrentExpression->Result.Value.b;
+        }
+
+        CurrentExpression = NULL;
+      }
+
+      continue;
+    }
+
+    //
+    // Parse the Opcode
+    //
+    switch (Operand) {
+
+    case EFI_IFR_FORM_SET_OP:
+      //
+      // check the formset GUID
+      //
+      if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
+      CopyMem (&FormSet->Help,         &((EFI_IFR_FORM_SET *) OpCodeData)->Help,         sizeof (EFI_STRING_ID));
+      break;
+
+    case EFI_IFR_FORM_OP:
+      //
+      // Create a new Form for this FormSet
+      //
+      CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
+      CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
+      InitializeListHead (&CurrentForm->ExpressionListHead);
+      InitializeListHead (&CurrentForm->StatementListHead);
+
+      CopyMem (&CurrentForm->FormId,    &((EFI_IFR_FORM *) OpCodeData)->FormId,    sizeof (UINT16));
+      CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
+
+      //
+      // Insert into Form list of this FormSet
+      //
+      InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
+      break;
+
+    //
+    // Storage
+    //
+    case EFI_IFR_VARSTORE_OP:
+      //
+      // Create a buffer Storage for this FormSet
+      //
+      Storage = CreateStorage (FormSet);
+      Storage->Type = EFI_HII_VARSTORE_BUFFER;
+
+      CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
+      CopyMem (&Storage->Guid,       &((EFI_IFR_VARSTORE *) OpCodeData)->Guid,       sizeof (EFI_GUID));
+      CopyMem (&Storage->Size,       &((EFI_IFR_VARSTORE *) OpCodeData)->Size,       sizeof (UINT16));
+
+      Storage->Buffer = AllocateZeroPool (Storage->Size);
+      Storage->EditBuffer = AllocateZeroPool (Storage->Size);
+
+      AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
+      Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);
+      ASSERT (Storage->Name != NULL);
+      for (Index = 0; AsciiString[Index] != 0; Index++) {
+        Storage->Name[Index] = (CHAR16) AsciiString[Index];
+      }
+
+      //
+      // Initialize <ConfigHdr>
+      //
+      InitializeConfigHdr (FormSet, Storage);
+      break;
+
+    case EFI_IFR_VARSTORE_NAME_VALUE_OP:
+      //
+      // Create a name/value Storage for this FormSet
+      //
+      Storage = CreateStorage (FormSet);
+      Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;
+
+      CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
+      CopyMem (&Storage->Guid,       &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid,       sizeof (EFI_GUID));
+
+      //
+      // Initialize <ConfigHdr>
+      //
+      InitializeConfigHdr (FormSet, Storage);
+      break;
+
+    case EFI_IFR_VARSTORE_EFI_OP:
+      //
+      // Create a EFI variable Storage for this FormSet
+      //
+      Storage = CreateStorage (FormSet);
+      Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;
+
+      CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
+      CopyMem (&Storage->Guid,       &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid,       sizeof (EFI_GUID));
+      CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));
+      break;
+
+    //
+    // DefaultStore
+    //
+    case EFI_IFR_DEFAULTSTORE_OP:
+      DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));
+      DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;
+
+      CopyMem (&DefaultStore->DefaultId,   &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId,   sizeof (UINT16));
+      CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
+
+      //
+      // Insert to DefaultStore list of this Formset
+      //
+      InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
+      break;
+
+    //
+    // Statements
+    //
+    case EFI_IFR_SUBTITLE_OP:
+      CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
+      CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
+
+      if (Scope) {
+        mInScopeSubtitle = TRUE;
+      }
+      break;
+
+    case EFI_IFR_TEXT_OP:
+      CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
+
+      CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
+      break;
+
+    //
+    // Questions
+    //
+    case EFI_IFR_ACTION_OP:
+      CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+      if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {
+        //
+        // No QuestionConfig present, so no configuration string will be processed
+        //
+        CurrentStatement->QuestionConfig = 0;
+      } else {
+        CopyMem (&CurrentStatement->QuestionConfig, &((EFI_IFR_ACTION *) OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));
+      }
+      break;
+
+    case EFI_IFR_RESET_BUTTON_OP:
+      CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+      CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
+      break;
+
+    case EFI_IFR_REF_OP:
+      CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+      CopyMem (&CurrentStatement->RefFormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
+      if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
+        CopyMem (&CurrentStatement->RefQuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
+
+        if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
+          CopyMem (&CurrentStatement->RefFormSetId, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
+
+          if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
+            CopyMem (&CurrentStatement->RefDevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
+          }
+        }
+      }
+      break;
+
+    case EFI_IFR_ONE_OF_OP:
+    case EFI_IFR_NUMERIC_OP:
+      CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+      CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;
+      Value = &CurrentStatement->HiiValue;
+
+      switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
+      case EFI_IFR_NUMERIC_SIZE_1:
+        CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
+        CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
+        CurrentStatement->Step    = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
+        CurrentStatement->StorageWidth = sizeof (UINT8);
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+        break;
+
+      case EFI_IFR_NUMERIC_SIZE_2:
+        CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
+        CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
+        CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step,     sizeof (UINT16));
+        CurrentStatement->StorageWidth = sizeof (UINT16);
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
+        break;
+
+      case EFI_IFR_NUMERIC_SIZE_4:
+        CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
+        CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
+        CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step,     sizeof (UINT32));
+        CurrentStatement->StorageWidth = sizeof (UINT32);
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
+        break;
+
+      case EFI_IFR_NUMERIC_SIZE_8:
+        CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
+        CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
+        CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step,     sizeof (UINT64));
+        CurrentStatement->StorageWidth = sizeof (UINT64);
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+        break;
+
+      default:
+        break;
+      }
+
+      InitializeRequestElement (FormSet, CurrentStatement);
+
+      if ((Operand == EFI_IFR_ONE_OF_OP) && Scope) {
+        SuppressForOption = TRUE;
+      }
+      break;
+
+    case EFI_IFR_ORDERED_LIST_OP:
+      CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+      CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;
+      CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;
+      CurrentStatement->StorageWidth = (UINT16)(CurrentStatement->MaxContainers * sizeof (UINT8));
+      InitializeRequestElement (FormSet, CurrentStatement);
+
+      //
+      // No buffer type is defined in EFI_IFR_TYPE_VALUE, so a Configuration Driver
+      // has to use FormBrowser2.Callback() to retrieve the uncommited data for
+      // an interactive orderedlist (i.e. with EFI_IFR_FLAG_CALLBACK flag set).
+      //
+      CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_OTHER;
+      CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
+
+      if (Scope) {
+        SuppressForOption = TRUE;
+      }
+      break;
+
+    case EFI_IFR_CHECKBOX_OP:
+      CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+      CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;
+      CurrentStatement->StorageWidth = sizeof (BOOLEAN);
+      CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
+
+      InitializeRequestElement (FormSet, CurrentStatement);
+      break;
+
+    case EFI_IFR_STRING_OP:
+      CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+      //
+      // MinSize is the minimum number of characters that can be accepted for this opcode,
+      // MaxSize is the maximum number of characters that can be accepted for this opcode.
+      // The characters are stored as Unicode, so the storage width should multiply 2.
+      //
+      CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;
+      CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;
+      CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (UINT16));
+      CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
+
+      CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
+      CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
+
+      InitializeRequestElement (FormSet, CurrentStatement);
+      break;
+
+    case EFI_IFR_PASSWORD_OP:
+      CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+      //
+      // MinSize is the minimum number of characters that can be accepted for this opcode,
+      // MaxSize is the maximum number of characters that can be accepted for this opcode.
+      // The characters are stored as Unicode, so the storage width should multiply 2.
+      //
+      CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));
+      CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));
+      CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (UINT16));
+
+      CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
+      CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
+
+      InitializeRequestElement (FormSet, CurrentStatement);
+      break;
+
+    case EFI_IFR_DATE_OP:
+      CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+      CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;
+      CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
+
+      if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
+        CurrentStatement->StorageWidth = sizeof (EFI_HII_DATE);
+
+        InitializeRequestElement (FormSet, CurrentStatement);
+      } else {
+        //
+        // Don't assign storage for RTC type of date/time
+        //
+        CurrentStatement->Storage = NULL;
+        CurrentStatement->StorageWidth = 0;
+      }
+      break;
+
+    case EFI_IFR_TIME_OP:
+      CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+      CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;
+      CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
+
+      if ((CurrentStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
+        CurrentStatement->StorageWidth = sizeof (EFI_IFR_TIME);
+
+        InitializeRequestElement (FormSet, CurrentStatement);
+      } else {
+        //
+        // Don't assign storage for RTC type of date/time
+        //
+        CurrentStatement->Storage = NULL;
+        CurrentStatement->StorageWidth = 0;
+      }
+      break;
+
+    //
+    // Default
+    //
+    case EFI_IFR_DEFAULT_OP:
+      //
+      // EFI_IFR_DEFAULT appear in scope of a Question,
+      // It creates a default value for the current question.
+      // A Question may have more than one Default value which have different default types.
+      //
+      CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
+      CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
+
+      CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;
+      CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));
+      CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
+      ExtendValueToU64 (&CurrentDefault->Value);
+
+      //
+      // Insert to Default Value list of current Question
+      //
+      InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
+
+      if (Scope) {
+        InScopeDefault = TRUE;
+      }
+      break;
+
+    //
+    // Option
+    //
+    case EFI_IFR_ONE_OF_OPTION_OP:
+      //
+      // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
+      // It create a selection for use in current Question.
+      //
+      CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
+      CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;
+
+      CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;
+      CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;
+      CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));
+      CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
+      ExtendValueToU64 (&CurrentOption->Value);
+
+      if (InScopeOptionSuppress) {
+        CurrentOption->SuppressExpression = OptionSuppressExpression;
+      }
+
+      //
+      // Insert to Option list of current Question
+      //
+      InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link);
+      break;
+
+    //
+    // Conditional
+    //
+    case EFI_IFR_NO_SUBMIT_IF_OP:
+    case EFI_IFR_INCONSISTENT_IF_OP:
+      //
+      // Create an Expression node
+      //
+      CurrentExpression = CreateExpression (CurrentForm);
+      CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));
+
+      if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
+        CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
+        InsertTailList (&CurrentStatement->NoSubmitListHead, &CurrentExpression->Link);
+      } else {
+        CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
+        InsertTailList (&CurrentStatement->InconsistentListHead, &CurrentExpression->Link);
+      }
+      break;
+
+    case EFI_IFR_SUPPRESS_IF_OP:
+      //
+      // Question and Option will appear in scope of this OpCode
+      //
+      CurrentExpression = CreateExpression (CurrentForm);
+      CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
+      InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
+
+      if (SuppressForOption) {
+        InScopeOptionSuppress = TRUE;
+        OptionSuppressExpression = CurrentExpression;
+      } else {
+        mInScopeSuppress = TRUE;
+        mSuppressExpression = CurrentExpression;
+      }
+      break;
+
+    case EFI_IFR_GRAY_OUT_IF_OP:
+      //
+      // Questions will appear in scope of this OpCode
+      //
+      CurrentExpression = CreateExpression (CurrentForm);
+      CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
+      InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
+
+      mInScopeGrayOut = TRUE;
+      mGrayOutExpression = CurrentExpression;
+      break;
+
+    case EFI_IFR_DISABLE_IF_OP:
+      //
+      // The DisableIf expression should only rely on constant, so it could be
+      // evaluated at initialization and it will not be queued
+      //
+      CurrentExpression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
+      CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE;
+      CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
+      InitializeListHead (&CurrentExpression->OpCodeListHead);
+
+      InScopeDisable = TRUE;
+      OpCodeDisabled = FALSE;
+
+      //
+      // Take a look at next OpCode to see whether current expression consists
+      // of single OpCode
+      //
+      if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
+        SingleOpCodeExpression = TRUE;
+      }
+      break;
+
+    //
+    // Expression
+    //
+    case EFI_IFR_VALUE_OP:
+      CurrentExpression = CreateExpression (CurrentForm);
+      CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
+      InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
+
+      if (InScopeDefault) {
+        //
+        // Used for default (EFI_IFR_DEFAULT)
+        //
+        CurrentDefault->ValueExpression = CurrentExpression;
+      } else {
+        //
+        // If used for a question, then the question will be read-only
+        //
+        CurrentStatement->ValueExpression = CurrentExpression;
+      }
+      break;
+
+    case EFI_IFR_RULE_OP:
+      CurrentExpression = CreateExpression (CurrentForm);
+      CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
+
+      CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;
+      InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
+      break;
+
+    //
+    // Image
+    //
+    case EFI_IFR_IMAGE_OP:
+      //
+      // Get ScopeOpcode from top of stack
+      //
+      PopScope (&ScopeOpCode);
+      PushScope (ScopeOpCode);
+
+      switch (ScopeOpCode) {
+      case EFI_IFR_FORM_SET_OP:
+        ImageId = &FormSet->ImageId;
+        break;
+
+      case EFI_IFR_FORM_OP:
+        ImageId = &CurrentForm->ImageId;
+        break;
+
+      case EFI_IFR_ONE_OF_OPTION_OP:
+        ImageId = &CurrentOption->ImageId;
+        break;
+
+      default:
+        ImageId = &CurrentStatement->ImageId;
+        break;
+      }
+
+      CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID));
+      break;
+
+    //
+    // Refresh
+    //
+    case EFI_IFR_REFRESH_OP:
+      CurrentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;
+      break;
+
+    //
+    // Vendor specific
+    //
+    case EFI_IFR_GUID_OP:
+      if (CompareGuid (&gTianoHiiIfrGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
+        //
+        // Tiano specific GUIDed opcodes
+        //
+        switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {
+        case EFI_IFR_EXTEND_OP_LABEL:
+          //
+          // just ignore label
+          //
+          break;
+
+        case EFI_IFR_EXTEND_OP_BANNER:
+          if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {
+            CopyMem (
+              &BannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][
+              ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],
+              &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,
+              sizeof (EFI_STRING_ID)
+              );
+          }
+          break;
+
+        case EFI_IFR_EXTEND_OP_CLASS:
+          CopyMem (&FormSet->Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16));
+          break;
+
+        case EFI_IFR_EXTEND_OP_SUBCLASS:
+          CopyMem (&FormSet->SubClass, &((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass, sizeof (UINT16));
+          break;
+
+        default:
+          break;
+        }
+      }
+      break;
+
+    //
+    // Scope End
+    //
+    case EFI_IFR_END_OP:
+      Status = PopScope (&ScopeOpCode);
+      if (EFI_ERROR (Status)) {
+        ResetScopeStack ();
+        return Status;
+      }
+
+      switch (ScopeOpCode) {
+      case EFI_IFR_FORM_SET_OP:
+        //
+        // End of FormSet, update FormSet IFR binary length
+        // to stop parsing substantial OpCodes
+        //
+        FormSet->IfrBinaryLength = OpCodeOffset;
+        break;
+
+      case EFI_IFR_FORM_OP:
+        //
+        // End of Form
+        //
+        CurrentForm = NULL;
+        break;
+
+      case EFI_IFR_ONE_OF_OPTION_OP:
+        //
+        // End of Option
+        //
+        CurrentOption = NULL;
+        break;
+
+      case EFI_IFR_SUBTITLE_OP:
+        mInScopeSubtitle = FALSE;
+        break;
+
+      case EFI_IFR_NO_SUBMIT_IF_OP:
+      case EFI_IFR_INCONSISTENT_IF_OP:
+        //
+        // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
+        //
+        break;
+
+      case EFI_IFR_SUPPRESS_IF_OP:
+        if (SuppressForOption) {
+          InScopeOptionSuppress = FALSE;
+        } else {
+          mInScopeSuppress = FALSE;
+        }
+        break;
+
+      case EFI_IFR_GRAY_OUT_IF_OP:
+        mInScopeGrayOut = FALSE;
+        break;
+
+      case EFI_IFR_DISABLE_IF_OP:
+        InScopeDisable = FALSE;
+        OpCodeDisabled = FALSE;
+        break;
+
+      case EFI_IFR_ONE_OF_OP:
+      case EFI_IFR_ORDERED_LIST_OP:
+        SuppressForOption = FALSE;
+        break;
+
+      case EFI_IFR_DEFAULT_OP:
+        InScopeDefault = FALSE;
+        break;
+
+      default:
+        if (IsExpressionOpCode (ScopeOpCode)) {
+          if (InScopeDisable) {
+            //
+            // Evaluate DisableIf expression
+            //
+            Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
+            if (EFI_ERROR (Status)) {
+              return Status;
+            }
+            if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
+              return EFI_INVALID_PARAMETER;
+            }
+
+            OpCodeDisabled = CurrentExpression->Result.Value.b;
+            //
+            // DisableIf Expression is only used once and not quequed, free it
+            //
+            DestroyExpression (CurrentExpression);
+          }
+
+          //
+          // End of current Expression
+          //
+          CurrentExpression = NULL;
+        }
+        break;
+      }
+      break;
+
+    default:
+      break;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c b/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c
new file mode 100644 (file)
index 0000000..5257f32
--- /dev/null
@@ -0,0 +1,1146 @@
+/** @file
+
+Copyright (c) 2004 - 2007, Intel Corporation
+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.
+
+Module Name:
+
+  InputHandler.c
+
+Abstract:
+
+  Implementation for handling user input from the User Interface
+
+Revision History
+
+
+**/
+
+#include "Ui.h"
+#include "Setup.h"
+
+
+/**
+  Get string or password input from user.
+
+  @param  MenuOption        Pointer to the current input menu.
+  @param  Prompt            The prompt string shown on popup window.
+  @param  StringPtr         Destination for use input string.
+
+  @retval EFI_SUCCESS       If string input is read successfully
+  @retval EFI_DEVICE_ERROR  If operation fails
+
+**/
+EFI_STATUS
+ReadString (
+  IN  UI_MENU_OPTION              *MenuOption,
+  IN  CHAR16                      *Prompt,
+  OUT CHAR16                      *StringPtr
+  )
+{
+  EFI_STATUS              Status;
+  EFI_INPUT_KEY           Key;
+  CHAR16                  NullCharacter;
+  UINTN                   ScreenSize;
+  CHAR16                  Space[2];
+  CHAR16                  KeyPad[2];
+  CHAR16                  *TempString;
+  CHAR16                  *BufferedString;
+  UINTN                   Index;
+  UINTN                   Count;
+  UINTN                   Start;
+  UINTN                   Top;
+  UINTN                   DimensionsWidth;
+  UINTN                   DimensionsHeight;
+  BOOLEAN                 CursorVisible;
+  UINTN                   Minimum;
+  UINTN                   Maximum;
+  FORM_BROWSER_STATEMENT  *Question;
+  BOOLEAN                 IsPassword;
+
+  DimensionsWidth  = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+  DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
+
+  NullCharacter    = CHAR_NULL;
+  ScreenSize       = GetStringWidth (Prompt) / sizeof (CHAR16);
+  Space[0]         = L' ';
+  Space[1]         = CHAR_NULL;
+
+  Question         = MenuOption->ThisTag;
+  Minimum          = (UINTN) Question->Minimum;
+  Maximum          = (UINTN) Question->Maximum;
+
+  if (Question->Operand == EFI_IFR_PASSWORD_OP) {
+    IsPassword = TRUE;
+  } else {
+    IsPassword = FALSE;
+  }
+
+  TempString = AllocateZeroPool ((Maximum + 1)* sizeof (CHAR16));
+  ASSERT (TempString);
+
+  if (ScreenSize < (Maximum + 1)) {
+    ScreenSize = Maximum + 1;
+  }
+
+  if ((ScreenSize + 2) > DimensionsWidth) {
+    ScreenSize = DimensionsWidth - 2;
+  }
+
+  BufferedString = AllocateZeroPool (ScreenSize * 2);
+  ASSERT (BufferedString);
+
+  Start = (DimensionsWidth - ScreenSize - 2) / 2 + gScreenDimensions.LeftColumn + 1;
+  Top   = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1;
+
+  //
+  // Display prompt for string
+  //
+  CreatePopUp (ScreenSize, 4, &NullCharacter, Prompt, Space, &NullCharacter);
+
+  gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));
+
+  CursorVisible = gST->ConOut->Mode->CursorVisible;
+  gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+  do {
+    Status = WaitForKeyStroke (&Key);
+    ASSERT_EFI_ERROR (Status);
+
+    gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));
+    switch (Key.UnicodeChar) {
+    case CHAR_NULL:
+      switch (Key.ScanCode) {
+      case SCAN_LEFT:
+        break;
+
+      case SCAN_RIGHT:
+        break;
+
+      case SCAN_ESC:
+        gBS->FreePool (TempString);
+        gBS->FreePool (BufferedString);
+        gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+        gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
+        return EFI_DEVICE_ERROR;
+
+      default:
+        break;
+      }
+
+      break;
+
+    case CHAR_CARRIAGE_RETURN:
+      if (GetStringWidth (StringPtr) >= ((Minimum + 1) * sizeof (CHAR16))) {
+
+        gBS->FreePool (TempString);
+        gBS->FreePool (BufferedString);
+        gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+        gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
+        return EFI_SUCCESS;
+      } else {
+        //
+        // Simply create a popup to tell the user that they had typed in too few characters.
+        // To save code space, we can then treat this as an error and return back to the menu.
+        //
+        do {
+          CreateDialog (4, TRUE, 0, NULL, &Key, &NullCharacter, gMiniString, gPressEnter, &NullCharacter);
+        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+
+        gBS->FreePool (TempString);
+        gBS->FreePool (BufferedString);
+        gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+        gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
+        return EFI_DEVICE_ERROR;
+      }
+
+      break;
+
+    case CHAR_BACKSPACE:
+      if (StringPtr[0] != CHAR_NULL) {
+        for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) {
+          TempString[Index] = StringPtr[Index];
+        }
+        //
+        // Effectively truncate string by 1 character
+        //
+        TempString[Index - 1] = CHAR_NULL;
+        StrCpy (StringPtr, TempString);
+      }
+
+    default:
+      //
+      // If it is the beginning of the string, don't worry about checking maximum limits
+      //
+      if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
+        StrnCpy (StringPtr, &Key.UnicodeChar, 1);
+        StrnCpy (TempString, &Key.UnicodeChar, 1);
+      } else if ((GetStringWidth (StringPtr) < ((Maximum + 1) * sizeof (CHAR16))) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
+        KeyPad[0] = Key.UnicodeChar;
+        KeyPad[1] = CHAR_NULL;
+        StrCat (StringPtr, KeyPad);
+        StrCat (TempString, KeyPad);
+      }
+
+      //
+      // If the width of the input string is now larger than the screen, we nee to
+      // adjust the index to start printing portions of the string
+      //
+      SetUnicodeMem (BufferedString, ScreenSize - 1, L' ');
+      PrintStringAt (Start + 1, Top + 3, BufferedString);
+
+      if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) {
+        Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2;
+      } else {
+        Index = 0;
+      }
+
+      if (IsPassword) {
+        gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3);
+      }
+
+      for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) {
+        BufferedString[Count] = StringPtr[Index];
+
+        if (IsPassword) {
+          PrintChar (L'*');
+        }
+      }
+
+      if (!IsPassword) {
+        PrintStringAt (Start + 1, Top + 3, BufferedString);
+      }
+      break;
+    }
+
+    gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+    gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3);
+  } while (TRUE);
+
+}
+
+
+/**
+  This routine reads a numeric value from the user input.
+
+  @param  Selection         Pointer to current selection.
+  @param  MenuOption        Pointer to the current input menu.
+
+  @retval EFI_SUCCESS       If numerical input is read successfully
+  @retval EFI_DEVICE_ERROR  If operation fails
+
+**/
+EFI_STATUS
+GetNumericInput (
+  IN  UI_MENU_SELECTION           *Selection,
+  IN  UI_MENU_OPTION              *MenuOption
+  )
+{
+  EFI_STATUS              Status;
+  UINTN                   Column;
+  UINTN                   Row;
+  CHAR16                  InputText[23];
+  CHAR16                  FormattedNumber[22];
+  UINT64                  PreviousNumber[20];
+  UINTN                   Count;
+  UINTN                   Loop;
+  BOOLEAN                 ManualInput;
+  BOOLEAN                 HexInput;
+  BOOLEAN                 DateOrTime;
+  UINTN                   InputWidth;
+  UINT64                  EditValue;
+  UINT64                  Step;
+  UINT64                  Minimum;
+  UINT64                  Maximum;
+  UINTN                   EraseLen;
+  UINT8                   Digital;
+  EFI_INPUT_KEY           Key;
+  EFI_HII_VALUE           *QuestionValue;
+  FORM_BROWSER_FORM       *Form;
+  FORM_BROWSER_FORMSET    *FormSet;
+  FORM_BROWSER_STATEMENT  *Question;
+
+  Column            = MenuOption->OptCol;
+  Row               = MenuOption->Row;
+  PreviousNumber[0] = 0;
+  Count             = 0;
+  InputWidth        = 0;
+  Digital           = 0;
+
+  FormSet       = Selection->FormSet;
+  Form          = Selection->Form;
+  Question      = MenuOption->ThisTag;
+  QuestionValue = &Question->HiiValue;
+  Step          = Question->Step;
+  Minimum       = Question->Minimum;
+  Maximum       = Question->Maximum;
+
+  if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {
+    DateOrTime = TRUE;
+  } else {
+    DateOrTime = FALSE;
+  }
+
+  //
+  // Prepare Value to be edit
+  //
+  EraseLen = 0;
+  EditValue = 0;
+  if (Question->Operand == EFI_IFR_DATE_OP) {
+    Step = 1;
+    Minimum = 1;
+
+    switch (MenuOption->Sequence) {
+    case 0:
+      Maximum = 12;
+      EraseLen = 4;
+      EditValue = QuestionValue->Value.date.Month;
+      break;
+
+    case 1:
+      Maximum = 31;
+      EraseLen = 3;
+      EditValue = QuestionValue->Value.date.Day;
+      break;
+
+    case 2:
+      Maximum = 0xffff;
+      EraseLen = 5;
+      EditValue = QuestionValue->Value.date.Year;
+      break;
+
+    default:
+      break;
+    }
+  } else if (Question->Operand == EFI_IFR_TIME_OP) {
+    Step = 1;
+    Minimum = 0;
+
+    switch (MenuOption->Sequence) {
+    case 0:
+      Maximum = 23;
+      EraseLen = 4;
+      EditValue = QuestionValue->Value.time.Hour;
+      break;
+
+    case 1:
+      Maximum = 59;
+      EraseLen = 3;
+      EditValue = QuestionValue->Value.time.Minute;
+      break;
+
+    case 2:
+      Maximum = 59;
+      EraseLen = 3;
+      EditValue = QuestionValue->Value.time.Second;
+      break;
+
+    default:
+      break;
+    }
+  } else {
+    //
+    // Numeric
+    //
+    EraseLen = gOptionBlockWidth;
+    EditValue = QuestionValue->Value.u64;
+    if (Maximum == 0) {
+      Maximum = (UINT64) -1;
+    }
+  }
+
+  if (Step == 0) {
+    ManualInput = TRUE;
+  } else {
+    ManualInput = FALSE;
+  }
+
+  if ((Question->Operand == EFI_IFR_NUMERIC_OP) &&
+      ((Question->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) {
+    HexInput = TRUE;
+  } else {
+    HexInput = FALSE;
+  }
+
+  if (ManualInput) {
+    if (HexInput) {
+      InputWidth = Question->StorageWidth * 2;
+    } else {
+      switch (Question->StorageWidth) {
+      case 1:
+        InputWidth = 3;
+        break;
+
+      case 2:
+        InputWidth = 5;
+        break;
+
+      case 4:
+        InputWidth = 10;
+        break;
+
+      case 8:
+        InputWidth = 20;
+        break;
+
+      default:
+        InputWidth = 0;
+        break;
+      }
+    }
+
+    InputText[0] = LEFT_NUMERIC_DELIMITER;
+    SetUnicodeMem (InputText + 1, InputWidth, L' ');
+    InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;
+    InputText[InputWidth + 2] = L'\0';
+
+    PrintAt (Column, Row, InputText);
+    Column++;
+  }
+
+  //
+  // First time we enter this handler, we need to check to see if
+  // we were passed an increment or decrement directive
+  //
+  do {
+    Key.UnicodeChar = CHAR_NULL;
+    if (gDirection != 0) {
+      Key.ScanCode  = gDirection;
+      gDirection    = 0;
+      goto TheKey2;
+    }
+
+    Status = WaitForKeyStroke (&Key);
+
+TheKey2:
+    switch (Key.UnicodeChar) {
+
+    case '+':
+    case '-':
+      if (Key.UnicodeChar == '+') {
+        Key.ScanCode = SCAN_RIGHT;
+      } else {
+        Key.ScanCode = SCAN_LEFT;
+      }
+      Key.UnicodeChar = CHAR_NULL;
+      goto TheKey2;
+
+    case CHAR_NULL:
+      switch (Key.ScanCode) {
+      case SCAN_LEFT:
+      case SCAN_RIGHT:
+        if (DateOrTime) {
+          //
+          // By setting this value, we will return back to the caller.
+          // We need to do this since an auto-refresh will destroy the adjustment
+          // based on what the real-time-clock is showing.  So we always commit
+          // upon changing the value.
+          //
+          gDirection = SCAN_DOWN;
+        }
+
+        if (!ManualInput) {
+          if (Key.ScanCode == SCAN_LEFT) {
+            if (EditValue > Step) {
+              EditValue = EditValue - Step;
+            } else {
+              EditValue = Minimum;
+            }
+          } else if (Key.ScanCode == SCAN_RIGHT) {
+            EditValue = EditValue + Step;
+            if (EditValue > Maximum) {
+              EditValue = Maximum;
+            }
+          }
+
+          ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));
+          if (Question->Operand == EFI_IFR_DATE_OP) {
+            if (MenuOption->Sequence == 2) {
+              //
+              // Year
+              //
+              UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%04d", EditValue);
+            } else {
+              //
+              // Month/Day
+              //
+              UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", EditValue);
+            }
+
+            if (MenuOption->Sequence == 0) {
+              FormattedNumber[EraseLen - 2] = DATE_SEPARATOR;
+            } else if (MenuOption->Sequence == 1) {
+              FormattedNumber[EraseLen - 1] = DATE_SEPARATOR;
+            }
+          } else if (Question->Operand == EFI_IFR_TIME_OP) {
+            UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", EditValue);
+
+            if (MenuOption->Sequence == 0) {
+              FormattedNumber[EraseLen - 2] = TIME_SEPARATOR;
+            } else if (MenuOption->Sequence == 1) {
+              FormattedNumber[EraseLen - 1] = TIME_SEPARATOR;
+            }
+          } else {
+            QuestionValue->Value.u64 = EditValue;
+            PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));
+          }
+
+          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+          for (Loop = 0; Loop < EraseLen; Loop++) {
+            PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");
+          }
+          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);
+
+          if (MenuOption->Sequence == 0) {
+            PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER);
+            Column = MenuOption->OptCol + 1;
+          }
+
+          PrintStringAt (Column, Row, FormattedNumber);
+
+          if (!DateOrTime || MenuOption->Sequence == 2) {
+            PrintChar (RIGHT_NUMERIC_DELIMITER);
+          }
+        }
+        break;
+
+      case SCAN_UP:
+      case SCAN_DOWN:
+        goto EnterCarriageReturn;
+
+      case SCAN_ESC:
+        return EFI_DEVICE_ERROR;
+
+      default:
+        break;
+      }
+
+      break;
+
+EnterCarriageReturn:
+
+    case CHAR_CARRIAGE_RETURN:
+      //
+      // Store Edit value back to Question
+      //
+      if (Question->Operand == EFI_IFR_DATE_OP) {
+        switch (MenuOption->Sequence) {
+        case 0:
+          QuestionValue->Value.date.Month = (UINT8) EditValue;
+          break;
+
+        case 1:
+          QuestionValue->Value.date.Day = (UINT8) EditValue;
+          break;
+
+        case 2:
+          QuestionValue->Value.date.Year = (UINT16) EditValue;
+          break;
+
+        default:
+          break;
+        }
+      } else if (Question->Operand == EFI_IFR_TIME_OP) {
+        switch (MenuOption->Sequence) {
+        case 0:
+          QuestionValue->Value.time.Hour = (UINT8) EditValue;
+          break;
+
+        case 1:
+          QuestionValue->Value.time.Minute = (UINT8) EditValue;
+          break;
+
+        case 2:
+          QuestionValue->Value.time.Second = (UINT8) EditValue;
+          break;
+
+        default:
+          break;
+        }
+      } else {
+        //
+        // Numeric
+        //
+        QuestionValue->Value.u64 = EditValue;
+      }
+
+      //
+      // Check to see if the Value is something reasonable against consistency limitations.
+      // If not, let's kick the error specified.
+      //
+      Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
+      if (EFI_ERROR (Status)) {
+        //
+        // Input value is not valid, restore Question Value
+        //
+        GetQuestionValue (FormSet, Form, Question, TRUE);
+      } else {
+        SetQuestionValue (FormSet, Form, Question, TRUE);
+        if (!DateOrTime || (Question->Storage != NULL)) {
+          //
+          // NV flag is unnecessary for RTC type of Date/Time
+          //
+          UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
+        }
+      }
+
+      return Status;
+      break;
+
+    case CHAR_BACKSPACE:
+      if (ManualInput) {
+        if (Count == 0) {
+          break;
+        }
+        //
+        // Remove a character
+        //
+        EditValue = PreviousNumber[Count - 1];
+        UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, FALSE);
+        Count--;
+        Column--;
+        PrintAt (Column, Row, L" ");
+      }
+      break;
+
+    default:
+      if (ManualInput) {
+        if (HexInput) {
+          if (!R8_IsHexDigit (&Digital, Key.UnicodeChar)) {
+            UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);
+            break;
+          }
+        } else {
+          if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') {
+            UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);
+            break;
+          }
+        }
+
+        //
+        // If Count exceed input width, there is no way more is valid
+        //
+        if (Count >= InputWidth) {
+          break;
+        }
+        //
+        // Someone typed something valid!
+        //
+        if (Count != 0) {
+          if (HexInput) {
+            EditValue = LShiftU64 (EditValue, 4) + Digital;
+          } else {
+            EditValue = MultU64x32 (EditValue, 10) + (Key.UnicodeChar - L'0');
+          }
+        } else {
+          if (HexInput) {
+            EditValue = Digital;
+          } else {
+            EditValue = Key.UnicodeChar - L'0';
+          }
+        }
+
+        if (EditValue > Maximum) {
+          UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);
+          EditValue = PreviousNumber[Count];
+          break;
+        } else {
+          UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, FALSE);
+        }
+
+        Count++;
+        PreviousNumber[Count] = EditValue;
+
+        PrintCharAt (Column, Row, Key.UnicodeChar);
+        Column++;
+      }
+      break;
+    }
+  } while (TRUE);
+
+}
+
+
+/**
+  Get selection for OneOf and OrderedList (Left/Right will be ignored).
+
+  @param  Selection         Pointer to current selection.
+  @param  MenuOption        Pointer to the current input menu.
+
+  @retval EFI_SUCCESS       If Option input is processed successfully
+  @retval EFI_DEVICE_ERROR  If operation fails
+
+**/
+EFI_STATUS
+GetSelectionInputPopUp (
+  IN  UI_MENU_SELECTION           *Selection,
+  IN  UI_MENU_OPTION              *MenuOption
+  )
+{
+  EFI_STATUS              Status;
+  EFI_INPUT_KEY           Key;
+  UINTN                   Index;
+  CHAR16                  *StringPtr;
+  CHAR16                  *TempStringPtr;
+  UINTN                   Index2;
+  UINTN                   TopOptionIndex;
+  UINTN                   HighlightOptionIndex;
+  UINTN                   Start;
+  UINTN                   End;
+  UINTN                   Top;
+  UINTN                   Bottom;
+  UINTN                   PopUpMenuLines;
+  UINTN                   MenuLinesInView;
+  UINTN                   PopUpWidth;
+  CHAR16                  Character;
+  INT32                   SavedAttribute;
+  BOOLEAN                 ShowDownArrow;
+  BOOLEAN                 ShowUpArrow;
+  UINTN                   DimensionsWidth;
+  LIST_ENTRY              *Link;
+  BOOLEAN                 OrderedList;
+  UINT8                   *ValueArray;
+  EFI_HII_VALUE           HiiValue;
+  EFI_HII_VALUE           *HiiValueArray;
+  UINTN                   OptionCount;
+  QUESTION_OPTION         *OneOfOption;
+  QUESTION_OPTION         *CurrentOption;
+  FORM_BROWSER_STATEMENT  *Question;
+
+  DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+
+  ValueArray        = NULL;
+  CurrentOption     = NULL;
+  ShowDownArrow     = FALSE;
+  ShowUpArrow       = FALSE;
+
+  StringPtr = AllocateZeroPool ((gOptionBlockWidth + 1) * 2);
+  ASSERT (StringPtr);
+
+  Question = MenuOption->ThisTag;
+  if (Question->Operand == EFI_IFR_ORDERED_LIST_OP) {
+    ValueArray = Question->BufferValue;
+    OrderedList = TRUE;
+  } else {
+    OrderedList = FALSE;
+  }
+
+  //
+  // Calculate Option count
+  //
+  if (OrderedList) {
+    for (Index = 0; Index < Question->MaxContainers; Index++) {
+      if (ValueArray[Index] == 0) {
+        break;
+      }
+    }
+
+    OptionCount = Index;
+  } else {
+    OptionCount = 0;
+    Link = GetFirstNode (&Question->OptionListHead);
+    while (!IsNull (&Question->OptionListHead, Link)) {
+      OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+
+      OptionCount++;
+
+      Link = GetNextNode (&Question->OptionListHead, Link);
+    }
+  }
+
+  //
+  // Prepare HiiValue array
+  //
+  HiiValueArray = AllocateZeroPool (OptionCount * sizeof (EFI_HII_VALUE));
+  ASSERT (HiiValueArray != NULL);
+  Link = GetFirstNode (&Question->OptionListHead);
+  for (Index = 0; Index < OptionCount; Index++) {
+    if (OrderedList) {
+      HiiValueArray[Index].Type = EFI_IFR_TYPE_NUM_SIZE_8;
+      HiiValueArray[Index].Value.u8 = ValueArray[Index];
+    } else {
+      OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+      CopyMem (&HiiValueArray[Index], &OneOfOption->Value, sizeof (EFI_HII_VALUE));
+      Link = GetNextNode (&Question->OptionListHead, Link);
+    }
+  }
+
+  //
+  // Move Suppressed Option to list tail
+  //
+  PopUpMenuLines = 0;
+  for (Index = 0; Index < OptionCount; Index++) {
+    OneOfOption = ValueToOption (Question, &HiiValueArray[OptionCount - Index - 1]);
+    if (OneOfOption == NULL) {
+      return EFI_NOT_FOUND;
+    }
+
+    RemoveEntryList (&OneOfOption->Link);
+
+    if ((OneOfOption->SuppressExpression != NULL) &&
+        (OneOfOption->SuppressExpression->Result.Value.b)) {
+      //
+      // This option is suppressed, insert to tail
+      //
+      InsertTailList (&Question->OptionListHead, &OneOfOption->Link);
+    } else {
+      //
+      // Insert to head
+      //
+      InsertHeadList (&Question->OptionListHead, &OneOfOption->Link);
+
+      PopUpMenuLines++;
+    }
+  }
+
+  //
+  // Get the number of one of options present and its size
+  //
+  PopUpWidth = 0;
+  HighlightOptionIndex = 0;
+  Link = GetFirstNode (&Question->OptionListHead);
+  for (Index = 0; Index < PopUpMenuLines; Index++) {
+    OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+
+    StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);
+    if (StrLen (StringPtr) > PopUpWidth) {
+      PopUpWidth = StrLen (StringPtr);
+    }
+    gBS->FreePool (StringPtr);
+
+    if (!OrderedList && CompareHiiValue (&Question->HiiValue, &OneOfOption->Value, NULL) == 0) {
+      //
+      // Find current selected Option for OneOf
+      //
+      HighlightOptionIndex = Index;
+    }
+
+    Link = GetNextNode (&Question->OptionListHead, Link);
+  }
+
+  //
+  // Perform popup menu initialization.
+  //
+  PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT;
+
+  SavedAttribute = gST->ConOut->Mode->Attribute;
+  gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+
+  if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) {
+    PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH;
+  }
+
+  Start  = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn;
+  End    = Start + PopUpWidth + POPUP_FRAME_WIDTH;
+  Top    = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;
+  Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - 1;
+
+  MenuLinesInView = Bottom - Top - 1;
+  if (MenuLinesInView >= PopUpMenuLines) {
+    Top     = Top + (MenuLinesInView - PopUpMenuLines) / 2;
+    Bottom  = Top + PopUpMenuLines + 1;
+  } else {
+    ShowDownArrow = TRUE;
+  }
+
+  if (HighlightOptionIndex > (MenuLinesInView - 1)) {
+    TopOptionIndex = HighlightOptionIndex - MenuLinesInView + 1;
+  } else {
+    TopOptionIndex = 0;
+  }
+
+  do {
+    //
+    // Clear that portion of the screen
+    //
+    ClearLines (Start, End, Top, Bottom, POPUP_TEXT | POPUP_BACKGROUND);
+
+    //
+    // Draw "One of" pop-up menu
+    //
+    Character = BOXDRAW_DOWN_RIGHT;
+    PrintCharAt (Start, Top, Character);
+    for (Index = Start; Index + 2 < End; Index++) {
+      if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) {
+        Character = GEOMETRICSHAPE_UP_TRIANGLE;
+      } else {
+        Character = BOXDRAW_HORIZONTAL;
+      }
+
+      PrintChar (Character);
+    }
+
+    Character = BOXDRAW_DOWN_LEFT;
+    PrintChar (Character);
+    Character = BOXDRAW_VERTICAL;
+    for (Index = Top + 1; Index < Bottom; Index++) {
+      PrintCharAt (Start, Index, Character);
+      PrintCharAt (End - 1, Index, Character);
+    }
+
+    //
+    // Move to top Option
+    //
+    Link = GetFirstNode (&Question->OptionListHead);
+    for (Index = 0; Index < TopOptionIndex; Index++) {
+      Link = GetNextNode (&Question->OptionListHead, Link);
+    }
+
+    //
+    // Display the One of options
+    //
+    Index2 = Top + 1;
+    for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) {
+      OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+      Link = GetNextNode (&Question->OptionListHead, Link);
+
+      StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);
+      //
+      // If the string occupies multiple lines, truncate it to fit in one line,
+      // and append a "..." for indication.
+      //
+      if (StrLen (StringPtr) > (PopUpWidth - 1)) {
+        TempStringPtr = AllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1));
+        ASSERT ( TempStringPtr != NULL );
+        CopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5)));
+        gBS->FreePool (StringPtr);
+        StringPtr = TempStringPtr;
+        StrCat (StringPtr, L"...");
+      }
+
+      if (Index == HighlightOptionIndex) {
+          //
+          // Highlight the selected one
+          //
+          CurrentOption = OneOfOption;
+
+          gST->ConOut->SetAttribute (gST->ConOut, PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND);
+          PrintStringAt (Start + 2, Index2, StringPtr);
+          gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+        } else {
+          gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+          PrintStringAt (Start + 2, Index2, StringPtr);
+        }
+
+      Index2++;
+      gBS->FreePool (StringPtr);
+    }
+
+    Character = BOXDRAW_UP_RIGHT;
+    PrintCharAt (Start, Bottom, Character);
+    for (Index = Start; Index + 2 < End; Index++) {
+      if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) {
+        Character = GEOMETRICSHAPE_DOWN_TRIANGLE;
+      } else {
+        Character = BOXDRAW_HORIZONTAL;
+      }
+
+      PrintChar (Character);
+    }
+
+    Character = BOXDRAW_UP_LEFT;
+    PrintChar (Character);
+
+    //
+    // Get User selection
+    //
+    Key.UnicodeChar = CHAR_NULL;
+    if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) {
+      Key.ScanCode  = gDirection;
+      gDirection    = 0;
+      goto TheKey;
+    }
+
+    Status = WaitForKeyStroke (&Key);
+
+TheKey:
+    switch (Key.UnicodeChar) {
+    case '+':
+      if (OrderedList) {
+        if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {
+          //
+          // Highlight reaches the top of the popup window, scroll one menu item.
+          //
+          TopOptionIndex--;
+          ShowDownArrow = TRUE;
+        }
+
+        if (TopOptionIndex == 0) {
+          ShowUpArrow = FALSE;
+        }
+
+        if (HighlightOptionIndex > 0) {
+          HighlightOptionIndex--;
+
+          SwapListEntries (CurrentOption->Link.BackLink, &CurrentOption->Link);
+        }
+      }
+      break;
+
+    case '-':
+      //
+      // If an ordered list op-code, we will allow for a popup of +/- keys
+      // to create an ordered list of items
+      //
+      if (OrderedList) {
+        if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&
+            (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {
+          //
+          // Highlight reaches the bottom of the popup window, scroll one menu item.
+          //
+          TopOptionIndex++;
+          ShowUpArrow = TRUE;
+        }
+
+        if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {
+          ShowDownArrow = FALSE;
+        }
+
+        if (HighlightOptionIndex < (PopUpMenuLines - 1)) {
+          HighlightOptionIndex++;
+
+          SwapListEntries (&CurrentOption->Link, CurrentOption->Link.ForwardLink);
+        }
+      }
+      break;
+
+    case CHAR_NULL:
+      switch (Key.ScanCode) {
+      case SCAN_UP:
+      case SCAN_DOWN:
+        if (Key.ScanCode == SCAN_UP) {
+          if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {
+            //
+            // Highlight reaches the top of the popup window, scroll one menu item.
+            //
+            TopOptionIndex--;
+            ShowDownArrow = TRUE;
+          }
+
+          if (TopOptionIndex == 0) {
+            ShowUpArrow = FALSE;
+          }
+
+          if (HighlightOptionIndex > 0) {
+            HighlightOptionIndex--;
+          }
+        } else {
+          if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&
+              (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {
+            //
+            // Highlight reaches the bottom of the popup window, scroll one menu item.
+            //
+            TopOptionIndex++;
+            ShowUpArrow = TRUE;
+          }
+
+          if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {
+            ShowDownArrow = FALSE;
+          }
+
+          if (HighlightOptionIndex < (PopUpMenuLines - 1)) {
+            HighlightOptionIndex++;
+          }
+        }
+        break;
+
+      case SCAN_ESC:
+        gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
+
+        //
+        // Restore link list order for orderedlist
+        //
+        if (OrderedList) {
+          HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_8;
+          HiiValue.Value.u64 = 0;
+          for (Index = 0; Index < Question->MaxContainers; Index++) {
+            HiiValue.Value.u8 = ValueArray[Index];
+            if (HiiValue.Value.u8) {
+              break;
+            }
+
+            OneOfOption = ValueToOption (Question, &HiiValue);
+            if (OneOfOption == NULL) {
+              return EFI_NOT_FOUND;
+            }
+
+            RemoveEntryList (&OneOfOption->Link);
+            InsertTailList (&Question->OptionListHead, &OneOfOption->Link);
+          }
+        }
+
+        gBS->FreePool (HiiValueArray);
+        return EFI_DEVICE_ERROR;
+
+      default:
+        break;
+      }
+
+      break;
+
+    case CHAR_CARRIAGE_RETURN:
+      //
+      // return the current selection
+      //
+      if (OrderedList) {
+        Index = 0;
+        Link = GetFirstNode (&Question->OptionListHead);
+        while (!IsNull (&Question->OptionListHead, Link)) {
+          OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+
+          Question->BufferValue[Index] = OneOfOption->Value.Value.u8;
+
+          Index++;
+          if (Index > Question->MaxContainers) {
+            break;
+          }
+
+          Link = GetNextNode (&Question->OptionListHead, Link);
+        }
+      } else {
+        CopyMem (&Question->HiiValue, &CurrentOption->Value, sizeof (EFI_HII_VALUE));
+      }
+
+      gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
+      gBS->FreePool (HiiValueArray);
+
+      Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
+      if (EFI_ERROR (Status)) {
+        //
+        // Input value is not valid, restore Question Value
+        //
+        GetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);
+      } else {
+        SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);
+        UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
+      }
+
+      return Status;
+
+    default:
+      break;
+    }
+  } while (TRUE);
+
+}
+
+EFI_STATUS
+WaitForKeyStroke (
+  OUT  EFI_INPUT_KEY           *Key
+  )
+{
+  EFI_STATUS  Status;
+
+  do {
+    UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, 0);
+    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);
+  } while (EFI_ERROR(Status));
+
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
new file mode 100644 (file)
index 0000000..631f641
--- /dev/null
@@ -0,0 +1,928 @@
+/** @file
+Copyright (c) 2004 - 2007, Intel Corporation
+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.
+
+Module Name:
+  Presentation.c
+
+Abstract:
+
+  Some presentation routines.
+
+
+**/
+
+#include "Setup.h"
+#include "Ui.h"
+
+BOOLEAN            mHiiPackageListUpdated;
+UI_MENU_SELECTION  *gCurrentSelection;
+
+
+/**
+  Clear retangle with specified text attribute.
+
+  @param  LeftColumn     Left column of retangle.
+  @param  RightColumn    Right column of retangle.
+  @param  TopRow         Start row of retangle.
+  @param  BottomRow      End row of retangle.
+  @param  TextAttribute  The character foreground and background.
+
+  @return None.
+
+**/
+VOID
+ClearLines (
+  UINTN                                       LeftColumn,
+  UINTN                                       RightColumn,
+  UINTN                                       TopRow,
+  UINTN                                       BottomRow,
+  UINTN                                       TextAttribute
+  )
+{
+  CHAR16  *Buffer;
+  UINTN   Row;
+
+  //
+  // For now, allocate an arbitrarily long buffer
+  //
+  Buffer = AllocateZeroPool (0x10000);
+  ASSERT (Buffer != NULL);
+
+  //
+  // Set foreground and background as defined
+  //
+  gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);
+
+  //
+  // Much faster to buffer the long string instead of print it a character at a time
+  //
+  SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');
+
+  //
+  // Clear the desired area with the appropriate foreground/background
+  //
+  for (Row = TopRow; Row <= BottomRow; Row++) {
+    PrintStringAt (LeftColumn, Row, Buffer);
+  }
+
+  gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);
+
+  gBS->FreePool (Buffer);
+  return ;
+}
+
+VOID
+NewStrCat (
+  CHAR16                                      *Destination,
+  CHAR16                                      *Source
+  )
+{
+  UINTN Length;
+
+  for (Length = 0; Destination[Length] != 0; Length++)
+    ;
+
+  //
+  // We now have the length of the original string
+  // We can safely assume for now that we are concatenating a narrow value to this string.
+  // For instance, the string is "XYZ" and cat'ing ">"
+  // If this assumption changes, we need to make this routine a bit more complex
+  //
+  Destination[Length] = NARROW_CHAR;
+  Length++;
+
+  StrCpy (Destination + Length, Source);
+}
+
+UINTN
+GetStringWidth (
+  CHAR16                                      *String
+  )
+{
+  UINTN Index;
+  UINTN Count;
+  UINTN IncrementValue;
+
+  Index           = 0;
+  Count           = 0;
+  IncrementValue  = 1;
+
+  do {
+    //
+    // Advance to the null-terminator or to the first width directive
+    //
+    for (;
+         (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);
+         Index++, Count = Count + IncrementValue
+        )
+      ;
+
+    //
+    // We hit the null-terminator, we now have a count
+    //
+    if (String[Index] == 0) {
+      break;
+    }
+    //
+    // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
+    // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
+    //
+    if (String[Index] == NARROW_CHAR) {
+      //
+      // Skip to the next character
+      //
+      Index++;
+      IncrementValue = 1;
+    } else {
+      //
+      // Skip to the next character
+      //
+      Index++;
+      IncrementValue = 2;
+    }
+  } while (String[Index] != 0);
+
+  //
+  // Increment by one to include the null-terminator in the size
+  //
+  Count++;
+
+  return Count * sizeof (CHAR16);
+}
+
+VOID
+DisplayPageFrame (
+  VOID
+  )
+{
+  UINTN                  Index;
+  UINT8                  Line;
+  UINT8                  Alignment;
+  CHAR16                 Character;
+  CHAR16                 *Buffer;
+  CHAR16                 *StrFrontPageBanner;
+  UINTN                  Row;
+  EFI_SCREEN_DESCRIPTOR  LocalScreen;
+
+  ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));
+  gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);
+  ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);
+
+  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+  //
+  // For now, allocate an arbitrarily long buffer
+  //
+  Buffer = AllocateZeroPool (0x10000);
+  ASSERT (Buffer != NULL);
+
+  Character = BOXDRAW_HORIZONTAL;
+
+  for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {
+    Buffer[Index] = Character;
+  }
+
+  if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
+    //
+    //    ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);
+    //
+    ClearLines (
+      LocalScreen.LeftColumn,
+      LocalScreen.RightColumn,
+      LocalScreen.TopRow,
+      FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,
+      BANNER_TEXT | BANNER_BACKGROUND
+      );
+    //
+    //    for (Line = 0; Line < BANNER_HEIGHT; Line++) {
+    //
+    for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {
+      //
+      //      for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {
+      //
+      for (Alignment = (UINT8) LocalScreen.LeftColumn;
+           Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;
+           Alignment++
+          ) {
+        if (BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn] != 0x0000) {
+          StrFrontPageBanner = GetToken (
+                                BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn],
+                                FrontPageHandle
+                                );
+        } else {
+          continue;
+        }
+
+        switch (Alignment - LocalScreen.LeftColumn) {
+        case 0:
+          //
+          // Handle left column
+          //
+          PrintStringAt (LocalScreen.LeftColumn, Line, StrFrontPageBanner);
+          break;
+
+        case 1:
+          //
+          // Handle center column
+          //
+          PrintStringAt (
+            LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
+            Line,
+            StrFrontPageBanner
+            );
+          break;
+
+        case 2:
+          //
+          // Handle right column
+          //
+          PrintStringAt (
+            LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
+            Line,
+            StrFrontPageBanner
+            );
+          break;
+        }
+
+        gBS->FreePool (StrFrontPageBanner);
+      }
+    }
+  }
+
+  ClearLines (
+    LocalScreen.LeftColumn,
+    LocalScreen.RightColumn,
+    LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT,
+    LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,
+    KEYHELP_TEXT | KEYHELP_BACKGROUND
+    );
+
+  if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
+    ClearLines (
+      LocalScreen.LeftColumn,
+      LocalScreen.RightColumn,
+      LocalScreen.TopRow,
+      LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,
+      TITLE_TEXT | TITLE_BACKGROUND
+      );
+    //
+    // Print Top border line
+    // +------------------------------------------------------------------------------+
+    // ?                                                                             ?
+    // +------------------------------------------------------------------------------+
+    //
+    Character = BOXDRAW_DOWN_RIGHT;
+
+    PrintChar (Character);
+    PrintString (Buffer);
+
+    Character = BOXDRAW_DOWN_LEFT;
+    PrintChar (Character);
+
+    Character = BOXDRAW_VERTICAL;
+    for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {
+      PrintCharAt (LocalScreen.LeftColumn, Row, Character);
+      PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
+    }
+
+    Character = BOXDRAW_UP_RIGHT;
+    PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);
+    PrintString (Buffer);
+
+    Character = BOXDRAW_UP_LEFT;
+    PrintChar (Character);
+
+    if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+      //
+      // Print Bottom border line
+      // +------------------------------------------------------------------------------+
+      // ?                                                                             ?
+      // +------------------------------------------------------------------------------+
+      //
+      Character = BOXDRAW_DOWN_RIGHT;
+      PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);
+
+      PrintString (Buffer);
+
+      Character = BOXDRAW_DOWN_LEFT;
+      PrintChar (Character);
+      Character = BOXDRAW_VERTICAL;
+      for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1;
+           Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;
+           Row++
+          ) {
+        PrintCharAt (LocalScreen.LeftColumn, Row, Character);
+        PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
+      }
+
+      Character = BOXDRAW_UP_RIGHT;
+      PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);
+
+      PrintString (Buffer);
+
+      Character = BOXDRAW_UP_LEFT;
+      PrintChar (Character);
+    }
+  }
+
+  gBS->FreePool (Buffer);
+
+}
+
+
+/**
+  Evaluate all expressions in a Form.
+
+  @param  FormSet        FormSet this Form belongs to.
+  @param  Form           The Form.
+
+  @retval EFI_SUCCESS    The expression evaluated successfuly
+
+**/
+EFI_STATUS
+EvaluateFormExpressions (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  IN FORM_BROWSER_FORM     *Form
+  )
+{
+  EFI_STATUS       Status;
+  LIST_ENTRY       *Link;
+  FORM_EXPRESSION  *Expression;
+
+  Link = GetFirstNode (&Form->ExpressionListHead);
+  while (!IsNull (&Form->ExpressionListHead, Link)) {
+    Expression = FORM_EXPRESSION_FROM_LINK (Link);
+    Link = GetNextNode (&Form->ExpressionListHead, Link);
+
+    if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||
+        Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
+      //
+      // Postpone Form validation to Question editing or Form submiting
+      //
+      continue;
+    }
+
+    Status = EvaluateExpression (FormSet, Form, Expression);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/*
++------------------------------------------------------------------------------+
+?F2=Previous Page                 Setup Page                                  ?
++------------------------------------------------------------------------------+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
++------------------------------------------------------------------------------+
+?F1=Scroll Help                 F9=Reset to Defaults        F10=Save and Exit ?
+| ^"=Move Highlight          <Spacebar> Toggles Checkbox   Esc=Discard Changes |
++------------------------------------------------------------------------------+
+*/
+EFI_STATUS
+DisplayForm (
+  IN OUT UI_MENU_SELECTION           *Selection
+  )
+{
+  CHAR16                 *StringPtr;
+  UINT16                 MenuItemCount;
+  EFI_HII_HANDLE         Handle;
+  BOOLEAN                Suppress;
+  EFI_SCREEN_DESCRIPTOR  LocalScreen;
+  UINT16                 Width;
+  UINTN                  ArrayEntry;
+  CHAR16                 *OutputString;
+  LIST_ENTRY             *Link;
+  FORM_BROWSER_STATEMENT *Statement;
+  UINT16                 NumberOfLines;
+  EFI_STATUS             Status;
+
+  Handle        = Selection->Handle;
+  MenuItemCount = 0;
+  ArrayEntry    = 0;
+  OutputString  = NULL;
+
+  UiInitMenu ();
+
+  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+  StringPtr = GetToken (Selection->FormSet->FormSetTitle, Handle);
+
+  if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
+    gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);
+    PrintStringAt (
+      (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,
+      LocalScreen.TopRow + 1,
+      StringPtr
+      );
+  }
+
+  if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+    gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+    //
+    // Display the infrastructure strings
+    //
+    if (!IsListEmpty (&gMenuList)) {
+      PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.TopRow + 1, gFunctionTwoString);
+    }
+
+    PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 4, gFunctionOneString);
+    PrintStringAt (
+      LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
+      LocalScreen.BottomRow - 4,
+      gFunctionNineString
+      );
+    PrintStringAt (
+      LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
+      LocalScreen.BottomRow - 4,
+      gFunctionTenString
+      );
+    PrintAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 3, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+    PrintStringAt (
+      LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
+      LocalScreen.BottomRow - 3,
+      gEscapeString
+      );
+  }
+  //
+  // Remove Buffer allocated for StringPtr after it has been used.
+  //
+  gBS->FreePool (StringPtr);
+
+  //
+  // Evaluate all the Expressions in this Form
+  //
+  Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Link = GetFirstNode (&Selection->Form->StatementListHead);
+  while (!IsNull (&Selection->Form->StatementListHead, Link)) {
+    Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+
+    if (Statement->SuppressExpression != NULL) {
+      Suppress = Statement->SuppressExpression->Result.Value.b;
+    } else {
+      Suppress = FALSE;
+    }
+
+    if (!Suppress) {
+      StringPtr = GetToken (Statement->Prompt, Handle);
+
+      Width     = GetWidth (Statement, Handle);
+
+      NumberOfLines = 1;
+      ArrayEntry = 0;
+      for (; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {
+        //
+        // If there is more string to process print on the next row and increment the Skip value
+        //
+        if (StrLen (&StringPtr[ArrayEntry])) {
+          NumberOfLines++;
+        }
+
+        gBS->FreePool (OutputString);
+      }
+
+      //
+      // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
+      // it in UiFreeMenu.
+      //
+      UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);
+      MenuItemCount++;
+    }
+
+    Link = GetNextNode (&Selection->Form->StatementListHead, Link);
+  }
+
+  Status = UiDisplayMenu (Selection);
+
+  UiFreeMenu ();
+
+  return Status;
+}
+
+VOID
+InitializeBrowserStrings (
+  VOID
+  )
+{
+  gFunctionOneString    = GetToken (STRING_TOKEN (FUNCTION_ONE_STRING), gHiiHandle);
+  gFunctionTwoString    = GetToken (STRING_TOKEN (FUNCTION_TWO_STRING), gHiiHandle);
+  gFunctionNineString   = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);
+  gFunctionTenString    = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);
+  gEnterString          = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);
+  gEnterCommitString    = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);
+  gEscapeString         = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);
+  gSaveFailed           = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);
+  gMoveHighlight        = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);
+  gMakeSelection        = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);
+  gDecNumericInput      = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);
+  gHexNumericInput      = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle);
+  gToggleCheckBox       = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);
+  gPromptForData        = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);
+  gPromptForPassword    = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);
+  gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);
+  gConfirmPassword      = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);
+  gConfirmError         = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);
+  gPassowordInvalid     = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);
+  gPressEnter           = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);
+  gEmptyString          = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+  gAreYouSure           = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);
+  gYesResponse          = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);
+  gNoResponse           = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);
+  gMiniString           = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);
+  gPlusString           = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);
+  gMinusString          = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);
+  gAdjustNumber         = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);
+  return ;
+}
+
+VOID
+FreeBrowserStrings (
+  VOID
+  )
+{
+  SafeFreePool (gFunctionOneString);
+  SafeFreePool (gFunctionTwoString);
+  SafeFreePool (gFunctionNineString);
+  SafeFreePool (gFunctionTenString);
+  SafeFreePool (gEnterString);
+  SafeFreePool (gEnterCommitString);
+  SafeFreePool (gEscapeString);
+  SafeFreePool (gMoveHighlight);
+  SafeFreePool (gMakeSelection);
+  SafeFreePool (gDecNumericInput);
+  SafeFreePool (gHexNumericInput);
+  SafeFreePool (gToggleCheckBox);
+  SafeFreePool (gPromptForData);
+  SafeFreePool (gPromptForPassword);
+  SafeFreePool (gPromptForNewPassword);
+  SafeFreePool (gConfirmPassword);
+  SafeFreePool (gPassowordInvalid);
+  SafeFreePool (gConfirmError);
+  SafeFreePool (gPressEnter);
+  SafeFreePool (gEmptyString);
+  SafeFreePool (gAreYouSure);
+  SafeFreePool (gYesResponse);
+  SafeFreePool (gNoResponse);
+  SafeFreePool (gMiniString);
+  SafeFreePool (gPlusString);
+  SafeFreePool (gMinusString);
+  SafeFreePool (gAdjustNumber);
+  return ;
+}
+
+
+/**
+  Update key's help imformation
+
+  @param  MenuOption     The Menu option
+  @param  Selected       Whether or not a tag be selected
+
+  @return None
+
+**/
+VOID
+UpdateKeyHelp (
+  IN  UI_MENU_OPTION              *MenuOption,
+  IN  BOOLEAN                     Selected
+  )
+{
+  UINTN                  SecCol;
+  UINTN                  ThdCol;
+  UINTN                  LeftColumnOfHelp;
+  UINTN                  RightColumnOfHelp;
+  UINTN                  TopRowOfHelp;
+  UINTN                  BottomRowOfHelp;
+  UINTN                  StartColumnOfHelp;
+  EFI_SCREEN_DESCRIPTOR  LocalScreen;
+  FORM_BROWSER_STATEMENT *Statement;
+
+  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+  SecCol            = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;
+  ThdCol            = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3;
+
+  StartColumnOfHelp = LocalScreen.LeftColumn + 2;
+  LeftColumnOfHelp  = LocalScreen.LeftColumn + 1;
+  RightColumnOfHelp = LocalScreen.RightColumn - 2;
+  TopRowOfHelp      = LocalScreen.BottomRow - 4;
+  BottomRowOfHelp   = LocalScreen.BottomRow - 3;
+
+  if (gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS) {
+    return ;
+  }
+
+  gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+  Statement = MenuOption->ThisTag;
+  switch (Statement->Operand) {
+  case EFI_IFR_ORDERED_LIST_OP:
+  case EFI_IFR_ONE_OF_OP:
+  case EFI_IFR_NUMERIC_OP:
+  case EFI_IFR_TIME_OP:
+  case EFI_IFR_DATE_OP:
+    ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+    if (!Selected) {
+      if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+        PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
+        PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
+        PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
+        PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+      }
+
+      if ((Statement->Operand == EFI_IFR_DATE_OP) ||
+          (Statement->Operand == EFI_IFR_TIME_OP) ||
+          (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) {
+        PrintAt (
+          StartColumnOfHelp,
+          BottomRowOfHelp,
+          L"%c%c%c%c%s",
+          ARROW_UP,
+          ARROW_DOWN,
+          ARROW_RIGHT,
+          ARROW_LEFT,
+          gMoveHighlight
+          );
+        PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);
+      } else {
+        PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+        PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
+      }
+    } else {
+      PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);
+
+      //
+      // If it is a selected numeric with manual input, display different message
+      //
+      if ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step == 0)) {
+        PrintStringAt (
+          SecCol,
+          TopRowOfHelp,
+          (Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput
+          );
+      } else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) {
+        PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+      }
+
+      if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {
+        PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);
+        PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);
+      }
+
+      PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+    }
+    break;
+
+  case EFI_IFR_CHECKBOX_OP:
+    ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+    if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+      PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
+      PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
+      PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
+      PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+    }
+
+    PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+    PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);
+    break;
+
+  case EFI_IFR_REF_OP:
+  case EFI_IFR_PASSWORD_OP:
+  case EFI_IFR_STRING_OP:
+  case EFI_IFR_TEXT_OP:
+  case EFI_IFR_ACTION_OP:
+  case EFI_IFR_RESET_BUTTON_OP:
+    ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+    if (!Selected) {
+      if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+        PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
+        PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
+        PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
+        PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+      }
+
+      PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+      if (Statement->Operand != EFI_IFR_TEXT_OP) {
+        PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
+      }
+    } else {
+      if (Statement->Operand != EFI_IFR_REF_OP) {
+        PrintStringAt (
+          (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,
+          BottomRowOfHelp,
+          gEnterCommitString
+          );
+        PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+      }
+    }
+    break;
+
+  default:
+    break;
+  }
+}
+
+EFI_STATUS
+FormUpdateNotify (
+  IN UINT8                              PackageType,
+  IN CONST EFI_GUID                     *PackageGuid,
+  IN CONST EFI_HII_PACKAGE_HEADER       *Package,
+  IN EFI_HII_HANDLE                     Handle,
+  IN EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType
+  )
+{
+  mHiiPackageListUpdated = TRUE;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SetupBrowser (
+  IN OUT UI_MENU_SELECTION    *Selection
+  )
+{
+  EFI_STATUS                      Status;
+  LIST_ENTRY                      *Link;
+  EFI_BROWSER_ACTION_REQUEST      ActionRequest;
+  EFI_HANDLE                      NotifyHandle;
+  EFI_HII_VALUE                   *HiiValue;
+  FORM_BROWSER_STATEMENT          *Statement;
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;
+
+  gMenuRefreshHead = NULL;
+  gResetRequired = FALSE;
+  gNvUpdateRequired = FALSE;
+
+  UiInitMenuList ();
+
+  //
+  // Register notify for Form package update
+  //
+  Status = mHiiDatabase->RegisterPackageNotify (
+                           mHiiDatabase,
+                           EFI_HII_PACKAGE_FORM,
+                           NULL,
+                           FormUpdateNotify,
+                           EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+                           &NotifyHandle
+                           );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  do {
+    //
+    // Displays the Header and Footer borders
+    //
+    DisplayPageFrame ();
+
+    //
+    // Initialize Selection->Form
+    //
+    if (Selection->FormId == 0) {
+      //
+      // Zero FormId indicates display the first Form in a FormSet
+      //
+      Link = GetFirstNode (&Selection->FormSet->FormListHead);
+
+      Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+      Selection->FormId = Selection->Form->FormId;
+    } else {
+      Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);
+    }
+
+    //
+    // Load Questions' Value for display
+    //
+    Status = LoadFormConfig (Selection->FormSet, Selection->Form);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    // Display form
+    //
+    Status = DisplayForm (Selection);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    // Check Selected Statement (if press ESC, Selection->Statement will be NULL)
+    //
+    Statement = Selection->Statement;
+    if (Statement != NULL) {
+      if (Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) {
+        gResetRequired = TRUE;
+      }
+
+      //
+      // Reset FormPackage update flag
+      //
+      mHiiPackageListUpdated = FALSE;
+
+      if (Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK && Statement->Operand != EFI_IFR_PASSWORD_OP) {
+        ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+
+        HiiValue = &Statement->HiiValue;
+        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
+          //
+          // Create String in HII database for Configuration Driver to retrieve
+          //
+          HiiValue->Value.string = NewString ((CHAR16 *) Statement->BufferValue, Selection->FormSet->HiiHandle);
+        }
+
+        ConfigAccess = Selection->FormSet->ConfigAccess;
+        if (ConfigAccess == NULL) {
+          return EFI_UNSUPPORTED;
+        }
+        Status = ConfigAccess->Callback (
+                                 ConfigAccess,
+                                 EFI_BROWSER_ACTION_CHANGING,
+                                 Statement->QuestionId,
+                                 HiiValue->Type,
+                                 &HiiValue->Value,
+                                 &ActionRequest
+                                 );
+
+        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
+          //
+          // Clean the String in HII Database
+          //
+          DeleteString (HiiValue->Value.string, Selection->FormSet->HiiHandle);
+        }
+
+        if (!EFI_ERROR (Status)) {
+          switch (ActionRequest) {
+          case EFI_BROWSER_ACTION_REQUEST_RESET:
+            gResetRequired = TRUE;
+            break;
+
+          case EFI_BROWSER_ACTION_REQUEST_SUBMIT:
+            SubmitForm (Selection->FormSet, Selection->Form);
+            break;
+
+          case EFI_BROWSER_ACTION_REQUEST_EXIT:
+            Selection->Action = UI_ACTION_EXIT;
+            gNvUpdateRequired = FALSE;
+            break;
+
+          default:
+            break;
+          }
+        }
+      }
+
+      //
+      // Check whether Form Package has been updated during Callback
+      //
+      if (mHiiPackageListUpdated && (Selection->Action == UI_ACTION_REFRESH_FORM)) {
+        //
+        // Force to reparse IFR binary of target Formset
+        //
+        Selection->Action = UI_ACTION_REFRESH_FORMSET;
+      }
+    }
+  } while (Selection->Action == UI_ACTION_REFRESH_FORM);
+
+  //
+  // Unregister notify for Form package update
+  //
+  Status = mHiiDatabase->UnregisterPackageNotify (
+                           mHiiDatabase,
+                           NotifyHandle
+                           );
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Print.c b/MdeModulePkg/Universal/SetupBrowserDxe/Print.c
new file mode 100644 (file)
index 0000000..6cc50c3
--- /dev/null
@@ -0,0 +1,331 @@
+/** @file
+
+Copyright (c) 2004 - 2007, Intel Corporation
+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.
+
+Module Name:
+
+  Print.c
+
+Abstract:
+
+  Basic Ascii AvSPrintf() function named VSPrint(). VSPrint() enables very
+  simple implemenation of SPrint() and Print() to support debug.
+
+  You can not Print more than EFI_DRIVER_LIB_MAX_PRINT_BUFFER characters at a
+  time. This makes the implementation very simple.
+
+  VSPrint, Print, SPrint format specification has the follwoing form
+
+  %type
+
+  type:
+    'S','s' - argument is an Unicode string
+    'c' - argument is an ascii character
+    '%' - Print a %
+
+
+**/
+
+//@MT:#include "Tiano.h"
+//@MT:#include "EfiDriverLib.h"
+//@MT:#include "EfiPrintLib.h"
+//@MT:#include "EfiStdArg.h"
+//@MT:#include "TianoHii.h"
+#include "Setup.h"
+
+UINTN
+ValueToString (
+  IN  OUT CHAR16  *Buffer,
+  IN  BOOLEAN     Flags,
+  IN  INT64       Value
+  );
+
+UINTN
+PrintInternal (
+  IN UINTN                            Column,
+  IN UINTN                            Row,
+  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL     *Out,
+  IN CHAR16                           *fmt,
+  IN VA_LIST                          args
+  )
+//
+// Display string worker for: Print, PrintAt, IPrint, IPrintAt
+//
+{
+  CHAR16  *Buffer;
+  CHAR16  *BackupBuffer;
+  UINTN   Index;
+  UINTN   PreviousIndex;
+
+  //
+  // For now, allocate an arbitrarily long buffer
+  //
+  Buffer        = AllocateZeroPool (0x10000);
+  BackupBuffer  = AllocateZeroPool (0x10000);
+  ASSERT (Buffer);
+  ASSERT (BackupBuffer);
+
+  if (Column != (UINTN) -1) {
+    Out->SetCursorPosition (Out, Column, Row);
+  }
+
+  UnicodeVSPrint (Buffer, 0x10000, fmt, args);
+
+  Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;
+
+  Out->SetAttribute (Out, Out->Mode->Attribute);
+
+  Index         = 0;
+  PreviousIndex = 0;
+
+  do {
+    for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) {
+      BackupBuffer[Index] = Buffer[Index];
+    }
+
+    if (Buffer[Index] == 0) {
+      break;
+    }
+    //
+    // Null-terminate the temporary string
+    //
+    BackupBuffer[Index] = 0;
+
+    //
+    // Print this out, we are about to switch widths
+    //
+    Out->OutputString (Out, &BackupBuffer[PreviousIndex]);
+
+    //
+    // Preserve the current index + 1, since this is where we will start printing from next
+    //
+    PreviousIndex = Index + 1;
+
+    //
+    // We are at a narrow or wide character directive.  Set attributes and strip it and print it
+    //
+    if (Buffer[Index] == NARROW_CHAR) {
+      //
+      // Preserve bits 0 - 6 and zero out the rest
+      //
+      Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;
+      Out->SetAttribute (Out, Out->Mode->Attribute);
+    } else {
+      //
+      // Must be wide, set bit 7 ON
+      //
+      Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE;
+      Out->SetAttribute (Out, Out->Mode->Attribute);
+    }
+
+    Index++;
+
+  } while (Buffer[Index] != 0);
+
+  //
+  // We hit the end of the string - print it
+  //
+  Out->OutputString (Out, &BackupBuffer[PreviousIndex]);
+
+  gBS->FreePool (Buffer);
+  gBS->FreePool (BackupBuffer);
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Prints a formatted unicode string to the default console
+
+  @param  fmt        Format string
+
+  @return Length of string printed to the console
+
+**/
+UINTN
+ConsolePrint (
+  IN CHAR16   *fmt,
+  ...
+  )
+{
+  VA_LIST args;
+
+  VA_START (args, fmt);
+  return PrintInternal ((UINTN) -1, (UINTN) -1, gST->ConOut, fmt, args);
+}
+
+
+/**
+  Prints a unicode string to the default console,
+  using L"%s" format.
+
+  @param  String     String pointer.
+
+  @return Length of string printed to the console
+
+**/
+UINTN
+PrintString (
+  CHAR16       *String
+  )
+{
+  return ConsolePrint (L"%s", String);
+}
+
+
+/**
+  Prints a chracter to the default console,
+  using L"%c" format.
+
+  @param  Character  Character to print.
+
+  @return Length of string printed to the console.
+
+**/
+UINTN
+PrintChar (
+  CHAR16       Character
+  )
+{
+  return ConsolePrint (L"%c", Character);
+}
+
+
+/**
+  Prints a formatted unicode string to the default console, at
+  the supplied cursor position
+
+  @param  Row        The cursor position to print the string at
+  @param  fmt        Format string
+
+  @return Length of string printed to the console
+
+**/
+UINTN
+PrintAt (
+  IN UINTN     Column,
+  IN UINTN     Row,
+  IN CHAR16    *fmt,
+  ...
+  )
+{
+  VA_LIST args;
+
+  VA_START (args, fmt);
+  return PrintInternal (Column, Row, gST->ConOut, fmt, args);
+}
+
+
+/**
+  Prints a unicode string to the default console, at
+  the supplied cursor position, using L"%s" format.
+
+  @param  Row        The cursor position to print the string at
+  @param  String     String pointer.
+
+  @return Length of string printed to the console
+
+**/
+UINTN
+PrintStringAt (
+  IN UINTN     Column,
+  IN UINTN     Row,
+  CHAR16       *String
+  )
+{
+  return PrintAt (Column, Row, L"%s", String);
+}
+
+
+/**
+  Prints a chracter to the default console, at
+  the supplied cursor position, using L"%c" format.
+
+  @param  Row        The cursor position to print the string at
+  @param  Character  Character to print.
+
+  @return Length of string printed to the console.
+
+**/
+UINTN
+PrintCharAt (
+  IN UINTN     Column,
+  IN UINTN     Row,
+  CHAR16       Character
+  )
+{
+  return PrintAt (Column, Row, L"%c", Character);
+}
+
+
+/**
+  VSPrint worker function that prints a Value as a decimal number in Buffer
+
+  @param  Buffer     Location to place ascii decimal number string of Value.
+  @param  Value      Decimal value to convert to a string in Buffer.
+  @param  Flags      Flags to use in printing decimal string, see file header for
+                     details.
+
+  @return Number of characters printed.
+
+**/
+UINTN
+ValueToString (
+  IN  OUT CHAR16  *Buffer,
+  IN  BOOLEAN     Flags,
+  IN  INT64       Value
+  )
+{
+  CHAR16  TempBuffer[30];
+  CHAR16  *TempStr;
+  CHAR16  *BufferPtr;
+  UINTN   Count;
+  UINTN   NumberCount;
+  UINT32  Remainder;
+  BOOLEAN Negative;
+
+  Negative    = FALSE;
+  TempStr     = TempBuffer;
+  BufferPtr   = Buffer;
+  Count       = 0;
+  NumberCount = 0;
+
+  if (Value < 0) {
+    Negative = TRUE;
+    Value    = -Value;
+  }
+
+  do {
+    Value         = (INT64) DivU64x32Remainder  ((UINT64) Value, 10, &Remainder);
+    *(TempStr++)  = (CHAR16) (Remainder + '0');
+    Count++;
+    NumberCount++;
+    if ((Flags & COMMA_TYPE) == COMMA_TYPE) {
+      if (NumberCount % 3 == 0 && Value != 0) {
+        *(TempStr++) = ',';
+        Count++;
+      }
+    }
+  } while (Value != 0);
+
+  if (Negative) {
+    *(BufferPtr++) = '-';
+    Count++;
+  }
+
+  //
+  // Reverse temp string into Buffer.
+  //
+  while (TempStr != TempBuffer) {
+    *(BufferPtr++) = *(--TempStr);
+  }
+
+  *BufferPtr = 0;
+  return Count;
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Print.h b/MdeModulePkg/Universal/SetupBrowserDxe/Print.h
new file mode 100644 (file)
index 0000000..c473a26
--- /dev/null
@@ -0,0 +1,38 @@
+/** @file
+
+Copyright (c) 2004, Intel Corporation
+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.
+
+Module Name:
+
+  Print.h
+
+Abstract:
+
+  Private data for Print.c
+
+
+**/
+
+#ifndef _PRINT_H_
+#define _PRINT_H_
+
+#define LEFT_JUSTIFY  0x01
+#define PREFIX_SIGN   0x02
+#define PREFIX_BLANK  0x04
+#define COMMA_TYPE    0x08
+#define LONG_TYPE     0x10
+#define PREFIX_ZERO   0x20
+
+//
+// Largest number of characters that can be printed out.
+//
+#define EFI_DRIVER_LIB_MAX_PRINT_BUFFER (80 * 4)
+
+#endif
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c b/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
new file mode 100644 (file)
index 0000000..ac9eeda
--- /dev/null
@@ -0,0 +1,986 @@
+/** @file
+
+Copyright (c) 2004 - 2007, Intel Corporation
+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.
+
+Module Name:
+
+  ProcessOptions.c
+
+Abstract:
+
+  Implementation for handling the User Interface option processing.
+
+Revision History
+
+
+**/
+
+#include "Ui.h"
+#include "Setup.h"
+
+
+/**
+  Process Question Config.
+
+  @param  Selection              The UI menu selection.
+  @param  Question               The Question to be peocessed.
+
+  @retval EFI_SUCCESS            Question Config process success.
+  @retval Other                  Question Config process fail.
+
+**/
+EFI_STATUS
+ProcessQuestionConfig (
+  IN  UI_MENU_SELECTION       *Selection,
+  IN  FORM_BROWSER_STATEMENT  *Question
+  )
+{
+  EFI_STATUS                      Status;
+  CHAR16                          *ConfigResp;
+  CHAR16                          *Progress;
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;
+
+  if (Question->QuestionConfig == 0) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Get <ConfigResp>
+  //
+  ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle);
+  if (ConfigResp == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Send config to Configuration Driver
+  //
+  ConfigAccess = Selection->FormSet->ConfigAccess;
+  if (ConfigAccess == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+  Status = ConfigAccess->RouteConfig (
+                           ConfigAccess,
+                           ConfigResp,
+                           &Progress
+                           );
+
+  return Status;
+}
+
+
+/**
+  Search an Option of a Question by its value.
+
+  @param  Question               The Question
+  @param  OptionValue            Value for Option to be searched.
+
+  @retval Pointer                Pointer to the found Option.
+  @retval NULL                   Option not found.
+
+**/
+QUESTION_OPTION *
+ValueToOption (
+  IN FORM_BROWSER_STATEMENT   *Question,
+  IN EFI_HII_VALUE            *OptionValue
+  )
+{
+  LIST_ENTRY       *Link;
+  QUESTION_OPTION  *Option;
+
+  Link = GetFirstNode (&Question->OptionListHead);
+  while (!IsNull (&Question->OptionListHead, Link)) {
+    Option = QUESTION_OPTION_FROM_LINK (Link);
+
+    if (CompareHiiValue (&Option->Value, OptionValue, NULL) == 0) {
+      return Option;
+    }
+
+    Link = GetNextNode (&Question->OptionListHead, Link);
+  }
+
+  return NULL;
+}
+
+
+/**
+  Print Question Value according to it's storage width and display attributes.
+
+  @param  Event                  The event to wait for
+  @param  FormattedNumber        Buffer for output string.
+  @param  BufferSize             The FormattedNumber buffer size in bytes.
+
+  @retval EFI_SUCCESS            Print success.
+  @retval EFI_BUFFER_TOO_SMALL   Buffer size is not enough for formatted number.
+
+**/
+EFI_STATUS
+PrintFormattedNumber (
+  IN FORM_BROWSER_STATEMENT   *Question,
+  IN OUT CHAR16               *FormattedNumber,
+  IN UINTN                    BufferSize
+  )
+{
+  INT64          Value;
+  CHAR16         *Format;
+  EFI_HII_VALUE  *QuestionValue;
+
+  if (BufferSize < (21 * sizeof (CHAR16))) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  QuestionValue = &Question->HiiValue;
+
+  Value = (INT64) QuestionValue->Value.u64;
+  switch (Question->Flags & EFI_IFR_DISPLAY) {
+  case EFI_IFR_DISPLAY_INT_DEC:
+    switch (QuestionValue->Type) {
+    case EFI_IFR_NUMERIC_SIZE_1:
+      Value = (INT64) ((INT8) QuestionValue->Value.u8);
+      break;
+
+    case EFI_IFR_NUMERIC_SIZE_2:
+      Value = (INT64) ((INT16) QuestionValue->Value.u16);
+      break;
+
+    case EFI_IFR_NUMERIC_SIZE_4:
+      Value = (INT64) ((INT32) QuestionValue->Value.u32);
+      break;
+
+    case EFI_IFR_NUMERIC_SIZE_8:
+    default:
+      break;
+    }
+
+    if (Value < 0) {
+      Value = -Value;
+      Format = L"-%ld";
+    } else {
+      Format = L"%ld";
+    }
+    break;
+
+  case EFI_IFR_DISPLAY_UINT_DEC:
+    Format = L"%ld";
+    break;
+
+  case EFI_IFR_DISPLAY_UINT_HEX:
+    Format = L"%lx";
+    break;
+
+  default:
+    return EFI_UNSUPPORTED;
+    break;
+  }
+
+  UnicodeSPrint (FormattedNumber, BufferSize, Format, Value);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Password may be stored as encrypted by Configuration Driver. When change a
+  password, user will be challenged with old password. To validate user input old
+  password, we will send the clear text to Configuration Driver via Callback().
+  Configuration driver is responsible to check the passed in password and return
+  the validation result. If validation pass, state machine in password Callback()
+  will transit from BROWSER_STATE_VALIDATE_PASSWORD to BROWSER_STATE_SET_PASSWORD.
+  After user type in new password twice, Callback() will be invoked to send the
+  new password to Configuration Driver.
+
+  @param  Selection              Pointer to UI_MENU_SELECTION.
+  @param  MenuOption             The MenuOption for this password Question.
+  @param  String                 The clear text of password.
+
+  @retval EFI_NOT_AVAILABLE_YET  Callback() request to terminate password input.
+  @return In state of BROWSER_STATE_VALIDATE_PASSWORD:
+  @retval EFI_SUCCESS            Password correct, Browser will prompt for new
+                                 password.
+  @retval EFI_NOT_READY          Password incorrect, Browser will show error
+                                 message.
+  @retval Other                  Browser will do nothing.
+  @return In state of BROWSER_STATE_SET_PASSWORD:
+  @retval EFI_SUCCESS            Set password success.
+  @retval Other                  Set password failed.
+
+**/
+EFI_STATUS
+PasswordCallback (
+  IN  UI_MENU_SELECTION           *Selection,
+  IN  UI_MENU_OPTION              *MenuOption,
+  IN  CHAR16                      *String
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;
+  EFI_BROWSER_ACTION_REQUEST      ActionRequest;
+  EFI_HII_VALUE                   *QuestionValue;
+
+  QuestionValue = &MenuOption->ThisTag->HiiValue;
+  ConfigAccess = Selection->FormSet->ConfigAccess;
+  if (ConfigAccess == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Prepare password string in HII database
+  //
+  if (String != NULL) {
+    QuestionValue->Value.string = NewString (String, Selection->FormSet->HiiHandle);
+  } else {
+    QuestionValue->Value.string = 0;
+  }
+
+  //
+  // Send password to Configuration Driver for validation
+  //
+  Status = ConfigAccess->Callback (
+                           ConfigAccess,
+                           EFI_BROWSER_ACTION_CHANGING,
+                           MenuOption->ThisTag->QuestionId,
+                           QuestionValue->Type,
+                           &QuestionValue->Value,
+                           &ActionRequest
+                           );
+
+  //
+  // Remove password string from HII database
+  //
+  if (String != NULL) {
+    DeleteString (QuestionValue->Value.string, Selection->FormSet->HiiHandle);
+  }
+
+  return Status;
+}
+
+
+/**
+  Display error message for invalid password.
+
+  None.
+
+  @return None.
+
+**/
+VOID
+PasswordInvalid (
+  VOID
+  )
+{
+  EFI_INPUT_KEY  Key;
+
+  //
+  // Invalid password, prompt error message
+  //
+  do {
+    CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gPassowordInvalid, gPressEnter, gEmptyString);
+  } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+}
+
+
+/**
+  Process a Question's Option (whether selected or un-selected).
+
+  @param  Selection              Pointer to UI_MENU_SELECTION.
+  @param  MenuOption             The MenuOption for this Question.
+  @param  Selected               TRUE: if Question is selected.
+  @param  OptionString           Pointer of the Option String to be displayed.
+
+  @retval EFI_SUCCESS            Question Option process success.
+  @retval Other                  Question Option process fail.
+
+**/
+EFI_STATUS
+ProcessOptions (
+  IN  UI_MENU_SELECTION           *Selection,
+  IN  UI_MENU_OPTION              *MenuOption,
+  IN  BOOLEAN                     Selected,
+  OUT CHAR16                      **OptionString
+  )
+{
+  EFI_STATUS                      Status;
+  CHAR16                          *StringPtr;
+  CHAR16                          *TempString;
+  UINTN                           Index;
+  FORM_BROWSER_STATEMENT          *Question;
+  CHAR16                          FormattedNumber[21];
+  UINT16                          Number;
+  CHAR16                          Character[2];
+  EFI_INPUT_KEY                   Key;
+  UINTN                           BufferSize;
+  QUESTION_OPTION                 *OneOfOption;
+  LIST_ENTRY                      *Link;
+  EFI_HII_VALUE                   HiiValue;
+  EFI_HII_VALUE                   *QuestionValue;
+  BOOLEAN                         Suppress;
+  UINT16                          Maximum;
+
+  Status        = EFI_SUCCESS;
+
+  StringPtr     = NULL;
+  Character[1]  = L'\0';
+  *OptionString = NULL;
+
+  ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));
+  BufferSize = (gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow;
+
+  Question = MenuOption->ThisTag;
+  QuestionValue = &Question->HiiValue;
+  Maximum = (UINT16) Question->Maximum;
+
+  switch (Question->Operand) {
+  case EFI_IFR_ORDERED_LIST_OP:
+    //
+    // Initialize Option value array
+    //
+    if (Question->BufferValue[0] == 0) {
+      GetQuestionDefault (Selection->FormSet, Selection->Form, Question, 0);
+    }
+
+    if (Selected) {
+      //
+      // Go ask for input
+      //
+      Status = GetSelectionInputPopUp (Selection, MenuOption);
+    } else {
+      //
+      // We now know how many strings we will have, so we can allocate the
+      // space required for the array or strings.
+      //
+      *OptionString = AllocateZeroPool (Question->MaxContainers * BufferSize);
+      ASSERT (*OptionString);
+
+      HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_8;
+      HiiValue.Value.u64 = 0;
+      for (Index = 0; Index < Question->MaxContainers; Index++) {
+        HiiValue.Value.u8 = Question->BufferValue[Index];
+        if (HiiValue.Value.u8 == 0) {
+          //
+          // Values for the options in ordered lists should never be a 0
+          //
+          break;
+        }
+
+        OneOfOption = ValueToOption (Question, &HiiValue);
+        if (OneOfOption == NULL) {
+          gBS->FreePool (*OptionString);
+          return EFI_NOT_FOUND;
+        }
+
+        Suppress = FALSE;
+        if ((OneOfOption->SuppressExpression != NULL) &&
+            (OneOfOption->SuppressExpression->Result.Value.b)) {
+          //
+          // This option is suppressed
+          //
+          Suppress = TRUE;
+        }
+
+        if (!Suppress) {
+          Character[0] = LEFT_ONEOF_DELIMITER;
+          NewStrCat (OptionString[0], Character);
+          StringPtr = GetToken (OneOfOption->Text, Selection->Handle);
+          NewStrCat (OptionString[0], StringPtr);
+          Character[0] = RIGHT_ONEOF_DELIMITER;
+          NewStrCat (OptionString[0], Character);
+          Character[0] = CHAR_CARRIAGE_RETURN;
+          NewStrCat (OptionString[0], Character);
+
+          gBS->FreePool (StringPtr);
+        }
+      }
+    }
+    break;
+
+  case EFI_IFR_ONE_OF_OP:
+    if (Selected) {
+      //
+      // Go ask for input
+      //
+      Status = GetSelectionInputPopUp (Selection, MenuOption);
+    } else {
+      *OptionString = AllocateZeroPool (BufferSize);
+      ASSERT (*OptionString);
+
+      OneOfOption = ValueToOption (Question, QuestionValue);
+      if (OneOfOption == NULL) {
+        gBS->FreePool (*OptionString);
+        return EFI_NOT_FOUND;
+      }
+
+      if ((OneOfOption->SuppressExpression != NULL) &&
+          (OneOfOption->SuppressExpression->Result.Value.b)) {
+        //
+        // This option is suppressed
+        //
+        Suppress = TRUE;
+      } else {
+        Suppress = FALSE;
+      }
+
+      if (Suppress) {
+        //
+        // Current selected option happen to be suppressed,
+        // enforce to select on a non-suppressed option
+        //
+        Link = GetFirstNode (&Question->OptionListHead);
+        while (!IsNull (&Question->OptionListHead, Link)) {
+          OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+
+          if ((OneOfOption->SuppressExpression == NULL) ||
+              !OneOfOption->SuppressExpression->Result.Value.b) {
+            Suppress = FALSE;
+            CopyMem (QuestionValue, &OneOfOption->Value, sizeof (EFI_HII_VALUE));
+            SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);
+            break;
+          }
+
+          Link = GetNextNode (&Question->OptionListHead, Link);
+        }
+      }
+
+      if (!Suppress) {
+        Character[0] = LEFT_ONEOF_DELIMITER;
+        NewStrCat (OptionString[0], Character);
+        StringPtr = GetToken (OneOfOption->Text, Selection->Handle);
+        NewStrCat (OptionString[0], StringPtr);
+        Character[0] = RIGHT_ONEOF_DELIMITER;
+        NewStrCat (OptionString[0], Character);
+
+        gBS->FreePool (StringPtr);
+      }
+    }
+    break;
+
+  case EFI_IFR_CHECKBOX_OP:
+    *OptionString = AllocateZeroPool (BufferSize);
+    ASSERT (*OptionString);
+
+    *OptionString[0] = LEFT_CHECKBOX_DELIMITER;
+
+    if (Selected) {
+      //
+      // Since this is a BOOLEAN operation, flip it upon selection
+      //
+      QuestionValue->Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE);
+
+      //
+      // Perform inconsistent check
+      //
+      Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
+      if (EFI_ERROR (Status)) {
+        //
+        // Inconsistent check fail, restore Question Value
+        //
+        QuestionValue->Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE);
+        gBS->FreePool (*OptionString);
+        return Status;
+      }
+
+      //
+      // Save Question value
+      //
+      Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);
+      UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
+    }
+
+    if (QuestionValue->Value.b) {
+      *(OptionString[0] + 1) = CHECK_ON;
+    } else {
+      *(OptionString[0] + 1) = CHECK_OFF;
+    }
+    *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER;
+    break;
+
+  case EFI_IFR_NUMERIC_OP:
+    if (Selected) {
+      //
+      // Go ask for input
+      //
+      Status = GetNumericInput (Selection, MenuOption);
+    } else {
+      *OptionString = AllocateZeroPool (BufferSize);
+      ASSERT (*OptionString);
+
+      *OptionString[0] = LEFT_NUMERIC_DELIMITER;
+
+      //
+      // Formatted print
+      //
+      PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));
+      Number = (UINT16) GetStringWidth (FormattedNumber);
+      CopyMem (OptionString[0] + 1, FormattedNumber, Number);
+
+      *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER;
+    }
+    break;
+
+  case EFI_IFR_DATE_OP:
+    if (Selected) {
+      //
+      // This is similar to numerics
+      //
+      Status = GetNumericInput (Selection, MenuOption);
+    } else {
+      *OptionString = AllocateZeroPool (BufferSize);
+      ASSERT (*OptionString);
+
+      switch (MenuOption->Sequence) {
+      case 0:
+        *OptionString[0] = LEFT_NUMERIC_DELIMITER;
+        UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Month);
+        *(OptionString[0] + 3) = DATE_SEPARATOR;
+        break;
+
+      case 1:
+        SetUnicodeMem (OptionString[0], 4, L' ');
+        UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Day);
+        *(OptionString[0] + 6) = DATE_SEPARATOR;
+        break;
+
+      case 2:
+        SetUnicodeMem (OptionString[0], 7, L' ');
+        UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%4d", QuestionValue->Value.date.Year);
+        *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER;
+        break;
+      }
+    }
+    break;
+
+  case EFI_IFR_TIME_OP:
+    if (Selected) {
+      //
+      // This is similar to numerics
+      //
+      Status = GetNumericInput (Selection, MenuOption);
+    } else {
+      *OptionString = AllocateZeroPool (BufferSize);
+      ASSERT (*OptionString);
+
+      switch (MenuOption->Sequence) {
+      case 0:
+        *OptionString[0] = LEFT_NUMERIC_DELIMITER;
+        UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Hour);
+        *(OptionString[0] + 3) = TIME_SEPARATOR;
+        break;
+
+      case 1:
+        SetUnicodeMem (OptionString[0], 4, L' ');
+        UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Minute);
+        *(OptionString[0] + 6) = TIME_SEPARATOR;
+        break;
+
+      case 2:
+        SetUnicodeMem (OptionString[0], 7, L' ');
+        UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Second);
+        *(OptionString[0] + 9) = RIGHT_NUMERIC_DELIMITER;
+        break;
+      }
+    }
+    break;
+
+  case EFI_IFR_STRING_OP:
+    if (Selected) {
+      StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
+      ASSERT (StringPtr);
+
+      Status = ReadString (MenuOption, gPromptForData, StringPtr);
+      if (!EFI_ERROR (Status)) {
+        CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));
+        SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);
+
+        UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
+      }
+
+      gBS->FreePool (StringPtr);
+    } else {
+      *OptionString = AllocateZeroPool (BufferSize);
+      ASSERT (*OptionString);
+
+      if (((CHAR16 *) Question->BufferValue)[0] == 0x0000) {
+        *(OptionString[0]) = '_';
+      } else {
+        if ((Maximum * sizeof (CHAR16)) < BufferSize) {
+          BufferSize = Maximum * sizeof (CHAR16);
+        }
+        CopyMem (OptionString[0], (CHAR16 *) Question->BufferValue, BufferSize);
+      }
+    }
+    break;
+
+  case EFI_IFR_PASSWORD_OP:
+    if (Selected) {
+      StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
+      ASSERT (StringPtr);
+
+      //
+      // For interactive passwords, old password is validated by callback
+      //
+      if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+        //
+        // Use a NULL password to test whether old password is required
+        //
+        *StringPtr = 0;
+        Status = PasswordCallback (Selection, MenuOption, StringPtr);
+        if (Status == EFI_NOT_AVAILABLE_YET) {
+          //
+          // Callback request to terminate password input
+          //
+          gBS->FreePool (StringPtr);
+          return EFI_SUCCESS;
+        }
+
+        if (EFI_ERROR (Status)) {
+          //
+          // Old password exist, ask user for the old password
+          //
+          Status = ReadString (MenuOption, gPromptForPassword, StringPtr);
+          if (EFI_ERROR (Status)) {
+            gBS->FreePool (StringPtr);
+            return Status;
+          }
+
+          //
+          // Check user input old password
+          //
+          Status = PasswordCallback (Selection, MenuOption, StringPtr);
+          if (EFI_ERROR (Status)) {
+            if (Status == EFI_NOT_READY) {
+              //
+              // Typed in old password incorrect
+              //
+              PasswordInvalid ();
+            } else {
+              Status = EFI_SUCCESS;
+            }
+
+            gBS->FreePool (StringPtr);
+            return Status;
+          }
+        }
+      } else {
+        //
+        // For non-interactive password, validate old password in local
+        //
+        if (*((CHAR16 *) Question->BufferValue) != 0) {
+          //
+          // There is something there!  Prompt for password
+          //
+          Status = ReadString (MenuOption, gPromptForPassword, StringPtr);
+          if (EFI_ERROR (Status)) {
+            gBS->FreePool (StringPtr);
+            return Status;
+          }
+
+          TempString = AllocateCopyPool ((Maximum + 1) * sizeof (CHAR16), Question->BufferValue);
+          TempString[Maximum] = L'\0';
+
+          if (StrCmp (StringPtr, TempString) != 0) {
+            //
+            // Typed in old password incorrect
+            //
+            PasswordInvalid ();
+
+            gBS->FreePool (StringPtr);
+            gBS->FreePool (TempString);
+            return Status;
+          }
+
+          gBS->FreePool (TempString);
+        }
+      }
+
+      //
+      // Ask for new password
+      //
+      ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
+      Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr);
+      if (EFI_ERROR (Status)) {
+        //
+        // Reset state machine for interactive password
+        //
+        if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+          PasswordCallback (Selection, MenuOption, NULL);
+        }
+
+        gBS->FreePool (StringPtr);
+        return Status;
+      }
+
+      //
+      // Confirm new password
+      //
+      TempString = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
+      ASSERT (TempString);
+      Status = ReadString (MenuOption, gConfirmPassword, TempString);
+      if (EFI_ERROR (Status)) {
+        //
+        // Reset state machine for interactive password
+        //
+        if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+          PasswordCallback (Selection, MenuOption, NULL);
+        }
+
+        gBS->FreePool (StringPtr);
+        gBS->FreePool (TempString);
+        return Status;
+      }
+
+      //
+      // Compare two typed-in new passwords
+      //
+      if (StrCmp (StringPtr, TempString) == 0) {
+        //
+        // Two password match, send it to Configuration Driver
+        //
+        if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+          PasswordCallback (Selection, MenuOption, StringPtr);
+        } else {
+          CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));
+          SetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE);
+        }
+      } else {
+        //
+        // Reset state machine for interactive password
+        //
+        if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+          PasswordCallback (Selection, MenuOption, NULL);
+        }
+
+        //
+        // Two password mismatch, prompt error message
+        //
+        do {
+          CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString);
+        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+      }
+
+      gBS->FreePool (TempString);
+      gBS->FreePool (StringPtr);
+    }
+    break;
+
+  default:
+    break;
+  }
+
+  return Status;
+}
+
+
+/**
+  Process the help string: Split StringPtr to several lines of strings stored in
+  FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
+
+  @param  StringPtr              The entire help string.
+  @param  MenuOption             The MenuOption for this Question.
+  @param  RowCount               TRUE: if Question is selected.
+  @param  OptionString           Pointer of the Option String to be displayed.
+
+  @return None.
+
+**/
+VOID
+ProcessHelpString (
+  IN  CHAR16  *StringPtr,
+  OUT CHAR16  **FormattedString,
+  IN  UINTN   RowCount
+  )
+{
+  CONST UINTN BlockWidth = (UINTN) gHelpBlockWidth - 1;
+  UINTN AllocateSize;
+  //
+  // [PrevCurrIndex, CurrIndex) forms a range of a screen-line
+  //
+  UINTN CurrIndex;
+  UINTN PrevCurrIndex;
+  UINTN LineCount;
+  UINTN VirtualLineCount;
+  //
+  // GlyphOffset stores glyph width of current screen-line
+  //
+  UINTN GlyphOffset;
+  //
+  // GlyphWidth equals to 2 if we meet width directive
+  //
+  UINTN GlyphWidth;
+  //
+  // during scanning, we remember the position of last space character
+  // in case that if next word cannot put in current line, we could restore back to the position
+  // of last space character
+  // while we should also remmeber the glyph width of the last space character for restoring
+  //
+  UINTN LastSpaceIndex;
+  UINTN LastSpaceGlyphWidth;
+  //
+  // every time we begin to form a new screen-line, we should remember glyph width of single character
+  // of last line
+  //
+  UINTN LineStartGlyphWidth;
+  UINTN *IndexArray;
+  UINTN *OldIndexArray;
+
+  //
+  // every three elements of IndexArray form a screen-line of string:[ IndexArray[i*3], IndexArray[i*3+1] )
+  // IndexArray[i*3+2] stores the initial glyph width of single character. to save this is because we want
+  // to bring the width directive of the last line to current screen-line.
+  // e.g.: "\wideabcde ... fghi", if "fghi" also has width directive but is splitted to the next screen-line
+  // different from that of "\wideabcde", we should remember the width directive.
+  //
+  AllocateSize  = 0x20;
+  IndexArray    = AllocatePool (AllocateSize * sizeof (UINTN) * 3);
+
+  if (*FormattedString != NULL) {
+    gBS->FreePool (*FormattedString);
+    *FormattedString = NULL;
+  }
+
+  for (PrevCurrIndex = 0, CurrIndex  = 0, LineCount   = 0, LastSpaceIndex = 0,
+       IndexArray[0] = 0, GlyphWidth = 1, GlyphOffset = 0, LastSpaceGlyphWidth = 1, LineStartGlyphWidth = 1;
+       (StringPtr[CurrIndex] != CHAR_NULL);
+       CurrIndex ++) {
+
+    if (LineCount == AllocateSize) {
+      AllocateSize += 0x10;
+      OldIndexArray  = IndexArray;
+      IndexArray = AllocatePool (AllocateSize * sizeof (UINTN) * 3);
+      CopyMem (IndexArray, OldIndexArray, LineCount * sizeof (UINTN) * 3);
+      gBS->FreePool (OldIndexArray);
+    }
+    switch (StringPtr[CurrIndex]) {
+
+      case NARROW_CHAR:
+      case WIDE_CHAR:
+        GlyphWidth = ((StringPtr[CurrIndex] == WIDE_CHAR) ? 2 : 1);
+        if (CurrIndex == 0) {
+          LineStartGlyphWidth = GlyphWidth;
+        }
+        break;
+
+      //
+      // char is '\n'
+      // "\r\n" isn't handled here, handled by case CHAR_CARRIAGE_RETURN
+      //
+      case CHAR_LINEFEED:
+        //
+        // Store a range of string as a line
+        //
+        IndexArray[LineCount*3]   = PrevCurrIndex;
+        IndexArray[LineCount*3+1] = CurrIndex;
+        IndexArray[LineCount*3+2] = LineStartGlyphWidth;
+        LineCount ++;
+        //
+        // Reset offset and save begin position of line
+        //
+        GlyphOffset = 0;
+        LineStartGlyphWidth = GlyphWidth;
+        PrevCurrIndex = CurrIndex + 1;
+        break;
+
+      //
+      // char is '\r'
+      // "\r\n" and "\r" both are handled here
+      //
+      case CHAR_CARRIAGE_RETURN:
+        if (StringPtr[CurrIndex + 1] == CHAR_LINEFEED) {
+          //
+          // next char is '\n'
+          //
+          IndexArray[LineCount*3]   = PrevCurrIndex;
+          IndexArray[LineCount*3+1] = CurrIndex;
+          IndexArray[LineCount*3+2] = LineStartGlyphWidth;
+          LineCount ++;
+          CurrIndex ++;
+        }
+        GlyphOffset = 0;
+        LineStartGlyphWidth = GlyphWidth;
+        PrevCurrIndex = CurrIndex + 1;
+        break;
+
+      //
+      // char is space or other char
+      //
+      default:
+        GlyphOffset     += GlyphWidth;
+        if (GlyphOffset >= BlockWidth) {
+          if (LastSpaceIndex > PrevCurrIndex) {
+            //
+            // LastSpaceIndex points to space inside current screen-line,
+            // restore to LastSpaceIndex
+            // (Otherwise the word is too long to fit one screen-line, just cut it)
+            //
+            CurrIndex  = LastSpaceIndex;
+            GlyphWidth = LastSpaceGlyphWidth;
+          } else if (GlyphOffset > BlockWidth) {
+            //
+            // the word is too long to fit one screen-line and we don't get the chance
+            // of GlyphOffset == BlockWidth because GlyphWidth = 2
+            //
+            CurrIndex --;
+          }
+
+          IndexArray[LineCount*3]   = PrevCurrIndex;
+          IndexArray[LineCount*3+1] = CurrIndex + 1;
+          IndexArray[LineCount*3+2] = LineStartGlyphWidth;
+          LineStartGlyphWidth = GlyphWidth;
+          LineCount ++;
+          //
+          // Reset offset and save begin position of line
+          //
+          GlyphOffset                 = 0;
+          PrevCurrIndex               = CurrIndex + 1;
+        }
+
+        //
+        // LastSpaceIndex: remember position of last space
+        //
+        if (StringPtr[CurrIndex] == CHAR_SPACE) {
+          LastSpaceIndex      = CurrIndex;
+          LastSpaceGlyphWidth = GlyphWidth;
+        }
+        break;
+    }
+  }
+
+  if (GlyphOffset > 0) {
+    IndexArray[LineCount*3]   = PrevCurrIndex;
+    IndexArray[LineCount*3+1] = CurrIndex;
+    IndexArray[LineCount*3+2] = GlyphWidth;
+    LineCount ++;
+  }
+
+  if (LineCount == 0) {
+    //
+    // in case we meet null string
+    //
+    IndexArray[0] = 0;
+    IndexArray[1] = 1;
+    //
+    // we assume null string's glyph width is 1
+    //
+    IndexArray[1] = 1;
+    LineCount ++;
+  }
+
+  VirtualLineCount = RowCount * (LineCount / RowCount + (LineCount % RowCount > 0));
+  *FormattedString = AllocateZeroPool (VirtualLineCount * (BlockWidth + 1) * sizeof (CHAR16) * 2);
+
+  for (CurrIndex = 0; CurrIndex < LineCount; CurrIndex ++) {
+    *(*FormattedString + CurrIndex * 2 * (BlockWidth + 1)) = (CHAR16) ((IndexArray[CurrIndex*3+2] == 2) ? WIDE_CHAR : NARROW_CHAR);
+    StrnCpy (
+      *FormattedString + CurrIndex * 2 * (BlockWidth + 1) + 1,
+      StringPtr + IndexArray[CurrIndex*3],
+      IndexArray[CurrIndex*3+1]-IndexArray[CurrIndex*3]
+      );
+  }
+
+  gBS->FreePool (IndexArray);
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/R8Lib.c b/MdeModulePkg/Universal/SetupBrowserDxe/R8Lib.c
new file mode 100644 (file)
index 0000000..1ffeb1b
--- /dev/null
@@ -0,0 +1,243 @@
+/**@file
+  Copyright (c) 2007, Intel Corporation
+
+  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 "Setup.h"
+
+CHAR16
+NibbleToHexChar (
+  IN UINT8      Nibble
+  )
+/*++
+
+  Routine Description:
+    Converts the low nibble of a byte  to hex unicode character.
+
+  Arguments:
+    Nibble - lower nibble of a byte.
+
+  Returns:
+    Hex unicode character.
+
+--*/
+{
+  Nibble &= 0x0F;
+  if (Nibble <= 0x9) {
+    return (CHAR16)(Nibble + L'0');
+  }
+
+  return (CHAR16)(Nibble - 0xA + L'A');
+}
+
+
+
+/**
+  Converts binary buffer to Unicode string.
+  At a minimum, any blob of data could be represented as a hex string.
+
+  @param  Str                    Pointer to the string.
+  @param  HexStringBufferLength  Length in bytes of buffer to hold the hex string.
+                                 Includes tailing '\0' character. If routine return
+                                 with EFI_SUCCESS, containing length of hex string
+                                 buffer. If routine return with
+                                 EFI_BUFFER_TOO_SMALL, containg length of hex
+                                 string buffer desired.
+  @param  Buf                    Buffer to be converted from.
+  @param  Len                    Length in bytes of the buffer to be converted.
+
+  @retval EFI_SUCCESS            Routine success.
+  @retval EFI_BUFFER_TOO_SMALL   The hex string buffer is too small.
+
+**/
+EFI_STATUS
+R8_BufToHexString (
+  IN OUT CHAR16                    *Str,
+  IN OUT UINTN                     *HexStringBufferLength,
+  IN     UINT8                     *Buf,
+  IN     UINTN                      Len
+  )
+{
+  //
+  // Porting Guide:
+  // This library interface is simply obsolete.
+  // Include the source code to user code.
+  //
+  UINTN       Idx;
+  UINT8       Byte;
+  UINTN       StrLen;
+
+  //
+  // Make sure string is either passed or allocate enough.
+  // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.
+  // Plus the Unicode termination character.
+  //
+  StrLen = Len * 2;
+  if (StrLen > ((*HexStringBufferLength) - 1)) {
+    *HexStringBufferLength = StrLen + 1;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  *HexStringBufferLength = StrLen + 1;
+  //
+  // Ends the string.
+  //
+  Str[StrLen] = L'\0';
+
+  for (Idx = 0; Idx < Len; Idx++) {
+
+    Byte = Buf[Idx];
+    Str[StrLen - 1 - Idx * 2] = NibbleToHexChar (Byte);
+    Str[StrLen - 2 - Idx * 2] = NibbleToHexChar ((UINT8)(Byte >> 4));
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+
+
+/**
+  Converts Unicode string to binary buffer.
+  The conversion may be partial.
+  The first character in the string that is not hex digit stops the conversion.
+  At a minimum, any blob of data could be represented as a hex string.
+
+  @param  Buf                    Pointer to buffer that receives the data.
+  @param  Len                    Length in bytes of the buffer to hold converted
+                                 data. If routine return with EFI_SUCCESS,
+                                 containing length of converted data. If routine
+                                 return with EFI_BUFFER_TOO_SMALL, containg length
+                                 of buffer desired.
+  @param  Str                    String to be converted from.
+  @param  ConvertedStrLen        Length of the Hex String consumed.
+
+  @retval EFI_SUCCESS            Routine Success.
+  @retval EFI_BUFFER_TOO_SMALL   The buffer is too small to hold converted data.
+
+**/
+EFI_STATUS
+R8_HexStringToBuf (
+  IN OUT UINT8                     *Buf,
+  IN OUT UINTN                    *Len,
+  IN     CHAR16                    *Str,
+  OUT    UINTN                     *ConvertedStrLen  OPTIONAL
+  )
+{
+  //
+  // Porting Guide:
+  // This library interface is simply obsolete.
+  // Include the source code to user code.
+  //
+
+  UINTN       HexCnt;
+  UINTN       Idx;
+  UINTN       BufferLength;
+  UINT8       Digit;
+  UINT8       Byte;
+
+  //
+  // Find out how many hex characters the string has.
+  //
+  for (Idx = 0, HexCnt = 0; R8_IsHexDigit (&Digit, Str[Idx]); Idx++, HexCnt++);
+
+  if (HexCnt == 0) {
+    *Len = 0;
+    return EFI_SUCCESS;
+  }
+  //
+  // Two Unicode characters make up 1 buffer byte. Round up.
+  //
+  BufferLength = (HexCnt + 1) / 2;
+
+  //
+  // Test if  buffer is passed enough.
+  //
+  if (BufferLength > (*Len)) {
+    *Len = BufferLength;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  *Len = BufferLength;
+
+  for (Idx = 0; Idx < HexCnt; Idx++) {
+
+    R8_IsHexDigit (&Digit, Str[HexCnt - 1 - Idx]);
+
+    //
+    // For odd charaters, write the lower nibble for each buffer byte,
+    // and for even characters, the upper nibble.
+    //
+    if ((Idx & 1) == 0) {
+      Byte = Digit;
+    } else {
+      Byte = Buf[Idx / 2];
+      Byte &= 0x0F;
+      Byte = (UINT8) (Byte | Digit << 4);
+    }
+
+    Buf[Idx / 2] = Byte;
+  }
+
+  if (ConvertedStrLen != NULL) {
+    *ConvertedStrLen = HexCnt;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+
+
+/**
+  Determines if a Unicode character is a hexadecimal digit.
+  The test is case insensitive.
+
+  @param  Digit                  Pointer to byte that receives the value of the hex
+                                 character.
+  @param  Char                   Unicode character to test.
+
+  @retval TRUE                   If the character is a hexadecimal digit.
+  @retval FALSE                  Otherwise.
+
+**/
+BOOLEAN
+R8_IsHexDigit (
+  OUT UINT8      *Digit,
+  IN  CHAR16      Char
+  )
+{
+  //
+  // Porting Guide:
+  // This library interface is simply obsolete.
+  // Include the source code to user code.
+  //
+
+  if ((Char >= L'0') && (Char <= L'9')) {
+    *Digit = (UINT8) (Char - L'0');
+    return TRUE;
+  }
+
+  if ((Char >= L'A') && (Char <= L'F')) {
+    *Digit = (UINT8) (Char - L'A' + 0x0A);
+    return TRUE;
+  }
+
+  if ((Char >= L'a') && (Char <= L'f')) {
+    *Digit = (UINT8) (Char - L'a' + 0x0A);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/R8Lib.h b/MdeModulePkg/Universal/SetupBrowserDxe/R8Lib.h
new file mode 100644 (file)
index 0000000..a090319
--- /dev/null
@@ -0,0 +1,97 @@
+/**@file
+  Copyright (c) 2007, Intel Corporation
+
+  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.
+
+
+**/
+
+
+
+/**
+  Converts binary buffer to Unicode string.
+  At a minimum, any blob of data could be represented as a hex string.
+
+  @param  Str                    Pointer to the string.
+  @param  HexStringBufferLength  Length in bytes of buffer to hold the hex string.
+                                 Includes tailing '\0' character. If routine return
+                                 with EFI_SUCCESS, containing length of hex string
+                                 buffer. If routine return with
+                                 EFI_BUFFER_TOO_SMALL, containg length of hex
+                                 string buffer desired.
+  @param  Buf                    Buffer to be converted from.
+  @param  Len                    Length in bytes of the buffer to be converted.
+
+  @retval EFI_SUCCESS            Routine success.
+  @retval EFI_BUFFER_TOO_SMALL   The hex string buffer is too small.
+
+**/
+EFI_STATUS
+R8_BufToHexString (
+  IN OUT CHAR16                    *Str,
+  IN OUT UINTN                     *HexStringBufferLength,
+  IN     UINT8                     *Buf,
+  IN     UINTN                      Len
+  )
+;
+
+
+
+
+/**
+  Converts Unicode string to binary buffer.
+  The conversion may be partial.
+  The first character in the string that is not hex digit stops the conversion.
+  At a minimum, any blob of data could be represented as a hex string.
+
+  @param  Buf                    Pointer to buffer that receives the data.
+  @param  Len                    Length in bytes of the buffer to hold converted
+                                 data. If routine return with EFI_SUCCESS,
+                                 containing length of converted data. If routine
+                                 return with EFI_BUFFER_TOO_SMALL, containg length
+                                 of buffer desired.
+  @param  Str                    String to be converted from.
+  @param  ConvertedStrLen        Length of the Hex String consumed.
+
+  @retval EFI_SUCCESS            Routine Success.
+  @retval EFI_BUFFER_TOO_SMALL   The buffer is too small to hold converted data.
+
+**/
+EFI_STATUS
+R8_HexStringToBuf (
+  IN OUT UINT8                     *Buf,
+  IN OUT UINTN                    *Len,
+  IN     CHAR16                    *Str,
+  OUT    UINTN                     *ConvertedStrLen  OPTIONAL
+  )
+;
+
+
+
+
+/**
+  Determines if a Unicode character is a hexadecimal digit.
+  The test is case insensitive.
+
+  @param  Digit                  Pointer to byte that receives the value of the hex
+                                 character.
+  @param  Char                   Unicode character to test.
+
+  @retval TRUE                   If the character is a hexadecimal digit.
+  @retval FALSE                  Otherwise.
+
+**/
+BOOLEAN
+R8_IsHexDigit (
+  OUT UINT8      *Digit,
+  IN  CHAR16      Char
+  )
+;
+
+
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
new file mode 100644 (file)
index 0000000..d14dac0
--- /dev/null
@@ -0,0 +1,2286 @@
+/** @file
+Copyright (c) 2007, Intel Corporation
+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.
+
+Module Name:
+
+  Setup.c
+
+Abstract:
+
+  Entry and initialization module for the browser.
+
+
+**/
+
+#include "Setup.h"
+#include "Ui.h"
+
+
+SETUP_DRIVER_PRIVATE_DATA  mPrivateData = {
+  SETUP_DRIVER_SIGNATURE,
+  NULL,
+  {
+    SendForm,
+    BrowserCallback
+  },
+  {
+    UnicodeVSPrint
+  }
+};
+
+EFI_HII_DATABASE_PROTOCOL         *mHiiDatabase;
+EFI_HII_STRING_PROTOCOL           *mHiiString;
+EFI_HII_CONFIG_ROUTING_PROTOCOL   *mHiiConfigRouting;
+
+BANNER_DATA           *BannerData;
+EFI_HII_HANDLE        FrontPageHandle;
+UINTN                 gClassOfVfr;
+UINTN                 gFunctionKeySetting;
+BOOLEAN               gResetRequired;
+BOOLEAN               gNvUpdateRequired;
+EFI_HII_HANDLE        gHiiHandle;
+BOOLEAN               gFirstIn;
+UINT16                gDirection;
+EFI_SCREEN_DESCRIPTOR gScreenDimensions;
+BOOLEAN               gUpArrow;
+BOOLEAN               gDownArrow;
+
+//
+// Browser Global Strings
+//
+CHAR16            *gFunctionOneString;
+CHAR16            *gFunctionTwoString;
+CHAR16            *gFunctionNineString;
+CHAR16            *gFunctionTenString;
+CHAR16            *gEnterString;
+CHAR16            *gEnterCommitString;
+CHAR16            *gEscapeString;
+CHAR16            *gSaveFailed;
+CHAR16            *gMoveHighlight;
+CHAR16            *gMakeSelection;
+CHAR16            *gDecNumericInput;
+CHAR16            *gHexNumericInput;
+CHAR16            *gToggleCheckBox;
+CHAR16            *gPromptForData;
+CHAR16            *gPromptForPassword;
+CHAR16            *gPromptForNewPassword;
+CHAR16            *gConfirmPassword;
+CHAR16            *gConfirmError;
+CHAR16            *gPassowordInvalid;
+CHAR16            *gPressEnter;
+CHAR16            *gEmptyString;
+CHAR16            *gAreYouSure;
+CHAR16            *gYesResponse;
+CHAR16            *gNoResponse;
+CHAR16            *gMiniString;
+CHAR16            *gPlusString;
+CHAR16            *gMinusString;
+CHAR16            *gAdjustNumber;
+
+CHAR16            gPromptBlockWidth;
+CHAR16            gOptionBlockWidth;
+CHAR16            gHelpBlockWidth;
+
+EFI_GUID  gZeroGuid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+EFI_GUID  gSetupBrowserGuid = {
+  0xab368524, 0xb60c, 0x495b, 0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32
+};
+
+FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
+  //
+  // Boot Manager
+  //
+  {
+    {
+      0x847bc3fe,
+      0xb974,
+      0x446d,
+      0x94,
+      0x49,
+      0x5a,
+      0xd5,
+      0x41,
+      0x2e,
+      0x99,
+      0x3b
+    },
+    NONE_FUNCTION_KEY_SETTING
+  },
+  //
+  // Device Manager
+  //
+  {
+    {
+      0x3ebfa8e6,
+      0x511d,
+      0x4b5b,
+      0xa9,
+      0x5f,
+      0xfb,
+      0x38,
+      0x26,
+      0xf,
+      0x1c,
+      0x27
+    },
+    NONE_FUNCTION_KEY_SETTING
+  },
+  //
+  // BMM FormSet.
+  //
+  {
+    {
+      0x642237c7,
+      0x35d4,
+      0x472d,
+      0x83,
+      0x65,
+      0x12,
+      0xe0,
+      0xcc,
+      0xf2,
+      0x7a,
+      0x22
+    },
+    NONE_FUNCTION_KEY_SETTING
+  },
+  //
+  // BMM File Explorer FormSet.
+  //
+  {
+    {
+      0x1f2d63e1,
+      0xfebd,
+      0x4dc7,
+      0x9c,
+      0xc5,
+      0xba,
+      0x2b,
+      0x1c,
+      0xef,
+      0x9c,
+      0x5b
+    },
+    NONE_FUNCTION_KEY_SETTING
+  },
+};
+
+//@MT: EFI_DRIVER_ENTRY_POINT (InitializeSetup)
+
+EFI_STATUS
+EFIAPI
+SendForm (
+  IN  CONST EFI_FORM_BROWSER2_PROTOCOL *This,
+  IN  EFI_HII_HANDLE                   *Handles,
+  IN  UINTN                            HandleCount,
+  IN  EFI_GUID                         *FormSetGuid, OPTIONAL
+  IN  UINT16                           FormId, OPTIONAL
+  IN  CONST EFI_SCREEN_DESCRIPTOR      *ScreenDimensions, OPTIONAL
+  OUT EFI_BROWSER_ACTION_REQUEST       *ActionRequest  OPTIONAL
+  )
+/*++
+
+Routine Description:
+  This is the routine which an external caller uses to direct the browser
+  where to obtain it's information.
+
+Arguments:
+  This            - The Form Browser protocol instanse.
+  Handles         - A pointer to an array of Handles.  If HandleCount > 1 we
+                    display a list of the formsets for the handles specified.
+  HandleCount     - The number of Handles specified in Handle.
+  FormSetGuid     - This field points to the EFI_GUID which must match the Guid
+                    field in the EFI_IFR_FORM_SET op-code for the specified
+                    forms-based package. If FormSetGuid is NULL, then this
+                    function will display the first found forms package.
+  FormId          - This field specifies which EFI_IFR_FORM to render as the first
+                    displayable page. If this field has a value of 0x0000, then
+                    the forms browser will render the specified forms in their encoded order.
+  ScreenDimenions - This allows the browser to be called so that it occupies a
+                    portion of the physical screen instead of dynamically determining the screen dimensions.
+  ActionRequest   - Points to the action recommended by the form.
+
+Returns:
+  EFI_SUCCESS           -  The function completed successfully.
+  EFI_INVALID_PARAMETER -  One of the parameters has an invalid value.
+  EFI_NOT_FOUND         -  No valid forms could be found to display.
+
+--*/
+{
+  EFI_STATUS            Status;
+  UI_MENU_SELECTION     *Selection;
+  UINTN                 Index;
+  FORM_BROWSER_FORMSET  *FormSet;
+
+  Status = EFI_SUCCESS;
+  ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+  //
+  // Seed the dimensions in the global
+  //
+  gST->ConOut->QueryMode (
+                 gST->ConOut,
+                 gST->ConOut->Mode->Mode,
+                 &gScreenDimensions.RightColumn,
+                 &gScreenDimensions.BottomRow
+                 );
+
+  if (ScreenDimensions != NULL) {
+    //
+    // Check local dimension vs. global dimension.
+    //
+    if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||
+        (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)
+        ) {
+      return EFI_INVALID_PARAMETER;
+    } else {
+      //
+      // Local dimension validation.
+      //
+      if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&
+          (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&
+          ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&
+          (
+            (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +
+            SCROLL_ARROW_HEIGHT *
+            2 +
+            FRONT_PAGE_HEADER_HEIGHT +
+            FOOTER_HEIGHT +
+            1
+          )
+        ) {
+        CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+      } else {
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+  }
+
+  gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);
+  gHelpBlockWidth   = gOptionBlockWidth;
+  gPromptBlockWidth = gOptionBlockWidth;
+
+  //
+  // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
+  //
+  InitializeBrowserStrings ();
+
+  gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;
+  gClassOfVfr         = EFI_SETUP_APPLICATION_SUBCLASS;
+
+  //
+  // Ensure we are in Text mode
+  //
+  if (gFirstIn) {
+    gFirstIn = FALSE;
+    gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+    DisableQuietBoot ();
+  }
+
+  for (Index = 0; Index < HandleCount; Index++) {
+    Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));
+    ASSERT (Selection != NULL);
+
+    Selection->Handle = Handles[Index];
+    if (FormSetGuid != NULL) {
+      CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));
+      Selection->FormId = FormId;
+    }
+
+    do {
+      FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
+      ASSERT (FormSet != NULL);
+
+      //
+      // Initialize internal data structures of FormSet
+      //
+      Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);
+      if (EFI_ERROR (Status)) {
+        DestroyFormSet (FormSet);
+        break;
+      }
+      Selection->FormSet = FormSet;
+
+      //
+      // Initialize current settings of Questions in this FormSet
+      //
+      Status = InitializeCurrentSetting (FormSet);
+      if (EFI_ERROR (Status)) {
+        DestroyFormSet (FormSet);
+        break;
+      }
+
+      //
+      // Display this formset
+      //
+      gCurrentSelection = Selection;
+
+      Status = SetupBrowser (Selection);
+
+      gCurrentSelection = NULL;
+      DestroyFormSet (FormSet);
+
+      if (EFI_ERROR (Status)) {
+        break;
+      }
+
+    } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);
+
+    gBS->FreePool (Selection);
+  }
+
+  if (ActionRequest != NULL) {
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+    if (gResetRequired) {
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;
+    }
+  }
+
+  FreeBrowserStrings ();
+
+  gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+  gST->ConOut->ClearScreen (gST->ConOut);
+
+  return Status;
+}
+
+
+/**
+  This function is called by a callback handler to retrieve uncommitted state
+  data from the browser.
+
+  @param  This                   A pointer to the EFI_FORM_BROWSER2_PROTOCOL
+                                 instance.
+  @param  ResultsDataSize        A pointer to the size of the buffer associated
+                                 with ResultsData.
+  @param  ResultsData            A string returned from an IFR browser or
+                                 equivalent. The results string will have no
+                                 routing information in them.
+  @param  RetrieveData           A BOOLEAN field which allows an agent to retrieve
+                                 (if RetrieveData = TRUE) data from the uncommitted
+                                 browser state information or set (if RetrieveData
+                                 = FALSE) data in the uncommitted browser state
+                                 information.
+  @param  VariableGuid           An optional field to indicate the target variable
+                                 GUID name to use.
+  @param  VariableName           An optional field to indicate the target
+                                 human-readable variable name.
+
+  @retval EFI_SUCCESS            The results have been distributed or are awaiting
+                                 distribution.
+  @retval EFI_BUFFER_TOO_SMALL   The ResultsDataSize specified was too small to
+                                 contain the results data.
+
+**/
+EFI_STATUS
+EFIAPI
+BrowserCallback (
+  IN CONST EFI_FORM_BROWSER2_PROTOCOL  *This,
+  IN OUT UINTN                         *ResultsDataSize,
+  IN OUT EFI_STRING                    ResultsData,
+  IN BOOLEAN                           RetrieveData,
+  IN CONST EFI_GUID                    *VariableGuid, OPTIONAL
+  IN CONST CHAR16                      *VariableName  OPTIONAL
+  )
+{
+  EFI_STATUS            Status;
+  LIST_ENTRY            *Link;
+  FORMSET_STORAGE       *Storage;
+  FORM_BROWSER_FORMSET  *FormSet;
+  BOOLEAN               Found;
+  CHAR16                *ConfigResp;
+  CHAR16                *StrPtr;
+  UINTN                 BufferSize;
+  UINTN                 TmpSize;
+
+  if (ResultsDataSize == NULL || ResultsData == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (gCurrentSelection == NULL) {
+    return EFI_NOT_READY;
+  }
+
+  Storage = NULL;
+  ConfigResp = NULL;
+  FormSet = gCurrentSelection->FormSet;
+
+  //
+  // Find target storage
+  //
+  Link = GetFirstNode (&FormSet->StorageListHead);
+  if (IsNull (&FormSet->StorageListHead, Link)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (VariableGuid != NULL) {
+    //
+    // Try to find target storage
+    //
+    Found = FALSE;
+    while (!IsNull (&FormSet->StorageListHead, Link)) {
+      Storage = FORMSET_STORAGE_FROM_LINK (Link);
+      Link = GetNextNode (&FormSet->StorageListHead, Link);
+
+      if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {
+        if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
+          //
+          // Buffer storage require both GUID and Name
+          //
+          if (VariableName == NULL) {
+            return EFI_NOT_FOUND;
+          }
+
+          if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {
+            continue;
+          }
+        }
+        Found = TRUE;
+        break;
+      }
+    }
+
+    if (!Found) {
+      return EFI_NOT_FOUND;
+    }
+  } else {
+    //
+    // GUID/Name is not specified, take the first storage in FormSet
+    //
+    Storage = FORMSET_STORAGE_FROM_LINK (Link);
+  }
+
+  if (RetrieveData) {
+    //
+    // Skip if there is no RequestElement
+    //
+    if (Storage->ElementCount == 0) {
+      return EFI_SUCCESS;
+    }
+
+    //
+    // Generate <ConfigResp>
+    //
+    Status = StorageToConfigResp (Storage, &ConfigResp);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    // Skip <ConfigHdr> and '&' to point to <ConfigBody>
+    //
+    StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;
+
+    BufferSize = StrSize (StrPtr);
+    if (*ResultsDataSize < BufferSize) {
+      *ResultsDataSize = BufferSize;
+
+      gBS->FreePool (ConfigResp);
+      return EFI_BUFFER_TOO_SMALL;
+    }
+
+    *ResultsDataSize = BufferSize;
+    CopyMem (ResultsData, StrPtr, BufferSize);
+
+    gBS->FreePool (ConfigResp);
+  } else {
+    //
+    // Prepare <ConfigResp>
+    //
+    TmpSize = StrLen (ResultsData);
+    BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);
+    ConfigResp = AllocateZeroPool (BufferSize);
+    ASSERT (ConfigResp != NULL);
+
+    StrCpy (ConfigResp, Storage->ConfigHdr);
+    StrCat (ConfigResp, L"&");
+    StrCat (ConfigResp, ResultsData);
+
+    //
+    // Update Browser uncommited data
+    //
+    Status = ConfigRespToStorage (Storage, ConfigResp);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Initialize Setup
+
+  @param  entry                  EFI_IMAGE_ENTRY_POINT)
+
+  @retval EFI_SUCCESS            Setup loaded.
+  @retval other                  Setup Error
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSetup (
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_HANDLE                  HiiDriverHandle;
+  EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+
+  //@MT: EfiInitializeDriverLib (ImageHandle, SystemTable);
+
+  //
+  // Locate required Hii relative protocols
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiHiiDatabaseProtocolGuid,
+                  NULL,
+                  (VOID **) &mHiiDatabase
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->LocateProtocol (
+                  &gEfiHiiStringProtocolGuid,
+                  NULL,
+                  (VOID **) &mHiiString
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->LocateProtocol (
+                  &gEfiHiiConfigRoutingProtocolGuid,
+                  NULL,
+                  (VOID **) &mHiiConfigRouting
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Publish our HII data
+  //
+  Status = HiiLibCreateHiiDriverHandle (&HiiDriverHandle);
+  ASSERT_EFI_ERROR (Status);
+
+  PackageList = PreparePackageList (1, &gSetupBrowserGuid, SetupBrowserStrings);
+  ASSERT (PackageList != NULL);
+  Status = mHiiDatabase->NewPackageList (
+                           mHiiDatabase,
+                           PackageList,
+                           HiiDriverHandle,
+                           &gHiiHandle
+                           );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Initialize Driver private data
+  //
+  gFirstIn = TRUE;
+  BannerData = AllocateZeroPool (sizeof (BANNER_DATA));
+  ASSERT (BannerData != NULL);
+
+  //
+  // Install FormBrowser2 protocol
+  //
+  mPrivateData.Handle = NULL;
+  Status = gBS->InstallProtocolInterface (
+                  &mPrivateData.Handle,
+                  &gEfiFormBrowser2ProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &mPrivateData.FormBrowser2
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Install Print protocol
+  //
+  Status = gBS->InstallProtocolInterface (
+                  &mPrivateData.Handle,
+                  &gEfiPrintProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &mPrivateData.Print
+                  );
+
+  return Status;
+}
+
+
+/**
+  Create a new string in HII Package List.
+
+  @param  String                 The String to be added
+  @param  HiiHandle              The package list in the HII database to insert the
+                                 specified string.
+
+  @return The output string.
+
+**/
+EFI_STRING_ID
+NewString (
+  IN  CHAR16                   *String,
+  IN  EFI_HII_HANDLE           HiiHandle
+  )
+{
+  EFI_STRING_ID  StringId;
+  EFI_STATUS     Status;
+
+  StringId = 0;
+  Status = IfrLibNewString (HiiHandle, &StringId, String);
+  ASSERT_EFI_ERROR (Status);
+
+  return StringId;
+}
+
+
+/**
+  Delete a string from HII Package List.
+
+  @param  StringId               Id of the string in HII database.
+  @param  HiiHandle              The HII package list handle.
+
+  @retval EFI_SUCCESS            The string was deleted successfully.
+
+**/
+EFI_STATUS
+DeleteString (
+  IN  EFI_STRING_ID            StringId,
+  IN  EFI_HII_HANDLE           HiiHandle
+  )
+{
+  CHAR16  NullChar;
+
+  NullChar = CHAR_NULL;
+  return IfrLibSetString (HiiHandle, StringId, &NullChar);
+}
+
+
+/**
+  Get the string based on the StringId and HII Package List Handle.
+
+  @param  Token                  The String's ID.
+  @param  HiiHandle              The package list in the HII database to search for
+                                 the specified string.
+
+  @return The output string.
+
+**/
+CHAR16 *
+GetToken (
+  IN  EFI_STRING_ID                Token,
+  IN  EFI_HII_HANDLE               HiiHandle
+  )
+{
+  EFI_STATUS  Status;
+  CHAR16      *String;
+  UINTN       BufferLength;
+
+  //
+  // Set default string size assumption at no more than 256 bytes
+  //
+  BufferLength = 0x100;
+  String = AllocateZeroPool (BufferLength);
+  ASSERT (String != NULL);
+
+  Status = IfrLibGetString (HiiHandle, Token, String, &BufferLength);
+
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    gBS->FreePool (String);
+    String = AllocateZeroPool (BufferLength);
+    ASSERT (String != NULL);
+
+    Status = IfrLibGetString (HiiHandle, Token, String, &BufferLength);
+  }
+  ASSERT_EFI_ERROR (Status);
+
+  return String;
+}
+
+
+/**
+  Allocate new memory and then copy the Unicode string Source to Destination.
+
+  @param  Dest                   Location to copy string
+  @param  Src                    String to copy
+
+  @return NONE
+
+**/
+VOID
+NewStringCpy (
+  IN OUT CHAR16       **Dest,
+  IN CHAR16           *Src
+  )
+{
+  SafeFreePool (*Dest);
+  *Dest = AllocateCopyPool (StrSize (Src), Src);
+  ASSERT (*Dest != NULL);
+}
+
+
+/**
+  Allocate new memory and concatinate Source on the end of Destination.
+
+  @param  Dest                   String to added to the end of.
+  @param  Src                    String to concatinate.
+
+  @return NONE
+
+**/
+VOID
+NewStringCat (
+  IN OUT CHAR16       **Dest,
+  IN CHAR16           *Src
+  )
+{
+  CHAR16  *NewString;
+  UINTN   TmpSize;
+
+  if (*Dest == NULL) {
+    NewStringCpy (Dest, Src);
+    return;
+  }
+
+  TmpSize = StrSize (*Dest);
+  NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);
+  ASSERT (NewString != NULL);
+
+  StrCpy (NewString, *Dest);
+  StrCat (NewString, Src);
+
+  gBS->FreePool (*Dest);
+  *Dest = NewString;
+}
+
+
+/**
+  Synchronize Storage's Edit copy to Shadow copy.
+
+  @param  Storage                The Storage to be synchronized.
+
+  @return NONE
+
+**/
+VOID
+SynchronizeStorage (
+  IN FORMSET_STORAGE         *Storage
+  )
+{
+  LIST_ENTRY              *Link;
+  NAME_VALUE_NODE         *Node;
+
+  switch (Storage->Type) {
+  case EFI_HII_VARSTORE_BUFFER:
+    CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);
+    break;
+
+  case EFI_HII_VARSTORE_NAME_VALUE:
+    Link = GetFirstNode (&Storage->NameValueListHead);
+    while (!IsNull (&Storage->NameValueListHead, Link)) {
+      Node = NAME_VALUE_NODE_FROM_LINK (Link);
+
+      NewStringCpy (&Node->Value, Node->EditValue);
+
+      Link = GetNextNode (&Storage->NameValueListHead, Link);
+    }
+    break;
+
+  case EFI_HII_VARSTORE_EFI_VARIABLE:
+  default:
+    break;
+  }
+}
+
+
+/**
+  Get Value for given Name from a NameValue Storage.
+
+  @param  Storage                The NameValue Storage.
+  @param  Name                   The Name.
+  @param  Value                  The retured Value.
+
+  @retval EFI_SUCCESS            Value found for given Name.
+  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.
+
+**/
+EFI_STATUS
+GetValueByName (
+  IN FORMSET_STORAGE         *Storage,
+  IN CHAR16                  *Name,
+  IN OUT CHAR16              **Value
+  )
+{
+  LIST_ENTRY              *Link;
+  NAME_VALUE_NODE         *Node;
+
+  *Value = NULL;
+
+  Link = GetFirstNode (&Storage->NameValueListHead);
+  while (!IsNull (&Storage->NameValueListHead, Link)) {
+    Node = NAME_VALUE_NODE_FROM_LINK (Link);
+
+    if (StrCmp (Name, Node->Name) == 0) {
+      NewStringCpy (Value, Node->EditValue);
+      return EFI_SUCCESS;
+    }
+
+    Link = GetNextNode (&Storage->NameValueListHead, Link);
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+
+/**
+  Set Value of given Name in a NameValue Storage.
+
+  @param  Storage                The NameValue Storage.
+  @param  Name                   The Name.
+  @param  Value                  The Value to set.
+
+  @retval EFI_SUCCESS            Value found for given Name.
+  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.
+
+**/
+EFI_STATUS
+SetValueByName (
+  IN FORMSET_STORAGE         *Storage,
+  IN CHAR16                  *Name,
+  IN CHAR16                  *Value
+  )
+{
+  LIST_ENTRY              *Link;
+  NAME_VALUE_NODE         *Node;
+
+  Link = GetFirstNode (&Storage->NameValueListHead);
+  while (!IsNull (&Storage->NameValueListHead, Link)) {
+    Node = NAME_VALUE_NODE_FROM_LINK (Link);
+
+    if (StrCmp (Name, Node->Name) == 0) {
+      SafeFreePool (Node->EditValue);
+      Node->EditValue = AllocateCopyPool (StrSize (Value), Value);
+      ASSERT (Node->EditValue != NULL);
+      return EFI_SUCCESS;
+    }
+
+    Link = GetNextNode (&Storage->NameValueListHead, Link);
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+
+/**
+  Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
+
+  @param  Storage                The Storage to be conveted.
+  @param  ConfigResp             The returned <ConfigResp>.
+
+  @retval EFI_SUCCESS            Convert success.
+  @retval EFI_INVALID_PARAMETER  Incorrect storage type.
+
+**/
+EFI_STATUS
+StorageToConfigResp (
+  IN FORMSET_STORAGE         *Storage,
+  IN CHAR16                  **ConfigResp
+  )
+{
+  EFI_STATUS  Status;
+  EFI_STRING  Progress;
+  LIST_ENTRY              *Link;
+  NAME_VALUE_NODE         *Node;
+
+  Status = EFI_SUCCESS;
+
+  switch (Storage->Type) {
+  case EFI_HII_VARSTORE_BUFFER:
+    Status = mHiiConfigRouting->BlockToConfig (
+                                  mHiiConfigRouting,
+                                  Storage->ConfigRequest,
+                                  Storage->EditBuffer,
+                                  Storage->Size,
+                                  ConfigResp,
+                                  &Progress
+                                  );
+    break;
+
+  case EFI_HII_VARSTORE_NAME_VALUE:
+    *ConfigResp = NULL;
+    NewStringCat (ConfigResp, Storage->ConfigHdr);
+
+    Link = GetFirstNode (&Storage->NameValueListHead);
+    while (!IsNull (&Storage->NameValueListHead, Link)) {
+      Node = NAME_VALUE_NODE_FROM_LINK (Link);
+
+      NewStringCat (ConfigResp, L"&");
+      NewStringCat (ConfigResp, Node->Name);
+      NewStringCat (ConfigResp, L"=");
+      NewStringCat (ConfigResp, Node->EditValue);
+
+      Link = GetNextNode (&Storage->NameValueListHead, Link);
+    }
+    break;
+
+  case EFI_HII_VARSTORE_EFI_VARIABLE:
+  default:
+    Status = EFI_INVALID_PARAMETER;
+    break;
+  }
+
+  return Status;
+}
+
+
+/**
+  Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
+
+  @param  Storage                The Storage to receive the settings.
+  @param  ConfigResp             The <ConfigResp> to be converted.
+
+  @retval EFI_SUCCESS            Convert success.
+  @retval EFI_INVALID_PARAMETER  Incorrect storage type.
+
+**/
+EFI_STATUS
+ConfigRespToStorage (
+  IN FORMSET_STORAGE         *Storage,
+  IN CHAR16                  *ConfigResp
+  )
+{
+  EFI_STATUS  Status;
+  EFI_STRING  Progress;
+  UINTN       BufferSize;
+  CHAR16      *StrPtr;
+  CHAR16      *Name;
+  CHAR16      *Value;
+
+  Status = EFI_SUCCESS;
+
+  switch (Storage->Type) {
+  case EFI_HII_VARSTORE_BUFFER:
+    BufferSize = Storage->Size;
+    Status = mHiiConfigRouting->ConfigToBlock (
+                                  mHiiConfigRouting,
+                                  ConfigResp,
+                                  Storage->EditBuffer,
+                                  &BufferSize,
+                                  &Progress
+                                  );
+    break;
+
+  case EFI_HII_VARSTORE_NAME_VALUE:
+    StrPtr = StrStr (ConfigResp, L"&");
+    while (StrPtr != NULL) {
+      //
+      // Skip '&'
+      //
+      StrPtr = StrPtr + 1;
+      Name = StrPtr;
+      StrPtr = StrStr (StrPtr, L"=");
+      if (StrPtr == NULL) {
+        break;
+      }
+      *StrPtr = 0;
+
+      //
+      // Skip '='
+      //
+      StrPtr = StrPtr + 1;
+      Value = StrPtr;
+      StrPtr = StrStr (StrPtr, L"&");
+      if (StrPtr != NULL) {
+        *StrPtr = 0;
+      }
+      SetValueByName (Storage, Name, Value);
+    }
+    break;
+
+  case EFI_HII_VARSTORE_EFI_VARIABLE:
+  default:
+    Status = EFI_INVALID_PARAMETER;
+    break;
+  }
+
+  return Status;
+}
+
+
+/**
+  Get Question's current Value.
+
+  @param  FormSet                FormSet data structure.
+  @param  Form                   Form data structure.
+  @param  Question               Question to be initialized.
+  @param  Cached                 TRUE:  get from Edit copy FALSE: get from original
+                                 Storage
+
+  @retval EFI_SUCCESS            The function completed successfully.
+
+**/
+EFI_STATUS
+GetQuestionValue (
+  IN FORM_BROWSER_FORMSET             *FormSet,
+  IN FORM_BROWSER_FORM                *Form,
+  IN OUT FORM_BROWSER_STATEMENT       *Question,
+  IN BOOLEAN                          Cached
+  )
+{
+  EFI_STATUS          Status;
+  BOOLEAN             Enabled;
+  BOOLEAN             Pending;
+  UINT8               *Dst;
+  UINTN               StorageWidth;
+  EFI_TIME            EfiTime;
+  FORMSET_STORAGE     *Storage;
+  EFI_IFR_TYPE_VALUE  *QuestionValue;
+  CHAR16              *ConfigRequest;
+  CHAR16              *Progress;
+  CHAR16              *Result;
+  CHAR16              *Value;
+  UINTN               Length;
+  BOOLEAN             IsBufferStorage;
+  BOOLEAN             IsString;
+
+  Status = EFI_SUCCESS;
+
+  //
+  // Statement don't have storage, skip them
+  //
+  if (Question->QuestionId == 0) {
+    return Status;
+  }
+
+  //
+  // Question value is provided by an Expression, evaluate it
+  //
+  if (Question->ValueExpression != NULL) {
+    Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);
+    if (!EFI_ERROR (Status)) {
+      CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));
+    }
+    return Status;
+  }
+
+  //
+  // Question value is provided by RTC
+  //
+  Storage = Question->Storage;
+  QuestionValue = &Question->HiiValue.Value;
+  if (Storage == NULL) {
+    //
+    // It's a Question without storage, or RTC date/time
+    //
+    if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {
+      //
+      // Date and time define the same Flags bit
+      //
+      switch (Question->Flags & EFI_QF_DATE_STORAGE) {
+      case QF_DATE_STORAGE_TIME:
+        Status = gRT->GetTime (&EfiTime, NULL);
+        break;
+
+      case QF_DATE_STORAGE_WAKEUP:
+        Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
+        break;
+
+      case QF_DATE_STORAGE_NORMAL:
+      default:
+        //
+        // For date/time without storage
+        //
+        return EFI_SUCCESS;
+      }
+
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      if (Question->Operand == EFI_IFR_DATE_OP) {
+        QuestionValue->date.Year  = EfiTime.Year;
+        QuestionValue->date.Month = EfiTime.Month;
+        QuestionValue->date.Day   = EfiTime.Day;
+      } else {
+        QuestionValue->time.Hour   = EfiTime.Hour;
+        QuestionValue->time.Minute = EfiTime.Minute;
+        QuestionValue->time.Second = EfiTime.Second;
+      }
+    }
+
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Question value is provided by EFI variable
+  //
+  StorageWidth = Question->StorageWidth;
+  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+    if (Question->BufferValue != NULL) {
+      Dst = Question->BufferValue;
+    } else {
+      Dst = (UINT8 *) QuestionValue;
+    }
+
+    Status = gRT->GetVariable (
+                     Question->VariableName,
+                     &Storage->Guid,
+                     NULL,
+                     &StorageWidth,
+                     Dst
+                     );
+    //
+    // Always return success, even this EFI variable doesn't exist
+    //
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Question Value is provided by Buffer Storage or NameValue Storage
+  //
+  if (Question->BufferValue != NULL) {
+    //
+    // This Question is password or orderedlist
+    //
+    Dst = Question->BufferValue;
+  } else {
+    //
+    // Other type of Questions
+    //
+    Dst = (UINT8 *) &Question->HiiValue.Value;
+  }
+
+  IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);
+  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);
+  if (Cached) {
+    if (IsBufferStorage) {
+      //
+      // Copy from storage Edit buffer
+      //
+      CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);
+    } else {
+      Status = GetValueByName (Storage, Question->VariableName, &Value);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      if (IsString) {
+        StrCpy ((CHAR16 *) Dst, Value);
+      } else {
+        Status = R8_HexStringToBuf (Dst, &StorageWidth, Value, NULL);
+      }
+
+      gBS->FreePool (Value);
+    }
+  } else {
+    //
+    // Request current settings from Configuration Driver
+    //
+    if (FormSet->ConfigAccess == NULL) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
+    //                   <ConfigHdr> + "&" + <VariableName>
+    //
+    if (IsBufferStorage) {
+      Length = StrLen (Storage->ConfigHdr);
+      Length += StrLen (Question->BlockName);
+    } else {
+      Length = StrLen (Storage->ConfigHdr);
+      Length += StrLen (Question->VariableName) + 1;
+    }
+    ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));
+    ASSERT (ConfigRequest != NULL);
+
+    StrCpy (ConfigRequest, Storage->ConfigHdr);
+    if (IsBufferStorage) {
+      StrCat (ConfigRequest, Question->BlockName);
+    } else {
+      StrCat (ConfigRequest, L"&");
+      StrCat (ConfigRequest, Question->VariableName);
+    }
+
+    Status = FormSet->ConfigAccess->ExtractConfig (
+                                      FormSet->ConfigAccess,
+                                      ConfigRequest,
+                                      &Progress,
+                                      &Result
+                                      );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    // Skip <ConfigRequest>
+    //
+    Value = Result + Length;
+    if (IsBufferStorage) {
+      //
+      // Skip "&VALUE"
+      //
+      Value = Value + 6;
+    }
+    if (*Value != '=') {
+      gBS->FreePool (Result);
+      return EFI_NOT_FOUND;
+    }
+    //
+    // Skip '=', point to value
+    //
+    Value = Value + 1;
+    if (!IsBufferStorage && IsString) {
+      StrCpy ((CHAR16 *) Dst, Value);
+    } else {
+      Status = R8_HexStringToBuf (Dst, &StorageWidth, Value, NULL);
+      if (EFI_ERROR (Status)) {
+        gBS->FreePool (Result);
+        return Status;
+      }
+    }
+
+    //
+    // Synchronize Edit Buffer
+    //
+    if (IsBufferStorage) {
+      CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);
+    } else {
+      SetValueByName (Storage, Question->VariableName, Value);
+    }
+    gBS->FreePool (Result);
+  }
+
+  return Status;
+}
+
+
+/**
+  Save Question Value to edit copy(cached) or Storage(uncached).
+
+  @param  FormSet                FormSet data structure.
+  @param  Form                   Form data structure.
+  @param  Question               Pointer to the Question.
+  @param  Cached                 TRUE:  set to Edit copy FALSE: set to original
+                                 Storage
+
+  @retval EFI_SUCCESS            The function completed successfully.
+
+**/
+EFI_STATUS
+SetQuestionValue (
+  IN FORM_BROWSER_FORMSET             *FormSet,
+  IN FORM_BROWSER_FORM                *Form,
+  IN OUT FORM_BROWSER_STATEMENT       *Question,
+  IN BOOLEAN                          Cached
+  )
+{
+  EFI_STATUS          Status;
+  BOOLEAN             Enabled;
+  BOOLEAN             Pending;
+  UINT8               *Src;
+  EFI_TIME            EfiTime;
+  UINTN               BufferLen;
+  UINTN               StorageWidth;
+  FORMSET_STORAGE     *Storage;
+  EFI_IFR_TYPE_VALUE  *QuestionValue;
+  CHAR16              *ConfigResp;
+  CHAR16              *Progress;
+  CHAR16              *Value;
+  UINTN               Length;
+  BOOLEAN             IsBufferStorage;
+  BOOLEAN             IsString;
+
+  Status = EFI_SUCCESS;
+
+  //
+  // Statement don't have storage, skip them
+  //
+  if (Question->QuestionId == 0) {
+    return Status;
+  }
+
+  //
+  // If Question value is provided by an Expression, then it is read only
+  //
+  if (Question->ValueExpression != NULL) {
+    return Status;
+  }
+
+  //
+  // Question value is provided by RTC
+  //
+  Storage = Question->Storage;
+  QuestionValue = &Question->HiiValue.Value;
+  if (Storage == NULL) {
+    //
+    // It's a Question without storage, or RTC date/time
+    //
+    if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {
+      //
+      // Date and time define the same Flags bit
+      //
+      switch (Question->Flags & EFI_QF_DATE_STORAGE) {
+      case QF_DATE_STORAGE_TIME:
+        Status = gRT->GetTime (&EfiTime, NULL);
+        break;
+
+      case QF_DATE_STORAGE_WAKEUP:
+        Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
+        break;
+
+      case QF_DATE_STORAGE_NORMAL:
+      default:
+        //
+        // For date/time without storage
+        //
+        return EFI_SUCCESS;
+      }
+
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      if (Question->Operand == EFI_IFR_DATE_OP) {
+        EfiTime.Year  = QuestionValue->date.Year;
+        EfiTime.Month = QuestionValue->date.Month;
+        EfiTime.Day   = QuestionValue->date.Day;
+      } else {
+        EfiTime.Hour   = QuestionValue->time.Hour;
+        EfiTime.Minute = QuestionValue->time.Minute;
+        EfiTime.Second = QuestionValue->time.Second;
+      }
+
+      if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {
+        Status = gRT->SetTime (&EfiTime);
+      } else {
+        Status = gRT->SetWakeupTime (TRUE, &EfiTime);
+      }
+    }
+
+    return Status;
+  }
+
+  //
+  // Question value is provided by EFI variable
+  //
+  StorageWidth = Question->StorageWidth;
+  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+    if (Question->BufferValue != NULL) {
+      Src = Question->BufferValue;
+    } else {
+      Src = (UINT8 *) QuestionValue;
+    }
+
+    Status = gRT->SetVariable (
+                     Question->VariableName,
+                     &Storage->Guid,
+                     Storage->Attributes,
+                     StorageWidth,
+                     Src
+                     );
+    return Status;
+  }
+
+  //
+  // Question Value is provided by Buffer Storage or NameValue Storage
+  //
+  if (Question->BufferValue != NULL) {
+    Src = Question->BufferValue;
+  } else {
+    Src = (UINT8 *) &Question->HiiValue.Value;
+  }
+
+  IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);
+  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);
+  if (IsBufferStorage) {
+    //
+    // Copy to storage edit buffer
+    //
+    CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
+  } else {
+    if (IsString) {
+      Value = NULL;
+      NewStringCpy (&Value, (CHAR16 *) Src);
+    } else {
+      BufferLen = (StorageWidth * 2 + 1) * sizeof (CHAR16);
+      Value = AllocateZeroPool (BufferLen);
+      ASSERT (Value != NULL);
+      R8_BufToHexString (Value, &BufferLen, Src, StorageWidth);
+    }
+
+    Status = SetValueByName (Storage, Question->VariableName, Value);
+    gBS->FreePool (Value);
+  }
+
+  if (!Cached) {
+    //
+    // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
+    //                <ConfigHdr> + "&" + <VariableName> + "=" + "<HexCh>StorageWidth * 2"
+    //
+    if (IsBufferStorage) {
+      Length = StrLen (Question->BlockName) + 7;
+    } else {
+      Length = StrLen (Question->VariableName) + 2;
+    }
+    if (!IsBufferStorage && IsString) {
+      Length += StrLen ((CHAR16 *) Src);
+    } else {
+      Length += (StorageWidth * 2);
+    }
+    ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));
+    ASSERT (ConfigResp != NULL);
+
+    StrCpy (ConfigResp, Storage->ConfigHdr);
+    if (IsBufferStorage) {
+      StrCat (ConfigResp, Question->BlockName);
+      StrCat (ConfigResp, L"&VALUE=");
+    } else {
+      StrCat (ConfigResp, L"&");
+      StrCat (ConfigResp, Question->VariableName);
+      StrCat (ConfigResp, L"=");
+    }
+
+    Value = ConfigResp + StrLen (ConfigResp);
+    if (!IsBufferStorage && IsString) {
+      StrCpy (Value, (CHAR16 *) Src);
+    } else {
+      BufferLen = (StorageWidth * 2 + 1) * sizeof (CHAR16);
+      R8_BufToHexString (Value, &BufferLen, Src, StorageWidth);
+    }
+
+    //
+    // Submit Question Value to Configuration Driver
+    //
+    if (FormSet->ConfigAccess != NULL) {
+      Status = FormSet->ConfigAccess->RouteConfig (
+                                        FormSet->ConfigAccess,
+                                        ConfigResp,
+                                        &Progress
+                                        );
+      if (EFI_ERROR (Status)) {
+        gBS->FreePool (ConfigResp);
+        return Status;
+      }
+    }
+    gBS->FreePool (ConfigResp);
+
+    //
+    // Synchronize shadow Buffer
+    //
+    SynchronizeStorage (Storage);
+  }
+
+  return Status;
+}
+
+
+/**
+  Perform inconsistent check for a Form.
+
+  @param  FormSet                FormSet data structure.
+  @param  Form                   Form data structure.
+  @param  Question               The Question to be validated.
+  @param  Type                   Validation type: InConsistent or NoSubmit
+
+  @retval EFI_SUCCESS            Form validation pass.
+  @retval other                  Form validation failed.
+
+**/
+EFI_STATUS
+ValidateQuestion (
+  IN  FORM_BROWSER_FORMSET            *FormSet,
+  IN  FORM_BROWSER_FORM               *Form,
+  IN  FORM_BROWSER_STATEMENT          *Question,
+  IN  UINTN                           Type
+  )
+{
+  EFI_STATUS              Status;
+  LIST_ENTRY              *Link;
+  LIST_ENTRY              *ListHead;
+  EFI_STRING              PopUp;
+  EFI_INPUT_KEY           Key;
+  FORM_EXPRESSION         *Expression;
+
+  if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {
+    ListHead = &Question->InconsistentListHead;
+  } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
+    ListHead = &Question->NoSubmitListHead;
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+
+  Link = GetFirstNode (ListHead);
+  while (!IsNull (ListHead, Link)) {
+    Expression = FORM_EXPRESSION_FROM_LINK (Link);
+
+    //
+    // Evaluate the expression
+    //
+    Status = EvaluateExpression (FormSet, Form, Expression);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    if (Expression->Result.Value.b) {
+      //
+      // Condition meet, show up error message
+      //
+      if (Expression->Error != 0) {
+        PopUp = GetToken (Expression->Error, FormSet->HiiHandle);
+        do {
+          CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);
+        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+        gBS->FreePool (PopUp);
+      }
+
+      return EFI_NOT_READY;
+    }
+
+    Link = GetNextNode (ListHead, Link);
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Perform NoSubmit check for a Form.
+
+  @param  FormSet                FormSet data structure.
+  @param  Form                   Form data structure.
+
+  @retval EFI_SUCCESS            Form validation pass.
+  @retval other                  Form validation failed.
+
+**/
+EFI_STATUS
+NoSubmitCheck (
+  IN  FORM_BROWSER_FORMSET            *FormSet,
+  IN  FORM_BROWSER_FORM               *Form
+  )
+{
+  EFI_STATUS              Status;
+  LIST_ENTRY              *Link;
+  FORM_BROWSER_STATEMENT  *Question;
+
+  Link = GetFirstNode (&Form->StatementListHead);
+  while (!IsNull (&Form->StatementListHead, Link)) {
+    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+
+    Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    Link = GetNextNode (&Form->StatementListHead, Link);
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Submit a Form.
+
+  @param  FormSet                FormSet data structure.
+  @param  Form                   Form data structure.
+
+  @retval EFI_SUCCESS            The function completed successfully.
+
+**/
+EFI_STATUS
+SubmitForm (
+  IN FORM_BROWSER_FORMSET             *FormSet,
+  IN FORM_BROWSER_FORM                *Form
+  )
+{
+  EFI_STATUS              Status;
+  LIST_ENTRY              *Link;
+  EFI_STRING              ConfigResp;
+  EFI_STRING              Progress;
+  FORMSET_STORAGE         *Storage;
+
+  //
+  // Validate the Form by NoSubmit check
+  //
+  Status = NoSubmitCheck (FormSet, Form);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Submit Buffer storage or Name/Value storage
+  //
+  Link = GetFirstNode (&FormSet->StorageListHead);
+  while (!IsNull (&FormSet->StorageListHead, Link)) {
+    Storage = FORMSET_STORAGE_FROM_LINK (Link);
+    Link = GetNextNode (&FormSet->StorageListHead, Link);
+
+    if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+      continue;
+    }
+
+    //
+    // Skip if there is no RequestElement
+    //
+    if (Storage->ElementCount == 0) {
+      continue;
+    }
+
+    //
+    // Prepare <ConfigResp>
+    //
+    Status = StorageToConfigResp (Storage, &ConfigResp);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    // Send <ConfigResp> to Configuration Driver
+    //
+    if (FormSet->ConfigAccess != NULL) {
+      Status = FormSet->ConfigAccess->RouteConfig (
+                                        FormSet->ConfigAccess,
+                                        ConfigResp,
+                                        &Progress
+                                        );
+      if (EFI_ERROR (Status)) {
+        gBS->FreePool (ConfigResp);
+        return Status;
+      }
+    }
+    gBS->FreePool (ConfigResp);
+
+    //
+    // Config success, update storage shadow Buffer
+    //
+    SynchronizeStorage (Storage);
+  }
+
+  gNvUpdateRequired = FALSE;
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Reset Question to its default value.
+
+  @param  FormSet                FormSet data structure.
+  @param  DefaultId              The Class of the default.
+
+  @retval EFI_SUCCESS            Question is reset to default value.
+
+**/
+EFI_STATUS
+GetQuestionDefault (
+  IN FORM_BROWSER_FORMSET             *FormSet,
+  IN FORM_BROWSER_FORM                *Form,
+  IN FORM_BROWSER_STATEMENT           *Question,
+  IN UINT16                           DefaultId
+  )
+{
+  EFI_STATUS              Status;
+  LIST_ENTRY              *Link;
+  QUESTION_DEFAULT        *Default;
+  QUESTION_OPTION         *Option;
+  EFI_HII_VALUE           *HiiValue;
+  UINT8                   Index;
+
+  Status = EFI_SUCCESS;
+
+  //
+  // Statement don't have storage, skip them
+  //
+  if (Question->QuestionId == 0) {
+    return Status;
+  }
+
+  //
+  // There are three ways to specify default value for a Question:
+  //  1, use nested EFI_IFR_DEFAULT (highest priority)
+  //  2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
+  //  3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
+  //
+  HiiValue = &Question->HiiValue;
+
+  //
+  // EFI_IFR_DEFAULT has highest priority
+  //
+  if (!IsListEmpty (&Question->DefaultListHead)) {
+    Link = GetFirstNode (&Question->DefaultListHead);
+    while (!IsNull (&Question->DefaultListHead, Link)) {
+      Default = QUESTION_DEFAULT_FROM_LINK (Link);
+
+      if (Default->DefaultId == DefaultId) {
+        if (Default->ValueExpression != NULL) {
+          //
+          // Default is provided by an Expression, evaluate it
+          //
+          Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);
+          if (EFI_ERROR (Status)) {
+            return Status;
+          }
+
+          CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));
+        } else {
+          //
+          // Default value is embedded in EFI_IFR_DEFAULT
+          //
+          CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
+        }
+
+        return EFI_SUCCESS;
+      }
+
+      Link = GetNextNode (&Question->DefaultListHead, Link);
+    }
+  }
+
+  //
+  // EFI_ONE_OF_OPTION
+  //
+  if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
+    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING)  {
+      //
+      // OneOfOption could only provide Standard and Manufacturing default
+      //
+      Link = GetFirstNode (&Question->OptionListHead);
+      while (!IsNull (&Question->OptionListHead, Link)) {
+        Option = QUESTION_OPTION_FROM_LINK (Link);
+
+        if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Option->Flags & EFI_IFR_OPTION_DEFAULT)) ||
+            ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG))
+           ) {
+          CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
+
+          return EFI_SUCCESS;
+        }
+
+        Link = GetNextNode (&Question->OptionListHead, Link);
+      }
+    }
+  }
+
+  //
+  // EFI_IFR_CHECKBOX - lowest priority
+  //
+  if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
+    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING)  {
+      //
+      // Checkbox could only provide Standard and Manufacturing default
+      //
+      if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT)) ||
+          ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG))
+         ) {
+        HiiValue->Value.b = TRUE;
+      } else {
+        HiiValue->Value.b = FALSE;
+      }
+
+      return EFI_SUCCESS;
+    }
+  }
+
+  //
+  // For Questions without default
+  //
+  switch (Question->Operand) {
+  case EFI_IFR_NUMERIC_OP:
+    //
+    // Take minimal value as numeric's default value
+    //
+    HiiValue->Value.u64 = Question->Minimum;
+    break;
+
+  case EFI_IFR_ONE_OF_OP:
+    //
+    // Take first oneof option as oneof's default value
+    //
+    Link = GetFirstNode (&Question->OptionListHead);
+    if (!IsNull (&Question->OptionListHead, Link)) {
+      Option = QUESTION_OPTION_FROM_LINK (Link);
+      CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
+    }
+    break;
+
+  case EFI_IFR_ORDERED_LIST_OP:
+    //
+    // Take option sequence in IFR as ordered list's default value
+    //
+    Index = 0;
+    Link = GetFirstNode (&Question->OptionListHead);
+    while (!IsNull (&Question->OptionListHead, Link)) {
+      Option = QUESTION_OPTION_FROM_LINK (Link);
+
+      Question->BufferValue[Index] = Option->Value.Value.u8;
+
+      Index++;
+      if (Index >= Question->MaxContainers) {
+        break;
+      }
+
+      Link = GetNextNode (&Question->OptionListHead, Link);
+    }
+    break;
+
+  default:
+    Status = EFI_NOT_FOUND;
+    break;
+  }
+
+  return Status;
+}
+
+
+/**
+  Reset Questions in a Form to their default value.
+
+  @param  FormSet                FormSet data structure.
+  @param  Form                   The Form which to be reset.
+  @param  DefaultId              The Class of the default.
+
+  @retval EFI_SUCCESS            The function completed successfully.
+
+**/
+EFI_STATUS
+ExtractFormDefault (
+  IN FORM_BROWSER_FORMSET             *FormSet,
+  IN FORM_BROWSER_FORM                *Form,
+  IN UINT16                           DefaultId
+  )
+{
+  EFI_STATUS              Status;
+  LIST_ENTRY              *Link;
+  FORM_BROWSER_STATEMENT  *Question;
+
+  Link = GetFirstNode (&Form->StatementListHead);
+  while (!IsNull (&Form->StatementListHead, Link)) {
+    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+    Link = GetNextNode (&Form->StatementListHead, Link);
+
+    //
+    // Reset Question to its default value
+    //
+    Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    //
+    // Synchronize Buffer storage's Edit buffer
+    //
+    if ((Question->Storage != NULL) &&
+        (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {
+      SetQuestionValue (FormSet, Form, Question, TRUE);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Initialize Question's Edit copy from Storage.
+
+  @param  FormSet                FormSet data structure.
+  @param  Form                   Form data structure.
+
+  @retval EFI_SUCCESS            The function completed successfully.
+
+**/
+EFI_STATUS
+LoadFormConfig (
+  IN FORM_BROWSER_FORMSET             *FormSet,
+  IN FORM_BROWSER_FORM                *Form
+  )
+{
+  EFI_STATUS              Status;
+  LIST_ENTRY              *Link;
+  FORM_BROWSER_STATEMENT  *Question;
+
+  Link = GetFirstNode (&Form->StatementListHead);
+  while (!IsNull (&Form->StatementListHead, Link)) {
+    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+
+    //
+    // Initialize local copy of Value for each Question
+    //
+    Status = GetQuestionValue (FormSet, Form, Question, TRUE);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    Link = GetNextNode (&Form->StatementListHead, Link);
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Fill storage's edit copy with settings requested from Configuration Driver.
+
+  @param  FormSet                FormSet data structure.
+  @param  Storage                Buffer Storage.
+
+  @retval EFI_SUCCESS            The function completed successfully.
+
+**/
+EFI_STATUS
+LoadStorage (
+  IN FORM_BROWSER_FORMSET    *FormSet,
+  IN FORMSET_STORAGE         *Storage
+  )
+{
+  EFI_STATUS  Status;
+  EFI_STRING  Progress;
+  EFI_STRING  Result;
+  CHAR16      *StrPtr;
+
+  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+    return EFI_SUCCESS;
+  }
+
+  if (FormSet->ConfigAccess == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  if (Storage->ElementCount == 0) {
+    //
+    // Skip if there is no RequestElement
+    //
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Request current settings from Configuration Driver
+  //
+  Status = FormSet->ConfigAccess->ExtractConfig (
+                                    FormSet->ConfigAccess,
+                                    Storage->ConfigRequest,
+                                    &Progress,
+                                    &Result
+                                    );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Convert Result from <ConfigAltResp> to <ConfigResp>
+  //
+  StrPtr = StrStr (Result, L"ALTCFG");
+  if (StrPtr != NULL) {
+    *StrPtr = L'\0';
+  }
+
+  Status = ConfigRespToStorage (Storage, Result);
+  gBS->FreePool (Result);
+  return Status;
+}
+
+
+/**
+  Get current setting of Questions.
+
+  @param  FormSet                FormSet data structure.
+
+  @retval EFI_SUCCESS            The function completed successfully.
+
+**/
+EFI_STATUS
+InitializeCurrentSetting (
+  IN OUT FORM_BROWSER_FORMSET             *FormSet
+  )
+{
+  LIST_ENTRY              *Link;
+  FORMSET_STORAGE         *Storage;
+  FORM_BROWSER_FORM       *Form;
+  EFI_STATUS              Status;
+
+  //
+  // Extract default from IFR binary
+  //
+  Link = GetFirstNode (&FormSet->FormListHead);
+  while (!IsNull (&FormSet->FormListHead, Link)) {
+    Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+
+    Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);
+
+    Link = GetNextNode (&FormSet->FormListHead, Link);
+  }
+
+  //
+  // Request current settings from Configuration Driver
+  //
+  Link = GetFirstNode (&FormSet->StorageListHead);
+  while (!IsNull (&FormSet->StorageListHead, Link)) {
+    Storage = FORMSET_STORAGE_FROM_LINK (Link);
+
+    Status = LoadStorage (FormSet, Storage);
+
+    //
+    // Now Edit Buffer is filled with default values(lower priority) and current
+    // settings(higher priority), sychronize it to shadow Buffer
+    //
+    if (!EFI_ERROR (Status)) {
+      SynchronizeStorage (Storage);
+    }
+
+    Link = GetNextNode (&FormSet->StorageListHead, Link);
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Fetch the Ifr binary data of a FormSet.
+
+  @param  Handle                 PackageList Handle
+  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero
+                                 GUID), take the first FormSet found in package
+                                 list.
+  @param  BinaryLength           The length of the FormSet IFR binary.
+  @param  BinaryData             The buffer designed to receive the FormSet.
+
+  @retval EFI_SUCCESS            Buffer filled with the requested FormSet.
+                                 BufferLength was updated.
+  @retval EFI_INVALID_PARAMETER  The handle is unknown.
+  @retval EFI_NOT_FOUND          A form or FormSet on the requested handle cannot
+                                 be found with the requested FormId.
+
+**/
+EFI_STATUS
+GetIfrBinaryData (
+  IN  EFI_HII_HANDLE   Handle,
+  IN OUT EFI_GUID      *FormSetGuid,
+  OUT UINTN            *BinaryLength,
+  OUT UINT8            **BinaryData
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
+  UINTN                        BufferSize;
+  UINT8                        *Package;
+  UINT8                        *OpCodeData;
+  UINT32                       Offset;
+  UINT32                       Offset2;
+  BOOLEAN                      ReturnDefault;
+  UINT32                       PackageListLength;
+  EFI_HII_PACKAGE_HEADER       PackageHeader;
+
+  OpCodeData = NULL;
+  Package = NULL;
+  ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;
+
+  //
+  // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
+  //
+  if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {
+    ReturnDefault = TRUE;
+  } else {
+    ReturnDefault = FALSE;
+  }
+
+  //
+  // Get HII PackageList
+  //
+  BufferSize = 0;
+  HiiPackageList = NULL;
+  Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    HiiPackageList = AllocatePool (BufferSize);
+    ASSERT (HiiPackageList != NULL);
+
+    Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
+  }
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Get Form package from this HII package List
+  //
+  Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+  Offset2 = 0;
+  CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
+
+  while (Offset < PackageListLength) {
+    Package = ((UINT8 *) HiiPackageList) + Offset;
+    CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+
+    if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {
+      //
+      // Search FormSet in this Form Package
+      //
+      Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
+      while (Offset2 < PackageHeader.Length) {
+        OpCodeData = Package + Offset2;
+
+        if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
+          //
+          // Check whether return default FormSet
+          //
+          if (ReturnDefault) {
+            break;
+          }
+
+          //
+          // FormSet GUID is specified, check it
+          //
+          if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
+            break;
+          }
+        }
+
+        Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+      }
+
+      if (Offset2 < PackageHeader.Length) {
+        //
+        // Target formset found
+        //
+        break;
+      }
+    }
+
+    Offset += PackageHeader.Length;
+  }
+
+  if (Offset >= PackageListLength) {
+    //
+    // Form package not found in this Package List
+    //
+    gBS->FreePool (HiiPackageList);
+    return EFI_NOT_FOUND;
+  }
+
+  if (ReturnDefault && FormSetGuid != NULL) {
+    //
+    // Return the default FormSet GUID
+    //
+    CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
+  }
+
+  //
+  // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
+  // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
+  // of the Form Package.
+  //
+  *BinaryLength = PackageHeader.Length - Offset2;
+  *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
+
+  gBS->FreePool (HiiPackageList);
+
+  if (*BinaryData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Initialize the internal data structure of a FormSet.
+
+  @param  Handle                 PackageList Handle
+  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero
+                                 GUID), take the first FormSet found in package
+                                 list.
+  @param  FormSet                FormSet data structure.
+
+  @retval EFI_SUCCESS            The function completed successfully.
+  @retval EFI_NOT_FOUND          The specified FormSet could not be found.
+
+**/
+EFI_STATUS
+InitializeFormSet (
+  IN  EFI_HII_HANDLE                   Handle,
+  IN OUT EFI_GUID                      *FormSetGuid,
+  OUT FORM_BROWSER_FORMSET             *FormSet
+  )
+{
+  EFI_STATUS                Status;
+  EFI_HANDLE                DriverHandle;
+  UINT16                    Index;
+
+  Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  FormSet->HiiHandle = Handle;
+  CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
+
+  //
+  // Retrieve ConfigAccess Protocol associated with this HiiPackageList
+  //
+  Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  FormSet->DriverHandle = DriverHandle;
+  Status = gBS->HandleProtocol (
+                  DriverHandle,
+                  &gEfiHiiConfigAccessProtocolGuid,
+                  (VOID **) &FormSet->ConfigAccess
+                  );
+  if (EFI_ERROR (Status)) {
+    //
+    // Configuration Driver don't attach ConfigAccess protocol to its HII package
+    // list, then there will be no configuration action required
+    //
+    FormSet->ConfigAccess = NULL;
+  }
+
+  //
+  // Parse the IFR binary OpCodes
+  //
+  Status = ParseOpCodes (FormSet);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  gClassOfVfr = FormSet->SubClass;
+  if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
+    FrontPageHandle = FormSet->HiiHandle;
+  }
+
+  //
+  // Match GUID to find out the function key setting. If match fail, use the default setting.
+  //
+  for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {
+    if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {
+      //
+      // Update the function key setting.
+      //
+      gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;
+      //
+      // Function key prompt can not be displayed if the function key has been disabled.
+      //
+      if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {
+        gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+      }
+
+      if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {
+        gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+      }
+
+      if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {
+        gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+      }
+
+      if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {
+        gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+      }
+    }
+  }
+
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
new file mode 100644 (file)
index 0000000..3ade4da
--- /dev/null
@@ -0,0 +1,760 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+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.
+
+Module Name:
+
+  Setup.h
+
+Abstract:
+
+
+Revision History
+
+
+**/
+
+#ifndef _SETUP_H
+#define _SETUP_H
+
+
+#include <PiDxe.h>
+
+#include <Protocol/Print.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/FormBrowser2.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+
+#include <MdeModuleHii.h>
+
+#include <Library/GraphicsLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/IfrSupportLib.h>
+#include <Library/HiiLib.h>
+
+#include "R8Lib.h"
+
+#include "Colors.h"
+
+//@MT:#include EFI_PROTOCOL_DEFINITION (HiiDatabase)
+//@MT:#include EFI_PROTOCOL_DEFINITION (HiiString)
+//@MT:#include EFI_PROTOCOL_DEFINITION (HiiConfigRouting)
+//@MT:#include EFI_PROTOCOL_DEFINITION (HiiConfigAccess)
+//@MT:#include EFI_PROTOCOL_DEFINITION (FormBrowser2)
+
+//@MT:#include EFI_GUID_DEFINITION (GlobalVariable)
+//@MT:#include EFI_PROTOCOL_DEFINITION (DevicePath)
+//@MT:#include EFI_PROTOCOL_DEFINITION (SimpleTextOut)
+//@MT:#include EFI_PROTOCOL_DEFINITION (SimpleTextIn)
+//@MT:#include EFI_PROTOCOL_DEFINITION (Print)
+//@MT:#include EFI_PROTOCOL_DEFINITION (UnicodeCollation)
+
+//
+// This is the generated header file which includes whatever needs to be exported (strings + IFR)
+//
+
+extern UINT8  SetupBrowserStrings[];
+
+//
+// Screen definitions
+//
+#define BANNER_HEIGHT                 6
+#define BANNER_COLUMNS                3
+
+#define FRONT_PAGE_HEADER_HEIGHT      6
+#define NONE_FRONT_PAGE_HEADER_HEIGHT 3
+#define LEFT_SKIPPED_COLUMNS          4
+#define FOOTER_HEIGHT                 4
+#define STATUS_BAR_HEIGHT             1
+#define SCROLL_ARROW_HEIGHT           1
+#define POPUP_PAD_SPACE_COUNT         5
+#define POPUP_FRAME_WIDTH             2
+
+//
+// Definition for function key setting
+//
+#define NONE_FUNCTION_KEY_SETTING     0
+#define DEFAULT_FUNCTION_KEY_SETTING  (FUNCTION_ONE | FUNCTION_TWO | FUNCTION_NINE | FUNCTION_TEN)
+
+#define FUNCTION_ONE                  (1 << 0)
+#define FUNCTION_TWO                  (1 << 1)
+#define FUNCTION_NINE                 (1 << 2)
+#define FUNCTION_TEN                  (1 << 3)
+
+typedef struct {
+  EFI_GUID  FormSetGuid;
+  UINTN     KeySetting;
+} FUNCTIION_KEY_SETTING;
+
+//
+// Character definitions
+//
+#define CHAR_SPACE              0x0020
+#define UPPER_LOWER_CASE_OFFSET 0x20
+
+//
+// Time definitions
+//
+#define ONE_SECOND  10000000
+
+//
+// Display definitions
+//
+#define LEFT_HYPER_DELIMITER      L'<'
+#define RIGHT_HYPER_DELIMITER     L'>'
+
+#define LEFT_ONEOF_DELIMITER      L'<'
+#define RIGHT_ONEOF_DELIMITER     L'>'
+
+#define LEFT_NUMERIC_DELIMITER    L'['
+#define RIGHT_NUMERIC_DELIMITER   L']'
+
+#define LEFT_CHECKBOX_DELIMITER   L'['
+#define RIGHT_CHECKBOX_DELIMITER  L']'
+
+#define CHECK_ON                  L'X'
+#define CHECK_OFF                 L' '
+
+#define TIME_SEPARATOR            L':'
+#define DATE_SEPARATOR            L'/'
+
+#define YES_ANSWER                L'Y'
+#define NO_ANSWER                 L'N'
+
+//
+// This is the Input Error Message
+//
+#define INPUT_ERROR 1
+
+//
+// This is the NV RAM update required Message
+//
+#define NV_UPDATE_REQUIRED  2
+
+//
+// Refresh the Status Bar with flags
+//
+#define REFRESH_STATUS_BAR  0xff
+
+//
+// Incremental string lenght of ConfigRequest
+//
+#define CONFIG_REQUEST_STRING_INCREMENTAL  1024
+
+//
+// HII value compare result
+//
+#define HII_VALUE_UNDEFINED     0
+#define HII_VALUE_EQUAL         1
+#define HII_VALUE_LESS_THAN     2
+#define HII_VALUE_GREATER_THAN  3
+
+//
+// Incremental size of stack for expression
+//
+#define EXPRESSION_STACK_SIZE_INCREMENT    0x100
+
+
+#define EFI_SPECIFICATION_ERRATA_VERSION   0
+
+#define EFI_IFR_SPECIFICATION_VERSION  \
+        ((((EFI_SPECIFICATION_VERSION) >> 8) & 0xff00) | \
+         (((EFI_SPECIFICATION_VERSION) & 0xf) << 4) | \
+         ((EFI_SPECIFICATION_ERRATA_VERSION) & 0xf))
+
+#define SETUP_DRIVER_SIGNATURE EFI_SIGNATURE_32 ('F', 'B', 'D', 'V')
+typedef struct {
+  UINT32                             Signature;
+
+  EFI_HANDLE                         Handle;
+
+  //
+  // Produced protocol
+  //
+  EFI_FORM_BROWSER2_PROTOCOL         FormBrowser2;
+  EFI_PRINT_PROTOCOL                 Print;
+
+} SETUP_DRIVER_PRIVATE_DATA;
+
+typedef struct {
+  EFI_STRING_ID  Banner[BANNER_HEIGHT][BANNER_COLUMNS];
+} BANNER_DATA;
+
+//
+// IFR relative definition
+//
+#define EFI_HII_EXPRESSION_INCONSISTENT_IF   0
+#define EFI_HII_EXPRESSION_NO_SUBMIT_IF      1
+#define EFI_HII_EXPRESSION_GRAY_OUT_IF       2
+#define EFI_HII_EXPRESSION_SUPPRESS_IF       3
+#define EFI_HII_EXPRESSION_DISABLE_IF        4
+#define EFI_HII_EXPRESSION_VALUE             5
+#define EFI_HII_EXPRESSION_RULE              6
+
+#define EFI_HII_VARSTORE_BUFFER              0
+#define EFI_HII_VARSTORE_NAME_VALUE          1
+#define EFI_HII_VARSTORE_EFI_VARIABLE        2
+
+#define FORM_INCONSISTENT_VALIDATION         0
+#define FORM_NO_SUBMIT_VALIDATION            1
+
+typedef struct {
+  UINT8               Type;
+  EFI_IFR_TYPE_VALUE  Value;
+} EFI_HII_VALUE;
+
+#define NAME_VALUE_NODE_SIGNATURE  EFI_SIGNATURE_32 ('N', 'V', 'S', 'T')
+
+typedef struct {
+  UINTN            Signature;
+  LIST_ENTRY       Link;
+  CHAR16           *Name;
+  CHAR16           *Value;
+  CHAR16           *EditValue;
+} NAME_VALUE_NODE;
+
+#define NAME_VALUE_NODE_FROM_LINK(a)  CR (a, NAME_VALUE_NODE, Link, NAME_VALUE_NODE_SIGNATURE)
+
+#define FORMSET_STORAGE_SIGNATURE  EFI_SIGNATURE_32 ('F', 'S', 'T', 'G')
+
+typedef struct {
+  UINTN            Signature;
+  LIST_ENTRY       Link;
+
+  UINT8            Type;           // Storage type
+
+  UINT16           VarStoreId;
+  EFI_GUID         Guid;
+
+  CHAR16           *Name;          // For EFI_IFR_VARSTORE
+  UINT16           Size;
+  UINT8            *Buffer;
+  UINT8            *EditBuffer;    // Edit copy for Buffer Storage
+
+  LIST_ENTRY       NameValueListHead; // List of NAME_VALUE_NODE
+
+  UINT32           Attributes;     // For EFI_IFR_VARSTORE_EFI: EFI Variable attribute
+
+  CHAR16           *ConfigHdr;     // <ConfigHdr>
+  CHAR16           *ConfigRequest; // <ConfigRequest> = <ConfigHdr> + <RequestElement>
+  UINTN            ElementCount;   // Number of <RequestElement> in the <ConfigRequest>
+  UINTN            SpareStrLen;    // Spare length of ConfigRequest string buffer
+} FORMSET_STORAGE;
+
+#define FORMSET_STORAGE_FROM_LINK(a)  CR (a, FORMSET_STORAGE, Link, FORMSET_STORAGE_SIGNATURE)
+
+#define EXPRESSION_OPCODE_SIGNATURE  EFI_SIGNATURE_32 ('E', 'X', 'O', 'P')
+
+typedef struct {
+  UINTN             Signature;
+  LIST_ENTRY        Link;
+
+  UINT8             Operand;
+
+  UINT8             Format;      // For EFI_IFR_TO_STRING, EFI_IFR_FIND
+  UINT8             Flags;       // For EFI_IFR_SPAN
+  UINT8             RuleId;      // For EFI_IFR_RULE_REF
+
+  EFI_HII_VALUE     Value;       // For EFI_IFR_EQ_ID_VAL, EFI_IFR_UINT64, EFI_IFR_UINT32, EFI_IFR_UINT16, EFI_IFR_UINT8, EFI_IFR_STRING_REF1
+
+  EFI_QUESTION_ID   QuestionId;  // For EFI_IFR_EQ_ID_ID, EFI_IFR_EQ_ID_LIST, EFI_IFR_QUESTION_REF1
+  EFI_QUESTION_ID   QuestionId2;
+
+  UINT16            ListLength;  // For EFI_IFR_EQ_ID_LIST
+  UINT16            *ValueList;
+
+  EFI_STRING_ID     DevicePath;  // For EFI_IFR_QUESTION_REF3_2, EFI_IFR_QUESTION_REF3_3
+  EFI_GUID          Guid;
+} EXPRESSION_OPCODE;
+
+#define EXPRESSION_OPCODE_FROM_LINK(a)  CR (a, EXPRESSION_OPCODE, Link, EXPRESSION_OPCODE_SIGNATURE)
+
+#define FORM_EXPRESSION_SIGNATURE  EFI_SIGNATURE_32 ('F', 'E', 'X', 'P')
+
+typedef struct {
+  UINTN             Signature;
+  LIST_ENTRY        Link;
+
+  UINT8             Type;            // Type for this expression
+
+  UINT8             RuleId;          // For EFI_IFR_RULE only
+  EFI_STRING_ID     Error;           // For EFI_IFR_NO_SUBMIT_IF, EFI_IFR_INCONSISTENT_IF only
+
+  EFI_HII_VALUE     Result;          // Expression evaluation result
+
+  LIST_ENTRY        OpCodeListHead;  // OpCodes consist of this expression (EXPRESSION_OPCODE)
+} FORM_EXPRESSION;
+
+#define FORM_EXPRESSION_FROM_LINK(a)  CR (a, FORM_EXPRESSION, Link, FORM_EXPRESSION_SIGNATURE)
+
+#define QUESTION_DEFAULT_SIGNATURE  EFI_SIGNATURE_32 ('Q', 'D', 'F', 'T')
+
+typedef struct {
+  UINTN               Signature;
+  LIST_ENTRY          Link;
+
+  UINT16              DefaultId;
+  EFI_HII_VALUE       Value;              // Default value
+
+  FORM_EXPRESSION     *ValueExpression;   // Not-NULL indicates default value is provided by EFI_IFR_VALUE
+} QUESTION_DEFAULT;
+
+#define QUESTION_DEFAULT_FROM_LINK(a)  CR (a, QUESTION_DEFAULT, Link, QUESTION_DEFAULT_SIGNATURE)
+
+#define QUESTION_OPTION_SIGNATURE  EFI_SIGNATURE_32 ('Q', 'O', 'P', 'T')
+
+typedef struct {
+  UINTN               Signature;
+  LIST_ENTRY          Link;
+
+  EFI_STRING_ID       Text;
+  UINT8               Flags;
+  EFI_HII_VALUE       Value;
+  EFI_IMAGE_ID        ImageId;
+
+  FORM_EXPRESSION     *SuppressExpression; // Non-NULL indicates nested inside of SuppressIf
+} QUESTION_OPTION;
+
+#define QUESTION_OPTION_FROM_LINK(a)  CR (a, QUESTION_OPTION, Link, QUESTION_OPTION_SIGNATURE)
+
+#define FORM_BROWSER_STATEMENT_SIGNATURE  EFI_SIGNATURE_32 ('F', 'S', 'T', 'A')
+typedef struct {
+  UINTN                 Signature;
+  LIST_ENTRY            Link;
+
+  UINT8                 Operand;          // The operand (first byte) of this Statement or Question
+
+  //
+  // Statement Header
+  //
+  EFI_STRING_ID         Prompt;
+  EFI_STRING_ID         Help;
+  EFI_STRING_ID         TextTwo;          // For EFI_IFR_TEXT
+
+  //
+  // Question Header
+  //
+  EFI_QUESTION_ID       QuestionId;       // The value of zero is reserved
+  EFI_VARSTORE_ID       VarStoreId;       // A value of zero indicates no variable storage
+  FORMSET_STORAGE       *Storage;
+  union {
+    EFI_STRING_ID       VarName;
+    UINT16              VarOffset;
+  }  VarStoreInfo;
+  UINT16                StorageWidth;
+  UINT8                 QuestionFlags;
+  CHAR16                *VariableName;    // Name/Value or EFI Variable name
+  CHAR16                *BlockName;       // Buffer storage block name: "OFFSET=...WIDTH=..."
+
+  EFI_HII_VALUE         HiiValue;         // Edit copy for checkbox, numberic, oneof
+  UINT8                 *BufferValue;     // Edit copy for string, password, orderedlist
+
+  //
+  // OpCode specific members
+  //
+  UINT8                 Flags;            // for EFI_IFR_CHECKBOX, EFI_IFR_DATE, EFI_IFR_NUMERIC, EFI_IFR_ONE_OF,
+                                          // EFI_IFR_ORDERED_LIST, EFI_IFR_STRING,EFI_IFR_SUBTITLE,EFI_IFR_TIME, EFI_IFR_BANNER
+  UINT8                 MaxContainers;    // for EFI_IFR_ORDERED_LIST
+
+  UINT16                BannerLineNumber; // for EFI_IFR_BANNER, 1-based line number
+  EFI_STRING_ID         QuestionConfig;   // for EFI_IFR_ACTION, if 0 then no configuration string will be processed
+
+  UINT64                Minimum;          // for EFI_IFR_ONE_OF/EFI_IFR_NUMERIC, it's Min/Max value
+  UINT64                Maximum;          // for EFI_IFR_STRING/EFI_IFR_PASSWORD, it's Min/Max length
+  UINT64                Step;
+
+  EFI_DEFAULT_ID        DefaultId;        // for EFI_IFR_RESET_BUTTON
+  EFI_FORM_ID           RefFormId;        // for EFI_IFR_REF
+  EFI_QUESTION_ID       RefQuestionId;    // for EFI_IFR_REF2
+  EFI_GUID              RefFormSetId;     // for EFI_IFR_REF3
+  EFI_STRING_ID         RefDevicePath;    // for EFI_IFR_REF4
+
+  //
+  // Get from IFR parsing
+  //
+  FORM_EXPRESSION       *ValueExpression;    // nested EFI_IFR_VALUE, provide Question value and indicate Question is ReadOnly
+  LIST_ENTRY            DefaultListHead;     // nested EFI_IFR_DEFAULT list (QUESTION_DEFAULT), provide default values
+  LIST_ENTRY            OptionListHead;      // nested EFI_IFR_ONE_OF_OPTION list (QUESTION_OPTION)
+
+  EFI_IMAGE_ID          ImageId;             // nested EFI_IFR_IMAGE
+  UINT8                 RefreshInterval;     // nested EFI_IFR_REFRESH, refresh interval(in seconds) for Question value, 0 means no refresh
+  BOOLEAN               InSubtitle;          // nesting inside of EFI_IFR_SUBTITLE
+
+  LIST_ENTRY            InconsistentListHead;// nested inconsistent expression list (FORM_EXPRESSION)
+  LIST_ENTRY            NoSubmitListHead;    // nested nosubmit expression list (FORM_EXPRESSION)
+  FORM_EXPRESSION       *GrayOutExpression;  // nesting inside of GrayOutIf
+  FORM_EXPRESSION       *SuppressExpression; // nesting inside of SuppressIf
+
+} FORM_BROWSER_STATEMENT;
+
+#define FORM_BROWSER_STATEMENT_FROM_LINK(a)  CR (a, FORM_BROWSER_STATEMENT, Link, FORM_BROWSER_STATEMENT_SIGNATURE)
+
+#define FORM_BROWSER_FORM_SIGNATURE  EFI_SIGNATURE_32 ('F', 'F', 'R', 'M')
+
+typedef struct {
+  UINTN             Signature;
+  LIST_ENTRY        Link;
+
+  UINT16            FormId;
+  EFI_STRING_ID     FormTitle;
+
+  EFI_IMAGE_ID      ImageId;
+
+  LIST_ENTRY        ExpressionListHead;   // List of Expressions (FORM_EXPRESSION)
+  LIST_ENTRY        StatementListHead;    // List of Statements and Questions (FORM_BROWSER_STATEMENT)
+} FORM_BROWSER_FORM;
+
+#define FORM_BROWSER_FORM_FROM_LINK(a)  CR (a, FORM_BROWSER_FORM, Link, FORM_BROWSER_FORM_SIGNATURE)
+
+#define FORMSET_DEFAULTSTORE_SIGNATURE  EFI_SIGNATURE_32 ('F', 'D', 'F', 'S')
+
+typedef struct {
+  UINTN            Signature;
+  LIST_ENTRY       Link;
+
+  UINT16           DefaultId;
+  EFI_STRING_ID    DefaultName;
+} FORMSET_DEFAULTSTORE;
+
+#define FORMSET_DEFAULTSTORE_FROM_LINK(a)  CR (a, FORMSET_DEFAULTSTORE, Link, FORMSET_DEFAULTSTORE_SIGNATURE)
+
+typedef struct {
+  EFI_HII_HANDLE                  HiiHandle;
+  EFI_HANDLE                      DriverHandle;
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;
+  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
+
+  UINTN                           IfrBinaryLength;
+  UINT8                           *IfrBinaryData;
+
+  EFI_GUID                        Guid;
+  EFI_STRING_ID                   FormSetTitle;
+  EFI_STRING_ID                   Help;
+  UINT16                          Class;
+  UINT16                          SubClass;
+  EFI_IMAGE_ID                    ImageId;
+
+  FORM_BROWSER_STATEMENT          *StatementBuffer;     // Buffer for all Statements and Questions
+  EXPRESSION_OPCODE               *ExpressionBuffer;    // Buffer for all Expression OpCode
+
+  LIST_ENTRY                      StorageListHead;      // Storage list (FORMSET_STORAGE)
+  LIST_ENTRY                      DefaultStoreListHead; // DefaultStore list (FORMSET_DEFAULTSTORE)
+  LIST_ENTRY                      FormListHead;         // Form list (FORM_BROWSER_FORM)
+} FORM_BROWSER_FORMSET;
+
+
+extern EFI_HII_DATABASE_PROTOCOL         *mHiiDatabase;
+extern EFI_HII_STRING_PROTOCOL           *mHiiString;
+extern EFI_HII_CONFIG_ROUTING_PROTOCOL   *mHiiConfigRouting;
+
+extern BANNER_DATA           *BannerData;
+extern EFI_HII_HANDLE        FrontPageHandle;
+extern UINTN                 gClassOfVfr;
+extern UINTN                 gFunctionKeySetting;
+extern BOOLEAN               gResetRequired;
+extern BOOLEAN               gNvUpdateRequired;
+extern EFI_HII_HANDLE        gHiiHandle;
+extern BOOLEAN               gFirstIn;
+extern UINT16                gDirection;
+extern EFI_SCREEN_DESCRIPTOR gScreenDimensions;
+extern BOOLEAN               gUpArrow;
+extern BOOLEAN               gDownArrow;
+
+//
+// Browser Global Strings
+//
+extern CHAR16            *gFunctionOneString;
+extern CHAR16            *gFunctionTwoString;
+extern CHAR16            *gFunctionNineString;
+extern CHAR16            *gFunctionTenString;
+extern CHAR16            *gEnterString;
+extern CHAR16            *gEnterCommitString;
+extern CHAR16            *gEscapeString;
+extern CHAR16            *gSaveFailed;
+extern CHAR16            *gMoveHighlight;
+extern CHAR16            *gMakeSelection;
+extern CHAR16            *gDecNumericInput;
+extern CHAR16            *gHexNumericInput;
+extern CHAR16            *gToggleCheckBox;
+extern CHAR16            *gPromptForData;
+extern CHAR16            *gPromptForPassword;
+extern CHAR16            *gPromptForNewPassword;
+extern CHAR16            *gConfirmPassword;
+extern CHAR16            *gConfirmError;
+extern CHAR16            *gPassowordInvalid;
+extern CHAR16            *gPressEnter;
+extern CHAR16            *gEmptyString;
+extern CHAR16            *gAreYouSure;
+extern CHAR16            *gYesResponse;
+extern CHAR16            *gNoResponse;
+extern CHAR16            *gMiniString;
+extern CHAR16            *gPlusString;
+extern CHAR16            *gMinusString;
+extern CHAR16            *gAdjustNumber;
+
+extern CHAR16            gPromptBlockWidth;
+extern CHAR16            gOptionBlockWidth;
+extern CHAR16            gHelpBlockWidth;
+
+extern EFI_GUID          gZeroGuid;
+extern EFI_GUID          gTianoHiiIfrGuid;
+
+//
+// Global Procedure Defines
+//
+VOID
+InitializeBrowserStrings (
+  VOID
+  )
+;
+
+UINTN
+_Print (
+  IN CHAR16                         *fmt,
+  ...
+  )
+;
+
+UINTN
+PrintString (
+  CHAR16       *String
+  )
+;
+
+UINTN
+PrintChar (
+  CHAR16       Character
+  )
+;
+
+UINTN
+PrintAt (
+  IN UINTN     Column,
+  IN UINTN     Row,
+  IN CHAR16    *fmt,
+  ...
+  )
+;
+
+UINTN
+PrintStringAt (
+  IN UINTN     Column,
+  IN UINTN     Row,
+  CHAR16       *String
+  )
+;
+
+UINTN
+PrintCharAt (
+  IN UINTN     Column,
+  IN UINTN     Row,
+  CHAR16       Character
+  )
+;
+
+EFI_STATUS
+ParseOpCodes (
+  IN FORM_BROWSER_FORMSET              *FormSet
+  )
+;
+
+VOID
+DestroyFormSet (
+  IN OUT FORM_BROWSER_FORMSET  *FormSet
+  )
+;
+
+VOID
+DisplayPageFrame (
+  VOID
+  )
+;
+
+EFI_STRING_ID
+NewString (
+  IN  CHAR16                   *String,
+  IN  EFI_HII_HANDLE           HiiHandle
+  )
+;
+
+EFI_STATUS
+DeleteString (
+  IN  EFI_STRING_ID            StringId,
+  IN  EFI_HII_HANDLE           HiiHandle
+  )
+;
+CHAR16 *
+GetToken (
+  IN  EFI_STRING_ID                Token,
+  IN  EFI_HII_HANDLE               HiiHandle
+  )
+;
+
+VOID
+CreateSharedPopUp (
+  IN  UINTN                       RequestedWidth,
+  IN  UINTN                       NumberOfLines,
+  IN  CHAR16                      **ArrayOfStrings
+  )
+;
+
+EFI_STATUS
+CreateDialog (
+  IN  UINTN                       NumberOfLines,
+  IN  BOOLEAN                     HotKey,
+  IN  UINTN                       MaximumStringSize,
+  OUT CHAR16                      *StringBuffer,
+  OUT EFI_INPUT_KEY               *KeyValue,
+  IN  CHAR16                      *String,
+  ...
+  )
+;
+
+EFI_STATUS
+GetQuestionValue (
+  IN FORM_BROWSER_FORMSET             *FormSet,
+  IN FORM_BROWSER_FORM                *Form,
+  IN OUT FORM_BROWSER_STATEMENT       *Question,
+  IN BOOLEAN                          Cached
+  )
+;
+
+EFI_STATUS
+SetQuestionValue (
+  IN FORM_BROWSER_FORMSET             *FormSet,
+  IN FORM_BROWSER_FORM                *Form,
+  IN OUT FORM_BROWSER_STATEMENT       *Question,
+  IN BOOLEAN                          Cached
+  )
+;
+
+EFI_STATUS
+ValidateQuestion (
+  IN  FORM_BROWSER_FORMSET            *FormSet,
+  IN  FORM_BROWSER_FORM               *Form,
+  IN  FORM_BROWSER_STATEMENT          *Question,
+  IN  UINTN                           Type
+  )
+;
+
+EFI_STATUS
+SubmitForm (
+  IN FORM_BROWSER_FORMSET             *FormSet,
+  IN FORM_BROWSER_FORM                *Form
+  )
+;
+
+EFI_STATUS
+GetQuestionDefault (
+  IN FORM_BROWSER_FORMSET             *FormSet,
+  IN FORM_BROWSER_FORM                *Form,
+  IN FORM_BROWSER_STATEMENT           *Question,
+  IN UINT16                           DefaultId
+  )
+;
+
+EFI_STATUS
+InitializeCurrentSetting (
+  IN OUT FORM_BROWSER_FORMSET             *FormSet
+  )
+;
+
+EFI_STATUS
+InitializeFormSet (
+  IN  EFI_HII_HANDLE                   Handle,
+  IN OUT EFI_GUID                      *FormSetGuid,
+  OUT FORM_BROWSER_FORMSET             *FormSet
+  )
+;
+
+EFI_STATUS
+ExtractFormDefault (
+  IN FORM_BROWSER_FORMSET             *FormSet,
+  IN  FORM_BROWSER_FORM               *Form,
+  IN UINT16                           DefaultId
+  )
+;
+
+EFI_STATUS
+LoadFormConfig (
+  IN FORM_BROWSER_FORMSET             *FormSet,
+  IN FORM_BROWSER_FORM                *Form
+  )
+;
+
+EFI_STATUS
+StorageToConfigResp (
+  IN FORMSET_STORAGE         *Storage,
+  IN CHAR16                  **ConfigResp
+  )
+;
+
+EFI_STATUS
+ConfigRespToStorage (
+  IN FORMSET_STORAGE         *Storage,
+  IN CHAR16                  *ConfigResp
+  )
+;
+
+EFI_STATUS
+LoadStorage (
+  IN FORM_BROWSER_FORMSET    *FormSet,
+  IN FORMSET_STORAGE         *Storage
+  )
+;
+
+EFI_STATUS
+GetIfrBinaryData (
+  IN  EFI_HII_HANDLE   Handle,
+  IN OUT EFI_GUID      *FormSetGuid,
+  OUT UINTN            *BinaryLength,
+  OUT UINT8            **BinaryData
+  )
+;
+
+EFI_STATUS
+EFIAPI
+SendForm (
+  IN  CONST EFI_FORM_BROWSER2_PROTOCOL *This,
+  IN  EFI_HII_HANDLE                   *Handles,
+  IN  UINTN                            HandleCount,
+  IN  EFI_GUID                         *FormSetGuid, OPTIONAL
+  IN  UINT16                           FormId, OPTIONAL
+  IN  CONST EFI_SCREEN_DESCRIPTOR      *ScreenDimensions, OPTIONAL
+  OUT EFI_BROWSER_ACTION_REQUEST       *ActionRequest  OPTIONAL
+  )
+;
+
+EFI_STATUS
+EFIAPI
+BrowserCallback (
+  IN CONST EFI_FORM_BROWSER2_PROTOCOL  *This,
+  IN OUT UINTN                         *ResultsDataSize,
+  IN OUT EFI_STRING                    ResultsData,
+  IN BOOLEAN                           RetrieveData,
+  IN CONST EFI_GUID                    *VariableGuid, OPTIONAL
+  IN CONST CHAR16                      *VariableName  OPTIONAL
+  )
+;
+
+#endif
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowser.msa b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowser.msa
new file mode 100644 (file)
index 0000000..5777499
--- /dev/null
@@ -0,0 +1,84 @@
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+  <MsaHeader>\r
+    <ModuleName>SetupBrowser</ModuleName>\r
+    <ModuleType>DXE_DRIVER</ModuleType>\r
+    <GuidValue>EBf342FE-B1D3-4EF8-957C-8048606FF671</GuidValue>\r
+    <Version>1.0</Version>\r
+    <Abstract>Component name for module SetupBrowser</Abstract>\r
+    <Description>FIX ME!</Description>\r
+    <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>\r
+    <License>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.</License>\r
+    <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION   0x00000052</Specification>\r
+  </MsaHeader>\r
+  <ModuleDefinitions>\r
+    <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+    <BinaryModule>false</BinaryModule>\r
+    <OutputFileBasename>SetupBrowser</OutputFileBasename>\r
+  </ModuleDefinitions>\r
+  <LibraryClassDefinitions>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>PrintLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DebugLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseMemoryLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiRuntimeServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiDriverEntryPoint</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiBootServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>MemoryAllocationLib</Keyword>\r
+    </LibraryClass>\r
+  </LibraryClassDefinitions>\r
+  <SourceFiles>\r
+    <Filename>R8Lib.h</Filename>\r
+    <Filename>Print.h</Filename>\r
+    <Filename>Setup.c</Filename>\r
+    <Filename>Setup.h</Filename>\r
+    <Filename>Ui.h</Filename>\r
+    <Filename>Print.c</Filename>\r
+    <Filename>SetupBrowser.dxs</Filename>\r
+    <Filename>R8Lib.c</Filename>\r
+    <Filename>ProcessOptions.c</Filename>\r
+    <Filename>InputHandler.c</Filename>\r
+    <Filename>Ui.c</Filename>\r
+    <Filename>IfrParse.c</Filename>\r
+    <Filename>Expression.c</Filename>\r
+    <Filename>Colors.h</Filename>\r
+    <Filename>Presentation.c</Filename>\r
+    <Filename>SetupBrowserStr.uni</Filename>\r
+  </SourceFiles>\r
+  <PackageDependencies>\r
+    <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+    <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+  </PackageDependencies>\r
+  <Protocols>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiPrintProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+  </Protocols>\r
+  <Externs>\r
+    <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+    <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+    <Extern>\r
+      <ModuleEntryPoint>InitializeSetup</ModuleEntryPoint>\r
+    </Extern>\r
+  </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
new file mode 100644 (file)
index 0000000..807076e
--- /dev/null
@@ -0,0 +1,82 @@
+#/** @file\r
+# Component name for module SetupBrowser\r
+#\r
+# FIX ME!\r
+# Copyright (c) 2007, Intel Corporation. All rights reserved.\r
+#\r
+#  All rights reserved. This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  \r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SetupBrowser\r
+  FILE_GUID                      = EBf342FE-B1D3-4EF8-957C-8048606FF671\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x0002000A\r
+\r
+  ENTRY_POINT                    = InitializeSetup\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+  SetupBrowserStr.uni\r
+  Setup.c\r
+  Setup.h\r
+  IfrParse.c\r
+  Expression.c\r
+  InputHandler.c\r
+  Print.c\r
+  Print.h\r
+  Presentation.c\r
+  ProcessOptions.c\r
+  Ui.c\r
+  Ui.h\r
+  R8Lib.c\r
+  R8Lib.h\r
+  Colors.h\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+  MemoryAllocationLib\r
+  BaseLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+  UefiRuntimeServicesTableLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  PrintLib\r
+  GraphicsLib\r
+  IfrSupportLib\r
+  HiiLib\r
+\r
+[Protocols]\r
+  gEfiPrintProtocolGuid                         # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiHiiConfigAccessProtocolGuid\r
+  gEfiHiiStringProtocolGuid\r
+  gEfiFormBrowser2ProtocolGuid\r
+  gEfiHiiConfigRoutingProtocolGuid\r
+  gEfiHiiDatabaseProtocolGuid\r
+  gEfiUnicodeCollation2ProtocolGuid\r
+\r
+[Depex]\r
+  gEfiHiiDatabaseProtocolGuid AND gEfiHiiConfigRoutingProtocolGuid\r
+\r
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni
new file mode 100644 (file)
index 0000000..5b5e282
Binary files /dev/null and b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni differ
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
new file mode 100644 (file)
index 0000000..34ec526
--- /dev/null
@@ -0,0 +1,2830 @@
+/** @file
+
+Copyright (c) 2004 - 2007, Intel Corporation
+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.
+
+Module Name:
+
+  Ui.c
+
+Abstract:
+
+  Implementation for UI.
+
+Revision History
+
+
+**/
+
+#include "Ui.h"
+#include "Setup.h"
+
+LIST_ENTRY          Menu;
+LIST_ENTRY          gMenuList;
+MENU_REFRESH_ENTRY  *gMenuRefreshHead;
+
+//
+// Search table for UiDisplayMenu()
+//
+SCAN_CODE_TO_SCREEN_OPERATION     gScanCodeToOperation[] = {
+  SCAN_UP,
+  UiUp,
+  SCAN_DOWN,
+  UiDown,
+  SCAN_PAGE_UP,
+  UiPageUp,
+  SCAN_PAGE_DOWN,
+  UiPageDown,
+  SCAN_ESC,
+  UiReset,
+  SCAN_F2,
+  UiPrevious,
+  SCAN_LEFT,
+  UiLeft,
+  SCAN_RIGHT,
+  UiRight,
+  SCAN_F9,
+  UiDefault,
+  SCAN_F10,
+  UiSave
+};
+
+SCREEN_OPERATION_T0_CONTROL_FLAG  gScreenOperationToControlFlag[] = {
+  UiNoOperation,
+  CfUiNoOperation,
+  UiDefault,
+  CfUiDefault,
+  UiSelect,
+  CfUiSelect,
+  UiUp,
+  CfUiUp,
+  UiDown,
+  CfUiDown,
+  UiLeft,
+  CfUiLeft,
+  UiRight,
+  CfUiRight,
+  UiReset,
+  CfUiReset,
+  UiSave,
+  CfUiSave,
+  UiPrevious,
+  CfUiPrevious,
+  UiPageUp,
+  CfUiPageUp,
+  UiPageDown,
+  CfUiPageDown
+};
+
+
+/**
+  Set Buffer to Value for Size bytes.
+
+  @param  Buffer                 Memory to set.
+  @param  Size                   Number of bytes to set
+  @param  Value                  Value of the set operation.
+
+  @return None
+
+**/
+VOID
+SetUnicodeMem (
+  IN VOID   *Buffer,
+  IN UINTN  Size,
+  IN CHAR16 Value
+  )
+{
+  CHAR16  *Ptr;
+
+  Ptr = Buffer;
+  while (Size--) {
+    *(Ptr++) = Value;
+  }
+}
+
+
+/**
+  Initialize Menu option list.
+
+  None.
+
+  @return None.
+
+**/
+VOID
+UiInitMenu (
+  VOID
+  )
+{
+  InitializeListHead (&Menu);
+}
+
+
+/**
+  Initialize Menu option list.
+
+  None.
+
+  @return None.
+
+**/
+VOID
+UiInitMenuList (
+  VOID
+  )
+{
+  InitializeListHead (&gMenuList);
+}
+
+
+/**
+  Remove a Menu in list, and return FormId/QuestionId for previous Menu.
+
+  @param  Selection              Menu selection.
+
+  @return None.
+
+**/
+VOID
+UiRemoveMenuListEntry (
+  IN OUT UI_MENU_SELECTION  *Selection
+  )
+{
+  UI_MENU_LIST  *UiMenuList;
+
+  if (!IsListEmpty (&gMenuList)) {
+    UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
+
+    Selection->FormId = UiMenuList->FormId;
+    Selection->QuestionId = UiMenuList->QuestionId;
+    RemoveEntryList (&UiMenuList->MenuLink);
+    gBS->FreePool (UiMenuList);
+  }
+}
+
+
+/**
+  Free Menu option linked list.
+
+  None.
+
+  @return None.
+
+**/
+VOID
+UiFreeMenuList (
+  VOID
+  )
+{
+  UI_MENU_LIST  *UiMenuList;
+
+  while (!IsListEmpty (&gMenuList)) {
+    UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
+    RemoveEntryList (&UiMenuList->MenuLink);
+    gBS->FreePool (UiMenuList);
+  }
+}
+
+
+/**
+  Add one menu entry to the linked lst
+
+  @param  Selection              Menu selection.
+
+  @return None.
+
+**/
+VOID
+UiAddMenuListEntry (
+  IN UI_MENU_SELECTION            *Selection
+  )
+{
+  UI_MENU_LIST  *UiMenuList;
+
+  UiMenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));
+  ASSERT (UiMenuList != NULL);
+
+  UiMenuList->Signature = UI_MENU_LIST_SIGNATURE;
+  UiMenuList->FormId = Selection->FormId;
+  UiMenuList->QuestionId = Selection->QuestionId;
+
+  InsertHeadList (&gMenuList, &UiMenuList->MenuLink);
+}
+
+
+/**
+  Free Menu option linked list.
+
+  None.
+
+  @return None.
+
+**/
+VOID
+UiFreeMenu (
+  VOID
+  )
+{
+  UI_MENU_OPTION  *MenuOption;
+
+  while (!IsListEmpty (&Menu)) {
+    MenuOption = MENU_OPTION_FROM_LINK (Menu.ForwardLink);
+    RemoveEntryList (&MenuOption->Link);
+
+    //
+    // We allocated space for this description when we did a GetToken, free it here
+    //
+    if (MenuOption->Skip != 0) {
+      //
+      // For date/time, MenuOption->Description is shared by three Menu Options
+      // Data format :      [01/02/2004]      [11:22:33]
+      // Line number :        0  0    1         0  0  1
+      //
+      gBS->FreePool (MenuOption->Description);
+    }
+    gBS->FreePool (MenuOption);
+  }
+}
+
+
+/**
+  Free Menu option linked list.
+
+  None.
+
+  @return None.
+
+**/
+VOID
+UiFreeRefreshList (
+  VOID
+  )
+{
+  MENU_REFRESH_ENTRY  *OldMenuRefreshEntry;
+
+  while (gMenuRefreshHead != NULL) {
+    OldMenuRefreshEntry = gMenuRefreshHead->Next;
+    gBS->FreePool (gMenuRefreshHead);
+    gMenuRefreshHead = OldMenuRefreshEntry;
+  }
+
+  gMenuRefreshHead = NULL;
+}
+
+
+
+/**
+  Refresh screen.
+
+  None.
+
+  @return None.
+
+**/
+VOID
+RefreshForm (
+  VOID
+  )
+{
+  CHAR16                  *OptionString;
+  MENU_REFRESH_ENTRY      *MenuRefreshEntry;
+  UINTN                   Index;
+  UINTN                   Loop;
+  EFI_STATUS              Status;
+  UI_MENU_SELECTION       *Selection;
+  FORM_BROWSER_STATEMENT  *Question;
+
+  OptionString = NULL;
+
+  if (gMenuRefreshHead != NULL) {
+
+    MenuRefreshEntry = gMenuRefreshHead;
+
+    do {
+      gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);
+
+      Selection = MenuRefreshEntry->Selection;
+      Question = MenuRefreshEntry->MenuOption->ThisTag;
+
+      //
+      // Don't update Question being edited
+      //
+      if (Question != MenuRefreshEntry->Selection->Statement) {
+
+        Status = GetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE);
+        if (EFI_ERROR (Status)) {
+          return;
+        }
+
+        ProcessOptions (Selection, MenuRefreshEntry->MenuOption, FALSE, &OptionString);
+
+        if (OptionString != NULL) {
+          //
+          // If leading spaces on OptionString - remove the spaces
+          //
+          for (Index = 0; OptionString[Index] == L' '; Index++)
+            ;
+
+          for (Loop = 0; OptionString[Index] != CHAR_NULL; Index++) {
+            OptionString[Loop] = OptionString[Index];
+            Loop++;
+          }
+
+          OptionString[Loop] = CHAR_NULL;
+
+          PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString);
+          gBS->FreePool (OptionString);
+        }
+      }
+
+      MenuRefreshEntry = MenuRefreshEntry->Next;
+
+    } while (MenuRefreshEntry != NULL);
+  }
+}
+
+
+/**
+  Wait 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.
+  @param  RefreshInterval        Menu refresh interval (in seconds).
+
+  @retval EFI_SUCCESS            Event fired before Timeout expired.
+  @retval EFI_TIME_OUT           Timout expired before Event fired.
+
+**/
+EFI_STATUS
+UiWaitForSingleEvent (
+  IN EFI_EVENT                Event,
+  IN UINT64                   Timeout, OPTIONAL
+  IN UINT8                    RefreshInterval OPTIONAL
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       Index;
+  EFI_EVENT   TimerEvent;
+  EFI_EVENT   WaitList[2];
+
+  if (Timeout) {
+    //
+    // 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 {
+    //
+    // Update screen every second
+    //
+    if (RefreshInterval == 0) {
+      Timeout = ONE_SECOND;
+    } else {
+      Timeout = RefreshInterval * ONE_SECOND;
+    }
+
+    do {
+      Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
+
+      //
+      // 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);
+
+      //
+      // If the timer expired, update anything that needs a refresh and keep waiting
+      //
+      if (!EFI_ERROR (Status) && Index == 1) {
+        Status = EFI_TIMEOUT;
+        if (RefreshInterval != 0) {
+          RefreshForm ();
+        }
+      }
+
+      gBS->CloseEvent (TimerEvent);
+    } while (Status == EFI_TIMEOUT);
+  }
+
+  return Status;
+}
+
+
+/**
+  Add one menu option by specified description and context.
+
+  @param  String                 String description for this option.
+  @param  Handle                 Hii handle for the package list.
+  @param  Statement              Statement of this Menu Option.
+  @param  NumberOfLines          Display lines for this Menu Option.
+  @param  MenuItemCount          The index for this Option in the Menu.
+
+  @return None.
+
+**/
+VOID
+UiAddMenuOption (
+  IN CHAR16                  *String,
+  IN EFI_HII_HANDLE          Handle,
+  IN FORM_BROWSER_STATEMENT  *Statement,
+  IN UINT16                  NumberOfLines,
+  IN UINT16                  MenuItemCount
+  )
+{
+  UI_MENU_OPTION  *MenuOption;
+  UINTN           Index;
+  UINTN           Count;
+
+  Count = 1;
+
+  if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
+    //
+    // Add three MenuOptions for Date/Time
+    // Data format :      [01/02/2004]      [11:22:33]
+    // Line number :        0  0    1         0  0  1
+    //
+    NumberOfLines = 0;
+    Count = 3;
+
+    if (Statement->Storage == NULL) {
+      //
+      // For RTC type of date/time, set default refresh interval to be 1 second
+      //
+      if (Statement->RefreshInterval == 0) {
+        Statement->RefreshInterval = 1;
+      }
+    }
+  }
+
+  for (Index = 0; Index < Count; Index++) {
+    MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));
+    ASSERT (MenuOption);
+
+    MenuOption->Signature   = UI_MENU_OPTION_SIGNATURE;
+    MenuOption->Description = String;
+    MenuOption->Handle      = Handle;
+    MenuOption->ThisTag     = Statement;
+    MenuOption->EntryNumber = MenuItemCount;
+
+    if (Index == 2) {
+      //
+      // Override LineNumber for the MenuOption in Date/Time sequence
+      //
+      MenuOption->Skip = 1;
+    } else {
+      MenuOption->Skip = NumberOfLines;
+    }
+    MenuOption->Sequence = Index;
+
+    if (Statement->GrayOutExpression != NULL) {
+      MenuOption->GrayOut = Statement->GrayOutExpression->Result.Value.b;
+    }
+
+    if ((Statement->ValueExpression != NULL) ||
+        (Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY)) {
+      MenuOption->ReadOnly = TRUE;
+    }
+
+    InsertTailList (&Menu, &MenuOption->Link);
+  }
+}
+
+
+/**
+  Routine used to abstract a generic dialog interface and return the selected key or string
+
+  @param  NumberOfLines          The number of lines for the dialog box
+  @param  HotKey                 Defines whether a single character is parsed
+                                 (TRUE) and returned in KeyValue or a string is
+                                 returned in StringBuffer.  Two special characters
+                                 are considered when entering a string, a SCAN_ESC
+                                 and an CHAR_CARRIAGE_RETURN.  SCAN_ESC terminates
+                                 string input and returns
+  @param  MaximumStringSize      The maximum size in bytes of a typed in string
+                                 (each character is a CHAR16) and the minimum
+                                 string returned is two bytes
+  @param  StringBuffer           The passed in pointer to the buffer which will
+                                 hold the typed in string if HotKey is FALSE
+  @param  KeyValue               The EFI_KEY value returned if HotKey is TRUE..
+  @param  String                 Pointer to the first string in the list
+  @param  ...                    A series of (quantity == NumberOfLines) text
+                                 strings which will be used to construct the dialog
+                                 box
+
+  @retval EFI_SUCCESS            Displayed dialog and received user interaction
+  @retval EFI_INVALID_PARAMETER  One of the parameters was invalid (e.g.
+                                 (StringBuffer == NULL) && (HotKey == FALSE))
+  @retval EFI_DEVICE_ERROR       User typed in an ESC character to exit the routine
+
+**/
+EFI_STATUS
+CreateDialog (
+  IN  UINTN                       NumberOfLines,
+  IN  BOOLEAN                     HotKey,
+  IN  UINTN                       MaximumStringSize,
+  OUT CHAR16                      *StringBuffer,
+  OUT EFI_INPUT_KEY               *KeyValue,
+  IN  CHAR16                      *String,
+  ...
+  )
+{
+  VA_LIST       Marker;
+  UINTN         Count;
+  EFI_INPUT_KEY Key;
+  UINTN         LargestString;
+  CHAR16        *TempString;
+  CHAR16        *BufferedString;
+  CHAR16        *StackString;
+  CHAR16        KeyPad[2];
+  UINTN         Start;
+  UINTN         Top;
+  UINTN         Index;
+  EFI_STATUS    Status;
+  BOOLEAN       SelectionComplete;
+  UINTN         InputOffset;
+  UINTN         CurrentAttribute;
+  UINTN         DimensionsWidth;
+  UINTN         DimensionsHeight;
+
+  DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+  DimensionsHeight  = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
+
+  SelectionComplete = FALSE;
+  InputOffset       = 0;
+  TempString        = AllocateZeroPool (MaximumStringSize * 2);
+  BufferedString    = AllocateZeroPool (MaximumStringSize * 2);
+  CurrentAttribute  = gST->ConOut->Mode->Attribute;
+
+  ASSERT (TempString);
+  ASSERT (BufferedString);
+
+  VA_START (Marker, String);
+
+  //
+  // Zero the outgoing buffer
+  //
+  ZeroMem (StringBuffer, MaximumStringSize);
+
+  if (HotKey) {
+    if (KeyValue == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+  } else {
+    if (StringBuffer == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+  //
+  // Disable cursor
+  //
+  gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+  LargestString = (GetStringWidth (String) / 2);
+
+  if (*String == L' ') {
+    InputOffset = 1;
+  }
+  //
+  // Determine the largest string in the dialog box
+  // Notice we are starting with 1 since String is the first string
+  //
+  for (Count = 1; Count < NumberOfLines; Count++) {
+    StackString = VA_ARG (Marker, CHAR16 *);
+
+    if (StackString[0] == L' ') {
+      InputOffset = Count + 1;
+    }
+
+    if ((GetStringWidth (StackString) / 2) > LargestString) {
+      //
+      // Size of the string visually and subtract the width by one for the null-terminator
+      //
+      LargestString = (GetStringWidth (StackString) / 2);
+    }
+  }
+
+  Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;
+  Top   = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
+
+  Count = 0;
+
+  //
+  // Display the Popup
+  //
+  CreateSharedPopUp (LargestString, NumberOfLines, &String);
+
+  //
+  // Take the first key typed and report it back?
+  //
+  if (HotKey) {
+    Status = WaitForKeyStroke (&Key);
+    ASSERT_EFI_ERROR (Status);
+    CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));
+
+  } else {
+    do {
+      Status = WaitForKeyStroke (&Key);
+
+      switch (Key.UnicodeChar) {
+      case CHAR_NULL:
+        switch (Key.ScanCode) {
+        case SCAN_ESC:
+          gBS->FreePool (TempString);
+          gBS->FreePool (BufferedString);
+          gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
+          gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+          return EFI_DEVICE_ERROR;
+
+        default:
+          break;
+        }
+
+        break;
+
+      case CHAR_CARRIAGE_RETURN:
+        SelectionComplete = TRUE;
+        gBS->FreePool (TempString);
+        gBS->FreePool (BufferedString);
+        gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
+        gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+        return EFI_SUCCESS;
+        break;
+
+      case CHAR_BACKSPACE:
+        if (StringBuffer[0] != CHAR_NULL) {
+          for (Index = 0; StringBuffer[Index] != CHAR_NULL; Index++) {
+            TempString[Index] = StringBuffer[Index];
+          }
+          //
+          // Effectively truncate string by 1 character
+          //
+          TempString[Index - 1] = CHAR_NULL;
+          StrCpy (StringBuffer, TempString);
+        }
+
+      default:
+        //
+        // If it is the beginning of the string, don't worry about checking maximum limits
+        //
+        if ((StringBuffer[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
+          StrnCpy (StringBuffer, &Key.UnicodeChar, 1);
+          StrnCpy (TempString, &Key.UnicodeChar, 1);
+        } else if ((GetStringWidth (StringBuffer) < MaximumStringSize) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
+          KeyPad[0] = Key.UnicodeChar;
+          KeyPad[1] = CHAR_NULL;
+          StrCat (StringBuffer, KeyPad);
+          StrCat (TempString, KeyPad);
+        }
+        //
+        // If the width of the input string is now larger than the screen, we nee to
+        // adjust the index to start printing portions of the string
+        //
+        SetUnicodeMem (BufferedString, LargestString, L' ');
+
+        PrintStringAt (Start + 1, Top + InputOffset, BufferedString);
+
+        if ((GetStringWidth (StringBuffer) / 2) > (DimensionsWidth - 2)) {
+          Index = (GetStringWidth (StringBuffer) / 2) - DimensionsWidth + 2;
+        } else {
+          Index = 0;
+        }
+
+        for (Count = 0; Index + 1 < GetStringWidth (StringBuffer) / 2; Index++, Count++) {
+          BufferedString[Count] = StringBuffer[Index];
+        }
+
+        PrintStringAt (Start + 1, Top + InputOffset, BufferedString);
+        break;
+      }
+    } while (!SelectionComplete);
+  }
+
+  gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
+  gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+  return EFI_SUCCESS;
+}
+
+VOID
+CreateSharedPopUp (
+  IN  UINTN                       RequestedWidth,
+  IN  UINTN                       NumberOfLines,
+  IN  CHAR16                      **ArrayOfStrings
+  )
+{
+  UINTN   Index;
+  UINTN   Count;
+  CHAR16  Character;
+  UINTN   Start;
+  UINTN   End;
+  UINTN   Top;
+  UINTN   Bottom;
+  CHAR16  *String;
+  UINTN   DimensionsWidth;
+  UINTN   DimensionsHeight;
+
+  DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+  DimensionsHeight  = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
+
+  Count = 0;
+
+  gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+
+  if ((RequestedWidth + 2) > DimensionsWidth) {
+    RequestedWidth = DimensionsWidth - 2;
+  }
+
+  //
+  // Subtract the PopUp width from total Columns, allow for one space extra on
+  // each end plus a border.
+  //
+  Start     = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1;
+  End       = Start + RequestedWidth + 1;
+
+  Top       = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
+  Bottom    = Top + NumberOfLines + 2;
+
+  Character = BOXDRAW_DOWN_RIGHT;
+  PrintCharAt (Start, Top, Character);
+  Character = BOXDRAW_HORIZONTAL;
+  for (Index = Start; Index + 2 < End; Index++) {
+    PrintChar (Character);
+  }
+
+  Character = BOXDRAW_DOWN_LEFT;
+  PrintChar (Character);
+  Character = BOXDRAW_VERTICAL;
+  for (Index = Top; Index + 2 < Bottom; Index++) {
+    String = ArrayOfStrings[Count];
+    Count++;
+
+    //
+    // This will clear the background of the line - we never know who might have been
+    // here before us.  This differs from the next clear in that it used the non-reverse
+    // video for normal printing.
+    //
+    if (GetStringWidth (String) / 2 > 1) {
+      ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);
+    }
+
+    //
+    // Passing in a space results in the assumption that this is where typing will occur
+    //
+    if (String[0] == L' ') {
+      ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);
+    }
+
+    //
+    // Passing in a NULL results in a blank space
+    //
+    if (String[0] == CHAR_NULL) {
+      ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);
+    }
+
+    PrintStringAt (
+      ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
+      Index + 1,
+      String
+      );
+    gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+    PrintCharAt (Start, Index + 1, Character);
+    PrintCharAt (End - 1, Index + 1, Character);
+  }
+
+  Character = BOXDRAW_UP_RIGHT;
+  PrintCharAt (Start, Bottom - 1, Character);
+  Character = BOXDRAW_HORIZONTAL;
+  for (Index = Start; Index + 2 < End; Index++) {
+    PrintChar (Character);
+  }
+
+  Character = BOXDRAW_UP_LEFT;
+  PrintChar (Character);
+}
+
+VOID
+CreatePopUp (
+  IN  UINTN                       RequestedWidth,
+  IN  UINTN                       NumberOfLines,
+  IN  CHAR16                      *ArrayOfStrings,
+  ...
+  )
+{
+  CreateSharedPopUp (RequestedWidth, NumberOfLines, &ArrayOfStrings);
+}
+
+
+/**
+  Update status bar on the bottom of menu.
+
+  @param  MessageType            The type of message to be shown.
+  @param  Flags                  The flags in Question header.
+  @param  State                  Set or clear.
+
+  @return None.
+
+**/
+VOID
+UpdateStatusBar (
+  IN  UINTN                       MessageType,
+  IN  UINT8                       Flags,
+  IN  BOOLEAN                     State
+  )
+{
+  UINTN           Index;
+  STATIC BOOLEAN  InputError;
+  CHAR16          *NvUpdateMessage;
+  CHAR16          *InputErrorMessage;
+
+  NvUpdateMessage   = GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), gHiiHandle);
+  InputErrorMessage = GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), gHiiHandle);
+
+  switch (MessageType) {
+  case INPUT_ERROR:
+    if (State) {
+      gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);
+      PrintStringAt (
+        gScreenDimensions.LeftColumn + gPromptBlockWidth,
+        gScreenDimensions.BottomRow - 1,
+        InputErrorMessage
+        );
+      InputError = TRUE;
+    } else {
+      gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);
+      for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) {
+        PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, L"  ");
+      }
+
+      InputError = FALSE;
+    }
+    break;
+
+  case NV_UPDATE_REQUIRED:
+    if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
+      if (State) {
+        gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);
+        PrintStringAt (
+          gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth,
+          gScreenDimensions.BottomRow - 1,
+          NvUpdateMessage
+          );
+        gResetRequired    = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED));
+
+        gNvUpdateRequired = TRUE;
+      } else {
+        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);
+        for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {
+          PrintAt (
+            (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index),
+            gScreenDimensions.BottomRow - 1,
+            L"  "
+            );
+        }
+
+        gNvUpdateRequired = FALSE;
+      }
+    }
+    break;
+
+  case REFRESH_STATUS_BAR:
+    if (InputError) {
+      UpdateStatusBar (INPUT_ERROR, Flags, TRUE);
+    }
+
+    if (gNvUpdateRequired) {
+      UpdateStatusBar (NV_UPDATE_REQUIRED, Flags, TRUE);
+    }
+    break;
+
+  default:
+    break;
+  }
+
+  gBS->FreePool (InputErrorMessage);
+  gBS->FreePool (NvUpdateMessage);
+  return ;
+}
+
+
+/**
+  Get the supported width for a particular op-code
+
+  @param  Statement              The FORM_BROWSER_STATEMENT structure passed in.
+  @param  Handle                 The handle in the HII database being used
+
+  @return Returns the number of CHAR16 characters that is support.
+
+**/
+UINT16
+GetWidth (
+  IN FORM_BROWSER_STATEMENT        *Statement,
+  IN EFI_HII_HANDLE                 Handle
+  )
+{
+  CHAR16  *String;
+  UINTN   Size;
+  UINT16  Width;
+
+  Size = 0;
+
+  //
+  // See if the second text parameter is really NULL
+  //
+  if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {
+    String = GetToken (Statement->TextTwo, Handle);
+    Size   = StrLen (String);
+    gBS->FreePool (String);
+  }
+
+  if ((Statement->Operand == EFI_IFR_SUBTITLE_OP) ||
+      (Statement->Operand == EFI_IFR_REF_OP) ||
+      (Statement->Operand == EFI_IFR_PASSWORD_OP) ||
+      (Statement->Operand == EFI_IFR_ACTION_OP) ||
+      (Statement->Operand == EFI_IFR_RESET_BUTTON_OP) ||
+      //
+      // Allow a wide display if text op-code and no secondary text op-code
+      //
+      ((Statement->Operand == EFI_IFR_TEXT_OP) && (Size == 0))
+      ) {
+    Width = (UINT16) (gPromptBlockWidth + gOptionBlockWidth);
+  } else {
+    Width = (UINT16) gPromptBlockWidth;
+  }
+
+  if (Statement->InSubtitle) {
+    Width -= SUBTITLE_INDENT;
+  }
+
+  return Width;
+}
+
+
+/**
+  Will copy LineWidth amount of a string in the OutputString buffer and return the
+  number of CHAR16 characters that were copied into the OutputString buffer.
+
+  @param  InputString            String description for this option.
+  @param  LineWidth              Width of the desired string to extract in CHAR16
+                                 characters
+  @param  Index                  Where in InputString to start the copy process
+  @param  OutputString           Buffer to copy the string into
+
+  @return Returns the number of CHAR16 characters that were copied into the OutputString buffer.
+
+**/
+UINT16
+GetLineByWidth (
+  IN      CHAR16                      *InputString,
+  IN      UINT16                      LineWidth,
+  IN OUT  UINTN                       *Index,
+  OUT     CHAR16                      **OutputString
+  )
+{
+  static BOOLEAN  Finished;
+  UINT16          Count;
+  UINT16          Count2;
+
+  if (Finished) {
+    Finished = FALSE;
+    return (UINT16) 0;
+  }
+
+  Count         = LineWidth;
+  Count2        = 0;
+
+  *OutputString = AllocateZeroPool (((UINTN) (LineWidth + 1) * 2));
+
+  //
+  // Ensure we have got a valid buffer
+  //
+  if (*OutputString != NULL) {
+
+    //
+    //NARROW_CHAR can not be printed in screen, so if a line only contain  the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line  in Screen.
+    //To avoid displaying this  empty line in screen,  just skip  the two CHARs here.
+    //
+   if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {
+     *Index = *Index + 2;
+   }
+
+    //
+    // Fast-forward the string and see if there is a carriage-return in the string
+    //
+    for (; (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++)
+      ;
+
+    //
+    // Copy the desired LineWidth of data to the output buffer.
+    // Also make sure that we don't copy more than the string.
+    // Also make sure that if there are linefeeds, we account for them.
+    //
+    if ((StrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) &&
+        (StrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2))
+        ) {
+      //
+      // Convert to CHAR16 value and show that we are done with this operation
+      //
+      LineWidth = (UINT16) ((StrSize (&InputString[*Index]) - 2) / 2);
+      if (LineWidth != 0) {
+        Finished = TRUE;
+      }
+    } else {
+      if (Count2 == LineWidth) {
+        //
+        // Rewind the string from the maximum size until we see a space to break the line
+        //
+        for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--)
+          ;
+        if (LineWidth == 0) {
+          LineWidth = Count;
+        }
+      } else {
+        LineWidth = Count2;
+      }
+    }
+
+    CopyMem (*OutputString, &InputString[*Index], LineWidth * 2);
+
+    //
+    // If currently pointing to a space, increment the index to the first non-space character
+    //
+    for (;
+         (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN);
+         (*Index)++
+        )
+      ;
+    *Index = (UINT16) (*Index + LineWidth);
+    return LineWidth;
+  } else {
+    return (UINT16) 0;
+  }
+}
+
+
+/**
+  Update display lines for a Menu Option.
+
+  @param  MenuOption             The MenuOption to be checked.
+
+  @retval TRUE                   This Menu Option is selectable.
+  @retval FALSE                  This Menu Option could not be selected.
+
+**/
+VOID
+UpdateOptionSkipLines (
+  IN UI_MENU_SELECTION            *Selection,
+  IN UI_MENU_OPTION               *MenuOption,
+  IN CHAR16                       **OptionalString,
+  IN UINTN                        SkipValue
+  )
+{
+  UINTN   Index;
+  UINT16  Width;
+  UINTN   Row;
+  UINTN   OriginalRow;
+  CHAR16  *OutputString;
+  CHAR16  *OptionString;
+
+  Row           = 0;
+  OptionString  = *OptionalString;
+  OutputString  = NULL;
+
+  ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
+
+  if (OptionString != NULL) {
+    Width               = (UINT16) gOptionBlockWidth;
+
+    OriginalRow         = Row;
+
+    for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+      //
+      // If there is more string to process print on the next row and increment the Skip value
+      //
+      if (StrLen (&OptionString[Index])) {
+        if (SkipValue == 0) {
+          Row++;
+          //
+          // Since the Number of lines for this menu entry may or may not be reflected accurately
+          // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
+          // some testing to ensure we are keeping this in-sync.
+          //
+          // If the difference in rows is greater than or equal to the skip value, increase the skip value
+          //
+          if ((Row - OriginalRow) >= MenuOption->Skip) {
+            MenuOption->Skip++;
+          }
+        }
+      }
+
+      gBS->FreePool (OutputString);
+      if (SkipValue != 0) {
+        SkipValue--;
+      }
+    }
+
+    Row = OriginalRow;
+  }
+
+  *OptionalString = OptionString;
+}
+
+
+/**
+  Check whether this Menu Option could be highlighted.
+
+  @param  MenuOption             The MenuOption to be checked.
+
+  @retval TRUE                   This Menu Option is selectable.
+  @retval FALSE                  This Menu Option could not be selected.
+
+**/
+STATIC
+BOOLEAN
+IsSelectable (
+  UI_MENU_OPTION   *MenuOption
+  )
+{
+  if ((MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) ||
+      MenuOption->GrayOut || MenuOption->ReadOnly) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+
+/**
+  Determine if the menu is the last menu that can be selected.
+
+  @param  Direction              the scroll direction. False is down. True is up.
+
+  @return FALSE -- the menu isn't the last menu that can be selected.
+  @return TRUE  -- the menu is the last menu that can be selected.
+
+**/
+STATIC
+BOOLEAN
+ValueIsScroll (
+  IN  BOOLEAN                     Direction,
+  IN  LIST_ENTRY                  *CurrentPos
+  )
+{
+  LIST_ENTRY      *Temp;
+  UI_MENU_OPTION  *MenuOption;
+
+  Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;
+
+  if (Temp == &Menu) {
+    return TRUE;
+  }
+
+  for (; Temp != &Menu; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) {
+    MenuOption = MENU_OPTION_FROM_LINK (Temp);
+    if (IsSelectable (MenuOption)) {
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+
+/**
+  Move to next selectable statement.
+
+  @param  GoUp                   The navigation direction. TRUE: up, FALSE: down.
+  @param  CurrentPosition        Current position.
+
+  @return The row distance from current MenuOption to next selectable MenuOption.
+
+**/
+STATIC
+INTN
+MoveToNextStatement (
+  IN     BOOLEAN                   GoUp,
+  IN OUT LIST_ENTRY                **CurrentPosition
+  )
+{
+  INTN             Distance;
+  LIST_ENTRY       *Pos;
+  BOOLEAN          HitEnd;
+  UI_MENU_OPTION   *NextMenuOption;
+
+  Distance = 0;
+  Pos      = *CurrentPosition;
+  HitEnd   = FALSE;
+
+  while (TRUE) {
+    NextMenuOption = MENU_OPTION_FROM_LINK (Pos);
+    if (IsSelectable (NextMenuOption)) {
+      break;
+    }
+    if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) {
+      HitEnd = TRUE;
+      break;
+    }
+    Distance += NextMenuOption->Skip;
+    Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);
+  }
+
+  if (HitEnd) {
+    //
+    // If we hit end there is still no statement can be focused,
+    // we go backwards to find the statement can be focused.
+    //
+    Distance = 0;
+    Pos = *CurrentPosition;
+
+    while (TRUE) {
+      NextMenuOption = MENU_OPTION_FROM_LINK (Pos);
+      if (IsSelectable (NextMenuOption)) {
+        break;
+      }
+      if ((!GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) {
+        ASSERT (FALSE);
+        break;
+      }
+      Distance -= NextMenuOption->Skip;
+      Pos = (!GoUp ? Pos->BackLink : Pos->ForwardLink);
+    }
+  }
+
+  *CurrentPosition = &NextMenuOption->Link;
+  return Distance;
+}
+
+
+/**
+  Adjust Data and Time position accordingly.
+  Data format :      [01/02/2004]      [11:22:33]
+  Line number :        0  0    1         0  0  1
+
+  @param  DirectionUp            the up or down direction. False is down. True is
+                                 up.
+  @param  CurrentPosition        Current position. On return: Point to the last
+                                 Option (Year or Second) if up; Point to the first
+                                 Option (Month or Hour) if down.
+
+  @return Return line number to pad. It is possible that we stand on a zero-advance
+  @return data or time opcode, so pad one line when we judge if we are going to scroll outside.
+
+**/
+STATIC
+UINTN
+AdjustDateAndTimePosition (
+  IN     BOOLEAN                     DirectionUp,
+  IN OUT LIST_ENTRY                  **CurrentPosition
+  )
+{
+  UINTN           Count;
+  LIST_ENTRY      *NewPosition;
+  UI_MENU_OPTION  *MenuOption;
+  UINTN           PadLineNumber;
+
+  PadLineNumber = 0;
+  NewPosition   = *CurrentPosition;
+  MenuOption    = MENU_OPTION_FROM_LINK (NewPosition);
+
+  if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||
+      (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
+    //
+    // Calculate the distance from current position to the last Date/Time MenuOption
+    //
+    Count = 0;
+    while (MenuOption->Skip == 0) {
+      Count++;
+      NewPosition   = NewPosition->ForwardLink;
+      MenuOption    = MENU_OPTION_FROM_LINK (NewPosition);
+      PadLineNumber = 1;
+    }
+
+    NewPosition = *CurrentPosition;
+    if (DirectionUp) {
+      //
+      // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended
+      // to be one that back to the previous set of MenuOptions, we need to advance to the first
+      // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate
+      // checking can be done.
+      //
+      while (Count++ < 2) {
+        NewPosition = NewPosition->BackLink;
+      }
+    } else {
+      //
+      // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended
+      // to be one that progresses to the next set of MenuOptions, we need to advance to the last
+      // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate
+      // checking can be done.
+      //
+      while (Count-- > 0) {
+        NewPosition = NewPosition->ForwardLink;
+      }
+    }
+
+    *CurrentPosition = NewPosition;
+  }
+
+  return PadLineNumber;
+}
+
+
+/**
+  Display menu and wait for user to select one menu option, then return it.
+  If AutoBoot is enabled, then if user doesn't select any option,
+  after period of time, it will automatically return the first menu option.
+
+
+  @return Return the pointer of the menu which selected,
+  @return otherwise return NULL.
+
+**/
+EFI_STATUS
+UiDisplayMenu (
+  IN OUT UI_MENU_SELECTION           *Selection
+  )
+{
+  INTN                            SkipValue;
+  INTN                            Difference;
+  INTN                            OldSkipValue;
+  UINTN                           DistanceValue;
+  UINTN                           Row;
+  UINTN                           Col;
+  UINTN                           Temp;
+  UINTN                           Temp2;
+  UINTN                           TopRow;
+  UINTN                           BottomRow;
+  UINTN                           OriginalRow;
+  UINTN                           Index;
+  UINT32                          Count;
+  UINT16                          Width;
+  CHAR16                          *StringPtr;
+  CHAR16                          *OptionString;
+  CHAR16                          *OutputString;
+  CHAR16                          *FormattedString;
+  CHAR16                          YesResponse;
+  CHAR16                          NoResponse;
+  BOOLEAN                         NewLine;
+  BOOLEAN                         Repaint;
+  BOOLEAN                         SavedValue;
+  EFI_STATUS                      Status;
+  EFI_INPUT_KEY                   Key;
+  LIST_ENTRY                      *Link;
+  LIST_ENTRY                      *NewPos;
+  LIST_ENTRY                      *TopOfScreen;
+  LIST_ENTRY                      *SavedListEntry;
+  UI_MENU_OPTION                  *MenuOption;
+  UI_MENU_OPTION                  *NextMenuOption;
+  UI_MENU_OPTION                  *SavedMenuOption;
+  UI_MENU_OPTION                  *PreviousMenuOption;
+  UI_CONTROL_FLAG                 ControlFlag;
+  EFI_SCREEN_DESCRIPTOR           LocalScreen;
+  MENU_REFRESH_ENTRY              *MenuRefreshEntry;
+  UI_SCREEN_OPERATION             ScreenOperation;
+  UINT8                           MinRefreshInterval;
+  UINTN                           BufferSize;
+  UINT16                          DefaultId;
+  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
+  FORM_BROWSER_STATEMENT          *Statement;
+
+  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+  Status              = EFI_SUCCESS;
+  FormattedString     = NULL;
+  OptionString        = NULL;
+  ScreenOperation     = UiNoOperation;
+  NewLine             = TRUE;
+  MinRefreshInterval  = 0;
+  DefaultId           = 0;
+
+  OutputString        = NULL;
+  gUpArrow            = FALSE;
+  gDownArrow          = FALSE;
+  SkipValue           = 0;
+  OldSkipValue        = 0;
+  MenuRefreshEntry    = gMenuRefreshHead;
+
+  NextMenuOption      = NULL;
+  PreviousMenuOption  = NULL;
+  SavedMenuOption     = NULL;
+
+  ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
+
+  if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
+    TopRow  = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
+    Row     = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
+  } else {
+    TopRow  = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
+    Row     = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
+  }
+
+  Col = LocalScreen.LeftColumn;
+  BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - SCROLL_ARROW_HEIGHT - 1;
+
+  Selection->TopRow = TopRow;
+  Selection->BottomRow = BottomRow;
+  Selection->PromptCol = Col;
+  Selection->OptionCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;
+  Selection->Statement = NULL;
+
+  TopOfScreen = Menu.ForwardLink;
+  Repaint     = TRUE;
+  MenuOption  = NULL;
+
+  //
+  // Get user's selection
+  //
+  NewPos = Menu.ForwardLink;
+
+  gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+  UpdateStatusBar (REFRESH_STATUS_BAR, (UINT8) 0, TRUE);
+
+  ControlFlag = CfInitialization;
+  Selection->Action = UI_ACTION_NONE;
+  while (TRUE) {
+    switch (ControlFlag) {
+    case CfInitialization:
+      if (IsListEmpty (&Menu)) {
+        ControlFlag = CfReadKey;
+      } else {
+        ControlFlag = CfCheckSelection;
+      }
+      break;
+
+    case CfCheckSelection:
+      if (Selection->Action != UI_ACTION_NONE) {
+        ControlFlag = CfExit;
+      } else {
+        ControlFlag = CfRepaint;
+      }
+      break;
+
+    case CfRepaint:
+      ControlFlag = CfRefreshHighLight;
+
+      if (Repaint) {
+        //
+        // Display menu
+        //
+        gDownArrow      = FALSE;
+        gUpArrow        = FALSE;
+        Row             = TopRow;
+
+        Temp            = SkipValue;
+        Temp2           = SkipValue;
+
+        ClearLines (
+          LocalScreen.LeftColumn,
+          LocalScreen.RightColumn,
+          TopRow - SCROLL_ARROW_HEIGHT,
+          BottomRow + SCROLL_ARROW_HEIGHT,
+          FIELD_TEXT | FIELD_BACKGROUND
+          );
+
+        UiFreeRefreshList ();
+        MinRefreshInterval = 0;
+
+        for (Link = TopOfScreen; Link != &Menu; Link = Link->ForwardLink) {
+          MenuOption          = MENU_OPTION_FROM_LINK (Link);
+          MenuOption->Row     = Row;
+          MenuOption->Col     = Col;
+          MenuOption->OptCol  = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;
+
+          Statement = MenuOption->ThisTag;
+          if (Statement->InSubtitle) {
+            MenuOption->Col += SUBTITLE_INDENT;
+          }
+
+          if (MenuOption->GrayOut) {
+            gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);
+          } else {
+            if (Statement->Operand == EFI_IFR_SUBTITLE_OP) {
+              gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);
+            }
+          }
+
+          Width       = GetWidth (Statement, MenuOption->Handle);
+          OriginalRow = Row;
+
+          for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
+            if ((Temp == 0) && (Row <= BottomRow)) {
+              PrintStringAt (MenuOption->Col, Row, OutputString);
+            }
+            //
+            // If there is more string to process print on the next row and increment the Skip value
+            //
+            if (StrLen (&MenuOption->Description[Index])) {
+              if (Temp == 0) {
+                Row++;
+              }
+            }
+
+            gBS->FreePool (OutputString);
+            if (Temp != 0) {
+              Temp--;
+            }
+          }
+
+          Temp  = 0;
+          Row   = OriginalRow;
+
+          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+          ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
+
+          if (OptionString != NULL) {
+            if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
+              //
+              // If leading spaces on OptionString - remove the spaces
+              //
+              for (Index = 0; OptionString[Index] == L' '; Index++) {
+                MenuOption->OptCol++;
+              }
+
+              for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
+                OptionString[Count] = OptionString[Index];
+                Count++;
+              }
+
+              OptionString[Count] = CHAR_NULL;
+            }
+
+            //
+            // If Question request refresh, register the op-code
+            //
+            if (Statement->RefreshInterval != 0) {
+              //
+              // Menu will be refreshed at minimal interval of all Questions
+              // which have refresh request
+              //
+              if (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval) {
+                MinRefreshInterval = Statement->RefreshInterval;
+              }
+
+              if (gMenuRefreshHead == NULL) {
+                MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
+                ASSERT (MenuRefreshEntry != NULL);
+                MenuRefreshEntry->MenuOption        = MenuOption;
+                MenuRefreshEntry->Selection         = Selection;
+                MenuRefreshEntry->CurrentColumn     = MenuOption->OptCol;
+                MenuRefreshEntry->CurrentRow        = MenuOption->Row;
+                MenuRefreshEntry->CurrentAttribute  = FIELD_TEXT | FIELD_BACKGROUND;
+                gMenuRefreshHead                    = MenuRefreshEntry;
+              } else {
+                //
+                // Advance to the last entry
+                //
+                for (MenuRefreshEntry = gMenuRefreshHead;
+                     MenuRefreshEntry->Next != NULL;
+                     MenuRefreshEntry = MenuRefreshEntry->Next
+                    )
+                  ;
+                MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
+                ASSERT (MenuRefreshEntry->Next != NULL);
+                MenuRefreshEntry                    = MenuRefreshEntry->Next;
+                MenuRefreshEntry->MenuOption        = MenuOption;
+                MenuRefreshEntry->Selection         = Selection;
+                MenuRefreshEntry->CurrentColumn     = MenuOption->OptCol;
+                MenuRefreshEntry->CurrentRow        = MenuOption->Row;
+                MenuRefreshEntry->CurrentAttribute  = FIELD_TEXT | FIELD_BACKGROUND;
+              }
+            }
+
+            Width       = (UINT16) gOptionBlockWidth;
+            OriginalRow = Row;
+
+            for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+              if ((Temp2 == 0) && (Row <= BottomRow)) {
+                PrintStringAt (MenuOption->OptCol, Row, OutputString);
+              }
+              //
+              // If there is more string to process print on the next row and increment the Skip value
+              //
+              if (StrLen (&OptionString[Index])) {
+                if (Temp2 == 0) {
+                  Row++;
+                  //
+                  // Since the Number of lines for this menu entry may or may not be reflected accurately
+                  // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
+                  // some testing to ensure we are keeping this in-sync.
+                  //
+                  // If the difference in rows is greater than or equal to the skip value, increase the skip value
+                  //
+                  if ((Row - OriginalRow) >= MenuOption->Skip) {
+                    MenuOption->Skip++;
+                  }
+                }
+              }
+
+              gBS->FreePool (OutputString);
+              if (Temp2 != 0) {
+                Temp2--;
+              }
+            }
+
+            Temp2 = 0;
+            Row   = OriginalRow;
+
+            gBS->FreePool (OptionString);
+          }
+          //
+          // If this is a text op with secondary text information
+          //
+          if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {
+            StringPtr   = GetToken (Statement->TextTwo, MenuOption->Handle);
+
+            Width       = (UINT16) gOptionBlockWidth;
+            OriginalRow = Row;
+
+            for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) {
+              if ((Temp == 0) && (Row <= BottomRow)) {
+                PrintStringAt (MenuOption->OptCol, Row, OutputString);
+              }
+              //
+              // If there is more string to process print on the next row and increment the Skip value
+              //
+              if (StrLen (&StringPtr[Index])) {
+                if (Temp2 == 0) {
+                  Row++;
+                  //
+                  // Since the Number of lines for this menu entry may or may not be reflected accurately
+                  // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
+                  // some testing to ensure we are keeping this in-sync.
+                  //
+                  // If the difference in rows is greater than or equal to the skip value, increase the skip value
+                  //
+                  if ((Row - OriginalRow) >= MenuOption->Skip) {
+                    MenuOption->Skip++;
+                  }
+                }
+              }
+
+              gBS->FreePool (OutputString);
+              if (Temp2 != 0) {
+                Temp2--;
+              }
+            }
+
+            Row = OriginalRow;
+            gBS->FreePool (StringPtr);
+          }
+
+          //
+          // Need to handle the bottom of the display
+          //
+          if (MenuOption->Skip > 1) {
+            Row += MenuOption->Skip - SkipValue;
+            SkipValue = 0;
+          } else {
+            Row += MenuOption->Skip;
+          }
+
+          if (Row > BottomRow) {
+            if (!ValueIsScroll (FALSE, Link)) {
+              gDownArrow = TRUE;
+            }
+
+            Row = BottomRow + 1;
+            break;
+          }
+        }
+
+        if (!ValueIsScroll (TRUE, TopOfScreen)) {
+          gUpArrow = TRUE;
+        }
+
+        if (gUpArrow) {
+          gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
+          PrintAt (
+            LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
+            TopRow - SCROLL_ARROW_HEIGHT,
+            L"%c",
+            ARROW_UP
+            );
+          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+        }
+
+        if (gDownArrow) {
+          gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
+          PrintAt (
+            LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
+            BottomRow + SCROLL_ARROW_HEIGHT,
+            L"%c",
+            ARROW_DOWN
+            );
+          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+        }
+
+        MenuOption = NULL;
+      }
+      break;
+
+    case CfRefreshHighLight:
+      //
+      // MenuOption: Last menu option that need to remove hilight
+      //             MenuOption is set to NULL in Repaint
+      // NewPos:     Current menu option that need to hilight
+      //
+      ControlFlag = CfUpdateHelpString;
+
+      //
+      // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily
+      // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.
+      //
+      SavedValue  = Repaint;
+      Repaint     = FALSE;
+
+      if (Selection->QuestionId != 0) {
+        NewPos = Menu.ForwardLink;
+        SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
+
+        while (SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId && NewPos->ForwardLink != &Menu) {
+          NewPos     = NewPos->ForwardLink;
+          SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
+        }
+        if (SavedMenuOption->ThisTag->QuestionId == Selection->QuestionId) {
+          //
+          // Target Question found, find its MenuOption
+          //
+          Link = TopOfScreen;
+
+          for (Index = TopRow; Index <= BottomRow && Link != NewPos;) {
+            SavedMenuOption = MENU_OPTION_FROM_LINK (Link);
+            Index += SavedMenuOption->Skip;
+            Link = Link->ForwardLink;
+          }
+
+          if (Link != NewPos || Index > BottomRow) {
+            //
+            // NewPos is not in the current page, simply scroll page so that NewPos is in the end of the page
+            //
+            Link    = NewPos;
+            for (Index = TopRow; Index <= BottomRow; ) {
+              Link = Link->BackLink;
+              SavedMenuOption = MENU_OPTION_FROM_LINK (Link);
+              Index     += SavedMenuOption->Skip;
+            }
+            TopOfScreen     = Link->ForwardLink;
+
+            Repaint = TRUE;
+            NewLine = TRUE;
+            ControlFlag = CfRepaint;
+            break;
+          }
+        } else {
+          //
+          // Target Question not found, highlight the default menu option
+          //
+          NewPos = TopOfScreen;
+        }
+
+        Selection->QuestionId = 0;
+      }
+
+      if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {
+        if (MenuOption != NULL) {
+          //
+          // Remove highlight on last Menu Option
+          //
+          gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
+          ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
+          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+          if (OptionString != NULL) {
+            if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||
+                (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)
+               ) {
+              //
+              // If leading spaces on OptionString - remove the spaces
+              //
+              for (Index = 0; OptionString[Index] == L' '; Index++)
+                ;
+
+              for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
+                OptionString[Count] = OptionString[Index];
+                Count++;
+              }
+
+              OptionString[Count] = CHAR_NULL;
+            }
+
+            Width               = (UINT16) gOptionBlockWidth;
+            OriginalRow         = MenuOption->Row;
+
+            for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+              if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
+                PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
+              }
+              //
+              // If there is more string to process print on the next row and increment the Skip value
+              //
+              if (StrLen (&OptionString[Index])) {
+                MenuOption->Row++;
+              }
+
+              gBS->FreePool (OutputString);
+            }
+
+            MenuOption->Row = OriginalRow;
+
+            gBS->FreePool (OptionString);
+          } else {
+            if (NewLine) {
+              if (MenuOption->GrayOut) {
+                gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);
+              } else if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {
+                gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);
+              }
+
+              OriginalRow = MenuOption->Row;
+              Width       = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
+
+              for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
+                if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
+                  PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);
+                }
+                //
+                // If there is more string to process print on the next row and increment the Skip value
+                //
+                if (StrLen (&MenuOption->Description[Index])) {
+                  MenuOption->Row++;
+                }
+
+                gBS->FreePool (OutputString);
+              }
+
+              MenuOption->Row = OriginalRow;
+              gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+            }
+          }
+        }
+
+        //
+        // This is only possible if we entered this page and the first menu option is
+        // a "non-menu" item.  In that case, force it UiDown
+        //
+        MenuOption = MENU_OPTION_FROM_LINK (NewPos);
+        if (!IsSelectable (MenuOption)) {
+          ASSERT (ScreenOperation == UiNoOperation);
+          ScreenOperation = UiDown;
+          ControlFlag     = CfScreenOperation;
+          break;
+        }
+
+        //
+        // This is the current selected statement
+        //
+        Statement = MenuOption->ThisTag;
+        Selection->Statement = Statement;
+
+        //
+        // Set reverse attribute
+        //
+        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);
+        gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
+
+        //
+        // Assuming that we have a refresh linked-list created, lets annotate the
+        // appropriate entry that we are highlighting with its new attribute.  Just prior to this
+        // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh
+        //
+        if (gMenuRefreshHead != NULL) {
+          for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) {
+            MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
+            if (MenuRefreshEntry->MenuOption == MenuOption) {
+              MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT;
+            }
+          }
+        }
+
+        ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
+        if (OptionString != NULL) {
+          if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
+            //
+            // If leading spaces on OptionString - remove the spaces
+            //
+            for (Index = 0; OptionString[Index] == L' '; Index++)
+              ;
+
+            for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
+              OptionString[Count] = OptionString[Index];
+              Count++;
+            }
+
+            OptionString[Count] = CHAR_NULL;
+          }
+          Width               = (UINT16) gOptionBlockWidth;
+
+          OriginalRow         = MenuOption->Row;
+
+          for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+            if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
+              PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
+            }
+            //
+            // If there is more string to process print on the next row and increment the Skip value
+            //
+            if (StrLen (&OptionString[Index])) {
+              MenuOption->Row++;
+            }
+
+            gBS->FreePool (OutputString);
+          }
+
+          MenuOption->Row = OriginalRow;
+
+          gBS->FreePool (OptionString);
+        } else {
+          if (NewLine) {
+            OriginalRow = MenuOption->Row;
+
+            Width       = GetWidth (Statement, MenuOption->Handle);
+
+            for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
+              if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
+                PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);
+              }
+              //
+              // If there is more string to process print on the next row and increment the Skip value
+              //
+              if (StrLen (&MenuOption->Description[Index])) {
+                MenuOption->Row++;
+              }
+
+              gBS->FreePool (OutputString);
+            }
+
+            MenuOption->Row = OriginalRow;
+
+          }
+        }
+
+        if (((NewPos->ForwardLink != &Menu) && (ScreenOperation == UiDown)) ||
+            ((NewPos->BackLink != &Menu) && (ScreenOperation == UiUp)) ||
+            (ScreenOperation == UiNoOperation)
+            ) {
+          UpdateKeyHelp (MenuOption, FALSE);
+        }
+        //
+        // Clear reverse attribute
+        //
+        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+      }
+      //
+      // Repaint flag will be used when process CfUpdateHelpString, so restore its value
+      // if we didn't break halfway when process CfRefreshHighLight.
+      //
+      Repaint = SavedValue;
+      break;
+
+    case CfUpdateHelpString:
+      ControlFlag = CfPrepareToReadKey;
+
+        if ((Repaint || NewLine) && (gClassOfVfr != EFI_GENERAL_APPLICATION_SUBCLASS)) {
+        //
+        // Don't print anything if it is a NULL help token
+        //
+        if (MenuOption->ThisTag->Help == 0) {
+          StringPtr = L"\0";
+        } else {
+          StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);
+        }
+
+        ProcessHelpString (StringPtr, &FormattedString, BottomRow - TopRow);
+
+        gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);
+
+        for (Index = 0; Index < BottomRow - TopRow; Index++) {
+          //
+          // Pad String with spaces to simulate a clearing of the previous line
+          //
+          for (; GetStringWidth (&FormattedString[Index * gHelpBlockWidth * 2]) / 2 < gHelpBlockWidth;) {
+            StrCat (&FormattedString[Index * gHelpBlockWidth * 2], L" ");
+          }
+
+          PrintStringAt (
+            LocalScreen.RightColumn - gHelpBlockWidth,
+            Index + TopRow,
+            &FormattedString[Index * gHelpBlockWidth * 2]
+            );
+        }
+      }
+      //
+      // Reset this flag every time we finish using it.
+      //
+      Repaint = FALSE;
+      NewLine = FALSE;
+      break;
+
+    case CfPrepareToReadKey:
+      ControlFlag = CfReadKey;
+      ScreenOperation = UiNoOperation;
+      break;
+
+    case CfReadKey:
+      ControlFlag = CfScreenOperation;
+
+      //
+      // Wait for user's selection
+      //
+      do {
+        Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, MinRefreshInterval);
+      } while (Status == EFI_TIMEOUT);
+
+      if (Status == EFI_TIMEOUT) {
+        Key.UnicodeChar = CHAR_CARRIAGE_RETURN;
+      } else {
+        Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+        //
+        // if we encounter error, continue to read another key in.
+        //
+        if (EFI_ERROR (Status)) {
+          ControlFlag = CfReadKey;
+          continue;
+        }
+      }
+
+      if (IsListEmpty (&Menu) && Key.UnicodeChar != CHAR_NULL) {
+        //
+        // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
+        //
+        break;
+      }
+
+      switch (Key.UnicodeChar) {
+      case CHAR_CARRIAGE_RETURN:
+        ScreenOperation = UiSelect;
+        gDirection      = 0;
+        break;
+
+      //
+      // We will push the adjustment of these numeric values directly to the input handler
+      //  NOTE: we won't handle manual input numeric
+      //
+      case '+':
+      case '-':
+        Statement = MenuOption->ThisTag;
+        if ((Statement->Operand == EFI_IFR_DATE_OP)
+          || (Statement->Operand == EFI_IFR_TIME_OP)
+          || ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step != 0))
+        ){
+          if (Key.UnicodeChar == '+') {
+            gDirection = SCAN_RIGHT;
+          } else {
+            gDirection = SCAN_LEFT;
+          }
+          Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);
+          SafeFreePool (OptionString);
+        }
+        break;
+
+      case '^':
+        ScreenOperation = UiUp;
+        break;
+
+      case 'V':
+      case 'v':
+        ScreenOperation = UiDown;
+        break;
+
+      case ' ':
+        if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
+          if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut) {
+            ScreenOperation = UiSelect;
+          }
+        }
+        break;
+
+      case CHAR_NULL:
+        if (((Key.ScanCode == SCAN_F1) && ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE)) ||
+            ((Key.ScanCode == SCAN_F2) && ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO)) ||
+            ((Key.ScanCode == SCAN_F9) && ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE)) ||
+            ((Key.ScanCode == SCAN_F10) && ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN))
+            ) {
+          //
+          // If the function key has been disabled, just ignore the key.
+          //
+        } else {
+          for (Index = 0; Index < sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]); Index++) {
+            if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {
+              if (Key.ScanCode == SCAN_F9) {
+                //
+                // Reset to standard default
+                //
+                DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+              }
+              ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;
+              break;
+            }
+          }
+        }
+        break;
+      }
+      break;
+
+    case CfScreenOperation:
+      if (ScreenOperation != UiPrevious && ScreenOperation != UiReset) {
+        //
+        // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
+        // ignore the selection and go back to reading keys.
+        //
+        if (IsListEmpty (&Menu)) {
+          ControlFlag = CfReadKey;
+          break;
+        }
+        //
+        // if there is nothing logical to place a cursor on, just move on to wait for a key.
+        //
+        for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) {
+          NextMenuOption = MENU_OPTION_FROM_LINK (Link);
+          if (IsSelectable (NextMenuOption)) {
+            break;
+          }
+        }
+
+        if (Link == &Menu) {
+          ControlFlag = CfPrepareToReadKey;
+          break;
+        }
+      } else if (ScreenOperation == UiReset) {
+        //
+        // Press ESC to exit FormSet
+        //
+        Selection->Action = UI_ACTION_EXIT;
+        Selection->Statement = NULL;
+      }
+
+      for (Index = 0;
+           Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);
+           Index++
+          ) {
+        if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {
+          ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;
+          break;
+        }
+      }
+      break;
+
+    case CfUiPrevious:
+      ControlFlag = CfCheckSelection;
+
+      if (IsListEmpty (&gMenuList)) {
+        Selection->Action = UI_ACTION_NONE;
+        if (IsListEmpty (&Menu)) {
+          ControlFlag = CfReadKey;
+        }
+        break;
+      }
+
+      //
+      // Remove the Cached page entry
+      //
+      UiRemoveMenuListEntry (Selection);
+
+      Selection->Action = UI_ACTION_REFRESH_FORM;
+      Selection->Statement = NULL;
+      break;
+
+    case CfUiSelect:
+      ControlFlag = CfCheckSelection;
+
+      Statement = MenuOption->ThisTag;
+      if ((Statement->Operand == EFI_IFR_TEXT_OP) ||
+          (Statement->Operand == EFI_IFR_DATE_OP) ||
+          (Statement->Operand == EFI_IFR_TIME_OP) ||
+          (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) {
+        break;
+      }
+
+      //
+      // Keep highlight on current MenuOption
+      //
+      Selection->QuestionId = Statement->QuestionId;
+
+      switch (Statement->Operand) {
+      case EFI_IFR_REF_OP:
+        if (Statement->RefDevicePath != 0) {
+          //
+          // Goto another Hii Package list
+          //
+          ControlFlag = CfUiReset;
+          Selection->Action = UI_ACTION_REFRESH_FORMSET;
+
+          StringPtr = GetToken (Statement->RefDevicePath, Selection->FormSet->HiiHandle);
+          if (StringPtr == NULL) {
+            //
+            // No device path string not found, exit
+            //
+            Selection->Action = UI_ACTION_EXIT;
+            Selection->Statement = NULL;
+            break;
+          }
+          BufferSize = StrLen (StringPtr) / 4;
+          DevicePath = AllocatePool (BufferSize);
+
+          HexStringToBuffer ((UINT8 *) DevicePath, &BufferSize, StringPtr);
+          Selection->Handle = DevicePathToHiiHandle (mHiiDatabase, DevicePath);
+          if (Selection->Handle == NULL) {
+            //
+            // If target Hii Handle not found, exit
+            //
+            Selection->Action = UI_ACTION_EXIT;
+            Selection->Statement = NULL;
+            break;
+          }
+
+          gBS->FreePool (StringPtr);
+          gBS->FreePool (DevicePath);
+
+          CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));
+          Selection->FormId = Statement->RefFormId;
+          Selection->QuestionId = Statement->RefQuestionId;
+        } else if (!CompareGuid (&Statement->RefFormSetId, &gZeroGuid)) {
+          //
+          // Goto another Formset, check for uncommitted data
+          //
+          ControlFlag = CfUiReset;
+          Selection->Action = UI_ACTION_REFRESH_FORMSET;
+
+          CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));
+          Selection->FormId = Statement->RefFormId;
+          Selection->QuestionId = Statement->RefQuestionId;
+        } else if (Statement->RefFormId != 0) {
+          //
+          // Goto another form inside this formset,
+          //
+          Selection->Action = UI_ACTION_REFRESH_FORM;
+
+          //
+          // Link current form so that we can always go back when someone hits the UiPrevious
+          //
+          UiAddMenuListEntry (Selection);
+
+          Selection->FormId = Statement->RefFormId;
+          Selection->QuestionId = Statement->RefQuestionId;
+        } else if (Statement->RefQuestionId != 0) {
+          //
+          // Goto another Question
+          //
+          Selection->QuestionId = Statement->RefQuestionId;
+
+          if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK)) {
+            Selection->Action = UI_ACTION_REFRESH_FORM;
+          } else {
+            Repaint = TRUE;
+            NewLine = TRUE;
+            break;
+          }
+        }
+        break;
+
+      case EFI_IFR_ACTION_OP:
+        //
+        // Process the Config string <ConfigResp>
+        //
+        Status = ProcessQuestionConfig (Selection, Statement);
+
+        if (EFI_ERROR (Status)) {
+          break;
+        }
+
+        //
+        // The action button may change some Question value, so refresh the form
+        //
+        Selection->Action = UI_ACTION_REFRESH_FORM;
+        break;
+
+      case EFI_IFR_RESET_BUTTON_OP:
+        //
+        // Reset Question to default value specified by DefaultId
+        //
+        ControlFlag = CfUiDefault;
+        DefaultId = Statement->DefaultId;
+        break;
+
+      default:
+        //
+        // Editable Questions: oneof, ordered list, checkbox, numeric, string, password
+        //
+        UpdateKeyHelp (MenuOption, TRUE);
+        Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);
+
+        if (EFI_ERROR (Status)) {
+          Repaint = TRUE;
+          NewLine = TRUE;
+          break;
+        }
+
+        if (OptionString != NULL) {
+          PrintStringAt (LocalScreen.LeftColumn + gPromptBlockWidth + 1, MenuOption->Row, OptionString);
+          gBS->FreePool (OptionString);
+        }
+
+        Selection->Action = UI_ACTION_REFRESH_FORM;
+        break;
+      }
+      break;
+
+    case CfUiReset:
+      //
+      // We are going to leave current FormSet, so check uncommited data in this FormSet
+      //
+      ControlFlag = CfCheckSelection;
+
+      if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
+        //
+        // There is no parent menu for FrontPage
+        //
+        Selection->Action = UI_ACTION_NONE;
+        Selection->Statement = MenuOption->ThisTag;
+        break;
+      }
+
+      //
+      // If NV flag is up, prompt user
+      //
+      if (gNvUpdateRequired) {
+        Status      = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+
+        YesResponse = gYesResponse[0];
+        NoResponse  = gNoResponse[0];
+
+        do {
+          CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gAreYouSure, gEmptyString);
+        } while
+        (
+          (Key.ScanCode != SCAN_ESC) &&
+          ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&
+          ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))
+        );
+
+        //
+        // If the user hits the YesResponse key
+        //
+        if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {
+        } else {
+          Repaint = TRUE;
+          NewLine = TRUE;
+
+          Selection->Action = UI_ACTION_NONE;
+          break;
+        }
+      }
+
+      gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+      gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+      UiFreeMenuList ();
+      gST->ConOut->ClearScreen (gST->ConOut);
+      return EFI_SUCCESS;
+
+    case CfUiLeft:
+      ControlFlag = CfCheckSelection;
+      if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
+        if (MenuOption->Sequence != 0) {
+          //
+          // In the middle or tail of the Date/Time op-code set, go left.
+          //
+          NewPos = NewPos->BackLink;
+        }
+      }
+      break;
+
+    case CfUiRight:
+      ControlFlag = CfCheckSelection;
+      if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
+        if (MenuOption->Sequence != 2) {
+          //
+          // In the middle or tail of the Date/Time op-code set, go left.
+          //
+          NewPos = NewPos->ForwardLink;
+        }
+      }
+      break;
+
+    case CfUiUp:
+      ControlFlag = CfCheckSelection;
+
+      SavedListEntry = TopOfScreen;
+
+      if (NewPos->BackLink != &Menu) {
+        NewLine = TRUE;
+        //
+        // Adjust Date/Time position before we advance forward.
+        //
+        AdjustDateAndTimePosition (TRUE, &NewPos);
+
+        //
+        // Caution that we have already rewind to the top, don't go backward in this situation.
+        //
+        if (NewPos->BackLink != &Menu) {
+          NewPos = NewPos->BackLink;
+        }
+
+        PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);
+        DistanceValue = PreviousMenuOption->Skip;
+
+        //
+        // Since the behavior of hitting the up arrow on a Date/Time op-code is intended
+        // to be one that back to the previous set of op-codes, we need to advance to the sencond
+        // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
+        // checking can be done.
+        //
+        DistanceValue += AdjustDateAndTimePosition (TRUE, &NewPos);
+
+        //
+        // Check the previous menu entry to see if it was a zero-length advance.  If it was,
+        // don't worry about a redraw.
+        //
+        if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {
+          Repaint     = TRUE;
+          TopOfScreen = NewPos;
+        }
+
+        Difference = MoveToNextStatement (TRUE, &NewPos);
+        if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {
+          if (Difference > 0) {
+            //
+            // Previous focus MenuOption is above the TopOfScreen, so we need to scroll
+            //
+            TopOfScreen = NewPos;
+            Repaint     = TRUE;
+          }
+        }
+        if (Difference < 0) {
+          //
+          // We want to goto previous MenuOption, but finally we go down.
+          // it means that we hit the begining MenuOption that can be focused
+          // so we simply scroll to the top
+          //
+          if (SavedListEntry != Menu.ForwardLink) {
+            TopOfScreen = Menu.ForwardLink;
+            Repaint     = TRUE;
+          }
+        }
+
+        //
+        // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
+        //
+        AdjustDateAndTimePosition (TRUE, &TopOfScreen);
+
+        UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
+      } else {
+        SavedMenuOption = MenuOption;
+        MenuOption      = MENU_OPTION_FROM_LINK (NewPos);
+        if (!IsSelectable (MenuOption)) {
+          //
+          // If we are at the end of the list and sitting on a text op, we need to more forward
+          //
+          ScreenOperation = UiDown;
+          ControlFlag     = CfScreenOperation;
+          break;
+        }
+
+        MenuOption = SavedMenuOption;
+      }
+      break;
+
+    case CfUiPageUp:
+      ControlFlag     = CfCheckSelection;
+
+      if (NewPos->BackLink == &Menu) {
+        NewLine = FALSE;
+        Repaint = FALSE;
+        break;
+      }
+
+      NewLine   = TRUE;
+      Repaint   = TRUE;
+      Link      = TopOfScreen;
+      PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);
+      Index = BottomRow;
+      while ((Index >= TopRow) && (Link->BackLink != &Menu)) {
+        Index = Index - PreviousMenuOption->Skip;
+        Link = Link->BackLink;
+        PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);
+      }
+
+      TopOfScreen = Link;
+      Difference = MoveToNextStatement (TRUE, &Link);
+      if (Difference > 0) {
+        //
+        // The focus MenuOption is above the TopOfScreen
+        //
+        TopOfScreen = Link;
+      } else if (Difference < 0) {
+        //
+        // This happens when there is no MenuOption can be focused from
+        // Current MenuOption to the first MenuOption
+        //
+        TopOfScreen = Menu.ForwardLink;
+      }
+      Index += Difference;
+      if (Index < TopRow) {
+        MenuOption = NULL;
+      }
+
+      if (NewPos == Link) {
+        Repaint = FALSE;
+        NewLine = FALSE;
+      } else {
+        NewPos = Link;
+      }
+
+      //
+      // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
+      // Don't do this when we are already in the first page.
+      //
+      AdjustDateAndTimePosition (TRUE, &TopOfScreen);
+      AdjustDateAndTimePosition (TRUE, &NewPos);
+      break;
+
+    case CfUiPageDown:
+      ControlFlag     = CfCheckSelection;
+
+      if (NewPos->ForwardLink == &Menu) {
+        NewLine = FALSE;
+        Repaint = FALSE;
+        break;
+      }
+
+      NewLine = TRUE;
+      Repaint = TRUE;
+      Link    = TopOfScreen;
+      NextMenuOption = MENU_OPTION_FROM_LINK (Link);
+      Index = TopRow;
+      while ((Index <= BottomRow) && (Link->ForwardLink != &Menu)) {
+        Index = Index + NextMenuOption->Skip;
+        Link           = Link->ForwardLink;
+        NextMenuOption = MENU_OPTION_FROM_LINK (Link);
+      }
+
+      Index += MoveToNextStatement (FALSE, &Link);
+      if (Index > BottomRow) {
+        //
+        // There are more MenuOption needing scrolling
+        //
+        TopOfScreen = Link;
+        MenuOption = NULL;
+      }
+      if (NewPos == Link && Index <= BottomRow) {
+        //
+        // Finally we know that NewPos is the last MenuOption can be focused.
+        //
+        NewLine = FALSE;
+        Repaint = FALSE;
+      } else {
+        NewPos  = Link;
+      }
+
+      //
+      // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
+      // Don't do this when we are already in the last page.
+      //
+      AdjustDateAndTimePosition (TRUE, &TopOfScreen);
+      AdjustDateAndTimePosition (TRUE, &NewPos);
+      break;
+
+    case CfUiDown:
+      ControlFlag = CfCheckSelection;
+      //
+      // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
+      // to be one that progresses to the next set of op-codes, we need to advance to the last
+      // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
+      // checking can be done.  The only other logic we need to introduce is that if a Date/Time
+      // op-code is the last entry in the menu, we need to rewind back to the first op-code of
+      // the Date/Time op-code.
+      //
+      SavedListEntry = NewPos;
+      DistanceValue  = AdjustDateAndTimePosition (FALSE, &NewPos);
+
+      if (NewPos->ForwardLink != &Menu) {
+        MenuOption      = MENU_OPTION_FROM_LINK (NewPos);
+        NewLine         = TRUE;
+        NewPos          = NewPos->ForwardLink;
+        NextMenuOption  = MENU_OPTION_FROM_LINK (NewPos);
+
+        DistanceValue  += NextMenuOption->Skip;
+        DistanceValue  += MoveToNextStatement (FALSE, &NewPos);
+        //
+        // An option might be multi-line, so we need to reflect that data in the overall skip value
+        //
+        UpdateOptionSkipLines (Selection, NextMenuOption, &OptionString, SkipValue);
+
+        Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;
+        if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&
+            (NextMenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||
+             NextMenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)
+            ) {
+          Temp ++;
+        }
+
+        //
+        // If we are going to scroll, update TopOfScreen
+        //
+        if (Temp > BottomRow) {
+          do {
+            //
+            // Is the current top of screen a zero-advance op-code?
+            // If so, keep moving forward till we hit a >0 advance op-code
+            //
+            SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
+
+            //
+            // If bottom op-code is more than one line or top op-code is more than one line
+            //
+            if ((DistanceValue > 1) || (MenuOption->Skip > 1)) {
+              //
+              // Is the bottom op-code greater than or equal in size to the top op-code?
+              //
+              if ((Temp - BottomRow) >= (SavedMenuOption->Skip - OldSkipValue)) {
+                //
+                // Skip the top op-code
+                //
+                TopOfScreen     = TopOfScreen->ForwardLink;
+                Difference      = (Temp - BottomRow) - (SavedMenuOption->Skip - OldSkipValue);
+
+                OldSkipValue    = Difference;
+
+                SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
+
+                //
+                // If we have a remainder, skip that many more op-codes until we drain the remainder
+                //
+                for (;
+                     Difference >= (INTN) SavedMenuOption->Skip;
+                     Difference = Difference - (INTN) SavedMenuOption->Skip
+                    ) {
+                  //
+                  // Since the Difference is greater than or equal to this op-code's skip value, skip it
+                  //
+                  TopOfScreen     = TopOfScreen->ForwardLink;
+                  SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
+                  if (Difference < (INTN) SavedMenuOption->Skip) {
+                    Difference = SavedMenuOption->Skip - Difference - 1;
+                    break;
+                  } else {
+                    if (Difference == (INTN) SavedMenuOption->Skip) {
+                      TopOfScreen     = TopOfScreen->ForwardLink;
+                      SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
+                      Difference      = SavedMenuOption->Skip - Difference;
+                      break;
+                    }
+                  }
+                }
+                //
+                // Since we will act on this op-code in the next routine, and increment the
+                // SkipValue, set the skips to one less than what is required.
+                //
+                SkipValue = Difference - 1;
+
+              } else {
+                //
+                // Since we will act on this op-code in the next routine, and increment the
+                // SkipValue, set the skips to one less than what is required.
+                //
+                SkipValue = OldSkipValue + (Temp - BottomRow) - 1;
+              }
+            } else {
+              if ((OldSkipValue + 1) == (INTN) SavedMenuOption->Skip) {
+                TopOfScreen = TopOfScreen->ForwardLink;
+                break;
+              } else {
+                SkipValue = OldSkipValue;
+              }
+            }
+            //
+            // If the op-code at the top of the screen is more than one line, let's not skip it yet
+            // Let's set a skip flag to smoothly scroll the top of the screen.
+            //
+            if (SavedMenuOption->Skip > 1) {
+              if (SavedMenuOption == NextMenuOption) {
+                SkipValue = 0;
+              } else {
+                SkipValue++;
+              }
+            } else {
+              SkipValue   = 0;
+              TopOfScreen = TopOfScreen->ForwardLink;
+            }
+          } while (SavedMenuOption->Skip == 0);
+
+          Repaint       = TRUE;
+          OldSkipValue  = SkipValue;
+        }
+
+        MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
+
+        UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
+
+      } else {
+        SavedMenuOption = MenuOption;
+        MenuOption      = MENU_OPTION_FROM_LINK (NewPos);
+        if (!IsSelectable (MenuOption)) {
+          //
+          // If we are at the end of the list and sitting on a text op, we need to more forward
+          //
+          ScreenOperation = UiUp;
+          ControlFlag     = CfScreenOperation;
+          break;
+        }
+
+        MenuOption = SavedMenuOption;
+        //
+        // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
+        //
+        AdjustDateAndTimePosition (TRUE, &NewPos);
+      }
+      break;
+
+    case CfUiSave:
+      ControlFlag = CfCheckSelection;
+
+      //
+      // Submit the form
+      //
+      Status = SubmitForm (Selection->FormSet, Selection->Form);
+
+      if (!EFI_ERROR (Status)) {
+        UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
+        UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE);
+      } else {
+        do {
+          CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveFailed, gPressEnter, gEmptyString);
+        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+
+        Repaint = TRUE;
+        NewLine = TRUE;
+      }
+      break;
+
+    case CfUiDefault:
+      ControlFlag = CfCheckSelection;
+
+      Status = ExtractFormDefault (Selection->FormSet, Selection->Form, DefaultId);
+
+      if (!EFI_ERROR (Status)) {
+        Selection->Action = UI_ACTION_REFRESH_FORM;
+
+        //
+        // Show NV update flag on status bar
+        //
+        gNvUpdateRequired = TRUE;
+      }
+      break;
+
+    case CfUiNoOperation:
+      ControlFlag = CfCheckSelection;
+      break;
+
+    case CfExit:
+      UiFreeRefreshList ();
+
+      gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+      gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);
+      gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+      gST->ConOut->OutputString (gST->ConOut, L"\n");
+
+      return EFI_SUCCESS;
+
+    default:
+      break;
+    }
+  }
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h
new file mode 100644 (file)
index 0000000..a5b7076
--- /dev/null
@@ -0,0 +1,478 @@
+/** @file
+
+Copyright (c) 2004 - 2007, Intel Corporation
+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.
+
+Module Name:
+
+  Ui.h
+
+Abstract:
+
+  Head file UI
+
+Revision History
+
+
+**/
+
+#ifndef _UI_H
+#define _UI_H
+
+//@MT:#include "Tiano.h"
+//@MT:#include "EfiDriverLib.h"
+#include "Setup.h"
+//@MT:#include "GraphicsLib.h"
+//@MT:#include "EfiPrintLib.h"
+
+//
+// Globals
+//
+#define REGULAR_NUMERIC 0
+#define TIME_NUMERIC    1
+#define DATE_NUMERIC    2
+
+#define SUBTITLE_INDENT  2
+
+typedef enum {
+  UiNoOperation,
+  UiDefault,
+  UiSelect,
+  UiUp,
+  UiDown,
+  UiLeft,
+  UiRight,
+  UiReset,
+  UiSave,
+  UiPrevious,
+  UiPageUp,
+  UiPageDown,
+  UiMaxOperation
+} UI_SCREEN_OPERATION;
+
+typedef enum {
+  CfInitialization,
+  CfCheckSelection,
+  CfRepaint,
+  CfRefreshHighLight,
+  CfUpdateHelpString,
+  CfPrepareToReadKey,
+  CfReadKey,
+  CfScreenOperation,
+  CfUiPrevious,
+  CfUiSelect,
+  CfUiReset,
+  CfUiLeft,
+  CfUiRight,
+  CfUiUp,
+  CfUiPageUp,
+  CfUiPageDown,
+  CfUiDown,
+  CfUiSave,
+  CfUiDefault,
+  CfUiNoOperation,
+  CfExit,
+  CfMaxControlFlag
+} UI_CONTROL_FLAG;
+
+#define UI_ACTION_NONE               0
+#define UI_ACTION_REFRESH_FORM       1
+#define UI_ACTION_REFRESH_FORMSET    2
+#define UI_ACTION_EXIT               3
+
+typedef struct {
+  EFI_HII_HANDLE  Handle;
+
+  //
+  // Target formset/form/Question information
+  //
+  EFI_GUID        FormSetGuid;
+  UINT16          FormId;
+  UINT16          QuestionId;
+
+  UINTN           TopRow;
+  UINTN           BottomRow;
+  UINTN           PromptCol;
+  UINTN           OptionCol;
+  UINTN           CurrentRow;
+
+  //
+  // Ation for Browser to taken:
+  //   UI_ACTION_NONE            - navigation inside a form
+  //   UI_ACTION_REFRESH_FORM    - re-evaluate expressions and repaint form
+  //   UI_ACTION_REFRESH_FORMSET - re-parse formset IFR binary
+  //
+  UINTN           Action;
+
+  //
+  // Current selected fomset/form/Question
+  //
+  FORM_BROWSER_FORMSET    *FormSet;
+  FORM_BROWSER_FORM       *Form;
+  FORM_BROWSER_STATEMENT  *Statement;
+} UI_MENU_SELECTION;
+
+#define UI_MENU_OPTION_SIGNATURE  EFI_SIGNATURE_32 ('u', 'i', 'm', 'm')
+#define UI_MENU_LIST_SIGNATURE    EFI_SIGNATURE_32 ('u', 'i', 'm', 'l')
+
+typedef struct {
+  UINTN                   Signature;
+  LIST_ENTRY              Link;
+
+  EFI_HII_HANDLE          Handle;
+  FORM_BROWSER_STATEMENT  *ThisTag;
+  UINT16                  EntryNumber;
+
+  UINTN                   Row;
+  UINTN                   Col;
+  UINTN                   OptCol;
+  CHAR16                  *Description;
+  UINTN                   Skip;           // Number of lines
+
+  //
+  // Display item sequence for date/time
+  //  Date:      Month/Day/Year
+  //  Sequence:  0     1   2
+  //
+  //  Time:      Hour : Minute : Second
+  //  Sequence:  0      1        2
+  //
+  //
+  UINTN                   Sequence;
+
+  BOOLEAN                 GrayOut;
+  BOOLEAN                 ReadOnly;
+} UI_MENU_OPTION;
+
+#define MENU_OPTION_FROM_LINK(a)  CR (a, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE)
+
+typedef struct {
+  UINTN           Signature;
+  LIST_ENTRY      MenuLink;
+
+  UINT16          FormId;
+  UINT16          QuestionId;
+} UI_MENU_LIST;
+
+typedef struct _MENU_REFRESH_ENTRY {
+  struct _MENU_REFRESH_ENTRY  *Next;
+  UI_MENU_OPTION              *MenuOption;  // Describes the entry needing an update
+  UI_MENU_SELECTION           *Selection;
+  UINTN                       CurrentColumn;
+  UINTN                       CurrentRow;
+  UINTN                       CurrentAttribute;
+} MENU_REFRESH_ENTRY;
+
+typedef struct {
+  UINT16              ScanCode;
+  UI_SCREEN_OPERATION ScreenOperation;
+} SCAN_CODE_TO_SCREEN_OPERATION;
+
+typedef struct {
+  UI_SCREEN_OPERATION ScreenOperation;
+  UI_CONTROL_FLAG     ControlFlag;
+} SCREEN_OPERATION_T0_CONTROL_FLAG;
+
+
+extern LIST_ENTRY          gMenuList;
+extern MENU_REFRESH_ENTRY  *gMenuRefreshHead;
+extern UI_MENU_SELECTION   *gCurrentSelection;
+
+//
+// Global Functions
+//
+VOID
+UiInitMenu (
+  VOID
+  )
+;
+
+VOID
+UiInitMenuList (
+  VOID
+  )
+;
+
+VOID
+UiRemoveMenuListEntry (
+  OUT UI_MENU_SELECTION  *Selection
+  )
+;
+
+VOID
+UiFreeMenuList (
+  VOID
+  )
+;
+
+VOID
+UiAddMenuListEntry (
+  IN UI_MENU_SELECTION            *Selection
+  )
+;
+
+VOID
+UiFreeMenu (
+  VOID
+  )
+;
+
+VOID
+UiAddMenuOption (
+  IN CHAR16                  *String,
+  IN EFI_HII_HANDLE          Handle,
+  IN FORM_BROWSER_STATEMENT  *Statement,
+  IN UINT16                  NumberOfLines,
+  IN UINT16                  MenuItemCount
+  )
+;
+
+EFI_STATUS
+UiDisplayMenu (
+  IN OUT UI_MENU_SELECTION           *Selection
+  )
+;
+
+VOID
+FreeBrowserStrings (
+  VOID
+  )
+;
+
+EFI_STATUS
+SetupBrowser (
+  IN OUT UI_MENU_SELECTION    *Selection
+  )
+;
+
+VOID
+ValueToString (
+  IN CHAR16   *Buffer,
+  IN BOOLEAN  Comma,
+  IN INT64    v
+  )
+;
+
+EFI_STATUS
+UiIntToString (
+  IN UINTN      num,
+  IN OUT CHAR16 *str,
+  IN UINT16     size
+  )
+;
+
+VOID
+SetUnicodeMem (
+  IN VOID   *Buffer,
+  IN UINTN  Size,
+  IN CHAR16 Value
+  )
+;
+
+EFI_STATUS
+UiWaitForSingleEvent (
+  IN EFI_EVENT                Event,
+  IN UINT64                   Timeout, OPTIONAL
+  IN UINT8                    RefreshInterval OPTIONAL
+  )
+;
+
+VOID
+CreatePopUp (
+  IN  UINTN                       ScreenWidth,
+  IN  UINTN                       NumberOfLines,
+  IN  CHAR16                      *ArrayOfStrings,
+  ...
+  )
+;
+
+EFI_STATUS
+ReadString (
+  IN  UI_MENU_OPTION              *MenuOption,
+  IN  CHAR16                      *Prompt,
+  OUT CHAR16                      *StringPtr
+  )
+;
+
+EFI_STATUS
+GetSelectionInputPopUp (
+  IN  UI_MENU_SELECTION           *Selection,
+  IN  UI_MENU_OPTION              *MenuOption
+  )
+;
+
+EFI_STATUS
+GetNumericInput (
+  IN  UI_MENU_SELECTION           *Selection,
+  IN  UI_MENU_OPTION              *MenuOption
+  )
+;
+
+VOID
+UpdateStatusBar (
+  IN  UINTN                       MessageType,
+  IN  UINT8                       Flags,
+  IN  BOOLEAN                     State
+  )
+;
+
+EFI_STATUS
+ProcessQuestionConfig (
+  IN  UI_MENU_SELECTION       *Selection,
+  IN  FORM_BROWSER_STATEMENT  *Question
+  )
+;
+
+EFI_STATUS
+PrintFormattedNumber (
+  IN FORM_BROWSER_STATEMENT   *Question,
+  IN OUT CHAR16               *FormattedNumber,
+  IN UINTN                    BufferSize
+  )
+;
+
+QUESTION_OPTION *
+ValueToOption (
+  IN FORM_BROWSER_STATEMENT   *Question,
+  IN EFI_HII_VALUE            *OptionValue
+  )
+;
+
+EFI_STATUS
+ProcessOptions (
+  IN  UI_MENU_SELECTION           *Selection,
+  IN  UI_MENU_OPTION              *MenuOption,
+  IN  BOOLEAN                     Selected,
+  OUT CHAR16                      **OptionString
+  )
+;
+
+VOID
+ProcessHelpString (
+  IN  CHAR16                      *StringPtr,
+  OUT CHAR16                      **FormattedString,
+  IN  UINTN                       RowCount
+  )
+;
+
+VOID
+UpdateKeyHelp (
+  IN  UI_MENU_OPTION              *MenuOption,
+  IN  BOOLEAN                     Selected
+  )
+;
+
+VOID
+ClearLines (
+  UINTN                                       LeftColumn,
+  UINTN                                       RightColumn,
+  UINTN                                       TopRow,
+  UINTN                                       BottomRow,
+  UINTN                                       TextAttribute
+  )
+;
+
+UINTN
+GetStringWidth (
+  CHAR16                                      *String
+  )
+;
+
+UINT16
+GetLineByWidth (
+  IN      CHAR16                      *InputString,
+  IN      UINT16                      LineWidth,
+  IN OUT  UINTN                       *Index,
+  OUT     CHAR16                      **OutputString
+  )
+;
+
+UINT16
+GetWidth (
+  IN FORM_BROWSER_STATEMENT        *Statement,
+  IN EFI_HII_HANDLE                 Handle
+  )
+;
+
+VOID
+NewStrCat (
+  CHAR16                                      *Destination,
+  CHAR16                                      *Source
+  )
+;
+
+EFI_STATUS
+WaitForKeyStroke (
+  OUT  EFI_INPUT_KEY           *Key
+  )
+;
+
+VOID
+ResetScopeStack (
+  VOID
+  )
+;
+
+EFI_STATUS
+PushScope (
+  IN UINT8   Operand
+  )
+;
+
+EFI_STATUS
+PopScope (
+  OUT UINT8     *Operand
+  )
+;
+
+FORM_BROWSER_FORM *
+IdToForm (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  IN UINT16                FormId
+)
+;
+
+FORM_BROWSER_STATEMENT *
+IdToQuestion (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  IN FORM_BROWSER_FORM     *Form,
+  IN UINT16                QuestionId
+  )
+;
+
+FORM_EXPRESSION *
+IdToExpression (
+  IN FORM_BROWSER_FORM  *Form,
+  IN UINT8              RuleId
+  )
+;
+
+VOID
+ExtendValueToU64 (
+  IN  EFI_HII_VALUE   *Value
+  )
+;
+
+INTN
+CompareHiiValue (
+  IN  EFI_HII_VALUE   *Value1,
+  IN  EFI_HII_VALUE   *Value2,
+  IN  EFI_HII_HANDLE  HiiHandle OPTIONAL
+  )
+;
+
+EFI_STATUS
+EvaluateExpression (
+  IN FORM_BROWSER_FORMSET  *FormSet,
+  IN FORM_BROWSER_FORM     *Form,
+  IN OUT FORM_EXPRESSION   *Expression
+  )
+;
+
+#endif // _UI_H
index faa570d4358abd277c6f4829738b3759f8fa8ee7..0e4569ca7ef4094b2425cc9edc496ac1fdeaccec 100644 (file)
@@ -77,8 +77,8 @@
   DevicePathLib\r
   DebugLib\r
   PrintLib\r
-  FrameworkHiiLib\r
-  FrameworkIfrSupportLib\r
+  HiiLib\r
+  IfrSupportLib\r
   NetLib\r
 \r
 [Protocols]\r
@@ -88,8 +88,8 @@
   gEfiExtScsiPassThruProtocolGuid\r
   gEfiDevicePathProtocolGuid\r
   gEfiTcp4ServiceBindingProtocolGuid\r
-  gEfiFormCallbackProtocolGuid\r
-  gEfiFormBrowserProtocolGuid\r
+  gEfiHiiDatabaseProtocolGuid\r
+  gEfiHiiConfigAccessProtocolGuid\r
   gEfiPciIoProtocolGuid\r
   gEfiAcpiSupportProtocolGuid\r
   gEfiDhcp4ProtocolGuid\r
index 6f4b170a60b304206157b06d4c04270d5f1e94be..e6ea8b5400331d2273eba26ba895ff377aa70b2c 100644 (file)
@@ -119,6 +119,7 @@ Returns:
 {\r
   EFI_STATUS                Status;\r
   ISCSI_SESSION             *Session;\r
+  ISCSI_SESSION_CONFIG_DATA *ConfigData;\r
   ISCSI_CHAP_AUTH_DATA      *AuthData;\r
   CHAR8                     *Value;\r
   UINT8                     *Data;\r
@@ -136,6 +137,7 @@ Returns:
   ASSERT (Conn->RspQue.BufNum != 0);\r
 \r
   Session     = Conn->Session;\r
+  ConfigData  = &Session->ConfigData;\r
   AuthData    = &Session->AuthData;\r
 \r
   Len         = Conn->RspQue.BufSize;\r
@@ -151,7 +153,7 @@ Returns:
   //\r
   // Build the key-value list from the data segment of the Login Response.\r
   //\r
-  KeyValueList = IScsiBuildKeyValueList ((CHAR8*)Data, Len);\r
+  KeyValueList = IScsiBuildKeyValueList (Data, Len);\r
   if (KeyValueList == NULL) {\r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto ON_EXIT;\r
@@ -317,6 +319,7 @@ Returns:
   EFI_STATUS                Status;\r
   ISCSI_SESSION             *Session;\r
   ISCSI_LOGIN_REQUEST       *LoginReq;\r
+  ISCSI_SESSION_CONFIG_DATA *ConfigData;\r
   ISCSI_CHAP_AUTH_DATA      *AuthData;\r
   CHAR8                     *Value;\r
   CHAR8                     ValueStr[256];\r
@@ -328,6 +331,7 @@ Returns:
   ASSERT (Conn->CurrentStage == ISCSI_SECURITY_NEGOTIATION);\r
 \r
   Session     = Conn->Session;\r
+  ConfigData  = &Session->ConfigData;\r
   AuthData    = &Session->AuthData;\r
   LoginReq    = (ISCSI_LOGIN_REQUEST *) NetbufGetByte (Pdu, 0, 0);\r
   Status      = EFI_SUCCESS;\r
@@ -383,7 +387,7 @@ Returns:
     //\r
     // CHAP_N=<N>\r
     //\r
-    IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_NAME, (CHAR8 *) &AuthData->AuthConfig.CHAPName);\r
+    IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_NAME, (UINT8 *) &AuthData->AuthConfig.CHAPName);\r
     //\r
     // CHAP_R=<R>\r
     //\r
index 4a152913e2a1116b1c94fd2d242b878ee177a5ce..130cccf96f4f5d6ad06b5869a58b0f4408a3e7f4 100644 (file)
@@ -22,7 +22,7 @@ Abstract:
 \r
 #define ISCSI_CHAP_AUTH_INFO_GUID \\r
   { \\r
-    0x786ec0ac, 0x65ae, 0x4d1b, 0xb1, 0x37, 0xd, 0x11, 0xa, 0x48, 0x37, 0x97 \\r
+    0x786ec0ac, 0x65ae, 0x4d1b, {0xb1, 0x37, 0xd, 0x11, 0xa, 0x48, 0x37, 0x97} \\r
   }\r
 \r
 extern EFI_GUID mIScsiCHAPAuthInfoGuid;\r
index a8ef2c79b61982efab991aeaaf86d02c99f49770..67dcb8b2ae17bc32fcde482499e999ea1523bed1 100644 (file)
@@ -22,6 +22,7 @@ Abstract:
 EFI_GUID        mVendorGuid             = ISCSI_CONFIG_GUID;\r
 BOOLEAN         mIScsiDeviceListUpdated = FALSE;\r
 UINTN           mNumberOfIScsiDevices   = 0;\r
+ISCSI_FORM_CALLBACK_INFO  *mCallbackInfo;\r
 \r
 NET_LIST_ENTRY  mIScsiConfigFormList = {\r
   &mIScsiConfigFormList,\r
@@ -74,21 +75,9 @@ Returns:
 \r
 --*/\r
 {\r
-  EFI_FORM_BROWSER_PROTOCOL *FormBrowser;\r
-  EFI_STATUS                Status;\r
   EFI_INPUT_KEY             Key;\r
-  CHAR16                    Buffer[10];\r
-\r
-  Status = gBS->LocateProtocol (\r
-                  &gEfiFormBrowserProtocolGuid,\r
-                  NULL,\r
-                  (VOID **)&FormBrowser\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return ;\r
-  }\r
 \r
-  FormBrowser->CreatePopUp (1, TRUE, 10, Buffer, &Key, Warning);\r
+  IfrLibCreatePopUp (1, &Key, Warning);\r
 }\r
 \r
 EFI_STATUS\r
@@ -335,42 +324,47 @@ Returns:
   IScsiAsciiStrToUnicodeStr (AuthConfigData->ReverseCHAPSecret, IfrNvData->ReverseCHAPSecret);\r
 }\r
 \r
+\r
 EFI_STATUS\r
 EFIAPI\r
-IScsiFormNvRead (\r
-  IN     EFI_FORM_CALLBACK_PROTOCOL    * This,\r
-  IN     CHAR16                        *VariableName,\r
-  IN     EFI_GUID                      * VendorGuid,\r
-  OUT    UINT32                        *Attributes OPTIONAL,\r
-  IN OUT UINTN                         *DataSize,\r
-  OUT    VOID                          *Buffer\r
+IScsiFormExtractConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Request,\r
+  OUT EFI_STRING                             *Progress,\r
+  OUT EFI_STRING                             *Results\r
   )\r
 /*++\r
 \r
-Routine Description:\r
-\r
-  NV read function for the iSCSI form callback protocol.\r
-\r
-Arguments:\r
-\r
-  This         - The EFI form callback protocol instance.\r
-  VariableName - Name of the variable to read.\r
-  VendorGuid   - Guid of the variable to read.\r
-  Attributes   - The storage to get the attributes of the variable.\r
-  DataSize     - The size of the buffer to store the variable.\r
-  Buffer       - The buffer to store the variable to read.\r
-\r
-Returns:\r
-\r
-  EFI_SUCCESS          - The variable is read.\r
-  EFI_BUFFER_TOO_SMALL - The buffer provided is too small to hold the variable.\r
+  Routine Description:\r
+    This function allows a caller to extract the current configuration for one\r
+    or more named elements from the target driver.\r
+\r
+  Arguments:\r
+    This       - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+    Request    - A null-terminated Unicode string in <ConfigRequest> format.\r
+    Progress   - On return, points to a character in the Request string.\r
+                 Points to the string's null terminator if request was successful.\r
+                 Points to the most recent '&' before the first failing name/value\r
+                 pair (or the beginning of the string if the failure is in the\r
+                 first name/value pair) if the request was not successful.\r
+    Results    - A null-terminated Unicode string in <ConfigAltResp> format which\r
+                 has all values filled in for the names in the Request string.\r
+                 String to be allocated by the called function.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The Results is filled with the requested values.\r
+    EFI_OUT_OF_RESOURCES  - Not enough memory to store the results.\r
+    EFI_INVALID_PARAMETER - Request is NULL, illegal syntax, or unknown name.\r
+    EFI_NOT_FOUND         - Routing data doesn't match any storage in this driver.\r
 \r
 --*/\r
 {\r
-  EFI_STATUS              Status;\r
-  CHAR8                   InitiatorName[ISCSI_NAME_IFR_MAX_SIZE];\r
-  UINTN                   BufferSize;\r
-  ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
+  EFI_STATUS                       Status;\r
+  CHAR8                            InitiatorName[ISCSI_NAME_IFR_MAX_SIZE];\r
+  UINTN                            BufferSize;\r
+  ISCSI_CONFIG_IFR_NVDATA          *IfrNvData;\r
+  ISCSI_FORM_CALLBACK_INFO         *Private;\r
+  EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;\r
 \r
   if (!mIScsiDeviceListUpdated) {\r
     //\r
@@ -380,9 +374,14 @@ Returns:
     mIScsiDeviceListUpdated = TRUE;\r
   }\r
 \r
-  IfrNvData   = (ISCSI_CONFIG_IFR_NVDATA *) Buffer;\r
-  BufferSize  = ISCSI_NAME_IFR_MAX_SIZE;\r
+  Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
+  IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
+  ASSERT (IfrNvData != NULL);\r
+  if (Private->Current != NULL) {\r
+    IScsiConvertDeviceConfigDataToIfrNvData (Private->Current, IfrNvData);\r
+  }\r
 \r
+  BufferSize  = ISCSI_NAME_IFR_MAX_SIZE;\r
   Status      = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);\r
   if (EFI_ERROR (Status)) {\r
     IfrNvData->InitiatorName[0] = L'\0';\r
@@ -390,37 +389,82 @@ Returns:
     IScsiAsciiStrToUnicodeStr (InitiatorName, IfrNvData->InitiatorName);\r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  //\r
+  // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
+  //\r
+  HiiConfigRouting = Private->ConfigRouting;\r
+  BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
+  Status = HiiConfigRouting->BlockToConfig (\r
+                               HiiConfigRouting,\r
+                               Request,\r
+                               (UINT8 *) IfrNvData,\r
+                               BufferSize,\r
+                               Results,\r
+                               Progress\r
+                               );\r
+  NetFreePool (IfrNvData);\r
+  return Status;\r
 }\r
 \r
 EFI_STATUS\r
 EFIAPI\r
-IScsiFormCallback (\r
-  IN EFI_FORM_CALLBACK_PROTOCOL       *This,\r
-  IN UINT16                           KeyValue,\r
-  IN EFI_IFR_DATA_ARRAY               *Data,\r
-  OUT EFI_HII_CALLBACK_PACKET         **Packet\r
+IScsiFormRouteConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Configuration,\r
+  OUT EFI_STRING                             *Progress\r
   )\r
 /*++\r
 \r
-Routine Description:\r
+  Routine Description:\r
+    This function processes the results of changes in configuration.\r
 \r
-  The form callback function for iSCSI form callback protocol, it processes\r
-  the events tiggered in the UI and take some operations to update the form,\r
-  store the data, etc.\r
+  Arguments:\r
+    This          - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+    Configuration - A null-terminated Unicode string in <ConfigResp> format.\r
+    Progress      - A pointer to a string filled in with the offset of the most\r
+                    recent '&' before the first failing name/value pair (or the\r
+                    beginning of the string if the failure is in the first\r
+                    name/value pair) or the terminating NULL if all was successful.\r
 \r
-Arguments:\r
+  Returns:\r
+    EFI_SUCCESS           - The Results is processed successfully.\r
+    EFI_INVALID_PARAMETER - Configuration is NULL.\r
+    EFI_NOT_FOUND         - Routing data doesn't match any storage in this driver.\r
 \r
-  This     - The EFI form callback protocol instance.\r
-  KeyValue - A unique value which is sent to the original exporting driver so that it\r
-             can identify the type of data to expect.  The format of the data tends to\r
-             vary based on the op-code that geerated the callback.\r
-  Data     - A pointer to the data being sent to the original exporting driver.\r
+--*/\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
 \r
-Returns:\r
+EFI_STATUS\r
+EFIAPI\r
+IScsiFormCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        KeyValue,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    This function processes the results of changes in configuration.\r
 \r
-  EFI_SUCCESS           - The data is valid and the correspondance operation is done.\r
-  EFI_INVALID_PARAMETER - The data is invalid.\r
+  Arguments:\r
+    This          - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+    Action        - Specifies the type of action taken by the browser.\r
+    QuestionId    - A unique value which is sent to the original exporting driver\r
+                    so that it can identify the type of data to expect.\r
+    Type          - The type of value for the question.\r
+    Value         - A pointer to the data being sent to the original exporting driver.\r
+    ActionRequest - On return, points to the action requested by the callback function.\r
+\r
+  Returns:\r
+    EFI_SUCCESS          - The callback successfully handled the action.\r
+    EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.\r
+    EFI_DEVICE_ERROR     - The variable could not be saved.\r
+    EFI_UNSUPPORTED      - The specified Action is not supported by the callback.\r
 \r
 --*/\r
 {\r
@@ -440,8 +484,18 @@ Returns:
   EFI_STATUS                Status;\r
 \r
   Private   = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
-  IfrNvData = (ISCSI_CONFIG_IFR_NVDATA *) Data->NvRamMap;\r
-  Status    = EFI_SUCCESS;\r
+\r
+  //\r
+  // Retrive uncommitted data from Browser\r
+  //\r
+  BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
+  IfrNvData = AllocateZeroPool (BufferSize);\r
+  ASSERT (IfrNvData != NULL);\r
+  Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) IfrNvData);\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePool (IfrNvData);\r
+    return Status;\r
+  }\r
 \r
   switch (KeyValue) {\r
   case KEY_INITIATOR_NAME:\r
@@ -633,7 +687,7 @@ Returns:
           BufferSize,\r
           &Private->Current->AuthConfigData\r
           );\r
-\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
     break;\r
 \r
   default:\r
@@ -644,16 +698,9 @@ Returns:
       ConfigFormEntry = IScsiGetConfigFormEntryByIndex ((UINT32) (KeyValue - KEY_DEVICE_ENTRY_BASE));\r
       ASSERT (ConfigFormEntry != NULL);\r
 \r
-      UnicodeSPrint (PortString, 128, L"Port %s", ConfigFormEntry->MacString);\r
+      UnicodeSPrint (PortString, (UINTN) 128, L"Port %s", ConfigFormEntry->MacString);\r
       DeviceFormTitleToken = (STRING_REF) STR_ISCSI_DEVICE_FORM_TITLE;\r
-\r
-      Private->Hii->NewString (\r
-                      Private->Hii,\r
-                      NULL,\r
-                      Private->RegisteredHandle,\r
-                      &DeviceFormTitleToken,\r
-                      PortString\r
-                      );\r
+      IfrLibSetString (Private->RegisteredHandle, DeviceFormTitleToken, PortString);\r
 \r
       IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry, IfrNvData);\r
 \r
@@ -663,9 +710,19 @@ Returns:
     break;\r
   }\r
 \r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Pass changed uncommitted data back to Form Browser\r
+    //\r
+    BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
+    Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);\r
+  }\r
+\r
+  NetFreePool (IfrNvData);\r
   return Status;\r
 }\r
 \r
+\r
 EFI_STATUS\r
 IScsiConfigUpdateForm (\r
   IN EFI_HANDLE  DriverBindingHandle,\r
@@ -695,28 +752,13 @@ Returns:
   NET_LIST_ENTRY              *Entry;\r
   ISCSI_CONFIG_FORM_ENTRY     *ConfigFormEntry;\r
   BOOLEAN                     EntryExisted;\r
-  EFI_HII_UPDATE_DATA         *UpdateData;\r
   EFI_STATUS                  Status;\r
-  EFI_FORM_CALLBACK_PROTOCOL  *Callback;\r
-  ISCSI_FORM_CALLBACK_INFO    *CallbackInfo;\r
+  EFI_HII_UPDATE_DATA         UpdateData;\r
   EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
   CHAR16                      PortString[128];\r
   UINT16                      FormIndex;\r
   UINTN                       BufferSize;\r
 \r
-  //\r
-  // Get the EFI_FORM_CALLBACK_PROTOCOL.\r
-  //\r
-  Status = gBS->HandleProtocol (\r
-                  DriverBindingHandle,\r
-                  &gEfiFormCallbackProtocolGuid,\r
-                  (VOID **)&Callback\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  CallbackInfo    = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (Callback);\r
 \r
   ConfigFormEntry = NULL;\r
   EntryExisted    = FALSE;\r
@@ -790,25 +832,13 @@ Returns:
       // Compose the Port string and create a new STRING_REF.\r
       //\r
       UnicodeSPrint (PortString, 128, L"Port %s", ConfigFormEntry->MacString);\r
-      CallbackInfo->Hii->NewString (\r
-                          CallbackInfo->Hii,\r
-                          NULL,\r
-                          CallbackInfo->RegisteredHandle,\r
-                          &ConfigFormEntry->PortTitleToken,\r
-                          PortString\r
-                          );\r
+      IfrLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleToken, PortString);\r
 \r
       //\r
       // Compose the help string of this port and create a new STRING_REF.\r
       //\r
       UnicodeSPrint (PortString, 128, L"Set the iSCSI parameters on port %s", ConfigFormEntry->MacString);\r
-      CallbackInfo->Hii->NewString (\r
-                          CallbackInfo->Hii,\r
-                          NULL,\r
-                          CallbackInfo->RegisteredHandle,\r
-                          &ConfigFormEntry->PortTitleHelpToken,\r
-                          PortString\r
-                          );\r
+      IfrLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleHelpToken, PortString);\r
 \r
       NetListInsertTail (&mIScsiConfigFormList, &ConfigFormEntry->Link);\r
       mNumberOfIScsiDevices++;\r
@@ -823,37 +853,11 @@ Returns:
   //\r
   // Allocate space for creation of Buffer\r
   //\r
-  UpdateData = (EFI_HII_UPDATE_DATA *) NetAllocatePool (0x1000);\r
-  NetZeroMem (UpdateData, 0x1000);\r
-\r
-  //\r
-  // Flag update pending in FormSet\r
-  //\r
-  UpdateData->FormSetUpdate = TRUE;\r
-\r
-  //\r
-  // Register CallbackHandle data for FormSet\r
-  //\r
-  UpdateData->FormCallbackHandle  = (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackInfo->CallbackHandle;\r
-  UpdateData->FormUpdate          = FALSE;\r
-  UpdateData->FormTitle           = 0;\r
-\r
-  //\r
-  // first of all, remove all the forms.\r
-  //\r
-  UpdateData->DataCount = 0xFF;\r
-\r
-  CallbackInfo->Hii->UpdateForm (\r
-                      CallbackInfo->Hii,\r
-                      CallbackInfo->RegisteredHandle,\r
-                      (EFI_FORM_LABEL) DEVICE_ENTRY_LABEL,\r
-                      FALSE,\r
-                      UpdateData\r
-                      );\r
-\r
-  UpdateData->DataCount = 1;\r
-  FormIndex             = 0;\r
+  UpdateData.BufferSize = 0x1000;\r
+  UpdateData.Data = NetAllocateZeroPool (0x1000);\r
+  UpdateData.Offset = 0;\r
 \r
+  FormIndex = 0;\r
   NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
     ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
 \r
@@ -861,23 +865,24 @@ Returns:
       FORMID_DEVICE_FORM,\r
       ConfigFormEntry->PortTitleToken,\r
       ConfigFormEntry->PortTitleHelpToken,\r
-      EFI_IFR_FLAG_INTERACTIVE,\r
-      (UINT16) (KEY_DEVICE_ENTRY_BASE + FormIndex),\r
-      &UpdateData->Data\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      KEY_DEVICE_ENTRY_BASE + FormIndex,\r
+      &UpdateData\r
       );\r
 \r
-    CallbackInfo->Hii->UpdateForm (\r
-                        CallbackInfo->Hii,\r
-                        CallbackInfo->RegisteredHandle,\r
-                        (EFI_FORM_LABEL) DEVICE_ENTRY_LABEL,\r
-                        TRUE,\r
-                        UpdateData\r
-                        );\r
-\r
     FormIndex++;\r
   }\r
 \r
-  NetFreePool (UpdateData);\r
+  IfrLibUpdateForm (\r
+    mCallbackInfo->RegisteredHandle,\r
+    &mVendorGuid,\r
+    FORMID_MAIN_FORM,\r
+    DEVICE_ENTRY_LABEL,\r
+    FALSE,\r
+    &UpdateData\r
+    );\r
+\r
+  NetFreePool (UpdateData.Data);\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -903,17 +908,14 @@ Returns:
 \r
 --*/\r
 {\r
-  EFI_STATUS                Status;\r
-  EFI_HII_PROTOCOL          *Hii;\r
-  EFI_HII_PACKAGES          *PackageList;\r
-  EFI_HII_HANDLE            HiiHandle;\r
-  EFI_HII_UPDATE_DATA       *UpdateData;\r
-  ISCSI_FORM_CALLBACK_INFO  *CallbackInfo;\r
-  EFI_GUID                  StringPackGuid = ISCSI_CONFIG_GUID;\r
-\r
-  Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, (VOID **)&Hii);\r
+  EFI_STATUS                  Status;\r
+  EFI_HII_DATABASE_PROTOCOL   *HiiDatabase;\r
+  EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+  ISCSI_FORM_CALLBACK_INFO    *CallbackInfo;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, &HiiDatabase);\r
   if (EFI_ERROR (Status)) {\r
-    return Status;;\r
+    return Status;\r
   }\r
 \r
   CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) NetAllocatePool (sizeof (ISCSI_FORM_CALLBACK_INFO));\r
@@ -922,59 +924,55 @@ Returns:
   }\r
 \r
   CallbackInfo->Signature             = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;\r
-  CallbackInfo->Hii                   = Hii;\r
+  CallbackInfo->HiiDatabase = HiiDatabase;\r
   CallbackInfo->Current               = NULL;\r
 \r
-  CallbackInfo->FormCallback.NvRead   = IScsiFormNvRead;\r
-  CallbackInfo->FormCallback.NvWrite  = NULL;\r
-  CallbackInfo->FormCallback.Callback = IScsiFormCallback;\r
+  CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;\r
+  CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;\r
+  CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;\r
 \r
+  Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, &CallbackInfo->ConfigRouting);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Create driver handle used by HII database\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&CallbackInfo->DriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  \r
   //\r
-  // Install protocol interface\r
+  // Install Config Access protocol to driver handle\r
   //\r
   Status = gBS->InstallProtocolInterface (\r
-                  &DriverBindingHandle,\r
-                  &gEfiFormCallbackProtocolGuid,\r
+                  &CallbackInfo->DriverHandle,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
                   EFI_NATIVE_INTERFACE,\r
-                  &CallbackInfo->FormCallback\r
+                  &CallbackInfo->ConfigAccess\r
                   );\r
-\r
   ASSERT_EFI_ERROR (Status);\r
-\r
-  CallbackInfo->CallbackHandle  = DriverBindingHandle;\r
-  PackageList                   = PreparePackages (2, &StringPackGuid, iSCSIStrings, IScsiConfigDxeBin);\r
-  Status                        = Hii->NewPack (Hii, PackageList, &HiiHandle);\r
-  NetFreePool (PackageList);\r
-\r
-  CallbackInfo->RegisteredHandle = HiiHandle;\r
-\r
+  \r
   //\r
-  // Allocate space for creation of Buffer\r
+  // Publish our HII data\r
   //\r
-  UpdateData = (EFI_HII_UPDATE_DATA *) NetAllocatePool (0x1000);\r
-  ASSERT (UpdateData != NULL);\r
-  if (UpdateData == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+  PackageList = PreparePackageList (2, &mVendorGuid, iSCSIStrings, IScsiConfigDxeBin);\r
+  ASSERT (PackageList != NULL);\r
+  \r
+  Status = HiiDatabase->NewPackageList (\r
+                           HiiDatabase,\r
+                           PackageList,\r
+                           CallbackInfo->DriverHandle,\r
+                           &CallbackInfo->RegisteredHandle\r
+                           );\r
+  NetFreePool (PackageList);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
   }\r
 \r
-  NetZeroMem (UpdateData, 0x1000);\r
-\r
-  //\r
-  // Flag update pending in FormSet\r
-  //\r
-  UpdateData->FormSetUpdate = TRUE;\r
-\r
-  //\r
-  // Register CallbackHandle data for FormSet\r
-  //\r
-  UpdateData->FormCallbackHandle  = (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackInfo->CallbackHandle;\r
-  UpdateData->FormUpdate          = FALSE;\r
-  UpdateData->FormTitle           = 0;\r
-  UpdateData->DataCount           = 0x1;\r
-\r
-  Hii->UpdateForm (Hii, HiiHandle, (EFI_FORM_LABEL) 0x1000, TRUE, UpdateData);\r
-\r
-  NetFreePool (UpdateData);\r
+  mCallbackInfo = CallbackInfo;\r
 \r
   return Status;\r
 }\r
@@ -1003,11 +1001,6 @@ Returns:
 --*/\r
 {\r
   ISCSI_CONFIG_FORM_ENTRY     *ConfigFormEntry;\r
-  EFI_STATUS                  Status;\r
-  EFI_HII_PROTOCOL            *Hii;\r
-  EFI_HII_UPDATE_DATA         *UpdateData;\r
-  EFI_FORM_CALLBACK_PROTOCOL  *FormCallback;\r
-  ISCSI_FORM_CALLBACK_INFO    *CallbackInfo;\r
 \r
   while (!NetListIsEmpty (&mIScsiConfigFormList)) {\r
     //\r
@@ -1021,54 +1014,25 @@ Returns:
     IScsiConfigUpdateForm (DriverBindingHandle, ConfigFormEntry->Controller, FALSE);\r
   }\r
 \r
-  Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, (VOID **)&Hii);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = gBS->HandleProtocol (DriverBindingHandle, &gEfiFormCallbackProtocolGuid, (VOID **)&FormCallback);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  CallbackInfo = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (FormCallback);\r
-\r
   //\r
-  // remove the form.\r
+  // Remove HII package list\r
   //\r
-  UpdateData = (EFI_HII_UPDATE_DATA *) NetAllocatePool (0x1000);\r
-  ASSERT (UpdateData != NULL);\r
-  if (UpdateData == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  NetZeroMem (UpdateData, 0x1000);\r
-\r
-  UpdateData->FormSetUpdate       = FALSE;\r
-  UpdateData->FormCallbackHandle  = 0;\r
-  UpdateData->FormUpdate          = FALSE;\r
-  UpdateData->FormTitle           = 0;\r
-  UpdateData->DataCount           = 0xFF;\r
-\r
-  Hii->UpdateForm (Hii, CallbackInfo->RegisteredHandle, (EFI_FORM_LABEL) 0x1000, FALSE, UpdateData);\r
-\r
-  NetFreePool (UpdateData);\r
+  mCallbackInfo->HiiDatabase->RemovePackageList (\r
+                                mCallbackInfo->HiiDatabase,\r
+                                mCallbackInfo->RegisteredHandle\r
+                                );\r
 \r
   //\r
-  // Uninstall the EFI_FORM_CALLBACK_PROTOCOL.\r
+  // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
   //\r
   gBS->UninstallProtocolInterface (\r
-        DriverBindingHandle,\r
-        &gEfiFormCallbackProtocolGuid,\r
-        FormCallback\r
+        mCallbackInfo->DriverHandle,\r
+        &gEfiHiiConfigAccessProtocolGuid,\r
+        &mCallbackInfo->ConfigAccess\r
         );\r
+  HiiLibDestroyHiiDriverHandle (mCallbackInfo->DriverHandle);\r
 \r
-  //\r
-  // Remove the package.\r
-  //\r
-  Hii->RemovePack (Hii, CallbackInfo->RegisteredHandle);\r
-\r
-  NetFreePool (CallbackInfo);\r
+  NetFreePool (mCallbackInfo);\r
 \r
   return EFI_SUCCESS;\r
 }\r
index 726b7a2f713d4d28fd8ff63fb5359635fa1ff772..aab488f4a0b9c1c3a0c58e66ee74e2dfc269d49d 100644 (file)
@@ -21,12 +21,17 @@ Abstract:
 #ifndef _ISCSI_CONFIG_H_\r
 #define _ISCSI_CONFIG_H_\r
 \r
-#include <Library/FrameworkHiiLib.h>\r
-#include <Protocol/FrameworkFormBrowser.h>\r
-#include <Protocol/FrameworkFormCallback.h>\r
-#include <Library/FrameworkIfrSupportLib.h>\r
+//#include "Tiano.h"\r
+//#include "EfiDriverLib.h"\r
+//#include "Base.h"\r
+#include <Library/HiiLib.h>\r
+#include <Library/IfrSupportLib.h>\r
 #include <Library/DebugLib.h>\r
 #include <Library/BaseLib.h>\r
+//#include "EfiPrintLib.h"\r
+//#include EFI_PROTOCOL_DEFINITION (Hii)\r
+//#include EFI_PROTOCOL_DEFINITION (FormBrowser)\r
+//#include EFI_PROTOCOL_DEFINITION (FormCallback)\r
 \r
 #include <Library/NetLib.h>\r
 #include "IScsiConfigNVDataStruc.h"\r
@@ -44,7 +49,7 @@ extern UINT8  iSCSIStrings[];
   CR ( \\r
   Callback, \\r
   ISCSI_FORM_CALLBACK_INFO, \\r
-  FormCallback, \\r
+  ConfigAccess, \\r
   ISCSI_FORM_CALLBACK_INFO_SIGNATURE \\r
   )\r
 \r
@@ -74,14 +79,15 @@ typedef struct _ISCSI_CONFIG_FORM_ENTRY {
 } ISCSI_CONFIG_FORM_ENTRY;\r
 \r
 typedef struct _ISCSI_FORM_CALLBACK_INFO {\r
-  UINTN                       Signature;\r
-  EFI_HANDLE                  CallbackHandle;\r
-  EFI_FORM_CALLBACK_PROTOCOL  FormCallback;\r
-  UINT16                      *KeyList;\r
-  VOID                        *FormBuffer;\r
-  EFI_HII_HANDLE              RegisteredHandle;\r
-  EFI_HII_PROTOCOL            *Hii;\r
-  ISCSI_CONFIG_FORM_ENTRY     *Current;\r
+  UINTN                            Signature;\r
+  EFI_HANDLE                       DriverHandle;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL   ConfigAccess;\r
+  EFI_HII_DATABASE_PROTOCOL        *HiiDatabase;\r
+  EFI_HII_CONFIG_ROUTING_PROTOCOL  *ConfigRouting;\r
+  UINT16                           *KeyList;\r
+  VOID                             *FormBuffer;\r
+  EFI_HII_HANDLE                   RegisteredHandle;\r
+  ISCSI_CONFIG_FORM_ENTRY          *Current;\r
 } ISCSI_FORM_CALLBACK_INFO;\r
 \r
 EFI_STATUS\r
index 3df9b18cb13a777363a75cf6f2c5e1aae47c78fa..db89affce28741d5f256d98d7be74389a4606947 100644 (file)
@@ -22,6 +22,8 @@
 #include "IScsiConfigNVDataStruc.h"\r
 #define EFI_NETWORK_DEVICE_CLASS  0x04\r
 \r
+#define LABEL_END                 0xffff\r
+\r
 formset \r
   guid     = ISCSI_CONFIG_GUID,\r
   title    = STRING_TOKEN(STR_ISCSI_CONFIG_FORM_TITLE),\r
@@ -29,8 +31,11 @@ formset
   class    = EFI_NETWORK_DEVICE_CLASS,\r
   subclass = 0x03,\r
 \r
+  varstore ISCSI_CONFIG_IFR_NVDATA,\r
+    name = ISCSI_CONFIG_IFR_NVDATA,\r
+    guid = ISCSI_CONFIG_GUID;\r
   form formid = FORMID_MAIN_FORM,\r
-    title  = STRING_TOKEN(STR_ISCSI_MAIN_FORM_TITLE);  // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code\r
+    title  = STRING_TOKEN(STR_ISCSI_MAIN_FORM_TITLE);\r
 \r
     string  varid   = ISCSI_CONFIG_IFR_NVDATA.InitiatorName, \r
             prompt  = STRING_TOKEN(STR_ISCSI_CONFIG_INIT_NAME),\r
@@ -42,6 +47,7 @@ formset
     endstring;\r
 \r
     label DEVICE_ENTRY_LABEL;\r
+    label LABEL_END;\r
 \r
   endform;\r
 \r
index 444cb69de0cfff6bb28fc396f515366d5d88f032..7e1d2f86cd8154d6088133d19a588f7540a40edf 100644 (file)
@@ -55,19 +55,19 @@ Abstract:
 \r
 #define DEVICE_ENTRY_LABEL        0x1234\r
 \r
-#define KEY_INITIATOR_NAME        0x01\r
-#define KEY_DHCP_ENABLE           0x02\r
-#define KEY_LOCAL_IP              0x03\r
-#define KEY_SUBNET_MASK           0x04\r
-#define KEY_GATE_WAY              0x05\r
-#define KEY_TARGET_IP             0x06\r
-#define KEY_CHAP_NAME             0x07\r
-#define KEY_CHAP_SECRET           0x08\r
-#define KEY_REVERSE_CHAP_NAME     0x09\r
-#define KEY_REVERSE_CHAP_SECRET   0x0a\r
-#define KEY_SAVE_CHANGES          0x0b\r
-#define KEY_TARGET_NAME           0x0c\r
-#define KEY_BOOT_LUN              0x0d\r
+#define KEY_INITIATOR_NAME        0x101\r
+#define KEY_DHCP_ENABLE           0x102\r
+#define KEY_LOCAL_IP              0x103\r
+#define KEY_SUBNET_MASK           0x104\r
+#define KEY_GATE_WAY              0x105\r
+#define KEY_TARGET_IP             0x106\r
+#define KEY_CHAP_NAME             0x107\r
+#define KEY_CHAP_SECRET           0x108\r
+#define KEY_REVERSE_CHAP_NAME     0x109\r
+#define KEY_REVERSE_CHAP_SECRET   0x10a\r
+#define KEY_SAVE_CHANGES          0x10b\r
+#define KEY_TARGET_NAME           0x10c\r
+#define KEY_BOOT_LUN              0x10d\r
 \r
 #define KEY_DEVICE_ENTRY_BASE     0x1000\r
 \r
index 145483b0e748f7d96047e50bd7d441ac45f1cbd7..b9b8cea8abcef62ce95402f223ae6f1faf71e3f4 100644 (file)
@@ -230,9 +230,9 @@ Returns:
 \r
   Status      = This->Parse (This, Packet, &OptionCount, NULL);\r
   if (Status != EFI_BUFFER_TOO_SMALL) {\r
-    return EFI_NOT_READY;\r
+    \rreturn EFI_NOT_READY;\r
   }\r
-  \r
+\r
   OptionList = NetAllocatePool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
   if (OptionList == NULL) {\r
     return EFI_NOT_READY;\r
@@ -437,7 +437,7 @@ Returns:
   // Ask the server to reply with Netmask, Router, DNS and RootPath options.\r
   //\r
   ParaList->OpCode  = DHCP4_TAG_PARA_LIST;\r
-  ParaList->Length  = (UINT8)(ConfigData->NvData.TargetInfoFromDhcp ? 4 : 3);\r
+  ParaList->Length  = ConfigData->NvData.TargetInfoFromDhcp ? 4 : 3;\r
   ParaList->Data[0] = DHCP4_TAG_NETMASK;\r
   ParaList->Data[1] = DHCP4_TAG_ROUTER;\r
   ParaList->Data[2] = DHCP4_TAG_DNS;\r
index f70aebd26e57e77a4c3765352fb9dc4ba08ddc2a..9312b547bd744b9462d66b143491528532b03400 100644 (file)
@@ -20,7 +20,9 @@ Abstract:
 #ifndef _ISCSI_DHCP_H_\r
 #define _ISCSI_DHCP_H_\r
 \r
-#include <Protocol/Dhcp4.h>\r
+//#include "Tiano.h"\r
+//#include EFI_PROTOCOL_CONSUMER (Dhcp4)\r
+#include "protocol\Dhcp4.h"\r
 \r
 #define DHCP4_TAG_PARA_LIST             55\r
 #define DHCP4_TAG_NETMASK               1\r
index bf68be6a3759f3337bf56bbf60bdfc98dc1c1225..e5d6324727698e4d87c34a2166e3fa58b98aa065 100644 (file)
@@ -101,7 +101,7 @@ Returns:
     // Need expand the control section if more than 2 NIC/Target sections\r
     // exist.\r
     //\r
-    Control->Header.Length = (UINT16)(Control->Header.Length + (NumOffset - 4) * sizeof (UINT16));\r
+    Control->Header.Length += (UINT16) (NumOffset - 4) * sizeof (UINT16);\r
   }\r
 }\r
 \r
@@ -191,7 +191,7 @@ Returns:
   //\r
   // Get the identifier from the handle.\r
   //\r
-  Status = gBS->HandleProtocol (Handle, &mIScsiPrivateGuid, (void **)&IScsiIdentifier);\r
+  Status = gBS->HandleProtocol (Handle, &mIScsiPrivateGuid, &IScsiIdentifier);\r
   if (EFI_ERROR (Status)) {\r
     ASSERT (FALSE);\r
     return ;\r
@@ -278,7 +278,7 @@ Returns:
   Status = gBS->HandleProtocol (\r
                   Controller,\r
                   &gEfiDevicePathProtocolGuid,\r
-                  (void **)&DevicePath\r
+                  &DevicePath\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     return 0;\r
@@ -293,7 +293,7 @@ Returns:
     return 0;\r
   }\r
 \r
-  Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (void **)&PciIo);\r
+  Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, &PciIo);\r
   if (EFI_ERROR (Status)) {\r
     return 0;\r
   }\r
@@ -333,7 +333,7 @@ Returns:
   Status = gBS->HandleProtocol (\r
                   Controller,\r
                   &gEfiSimpleNetworkProtocolGuid,\r
-                  (void **)&Snp\r
+                  &Snp\r
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
@@ -392,7 +392,7 @@ Returns:
   SectionOffset = &Control->NIC0Offset;\r
 \r
   for (Index = 0; Index < HandleCount; Index++) {\r
-    Status = gBS->HandleProtocol (Handles[Index], &mIScsiPrivateGuid, (void **)&IScsiIdentifier);\r
+    Status = gBS->HandleProtocol (Handles[Index], &mIScsiPrivateGuid, &IScsiIdentifier);\r
     if (EFI_ERROR (Status)) {\r
       ASSERT (FALSE);\r
       return ;\r
@@ -552,7 +552,7 @@ Returns:
   EFI_ACPI_TABLE_VERSION                    Version;\r
   UINT32                                    Signature;\r
 \r
-  Status = gBS->LocateProtocol (&gEfiAcpiSupportProtocolGuid, NULL, (void **)&AcpiSupport);\r
+  Status = gBS->LocateProtocol (&gEfiAcpiSupportProtocolGuid, NULL, &AcpiSupport);\r
   if (EFI_ERROR (Status)) {\r
     return ;\r
   }\r
@@ -563,7 +563,7 @@ Returns:
     Status = AcpiSupport->GetAcpiTable (\r
                             AcpiSupport,\r
                             Index,\r
-                            (void **)&Table,\r
+                            &Table,\r
                             &Version,\r
                             &TableHandle\r
                             );\r
@@ -613,7 +613,7 @@ Returns:
     return ;\r
   }\r
 \r
-  Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET;\r
+  Heap = (CHAR8 *) Table + IBFT_HEAP_OFFSET;\r
 \r
   //\r
   // Fill in the various section of the iSCSI Boot Firmware Table.\r
index 535bc8461e7a0f481a773598b667cb709e9118c3..715f814882b92f86c429f4ca29457d6209de96b0 100644 (file)
@@ -37,7 +37,7 @@ Abstract:
 \r
 #define ISCSI_SESSION_SIGNATURE EFI_SIGNATURE_32 ('I', 'S', 'S', 'N')\r
 \r
-struct _ISCSI_SESSION {\r
+typedef struct _ISCSI_SESSION {\r
   UINT32                    Signature;\r
 \r
   ISCSI_SESSION_CONFIG_DATA ConfigData;\r
@@ -77,11 +77,11 @@ struct _ISCSI_SESSION {
   BOOLEAN                   DataPDUInOrder;\r
   BOOLEAN                   DataSequenceInOrder;\r
   UINT8                     ErrorRecoveryLevel;\r
-};\r
+} ISCSI_SESSION;\r
 \r
 #define ISCSI_CONNECTION_SIGNATURE  EFI_SIGNATURE_32 ('I', 'S', 'C', 'N')\r
 \r
-struct _ISCSI_CONNECTION {\r
+typedef struct _ISCSI_CONNECTION {\r
   UINT32            Signature;\r
   NET_LIST_ENTRY    Link;\r
 \r
@@ -116,7 +116,7 @@ struct _ISCSI_CONNECTION {
   UINT32            MaxRecvDataSegmentLength;\r
   ISCSI_DIGEST_TYPE HeaderDigest;\r
   ISCSI_DIGEST_TYPE DataDigest;\r
-};\r
+} ISCSI_CONNECTION;\r
 \r
 #define ISCSI_DRIVER_DATA_SIGNATURE EFI_SIGNATURE_32 ('I', 'S', 'D', 'A')\r
 \r
@@ -142,7 +142,7 @@ struct _ISCSI_CONNECTION {
   ISCSI_DRIVER_DATA_SIGNATURE \\r
   )\r
 \r
-struct _ISCSI_DRIVER_DATA {\r
+typedef struct _ISCSI_DRIVER_DATA {\r
   UINT32                          Signature;\r
   EFI_HANDLE                      Image;\r
   EFI_HANDLE                      Controller;\r
@@ -156,6 +156,6 @@ struct _ISCSI_DRIVER_DATA {
   EFI_DEVICE_PATH_PROTOCOL        *DevicePath;\r
 \r
   ISCSI_SESSION                   Session;\r
-};\r
+} ISCSI_DRIVER_DATA;\r
 \r
 #endif\r
index 214af746976333e571b40b8cda2853b101a5d46d..0347d320423275a0145531c9ec860ace3c9d508c 100644 (file)
@@ -167,7 +167,7 @@ Returns:
     Len++;\r
   }\r
 \r
-  return (UINT8)(32 - Len);\r
+  return 32 - Len;\r
 }\r
 \r
 EFI_STATUS\r
@@ -196,7 +196,6 @@ Returns:
   UINT32  Index;\r
   CHAR8   *LunUnitStr[4];\r
   CHAR8   Digit;\r
-  UINTN   Temp;\r
 \r
   NetZeroMem (Lun, 8);\r
   NetZeroMem (LunUnitStr, sizeof (LunUnitStr));\r
@@ -204,7 +203,7 @@ Returns:
   Index         = 0;\r
   LunUnitStr[0] = Str;\r
 \r
-  if (!IsHexDigit ((UINT8 *)&Digit, *Str)) {\r
+  if (!IsHexDigit (&Digit, *Str)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -220,13 +219,13 @@ Returns:
       Index++;\r
 \r
       if (*(Str + 1) != '\0') {\r
-        if (!IsHexDigit ((UINT8 *)&Digit, *(Str + 1))) {\r
+        if (!IsHexDigit (&Digit, *(Str + 1))) {\r
           return EFI_INVALID_PARAMETER;\r
         }\r
 \r
         LunUnitStr[Index] = Str + 1;\r
       }\r
-    } else if (!IsHexDigit ((UINT8 *)&Digit, *Str)) {\r
+    } else if (!IsHexDigit (&Digit, *Str)) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
@@ -238,8 +237,7 @@ Returns:
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
-    Temp = AsciiStrHexToUintn (LunUnitStr[Index]);\r
-    *((UINT16 *) &Lun[Index * 2]) = HTONS (Temp);\r
+    *((UINT16 *) &Lun[Index * 2]) = HTONS (AsciiStrHexToUintn (LunUnitStr[Index]));\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -472,7 +470,7 @@ Returns:
   UINT32  Index;\r
 \r
   for (Index = 0; Index < Len; Index++) {\r
-    Str[3 * Index]      = NibbleToHexChar ((UINT8)(Mac->Addr[Index] >> 4));\r
+    Str[3 * Index]      = NibbleToHexChar (Mac->Addr[Index] >> 4);\r
     Str[3 * Index + 1]  = NibbleToHexChar (Mac->Addr[Index]);\r
     Str[3 * Index + 2]  = L'-';\r
   }\r
@@ -602,7 +600,7 @@ Returns:
     } else {\r
       Byte = BinBuffer[*BinLength - 1 - Index / 2];\r
       Byte &= 0x0F;\r
-      Byte = (UINT8)(Byte | (Digit << 4));\r
+      Byte |= Digit << 4;\r
     }\r
 \r
     BinBuffer[*BinLength - 1 - Index / 2] = Byte;\r
@@ -811,7 +809,7 @@ Returns:
   Status = gBS->HandleProtocol (\r
                   Private->Controller,\r
                   &gEfiSimpleNetworkProtocolGuid,\r
-                  (void **)&Snp\r
+                  &Snp\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -907,7 +905,7 @@ Returns:
   Status = gBS->HandleProtocol (\r
                   Tcp4Io->Handle,\r
                   &gEfiDevicePathProtocolGuid,\r
-                  (void **)&DevicePath\r
+                  &DevicePath\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     return NULL;\r
@@ -925,7 +923,7 @@ Returns:
         ) {\r
 \r
       DPathNode->Ipv4.LocalPort       = 0;\r
-      DPathNode->Ipv4.StaticIpAddress = (BOOLEAN)(!Session->ConfigData.NvData.InitiatorInfoFromDhcp);\r
+      DPathNode->Ipv4.StaticIpAddress = !Session->ConfigData.NvData.InitiatorInfoFromDhcp;\r
       break;\r
     }\r
 \r
index fa1c7d6c1b4394d747e739c725b6976aaf8b60bd..4cef3dc45d3c9e92072667bc9bfa793898c2daef 100644 (file)
@@ -546,7 +546,7 @@ Returns:
   //\r
   // Allocate the space for the key-value pair.\r
   //\r
-  Data = (CHAR8 *) NetbufAllocSpace (Pdu, TotalLen, NET_BUF_TAIL);\r
+  Data = NetbufAllocSpace (Pdu, TotalLen, NET_BUF_TAIL);\r
   if (Data == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
@@ -668,7 +668,7 @@ Returns:
     //\r
     // Check whether we will issue the stage transition signal?\r
     //\r
-    Conn->TransitInitiated = (BOOLEAN)ISCSI_FLAG_ON (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);\r
+    Conn->TransitInitiated = ISCSI_FLAG_ON (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);\r
   }\r
 \r
   return Nbuf;\r
@@ -746,7 +746,7 @@ Returns:
     // Process the TargetAddress key-value strings in the data segment to update the\r
     // target address info.\r
     //\r
-    Status = IScsiUpdateTargetAddress (Session, (CHAR8 *)DataSeg, DataSegLen);\r
+    Status = IScsiUpdateTargetAddress (Session, DataSeg, DataSegLen);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
@@ -765,11 +765,11 @@ Returns:
   //\r
   // The status is sucess, extract the wanted fields from the header segment.\r
   //\r
-  Transit                     = (BOOLEAN)ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_TRANSIT);\r
-  Continue                    = (BOOLEAN)ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_CONTINUE);\r
+  Transit                     = ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_TRANSIT);\r
+  Continue                    = ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_CONTINUE);\r
 \r
-  CurrentStage                = (UINT8)ISCSI_GET_CURRENT_STAGE (LoginRsp);\r
-  NextStage                   = (UINT8)ISCSI_GET_NEXT_STAGE (LoginRsp);\r
+  CurrentStage                = ISCSI_GET_CURRENT_STAGE (LoginRsp);\r
+  NextStage                   = ISCSI_GET_NEXT_STAGE (LoginRsp);\r
 \r
   LoginRsp->InitiatorTaskTag  = NTOHL (LoginRsp->InitiatorTaskTag);\r
 \r
@@ -1283,7 +1283,7 @@ Returns:
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  NetbufQueCopy (&Conn->RspQue, 0, Len, (UINT8 *)Data);\r
+  NetbufQueCopy (&Conn->RspQue, 0, Len, Data);\r
 \r
   Status = EFI_PROTOCOL_ERROR;\r
 \r
@@ -1352,7 +1352,7 @@ Returns:
     goto ON_ERROR;\r
   }\r
 \r
-  Session->InitialR2T = (BOOLEAN)(Session->InitialR2T || (AsciiStrCmp (Value, "Yes") == 0));\r
+  Session->InitialR2T = Session->InitialR2T || (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);\r
 \r
   //\r
   // ImmediateData, result function is AND.\r
@@ -1362,7 +1362,7 @@ Returns:
     goto ON_ERROR;\r
   }\r
 \r
-  Session->ImmediateData = (BOOLEAN)(Session->ImmediateData && (AsciiStrCmp (Value, "Yes") == 0));\r
+  Session->ImmediateData = Session->ImmediateData && (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);\r
 \r
   //\r
   // MaxRecvDataSegmentLength, result function is Mininum.\r
@@ -1422,7 +1422,7 @@ Returns:
     goto ON_ERROR;\r
   }\r
 \r
-  Session->DataPDUInOrder = (BOOLEAN)(Session->DataPDUInOrder || (AsciiStrCmp (Value, "Yes") == 0));\r
+  Session->DataPDUInOrder = Session->DataPDUInOrder || (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);\r
 \r
   //\r
   // DataSequenceInorder, result function is OR.\r
@@ -1432,7 +1432,7 @@ Returns:
     goto ON_ERROR;\r
   }\r
 \r
-  Session->DataSequenceInOrder = (BOOLEAN)(Session->DataSequenceInOrder || (AsciiStrCmp (Value, "Yes") == 0));\r
+  Session->DataSequenceInOrder = Session->DataSequenceInOrder || (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);\r
 \r
   //\r
   // DefaultTime2Wait, result function is Maximum.\r
@@ -1799,7 +1799,7 @@ Returns:
       //\r
       // Convert the upper-case characters to lower-case ones\r
       //\r
-      Name[Index] = (CHAR8)(Name[Index] - 'A' + 'a');\r
+      Name[Index] = Name[Index] - 'A' + 'a';\r
     }\r
 \r
     if (!NET_IS_LOWER_CASE_CHAR (Name[Index]) &&\r
@@ -2048,7 +2048,7 @@ Returns:
     //\r
     // The CDB exceeds 16 bytes, an extended CDB AHS is required.\r
     //\r
-    AHSLength = (UINT8)(AHSLength + (ISCSI_ROUNDUP (Packet->CdbLength - 16) + sizeof (ISCSI_ADDITIONAL_HEADER)));\r
+    AHSLength += ISCSI_ROUNDUP (Packet->CdbLength - 16) + sizeof (ISCSI_ADDITIONAL_HEADER);\r
   }\r
 \r
   Length    = sizeof (SCSI_COMMAND) + AHSLength;\r
@@ -2769,7 +2769,6 @@ Returns:
   UINT8                   *Data;\r
   ISCSI_IN_BUFFER_CONTEXT InBufferContext;\r
   UINT64                  Timeout;\r
-  UINT8                   *Buffer;\r
 \r
   Private       = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru);\r
   Session       = &Private->Session;\r
@@ -2815,8 +2814,7 @@ Returns:
   }\r
 \r
   XferContext         = &Tcb->XferContext;\r
-  Buffer              = NetbufGetByte (Pdu, 0, NULL);\r
-  XferContext->Offset = ISCSI_GET_DATASEG_LEN (Buffer);\r
+  XferContext->Offset = ISCSI_GET_DATASEG_LEN (NetbufGetByte (Pdu, 0, NULL));\r
 \r
   //\r
   // Transmit the SCSI Command PDU.\r
index d47a5b56799e3446cdc414716cf581d3fef0c6a1..59608fcec7fe2b1a23aa5daa81fef75ad95acb35 100644 (file)
@@ -119,8 +119,8 @@ typedef enum {
 #define ISCSI_IMMEDIATE_ON(PduHdr)          ((PduHdr)->OpCode & ISCSI_REQ_IMMEDIATE)\r
 #define ISCSI_SET_FLAG(PduHdr, Flag)        (((ISCSI_BASIC_HEADER *) (PduHdr))->Flags |= (Flag))\r
 #define ISCSI_CLEAR_FLAG(PduHdr, Flag)      (((ISCSI_BASIC_HEADER *) (PduHdr))->Flags &= ~(Flag))\r
-#define ISCSI_FLAG_ON(PduHdr, Flag)         ((((ISCSI_BASIC_HEADER *) (PduHdr))->Flags & (Flag)) == (BOOLEAN)(Flag))\r
-#define ISCSI_SET_STAGES(PduHdr, Cur, Nxt)  ((PduHdr)->Flags = (UINT8)(((PduHdr)->Flags)|(((Cur) << 2) | (Nxt))))\r
+#define ISCSI_FLAG_ON(PduHdr, Flag)         ((((ISCSI_BASIC_HEADER *) (PduHdr))->Flags & (Flag)) == (Flag))\r
+#define ISCSI_SET_STAGES(PduHdr, Cur, Nxt)  ((PduHdr)->Flags |= ((Cur) << 2 | (Nxt)))\r
 #define ISCSI_GET_CURRENT_STAGE(PduHdr)     (((PduHdr)->Flags >> 2) & 0x3)\r
 #define ISCSI_GET_NEXT_STAGE(PduHdr)        (((PduHdr)->Flags) & 0x3)\r
 \r
@@ -129,9 +129,9 @@ typedef enum {
 \r
 #define HTON24(Dst, Src) \\r
   do { \\r
-    (Dst)[0]  = (UINT8)(((Src) >> 16) & 0xFF); \\r
-    (Dst)[1]  = (UINT8)(((Src) >> 8) & 0xFF); \\r
-    (Dst)[2]  = (UINT8)((Src) & 0xFF); \\r
+    (Dst)[0]  = (UINT8) ((Src) >> 16) & 0xFF; \\r
+    (Dst)[1]  = (UINT8) ((Src) >> 8) & 0xFF; \\r
+    (Dst)[2]  = (UINT8) (Src) & 0xFF; \\r
   } while (0);\r
 \r
 #define NTOH24(src)                         (((src)[0] << 16) | ((src)[1] << 8) | ((src)[2]))\r